@jskit-ai/crud-core 0.1.55 → 0.1.57

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.
@@ -1,7 +1,7 @@
1
1
  export default Object.freeze({
2
2
  packageVersion: 1,
3
3
  packageId: "@jskit-ai/crud-core",
4
- version: "0.1.55",
4
+ version: "0.1.57",
5
5
  kind: "runtime",
6
6
  description: "Shared CRUD helpers used by CRUD modules.",
7
7
  dependsOn: [
@@ -26,7 +26,7 @@ export default Object.freeze({
26
26
  mutations: {
27
27
  dependencies: {
28
28
  runtime: {
29
- "@jskit-ai/crud-core": "0.1.55"
29
+ "@jskit-ai/crud-core": "0.1.57"
30
30
  },
31
31
  dev: {}
32
32
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jskit-ai/crud-core",
3
- "version": "0.1.55",
3
+ "version": "0.1.57",
4
4
  "type": "module",
5
5
  "scripts": {
6
6
  "test": "node --test"
@@ -26,12 +26,12 @@
26
26
  },
27
27
  "dependencies": {
28
28
  "@tanstack/vue-query": "^5.90.5",
29
- "@jskit-ai/database-runtime": "0.1.47",
30
- "@jskit-ai/kernel": "0.1.47",
31
- "@jskit-ai/realtime": "0.1.46",
32
- "@jskit-ai/shell-web": "0.1.46",
33
- "@jskit-ai/users-core": "0.1.57",
34
- "@jskit-ai/users-web": "0.1.62",
29
+ "@jskit-ai/database-runtime": "0.1.49",
30
+ "@jskit-ai/kernel": "0.1.49",
31
+ "@jskit-ai/realtime": "0.1.48",
32
+ "@jskit-ai/shell-web": "0.1.48",
33
+ "@jskit-ai/users-core": "0.1.59",
34
+ "@jskit-ai/users-web": "0.1.64",
35
35
  "typebox": "^1.0.81"
36
36
  }
37
37
  }
@@ -284,7 +284,10 @@ function buildLookupHydrationPlan(
284
284
 
285
285
  const entries = Array.isArray(runtime?.entries) ? runtime.entries : [];
286
286
  if (entries.length < 1) {
287
- if (includeWasExplicit === true) {
287
+ const wildcardOnlyInclude =
288
+ includePaths.length > 0 &&
289
+ includePaths.every((pathSegments) => Array.isArray(pathSegments) && pathSegments[0] === "*");
290
+ if (includeWasExplicit === true && wildcardOnlyInclude !== true) {
288
291
  throw new Error(`${context} include requires lookups, but the resource declares no lookup relations.`);
289
292
  }
290
293
  return {
@@ -292,6 +292,45 @@ function createLookupResourceFixture() {
292
292
  };
293
293
  }
294
294
 
295
+ function createLeafLookupResourceFixture() {
296
+ return {
297
+ namespace: "users",
298
+ tableName: "users_table",
299
+ idColumn: "user_id",
300
+ operations: {
301
+ view: {
302
+ outputValidator: {
303
+ schema: {
304
+ type: "object",
305
+ properties: {
306
+ id: recordIdSchema,
307
+ name: { type: "string" }
308
+ }
309
+ }
310
+ }
311
+ },
312
+ create: {
313
+ bodyValidator: {
314
+ schema: {
315
+ type: "object",
316
+ properties: {}
317
+ }
318
+ }
319
+ }
320
+ },
321
+ fieldMeta: [
322
+ {
323
+ key: "id",
324
+ repository: { column: "user_id" }
325
+ },
326
+ {
327
+ key: "name",
328
+ repository: { column: "display_name" }
329
+ }
330
+ ]
331
+ };
332
+ }
333
+
295
334
  function createNormalizedWriteResourceFixture() {
296
335
  return {
297
336
  namespace: "contacts",
@@ -629,6 +668,49 @@ test("list forwards nested include paths to child lookup repositories", async ()
629
668
  assert.equal(lookupCalls[0].options.include, "vetTypeId");
630
669
  });
631
670
 
671
+ test("list wildcard hydration does not fail when child lookup resources declare no nested lookups", async () => {
672
+ const { knex } = createKnexDouble([
673
+ {
674
+ contact_id: 3,
675
+ first_name: "Tony",
676
+ primary_vet_id: 10,
677
+ secondary_vet_id: 12
678
+ }
679
+ ]);
680
+ const { knex: childKnex } = createKnexDouble([
681
+ {
682
+ user_id: 10,
683
+ display_name: "Vet A"
684
+ },
685
+ {
686
+ user_id: 12,
687
+ display_name: "Vet B"
688
+ }
689
+ ]);
690
+
691
+ const childRepository = createCrudResourceRuntime(createLeafLookupResourceFixture(), childKnex, {
692
+ context: "users repository"
693
+ });
694
+ const repository = createCrudResourceRuntime(createLookupResourceFixture(), knex, {
695
+ resolveLookup() {
696
+ return {
697
+ async listByIds(ids = [], options = {}) {
698
+ return childRepository.listByIds(ids, options);
699
+ }
700
+ };
701
+ }
702
+ });
703
+
704
+ const result = await repository.list({}, {
705
+ include: "*"
706
+ });
707
+
708
+ assert.deepEqual(result.items[0].lookups, {
709
+ primaryVetId: { id: "10", name: "Vet A" },
710
+ secondaryVetId: { id: "12", name: "Vet B" }
711
+ });
712
+ });
713
+
632
714
  test("operations.read.applyQuery and operations.list.applyQuery run before canonical filters", async () => {
633
715
  const { knex, calls } = createKnexDouble([
634
716
  {