@voxgig/sdkgen 0.43.0 → 0.45.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.
Files changed (127) hide show
  1. package/bin/voxgig-sdkgen +1 -1
  2. package/dist/cmp/ReadmeEntity.js +9 -153
  3. package/dist/cmp/ReadmeEntity.js.map +1 -1
  4. package/dist/cmp/ReadmeIntro.js +9 -14
  5. package/dist/cmp/ReadmeIntro.js.map +1 -1
  6. package/dist/cmp/ReadmeModel.js +6 -4
  7. package/dist/cmp/ReadmeModel.js.map +1 -1
  8. package/dist/cmp/ReadmeOptions.js +9 -61
  9. package/dist/cmp/ReadmeOptions.js.map +1 -1
  10. package/dist/cmp/ReadmeRef.js +10 -1328
  11. package/dist/cmp/ReadmeRef.js.map +1 -1
  12. package/dist/sdkgen.d.ts +2 -2
  13. package/dist/sdkgen.js +2 -1
  14. package/dist/sdkgen.js.map +1 -1
  15. package/dist/utility.d.ts +2 -1
  16. package/dist/utility.js +9 -0
  17. package/dist/utility.js.map +1 -1
  18. package/package.json +1 -1
  19. package/project/.sdk/src/cmp/go/Config_go.ts +9 -4
  20. package/project/.sdk/src/cmp/go/Gitignore_go.ts +47 -0
  21. package/project/.sdk/src/cmp/go/Main_go.ts +3 -0
  22. package/project/.sdk/src/cmp/go/ReadmeEntity_go.ts +138 -0
  23. package/project/.sdk/src/cmp/go/ReadmeHowto_go.ts +6 -3
  24. package/project/.sdk/src/cmp/go/ReadmeIntro_go.ts +18 -0
  25. package/project/.sdk/src/cmp/go/ReadmeModel_go.ts +6 -3
  26. package/project/.sdk/src/cmp/go/ReadmeOptions_go.ts +58 -0
  27. package/project/.sdk/src/cmp/go/ReadmeQuick_go.ts +11 -7
  28. package/project/.sdk/src/cmp/go/ReadmeRef_go.ts +354 -0
  29. package/project/.sdk/src/cmp/go/ReadmeTopQuick_go.ts +6 -4
  30. package/project/.sdk/src/cmp/go/TestDirect_go.ts +18 -8
  31. package/project/.sdk/src/cmp/go/TestEntity_go.ts +105 -54
  32. package/project/.sdk/src/cmp/js/Config_js.ts +18 -0
  33. package/project/.sdk/src/cmp/js/Gitignore_js.ts +35 -0
  34. package/project/.sdk/src/cmp/js/Main_js.ts +3 -0
  35. package/project/.sdk/src/cmp/js/ReadmeEntity_js.ts +138 -0
  36. package/project/.sdk/src/cmp/js/ReadmeHowto_js.ts +11 -6
  37. package/project/.sdk/src/cmp/js/ReadmeIntro_js.ts +18 -0
  38. package/project/.sdk/src/cmp/js/ReadmeModel_js.ts +6 -3
  39. package/project/.sdk/src/cmp/js/ReadmeOptions_js.ts +58 -0
  40. package/project/.sdk/src/cmp/js/ReadmeQuick_js.ts +6 -4
  41. package/project/.sdk/src/cmp/js/ReadmeRef_js.ts +384 -0
  42. package/project/.sdk/src/cmp/js/ReadmeTopQuick_js.ts +6 -4
  43. package/project/.sdk/src/cmp/js/TestDirect_js.ts +23 -12
  44. package/project/.sdk/src/cmp/js/TestEntity_js.ts +107 -74
  45. package/project/.sdk/src/cmp/js/fragment/Config.fragment.js +1 -5
  46. package/project/.sdk/src/cmp/lua/Config_lua.ts +9 -4
  47. package/project/.sdk/src/cmp/lua/Gitignore_lua.ts +39 -0
  48. package/project/.sdk/src/cmp/lua/Main_lua.ts +3 -0
  49. package/project/.sdk/src/cmp/lua/ReadmeEntity_lua.ts +138 -0
  50. package/project/.sdk/src/cmp/lua/ReadmeHowto_lua.ts +6 -3
  51. package/project/.sdk/src/cmp/lua/ReadmeIntro_lua.ts +18 -0
  52. package/project/.sdk/src/cmp/lua/ReadmeModel_lua.ts +6 -3
  53. package/project/.sdk/src/cmp/lua/ReadmeOptions_lua.ts +58 -0
  54. package/project/.sdk/src/cmp/lua/ReadmeQuick_lua.ts +6 -4
  55. package/project/.sdk/src/cmp/lua/ReadmeRef_lua.ts +360 -0
  56. package/project/.sdk/src/cmp/lua/ReadmeTopQuick_lua.ts +6 -4
  57. package/project/.sdk/src/cmp/lua/TestDirect_lua.ts +18 -8
  58. package/project/.sdk/src/cmp/lua/TestEntity_lua.ts +95 -51
  59. package/project/.sdk/src/cmp/php/Config_php.ts +10 -8
  60. package/project/.sdk/src/cmp/php/Gitignore_php.ts +33 -0
  61. package/project/.sdk/src/cmp/php/Main_php.ts +3 -0
  62. package/project/.sdk/src/cmp/php/ReadmeEntity_php.ts +138 -0
  63. package/project/.sdk/src/cmp/php/ReadmeHowto_php.ts +6 -3
  64. package/project/.sdk/src/cmp/php/ReadmeIntro_php.ts +18 -0
  65. package/project/.sdk/src/cmp/php/ReadmeModel_php.ts +6 -3
  66. package/project/.sdk/src/cmp/php/ReadmeOptions_php.ts +58 -0
  67. package/project/.sdk/src/cmp/php/ReadmeQuick_php.ts +6 -4
  68. package/project/.sdk/src/cmp/php/ReadmeRef_php.ts +358 -0
  69. package/project/.sdk/src/cmp/php/ReadmeTopQuick_php.ts +6 -4
  70. package/project/.sdk/src/cmp/php/TestDirect_php.ts +18 -8
  71. package/project/.sdk/src/cmp/php/TestEntity_php.ts +101 -54
  72. package/project/.sdk/src/cmp/py/Config_py.ts +9 -4
  73. package/project/.sdk/src/cmp/py/Gitignore_py.ts +55 -0
  74. package/project/.sdk/src/cmp/py/Main_py.ts +3 -0
  75. package/project/.sdk/src/cmp/py/ReadmeEntity_py.ts +138 -0
  76. package/project/.sdk/src/cmp/py/ReadmeHowto_py.ts +6 -3
  77. package/project/.sdk/src/cmp/py/ReadmeIntro_py.ts +18 -0
  78. package/project/.sdk/src/cmp/py/ReadmeModel_py.ts +6 -3
  79. package/project/.sdk/src/cmp/py/ReadmeOptions_py.ts +58 -0
  80. package/project/.sdk/src/cmp/py/ReadmeQuick_py.ts +9 -6
  81. package/project/.sdk/src/cmp/py/ReadmeRef_py.ts +356 -0
  82. package/project/.sdk/src/cmp/py/ReadmeTopQuick_py.ts +9 -6
  83. package/project/.sdk/src/cmp/py/TestDirect_py.ts +18 -8
  84. package/project/.sdk/src/cmp/py/TestEntity_py.ts +100 -50
  85. package/project/.sdk/src/cmp/rb/Config_rb.ts +9 -4
  86. package/project/.sdk/src/cmp/rb/Gitignore_rb.ts +38 -0
  87. package/project/.sdk/src/cmp/rb/Main_rb.ts +3 -0
  88. package/project/.sdk/src/cmp/rb/ReadmeEntity_rb.ts +138 -0
  89. package/project/.sdk/src/cmp/rb/ReadmeHowto_rb.ts +6 -3
  90. package/project/.sdk/src/cmp/rb/ReadmeIntro_rb.ts +18 -0
  91. package/project/.sdk/src/cmp/rb/ReadmeModel_rb.ts +6 -3
  92. package/project/.sdk/src/cmp/rb/ReadmeOptions_rb.ts +58 -0
  93. package/project/.sdk/src/cmp/rb/ReadmeQuick_rb.ts +6 -4
  94. package/project/.sdk/src/cmp/rb/ReadmeRef_rb.ts +361 -0
  95. package/project/.sdk/src/cmp/rb/ReadmeTopQuick_rb.ts +6 -4
  96. package/project/.sdk/src/cmp/rb/TestDirect_rb.ts +18 -8
  97. package/project/.sdk/src/cmp/rb/TestEntity_rb.ts +95 -51
  98. package/project/.sdk/src/cmp/ts/Config_ts.ts +18 -0
  99. package/project/.sdk/src/cmp/ts/Gitignore_ts.ts +37 -0
  100. package/project/.sdk/src/cmp/ts/Main_ts.ts +3 -0
  101. package/project/.sdk/src/cmp/ts/ReadmeEntity_ts.ts +138 -0
  102. package/project/.sdk/src/cmp/ts/ReadmeHowto_ts.ts +11 -6
  103. package/project/.sdk/src/cmp/ts/ReadmeIntro_ts.ts +18 -0
  104. package/project/.sdk/src/cmp/ts/ReadmeModel_ts.ts +9 -5
  105. package/project/.sdk/src/cmp/ts/ReadmeOptions_ts.ts +58 -0
  106. package/project/.sdk/src/cmp/ts/ReadmeQuick_ts.ts +6 -4
  107. package/project/.sdk/src/cmp/ts/ReadmeRef_ts.ts +384 -0
  108. package/project/.sdk/src/cmp/ts/ReadmeTopQuick_ts.ts +6 -4
  109. package/project/.sdk/src/cmp/ts/TestDirect_ts.ts +68 -20
  110. package/project/.sdk/src/cmp/ts/TestEntity_ts.ts +109 -74
  111. package/project/.sdk/src/cmp/ts/fragment/Config.fragment.ts +1 -5
  112. package/project/.sdk/tm/go/utility/prepare_auth.go +15 -1
  113. package/project/.sdk/tm/js/src/utility/PrepareAuthUtility.js +7 -1
  114. package/project/.sdk/tm/lua/utility/prepare_auth.lua +9 -1
  115. package/project/.sdk/tm/php/utility/PrepareAuth.php +11 -1
  116. package/project/.sdk/tm/py/utility/prepare_auth.py +10 -1
  117. package/project/.sdk/tm/rb/utility/prepare_auth.rb +8 -1
  118. package/project/.sdk/tm/ts/src/utility/MakeUrlUtility.ts +7 -8
  119. package/project/.sdk/tm/ts/src/utility/PrepareAuthUtility.ts +7 -1
  120. package/src/cmp/ReadmeEntity.ts +11 -178
  121. package/src/cmp/ReadmeIntro.ts +11 -25
  122. package/src/cmp/ReadmeModel.ts +7 -5
  123. package/src/cmp/ReadmeOptions.ts +12 -74
  124. package/src/cmp/ReadmeRef.ts +11 -1372
  125. package/src/sdkgen.ts +2 -1
  126. package/src/utility.ts +12 -0
  127. /package/project/.sdk/tm/go/utility/{make_target.go → make_point.go} +0 -0
