@voxgig/sdkgen 0.34.11 → 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
|
|
|
@@ -129,13 +130,13 @@ function generateDirectLoad(model: any, entity: any) {
|
|
|
129
130
|
}
|
|
130
131
|
|
|
131
132
|
const loadParams = loadPoint.args?.params || []
|
|
132
|
-
const loadPath = normalizePathParams(loadPoint.parts || [], loadParams)
|
|
133
|
+
const loadPath = normalizePathParams(loadPoint.parts || [], loadParams, loadPoint.rename?.param)
|
|
133
134
|
|
|
134
135
|
// Get list info for live mode bootstrapping
|
|
135
136
|
const listOp = entity.op.list
|
|
136
137
|
const listPoint = listOp?.points?.[0]
|
|
137
138
|
const listParams = listPoint?.args?.params || []
|
|
138
|
-
const listPath = listPoint ? normalizePathParams(listPoint.parts || [], listParams) : ''
|
|
139
|
+
const listPath = listPoint ? normalizePathParams(listPoint.parts || [], listParams, listPoint.rename?.param) : ''
|
|
139
140
|
const hasList = null != listPoint
|
|
140
141
|
|
|
141
142
|
// Ancestor params (not 'id') for live mode
|
|
@@ -226,7 +227,7 @@ function generateDirectList(model: any, entity: any) {
|
|
|
226
227
|
}
|
|
227
228
|
|
|
228
229
|
const listParams = listPoint.args?.params || []
|
|
229
|
-
const listPath = normalizePathParams(listPoint.parts || [], listParams)
|
|
230
|
+
const listPath = normalizePathParams(listPoint.parts || [], listParams, listPoint.rename?.param)
|
|
230
231
|
|
|
231
232
|
// Build live params
|
|
232
233
|
const liveParams = listParams.map((p: any) => {
|
|
@@ -286,15 +287,46 @@ ${paramAsserts} }
|
|
|
286
287
|
|
|
287
288
|
// Replace raw OpenAPI parameter names in path parts with model parameter names.
|
|
288
289
|
// Path parts may have e.g. {subBreed} while model params use sub_breed.
|
|
289
|
-
|
|
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 {
|
|
290
298
|
return parts.map((part: string) => {
|
|
291
|
-
|
|
292
|
-
|
|
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) => {
|
|
293
303
|
const snaked = snakify(rawName)
|
|
294
|
-
const
|
|
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
|
+
)
|
|
295
309
|
if (param) return '{' + param.name + '}'
|
|
296
|
-
|
|
297
|
-
|
|
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
|
+
})
|
|
298
330
|
}).join('/')
|
|
299
331
|
}
|
|
300
332
|
|
|
@@ -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,17 +378,21 @@ 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))
|
|
360
|
-
|
|
361
|
-
// Check if srcdatavar was declared by a prior create step
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
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
|
+
})
|
|
370
396
|
|
|
371
397
|
Content(`
|
|
372
398
|
// LOAD
|
|
@@ -401,7 +427,7 @@ const generateRemove: OpGen = (
|
|
|
401
427
|
|
|
402
428
|
const priorSteps = Object.values(flow.step).slice(0, Number(index))
|
|
403
429
|
const needsEnt = !priorSteps.some((s: any) =>
|
|
404
|
-
['create', 'list', 'load', 'remove'].includes(s.op))
|
|
430
|
+
['create', 'list', 'load', 'update', 'remove'].includes(s.op))
|
|
405
431
|
|
|
406
432
|
Content(`
|
|
407
433
|
// REMOVE
|