@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.
- package/bin/voxgig-sdkgen +1 -1
- package/dist/cmp/ReadmeEntity.js +9 -153
- package/dist/cmp/ReadmeEntity.js.map +1 -1
- package/dist/cmp/ReadmeIntro.js +9 -14
- package/dist/cmp/ReadmeIntro.js.map +1 -1
- package/dist/cmp/ReadmeModel.js +6 -4
- package/dist/cmp/ReadmeModel.js.map +1 -1
- package/dist/cmp/ReadmeOptions.js +9 -61
- package/dist/cmp/ReadmeOptions.js.map +1 -1
- package/dist/cmp/ReadmeRef.js +10 -1328
- package/dist/cmp/ReadmeRef.js.map +1 -1
- package/dist/sdkgen.d.ts +2 -2
- package/dist/sdkgen.js +2 -1
- package/dist/sdkgen.js.map +1 -1
- package/dist/utility.d.ts +2 -1
- package/dist/utility.js +9 -0
- package/dist/utility.js.map +1 -1
- package/package.json +1 -1
- package/project/.sdk/src/cmp/go/Config_go.ts +9 -4
- package/project/.sdk/src/cmp/go/Gitignore_go.ts +47 -0
- package/project/.sdk/src/cmp/go/Main_go.ts +3 -0
- package/project/.sdk/src/cmp/go/ReadmeEntity_go.ts +138 -0
- package/project/.sdk/src/cmp/go/ReadmeHowto_go.ts +6 -3
- package/project/.sdk/src/cmp/go/ReadmeIntro_go.ts +18 -0
- package/project/.sdk/src/cmp/go/ReadmeModel_go.ts +6 -3
- package/project/.sdk/src/cmp/go/ReadmeOptions_go.ts +58 -0
- package/project/.sdk/src/cmp/go/ReadmeQuick_go.ts +11 -7
- package/project/.sdk/src/cmp/go/ReadmeRef_go.ts +354 -0
- package/project/.sdk/src/cmp/go/ReadmeTopQuick_go.ts +6 -4
- package/project/.sdk/src/cmp/go/TestDirect_go.ts +18 -8
- package/project/.sdk/src/cmp/go/TestEntity_go.ts +105 -54
- package/project/.sdk/src/cmp/js/Config_js.ts +18 -0
- package/project/.sdk/src/cmp/js/Gitignore_js.ts +35 -0
- package/project/.sdk/src/cmp/js/Main_js.ts +3 -0
- package/project/.sdk/src/cmp/js/ReadmeEntity_js.ts +138 -0
- package/project/.sdk/src/cmp/js/ReadmeHowto_js.ts +11 -6
- package/project/.sdk/src/cmp/js/ReadmeIntro_js.ts +18 -0
- package/project/.sdk/src/cmp/js/ReadmeModel_js.ts +6 -3
- package/project/.sdk/src/cmp/js/ReadmeOptions_js.ts +58 -0
- package/project/.sdk/src/cmp/js/ReadmeQuick_js.ts +6 -4
- package/project/.sdk/src/cmp/js/ReadmeRef_js.ts +384 -0
- package/project/.sdk/src/cmp/js/ReadmeTopQuick_js.ts +6 -4
- package/project/.sdk/src/cmp/js/TestDirect_js.ts +23 -12
- package/project/.sdk/src/cmp/js/TestEntity_js.ts +107 -74
- package/project/.sdk/src/cmp/js/fragment/Config.fragment.js +1 -5
- package/project/.sdk/src/cmp/lua/Config_lua.ts +9 -4
- package/project/.sdk/src/cmp/lua/Gitignore_lua.ts +39 -0
- package/project/.sdk/src/cmp/lua/Main_lua.ts +3 -0
- package/project/.sdk/src/cmp/lua/ReadmeEntity_lua.ts +138 -0
- package/project/.sdk/src/cmp/lua/ReadmeHowto_lua.ts +6 -3
- package/project/.sdk/src/cmp/lua/ReadmeIntro_lua.ts +18 -0
- package/project/.sdk/src/cmp/lua/ReadmeModel_lua.ts +6 -3
- package/project/.sdk/src/cmp/lua/ReadmeOptions_lua.ts +58 -0
- package/project/.sdk/src/cmp/lua/ReadmeQuick_lua.ts +6 -4
- package/project/.sdk/src/cmp/lua/ReadmeRef_lua.ts +360 -0
- package/project/.sdk/src/cmp/lua/ReadmeTopQuick_lua.ts +6 -4
- package/project/.sdk/src/cmp/lua/TestDirect_lua.ts +18 -8
- package/project/.sdk/src/cmp/lua/TestEntity_lua.ts +95 -51
- package/project/.sdk/src/cmp/php/Config_php.ts +10 -8
- package/project/.sdk/src/cmp/php/Gitignore_php.ts +33 -0
- package/project/.sdk/src/cmp/php/Main_php.ts +3 -0
- package/project/.sdk/src/cmp/php/ReadmeEntity_php.ts +138 -0
- package/project/.sdk/src/cmp/php/ReadmeHowto_php.ts +6 -3
- package/project/.sdk/src/cmp/php/ReadmeIntro_php.ts +18 -0
- package/project/.sdk/src/cmp/php/ReadmeModel_php.ts +6 -3
- package/project/.sdk/src/cmp/php/ReadmeOptions_php.ts +58 -0
- package/project/.sdk/src/cmp/php/ReadmeQuick_php.ts +6 -4
- package/project/.sdk/src/cmp/php/ReadmeRef_php.ts +358 -0
- package/project/.sdk/src/cmp/php/ReadmeTopQuick_php.ts +6 -4
- package/project/.sdk/src/cmp/php/TestDirect_php.ts +18 -8
- package/project/.sdk/src/cmp/php/TestEntity_php.ts +101 -54
- package/project/.sdk/src/cmp/py/Config_py.ts +9 -4
- package/project/.sdk/src/cmp/py/Gitignore_py.ts +55 -0
- package/project/.sdk/src/cmp/py/Main_py.ts +3 -0
- package/project/.sdk/src/cmp/py/ReadmeEntity_py.ts +138 -0
- package/project/.sdk/src/cmp/py/ReadmeHowto_py.ts +6 -3
- package/project/.sdk/src/cmp/py/ReadmeIntro_py.ts +18 -0
- package/project/.sdk/src/cmp/py/ReadmeModel_py.ts +6 -3
- package/project/.sdk/src/cmp/py/ReadmeOptions_py.ts +58 -0
- package/project/.sdk/src/cmp/py/ReadmeQuick_py.ts +9 -6
- package/project/.sdk/src/cmp/py/ReadmeRef_py.ts +356 -0
- package/project/.sdk/src/cmp/py/ReadmeTopQuick_py.ts +9 -6
- package/project/.sdk/src/cmp/py/TestDirect_py.ts +18 -8
- package/project/.sdk/src/cmp/py/TestEntity_py.ts +100 -50
- package/project/.sdk/src/cmp/rb/Config_rb.ts +9 -4
- package/project/.sdk/src/cmp/rb/Gitignore_rb.ts +38 -0
- package/project/.sdk/src/cmp/rb/Main_rb.ts +3 -0
- package/project/.sdk/src/cmp/rb/ReadmeEntity_rb.ts +138 -0
- package/project/.sdk/src/cmp/rb/ReadmeHowto_rb.ts +6 -3
- package/project/.sdk/src/cmp/rb/ReadmeIntro_rb.ts +18 -0
- package/project/.sdk/src/cmp/rb/ReadmeModel_rb.ts +6 -3
- package/project/.sdk/src/cmp/rb/ReadmeOptions_rb.ts +58 -0
- package/project/.sdk/src/cmp/rb/ReadmeQuick_rb.ts +6 -4
- package/project/.sdk/src/cmp/rb/ReadmeRef_rb.ts +361 -0
- package/project/.sdk/src/cmp/rb/ReadmeTopQuick_rb.ts +6 -4
- package/project/.sdk/src/cmp/rb/TestDirect_rb.ts +18 -8
- package/project/.sdk/src/cmp/rb/TestEntity_rb.ts +95 -51
- package/project/.sdk/src/cmp/ts/Config_ts.ts +18 -0
- package/project/.sdk/src/cmp/ts/Gitignore_ts.ts +37 -0
- package/project/.sdk/src/cmp/ts/Main_ts.ts +3 -0
- package/project/.sdk/src/cmp/ts/ReadmeEntity_ts.ts +138 -0
- package/project/.sdk/src/cmp/ts/ReadmeHowto_ts.ts +11 -6
- package/project/.sdk/src/cmp/ts/ReadmeIntro_ts.ts +18 -0
- package/project/.sdk/src/cmp/ts/ReadmeModel_ts.ts +9 -5
- package/project/.sdk/src/cmp/ts/ReadmeOptions_ts.ts +58 -0
- package/project/.sdk/src/cmp/ts/ReadmeQuick_ts.ts +6 -4
- package/project/.sdk/src/cmp/ts/ReadmeRef_ts.ts +384 -0
- package/project/.sdk/src/cmp/ts/ReadmeTopQuick_ts.ts +6 -4
- package/project/.sdk/src/cmp/ts/TestDirect_ts.ts +68 -20
- package/project/.sdk/src/cmp/ts/TestEntity_ts.ts +109 -74
- package/project/.sdk/src/cmp/ts/fragment/Config.fragment.ts +1 -5
- package/project/.sdk/tm/go/utility/prepare_auth.go +15 -1
- package/project/.sdk/tm/js/src/utility/PrepareAuthUtility.js +7 -1
- package/project/.sdk/tm/lua/utility/prepare_auth.lua +9 -1
- package/project/.sdk/tm/php/utility/PrepareAuth.php +11 -1
- package/project/.sdk/tm/py/utility/prepare_auth.py +10 -1
- package/project/.sdk/tm/rb/utility/prepare_auth.rb +8 -1
- package/project/.sdk/tm/ts/src/utility/MakeUrlUtility.ts +7 -8
- package/project/.sdk/tm/ts/src/utility/PrepareAuthUtility.ts +7 -1
- package/src/cmp/ReadmeEntity.ts +11 -178
- package/src/cmp/ReadmeIntro.ts +11 -25
- package/src/cmp/ReadmeModel.ts +7 -5
- package/src/cmp/ReadmeOptions.ts +12 -74
- package/src/cmp/ReadmeRef.ts +11 -1372
- package/src/sdkgen.ts +2 -1
- package/src/utility.ts +12 -0
- /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
|
|
35
|
-
const entidEnvVar = `${PROJECTNAME}_TEST_${entity
|
|
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:
|
|
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 (
|
|
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:
|
|
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 =
|
|
246
|
-
|
|
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)
|