@voxgig/sdkgen 0.36.0 → 0.38.1

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 (141) hide show
  1. package/bin/voxgig-sdkgen +1 -1
  2. package/dist/cmp/Main.js +0 -12
  3. package/dist/cmp/Main.js.map +1 -1
  4. package/package.json +2 -3
  5. package/project/.sdk/model/feature/log.jsonic +1 -1
  6. package/project/.sdk/model/target/js.jsonic +1 -1
  7. package/project/.sdk/model/target/py.jsonic +1 -1
  8. package/project/.sdk/model/target/ts.jsonic +2 -2
  9. package/project/.sdk/src/cmp/go/Config_go.ts +6 -2
  10. package/project/.sdk/src/cmp/js/EntityBase_js.ts +34 -0
  11. package/project/.sdk/src/cmp/js/Main_js.ts +10 -0
  12. package/project/.sdk/src/cmp/js/ReadmeExplanation_js.ts +33 -0
  13. package/project/.sdk/src/cmp/js/ReadmeHowto_js.ts +123 -0
  14. package/project/.sdk/src/cmp/js/ReadmeModel_js.ts +152 -0
  15. package/project/.sdk/src/cmp/js/ReadmeTopHowto_js.ts +25 -0
  16. package/project/.sdk/src/cmp/js/ReadmeTopQuick_js.ts +65 -0
  17. package/project/.sdk/src/cmp/js/ReadmeTopTest_js.ts +36 -0
  18. package/project/.sdk/src/cmp/js/TestDirect_js.ts +53 -5
  19. package/project/.sdk/src/cmp/js/TestEntity_js.ts +114 -20
  20. package/project/.sdk/src/cmp/js/fragment/Entity.fragment.js +7 -139
  21. package/project/.sdk/src/cmp/js/fragment/EntityBase.fragment.js +149 -0
  22. package/project/.sdk/src/cmp/js/fragment/EntityCreateOp.fragment.js +6 -10
  23. package/project/.sdk/src/cmp/js/fragment/EntityListOp.fragment.js +6 -10
  24. package/project/.sdk/src/cmp/js/fragment/EntityLoadOp.fragment.js +7 -11
  25. package/project/.sdk/src/cmp/js/fragment/EntityRemoveOp.fragment.js +7 -11
  26. package/project/.sdk/src/cmp/js/fragment/EntityUpdateOp.fragment.js +7 -11
  27. package/project/.sdk/src/cmp/js/fragment/Main.fragment.js +2 -0
  28. package/project/.sdk/src/cmp/js/fragment/SdkError.fragment.js +0 -2
  29. package/project/.sdk/src/cmp/lua/Config_lua.ts +6 -2
  30. package/project/.sdk/src/cmp/lua/TestEntity_lua.ts +3 -1
  31. package/project/.sdk/src/cmp/php/Config_php.ts +6 -2
  32. package/project/.sdk/src/cmp/php/Package_php.ts +2 -2
  33. package/project/.sdk/src/cmp/php/TestDirect_php.ts +2 -2
  34. package/project/.sdk/src/cmp/php/TestEntity_php.ts +10 -15
  35. package/project/.sdk/src/cmp/py/Config_py.ts +6 -2
  36. package/project/.sdk/src/cmp/py/Package_py.ts +1 -1
  37. package/project/.sdk/src/cmp/py/TestEntity_py.ts +3 -1
  38. package/project/.sdk/src/cmp/rb/Config_rb.ts +6 -2
  39. package/project/.sdk/src/cmp/ts/Main_ts.ts +7 -0
  40. package/project/.sdk/tm/go/feature/log_feature.go +1 -1
  41. package/project/.sdk/tm/go/test/runner_test.go +16 -2
  42. package/project/.sdk/tm/js/src/Context.js +142 -0
  43. package/project/.sdk/tm/js/src/Control.js +16 -0
  44. package/project/.sdk/tm/js/src/Operation.js +19 -0
  45. package/project/.sdk/tm/js/src/Point.js +24 -0
  46. package/project/.sdk/tm/js/src/README.md +1 -0
  47. package/project/.sdk/tm/js/src/Response.js +19 -0
  48. package/project/.sdk/tm/js/src/Result.js +21 -0
  49. package/project/.sdk/tm/js/src/Spec.js +26 -0
  50. package/project/.sdk/tm/js/src/feature/README.md +1 -0
  51. package/project/.sdk/tm/js/src/feature/base/BaseFeature.js +45 -0
  52. package/project/.sdk/tm/js/src/feature/log/LogFeature.js +46 -47
  53. package/project/.sdk/tm/js/src/feature/test/TestFeature.js +207 -0
  54. package/project/.sdk/tm/js/src/types.js +22 -0
  55. package/project/.sdk/tm/js/src/utility/CleanUtility.js +31 -0
  56. package/project/.sdk/tm/js/src/utility/DoneUtility.js +11 -4
  57. package/project/.sdk/tm/js/src/utility/FeatureAddUtility.js +42 -0
  58. package/project/.sdk/tm/js/src/utility/FeatureHookUtility.js +25 -0
  59. package/project/.sdk/tm/js/src/utility/FeatureInitUtility.js +11 -0
  60. package/project/.sdk/tm/js/src/utility/FetcherUtility.js +28 -0
  61. package/project/.sdk/tm/js/src/utility/MakeContextUtility.js +11 -0
  62. package/project/.sdk/tm/js/src/utility/MakeErrorUtility.js +55 -0
  63. package/project/.sdk/tm/js/src/utility/MakeFetchDefUtility.js +44 -0
  64. package/project/.sdk/tm/js/src/utility/MakeOptionsUtility.js +93 -0
  65. package/project/.sdk/tm/js/src/utility/MakePointUtility.js +77 -0
  66. package/project/.sdk/tm/js/src/utility/MakeRequestUtility.js +63 -0
  67. package/project/.sdk/tm/js/src/utility/MakeResponseUtility.js +55 -0
  68. package/project/.sdk/tm/js/src/utility/MakeResultUtility.js +54 -0
  69. package/project/.sdk/tm/js/src/utility/MakeSpecUtility.js +58 -0
  70. package/project/.sdk/tm/js/src/utility/MakeUrlUtility.js +40 -0
  71. package/project/.sdk/tm/js/src/utility/ParamUtility.js +61 -0
  72. package/project/.sdk/tm/js/src/utility/PrepareAuthUtility.js +41 -0
  73. package/project/.sdk/tm/js/src/utility/PrepareBodyUtility.js +25 -0
  74. package/project/.sdk/tm/js/src/utility/PrepareHeadersUtility.js +18 -0
  75. package/project/.sdk/tm/js/src/utility/{MethodUtility.js → PrepareMethodUtility.js} +7 -7
  76. package/project/.sdk/tm/js/src/utility/PrepareParamsUtility.js +25 -0
  77. package/project/.sdk/tm/js/src/utility/PreparePathUtility.js +13 -0
  78. package/project/.sdk/tm/js/src/utility/PrepareQueryUtility.js +26 -0
  79. package/project/.sdk/tm/js/src/utility/README.md +1 -0
  80. package/project/.sdk/tm/js/src/utility/ResultBasicUtility.js +34 -0
  81. package/project/.sdk/tm/js/src/utility/ResultBodyUtility.js +18 -0
  82. package/project/.sdk/tm/js/src/utility/ResultHeadersUtility.js +22 -0
  83. package/project/.sdk/tm/js/src/utility/StructUtility.js +2219 -1078
  84. package/project/.sdk/tm/js/src/utility/TransformRequestUtility.js +28 -0
  85. package/project/.sdk/tm/js/src/utility/TransformResponseUtility.js +31 -0
  86. package/project/.sdk/tm/js/src/utility/Utility.js +61 -61
  87. package/project/.sdk/tm/js/test/README.md +1 -0
  88. package/project/.sdk/tm/js/test/exists.test.js +16 -0
  89. package/project/.sdk/tm/js/test/runner.js +323 -107
  90. package/project/.sdk/tm/js/test/utility/Custom.test.js +41 -63
  91. package/project/.sdk/tm/js/test/utility/PrimaryUtility.test.js +390 -116
  92. package/project/.sdk/tm/js/test/utility/StructUtility.test.js +728 -175
  93. package/project/.sdk/tm/js/test/utility/index.js +9 -0
  94. package/project/.sdk/tm/js/test/utility.js +72 -0
  95. package/project/.sdk/tm/lua/test/primary_utility_test.lua +1213 -0
  96. package/project/.sdk/tm/lua/test/runner.lua +2 -2
  97. package/project/.sdk/tm/lua/test/struct_runner.lua +602 -0
  98. package/project/.sdk/tm/lua/test/struct_utility_test.lua +959 -0
  99. package/project/.sdk/tm/lua/utility/struct/struct.lua +10 -0
  100. package/project/.sdk/tm/php/feature/TestFeature.php +59 -96
  101. package/project/.sdk/tm/php/test/PrimaryUtilityTest.php +1309 -0
  102. package/project/.sdk/tm/php/test/Runner.php +24 -1
  103. package/project/.sdk/tm/php/test/StructRunner.php +275 -0
  104. package/project/.sdk/tm/php/test/StructUtilityTest.php +1336 -0
  105. package/project/.sdk/tm/php/utility/Fetcher.php +6 -2
  106. package/project/.sdk/tm/php/utility/MakeOptions.php +5 -1
  107. package/project/.sdk/tm/php/utility/MakeResult.php +3 -0
  108. package/project/.sdk/tm/php/utility/Param.php +9 -7
  109. package/project/.sdk/tm/php/utility/struct/Struct.php +312 -208
  110. package/project/.sdk/tm/py/test/runner.py +13 -0
  111. package/project/.sdk/tm/py/test/struct_runner.py +411 -0
  112. package/project/.sdk/tm/py/test/test_primary_utility.py +1101 -0
  113. package/project/.sdk/tm/py/test/test_struct_utility.py +751 -0
  114. package/project/.sdk/tm/rb/test/primary_utility_test.rb +1083 -0
  115. package/project/.sdk/tm/rb/test/runner.rb +5 -0
  116. package/project/.sdk/tm/rb/test/struct_runner.rb +309 -0
  117. package/project/.sdk/tm/rb/test/struct_utility_test.rb +670 -0
  118. package/src/cmp/Main.ts +1 -16
  119. package/project/.sdk/src/cmp/js/Quick_js.ts +0 -78
  120. package/project/.sdk/src/cmp/js/TestAcceptEntity_js.ts +0 -13
  121. package/project/.sdk/src/cmp/js/TestAccept_js.ts +0 -18
  122. package/project/.sdk/tm/js/src/utility/AuthUtility.js +0 -21
  123. package/project/.sdk/tm/js/src/utility/BodyUtility.js +0 -29
  124. package/project/.sdk/tm/js/src/utility/ErrorUtility.js +0 -33
  125. package/project/.sdk/tm/js/src/utility/FindparamUtility.js +0 -31
  126. package/project/.sdk/tm/js/src/utility/FullurlUtility.js +0 -39
  127. package/project/.sdk/tm/js/src/utility/HeadersUtility.js +0 -13
  128. package/project/.sdk/tm/js/src/utility/JoinurlUtility.js +0 -14
  129. package/project/.sdk/tm/js/src/utility/OperatorUtility.js +0 -44
  130. package/project/.sdk/tm/js/src/utility/OptionsUtility.js +0 -54
  131. package/project/.sdk/tm/js/src/utility/ParamsUtility.js +0 -21
  132. package/project/.sdk/tm/js/src/utility/QueryUtility.js +0 -21
  133. package/project/.sdk/tm/js/src/utility/ReqformUtility.js +0 -32
  134. package/project/.sdk/tm/js/src/utility/RequestUtility.js +0 -48
  135. package/project/.sdk/tm/js/src/utility/ResbasicUtility.js +0 -27
  136. package/project/.sdk/tm/js/src/utility/ResbodyUtility.js +0 -15
  137. package/project/.sdk/tm/js/src/utility/ResformUtility.js +0 -34
  138. package/project/.sdk/tm/js/src/utility/ResheadersUtility.js +0 -19
  139. package/project/.sdk/tm/js/src/utility/ResponseUtility.js +0 -37
  140. package/project/.sdk/tm/js/src/utility/ResultUtility.js +0 -28
  141. package/project/.sdk/tm/js/src/utility/SpecUtility.js +0 -35
