@afora/core 0.0.5 → 0.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/README.md +2 -0
  2. package/dist/core/application/types/application.interface.d.ts +45 -11
  3. package/dist/core/blueprint/types/slice.interface.d.ts +5 -2
  4. package/dist/core/entity/abstract-entity.d.ts +1 -1
  5. package/dist/core/entity/types/entity.interface.d.ts +13 -7
  6. package/dist/core/exception/exception.d.ts +10 -1
  7. package/dist/core/output/status.d.ts +2 -2
  8. package/dist/core/property/property.d.ts +4 -4
  9. package/dist/core/property/types/optional-property.type.d.ts +2 -2
  10. package/dist/core/property/types/property-type.interface.d.ts +17 -0
  11. package/dist/core/record/abstract-record.d.ts +4 -4
  12. package/dist/core/record/exceptions.d.ts +2 -0
  13. package/dist/core/record/name.d.ts +16 -0
  14. package/dist/core/record/record.d.ts +4 -3
  15. package/dist/core/record/types/plugin.interface.d.ts +11 -0
  16. package/dist/core/record/types/record.interface.d.ts +71 -10
  17. package/dist/core/repository/cursor.d.ts +13 -0
  18. package/dist/core/repository/exceptions.d.ts +10 -0
  19. package/dist/core/repository/query.d.ts +4 -4
  20. package/dist/core/repository/repository.d.ts +1 -1
  21. package/dist/core/repository/types/query.interface.d.ts +37 -0
  22. package/dist/core/repository/types/repository.interface.d.ts +10 -6
  23. package/dist/core/use-case/steps/types/steps.interface.d.ts +1 -1
  24. package/dist/experimental.js +3 -2
  25. package/dist/{index-hn82hm31.js → index-3nd9bjnc.js} +69 -10
  26. package/dist/{index-8m80wjzf.js → index-gbgc40xe.js} +188 -39
  27. package/dist/index.d.ts +7 -6
  28. package/dist/index.js +8 -2
  29. package/dist/std/properties/password.d.ts +5 -1
  30. package/dist/std/record-plugins.d.ts +5 -5
  31. package/dist/testing/index.js +91 -2
  32. package/dist/testing/provider-contract.d.ts +5 -0
  33. package/package.json +1 -1
@@ -1,10 +1,10 @@
1
- import"../index-hn82hm31.js";
1
+ import"../index-3nd9bjnc.js";
2
2
  import {
3
3
  RepositoryUniqueViolation2,
4
4
  RepositoryEntityNotFound2,
5
5
  blueprintOf2,
6
6
  entityOf2
7
- } from "../index-8m80wjzf.js";
7
+ } from "../index-gbgc40xe.js";
8
8
 
9
9
  // src/testing/provider-contract.ts
10
10
  function contextOf(name = "Accounts") {
@@ -371,6 +371,95 @@ function providerContract(runner, makeProvider, options = {}) {
371
371
  expect(stored).toEqual(data);
372
372
  });
373
373
  });