@@ -7,7 +7,12 @@ import {
7
7
 
8
8
  import {
9
9
  KIT,
10
+ Model,
11
+ ModelEntity,
12
+ ModelEntityFlow,
13
+ ModelEntityFlowStep,
10
14
  getModelPath,
15
+ nom,
11
16
  } from '@voxgig/apidef'
12
17
 
13
18
 
@@ -18,34 +23,47 @@ import {
18
23
  each,
19
24
  buildIdNames,
20
25
  getMatchEntries,
26
+ isAuthActive,
21
27
  } from '@voxgig/sdkgen'
22
28
 
23
29
 
24
- type OpGen = (ctx: GenCtx, step: any, index: any) => void
25
-
30
+ // See TestEntity_ts.ts for the GenCtx/OpGen contract.
26
31
  type GenCtx = {
27
- model: any
28
- entity: any
29
- flow: any
32
+ model: Model
33
+ entity: ModelEntity
34
+ flow: ModelEntityFlow
30
35
  PROJUPPER: string
31
36
  }
32
37
 
38
+ type OpGen = (ctx: GenCtx, step: ModelEntityFlowStep, index: number) => void
39
+
33
40
 
34
41
  const TestEntity = cmp(function TestEntity(props: any) {
35
42
  const ctx$ = props.ctx$
36
- const model = ctx$.model
43
+ const model: Model = ctx$.model
37
44
 
38
45
  const target = props.target
39
- const entity = props.entity
46
+ const entity: ModelEntity = props.entity
40
47
 
41
- const basicflow = getModelPath(model, `main.${KIT}.flow.Basic${entity.Name}Flow`)
42
- const dobasic = basicflow && true === basicflow.active
48
+ const basicflow: ModelEntityFlow | undefined =
49
+ getModelPath(model, `main.${KIT}.flow.Basic${nom(entity, 'Name')}Flow`)
43
50
 
44
- if (!dobasic) {
51
+ // No flow or flow inactive — nothing to generate. The narrowed-form
52
+ // check (rather than `if (!dobasic)`) is what lets TS know `basicflow`
53
+ // is non-null in the rest of the cmp body.
54
+ if (null == basicflow || true !== basicflow.active) {
45
55
  return
46
56
  }
47
57
 
48
- const PROJUPPER = model.const.Name.toUpperCase().replace(/[^A-Z_]/g, '_')
58
+ const PROJUPPER = nom(model.const, 'Name').toUpperCase().replace(/[^A-Z_]/g, '_')
59
+
60
+ const authActive = isAuthActive(model)
61
+ const apikeyEnvEntry = authActive
62
+ ? `\n "${PROJUPPER}_APIKEY": "NONE",`
63
+ : ''
64
+ const apikeyLiveField = authActive
65
+ ? `\n "apikey": env.get("${PROJUPPER}_APIKEY"),`
66
+ : ''
49
67
 
50
68
  const idnames = buildIdNames(entity, basicflow)
51
69
  const idnamesStr = idnames.map(n => `"${n}"`).join(', ')
@@ -147,8 +165,7 @@ def _${entity.name}_basic_setup(extra):
147
165
  Content(` env = runner.env_override({
148
166
  "${PROJUPPER}_TEST_${entity.name.toUpperCase().replace(/[^A-Z_]/g, '_')}_ENTID": idmap,
149
167
  "${PROJUPPER}_TEST_LIVE": "FALSE",
150
- "${PROJUPPER}_TEST_EXPLAIN": "FALSE",
151
- "${PROJUPPER}_APIKEY": "NONE",
168
+ "${PROJUPPER}_TEST_EXPLAIN": "FALSE",${apikeyEnvEntry}
152
169
  })
153
170
 
154
171
  idmap_resolved = helpers.to_map(
@@ -167,8 +184,7 @@ def _${entity.name}_basic_setup(extra):
167
184
  Content(`
168
185
  if env.get("${PROJUPPER}_TEST_LIVE") == "TRUE":
169
186
  merged_opts = vs.merge([
170
- {
171
- "apikey": env.get("${PROJUPPER}_APIKEY"),
187
+ {${apikeyLiveField}
172
188
  },
173
189
  extra or {},
174
190
  ])
@@ -189,9 +205,9 @@ def _${entity.name}_basic_setup(extra):
189
205
 
190
206
  const generateCreate: OpGen = (ctx, step, index) => {
191
207
  const { entity, flow } = ctx
192
- const ref = step.input?.ref ?? entity.name + '_ref01'
193
- const entvar = step.input?.entvar ?? ref + '_ent'
194
- const datavar = step.input?.datavar ?? (ref + '_data' + (step.input?.suffix ?? ''))
208
+ const ref = step.input.ref ?? entity.name + '_ref01'
209
+ const entvar = step.input.entvar ?? ref + '_ent'
210
+ const datavar = step.input.datavar ?? (ref + '_data' + (step.input.suffix ?? ''))
195
211
 
196
212
  const priorSteps = Object.values(flow.step).slice(0, Number(index)) as any[]
197
213
  const needsEnt = !priorSteps.some((s: any) =>
@@ -199,8 +215,8 @@ const generateCreate: OpGen = (ctx, step, index) => {
199
215
 
200
216
  const hasDatvar = priorSteps.some((s: any) => {
201
217
  if ('create' === s.op) {
202
- const priorRef = s.input?.ref ?? entity.name + '_ref01'
203
- const priorDatvar = s.input?.datavar ?? (priorRef + '_data' + (s.input?.suffix ?? ''))
218
+ const priorRef = s.input.ref ?? entity.name + '_ref01'
219
+ const priorDatvar = s.input.datavar ?? (priorRef + '_data' + (s.input.suffix ?? ''))
204
220
  return priorDatvar === datavar
205
221
  }
206
222
  return false
@@ -229,22 +245,27 @@ const generateCreate: OpGen = (ctx, step, index) => {
229
245
  `)
230
246
  }
231
247
 
248
+ const hasEntIdC = null != ctx.entity.id
249
+
232
250
  Content(`
233
251
  ${datavar}_result, err = ${entvar}.create(${datavar}, None)
234
252
  assert err is None
235
253
  ${datavar} = helpers.to_map(${datavar}_result)
236
254
  assert ${datavar} is not None
237
- assert ${datavar}["id"] is not None
238
255
  `)
256
+ if (hasEntIdC) {
257
+ Content(` assert ${datavar}["id"] is not None
258
+ `)
259
+ }
239
260
  }
240
261
 
241
262
 
242
263
  const generateList: OpGen = (ctx, step, index) => {
243
264
  const { entity, flow } = ctx
244
- const ref = step.input?.ref ?? entity.name + '_ref01'
245
- const entvar = step.input?.entvar ?? ref + '_ent'
246
- const matchvar = step.input?.matchvar ?? (ref + '_match' + (step.input?.suffix ?? ''))
247
- const listvar = step.input?.listvar ?? (ref + '_list' + (step.input?.suffix ?? ''))
265
+ const ref = step.input.ref ?? entity.name + '_ref01'
266
+ const entvar = step.input.entvar ?? ref + '_ent'
267
+ const matchvar = step.input.matchvar ?? (ref + '_match' + (step.input.suffix ?? ''))
268
+ const listvar = step.input.listvar ?? (ref + '_list' + (step.input.suffix ?? ''))
248
269
 
249
270
  const priorSteps = Object.values(flow.step).slice(0, Number(index)) as any[]
250
271
  const needsEnt = !priorSteps.some((s: any) =>
@@ -284,7 +305,7 @@ const generateList: OpGen = (ctx, step, index) => {
284
305
  for (const validator of step.valid) {
285
306
  const validRef = validator.def?.ref
286
307
  const hasRefData = validRef && allSteps.some((s: any) => 'create' === s.op &&
287
- ((s.input?.ref ?? entity.name + '_ref01') === validRef))
308
+ ((s.input.ref ?? entity.name + '_ref01') === validRef))
288
309
 
289
310
  if ('ItemExists' === validator.apply && hasRefData) {
290
311
  const refDataVar = validRef + '_data'
@@ -310,17 +331,19 @@ const generateList: OpGen = (ctx, step, index) => {
310
331
 
311
332
  const generateUpdate: OpGen = (ctx, step, index) => {
312
333
  const { entity, flow } = ctx
313
- const ref = step.input?.ref ?? entity.name + '_ref01'
314
- const entvar = step.input?.entvar ?? ref + '_ent'
315
- const datavar = step.input?.datavar ?? (ref + '_data' + (step.input?.suffix ?? ''))
316
- const resdatavar = step.input?.resdatavar ?? (ref + '_resdata' + (step.input?.suffix ?? ''))
317
- const markdefvar = step.input?.markdefvar ?? (ref + '_markdef' + (step.input?.suffix ?? ''))
318
- const srcdatavar = step.input?.srcdatavar ?? (ref + '_data' + (step.input?.suffix ?? ''))
334
+ const ref = step.input.ref ?? entity.name + '_ref01'
335
+ const entvar = step.input.entvar ?? ref + '_ent'
336
+ const datavar = step.input.datavar ?? (ref + '_data' + (step.input.suffix ?? ''))
337
+ const resdatavar = step.input.resdatavar ?? (ref + '_resdata' + (step.input.suffix ?? ''))
338
+ const markdefvar = step.input.markdefvar ?? (ref + '_markdef' + (step.input.suffix ?? ''))
339
+ const srcdatavar = step.input.srcdatavar ?? (ref + '_data' + (step.input.suffix ?? ''))
319
340
 
320
341
  const priorSteps = Object.values(flow.step).slice(0, Number(index)) as any[]
321
342
  const needsEnt = !priorSteps.some((s: any) =>
322
343
  ['create', 'list', 'load', 'update', 'remove'].includes(s.op))
323
344
 
345
+ const hasEntIdU = null != entity.id
346
+
324
347
  Content(` # UPDATE
325
348
  `)
326
349
  if (needsEnt) {
@@ -328,8 +351,11 @@ const generateUpdate: OpGen = (ctx, step, index) => {
328
351
  `)
329
352
  }
330
353
  Content(` ${datavar}_up = {
331
- "id": ${srcdatavar}["id"],
332
354
  `)
355
+ if (hasEntIdU) {
356
+ Content(` "id": ${srcdatavar}["id"],
357
+ `)
358
+ }
333
359
 
334
360
  if (step.data) {
335
361
  const dataEntries = Object.entries(step.data).filter(([k]: any) => k !== 'id' && !k.endsWith('$'))
@@ -344,7 +370,7 @@ const generateUpdate: OpGen = (ctx, step, index) => {
344
370
 
345
371
  if (step.spec) {
346
372
  for (const spec of step.spec) {
347
- if ('TextFieldMark' === spec.apply && null != step.input?.textfield) {
373
+ if ('TextFieldMark' === spec.apply && null != step.input.textfield) {
348
374
  const fieldname = step.input.textfield
349
375
  const fieldvalue = spec.def?.mark ?? `Mark01-${ref}`
350
376
  Content(`
@@ -361,12 +387,15 @@ const generateUpdate: OpGen = (ctx, step, index) => {
361
387
  assert err is None
362
388
  ${resdatavar} = helpers.to_map(${resdatavar}_result)
363
389
  assert ${resdatavar} is not None
364
- assert ${resdatavar}["id"] == ${datavar}_up["id"]
365
390
  `)
391
+ if (hasEntIdU) {
392
+ Content(` assert ${resdatavar}["id"] == ${datavar}_up["id"]
393
+ `)
394
+ }
366
395
 
367
396
  if (step.spec) {
368
397
  for (const spec of step.spec) {
369
- if ('TextFieldMark' === spec.apply && null != step.input?.textfield) {
398
+ if ('TextFieldMark' === spec.apply && null != step.input.textfield) {
370
399
  Content(` assert ${resdatavar}[${markdefvar}_name] == ${markdefvar}_value
371
400
  `)
372
401
  }
@@ -377,11 +406,11 @@ const generateUpdate: OpGen = (ctx, step, index) => {
377
406
 
378
407
  const generateLoad: OpGen = (ctx, step, index) => {
379
408
  const { entity, flow } = ctx
380
- const ref = step.input?.ref ?? entity.name + '_ref01'
381
- const entvar = step.input?.entvar ?? ref + '_ent'
382
- const matchvar = step.input?.matchvar ?? (ref + '_match' + (step.input?.suffix ?? ''))
383
- const datavar = step.input?.datavar ?? (ref + '_data' + (step.input?.suffix ?? ''))
384
- const srcdatavar = step.input?.srcdatavar ?? (ref + '_data' + (step.input?.suffix ?? ''))
409
+ const ref = step.input.ref ?? entity.name + '_ref01'
410
+ const entvar = step.input.entvar ?? ref + '_ent'
411
+ const matchvar = step.input.matchvar ?? (ref + '_match' + (step.input.suffix ?? ''))
412
+ const datavar = step.input.datavar ?? (ref + '_data' + (step.input.suffix ?? ''))
413
+ const srcdatavar = step.input.srcdatavar ?? (ref + '_data' + (step.input.suffix ?? ''))
385
414
 
386
415
  const priorSteps = Object.values(flow.step).slice(0, Number(index)) as any[]
387
416
  const hasEntVar = priorSteps.some((s: any) =>
@@ -392,20 +421,22 @@ const generateLoad: OpGen = (ctx, step, index) => {
392
421
  const hasSrcData = (!flowHasCreate && srcdatavar === (preambleRef + '_data')) ||
393
422
  priorSteps.some((s: any) => {
394
423
  if ('create' === s.op) {
395
- const priorRef = s.input?.ref ?? entity.name + '_ref01'
396
- const priorDatvar = s.input?.datavar ?? (priorRef + '_data' + (s.input?.suffix ?? ''))
424
+ const priorRef = s.input.ref ?? entity.name + '_ref01'
425
+ const priorDatvar = s.input.datavar ?? (priorRef + '_data' + (s.input.suffix ?? ''))
397
426
  return priorDatvar === srcdatavar
398
427
  }
399
428
  return false
400
429
  })
401
430
 
431
+ const hasEntId = null != entity.id
432
+
402
433
  Content(` # LOAD
403
434
  `)
404
435
  if (!hasEntVar) {
405
436
  Content(` ${entvar} = client.${entity.Name}(None)
406
437
  `)
407
438
  }
408
- if (!hasSrcData) {
439
+ if (!hasSrcData && hasEntId) {
409
440
  Content(` ${srcdatavar}_raw = vs.items(helpers.to_map(
410
441
  vs.getpath(setup["data"], "existing.${entity.name}")))
411
442
  ${srcdatavar} = None
@@ -413,7 +444,8 @@ const generateLoad: OpGen = (ctx, step, index) => {
413
444
  ${srcdatavar} = helpers.to_map(${srcdatavar}_raw[0][1])
414
445
  `)
415
446
  }
416
- Content(` ${matchvar} = {
447
+ if (hasEntId) {
448
+ Content(` ${matchvar} = {
417
449
  "id": ${srcdatavar}["id"],
418
450
  }
419
451
  ${datavar}_loaded, err = ${entvar}.load(${matchvar}, None)
@@ -422,32 +454,50 @@ const generateLoad: OpGen = (ctx, step, index) => {
422
454
  assert ${datavar}_load_result is not None
423
455
  assert ${datavar}_load_result["id"] == ${srcdatavar}["id"]
424
456
  `)
457
+ }
458
+ else {
459
+ Content(` ${matchvar} = {}
460
+ ${datavar}_loaded, err = ${entvar}.load(${matchvar}, None)
461
+ assert err is None
462
+ assert ${datavar}_loaded is not None
463
+ `)
464
+ }
425
465
  }
426
466
 
427
467
 
428
468
  const generateRemove: OpGen = (ctx, step, index) => {
429
469
  const { entity, flow } = ctx
430
- const ref = step.input?.ref ?? entity.name + '_ref01'
431
- const entvar = step.input?.entvar ?? ref + '_ent'
432
- const matchvar = step.input?.matchvar ?? (ref + '_match' + (step.input?.suffix ?? ''))
433
- const srcdatavar = step.input?.srcdatavar ?? (ref + '_data')
470
+ const ref = step.input.ref ?? entity.name + '_ref01'
471
+ const entvar = step.input.entvar ?? ref + '_ent'
472
+ const matchvar = step.input.matchvar ?? (ref + '_match' + (step.input.suffix ?? ''))
473
+ const srcdatavar = step.input.srcdatavar ?? (ref + '_data')
434
474
 
435
475
  const priorSteps = Object.values(flow.step).slice(0, Number(index)) as any[]
436
476
  const needsEnt = !priorSteps.some((s: any) =>
437
477
  ['create', 'list', 'load', 'update', 'remove'].includes(s.op))
438
478
 
479
+ const hasEntIdR = null != entity.id
480
+
439
481
  Content(` # REMOVE
440
482
  `)
441
483
  if (needsEnt) {
442
484
  Content(` ${entvar} = client.${entity.Name}(None)
443
485
  `)
444
486
  }
445
- Content(` ${matchvar} = {
487
+ if (hasEntIdR) {
488
+ Content(` ${matchvar} = {
446
489
  "id": ${srcdatavar}["id"],
447
490
  }
448
491
  _, err = ${entvar}.remove(${matchvar}, None)
449
492
  assert err is None
450
493
  `)
494
+ }
495
+ else {
496
+ Content(` ${matchvar} = {}
497
+ _, err = ${entvar}.remove(${matchvar}, None)
498
+ assert err is None
499
+ `)
500
+ }
451
501
  }
452
502
 
453
503
 
@@ -9,6 +9,7 @@ import {
9
9
  Line,
10
10
  cmp,
11
11
  each,
12
+ isAuthActive,
12
13
  } from '@voxgig/sdkgen'
13
14
 
14
15
 
@@ -37,12 +38,19 @@ const Config = cmp(async function Config(props: any) {
37
38
 
38
39
  const headers = getModelPath(model, `main.${KIT}.config.headers`) || {}
39
40
 
41
+ const authActive = isAuthActive(model)
40
42
  let authPrefix = ''
41
43
  try { authPrefix = getModelPath(model, `main.${KIT}.config.auth.prefix`) } catch (_e) { }
42
44
 
43
45
  let baseUrl = ''
44
46
  try { baseUrl = getModelPath(model, `main.${KIT}.info.servers.0.url`) } catch (_e) { }
45
47
 
48
+ const authBlock = authActive
49
+ ? ` "auth" => {
50
+ "prefix" => "${authPrefix}",
51
+ },\n`
52
+ : ''
53
+
46
54
  File({ name: 'config.' + target.ext }, () => {
47
55
 
48
56
  Content(`# ${model.const.Name} SDK configuration
@@ -65,10 +73,7 @@ module ${model.const.Name}Config
65
73
  Content(` },
66
74
  "options" => {
67
75
  "base" => "${baseUrl}",
68
- "auth" => {
69
- "prefix" => "${authPrefix}",
70
- },
71
- "headers" => ${formatRubyHash(headers, 4)},
76
+ ${authBlock} "headers" => ${formatRubyHash(headers, 4)},
72
77
  "entity" => {
73
78
  `)
74
79
 
@@ -0,0 +1,38 @@
1
+
2
+ import {
3
+ Content,
4
+ File,
5
+ cmp,
6
+ } from '@voxgig/sdkgen'
7
+
8
+
9
+ const Gitignore = cmp(async function Gitignore(_props: any) {
10
+ File({ name: '.gitignore' }, () => {
11
+ Content(`# Bundler / gem build artifacts
12
+ *.gem
13
+ .bundle/
14
+ vendor/bundle/
15
+ pkg/
16
+
17
+ # Test / coverage
18
+ coverage/
19
+ .rspec_status
20
+
21
+ # Documentation
22
+ .yardoc/
23
+ _yardoc/
24
+ doc/
25
+ rdoc/
26
+
27
+ # IDE / OS
28
+ .idea/
29
+ .vscode/
30
+ .DS_Store
31
+ `)
32
+ })
33
+ })
34
+
35
+
36
+ export {
37
+ Gitignore
38
+ }
@@ -20,6 +20,7 @@ import {
20
20
 
21
21
  import { Package } from './Package_rb'
22
22
  import { Config } from './Config_rb'
23
+ import { Gitignore } from './Gitignore_rb'
23
24
  import { MainEntity } from './MainEntity_rb'
24
25
 
25
26
 
@@ -33,6 +34,8 @@ const Main = cmp(async function Main(props: any) {
33
34
 
34
35
  Package({ target })
35
36
 
37
+ Gitignore({})
38
+
36
39
  // Copy tm/rb files with replacements
37
40
  Copy({
38
41
  from: 'tm/' + target.name,
@@ -0,0 +1,138 @@
1
+
2
+ import { cmp, each, Content } from '@voxgig/sdkgen'
3
+
4
+ import {
5
+ KIT,
6
+ getModelPath,
7
+ } from '@voxgig/apidef'
8
+
9
+
10
+ // Operation method spelling differs between Go and other languages — Go
11
+ // uses PascalCase methods with explicit ctrl arg, others use lowercase
12
+ // methods with optional ctrl. The op descriptions are language-agnostic.
13
+ const OP_DESC: Record<string, { method: string, desc: string }> = {
14
+ load: { method: 'load(match)', desc: 'Load a single entity by match criteria.' },
15
+ list: { method: 'list(match)', desc: 'List entities matching the criteria.' },
16
+ create: { method: 'create(data)', desc: 'Create a new entity with the given data.' },
17
+ update: { method: 'update(data)', desc: 'Update an existing entity.' },
18
+ remove: { method: 'remove(match)', desc: 'Remove the matching entity.' },
19
+ }
20
+
21
+
22
+ const ReadmeEntity = cmp(function ReadmeEntity(props: any) {
23
+ const { target } = props
24
+ const { model } = props.ctx$
25
+
26
+ const entity = getModelPath(model, `main.${KIT}.entity`)
27
+
28
+ const publishedEntities = each(entity)
29
+ .filter((entity: any) => entity.active !== false)
30
+
31
+ if (0 === publishedEntities.length) {
32
+ return
33
+ }
34
+
35
+ Content(`
36
+
37
+ ## Entities
38
+
39
+ `)
40
+
41
+ publishedEntities.map((entity: any) => {
42
+ const opnames = Object.keys(entity.op || {})
43
+ const fields = entity.fields || []
44
+
45
+ Content(`
46
+ ### ${entity.Name}
47
+
48
+ `)
49
+
50
+ if (entity.short) {
51
+ Content(`${entity.short}
52
+
53
+ `)
54
+ }
55
+
56
+ Content(`Create an instance: \`const ${entity.name} = client.${entity.Name}()\`
57
+
58
+ `)
59
+
60
+ if (opnames.length > 0) {
61
+ Content(`#### Operations
62
+
63
+ | Method | Description |
64
+ | --- | --- |
65
+ `)
66
+ opnames.map((opname: string) => {
67
+ const info = OP_DESC[opname]
68
+ if (info) {
69
+ Content(`| \`${info.method}\` | ${info.desc} |
70
+ `)
71
+ }
72
+ })
73
+
74
+ Content(`
75
+ `)
76
+ }
77
+
78
+ if (fields.length > 0) {
79
+ Content(`#### Fields
80
+
81
+ | Field | Type | Description |
82
+ | --- | --- | --- |
83
+ `)
84
+
85
+ each(fields, (field: any) => {
86
+ const desc = field.short || ''
87
+ Content(`| \`${field.name}\` | \`${field.type || 'any'}\` | ${desc} |
88
+ `)
89
+ })
90
+
91
+ Content(`
92
+ `)
93
+ }
94
+
95
+ if (opnames.includes('load')) {
96
+ Content(`#### Example: Load
97
+
98
+ \`\`\`ts
99
+ const ${entity.name} = await client.${entity.Name}().load({ id: '${entity.name}_id' })
100
+ \`\`\`
101
+
102
+ `)
103
+ }
104
+
105
+ if (opnames.includes('list')) {
106
+ Content(`#### Example: List
107
+
108
+ \`\`\`ts
109
+ const ${entity.name}s = await client.${entity.Name}().list()
110
+ \`\`\`
111
+
112
+ `)
113
+ }
114
+
115
+ if (opnames.includes('create')) {
116
+ Content(`#### Example: Create
117
+
118
+ \`\`\`ts
119
+ const ${entity.name} = await client.${entity.Name}().create({
120
+ `)
121
+ each(fields, (field: any) => {
122
+ if ('id' !== field.name && field.req) {
123
+ Content(` ${field.name}: /* ${field.type || 'value'} */,
124
+ `)
125
+ }
126
+ })
127
+ Content(`})
128
+ \`\`\`
129
+
130
+ `)
131
+ }
132
+ })
133
+ })
134
+
135
+
136
+ export {
137
+ ReadmeEntity
138
+ }
@@ -1,10 +1,14 @@
1
1
 
2
- import { cmp, Content } from '@voxgig/sdkgen'
2
+ import { cmp, Content, isAuthActive } from '@voxgig/sdkgen'
3
3
 
4
4
 
5
5
  const ReadmeHowto = cmp(function ReadmeHowto(props: any) {
6
6
  const { target, ctx$: { model } } = props
7
7
 
8
+ const apikeyEnvLine = isAuthActive(model)
9
+ ? `\n${model.NAME}_APIKEY=<your-key>`
10
+ : ''
11
+
8
12
  Content(`### Make a direct HTTP request
9
13
 
10
14
  For endpoints not covered by entity methods:
@@ -78,8 +82,7 @@ client = ${model.const.Name}SDK.new({
78
82
  Create a \`.env.local\` file at the project root:
79
83
 
80
84
  \`\`\`
81
- ${model.NAME}_TEST_LIVE=TRUE
82
- ${model.NAME}_APIKEY=<your-key>
85
+ ${model.NAME}_TEST_LIVE=TRUE${apikeyEnvLine}
83
86
  \`\`\`
84
87
 
85
88
  Then run:
@@ -0,0 +1,18 @@
1
+
2
+ import { cmp, Content } from '@voxgig/sdkgen'
3
+
4
+
5
+ const ReadmeIntro = cmp(function ReadmeIntro(props: any) {
6
+ const { target, ctx$: { model } } = props
7
+
8
+ Content(`# ${model.Name} ${target.title} SDK
9
+
10
+ The ${target.title} SDK for the ${model.Name} API. Provides an entity-oriented interface using idiomatic Ruby conventions.
11
+
12
+ `)
13
+ })
14
+
15
+
16
+ export {
17
+ ReadmeIntro
18
+ }
@@ -1,5 +1,5 @@
1
1
 
2
- import { cmp, each, Content } from '@voxgig/sdkgen'
2
+ import { cmp, each, Content, isAuthActive } from '@voxgig/sdkgen'
3
3
 
4
4
  import {
5
5
  KIT,
@@ -13,6 +13,10 @@ const ReadmeModel = cmp(function ReadmeModel(props: any) {
13
13
  const entity = getModelPath(model, `main.${KIT}.entity`)
14
14
  const entityList = each(entity).filter((e: any) => e.active !== false)
15
15
 
16
+ const apikeyOptionRow = isAuthActive(model)
17
+ ? '| `apikey` | `String` | API key for authentication. |\n'
18
+ : ''
19
+
16
20
  Content(`### ${model.const.Name}SDK
17
21
 
18
22
  \`\`\`ruby
@@ -24,8 +28,7 @@ Creates a new SDK client.
24
28
 
25
29
  | Option | Type | Description |
26
30
  | --- | --- | --- |
27
- | \`apikey\` | \`String\` | API key for authentication. |
28
- | \`base\` | \`String\` | Base URL of the API server. |
31
+ ${apikeyOptionRow}| \`base\` | \`String\` | Base URL of the API server. |
29
32
  | \`prefix\` | \`String\` | URL path prefix prepended to all requests. |
30
33
  | \`suffix\` | \`String\` | URL path suffix appended to all requests. |
31
34
  | \`feature\` | \`Hash\` | Feature activation flags. |
@@ -0,0 +1,58 @@
1
+
2
+ import { cmp, each, Content } from '@voxgig/sdkgen'
3
+
4
+
5
+ const ReadmeOptions = cmp(function ReadmeOptions(props: any) {
6
+ const { target } = props
7
+ const { model } = props.ctx$
8
+
9
+ const publishedOptions = each(target.options).filter((option: any) => option.publish)
10
+ if (0 === publishedOptions.length) {
11
+ return
12
+ }
13
+
14
+ Content(`
15
+
16
+ ## Options
17
+
18
+ Pass options when creating a client instance:
19
+
20
+ `)
21
+
22
+ Content(`\`\`\`ruby
23
+ client = ${model.Name}SDK.new({
24
+ `)
25
+
26
+ publishedOptions.map((option: any) => {
27
+ if ('apikey' === option.name) {
28
+ Content(` "${option.name}" => ENV["${model.NAME}_APIKEY"],
29
+ `)
30
+ }
31
+ else {
32
+ Content(` # "${option.name}" => ${option.kind === 'string' ? '"..."' : '...'},
33
+ `)
34
+ }
35
+ })
36
+
37
+ Content(`})
38
+ \`\`\`
39
+
40
+ `)
41
+
42
+ Content(`| Option | Type | Description |
43
+ | --- | --- | --- |
44
+ `)
45
+
46
+ publishedOptions.map((option: any) => {
47
+ Content(`| \`${option.name}\` | \`${option.kind}\` | ${option.short} |
48
+ `)
49
+ })
50
+
51
+ Content(`
52
+ `)
53
+ })
54
+
55
+
56
+ export {
57
+ ReadmeOptions
58
+ }