@@ -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
 
@@ -121,20 +123,20 @@ function directSetup(mockres) {
121
123
 
122
124
  function generateDirectLoad(model: any, entity: any) {
123
125
  const loadOp = entity.op.load
124
- const loadPoint = loadOp.points[0]
126
+ const loadPoint = loadOp?.points?.[0]
125
127
 
126
128
  if (null == loadPoint) {
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
@@ -218,14 +220,14 @@ ${paramAsserts} }
218
220
 
219
221
  function generateDirectList(model: any, entity: any) {
220
222
  const listOp = entity.op.list
221
- const listPoint = listOp.points[0]
223
+ const listPoint = listOp?.points?.[0]
222
224
 
223
225
  if (null == listPoint) {
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
  }
@@ -37,7 +37,7 @@ import {
37
37
  } from './utility_js'
38
38
 
39
39
 
40
- type OpGen = (model: any, entity: any, flow: any, step: any, index: any) => void
40
+ type OpGen = (model: any, entity: any, flow: any, step: any, index: { key$: number, val$: any }) => void
41
41
 
42
42
 
43
43
  const TestEntity = cmp(function TestEntity(props: any) {
@@ -78,9 +78,9 @@ const TestEntity = cmp(function TestEntity(props: any) {
78
78
  const indent = 2
79
79
 
80
80
  const idlist = flatten([
81
- '${entity.name}01',
82
- '${entity.name}02',
83
- '${entity.name}03',
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) {
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) {
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]
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)
@@ -183,17 +196,39 @@ const generateCreate: OpGen = (
183
196
  entity: ModelEntity,
184
197
  flow: ModelEntityFlow,
185
198
  step: ModelEntityFlowStep,
186
- index: number
199
+ index: any
187
200
  ) => {
188
201
  const ref = step.input.ref ?? entity.name + '_ref01'
189
202
  const entvar = step.input.entvar ?? ref + '_ent'
190
203
  const datavar = step.input.datavar ?? (ref + '_data' + (step.input.suffix ?? ''))
191
204
 
205
+ const priorSteps = Object.values(flow.step).slice(0, Number(index))
206
+ const needsEnt = !priorSteps.some((s: any) =>
207
+ ['create', 'list', 'load', 'update', 'remove'].includes(s.op))
208
+
209
+ const hasDatvar = priorSteps.some((s: any) => {
210
+ if ('create' === s.op) {
211
+ const priorRef = s.input?.ref ?? entity.name + '_ref01'
212
+ const priorDatvar = s.input?.datavar ?? (priorRef + '_data' + (s.input?.suffix ?? ''))
213
+ return priorDatvar === datavar
214
+ }
215
+ return false
216
+ })
217
+
192
218
  Content(`
193
219
  // CREATE
194
- const ${entvar} = client.${nom(entity, 'Name')}()
195
- let ${datavar} = setup.data.new.${entity.name}['${ref}']
196
220
  `)
221
+ if (needsEnt) {
222
+ Content(` const ${entvar} = client.${nom(entity, 'Name')}()
223
+ `)
224
+ }
225
+ if (hasDatvar) {
226
+ Content(` ${datavar} = setup.data.new.${entity.name}['${ref}']
227
+ `)
228
+ } else {
229
+ Content(` let ${datavar} = setup.data.new.${entity.name}['${ref}']
230
+ `)
231
+ }
197
232
 
198
233
  each(step.match, (mi: any) => {
199
234
  Content(` ${datavar}['${mi.key$}'] = setup.idmap['${mi.val$}']
@@ -212,16 +247,25 @@ const generateList: OpGen = (
212
247
  entity: ModelEntity,
213
248
  flow: ModelEntityFlow,
214
249
  step: ModelEntityFlowStep,
215
- index: number
250
+ index: any
216
251
  ) => {
217
252
  const ref = step.input.ref ?? entity.name + '_ref01'
218
253
  const entvar = step.input.entvar ?? ref + '_ent'
219
254
  const matchvar = step.input.matchvar ?? (ref + '_match' + (step.input.suffix ?? ''))
220
255
  const listvar = step.input.listvar ?? (ref + '_list' + (step.input.suffix ?? ''))
221
256
 
257
+ const priorSteps = Object.values(flow.step).slice(0, Number(index))
258
+ const needsEnt = !priorSteps.some((s: any) =>
259
+ ['create', 'list', 'load', 'update', 'remove'].includes(s.op))
260
+
222
261
  Content(`
223
262
  // LIST
224
- const ${matchvar} = {}
263
+ `)
264
+ if (needsEnt) {
265
+ Content(` const ${entvar} = client.${nom(entity, 'Name')}()
266
+ `)
267
+ }
268
+ Content(` const ${matchvar} = {}
225
269
  `)
226
270
 
227
271
  each(step.match, (mi: any) => {
@@ -232,16 +276,21 @@ const generateList: OpGen = (
232
276
  Content(`
233
277
  const ${listvar} = await ${entvar}.list(${matchvar})
234
278
  `)
279
+ const allSteps = Object.values(flow.step)
235
280
  for (let vI = 0; vI < step.valid.length; vI++) {
236
281
  const validator = step.valid[vI]
237
- if ('ItemExists' === validator.apply) {
282
+ const validRef = validator.def?.ref
283
+ const hasRefData = validRef && allSteps.some((s: any) => 'create' === s.op &&
284
+ ((s.input?.ref ?? entity.name + '_ref01') === validRef))
285
+
286
+ if ('ItemExists' === validator.apply && hasRefData) {
238
287
  Content(`
239
- assert(!isempty(select(${listvar}, { id: ${validator.def.ref}_data.id })))
288
+ assert(!isempty(select(${listvar}, { id: ${validRef}_data.id })))
240
289
  `)
241
290
  }
242
- else if ('ItemNotExists' === validator.apply) {
291
+ else if ('ItemNotExists' === validator.apply && hasRefData) {
243
292
  Content(`
244
- assert(isempty(select(${listvar}, { id: ${validator.def.ref}_data.id })))
293
+ assert(isempty(select(${listvar}, { id: ${validRef}_data.id })))
245
294
  `)
246
295
  }
247
296
  }
@@ -253,7 +302,7 @@ const generateUpdate: OpGen = (
253
302
  entity: ModelEntity,
254
303
  flow: ModelEntityFlow,
255
304
  step: ModelEntityFlowStep,
256
- index: number
305
+ index: any
257
306
  ) => {
258
307
  const ref = step.input.ref ?? entity.name + '_ref01'
259
308
  const entvar = step.input.entvar ?? ref + '_ent'
@@ -262,9 +311,18 @@ const generateUpdate: OpGen = (
262
311
  const markdefvar = step.input.markdefvar ?? (ref + '_markdef' + (step.input.suffix ?? ''))
263
312
  const srcdatavar = step.input.srcdatavar ?? (ref + '_data' + (step.input.suffix ?? ''))
264
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
+
265
318
  Content(`
266
319
  // UPDATE
267
- const ${datavar} = {}
320
+ `)
321
+ if (needsEnt) {
322
+ Content(` const ${entvar} = client.${nom(entity, 'Name')}()
323
+ `)
324
+ }
325
+ Content(` const ${datavar} = {}
268
326
  ${datavar}.id = ${srcdatavar}.id
269
327
  `)
270
328
 
@@ -295,7 +353,7 @@ const generateUpdate: OpGen = (
295
353
 
296
354
  for (let sI = 0; sI < step.spec.length; sI++) {
297
355
  const spec = step.spec[sI]
298
- if ('TextFieldMark' === spec.apply) {
356
+ if ('TextFieldMark' === spec.apply && null != step.input.textfield) {
299
357
  Content(`
300
358
  assert(${resdatavar}[${markdefvar}.name] === ${markdefvar}.value)
301
359
  `)
@@ -310,7 +368,7 @@ const generateLoad: OpGen = (
310
368
  entity: ModelEntity,
311
369
  flow: ModelEntityFlow,
312
370
  step: ModelEntityFlowStep,
313
- index: number
371
+ index: any
314
372
  ) => {
315
373
  const ref = step.input.ref ?? entity.name + '_ref01'
316
374
  const entvar = step.input.entvar ?? ref + '_ent'
@@ -318,9 +376,36 @@ const generateLoad: OpGen = (
318
376
  const datavar = step.input.datavar ?? (ref + '_data' + (step.input.suffix ?? ''))
319
377
  const srcdatavar = step.input.srcdatavar ?? (ref + '_data' + (step.input.suffix ?? ''))
320
378
 
379
+ const priorSteps = Object.values(flow.step).slice(0, Number(index))
380
+ const hasEntVar = priorSteps.some((s: any) =>
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
+ })
396
+
321
397
  Content(`
322
398
  // LOAD
323
- const ${matchvar} = {}
399
+ `)
400
+ if (!hasEntVar) {
401
+ Content(` const ${entvar} = client.${nom(entity, 'Name')}()
402
+ `)
403
+ }
404
+ if (!hasSrcData) {
405
+ Content(` const ${srcdatavar} = Object.values(setup.data.existing.${entity.name})[0]
406
+ `)
407
+ }
408
+ Content(` const ${matchvar} = {}
324
409
  ${matchvar}.id = ${srcdatavar}.id
325
410
  const ${datavar} = await ${entvar}.load(${matchvar})
326
411
  assert(${datavar}.id === ${srcdatavar}.id)
@@ -333,16 +418,25 @@ const generateRemove: OpGen = (
333
418
  entity: ModelEntity,
334
419
  flow: ModelEntityFlow,
335
420
  step: ModelEntityFlowStep,
336
- index: number
421
+ index: any
337
422
  ) => {
338
423
  const ref = step.input.ref ?? entity.name + '_ref01'
339
424
  const entvar = step.input.entvar ?? ref + '_ent'
340
425
  const matchvar = step.input.matchvar ?? (ref + '_match' + (step.input.suffix ?? ''))
341
426
  const srcdatavar = step.input.srcdatavar ?? (ref + '_data')
342
427
 
428
+ const priorSteps = Object.values(flow.step).slice(0, Number(index))
429
+ const needsEnt = !priorSteps.some((s: any) =>
430
+ ['create', 'list', 'load', 'update', 'remove'].includes(s.op))
431
+
343
432
  Content(`
344
433
  // REMOVE
345
- const ${matchvar} = {}
434
+ `)
435
+ if (needsEnt) {
436
+ Content(` const ${entvar} = client.${nom(entity, 'Name')}()
437
+ `)
438
+ }
439
+ Content(` const ${matchvar} = {}
346
440
  ${matchvar}.id = ${srcdatavar}.id
347
441
  await ${entvar}.remove(${matchvar})
348
442
  `)
@@ -1,106 +1,22 @@
1
1
 
2
2
  const { inspect } = require('node:util')
3
3
 
4
- const {
5
- SdkNameSDK,
6
- SdkNameEntity,
7
- } = require('../SdkNameSDK')
8
-
9
- const {
10
- Utility
11
- } = require('../utility/Utility')
4
+ const { ProjectNameEntityBase } = require('../ProjectNameEntityBase')
12
5
 
13
6
 
14
7
  // TODO: needs Entity superclass
15
- class EntityNameEntity {
16
- name = 'entityname'
17
-
18
- #client
19
- #utility
20
- #entopts
21
- #data
22
- #match
23
-
24
- _entctx
8
+ class EntityNameEntity extends ProjectNameEntityBase {
25
9
 
26
10
  constructor(client, entopts) {
27
- // super()
28
- entopts = entopts || {}
29
- entopts.active = false !== entopts.active
30
-
31
- this.#client = client
32
- this.#entopts = entopts
33
- this.#utility = client.utility()
34
- this.#data = {}
35
- this.#match = {}
36
-
37
- const makeContext = this.#utility.makeContext
38
-
39
- this._entctx = makeContext({
40
- entity: this,
41
- entopts,
42
- }, client._rootctx)
43
-
44
- const featureHook = this.#utility.featureHook
45
- featureHook(this._entctx, 'PostConstructEntity')
11
+ super(client, entopts)
12
+ this.name = 'entityname'
13
+ this.name_ = 'entityname'
14
+ this.Name = 'EntityName'
46
15
  }
47
16
 
48
- entopts() {
49
- return { ...this.#entopts }
50
- }
51
-
52
- client() {
53
- return this.#client
54
- }
55
17
 
56
18
  make() {
57
- return new EntityNameEntity(this.#client, this.entopts())
58
- }
59
-
60
-
61
- data(data) {
62
- const struct = this.#utility.struct
63
- const featureHook = this.#utility.featureHook
64
-
65
- if (null != data) {
66
- this.#data = struct.clone(data)
67
- featureHook(this._entctx, 'SetData')
68
- }
69
-
70
- featureHook(this._entctx, 'GetData')
71
- let out = struct.clone(this.#data)
72
-
73
- return out
74
- }
75
-
76
-
77
- match(match) {
78
- const struct = this.#utility.struct
79
- const featureHook = this.#utility.featureHook
80
-
81
- if (null != match) {
82
- this.#match = struct.clone(match)
83
- featureHook(this._entctx, 'SetMatch')
84
- }
85
-
86
- featureHook(this._entctx, 'GetMatch')
87
- let out = struct.clone(this.#match)
88
-
89
- return out
90
- }
91
-
92
-
93
- toJSON() {
94
- const struct = this.#utility.struct
95
- return struct.merge([{}, struct.getdef(this.#data, {}), { $entity: 'EntityName' }])
96
- }
97
-
98
- toString() {
99
- return 'EntityName ' + this.#utility.struct.jsonify(this.#data)
100
- }
101
-
102
- [inspect.custom]() {
103
- return this.toString()
19
+ return new EntityNameEntity(this._client, this.entopts())
104
20
  }
105
21
 
106
22
 
@@ -114,54 +30,6 @@ class EntityNameEntity {
114
30
 
115
31
  // #RemoveOp
116
32
 
117
-
118
- #unexpected(ctx, err) {
119
- const clean = this.#utility.clean
120
- const struct = this.#utility.struct
121
-
122
- const delprop = struct.delprop
123
- const clone = struct.clone
124
- const merge = struct.merge
125
-
126
- const ctrl = ctx.ctrl
127
-
128
- ctrl.err = err
129
-
130
- if (ctrl.explain) {
131
- ctx.ctrl.explain = clean(ctx, ctx.ctrl.explain)
132
- delprop(ctx.ctrl.explain.result, 'err')
133
-
134
- if (null != ctx.result && null != ctx.result.err) {
135
- ctrl.explain.err = clean(ctx, merge([
136
- clone({ err: ctx.result.err }).err,
137
- {
138
- message: ctx.result.err.message,
139
- stack: ctx.result.err.stack,
140
- }]))
141
- }
142
-
143
- const cleanerr = clean(ctx, merge([
144
- clone({ err }).err,
145
- {
146
- message: err.message,
147
- stack: err.stack,
148
- }]))
149
-
150
- if (null == ctrl.explain.err) {
151
- ctrl.explain.err = cleanerr
152
- }
153
- else if (ctrl.explain.err.message != cleanerr.message) {
154
- ctrl.explain.unexpected = cleanerr
155
- }
156
- }
157
-
158
- if (false === ctrl.throw) {
159
- return undefined
160
- }
161
-
162
- return err
163
- }
164
-
165
33
  }
166
34
 
167
35
 
@@ -0,0 +1,149 @@
1
+
2
+ const { inspect } = require('node:util')
3
+
4
+
5
+ // TODO: needs Entity superclass
6
+ class ProjectNameEntityBase {
7
+ name = ''
8
+ name_ = ''
9
+ Name = ''
10
+
11
+ _client
12
+ _utility
13
+ _entopts
14
+ _data
15
+ _match
16
+ _entctx
17
+
18
+
19
+ constructor(client, entopts) {
20
+ entopts = entopts || {}
21
+ entopts.active = false !== entopts.active
22
+
23
+ this._client = client
24
+ this._entopts = entopts
25
+ this._utility = client.utility()
26
+ this._data = {}
27
+ this._match = {}
28
+
29
+ const makeContext = this._utility.makeContext
30
+
31
+ this._entctx = makeContext({
32
+ entity: this,
33
+ entopts,
34
+ }, client._rootctx)
35
+
36
+ const featureHook = this._utility.featureHook
37
+ featureHook(this._entctx, 'PostConstructEntity')
38
+ }
39
+
40
+ entopts() {
41
+ return this._utility.struct.merge([{}, this._entopts])
42
+ }
43
+
44
+ client() {
45
+ return this._client
46
+ }
47
+
48
+
49
+ data(data) {
50
+ const struct = this._utility.struct
51
+ const featureHook = this._utility.featureHook
52
+
53
+ if (null != data) {
54
+ this._data = struct.clone(data)
55
+ featureHook(this._entctx, 'SetData')
56
+ }
57
+
58
+ featureHook(this._entctx, 'GetData')
59
+ let out = struct.clone(this._data)
60
+
61
+ return out
62
+ }
63
+
64
+
65
+ match(match) {
66
+ const struct = this._utility.struct
67
+ const featureHook = this._utility.featureHook
68
+
69
+ if (null != match) {
70
+ this._match = struct.clone(match)
71
+ featureHook(this._entctx, 'SetMatch')
72
+ }
73
+
74
+ featureHook(this._entctx, 'GetMatch')
75
+ let out = struct.clone(this._match)
76
+
77
+ return out
78
+ }
79
+
80
+
81
+ toJSON() {
82
+ const struct = this._utility.struct
83
+ return struct.merge([{}, struct.getdef(this._data, {}), { entity$: this.Name }])
84
+ }
85
+
86
+
87
+ toString() {
88
+ return this.Name + ' ' + this._utility.struct.jsonify(this._data)
89
+ }
90
+
91
+
92
+ [inspect.custom]() {
93
+ return this.toString()
94
+ }
95
+
96
+
97
+ _unexpected(ctx, err) {
98
+ const clean = this._utility.clean
99
+ const struct = this._utility.struct
100
+
101
+ const delprop = struct.delprop
102
+ const clone = struct.clone
103
+ const merge = struct.merge
104
+
105
+ const ctrl = ctx.ctrl
106
+
107
+ ctrl.err = err
108
+
109
+ if (ctrl.explain) {
110
+ ctx.ctrl.explain = clean(ctx, ctx.ctrl.explain)
111
+ delprop(ctx.ctrl.explain.result, 'err')
112
+
113
+ if (null != ctx.result && null != ctx.result.err) {
114
+ ctrl.explain.err = clean(ctx, merge([
115
+ clone({ err: ctx.result.err }).err,
116
+ {
117
+ message: ctx.result.err.message,
118
+ stack: ctx.result.err.stack,
119
+ }]))
120
+ }
121
+
122
+ const cleanerr = clean(ctx, merge([
123
+ clone({ err }).err,
124
+ {
125
+ message: err.message,
126
+ stack: err.stack,
127
+ }]))
128
+
129
+ if (null == ctrl.explain.err) {
130
+ ctrl.explain.err = cleanerr
131
+ }
132
+ else if (ctrl.explain.err.message != cleanerr.message) {
133
+ ctrl.explain.unexpected = cleanerr
134
+ }
135
+ }
136
+
137
+ if (false === ctrl.throw) {
138
+ return undefined
139
+ }
140
+
141
+ return err
142
+ }
143
+
144
+ }
145
+
146
+
147
+ module.exports = {
148
+ ProjectNameEntityBase
149
+ }