@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,6 +23,7 @@ import {
18
23
  each,
19
24
  buildIdNames,
20
25
  getMatchEntries,
26
+ isAuthActive,
21
27
  } from '@voxgig/sdkgen'
22
28
 
23
29
 
@@ -27,33 +33,42 @@ function goVar(name: string): string {
27
33
  }
28
34
 
29
35
 
30
- type OpGen = (ctx: GenCtx, step: any, index: any) => void
31
-
36
+ // Go's GenCtx mirrors the shared shape (see TestEntity_ts.ts) plus a
37
+ // `gomodule` slot used to build qualified package paths in emitted code.
32
38
  type GenCtx = {
33
- model: any
34
- entity: any
39
+ model: Model
40
+ entity: ModelEntity
35
41
  gomodule: string
36
- flow: any
42
+ flow: ModelEntityFlow
37
43
  PROJUPPER: string
38
44
  }
39
45
 
46
+ type OpGen = (ctx: GenCtx, step: ModelEntityFlowStep, index: number) => void
47
+
40
48
 
41
49
  const TestEntity = cmp(function TestEntity(props: any) {
42
50
  const ctx$ = props.ctx$
43
- const model = ctx$.model
51
+ const model: Model = ctx$.model
44
52
 
45
53
  const target = props.target
46
- const entity = props.entity
47
- const gomodule = props.gomodule
48
-
49
- const basicflow = getModelPath(model, `main.${KIT}.flow.Basic${entity.Name}Flow`)
50
- const dobasic = basicflow && true === basicflow.active
54
+ const entity: ModelEntity = props.entity
55
+ const gomodule: string = props.gomodule
51
56
 
52
- if (!dobasic) {
57
+ const basicflow: ModelEntityFlow | undefined =
58
+ getModelPath(model, `main.${KIT}.flow.Basic${nom(entity, 'Name')}Flow`)
59
+ if (null == basicflow || true !== basicflow.active) {
53
60
  return
54
61
  }
55
62
 
56
- const PROJUPPER = model.const.Name.toUpperCase().replace(/[^A-Z_]/g, '_')
63
+ const PROJUPPER = nom(model.const, 'Name').toUpperCase().replace(/[^A-Z_]/g, '_')
64
+
65
+ const authActive = isAuthActive(model)
66
+ const apikeyEnvEntry = authActive
67
+ ? `\n\t\t"${PROJUPPER}_APIKEY": "NONE",`
68
+ : ''
69
+ const apikeyLiveField = authActive
70
+ ? `\n\t\t\t\t"apikey": env["${PROJUPPER}_APIKEY"],`
71
+ : ''
57
72
 
58
73
  const idnames = buildIdNames(entity, basicflow)
59
74
  const idnamesStr = idnames.map(n => `"${n}"`).join(', ')
@@ -72,7 +87,7 @@ const TestEntity = cmp(function TestEntity(props: any) {
72
87
  // when no step needs it, otherwise Go's strict unused-import check fails.
73
88
  const needsFmt = allSteps.some((s: any) =>
74
89
  s.op === 'update' &&
75
- s.input?.textfield &&
90
+ s.input.textfield &&
76
91
  Array.isArray(s.spec) &&
77
92
  s.spec.some((sp: any) => sp.apply === 'TextFieldMark'))
78
93
 
@@ -181,8 +196,7 @@ ${allSteps.length > 0 ? '\t\tclient := setup.client\n\n' : ''}`)
181
196
  env := envOverride(map[string]any{
182
197
  "${PROJUPPER}_TEST_${entity.name.toUpperCase().replace(/[^A-Z_]/g, '_')}_ENTID": idmap,
183
198
  "${PROJUPPER}_TEST_LIVE": "FALSE",
184
- "${PROJUPPER}_TEST_EXPLAIN": "FALSE",
185
- "${PROJUPPER}_APIKEY": "NONE",
199
+ "${PROJUPPER}_TEST_EXPLAIN": "FALSE",${apikeyEnvEntry}
186
200
  })
187
201
 
188
202
  idmapResolved := core.ToMapAny(env["${PROJUPPER}_TEST_${entity.name.toUpperCase().replace(/[^A-Z_]/g, '_')}_ENTID"])
@@ -203,8 +217,7 @@ ${allSteps.length > 0 ? '\t\tclient := setup.client\n\n' : ''}`)
203
217
  Content(`
204
218
  if env["${PROJUPPER}_TEST_LIVE"] == "TRUE" {
205
219
  mergedOpts := vs.Merge([]any{
206
- map[string]any{
207
- "apikey": env["${PROJUPPER}_APIKEY"],
220
+ map[string]any{${apikeyLiveField}
208
221
  },
209
222
  extra,
210
223
  })
@@ -227,9 +240,9 @@ ${allSteps.length > 0 ? '\t\tclient := setup.client\n\n' : ''}`)
227
240
 
228
241
  const generateCreate: OpGen = (ctx, step, index) => {
229
242
  const { entity, flow } = ctx
230
- const ref = step.input?.ref ?? entity.name + '_ref01'
231
- const entvar = goVar(step.input?.entvar ?? ref + '_ent')
232
- const datavar = goVar(step.input?.datavar ?? (ref + '_data' + (step.input?.suffix ?? '')))
243
+ const ref = step.input.ref ?? entity.name + '_ref01'
244
+ const entvar = goVar(step.input.entvar ?? ref + '_ent')
245
+ const datavar = goVar(step.input.datavar ?? (ref + '_data' + (step.input.suffix ?? '')))
233
246
 
234
247
  const priorSteps = Object.values(flow.step).slice(0, Number(index)) as any[]
235
248
  const needsEnt = !priorSteps.some((s: any) =>
@@ -237,8 +250,8 @@ const generateCreate: OpGen = (ctx, step, index) => {
237
250
 
238
251
  const hasDatvar = priorSteps.some((s: any) => {
239
252
  if ('create' === s.op) {
240
- const priorRef = s.input?.ref ?? entity.name + '_ref01'
241
- const priorDatvar = goVar(s.input?.datavar ?? (priorRef + '_data' + (s.input?.suffix ?? '')))
253
+ const priorRef = s.input.ref ?? entity.name + '_ref01'
254
+ const priorDatvar = goVar(s.input.datavar ?? (priorRef + '_data' + (s.input.suffix ?? '')))
242
255
  return priorDatvar === datavar
243
256
  }
244
257
  return false
@@ -278,19 +291,22 @@ const generateCreate: OpGen = (ctx, step, index) => {
278
291
  if ${datavar} == nil {
279
292
  t.Fatal("expected create result to be a map")
280
293
  }
281
- if ${datavar}["id"] == nil {
294
+ `)
295
+ if (null != ctx.entity.id) {
296
+ Content(` if ${datavar}["id"] == nil {
282
297
  t.Fatal("expected created entity to have an id")
283
298
  }
284
299
  `)
300
+ }
285
301
  }
286
302
 
287
303
 
288
304
  const generateList: OpGen = (ctx, step, index) => {
289
305
  const { entity, flow } = ctx
290
- const ref = step.input?.ref ?? entity.name + '_ref01'
291
- const entvar = goVar(step.input?.entvar ?? ref + '_ent')
292
- const matchvar = goVar(step.input?.matchvar ?? (ref + '_match' + (step.input?.suffix ?? '')))
293
- const listvar = goVar(step.input?.listvar ?? (ref + '_list' + (step.input?.suffix ?? '')))
306
+ const ref = step.input.ref ?? entity.name + '_ref01'
307
+ const entvar = goVar(step.input.entvar ?? ref + '_ent')
308
+ const matchvar = goVar(step.input.matchvar ?? (ref + '_match' + (step.input.suffix ?? '')))
309
+ const listvar = goVar(step.input.listvar ?? (ref + '_list' + (step.input.suffix ?? '')))
294
310
 
295
311
  const priorSteps = Object.values(flow.step).slice(0, Number(index)) as any[]
296
312
  const needsEnt = !priorSteps.some((s: any) =>
@@ -326,7 +342,7 @@ const generateList: OpGen = (ctx, step, index) => {
326
342
  if ('ItemExists' !== v.apply && 'ItemNotExists' !== v.apply) return false
327
343
  const validRef = v.def?.ref
328
344
  return validRef && allSteps.some((s: any) => 'create' === s.op &&
329
- ((s.input?.ref ?? entity.name + '_ref01') === validRef))
345
+ ((s.input.ref ?? entity.name + '_ref01') === validRef))
330
346
  })
331
347
  const listvarBind = listvarUsed ? listvar : '_'
332
348
 
@@ -349,7 +365,7 @@ const generateList: OpGen = (ctx, step, index) => {
349
365
  for (const validator of step.valid) {
350
366
  const validRef = validator.def?.ref
351
367
  const hasRefData = validRef && allSteps.some((s: any) => 'create' === s.op &&
352
- ((s.input?.ref ?? entity.name + '_ref01') === validRef))
368
+ ((s.input.ref ?? entity.name + '_ref01') === validRef))
353
369
 
354
370
  if ('ItemExists' === validator.apply && hasRefData) {
355
371
  const refDataVar = goVar(validRef + '_data')
@@ -375,17 +391,19 @@ const generateList: OpGen = (ctx, step, index) => {
375
391
 
376
392
  const generateUpdate: OpGen = (ctx, step, index) => {
377
393
  const { entity, flow } = ctx
378
- const ref = step.input?.ref ?? entity.name + '_ref01'
379
- const entvar = goVar(step.input?.entvar ?? ref + '_ent')
380
- const datavar = goVar(step.input?.datavar ?? (ref + '_data' + (step.input?.suffix ?? '')))
381
- const resdatavar = goVar(step.input?.resdatavar ?? (ref + '_resdata' + (step.input?.suffix ?? '')))
382
- const markdefvar = goVar(step.input?.markdefvar ?? (ref + '_markdef' + (step.input?.suffix ?? '')))
383
- const srcdatavar = goVar(step.input?.srcdatavar ?? (ref + '_data' + (step.input?.suffix ?? '')))
394
+ const ref = step.input.ref ?? entity.name + '_ref01'
395
+ const entvar = goVar(step.input.entvar ?? ref + '_ent')
396
+ const datavar = goVar(step.input.datavar ?? (ref + '_data' + (step.input.suffix ?? '')))
397
+ const resdatavar = goVar(step.input.resdatavar ?? (ref + '_resdata' + (step.input.suffix ?? '')))
398
+ const markdefvar = goVar(step.input.markdefvar ?? (ref + '_markdef' + (step.input.suffix ?? '')))
399
+ const srcdatavar = goVar(step.input.srcdatavar ?? (ref + '_data' + (step.input.suffix ?? '')))
384
400
 
385
401
  const priorSteps = Object.values(flow.step).slice(0, Number(index)) as any[]
386
402
  const needsEnt = !priorSteps.some((s: any) =>
387
403
  ['create', 'list', 'load', 'update', 'remove'].includes(s.op))
388
404
 
405
+ const hasEntIdU = null != entity.id
406
+
389
407
  Content(` // UPDATE
390
408
  `)
391
409
  if (needsEnt) {
@@ -393,8 +411,11 @@ const generateUpdate: OpGen = (ctx, step, index) => {
393
411
  `)
394
412
  }
395
413
  Content(` ${datavar}Up := map[string]any{
396
- "id": ${srcdatavar}["id"],
397
414
  `)
415
+ if (hasEntIdU) {
416
+ Content(` "id": ${srcdatavar}["id"],
417
+ `)
418
+ }
398
419
 
399
420
  // Add data entries from step.data
400
421
  if (step.data) {
@@ -411,7 +432,7 @@ const generateUpdate: OpGen = (ctx, step, index) => {
411
432
  // Handle TextFieldMark spec
412
433
  if (step.spec) {
413
434
  for (const spec of step.spec) {
414
- if ('TextFieldMark' === spec.apply && null != step.input?.textfield) {
435
+ if ('TextFieldMark' === spec.apply && null != step.input.textfield) {
415
436
  const fieldname = step.input.textfield
416
437
  const fieldvalue = spec.def?.mark ?? `Mark01-${ref}`
417
438
  Content(`
@@ -432,15 +453,18 @@ const generateUpdate: OpGen = (ctx, step, index) => {
432
453
  if ${resdatavar} == nil {
433
454
  t.Fatal("expected update result to be a map")
434
455
  }
435
- if ${resdatavar}["id"] != ${datavar}Up["id"] {
456
+ `)
457
+ if (hasEntIdU) {
458
+ Content(` if ${resdatavar}["id"] != ${datavar}Up["id"] {
436
459
  t.Fatal("expected update result id to match")
437
460
  }
438
461
  `)
462
+ }
439
463
 
440
464
  // Assert TextFieldMark
441
465
  if (step.spec) {
442
466
  for (const spec of step.spec) {
443
- if ('TextFieldMark' === spec.apply && null != step.input?.textfield) {
467
+ if ('TextFieldMark' === spec.apply && null != step.input.textfield) {
444
468
  Content(` if ${resdatavar}[${markdefvar}Name] != ${markdefvar}Value {
445
469
  t.Fatalf("expected %s to be updated, got %v", ${markdefvar}Name, ${resdatavar}[${markdefvar}Name])
446
470
  }
@@ -453,11 +477,11 @@ const generateUpdate: OpGen = (ctx, step, index) => {
453
477
 
454
478
  const generateLoad: OpGen = (ctx, step, index) => {
455
479
  const { entity, flow } = ctx
456
- const ref = step.input?.ref ?? entity.name + '_ref01'
457
- const entvar = goVar(step.input?.entvar ?? ref + '_ent')
458
- const matchvar = goVar(step.input?.matchvar ?? (ref + '_match' + (step.input?.suffix ?? '')))
459
- const datavar = goVar(step.input?.datavar ?? (ref + '_data' + (step.input?.suffix ?? '')))
460
- const srcdatavar = goVar(step.input?.srcdatavar ?? (ref + '_data' + (step.input?.suffix ?? '')))
480
+ const ref = step.input.ref ?? entity.name + '_ref01'
481
+ const entvar = goVar(step.input.entvar ?? ref + '_ent')
482
+ const matchvar = goVar(step.input.matchvar ?? (ref + '_match' + (step.input.suffix ?? '')))
483
+ const datavar = goVar(step.input.datavar ?? (ref + '_data' + (step.input.suffix ?? '')))
484
+ const srcdatavar = goVar(step.input.srcdatavar ?? (ref + '_data' + (step.input.suffix ?? '')))
461
485
 
462
486
  const priorSteps = Object.values(flow.step).slice(0, Number(index)) as any[]
463
487
  const hasEntVar = priorSteps.some((s: any) =>
@@ -469,20 +493,22 @@ const generateLoad: OpGen = (ctx, step, index) => {
469
493
  const hasSrcData = (!flowHasCreate && srcdatavar === goVar(preambleRef + '_data')) ||
470
494
  priorSteps.some((s: any) => {
471
495
  if ('create' === s.op) {
472
- const priorRef = s.input?.ref ?? entity.name + '_ref01'
473
- const priorDatvar = goVar(s.input?.datavar ?? (priorRef + '_data' + (s.input?.suffix ?? '')))
496
+ const priorRef = s.input.ref ?? entity.name + '_ref01'
497
+ const priorDatvar = goVar(s.input.datavar ?? (priorRef + '_data' + (s.input.suffix ?? '')))
474
498
  return priorDatvar === srcdatavar
475
499
  }
476
500
  return false
477
501
  })
478
502
 
503
+ const hasEntId = null != entity.id
504
+
479
505
  Content(` // LOAD
480
506
  `)
481
507
  if (!hasEntVar) {
482
508
  Content(` ${entvar} := client.${entity.Name}(nil)
483
509
  `)
484
510
  }
485
- if (!hasSrcData) {
511
+ if (!hasSrcData && hasEntId) {
486
512
  Content(` ${srcdatavar}Raw := vs.Items(core.ToMapAny(vs.GetPath("existing.${entity.name}", setup.data)))
487
513
  var ${srcdatavar} map[string]any
488
514
  if len(${srcdatavar}Raw) > 0 {
@@ -490,7 +516,8 @@ const generateLoad: OpGen = (ctx, step, index) => {
490
516
  }
491
517
  `)
492
518
  }
493
- Content(` ${matchvar} := map[string]any{
519
+ if (hasEntId) {
520
+ Content(` ${matchvar} := map[string]any{
494
521
  "id": ${srcdatavar}["id"],
495
522
  }
496
523
  ${datavar}Loaded, err := ${entvar}.Load(${matchvar}, nil)
@@ -505,15 +532,27 @@ const generateLoad: OpGen = (ctx, step, index) => {
505
532
  t.Fatal("expected load result id to match")
506
533
  }
507
534
  `)
535
+ }
536
+ else {
537
+ Content(` ${matchvar} := map[string]any{}
538
+ ${datavar}Loaded, err := ${entvar}.Load(${matchvar}, nil)
539
+ if err != nil {
540
+ t.Fatalf("load failed: %v", err)
541
+ }
542
+ if ${datavar}Loaded == nil {
543
+ t.Fatal("expected load result to be non-nil")
544
+ }
545
+ `)
546
+ }
508
547
  }
509
548
 
510
549
 
511
550
  const generateRemove: OpGen = (ctx, step, index) => {
512
551
  const { entity, flow } = ctx
513
- const ref = step.input?.ref ?? entity.name + '_ref01'
514
- const entvar = goVar(step.input?.entvar ?? ref + '_ent')
515
- const matchvar = goVar(step.input?.matchvar ?? (ref + '_match' + (step.input?.suffix ?? '')))
516
- const srcdatavar = goVar(step.input?.srcdatavar ?? (ref + '_data'))
552
+ const ref = step.input.ref ?? entity.name + '_ref01'
553
+ const entvar = goVar(step.input.entvar ?? ref + '_ent')
554
+ const matchvar = goVar(step.input.matchvar ?? (ref + '_match' + (step.input.suffix ?? '')))
555
+ const srcdatavar = goVar(step.input.srcdatavar ?? (ref + '_data'))
517
556
 
518
557
  const priorSteps = Object.values(flow.step).slice(0, Number(index)) as any[]
519
558
  const needsEnt = !priorSteps.some((s: any) =>
@@ -523,13 +562,16 @@ const generateRemove: OpGen = (ctx, step, index) => {
523
562
  // otherwise reuse the `err` from a prior op step.
524
563
  const errOp = needsEnt ? ':=' : '='
525
564
 
565
+ const hasEntIdR = null != entity.id
566
+
526
567
  Content(` // REMOVE
527
568
  `)
528
569
  if (needsEnt) {
529
570
  Content(` ${entvar} := client.${entity.Name}(nil)
530
571
  `)
531
572
  }
532
- Content(` ${matchvar} := map[string]any{
573
+ if (hasEntIdR) {
574
+ Content(` ${matchvar} := map[string]any{
533
575
  "id": ${srcdatavar}["id"],
534
576
  }
535
577
  _, err ${errOp} ${entvar}.Remove(${matchvar}, nil)
@@ -537,6 +579,15 @@ const generateRemove: OpGen = (ctx, step, index) => {
537
579
  t.Fatalf("remove failed: %v", err)
538
580
  }
539
581
  `)
582
+ }
583
+ else {
584
+ Content(` ${matchvar} := map[string]any{}
585
+ _, err ${errOp} ${entvar}.Remove(${matchvar}, nil)
586
+ if err != nil {
587
+ t.Fatalf("remove failed: %v", err)
588
+ }
589
+ `)
590
+ }
540
591
  }
541
592
 
542
593
 
@@ -10,6 +10,7 @@ import {
10
10
  cmp,
11
11
  each,
12
12
  indent,
13
+ isAuthActive,
13
14
  } from '@voxgig/sdkgen'
14
15
 
15
16
 
@@ -40,6 +41,21 @@ const Config = cmp(async function Config(props: any) {
40
41
 
41
42
  const headers = getModelPath(model, `main.${KIT}.config.headers`) || {}
42
43
 
44
+ const authActive = isAuthActive(model)
45
+ let authPrefix = 'Bearer'
46
+ try {
47
+ const v = getModelPath(model, `main.${KIT}.config.auth.prefix`,
48
+ { only_active: false, required: false })
49
+ if (null != v) authPrefix = v
50
+ } catch (_e) { /* ignore */ }
51
+ const authBlock = authActive
52
+ ? `auth: {
53
+ prefix: '${authPrefix}',
54
+ },
55
+
56
+ `
57
+ : ''
58
+
43
59
  File({ name: 'Config.' + target.ext }, () => {
44
60
 
45
61
  Fragment({
@@ -47,6 +63,8 @@ const Config = cmp(async function Config(props: any) {
47
63
 
48
64
  replace: {
49
65
 
66
+ "'AUTHBLOCK'": authBlock,
67
+
50
68
  "'HEADERS'": indent(JSON.stringify(headers, null, 2), 4).trim(),
51
69
 
52
70
  '// #ImportFeatures': () => each(feature, (f: any) => {
@@ -0,0 +1,35 @@
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(`# Dependencies
12
+ node_modules/
13
+
14
+ # Build output
15
+ dist/
16
+
17
+ # Coverage
18
+ coverage/
19
+
20
+ # Logs
21
+ *.log
22
+ npm-debug.log*
23
+
24
+ # IDE / OS
25
+ .idea/
26
+ .vscode/
27
+ .DS_Store
28
+ `)
29
+ })
30
+ })
31
+
32
+
33
+ export {
34
+ Gitignore
35
+ }
@@ -20,6 +20,7 @@ import {
20
20
 
21
21
  import { Package } from './Package_js'
22
22
  import { Config } from './Config_js'
23
+ import { Gitignore } from './Gitignore_js'
23
24
  import { MainEntity } from './MainEntity_js'
24
25
  import { SdkError } from './SdkError_js'
25
26
  import { EntityBase } from './EntityBase_js'
@@ -36,6 +37,8 @@ const Main = cmp(async function Main(props: any) {
36
37
 
37
38
  Package({ target })
38
39
 
40
+ Gitignore({})
41
+
39
42
  Copy({
40
43
  from: 'tm/' + target.name,
41
44
  replace: {
@@ -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,5 +1,5 @@
1
1
 
2
- import { cmp, Content } from '@voxgig/sdkgen'
2
+ import { cmp, Content, isAuthActive } from '@voxgig/sdkgen'
3
3
 
4
4
  import {
5
5
  KIT,
@@ -10,6 +10,13 @@ import {
10
10
  const ReadmeHowto = cmp(function ReadmeHowto(props: any) {
11
11
  const { target, ctx$: { model } } = props
12
12
 
13
+ const authActive = isAuthActive(model)
14
+ const apikeyTesterCtor = authActive
15
+ ? `new ${model.const.Name}SDK({ apikey: '...' })`
16
+ : `new ${model.const.Name}SDK()`
17
+ const apikeyExtendField = authActive ? `\n apikey: '...',` : ''
18
+ const apikeyEnvLine = authActive ? `\n${model.NAME}_APIKEY=<your-key>` : ''
19
+
13
20
  Content(`### Make a direct HTTP request
14
21
 
15
22
  For endpoints not covered by entity methods:
@@ -57,7 +64,7 @@ const result = await client.Planet().load({ id: 'test01' })
57
64
  You can also use the instance method:
58
65
 
59
66
  \`\`\`js
60
- const client = new ${model.const.Name}SDK({ apikey: '...' })
67
+ const client = ${apikeyTesterCtor}
61
68
  const testClient = client.tester()
62
69
  \`\`\`
63
70
 
@@ -92,8 +99,7 @@ const logger = {
92
99
  },
93
100
  }
94
101
 
95
- const client = new ${model.const.Name}SDK({
96
- apikey: '...',
102
+ const client = new ${model.const.Name}SDK({${apikeyExtendField}
97
103
  extend: [logger],
98
104
  })
99
105
  \`\`\`
@@ -103,8 +109,7 @@ const client = new ${model.const.Name}SDK({
103
109
  Create a \`.env.local\` file at the project root:
104
110
 
105
111
  \`\`\`
106
- ${model.NAME}_TEST_LIVE=TRUE
107
- ${model.NAME}_APIKEY=<your-key>
112
+ ${model.NAME}_TEST_LIVE=TRUE${apikeyEnvLine}
108
113
  \`\`\`
109
114
 
110
115
  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 with full async/await support.
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
  #### Constructor
@@ -23,8 +27,7 @@ new ${model.const.Name}SDK(options?)
23
27
 
24
28
  | Option | Type | Description |
25
29
  | --- | --- | --- |
26
- | \`apikey\` | \`string\` | API key for authentication. |
27
- | \`base\` | \`string\` | Base URL of the API server. |
30
+ ${apikeyOptionRow}| \`base\` | \`string\` | Base URL of the API server. |
28
31
  | \`prefix\` | \`string\` | URL path prefix prepended to all requests. |
29
32
  | \`suffix\` | \`string\` | URL path suffix appended to all requests. |
30
33
  | \`feature\` | \`object\` | Feature activation flags (e.g. \`{ test: { active: true } }\`). |