@stonecrop/nuxt 0.16.5 → 0.16.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.
package/dist/module.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@stonecrop/nuxt",
3
3
  "configKey": "stonecrop",
4
- "version": "0.16.5",
4
+ "version": "0.16.6",
5
5
  "builder": {
6
6
  "@nuxt/module-builder": "1.0.2",
7
7
  "unbuild": "unknown"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stonecrop/nuxt",
3
- "version": "0.16.5",
3
+ "version": "0.16.6",
4
4
  "description": "Nuxt module for Stonecrop",
5
5
  "repository": {
6
6
  "type": "git",
@@ -45,18 +45,18 @@
45
45
  "pathe": "^2.0.3",
46
46
  "pinia": "^3.0.4",
47
47
  "prompts": "^2.4.2",
48
- "@stonecrop/casl-middleware": "0.16.5",
49
- "@stonecrop/aform": "0.16.5",
50
- "@stonecrop/atable": "0.16.5",
51
- "@stonecrop/code-editor": "0.16.5",
52
- "@stonecrop/desktop": "0.16.5",
53
- "@stonecrop/graphql-middleware": "0.16.5",
54
- "@stonecrop/node-editor": "0.16.5",
55
- "@stonecrop/graphql-client": "0.16.5",
56
- "@stonecrop/schema": "0.16.5",
57
- "@stonecrop/nuxt-grafserv": "0.16.5",
58
- "@stonecrop/stonecrop": "0.16.5",
59
- "@stonecrop/themes": "0.16.5"
48
+ "@stonecrop/aform": "0.16.6",
49
+ "@stonecrop/desktop": "0.16.6",
50
+ "@stonecrop/casl-middleware": "0.16.6",
51
+ "@stonecrop/graphql-client": "0.16.6",
52
+ "@stonecrop/code-editor": "0.16.6",
53
+ "@stonecrop/graphql-middleware": "0.16.6",
54
+ "@stonecrop/node-editor": "0.16.6",
55
+ "@stonecrop/schema": "0.16.6",
56
+ "@stonecrop/nuxt-grafserv": "0.16.6",
57
+ "@stonecrop/stonecrop": "0.16.6",
58
+ "@stonecrop/themes": "0.16.6",
59
+ "@stonecrop/atable": "0.16.6"
60
60
  },
61
61
  "devDependencies": {
62
62
  "@eslint/js": "^10.0.1",
@@ -103,7 +103,7 @@
103
103
  "prepublish": "rushx dev:prepare && nuxt-module-build build",
104
104
  "test": "vitest run",
105
105
  "test:coverage": "vitest run --coverage.enabled --coverage.provider=istanbul",
106
- "test:types": "vue-tsc --noEmit -p tsconfig.runtime.json && cd playground && vue-tsc --noEmit && cd ../fullstack && vue-tsc --noEmit",
106
+ "test:types": "vue-tsc --noEmit -p tsconfig.runtime.json && cd playground && vue-tsc --noEmit && cd ../fullstack && vue-tsc --noEmit && vue-tsc --noEmit -p server/tsconfig.json",
107
107
  "test:ui": "vitest --ui",
108
108
  "test:watch": "vitest watch"
109
109
  }
@@ -4,6 +4,7 @@
4
4
  "fields": [
5
5
  {
6
6
  "fieldname": "id",
7
+ "primaryKey": true,
7
8
  "label": "ID",
8
9
  "component": "ATextInput",
9
10
  "mode": "display"
@@ -4,6 +4,7 @@
4
4
  "fields": [
5
5
  {
6
6
  "fieldname": "id",
7
+ "primaryKey": true,
7
8
  "label": "ID",
8
9
  "component": "ATextInput",
9
10
  "mode": "display"
@@ -19,6 +19,7 @@
19
19
 
20
20
  import { constant, lambda, loadOne, object } from 'grafast'
21
21
  import { getMeta, getAllMeta, applyGuardedTransition } from '@stonecrop/graphql-middleware'
22
+ import { getPrimaryKeyField } from '@stonecrop/schema'
22
23
  import type { DoctypeMeta } from '@stonecrop/schema'
23
24
  import { projects, tasks, type Project, type Task } from './data'
24
25
 
@@ -57,10 +58,36 @@ export function formatDoctypeMeta(meta: DoctypeMeta) {
57
58
  // Record helpers — read/write the in-memory Maps by doctype
58
59
  // ============================================================
59
60
 
60
- function getRecord(doctype: string, id: string): Project | Task | null {
61
+ /**
62
+ * The field an incoming `stonecropRecord(id:)` argument is matched against.
63
+ *
64
+ * Part of the adapter contract — see test/adapter-conformance.test.ts, which runs the same
65
+ * expectations against every host. A doctype that declares a `primaryKey` is keyed by that
66
+ * field; the client resolves the same field via `@stonecrop/schema`'s `getRecordIdentity`,
67
+ * so an adapter that ignores the declaration looks records up by a key the client never sent.
68
+ *
69
+ * The `id` fallback covers doctypes that declare no `primaryKey`. Every doctype in this repo now
70
+ * declares one, enforced by test/doctype-fixtures.test.ts, so in-repo the fallback is inert.
71
+ * It stays for consumer doctypes that have not adopted the rule: the Postgres adapter refuses
72
+ * those outright (`data: null`), and this host stays permissive. The conformance suite records
73
+ * that difference rather than asserting one answer.
74
+ */
75
+ export function recordLookupField(meta: DoctypeMeta): string {
76
+ return getPrimaryKeyField(meta.fields)?.fieldname ?? 'id'
77
+ }
78
+
79
+ function getRecord(doctype: string, id: string, lookupField = 'id'): Project | Task | null {
61
80
  const d = doctype.toLowerCase()
62
- if (d === 'project') return projects.get(id) ?? null
63
- if (d === 'task') return tasks.get(id) ?? null
81
+ const store = d === 'project' ? projects : d === 'task' ? tasks : null
82
+ if (!store) return null
83
+ if (lookupField === 'id') return store.get(id) ?? null
84
+ // A natural key is not the Map key, so the store is scanned. Values are compared as
85
+ // strings because the `id` argument arrives from GraphQL as `String!`. Only primitives
86
+ // are usable keys — stringifying an object would compare "[object Object]".
87
+ for (const record of store.values()) {
88
+ const value: unknown = Reflect.get(record, lookupField)
89
+ if ((typeof value === 'string' || typeof value === 'number') && String(value) === id) return record
90
+ }
64
91
  return null
65
92
  }
66
93
 
@@ -117,10 +144,13 @@ export const resolvers = {
117
144
 
118
145
  stonecropRecord(_: unknown, { $doctype, $id, $options }: any) {
119
146
  return loadOne(object({ doctype: $doctype, id: $id, options: $options }), async (specs: readonly any[]) => {
120
- return specs.map(spec => ({
121
- data: getRecord(spec.doctype, spec.id),
122
- doctype: spec.doctype,
123
- }))
147
+ return specs.map(spec => {
148
+ const meta = getMeta(spec.doctype)
149
+ return {
150
+ data: meta ? getRecord(spec.doctype, spec.id, recordLookupField(meta)) : null,
151
+ doctype: spec.doctype,
152
+ }
153
+ })
124
154
  })
125
155
  },
126
156