@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
@@ -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(`\`\`\`ts
23
+ const client = new ${model.Name}SDK({
24
+ `)
25
+
26
+ publishedOptions.map((option: any) => {
27
+ if ('apikey' === option.name) {
28
+ Content(` ${option.name}: process.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
+ }
@@ -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,
@@ -21,14 +21,16 @@ const ReadmeQuick = cmp(function ReadmeQuick(props: any) {
21
21
  e.active !== false && e.ancestors && e.ancestors.length > 0
22
22
  ) as any
23
23
 
24
+ const apikeyArg = isAuthActive(model)
25
+ ? `\n apikey: process.env.${model.NAME}_APIKEY,\n`
26
+ : ''
27
+
24
28
  Content(`### 1. Create a client
25
29
 
26
30
  \`\`\`ts
27
31
  import { ${model.const.Name}SDK } from '${target.module.name}'
28
32
 
29
- const client = new ${model.const.Name}SDK({
30
- apikey: process.env.${model.NAME}_APIKEY,
31
- })
33
+ const client = new ${model.const.Name}SDK({${apikeyArg}})
32
34
  \`\`\`
33
35
 
34
36
  `)
@@ -0,0 +1,384 @@
1
+
2
+ import { cmp, each, Content, File, isAuthActive } from '@voxgig/sdkgen'
3
+
4
+ import {
5
+ KIT,
6
+ getModelPath,
7
+ } from '@voxgig/apidef'
8
+
9
+
10
+ const OP_SIGNATURES: Record<string, { sig: string, returns: string, desc: string }> = {
11
+ load: {
12
+ sig: 'load(match: object, ctrl?: object)',
13
+ returns: 'Promise<object>',
14
+ desc: 'Load a single entity matching the given criteria.',
15
+ },
16
+ list: {
17
+ sig: 'list(match: object, ctrl?: object)',
18
+ returns: 'Promise<object[]>',
19
+ desc: 'List entities matching the given criteria. Returns an array.',
20
+ },
21
+ create: {
22
+ sig: 'create(data: object, ctrl?: object)',
23
+ returns: 'Promise<object>',
24
+ desc: 'Create a new entity with the given data.',
25
+ },
26
+ update: {
27
+ sig: 'update(data: object, ctrl?: object)',
28
+ returns: 'Promise<object>',
29
+ desc: 'Update an existing entity. The data must include the entity `id`.',
30
+ },
31
+ remove: {
32
+ sig: 'remove(match: object, ctrl?: object)',
33
+ returns: 'Promise<void>',
34
+ desc: 'Remove the entity matching the given criteria.',
35
+ },
36
+ }
37
+
38
+
39
+ const ReadmeRef = cmp(function ReadmeRef(props: any) {
40
+ const { target } = props
41
+ const { model } = props.ctx$
42
+
43
+ const entity = getModelPath(model, `main.${KIT}.entity`)
44
+ const feature = getModelPath(model, `main.${KIT}.feature`)
45
+
46
+ const publishedEntities = each(entity).filter((e: any) => e.active !== false)
47
+
48
+
49
+ File({ name: 'REFERENCE.md' }, () => {
50
+
51
+ Content(`# ${model.Name} ${target.title} SDK Reference
52
+
53
+ Complete API reference for the ${model.Name} ${target.title} SDK.
54
+
55
+
56
+ ## ${model.Name}SDK
57
+
58
+ ### Constructor
59
+
60
+ `)
61
+
62
+ Content(`\`\`\`ts
63
+ new ${model.Name}SDK(options?: object)
64
+ \`\`\`
65
+
66
+ Create a new SDK client instance.
67
+
68
+ **Parameters:**
69
+
70
+ | Name | Type | Description |
71
+ | --- | --- | --- |
72
+ | \`options\` | \`object\` | SDK configuration options. |
73
+ | \`options.apikey\` | \`string\` | API key for authentication. |
74
+ | \`options.base\` | \`string\` | Base URL for API requests. |
75
+ | \`options.prefix\` | \`string\` | URL prefix appended after base. |
76
+ | \`options.suffix\` | \`string\` | URL suffix appended after path. |
77
+ | \`options.headers\` | \`object\` | Custom headers for all requests. |
78
+ | \`options.feature\` | \`object\` | Feature configuration. |
79
+ | \`options.system\` | \`object\` | System overrides (e.g. custom fetch). |
80
+
81
+ `)
82
+
83
+
84
+ Content(`
85
+ ### Static Methods
86
+
87
+ `)
88
+
89
+ Content(`#### \`${model.Name}SDK.test(testopts?, sdkopts?)\`
90
+
91
+ Create a test client with mock features active.
92
+
93
+ \`\`\`ts
94
+ const client = ${model.Name}SDK.test()
95
+ \`\`\`
96
+
97
+ **Parameters:**
98
+
99
+ | Name | Type | Description |
100
+ | --- | --- | --- |
101
+ | \`testopts\` | \`object\` | Test feature options. |
102
+ | \`sdkopts\` | \`object\` | Additional SDK options merged with test defaults. |
103
+
104
+ **Returns:** \`${model.Name}SDK\` instance in test mode.
105
+
106
+ `)
107
+
108
+
109
+ Content(`
110
+ ### Instance Methods
111
+
112
+ `)
113
+
114
+
115
+ // Entity factory methods
116
+ publishedEntities.map((ent: any) => {
117
+ Content(`#### \`${ent.Name}(data?: object)\`
118
+
119
+ Create a new \`${ent.Name}\` entity instance.
120
+
121
+ **Parameters:**
122
+
123
+ | Name | Type | Description |
124
+ | --- | --- | --- |
125
+ | \`data\` | \`object\` | Initial entity data. |
126
+
127
+ **Returns:** \`${ent.Name}Entity\` instance.
128
+
129
+ `)
130
+ })
131
+
132
+
133
+ Content(`#### \`options()\`
134
+
135
+ Return a deep copy of the current SDK options.
136
+
137
+ **Returns:** \`object\`
138
+
139
+ #### \`utility()\`
140
+
141
+ Return a copy of the SDK utility object.
142
+
143
+ **Returns:** \`object\`
144
+
145
+ #### \`direct(fetchargs?: object)\`
146
+
147
+ Make a direct HTTP request to any API endpoint.
148
+
149
+ **Parameters:**
150
+
151
+ | Name | Type | Description |
152
+ | --- | --- | --- |
153
+ | \`fetchargs.path\` | \`string\` | URL path with optional \`{param}\` placeholders. |
154
+ | \`fetchargs.method\` | \`string\` | HTTP method (default: \`GET\`). |
155
+ | \`fetchargs.params\` | \`object\` | Path parameter values for \`{param}\` substitution. |
156
+ | \`fetchargs.query\` | \`object\` | Query string parameters. |
157
+ | \`fetchargs.headers\` | \`object\` | Request headers (merged with defaults). |
158
+ | \`fetchargs.body\` | \`any\` | Request body (objects are JSON-serialized). |
159
+ | \`fetchargs.ctrl\` | \`object\` | Control options (e.g. \`{ explain: true }\`). |
160
+
161
+ **Returns:** \`Promise<{ ok, status, headers, data } | Error>\`
162
+
163
+ #### \`prepare(fetchargs?: object)\`
164
+
165
+ Prepare a fetch definition without sending the request. Accepts the
166
+ same parameters as \`direct()\`.
167
+
168
+ **Returns:** \`Promise<{ url, method, headers, body } | Error>\`
169
+
170
+ #### \`tester(testopts?, sdkopts?)\`
171
+
172
+ Alias for \`${model.Name}SDK.test()\`.
173
+
174
+ **Returns:** \`${model.Name}SDK\` instance in test mode.
175
+
176
+ `)
177
+
178
+
179
+ // Entity reference sections
180
+ publishedEntities.map((ent: any) => {
181
+ const opnames = Object.keys(ent.op || {})
182
+ const fields = ent.fields || []
183
+
184
+ Content(`
185
+ ---
186
+
187
+ ## ${ent.Name}Entity
188
+
189
+ `)
190
+
191
+ if (ent.short) {
192
+ Content(`${ent.short}
193
+
194
+ `)
195
+ }
196
+
197
+ Content(`\`\`\`ts
198
+ const ${ent.name} = client.${ent.Name}()
199
+ \`\`\`
200
+
201
+ `)
202
+
203
+
204
+ // Field schema
205
+ if (fields.length > 0) {
206
+ Content(`### Fields
207
+
208
+ | Field | Type | Required | Description |
209
+ | --- | --- | --- | --- |
210
+ `)
211
+ each(fields, (field: any) => {
212
+ const req = field.req ? 'Yes' : 'No'
213
+ const desc = field.short || ''
214
+ Content(`| \`${field.name}\` | \`${field.type || 'any'}\` | ${req} | ${desc} |
215
+ `)
216
+ })
217
+
218
+ Content(`
219
+ `)
220
+
221
+ // Field operations breakdown
222
+ const hasFieldOps = fields.some((f: any) => f.op && Object.keys(f.op).length > 0)
223
+ if (hasFieldOps) {
224
+ Content(`### Field Usage by Operation
225
+
226
+ | Field | load | list | create | update | remove |
227
+ | --- | --- | --- | --- | --- | --- |
228
+ `)
229
+ each(fields, (field: any) => {
230
+ const fops = field.op || {}
231
+ const cols = ['load', 'list', 'create', 'update', 'remove'].map((op: string) => {
232
+ if (!opnames.includes(op)) return '-'
233
+ const fop = fops[op]
234
+ if (null == fop) return '-'
235
+ if (fop.active === false) return '-'
236
+ return 'Yes'
237
+ })
238
+ Content(`| \`${field.name}\` | ${cols.join(' | ')} |
239
+ `)
240
+ })
241
+
242
+ Content(`
243
+ `)
244
+ }
245
+ }
246
+
247
+
248
+ // Operation details
249
+ if (opnames.length > 0) {
250
+ Content(`### Operations
251
+
252
+ `)
253
+
254
+ opnames.map((opname: string) => {
255
+ const info = OP_SIGNATURES[opname]
256
+ if (!info) return
257
+
258
+ Content(`#### \`${info.sig}\`
259
+
260
+ ${info.desc}
261
+
262
+ `)
263
+
264
+ // Show example
265
+ if ('load' === opname || 'remove' === opname) {
266
+ Content(`\`\`\`ts
267
+ const result = await client.${ent.Name}().${opname}({ id: '${ent.name}_id' })
268
+ \`\`\`
269
+
270
+ `)
271
+ }
272
+ else if ('list' === opname) {
273
+ Content(`\`\`\`ts
274
+ const results = await client.${ent.Name}().${opname}()
275
+ \`\`\`
276
+
277
+ `)
278
+ }
279
+ else if ('create' === opname) {
280
+ Content(`\`\`\`ts
281
+ const result = await client.${ent.Name}().create({
282
+ `)
283
+ each(fields, (field: any) => {
284
+ if ('id' !== field.name && field.req) {
285
+ Content(` ${field.name}: /* ${field.type || 'value'} */,
286
+ `)
287
+ }
288
+ })
289
+ Content(`})
290
+ \`\`\`
291
+
292
+ `)
293
+ }
294
+ else if ('update' === opname) {
295
+ Content(`\`\`\`ts
296
+ const result = await client.${ent.Name}().update({
297
+ id: '${ent.name}_id',
298
+ // Fields to update
299
+ })
300
+ \`\`\`
301
+
302
+ `)
303
+ }
304
+ })
305
+ }
306
+
307
+
308
+ // Common methods
309
+ Content(`### Common Methods
310
+
311
+ #### \`data(data?: object)\`
312
+
313
+ Get or set the entity data. When called with data, sets the entity's
314
+ internal data and returns the current data. When called without
315
+ arguments, returns a copy of the current data.
316
+
317
+ #### \`match(match?: object)\`
318
+
319
+ Get or set the entity match criteria. Works the same as \`data()\`.
320
+
321
+ #### \`make()\`
322
+
323
+ Create a new \`${ent.Name}Entity\` instance with the same client and
324
+ options.
325
+
326
+ #### \`client()\`
327
+
328
+ Return the parent \`${model.Name}SDK\` instance.
329
+
330
+ #### \`entopts()\`
331
+
332
+ Return a copy of the entity options.
333
+
334
+ `)
335
+ })
336
+
337
+
338
+ // Features section
339
+ const activeFeatures = each(feature).filter((f: any) => f.active)
340
+ if (activeFeatures.length > 0) {
341
+ Content(`
342
+ ---
343
+
344
+ ## Features
345
+
346
+ | Feature | Version | Description |
347
+ | --- | --- | --- |
348
+ `)
349
+
350
+ activeFeatures.map((f: any) => {
351
+ Content(`| \`${f.name}\` | ${f.version || '0.0.1'} | ${f.title || ''} |
352
+ `)
353
+ })
354
+
355
+ Content(`
356
+
357
+ Features are activated via the \`feature\` option:
358
+
359
+ `)
360
+
361
+ Content(`\`\`\`ts
362
+ const client = new ${model.Name}SDK({
363
+ feature: {
364
+ `)
365
+ activeFeatures.map((f: any) => {
366
+ Content(` ${f.name}: { active: true },
367
+ `)
368
+ })
369
+ Content(` }
370
+ })
371
+ \`\`\`
372
+
373
+ `)
374
+ }
375
+
376
+ })
377
+ })
378
+
379
+
380
+
381
+
382
+ export {
383
+ ReadmeRef
384
+ }
@@ -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,
@@ -14,12 +14,14 @@ const ReadmeTopQuick = cmp(function ReadmeTopQuick(props: any) {
14
14
  const entity = getModelPath(model, `main.${KIT}.entity`)
15
15
  const exampleEntity = Object.values(entity).find((e: any) => e.active !== false) as any
16
16
 
17
+ const apikeyArg = isAuthActive(model)
18
+ ? `\n apikey: process.env.${model.NAME}_APIKEY,\n`
19
+ : ''
20
+
17
21
  Content(`\`\`\`ts
18
22
  import { ${model.const.Name}SDK } from '${target.module.name}'
19
23
 
20
- const client = new ${model.const.Name}SDK({
21
- apikey: process.env.${model.NAME}_APIKEY,
22
- })
24
+ const client = new ${model.const.Name}SDK({${apikeyArg}})
23
25
 
24
26
  `)
25
27
 
@@ -1,5 +1,8 @@
1
1
 
2
2
  import {
3
+ Model,
4
+ ModelEntity,
5
+ ModelPoint,
3
6
  nom,
4
7
  depluralize,
5
8
  } from '@voxgig/apidef'
@@ -13,6 +16,7 @@ import {
13
16
  Slot,
14
17
  cmp,
15
18
  snakify,
19
+ isAuthActive,
16
20
  } from '@voxgig/sdkgen'
17
21
 
18
22
 
@@ -23,16 +27,25 @@ import {
23
27
 
24
28
  const TestDirect = cmp(function TestDirect(props: any) {
25
29
  const ctx$ = props.ctx$
26
- const model = ctx$.model
30
+ const model: Model = ctx$.model
27
31
  const stdrep = ctx$.stdrep
28
32
 
29
33
  const target = props.target
30
- const entity = props.entity
34
+ const entity: ModelEntity = props.entity
31
35
 
32
36
  const ff = projectPath('src/cmp/ts/fragment/')
33
37
 
34
- const PROJECTNAME = model.Name.toUpperCase().replace(/[^A-Z_]/g, '_')
35
- const entidEnvVar = `${PROJECTNAME}_TEST_${entity.Name.toUpperCase().replace(/[^A-Z_]/g, '_')}_ENTID`
38
+ const PROJECTNAME = nom(model, 'Name').toUpperCase().replace(/[^A-Z_]/g, '_')
39
+ const entidEnvVar = `${PROJECTNAME}_TEST_${nom(entity, 'NAME').replace(/[^A-Z_]/g, '_')}_ENTID`
40
+
41
+ const authActive = isAuthActive(model)
42
+ const apikeyEnvEntry = authActive
43
+ ? `\n '${PROJECTNAME}_APIKEY': 'NONE',`
44
+ : ''
45
+ const apikeyLiveField = authActive
46
+ ? `
47
+ apikey: env.${PROJECTNAME}_APIKEY,`
48
+ : ''
36
49
 
37
50
  const opnames = Object.keys(entity.op)
38
51
  const hasLoad = opnames.includes('load')
@@ -64,15 +77,13 @@ function directSetup(mockres?: any) {
64
77
 
65
78
  const env = envOverride({
66
79
  '${entidEnvVar}': {},
67
- '${PROJECTNAME}_TEST_LIVE': 'FALSE',
68
- '${PROJECTNAME}_APIKEY': 'NONE',
80
+ '${PROJECTNAME}_TEST_LIVE': 'FALSE',${apikeyEnvEntry}
69
81
  })
70
82
 
71
83
  const live = 'TRUE' === env.${PROJECTNAME}_TEST_LIVE
72
84
 
73
85
  if (live) {
74
- const client = new ${nom(model.const, 'Name')}SDK({
75
- apikey: env.${PROJECTNAME}_APIKEY,
86
+ const client = new ${nom(model.const, 'Name')}SDK({${apikeyLiveField}
76
87
  })
77
88
 
78
89
  let idmap: any = env['${entidEnvVar}']
@@ -121,9 +132,9 @@ function directSetup(mockres?: any) {
121
132
  })
122
133
 
123
134
 
124
- function generateDirectLoad(model: any, entity: any) {
135
+ function generateDirectLoad(model: Model, entity: ModelEntity) {
125
136
  const loadOp = entity.op.load
126
- const loadPoint = loadOp?.points?.[0]
137
+ const loadPoint: ModelPoint | undefined = loadOp?.points?.[0]
127
138
 
128
139
  if (null == loadPoint) {
129
140
  return
@@ -132,6 +143,19 @@ function generateDirectLoad(model: any, entity: any) {
132
143
  const loadParams = loadPoint.args?.params || []
133
144
  const loadPath = normalizePathParams(loadPoint.parts || [], loadParams, loadPoint.rename?.param)
134
145
 
146
+ // Required query params that the spec advertises an example value for.
147
+ // Live mode needs these on the request or the API returns 4xx; mock mode
148
+ // ignores them. Optional query params (e.g. `app`, `version`) are skipped
149
+ // even when they have examples — only the strictly required ones are
150
+ // necessary to satisfy the contract.
151
+ const loadQuery = loadPoint.args?.query || []
152
+ const liveQueryEntries = loadQuery
153
+ .filter((q: any) => q.reqd && undefined !== q.example && null !== q.example)
154
+ const hasLiveQuery = liveQueryEntries.length > 0
155
+ const liveQueryLines = liveQueryEntries
156
+ .map((q: any) => ` query.${q.name} = ${JSON.stringify(q.example)}`)
157
+ .join('\n')
158
+
135
159
  // Get list info for live mode bootstrapping
136
160
  const listOp = entity.op.list
137
161
  const listPoint = listOp?.points?.[0]
@@ -159,6 +183,10 @@ function generateDirectLoad(model: any, entity: any) {
159
183
  return { name: p.name, key }
160
184
  })
161
185
 
186
+ // Prefix the live block with required-query setup so it applies to both
187
+ // the list-bootstrapped and the no-list cases.
188
+ const liveQueryPrefix = liveQueryLines ? liveQueryLines + '\n' : ''
189
+
162
190
  let liveParamsBlock = ''
163
191
  if (hasList) {
164
192
  const listParamLines = liveListParams.map((lp: any) =>
@@ -167,7 +195,7 @@ function generateDirectLoad(model: any, entity: any) {
167
195
  ` params.${lp.name} = setup.idmap['${lp.key}']`).join('\n')
168
196
 
169
197
  liveParamsBlock = ` if (setup.live) {
170
- const listResult: any = await client.direct({
198
+ ${liveQueryPrefix} const listResult: any = await client.direct({
171
199
  path: '${listPath}',
172
200
  method: 'GET',
173
201
  params: {
@@ -184,10 +212,14 @@ ${ancestorParamLines}
184
212
  } else {
185
213
  ${loadParams.map((p: any, i: number) => ` params.${p.name} = 'direct0${i + 1}'`).join('\n')}
186
214
  }`
187
- } else {
188
- liveParamsBlock = ` if (!setup.live) {
215
+ } else if (hasLiveQuery || loadParams.length > 0) {
216
+ liveParamsBlock = ` if (setup.live) {
217
+ ${liveQueryPrefix.replace(/\n$/, '')}
218
+ } else {
189
219
  ${loadParams.map((p: any, i: number) => ` params.${p.name} = 'direct0${i + 1}'`).join('\n')}
190
220
  }`
221
+ } else {
222
+ liveParamsBlock = ''
191
223
  }
192
224
 
193
225
  Content(`
@@ -196,12 +228,14 @@ ${loadParams.map((p: any, i: number) => ` params.${p.name} = 'direct0${i +
196
228
  const { client, calls } = setup
197
229
 
198
230
  const params: any = {}
231
+ const query: any = {}
199
232
  ${liveParamsBlock}
200
233
 
201
234
  const result: any = await client.direct({
202
235
  path: '${loadPath}',
203
236
  method: 'GET',
204
237
  params,
238
+ query,
205
239
  })
206
240
 
207
241
  assert(result.ok === true)
@@ -218,9 +252,9 @@ ${paramAsserts} }
218
252
  }
219
253
 
220
254
 
221
- function generateDirectList(model: any, entity: any) {
255
+ function generateDirectList(model: Model, entity: ModelEntity) {
222
256
  const listOp = entity.op.list
223
- const listPoint = listOp?.points?.[0]
257
+ const listPoint: ModelPoint | undefined = listOp?.points?.[0]
224
258
 
225
259
  if (null == listPoint) {
226
260
  return
@@ -229,6 +263,14 @@ function generateDirectList(model: any, entity: any) {
229
263
  const listParams = listPoint.args?.params || []
230
264
  const listPath = normalizePathParams(listPoint.parts || [], listParams, listPoint.rename?.param)
231
265
 
266
+ // Required query params with spec-provided examples — needed to satisfy
267
+ // the API contract in live mode (see generateDirectLoad for rationale).
268
+ const listQuery = listPoint.args?.query || []
269
+ const liveQueryLines = listQuery
270
+ .filter((q: any) => q.reqd && undefined !== q.example && null !== q.example)
271
+ .map((q: any) => ` query.${q.name} = ${JSON.stringify(q.example)}`)
272
+ .join('\n')
273
+
232
274
  // Build live params
233
275
  const liveParams = listParams.map((p: any) => {
234
276
  const key = p.name === 'id'
@@ -241,21 +283,26 @@ function generateDirectList(model: any, entity: any) {
241
283
  ' assert(calls[0].url.includes(\'direct0' + (i + 1) + '\'))\n').join('')
242
284
 
243
285
  let paramsBlock = ''
244
- if (listParams.length > 0) {
245
- const liveLines = liveParams.map((lp: any) =>
246
- ` params.${lp.name} = setup.idmap['${lp.key}']`).join('\n')
286
+ if (listParams.length > 0 || liveQueryLines) {
287
+ const liveLines = [
288
+ liveQueryLines,
289
+ liveParams.map((lp: any) =>
290
+ ` params.${lp.name} = setup.idmap['${lp.key}']`).join('\n'),
291
+ ].filter(Boolean).join('\n')
247
292
  const mockLines = listParams.map((p: any, i: number) =>
248
293
  ` params.${p.name} = 'direct0${i + 1}'`).join('\n')
249
294
 
250
295
  paramsBlock = ` const params: any = {}
296
+ const query: any = {}
251
297
  if (setup.live) {
252
298
  ${liveLines}
253
- } else {
299
+ }${mockLines ? ` else {
254
300
  ${mockLines}
255
- }
301
+ }` : ''}
256
302
  `
257
303
  } else {
258
304
  paramsBlock = ` const params: any = {}
305
+ const query: any = {}
259
306
  `
260
307
  }
261
308
 
@@ -269,6 +316,7 @@ ${paramsBlock}
269
316
  path: '${listPath}',
270
317
  method: 'GET',
271
318
  params,
319
+ query,
272
320
  })
273
321
 
274
322
  assert(result.ok === true)