@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
@@ -8,7 +8,7 @@ const { Gubu, Fault, One } = require('gubu')
8
8
 
9
9
  const { SdkGen } = require('../dist/sdkgen.js')
10
10
 
11
- const VERSION = '0.34.11'
11
+ const VERSION = '0.35.0'
12
12
  const KONSOLE = console
13
13
 
14
14
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@voxgig/sdkgen",
3
- "version": "0.34.11",
3
+ "version": "0.35.0",
4
4
  "main": "dist/sdkgen.js",
5
5
  "type": "commonjs",
6
6
  "types": "dist/sdkgen.d.ts",
@@ -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
- function normalizePathParams(parts: string[], params: any[]): string {
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
- if (part.startsWith('{') && part.endsWith('}')) {
292
- const rawName = part.slice(1, -1)
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 param = params.find((p: any) => p.orig === snaked || p.name === snaked)
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
- return part
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
- const ${datavar}: any = {}
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
- const hasSrcData = priorSteps.some((s: any) => {
363
- if ('create' === s.op) {
364
- const priorRef = s.input?.ref ?? entity.name + '_ref01'
365
- const priorDatvar = s.input?.datavar ?? (priorRef + '_data' + (s.input?.suffix ?? ''))
366
- return priorDatvar === srcdatavar
367
- }
368
- return false
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