374
+ describe("keyset", () => {
375
+ const keyset = (name, body) => it(name, async () => {
376
+ const enabled = options.keyset ?? (await makeProvider()).capabilities?.keyset;
377
+ if (enabled === true)
378
+ await body();
379
+ });
380
+ const seeded = async () => {
381
+ const f = await fixture();
382
+ const [a, b, c, d, e, g] = [
383
+ row({ n: 1, group: 1, name: "Gil" }),
384
+ row({ group: 1, name: "Érico" }),
385
+ row({ n: 2, group: 2, name: "Ana" }),
386
+ row({ n: 2, group: 1, name: "ana" }),
387
+ row({ group: 2, name: "Bia" }),
388
+ row({ n: 3, group: 2, name: "Zoe" })
389
+ ];
390
+ await f.seed(a, b, c, d, e, g);
391
+ const find = (query) => f.provider.findMany(f.context, query).then(ids);
392
+ return { ...f, a, b, c, d, e, g, find };
393
+ };
394
+ const by = (key, direction = "asc") => [{ key, direction }, { key: "id" }];
395
+ keyset("gives the rows strictly after the position, ascending", async () => {
396
+ const { find, a, c, d, g } = await seeded();
397
+ const orderBy = by("n");
398
+ expect(await find({ orderBy, after: [1, a.id] })).toEqual([
399
+ c.id,
400
+ d.id,
401
+ g.id
402
+ ]);
403
+ expect(await find({ orderBy, after: [2, c.id] })).toEqual([
404
+ d.id,
405
+ g.id
406
+ ]);
407
+ expect(await find({ orderBy, after: [3, g.id] })).toEqual([]);
408
+ });
409
+ keyset("follows a descending order", async () => {
410
+ const { find, a, c, d, g } = await seeded();
411
+ const orderBy = by("n", "desc");
412
+ expect(await find({
413
+ orderBy,
414
+ after: [3, g.id],
415
+ where: { n: { in: [1, 2] } }
416
+ })).toEqual([c.id, d.id, a.id]);
417
+ expect(await find({
418
+ orderBy,
419
+ after: [2, d.id],
420
+ where: { n: { in: [1, 2] } }
421
+ })).toEqual([a.id]);
422
+ });
423
+ keyset("missing values are first ascending and last descending", async () => {
424
+ const { find, a, b, c, d, e, g } = await seeded();
425
+ expect(await find({ orderBy: by("n"), after: [undefined, b.id] })).toEqual([e.id, a.id, c.id, d.id, g.id]);
426
+ expect(await find({ orderBy: by("n"), after: [undefined, e.id] })).toEqual([a.id, c.id, d.id, g.id]);
427
+ expect(await find({ orderBy: by("n", "desc"), after: [1, a.id] })).toEqual([b.id, e.id]);
428
+ expect(await find({ orderBy: by("n", "desc"), after: [undefined, b.id] })).toEqual([e.id]);
429
+ expect(await find({ orderBy: by("n", "desc"), after: [undefined, e.id] })).toEqual([]);
430
+ });
431
+ keyset("compares strings by code point", async () => {
432
+ const { find, a, b, c, d, e, g } = await seeded();
433
+ expect(await find({ orderBy: by("name"), after: ["Bia", e.id] })).toEqual([a.id, g.id, d.id, b.id]);
434
+ expect(await find({ orderBy: by("name", "desc"), after: ["ana", d.id] })).toEqual([g.id, a.id, e.id, c.id]);
435
+ });
436
+ keyset("combines with where, withDeleted and limit; count ignores it", async () => {
437
+ const { provider, context, find, a, b, d } = await seeded();
438
+ const orderBy = [{ key: "id" }];
439
+ expect(await find({
440
+ orderBy,
441
+ after: [a.id],
442
+ where: { group: 1 },
443
+ limit: 1
444
+ })).toEqual([b.id]);
445
+ expect(await find({ orderBy, after: [b.id], where: { group: 1 } })).toEqual([d.id]);
446
+ await provider.update(context, {
447
+ ...d,
448
+ deletedAt: "2024-01-01T00:00:00.000Z"
449
+ });
450
+ expect(await find({ orderBy, after: [b.id], where: { group: 1 } })).toEqual([]);
451
+ expect(await find({
452
+ orderBy,
453
+ after: [b.id],
454
+ where: { group: 1 },
455
+ withDeleted: true
456
+ })).toEqual([d.id]);
457
+ expect(await provider.count(context, {
458
+ orderBy,
459
+ after: [b.id]
460
+ })).toBe(5);
461
+ });
462
+ });
374
463
  const withTransactions = async () => {
375
464
  const enabled = options.transactions ?? (await makeProvider()).capabilities?.transactions;
376
465
  return enabled === true;
@@ -13,6 +13,11 @@ export interface ProviderContractOptions {
13
13
  * Run the transaction cases. Defaults to `provider.capabilities?.transactions`.
14
14
  */
15
15
  readonly transactions?: boolean;
16
+ /**
17
+ * Run the cases of `after`, which `findCursor` gives to `findMany`. Defaults
18
+ * to `provider.capabilities?.keyset`.
19
+ */
20
+ readonly keyset?: boolean;
16
21
  }
17
22
  /**
18
23
  * Registers the behavior every `IRepositoryProvider` v2 must have. Pass the
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@afora/core",
3
- "version": "0.0.5",
3
+ "version": "0.0.6",
4
4
  "description": "Domain modeling on TypeBox: entities with invariants, repositories, use cases, sensitive data masking and layered exceptions, usable by any Standard Schema consumer.",
5
5
  "keywords": [
6
6
  "domain-driven-design",