@specverse/engines 4.3.1 → 4.3.3
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/inference/ui-contracts/rules/action-buttons-present.d.ts +4 -0
- package/dist/inference/ui-contracts/rules/action-buttons-present.d.ts.map +1 -1
- package/dist/inference/ui-contracts/rules/action-buttons-present.js +70 -20
- package/dist/inference/ui-contracts/rules/action-buttons-present.js.map +1 -1
- package/dist/inference/ui-contracts/translator.d.ts.map +1 -1
- package/dist/inference/ui-contracts/translator.js +20 -1
- package/dist/inference/ui-contracts/translator.js.map +1 -1
- package/dist/libs/instance-factories/applications/templates/react/api-client-generator.js +20 -11
- package/libs/instance-factories/applications/templates/react/api-client-generator.ts +20 -11
- package/package.json +1 -1
|
@@ -16,6 +16,10 @@
|
|
|
16
16
|
* its row before asserting. Retrieve + validate fire implicitly and
|
|
17
17
|
* have no user-facing button.
|
|
18
18
|
*
|
|
19
|
+
* Models with required `belongsTo` relationships have their parents
|
|
20
|
+
* seeded first (recursively) and the parent's id threaded into the
|
|
21
|
+
* FK field via `$expr:varName.id`.
|
|
22
|
+
*
|
|
19
23
|
* One TestCase per (controller, cured-operation) pair.
|
|
20
24
|
*/
|
|
21
25
|
import type { UiContractRule } from '../test-case-types.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"action-buttons-present.d.ts","sourceRoot":"","sources":["../../../../src/inference/ui-contracts/rules/action-buttons-present.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"action-buttons-present.d.ts","sourceRoot":"","sources":["../../../../src/inference/ui-contracts/rules/action-buttons-present.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAkF,MAAM,uBAAuB,CAAC;AAE5I,eAAO,MAAM,OAAO,2BAA2B,CAAC;AAqHhD,eAAO,MAAM,oBAAoB,EAAE,cAyClC,CAAC"}
|
|
@@ -16,6 +16,10 @@
|
|
|
16
16
|
* its row before asserting. Retrieve + validate fire implicitly and
|
|
17
17
|
* have no user-facing button.
|
|
18
18
|
*
|
|
19
|
+
* Models with required `belongsTo` relationships have their parents
|
|
20
|
+
* seeded first (recursively) and the parent's id threaded into the
|
|
21
|
+
* FK field via `$expr:varName.id`.
|
|
22
|
+
*
|
|
19
23
|
* One TestCase per (controller, cured-operation) pair.
|
|
20
24
|
*/
|
|
21
25
|
export const RULE_ID = 'action-buttons-present';
|
|
@@ -30,15 +34,8 @@ const CURED_LABELS = new Set([
|
|
|
30
34
|
/**
|
|
31
35
|
* Build a minimal-but-valid body for createEntity against a model.
|
|
32
36
|
* Covers required non-auto business attributes with type-based
|
|
33
|
-
* defaults. Skips
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
* Models with required belongsTo relationships would need a parent
|
|
37
|
-
* entity created first; this helper doesn't handle that, so tests
|
|
38
|
-
* for such models' update/delete/evolve buttons may fail at the
|
|
39
|
-
* createEntity step. That's a rule-design gap, tracked as future
|
|
40
|
-
* work — the alternative (skipping the test) would silently lose
|
|
41
|
-
* coverage.
|
|
37
|
+
* defaults. Skips metadata + relationship categories — relationship
|
|
38
|
+
* FK values are provided separately by the seed-chain builder.
|
|
42
39
|
*/
|
|
43
40
|
function synthesizeBody(model) {
|
|
44
41
|
const out = {};
|
|
@@ -78,12 +75,65 @@ function defaultValueForAttribute(attr) {
|
|
|
78
75
|
case 'uuid':
|
|
79
76
|
return '00000000-0000-0000-0000-000000000000';
|
|
80
77
|
default:
|
|
81
|
-
// String / Text / Email / Url / URL / arbitrary — use the
|
|
82
|
-
// attribute name as a unique-ish marker so assertEntityInList
|
|
83
|
-
// can match it later if the rule binds one.
|
|
84
78
|
return `test-${attr.name}`;
|
|
85
79
|
}
|
|
86
80
|
}
|
|
81
|
+
/**
|
|
82
|
+
* Walk a model's belongsTo relationships and emit createEntity steps
|
|
83
|
+
* for every dependency, seeding leaves first. Each seed binds to a
|
|
84
|
+
* unique variable name; FK fields on downstream models reference
|
|
85
|
+
* those variables via `$expr:varName.id`.
|
|
86
|
+
*
|
|
87
|
+
* Returns the ordered step list + the variable name bound to the
|
|
88
|
+
* final (target) model.
|
|
89
|
+
*
|
|
90
|
+
* Cycles are guarded: if A → B → A, the second visit skips. Cyclic
|
|
91
|
+
* required-FK specs would be unsatisfiable anyway.
|
|
92
|
+
*/
|
|
93
|
+
function buildSeedChain(model, modelByName) {
|
|
94
|
+
const steps = [];
|
|
95
|
+
const bindings = new Map(); // modelName -> varName
|
|
96
|
+
const inProgress = new Set();
|
|
97
|
+
function seed(m) {
|
|
98
|
+
const existing = bindings.get(m.name);
|
|
99
|
+
if (existing)
|
|
100
|
+
return existing;
|
|
101
|
+
if (inProgress.has(m.name)) {
|
|
102
|
+
// Cycle — fall back to bare body without the FK (will likely
|
|
103
|
+
// fail at the backend, but the test will surface the issue
|
|
104
|
+
// rather than the rule crashing).
|
|
105
|
+
return `seed_${m.name}`;
|
|
106
|
+
}
|
|
107
|
+
inProgress.add(m.name);
|
|
108
|
+
const body = synthesizeBody(m);
|
|
109
|
+
for (const rel of m.relationships || []) {
|
|
110
|
+
if (!isBelongsTo(rel))
|
|
111
|
+
continue;
|
|
112
|
+
if (!rel.target)
|
|
113
|
+
continue;
|
|
114
|
+
const parent = modelByName.get(rel.target);
|
|
115
|
+
if (!parent)
|
|
116
|
+
continue;
|
|
117
|
+
const parentVar = seed(parent);
|
|
118
|
+
body[`${rel.name}Id`] = `$expr:${parentVar}.id`;
|
|
119
|
+
}
|
|
120
|
+
const myVar = `seed_${m.name}`;
|
|
121
|
+
steps.push({
|
|
122
|
+
action: 'createEntity',
|
|
123
|
+
modelName: m.name,
|
|
124
|
+
data: body,
|
|
125
|
+
bindAs: myVar,
|
|
126
|
+
});
|
|
127
|
+
bindings.set(m.name, myVar);
|
|
128
|
+
inProgress.delete(m.name);
|
|
129
|
+
return myVar;
|
|
130
|
+
}
|
|
131
|
+
const targetVar = seed(model);
|
|
132
|
+
return { steps, targetVar };
|
|
133
|
+
}
|
|
134
|
+
function isBelongsTo(rel) {
|
|
135
|
+
return String(rel.type || '').toLowerCase() === 'belongsto';
|
|
136
|
+
}
|
|
87
137
|
export const actionButtonsPresent = (spec) => {
|
|
88
138
|
const cases = [];
|
|
89
139
|
const modelByName = new Map();
|
|
@@ -95,24 +145,24 @@ export const actionButtonsPresent = (spec) => {
|
|
|
95
145
|
continue;
|
|
96
146
|
const modelName = controller.model || controller.name.replace(/Controller$/, '');
|
|
97
147
|
const model = modelByName.get(modelName);
|
|
98
|
-
|
|
148
|
+
if (!model)
|
|
149
|
+
continue;
|
|
99
150
|
for (const opName of Object.keys(cured)) {
|
|
100
151
|
if (!CURED_LABELS.has(opName))
|
|
101
152
|
continue;
|
|
102
153
|
if (opName === 'retrieve' || opName === 'validate')
|
|
103
154
|
continue;
|
|
104
|
-
// Navigate to form — the walker's form view renders Create
|
|
105
|
-
// unconditionally and Update / Delete / Evolve once an entity
|
|
106
|
-
// is selected.
|
|
107
155
|
const steps = [
|
|
108
156
|
{ action: 'bootRuntime' },
|
|
109
157
|
{ action: 'navigateToModelForm', modelName },
|
|
110
158
|
];
|
|
111
159
|
if (opName !== 'create') {
|
|
112
|
-
// Seed an entity
|
|
113
|
-
//
|
|
114
|
-
|
|
115
|
-
|
|
160
|
+
// Seed an entity (plus any belongsTo parents) via API, then
|
|
161
|
+
// click its row to put the form into update mode where
|
|
162
|
+
// Update / Delete / Evolve render.
|
|
163
|
+
const { steps: seedSteps, targetVar } = buildSeedChain(model, modelByName);
|
|
164
|
+
steps.push(...seedSteps);
|
|
165
|
+
steps.push({ action: 'selectEntityInList', idExpr: `${targetVar}.id` });
|
|
116
166
|
}
|
|
117
167
|
steps.push({ action: 'expectActionButton', modelName, actionLabel: opName });
|
|
118
168
|
cases.push({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"action-buttons-present.js","sourceRoot":"","sources":["../../../../src/inference/ui-contracts/rules/action-buttons-present.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"action-buttons-present.js","sourceRoot":"","sources":["../../../../src/inference/ui-contracts/rules/action-buttons-present.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"translator.d.ts","sourceRoot":"","sources":["../../../src/inference/ui-contracts/translator.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAY,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"translator.d.ts","sourceRoot":"","sources":["../../../src/inference/ui-contracts/translator.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAY,MAAM,sBAAsB,CAAC;AA+H/D;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,MAAM,CA6B5E"}
|
|
@@ -7,6 +7,21 @@
|
|
|
7
7
|
* helpers. The translator is intentionally dumb: each step maps to a
|
|
8
8
|
* helper call, nothing more.
|
|
9
9
|
*/
|
|
10
|
+
/**
|
|
11
|
+
* Render a `createEntity` data object. String values prefixed with
|
|
12
|
+
* `$expr:` emit as raw JS identifiers (e.g. `$expr:p.id` → `p.id`),
|
|
13
|
+
* so rules can thread bound variables from earlier steps into FK
|
|
14
|
+
* fields. Everything else round-trips through JSON.stringify.
|
|
15
|
+
*/
|
|
16
|
+
function renderDataLit(data) {
|
|
17
|
+
const parts = Object.entries(data).map(([k, v]) => {
|
|
18
|
+
if (typeof v === 'string' && v.startsWith('$expr:')) {
|
|
19
|
+
return `${JSON.stringify(k)}: ${v.slice(6)}`;
|
|
20
|
+
}
|
|
21
|
+
return `${JSON.stringify(k)}: ${JSON.stringify(v)}`;
|
|
22
|
+
});
|
|
23
|
+
return `{ ${parts.join(', ')} }`;
|
|
24
|
+
}
|
|
10
25
|
/**
|
|
11
26
|
* Render a single step as a line of test body code.
|
|
12
27
|
*/
|
|
@@ -40,7 +55,11 @@ function renderStep(step) {
|
|
|
40
55
|
return ` await expectActionButton(page, ${JSON.stringify(step.modelName)}, ${JSON.stringify(step.actionLabel)});`;
|
|
41
56
|
case 'createEntity': {
|
|
42
57
|
const varName = step.bindAs || 'created';
|
|
43
|
-
|
|
58
|
+
// String values prefixed with `$expr:` are emitted as raw
|
|
59
|
+
// identifier expressions (not JSON literals). Lets rules
|
|
60
|
+
// reference other bound variables — e.g. pollId = parentPoll.id
|
|
61
|
+
// when seeding Option after Poll.
|
|
62
|
+
const dataLit = renderDataLit(step.data);
|
|
44
63
|
const optsLit = step.uniqueField
|
|
45
64
|
? `, { uniqueField: ${JSON.stringify(step.uniqueField)} }`
|
|
46
65
|
: '';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"translator.js","sourceRoot":"","sources":["../../../src/inference/ui-contracts/translator.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH;;GAEG;AACH,SAAS,UAAU,CAAC,IAAc;IAChC,QAAQ,IAAI,CAAC,MAAM,EAAE,CAAC;QACpB,KAAK,aAAa;YAChB,+DAA+D;YAC/D,iEAAiE;YACjE,OAAO,gDAAgD,CAAC;QAC1D,KAAK,mBAAmB;YACtB,OAAO,mCAAmC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;QAC/E,KAAK,iBAAiB;YACpB,OAAO,iCAAiC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;QAC7E,KAAK,qBAAqB;YACxB,OAAO,qCAAqC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;QACjF,KAAK,uBAAuB;YAC1B,OAAO,uCAAuC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;QACnF,KAAK,mBAAmB;YACtB,OAAO,kCAAkC,CAAC;QAC5C,KAAK,kBAAkB;YACrB,OAAO,kCAAkC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC;QACrH,KAAK,iBAAiB,CAAC,CAAC,CAAC;YACvB,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,EAAE,CAAC;YACzD,OAAO,iCAAiC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,aAAa,CAAC,GAAG,IAAI,IAAI,CAAC;QAC3H,CAAC;QACD,KAAK,sBAAsB;YACzB,OAAO,sCAAsC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;QACrH,KAAK,2BAA2B;YAC9B,OAAO,2CAA2C,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC;QACjI,KAAK,oBAAoB;YACvB,OAAO,oCAAoC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC;QACrH,KAAK,cAAc,CAAC,CAAC,CAAC;YACpB,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,IAAI,SAAS,CAAC;YACzC,MAAM,OAAO,GAAG,
|
|
1
|
+
{"version":3,"file":"translator.js","sourceRoot":"","sources":["../../../src/inference/ui-contracts/translator.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH;;;;;GAKG;AACH,SAAS,aAAa,CAAC,IAA6B;IAClD,MAAM,KAAK,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE;QAChD,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;YACpD,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;QAC/C,CAAC;QACD,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC;IACtD,CAAC,CAAC,CAAC;IACH,OAAO,KAAK,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;AACnC,CAAC;AAED;;GAEG;AACH,SAAS,UAAU,CAAC,IAAc;IAChC,QAAQ,IAAI,CAAC,MAAM,EAAE,CAAC;QACpB,KAAK,aAAa;YAChB,+DAA+D;YAC/D,iEAAiE;YACjE,OAAO,gDAAgD,CAAC;QAC1D,KAAK,mBAAmB;YACtB,OAAO,mCAAmC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;QAC/E,KAAK,iBAAiB;YACpB,OAAO,iCAAiC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;QAC7E,KAAK,qBAAqB;YACxB,OAAO,qCAAqC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;QACjF,KAAK,uBAAuB;YAC1B,OAAO,uCAAuC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;QACnF,KAAK,mBAAmB;YACtB,OAAO,kCAAkC,CAAC;QAC5C,KAAK,kBAAkB;YACrB,OAAO,kCAAkC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC;QACrH,KAAK,iBAAiB,CAAC,CAAC,CAAC;YACvB,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,EAAE,CAAC;YACzD,OAAO,iCAAiC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,aAAa,CAAC,GAAG,IAAI,IAAI,CAAC;QAC3H,CAAC;QACD,KAAK,sBAAsB;YACzB,OAAO,sCAAsC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;QACrH,KAAK,2BAA2B;YAC9B,OAAO,2CAA2C,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC;QACjI,KAAK,oBAAoB;YACvB,OAAO,oCAAoC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC;QACrH,KAAK,cAAc,CAAC,CAAC,CAAC;YACpB,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,IAAI,SAAS,CAAC;YACzC,0DAA0D;YAC1D,yDAAyD;YACzD,gEAAgE;YAChE,kCAAkC;YAClC,MAAM,OAAO,GAAG,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACzC,MAAM,OAAO,GAAG,IAAI,CAAC,WAAW;gBAC9B,CAAC,CAAC,oBAAoB,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI;gBAC1D,CAAC,CAAC,EAAE,CAAC;YACP,OAAO,WAAW,OAAO,+BAA+B,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,OAAO,GAAG,OAAO,IAAI,CAAC;QACnH,CAAC;QACD,KAAK,oBAAoB;YACvB,OAAO,oCAAoC,IAAI,CAAC,MAAM,IAAI,CAAC;QAC7D,KAAK,cAAc;YACjB,OAAO,8BAA8B,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,IAAI,CAAC,MAAM,IAAI,CAAC;QAC1F,KAAK,cAAc;YACjB,OAAO,8BAA8B,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,IAAI,CAAC,MAAM,KAAK,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC;QAC/H,KAAK,oBAAoB,CAAC,CAAC,CAAC;YAC1B,MAAM,OAAO,GAAG,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,YAAY,IAAI,EAAE,CAAC,CAAC;YAC5E,OAAO,oCAAoC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,OAAO,IAAI,CAAC;QAC5F,CAAC;QACD,KAAK,oBAAoB,CAAC,CAAC,CAAC;YAC1B,MAAM,OAAO,GAAG,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,YAAY,IAAI,EAAE,CAAC,CAAC;YAC5E,OAAO,oCAAoC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,OAAO,IAAI,CAAC;QAC5F,CAAC;QACD,OAAO,CAAC,CAAC,CAAC;YACR,MAAM,WAAW,GAAU,IAAI,CAAC;YAChC,MAAM,IAAI,KAAK,CAAC,oCAAoC,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;QACrF,CAAC;IACH,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,SAAS,UAAU,CAAC,IAAc;IAChC,QAAQ,IAAI,CAAC,MAAM,EAAE,CAAC;QACpB,KAAK,aAAa;YAChB,OAAO,CAAC,aAAa,CAAC,CAAC;QACzB,KAAK,mBAAmB;YACtB,OAAO,CAAC,mBAAmB,CAAC,CAAC;QAC/B,KAAK,iBAAiB;YACpB,OAAO,CAAC,iBAAiB,CAAC,CAAC;QAC7B,KAAK,qBAAqB;YACxB,OAAO,CAAC,qBAAqB,CAAC,CAAC;QACjC,KAAK,uBAAuB;YAC1B,OAAO,CAAC,uBAAuB,CAAC,CAAC;QACnC,KAAK,mBAAmB;YACtB,OAAO,CAAC,mBAAmB,CAAC,CAAC;QAC/B,KAAK,kBAAkB;YACrB,OAAO,CAAC,kBAAkB,CAAC,CAAC;QAC9B,KAAK,iBAAiB;YACpB,OAAO,CAAC,iBAAiB,CAAC,CAAC;QAC7B,KAAK,sBAAsB;YACzB,OAAO,CAAC,sBAAsB,CAAC,CAAC;QAClC,KAAK,2BAA2B;YAC9B,OAAO,CAAC,2BAA2B,CAAC,CAAC;QACvC,KAAK,oBAAoB;YACvB,OAAO,CAAC,oBAAoB,CAAC,CAAC;QAChC,KAAK,cAAc;YACjB,OAAO,CAAC,cAAc,CAAC,CAAC;QAC1B,KAAK,oBAAoB;YACvB,OAAO,CAAC,oBAAoB,CAAC,CAAC;QAChC,KAAK,cAAc;YACjB,OAAO,CAAC,cAAc,CAAC,CAAC;QAC1B,KAAK,cAAc;YACjB,OAAO,CAAC,cAAc,CAAC,CAAC;QAC1B,KAAK,oBAAoB;YACvB,OAAO,CAAC,oBAAoB,CAAC,CAAC;QAChC,KAAK,oBAAoB;YACvB,OAAO,CAAC,oBAAoB,CAAC,CAAC;QAChC;YACE,OAAO,EAAE,CAAC;IACd,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAAC,MAAc,EAAE,SAAqB;IAClE,MAAM,OAAO,GAAG,IAAI,GAAG,EAAU,CAAC;IAClC,KAAK,MAAM,EAAE,IAAI,SAAS,EAAE,CAAC;QAC3B,KAAK,MAAM,IAAI,IAAI,EAAE,CAAC,KAAK,EAAE,CAAC;YAC5B,KAAK,MAAM,CAAC,IAAI,UAAU,CAAC,IAAI,CAAC;gBAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QACnD,CAAC;IACH,CAAC;IACD,MAAM,UAAU,GAAG,CAAC,GAAG,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAElD,MAAM,MAAM,GAAG;;WAEN,MAAM;;;;;;WAMN,UAAU;CACpB,CAAC;IAEA,MAAM,IAAI,GAAG,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE;QAC9B,MAAM,SAAS,GAAG,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACtD,OAAO;OACJ,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,IAAI,CAAC;EAC5B,SAAS;IACP,CAAC;IACH,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAEd,OAAO,MAAM,GAAG,IAAI,GAAG,IAAI,CAAC;AAC9B,CAAC"}
|
|
@@ -30,6 +30,19 @@ function generateApiClient(pattern) {
|
|
|
30
30
|
|
|
31
31
|
import type { ApiResponse, RuntimeInfo, ModelSchema, View, Service, Behavior, Entity, Operation } from '../types/api';
|
|
32
32
|
|
|
33
|
+
/**
|
|
34
|
+
* English pluralizer, matches \`deriveBasePath\` in
|
|
35
|
+
* @specverse/types/spec-rules \u2014 the source of truth for how the
|
|
36
|
+
* backend pluralizes REST paths. Keep in sync: Category \u2192
|
|
37
|
+
* categories (not \`categorys\`), Box \u2192 boxes, Child \u2192 childs (yes,
|
|
38
|
+
* naive \u2014 irregulars not supported).
|
|
39
|
+
*/
|
|
40
|
+
function pluralize(s: string): string {
|
|
41
|
+
if (/[^aeiou]y$/i.test(s)) return s.slice(0, -1) + 'ies';
|
|
42
|
+
if (/(s|x|z|ch|sh)$/i.test(s)) return s + 'es';
|
|
43
|
+
return s + 's';
|
|
44
|
+
}
|
|
45
|
+
|
|
33
46
|
// Get API URL from query parameter or default to proxy
|
|
34
47
|
const urlParams = new URLSearchParams(window.location.search);
|
|
35
48
|
const apiUrl = urlParams.get('api');
|
|
@@ -225,10 +238,8 @@ export async function getModelSchema(modelName: string): Promise<ModelSchema> {
|
|
|
225
238
|
*/
|
|
226
239
|
export async function listEntities(controllerName: string): Promise<Entity[]> {
|
|
227
240
|
try {
|
|
228
|
-
//
|
|
229
|
-
const modelName = controllerName
|
|
230
|
-
.replace(/Controller$/, '')
|
|
231
|
-
.toLowerCase() + 's';
|
|
241
|
+
// Derive REST path \u2014 matches \`deriveBasePath\` in the backend.
|
|
242
|
+
const modelName = pluralize(controllerName.replace(/Controller$/, '').toLowerCase());
|
|
232
243
|
|
|
233
244
|
const entities = await apiRequest<Entity[]>('GET', \`/\${modelName}\`);
|
|
234
245
|
return entities || [];
|
|
@@ -247,10 +258,8 @@ export async function executeOperation(
|
|
|
247
258
|
operationName: string,
|
|
248
259
|
params: Record<string, any>
|
|
249
260
|
): Promise<ApiResponse> {
|
|
250
|
-
//
|
|
251
|
-
const modelName = controllerName
|
|
252
|
-
.replace(/Controller$/, '')
|
|
253
|
-
.toLowerCase() + 's';
|
|
261
|
+
// Derive REST path \u2014 matches \`deriveBasePath\` in the backend.
|
|
262
|
+
const modelName = pluralize(controllerName.replace(/Controller$/, '').toLowerCase());
|
|
254
263
|
|
|
255
264
|
let method: string;
|
|
256
265
|
let path: string;
|
|
@@ -344,7 +353,7 @@ export async function transitionState(
|
|
|
344
353
|
body.lifecycleName = lifecycleName;
|
|
345
354
|
}
|
|
346
355
|
|
|
347
|
-
const resource = modelName.toLowerCase()
|
|
356
|
+
const resource = pluralize(modelName.toLowerCase());
|
|
348
357
|
return apiRequest<ApiResponse>(
|
|
349
358
|
'PATCH',
|
|
350
359
|
\`/\${resource}/\${entityId}/evolve\`,
|
|
@@ -360,7 +369,7 @@ export async function getAvailableTransitions(
|
|
|
360
369
|
entityId: string,
|
|
361
370
|
lifecycleName?: string
|
|
362
371
|
): Promise<string[]> {
|
|
363
|
-
const resource = modelName.toLowerCase()
|
|
372
|
+
const resource = pluralize(modelName.toLowerCase());
|
|
364
373
|
const url = lifecycleName
|
|
365
374
|
? \`/\${resource}/\${entityId}/transitions?lifecycleName=\${lifecycleName}\`
|
|
366
375
|
: \`/\${resource}/\${entityId}/transitions\`;
|
|
@@ -453,7 +462,7 @@ export async function transitionState(
|
|
|
453
462
|
body.lifecycleName = lifecycleName;
|
|
454
463
|
}
|
|
455
464
|
|
|
456
|
-
const resource = modelName.toLowerCase()
|
|
465
|
+
const resource = pluralize(modelName.toLowerCase());
|
|
457
466
|
return apiRequest<ApiResponse>(
|
|
458
467
|
'PATCH',
|
|
459
468
|
\`/\${resource}/\${entityId}/evolve\`,
|
|
@@ -63,6 +63,19 @@ function generateApiClient(pattern: 'rest' | 'controller'): string {
|
|
|
63
63
|
|
|
64
64
|
import type { ApiResponse, RuntimeInfo, ModelSchema, View, Service, Behavior, Entity, Operation } from '../types/api';
|
|
65
65
|
|
|
66
|
+
/**
|
|
67
|
+
* English pluralizer, matches \`deriveBasePath\` in
|
|
68
|
+
* @specverse/types/spec-rules — the source of truth for how the
|
|
69
|
+
* backend pluralizes REST paths. Keep in sync: Category →
|
|
70
|
+
* categories (not \`categorys\`), Box → boxes, Child → childs (yes,
|
|
71
|
+
* naive — irregulars not supported).
|
|
72
|
+
*/
|
|
73
|
+
function pluralize(s: string): string {
|
|
74
|
+
if (/[^aeiou]y$/i.test(s)) return s.slice(0, -1) + 'ies';
|
|
75
|
+
if (/(s|x|z|ch|sh)$/i.test(s)) return s + 'es';
|
|
76
|
+
return s + 's';
|
|
77
|
+
}
|
|
78
|
+
|
|
66
79
|
// Get API URL from query parameter or default to proxy
|
|
67
80
|
const urlParams = new URLSearchParams(window.location.search);
|
|
68
81
|
const apiUrl = urlParams.get('api');
|
|
@@ -261,10 +274,8 @@ export async function getModelSchema(modelName: string): Promise<ModelSchema> {
|
|
|
261
274
|
*/
|
|
262
275
|
export async function listEntities(controllerName: string): Promise<Entity[]> {
|
|
263
276
|
try {
|
|
264
|
-
//
|
|
265
|
-
const modelName = controllerName
|
|
266
|
-
.replace(/Controller$/, '')
|
|
267
|
-
.toLowerCase() + 's';
|
|
277
|
+
// Derive REST path — matches \`deriveBasePath\` in the backend.
|
|
278
|
+
const modelName = pluralize(controllerName.replace(/Controller$/, '').toLowerCase());
|
|
268
279
|
|
|
269
280
|
const entities = await apiRequest<Entity[]>('GET', \`/\${modelName}\`);
|
|
270
281
|
return entities || [];
|
|
@@ -283,10 +294,8 @@ export async function executeOperation(
|
|
|
283
294
|
operationName: string,
|
|
284
295
|
params: Record<string, any>
|
|
285
296
|
): Promise<ApiResponse> {
|
|
286
|
-
//
|
|
287
|
-
const modelName = controllerName
|
|
288
|
-
.replace(/Controller$/, '')
|
|
289
|
-
.toLowerCase() + 's';
|
|
297
|
+
// Derive REST path — matches \`deriveBasePath\` in the backend.
|
|
298
|
+
const modelName = pluralize(controllerName.replace(/Controller$/, '').toLowerCase());
|
|
290
299
|
|
|
291
300
|
let method: string;
|
|
292
301
|
let path: string;
|
|
@@ -380,7 +389,7 @@ export async function transitionState(
|
|
|
380
389
|
body.lifecycleName = lifecycleName;
|
|
381
390
|
}
|
|
382
391
|
|
|
383
|
-
const resource = modelName.toLowerCase()
|
|
392
|
+
const resource = pluralize(modelName.toLowerCase());
|
|
384
393
|
return apiRequest<ApiResponse>(
|
|
385
394
|
'PATCH',
|
|
386
395
|
\`/\${resource}/\${entityId}/evolve\`,
|
|
@@ -396,7 +405,7 @@ export async function getAvailableTransitions(
|
|
|
396
405
|
entityId: string,
|
|
397
406
|
lifecycleName?: string
|
|
398
407
|
): Promise<string[]> {
|
|
399
|
-
const resource = modelName.toLowerCase()
|
|
408
|
+
const resource = pluralize(modelName.toLowerCase());
|
|
400
409
|
const url = lifecycleName
|
|
401
410
|
? \`/\${resource}/\${entityId}/transitions?lifecycleName=\${lifecycleName}\`
|
|
402
411
|
: \`/\${resource}/\${entityId}/transitions\`;
|
|
@@ -490,7 +499,7 @@ export async function transitionState(
|
|
|
490
499
|
body.lifecycleName = lifecycleName;
|
|
491
500
|
}
|
|
492
501
|
|
|
493
|
-
const resource = modelName.toLowerCase()
|
|
502
|
+
const resource = pluralize(modelName.toLowerCase());
|
|
494
503
|
return apiRequest<ApiResponse>(
|
|
495
504
|
'PATCH',
|
|
496
505
|
\`/\${resource}/\${entityId}/evolve\`,
|