@stonecrop/nuxt 0.16.4 → 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.d.mts +2 -1
- package/dist/module.json +1 -1
- package/dist/module.mjs +3 -1
- package/dist/runtime/app/components/DocBuilderFieldsPanel.vue +11 -10
- package/dist/types.d.mts +1 -1
- package/package.json +14 -14
- package/src/cli/installers/frontend.ts +5 -8
- package/templates/Project.json +1 -0
- package/templates/Task.json +1 -0
- package/templates/resolvers.ts +37 -7
package/dist/module.d.mts
CHANGED
|
@@ -87,7 +87,8 @@ interface ModuleOptions {
|
|
|
87
87
|
*/
|
|
88
88
|
theme?: string | false;
|
|
89
89
|
}
|
|
90
|
+
declare const STONECROP_PACKAGES: string[];
|
|
90
91
|
declare const _default: _nuxt_schema.NuxtModule<ModuleOptions, ModuleOptions, false>;
|
|
91
92
|
|
|
92
|
-
export { _default as default };
|
|
93
|
+
export { STONECROP_PACKAGES, _default as default };
|
|
93
94
|
export type { ModuleOptions, ParsedDoctype, RouteStrategyFn };
|
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -7,6 +7,8 @@ const { resolve } = createResolver(import.meta.url);
|
|
|
7
7
|
const STONECROP_PACKAGES = [
|
|
8
8
|
"@stonecrop/aform",
|
|
9
9
|
"@stonecrop/atable",
|
|
10
|
+
"@stonecrop/code-editor",
|
|
11
|
+
"@stonecrop/desktop",
|
|
10
12
|
"@stonecrop/stonecrop",
|
|
11
13
|
"@stonecrop/node-editor",
|
|
12
14
|
"@stonecrop/utilities",
|
|
@@ -251,4 +253,4 @@ const module$1 = defineNuxtModule({
|
|
|
251
253
|
}
|
|
252
254
|
});
|
|
253
255
|
|
|
254
|
-
export { module$1 as default };
|
|
256
|
+
export { STONECROP_PACKAGES, module$1 as default };
|
|
@@ -70,14 +70,14 @@
|
|
|
70
70
|
<input
|
|
71
71
|
type="text"
|
|
72
72
|
:value="str(row.__field[p.key])"
|
|
73
|
-
:disabled="
|
|
73
|
+
:disabled="isIdentity(p.key) && isLocked(row.__field)"
|
|
74
74
|
@input="update(row.__realIndex, p.key, value($event) || void 0)" />
|
|
75
75
|
</label>
|
|
76
76
|
<label v-for="p in SELECT_PROPS" :key="p.key" class="field-prop">
|
|
77
77
|
<span>{{ p.label }}</span>
|
|
78
78
|
<select
|
|
79
79
|
:value="str(row.__field[p.key])"
|
|
80
|
-
:disabled="
|
|
80
|
+
:disabled="isIdentity(p.key) && isLocked(row.__field)"
|
|
81
81
|
@change="update(row.__realIndex, p.key, value($event) || void 0)">
|
|
82
82
|
<option value="">—</option>
|
|
83
83
|
<option v-for="o in p.options" :key="o" :value="o">{{ o }}</option>
|
|
@@ -87,7 +87,7 @@
|
|
|
87
87
|
<input
|
|
88
88
|
type="checkbox"
|
|
89
89
|
:checked="bool(row.__field[p.key])"
|
|
90
|
-
:disabled="
|
|
90
|
+
:disabled="isIdentity(p.key) && isLocked(row.__field)"
|
|
91
91
|
@change="update(row.__realIndex, p.key, checked($event) || void 0)" />
|
|
92
92
|
<span>{{ p.label }}</span>
|
|
93
93
|
</label>
|
|
@@ -96,7 +96,7 @@
|
|
|
96
96
|
<input
|
|
97
97
|
type="text"
|
|
98
98
|
:value="jsonStr(row.__field[p.key])"
|
|
99
|
-
:disabled="
|
|
99
|
+
:disabled="isIdentity(p.key) && isLocked(row.__field)"
|
|
100
100
|
:class="{ 'json-invalid': jsonErrors[`${row.__realIndex}:${p.key}`] }"
|
|
101
101
|
@change="updateJson(row.__realIndex, p.key, value($event))" />
|
|
102
102
|
</label>
|
|
@@ -127,11 +127,13 @@
|
|
|
127
127
|
|
|
128
128
|
<script setup>
|
|
129
129
|
import { ATable, ARow } from "@stonecrop/atable";
|
|
130
|
-
import { CANONICAL_COMPONENTS } from "@stonecrop/schema";
|
|
130
|
+
import { CANONICAL_COMPONENTS, INTROSPECTED_IDENTITY_PROPS } from "@stonecrop/schema";
|
|
131
131
|
import { computed, nextTick, ref, useId } from "vue";
|
|
132
|
+
const IDENTITY_PROPS = new Set(INTROSPECTED_IDENTITY_PROPS);
|
|
133
|
+
const isIdentity = (key) => IDENTITY_PROPS.has(key);
|
|
132
134
|
const componentListId = useId();
|
|
133
135
|
const TEXT_PROPS = [
|
|
134
|
-
{ key: "doctype", label: "Link target"
|
|
136
|
+
{ key: "doctype", label: "Link target" },
|
|
135
137
|
{ key: "width", label: "Width" },
|
|
136
138
|
{ key: "mask", label: "Mask" },
|
|
137
139
|
{ key: "format", label: "Format" },
|
|
@@ -143,19 +145,18 @@ const SELECT_PROPS = [
|
|
|
143
145
|
{
|
|
144
146
|
key: "cardinality",
|
|
145
147
|
label: "Cardinality",
|
|
146
|
-
options: ["atMostOne", "one", "noneOrMany", "atLeastOne"]
|
|
147
|
-
identity: true
|
|
148
|
+
options: ["atMostOne", "one", "noneOrMany", "atLeastOne"]
|
|
148
149
|
}
|
|
149
150
|
];
|
|
150
151
|
const BOOL_PROPS = [
|
|
151
152
|
{ key: "readOnly", label: "Read only" },
|
|
152
153
|
{ key: "hidden", label: "Hidden" },
|
|
153
154
|
{ key: "edit", label: "Editable in table" },
|
|
154
|
-
{ key: "primaryKey", label: "Primary key"
|
|
155
|
+
{ key: "primaryKey", label: "Primary key" },
|
|
155
156
|
{ key: "computed", label: "Computed (no DB column)" }
|
|
156
157
|
];
|
|
157
158
|
const JSON_PROPS = [
|
|
158
|
-
{ key: "options", label: "Options"
|
|
159
|
+
{ key: "options", label: "Options" },
|
|
159
160
|
{ key: "default", label: "Default" }
|
|
160
161
|
];
|
|
161
162
|
const FIELD_COLUMNS = [
|
package/dist/types.d.mts
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stonecrop/nuxt",
|
|
3
|
-
"version": "0.16.
|
|
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/
|
|
49
|
-
"@stonecrop/
|
|
50
|
-
"@stonecrop/casl-middleware": "0.16.
|
|
51
|
-
"@stonecrop/
|
|
52
|
-
"@stonecrop/
|
|
53
|
-
"@stonecrop/graphql-middleware": "0.16.
|
|
54
|
-
"@stonecrop/
|
|
55
|
-
"@stonecrop/
|
|
56
|
-
"@stonecrop/
|
|
57
|
-
"@stonecrop/stonecrop": "0.16.
|
|
58
|
-
"@stonecrop/themes": "0.16.
|
|
59
|
-
"@stonecrop/
|
|
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
|
}
|
|
@@ -10,6 +10,7 @@ import consola from 'consola'
|
|
|
10
10
|
import { addDependencies } from '../utils/package'
|
|
11
11
|
import { updateNuxtConfig } from '../utils/config'
|
|
12
12
|
import { loadTemplate } from '../utils/templates'
|
|
13
|
+
import { STONECROP_PACKAGES } from '../../module'
|
|
13
14
|
|
|
14
15
|
export interface FrontendInstallerOptions {
|
|
15
16
|
cwd: string
|
|
@@ -60,15 +61,11 @@ export async function installFrontend(options: FrontendInstallerOptions): Promis
|
|
|
60
61
|
// This is required because the packages use vite-plugin-lib-inject-css which adds
|
|
61
62
|
// CSS imports to the JavaScript bundles. Node.js ESM loader doesn't understand .css files,
|
|
62
63
|
// so we need Nitro to bundle these packages (allowing Vite to process the CSS)
|
|
64
|
+
// Shares the module's list rather than restating it: the two previously disagreed
|
|
65
|
+
// (this one had `desktop` but not `themes`; the module's had the reverse), so a
|
|
66
|
+
// scaffolded app and the module inlined different sets.
|
|
63
67
|
nitroConfig: {
|
|
64
|
-
externalsInline: [
|
|
65
|
-
'@stonecrop/aform',
|
|
66
|
-
'@stonecrop/atable',
|
|
67
|
-
'@stonecrop/stonecrop',
|
|
68
|
-
'@stonecrop/node-editor',
|
|
69
|
-
'@stonecrop/utilities',
|
|
70
|
-
'@stonecrop/desktop',
|
|
71
|
-
],
|
|
68
|
+
externalsInline: [...STONECROP_PACKAGES],
|
|
72
69
|
},
|
|
73
70
|
css: ['@stonecrop/desktop/styles'],
|
|
74
71
|
})
|
package/templates/Project.json
CHANGED
package/templates/Task.json
CHANGED
package/templates/resolvers.ts
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
63
|
-
if (
|
|
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
|
-
|
|
122
|
-
|
|
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
|
|