@voxgig/sdkgen 0.34.10 → 0.35.0
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/bin/voxgig-sdkgen
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
|
|
2
2
|
import {
|
|
3
3
|
nom,
|
|
4
|
+
depluralize,
|
|
4
5
|
} from '@voxgig/apidef'
|
|
5
6
|
|
|
6
7
|
|
|
@@ -11,6 +12,7 @@ import {
|
|
|
11
12
|
Fragment,
|
|
12
13
|
Slot,
|
|
13
14
|
cmp,
|
|
15
|
+
snakify,
|
|
14
16
|
} from '@voxgig/sdkgen'
|
|
15
17
|
|
|
16
18
|
|
|
@@ -127,14 +129,14 @@ function generateDirectLoad(model: any, entity: any) {
|
|
|
127
129
|
return
|
|
128
130
|
}
|
|
129
131
|
|
|
130
|
-
const loadPath = (loadPoint.parts || []).join('/')
|
|
131
132
|
const loadParams = loadPoint.args?.params || []
|
|
133
|
+
const loadPath = normalizePathParams(loadPoint.parts || [], loadParams, loadPoint.rename?.param)
|
|
132
134
|
|
|
133
135
|
// Get list info for live mode bootstrapping
|
|
134
136
|
const listOp = entity.op.list
|
|
135
137
|
const listPoint = listOp?.points?.[0]
|
|
136
|
-
const listPath = listPoint ? (listPoint.parts || []).join('/') : ''
|
|
137
138
|
const listParams = listPoint?.args?.params || []
|
|
139
|
+
const listPath = listPoint ? normalizePathParams(listPoint.parts || [], listParams, listPoint.rename?.param) : ''
|
|
138
140
|
const hasList = null != listPoint
|
|
139
141
|
|
|
140
142
|
// Ancestor params (not 'id') for live mode
|
|
@@ -224,8 +226,8 @@ function generateDirectList(model: any, entity: any) {
|
|
|
224
226
|
return
|
|
225
227
|
}
|
|
226
228
|
|
|
227
|
-
const listPath = (listPoint.parts || []).join('/')
|
|
228
229
|
const listParams = listPoint.args?.params || []
|
|
230
|
+
const listPath = normalizePathParams(listPoint.parts || [], listParams, listPoint.rename?.param)
|
|
229
231
|
|
|
230
232
|
// Build live params
|
|
231
233
|
const liveParams = listParams.map((p: any) => {
|
|
@@ -283,6 +285,52 @@ ${paramAsserts} }
|
|
|
283
285
|
}
|
|
284
286
|
|
|
285
287
|
|
|
288
|
+
// Replace raw OpenAPI parameter names in path parts with model parameter names.
|
|
289
|
+
// Path parts may have e.g. {subBreed} while model params use sub_breed.
|
|
290
|
+
// When a rename mapping exists (e.g. closureId -> id), path parts contain the
|
|
291
|
+
// renamed form {id} but params still use the original name closure_id.
|
|
292
|
+
// The rename mapping is used to reverse-lookup the original param name.
|
|
293
|
+
function normalizePathParams(
|
|
294
|
+
parts: string[],
|
|
295
|
+
params: any[],
|
|
296
|
+
rename?: Record<string, string>
|
|
297
|
+
): string {
|
|
298
|
+
return parts.map((part: string) => {
|
|
299
|
+
// Replace each {paramName} occurrence within the part.
|
|
300
|
+
// Handles both simple parts like "{id}" and compound parts like
|
|
301
|
+
// "{outputFields}.{format}" that contain multiple parameters.
|
|
302
|
+
return part.replace(/\{([^}]+)\}/g, (match: string, rawName: string) => {
|
|
303
|
+
const snaked = snakify(rawName)
|
|
304
|
+
const depluralized = depluralize(snaked)
|
|
305
|
+
const param = params.find((p: any) =>
|
|
306
|
+
p.orig === snaked || p.name === snaked ||
|
|
307
|
+
p.orig === depluralized || p.name === depluralized
|
|
308
|
+
)
|
|
309
|
+
if (param) return '{' + param.name + '}'
|
|
310
|
+
|
|
311
|
+
// Reverse-lookup through rename mapping: if rawName is a renamed value
|
|
312
|
+
// (e.g. "id"), find the original camelCase key (e.g. "closureId"),
|
|
313
|
+
// snakify+depluralize it (e.g. "closure_id"), and match against params.
|
|
314
|
+
if (rename) {
|
|
315
|
+
for (const [origCamel, renamedTo] of Object.entries(rename)) {
|
|
316
|
+
if (renamedTo === rawName) {
|
|
317
|
+
const origSnaked = snakify(origCamel)
|
|
318
|
+
const origDepluralized = depluralize(origSnaked)
|
|
319
|
+
const renamedParam = params.find(
|
|
320
|
+
(p: any) => p.orig === origSnaked || p.name === origSnaked ||
|
|
321
|
+
p.orig === origDepluralized || p.name === origDepluralized
|
|
322
|
+
)
|
|
323
|
+
if (renamedParam) return '{' + renamedParam.name + '}'
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
return match
|
|
329
|
+
})
|
|
330
|
+
}).join('/')
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
|
|
286
334
|
export {
|
|
287
335
|
TestDirect
|
|
288
336
|
}
|
|
@@ -78,9 +78,9 @@ const TestEntity = cmp(function TestEntity(props: any) {
|
|
|
78
78
|
const indent = 2
|
|
79
79
|
|
|
80
80
|
const idlist = flatten([
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
81
|
+
entity.name + '01',
|
|
82
|
+
entity.name + '02',
|
|
83
|
+
entity.name + '03',
|
|
84
84
|
flatten(items(entity.relations.ancestors, (ap: any) =>
|
|
85
85
|
items(ap[1], (a: any) =>
|
|
86
86
|
items(['01', '02', '03'], (n: any) =>
|
|
@@ -156,6 +156,10 @@ function basicSetup(extra?: any) {
|
|
|
156
156
|
|
|
157
157
|
|
|
158
158
|
Slot({ name: 'basic' }, () => {
|
|
159
|
+
const flowHasCreate = Object.values(basicflow.step).some(
|
|
160
|
+
(s: any) => s.op === 'create'
|
|
161
|
+
)
|
|
162
|
+
|
|
159
163
|
Content(`
|
|
160
164
|
const setup = basicSetup()
|
|
161
165
|
const client = setup.client
|
|
@@ -166,6 +170,15 @@ function basicSetup(extra?: any) {
|
|
|
166
170
|
|
|
167
171
|
`)
|
|
168
172
|
|
|
173
|
+
// When the flow has no create step, bootstrap the entity data variable
|
|
174
|
+
// from existing test data so that subsequent update/load/remove steps
|
|
175
|
+
// can reference it.
|
|
176
|
+
if (!flowHasCreate) {
|
|
177
|
+
const ref01 = entity.name + '_ref01'
|
|
178
|
+
Content(` let ${ref01}_data = Object.values(setup.data.existing.${entity.name})[0] as any
|
|
179
|
+
`)
|
|
180
|
+
}
|
|
181
|
+
|
|
169
182
|
each(basicflow.step, (step: any, index: any) => {
|
|
170
183
|
const opgen: OpGen = GENERATE_OP[step.op]
|
|
171
184
|
opgen(model, entity, basicflow, step, index)
|
|
@@ -191,7 +204,7 @@ const generateCreate: OpGen = (
|
|
|
191
204
|
|
|
192
205
|
const priorSteps = Object.values(flow.step).slice(0, Number(index))
|
|
193
206
|
const needsEnt = !priorSteps.some((s: any) =>
|
|
194
|
-
['create', 'list', 'load', 'remove'].includes(s.op))
|
|
207
|
+
['create', 'list', 'load', 'update', 'remove'].includes(s.op))
|
|
195
208
|
|
|
196
209
|
const hasDatvar = priorSteps.some((s: any) => {
|
|
197
210
|
if ('create' === s.op) {
|
|
@@ -243,7 +256,7 @@ const generateList: OpGen = (
|
|
|
243
256
|
|
|
244
257
|
const priorSteps = Object.values(flow.step).slice(0, Number(index))
|
|
245
258
|
const needsEnt = !priorSteps.some((s: any) =>
|
|
246
|
-
['create', 'list', 'load', 'remove'].includes(s.op))
|
|
259
|
+
['create', 'list', 'load', 'update', 'remove'].includes(s.op))
|
|
247
260
|
|
|
248
261
|
Content(`
|
|
249
262
|
// LIST
|
|
@@ -298,9 +311,18 @@ const generateUpdate: OpGen = (
|
|
|
298
311
|
const markdefvar = step.input.markdefvar ?? (ref + '_markdef' + (step.input.suffix ?? ''))
|
|
299
312
|
const srcdatavar = step.input.srcdatavar ?? (ref + '_data' + (step.input.suffix ?? ''))
|
|
300
313
|
|
|
314
|
+
const priorSteps = Object.values(flow.step).slice(0, Number(index))
|
|
315
|
+
const needsEnt = !priorSteps.some((s: any) =>
|
|
316
|
+
['create', 'list', 'load', 'update', 'remove'].includes(s.op))
|
|
317
|
+
|
|
301
318
|
Content(`
|
|
302
319
|
// UPDATE
|
|
303
|
-
|
|
320
|
+
`)
|
|
321
|
+
if (needsEnt) {
|
|
322
|
+
Content(` const ${entvar} = client.${nom(entity, 'Name')}()
|
|
323
|
+
`)
|
|
324
|
+
}
|
|
325
|
+
Content(` const ${datavar}: any = {}
|
|
304
326
|
${datavar}.id = ${srcdatavar}.id
|
|
305
327
|
`)
|
|
306
328
|
|
|
@@ -331,7 +353,7 @@ const generateUpdate: OpGen = (
|
|
|
331
353
|
|
|
332
354
|
for (let sI = 0; sI < step.spec.length; sI++) {
|
|
333
355
|
const spec = step.spec[sI]
|
|
334
|
-
if ('TextFieldMark' === spec.apply) {
|
|
356
|
+
if ('TextFieldMark' === spec.apply && null != step.input.textfield) {
|
|
335
357
|
Content(`
|
|
336
358
|
assert(${resdatavar}[${markdefvar}.name] === ${markdefvar}.value)
|
|
337
359
|
`)
|
|
@@ -356,14 +378,31 @@ const generateLoad: OpGen = (
|
|
|
356
378
|
|
|
357
379
|
const priorSteps = Object.values(flow.step).slice(0, Number(index))
|
|
358
380
|
const hasEntVar = priorSteps.some((s: any) =>
|
|
359
|
-
['create', 'list', 'load', 'remove'].includes(s.op))
|
|
381
|
+
['create', 'list', 'load', 'update', 'remove'].includes(s.op))
|
|
382
|
+
|
|
383
|
+
// Check if srcdatavar was declared by a prior create step or by the
|
|
384
|
+
// preamble bootstrap (which runs when the flow has no create step)
|
|
385
|
+
const flowHasCreate = Object.values(flow.step).some((s: any) => s.op === 'create')
|
|
386
|
+
const preambleRef = entity.name + '_ref01'
|
|
387
|
+
const hasSrcData = (!flowHasCreate && srcdatavar === preambleRef + '_data') ||
|
|
388
|
+
priorSteps.some((s: any) => {
|
|
389
|
+
if ('create' === s.op) {
|
|
390
|
+
const priorRef = s.input?.ref ?? entity.name + '_ref01'
|
|
391
|
+
const priorDatvar = s.input?.datavar ?? (priorRef + '_data' + (s.input?.suffix ?? ''))
|
|
392
|
+
return priorDatvar === srcdatavar
|
|
393
|
+
}
|
|
394
|
+
return false
|
|
395
|
+
})
|
|
360
396
|
|
|
361
397
|
Content(`
|
|
362
398
|
// LOAD
|
|
363
399
|
`)
|
|
364
400
|
if (!hasEntVar) {
|
|
365
401
|
Content(` const ${entvar} = client.${nom(entity, 'Name')}()
|
|
366
|
-
|
|
402
|
+
`)
|
|
403
|
+
}
|
|
404
|
+
if (!hasSrcData) {
|
|
405
|
+
Content(` const ${srcdatavar} = Object.values(setup.data.existing.${entity.name})[0] as any
|
|
367
406
|
`)
|
|
368
407
|
}
|
|
369
408
|
Content(` const ${matchvar}: any = {}
|
|
@@ -388,7 +427,7 @@ const generateRemove: OpGen = (
|
|
|
388
427
|
|
|
389
428
|
const priorSteps = Object.values(flow.step).slice(0, Number(index))
|
|
390
429
|
const needsEnt = !priorSteps.some((s: any) =>
|
|
391
|
-
['create', 'list', 'load', 'remove'].includes(s.op))
|
|
430
|
+
['create', 'list', 'load', 'update', 'remove'].includes(s.op))
|
|
392
431
|
|
|
393
432
|
Content(`
|
|
394
433
|
// REMOVE
|