Release notes v0.0.79
The first time we actually have release notes. I guess it is a start in making LBU a bit more mature. Remember when you had to search through all PR's cause something was broken in a new release? Yea, I do ;P Let's get to the juicy details.
Chores
We have updated Postgres twice to a new minor versions of 2.0.0-beta
. Although the package doesn't have clear goal for what the 2.0.0
release should contain, we don't have to step up there or look for alternatives yet. Other than that, some minor things like automatically linking these release notes in the generated changelog, switching the default branch to main
and fixing up the dependabot config.
Cli
In our test runner we now warn when a subtest uses an assertion on the parent t
. This prevents confusion when a failing assertion is printed under the parent, instead of the subtest.
import { mainTestFn, test } from "@compas/cli";
mainTestFn(import.meta);
test("My test", (t) => {
t.test("sub test", () => {
// warning: called 't.ok' on parent 't'. Accept 't' as argument in the callback of 't.test(msg, callback)'.
t.ok(true);
});
});
This caught a single usage in the lbu codebase here .
Code gen
Since we actively used the open-api importer for the first time, @tjonger found and fixed various bugs in there. Notably, resolving references in path and query parameters and creating a name from the path if operationId
is not available.
Other than that we have two new features, soft deletes for sql generation and cancel token support in apiClient and react-query hook generation. Let's start with the latter.
We added support for request cancellation with Axios. To minimize the differences between the api client generated when isNode
is used versus isBrowser
, most of the logic is done in the generated hooks. We accept the property cancelToken
on the options
argument, which is the QueryConfig
provided to useQuery
. If provided, the cancelToken#token
is passed through to the generated api client function, and the cancelToken#cancel
function is added to the returned Promise. This is behaviour is mostly in line with react-query documentation.
import { CancelToken, CancelTokenSource } from "axios";
export const MyComponent = () => {
const [count, setCount] = useState(0);
// I don't know React, please provide better sample :S
const cancelToken = useMemo(() => CancelToken.source(), [count]);
// Expensive operation
const { data: imageBlob } = useAppConvertCountToImage(
{ count },
{ cancelToken },
);
return (
<div>
<Button onClick={() => setCount(count + 1)} />
<img src={URL.createObjectURL(imageBlob)} />
</div>
);
};
The other big thing is soft delete support in sql generation. This can be enabled by passing in withSoftDeletes: true
in enableQueries
calls. This takes over the old withHistory
, and immediately removed support. Soft deletes add a deletedAt
column. All generated where
arguments by default won't return 'deleted' records. This can be enabled by providing { deletedAtInclude: true }
. To permanently delete a record, groupQueries.tableDeletePermanent
is generated as well.
// In generate
const T = new TypeCreator();
app.add(
T.object("myValue")
.keys({
id: T.uuid().primary(),
count: T.number(),
})
.enableQueries({ withSoftDeletes: true }),
);
// Insert a record
const [myValue] = await appQueries.myValueInsert(sql, { count: 5 });
const firstCount = await appQueries.myValueCount(sql);
// firstCount === 1
// Delete our `myValue`
await appQueries.myValueDelete(sql, { id: myValue.id });
const secondCount = await appQueries.myValueCount(sql);
// secondCount === 0, deleted records are not included
const countWithDeleted = await appQueries.myValueCount(sql, {
deletedAtInclude: true,
});
// countWithDeleted === 1
// Remove record completely
await appQueries.myValueDeletePermanent(sql, { id: myValue.id });
Note that cascading soft deletes is not included in this release. The generated DDL, enabled by app.generate({ ..., dumpPostgres: true })
does not yet interact with withSoftDeletes
. For an example of how to use it manually see the open issue
Store
This package seems to have the most breaking changes. We renamed all table names to use singular nouns:
migrations
->migration
fileStore
->file
->storeQueries.fileSelect
sessionStore
->session
->storeQueries.sessionSelect
jobQueue
->job
->storeQueries.jobSelect
File now uses the withSoftDeletes
instead of withHistory
. This means that the syncDeletedFiles
function will only clean up 'permanently' deleted files. We also renamed file#filename
to file#name
.
getMigrationsToBeApplied
from the migration part of @lbu/store
, will also return a list of migrations that have changed since they are applied to the database. This allows you to communicate to other developers that some migrations have changed and that they may need to do a full database reset.
In closing
As it is the first time doing this, I did not expect it to take this much time. Any constructive feedback to the writing style, background information provided or other questions are welcome.
That's all!
Only 14 days vacation left 🎃