@voxgig/sdkgen 0.36.0 → 0.37.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/Main.js +0 -12
- package/dist/cmp/Main.js.map +1 -1
- package/package.json +1 -1
- package/project/.sdk/src/cmp/go/Config_go.ts +6 -2
- package/project/.sdk/src/cmp/js/EntityBase_js.ts +34 -0
- package/project/.sdk/src/cmp/js/Main_js.ts +10 -0
- package/project/.sdk/src/cmp/js/ReadmeExplanation_js.ts +33 -0
- package/project/.sdk/src/cmp/js/ReadmeHowto_js.ts +123 -0
- package/project/.sdk/src/cmp/js/ReadmeModel_js.ts +152 -0
- package/project/.sdk/src/cmp/js/ReadmeTopHowto_js.ts +25 -0
- package/project/.sdk/src/cmp/js/ReadmeTopQuick_js.ts +65 -0
- package/project/.sdk/src/cmp/js/ReadmeTopTest_js.ts +36 -0
- package/project/.sdk/src/cmp/js/TestDirect_js.ts +53 -5
- package/project/.sdk/src/cmp/js/TestEntity_js.ts +114 -20
- package/project/.sdk/src/cmp/js/fragment/Entity.fragment.js +7 -139
- package/project/.sdk/src/cmp/js/fragment/EntityBase.fragment.js +149 -0
- package/project/.sdk/src/cmp/js/fragment/EntityCreateOp.fragment.js +6 -10
- package/project/.sdk/src/cmp/js/fragment/EntityListOp.fragment.js +6 -10
- package/project/.sdk/src/cmp/js/fragment/EntityLoadOp.fragment.js +7 -11
- package/project/.sdk/src/cmp/js/fragment/EntityRemoveOp.fragment.js +7 -11
- package/project/.sdk/src/cmp/js/fragment/EntityUpdateOp.fragment.js +7 -11
- package/project/.sdk/src/cmp/js/fragment/Main.fragment.js +2 -0
- package/project/.sdk/src/cmp/js/fragment/SdkError.fragment.js +0 -2
- package/project/.sdk/src/cmp/lua/Config_lua.ts +6 -2
- package/project/.sdk/src/cmp/lua/TestEntity_lua.ts +3 -1
- package/project/.sdk/src/cmp/php/Config_php.ts +6 -2
- package/project/.sdk/src/cmp/php/TestDirect_php.ts +2 -2
- package/project/.sdk/src/cmp/php/TestEntity_php.ts +10 -15
- package/project/.sdk/src/cmp/py/Config_py.ts +6 -2
- package/project/.sdk/src/cmp/py/TestEntity_py.ts +3 -1
- package/project/.sdk/src/cmp/rb/Config_rb.ts +6 -2
- package/project/.sdk/src/cmp/ts/Main_ts.ts +7 -0
- package/project/.sdk/tm/go/feature/log_feature.go +1 -1
- package/project/.sdk/tm/go/test/runner_test.go +16 -2
- package/project/.sdk/tm/js/src/Context.js +142 -0
- package/project/.sdk/tm/js/src/Control.js +16 -0
- package/project/.sdk/tm/js/src/Operation.js +19 -0
- package/project/.sdk/tm/js/src/Point.js +24 -0
- package/project/.sdk/tm/js/src/README.md +1 -0
- package/project/.sdk/tm/js/src/Response.js +19 -0
- package/project/.sdk/tm/js/src/Result.js +21 -0
- package/project/.sdk/tm/js/src/Spec.js +26 -0
- package/project/.sdk/tm/js/src/feature/README.md +1 -0
- package/project/.sdk/tm/js/src/feature/base/BaseFeature.js +45 -0
- package/project/.sdk/tm/js/src/feature/log/LogFeature.js +46 -47
- package/project/.sdk/tm/js/src/feature/test/TestFeature.js +207 -0
- package/project/.sdk/tm/js/src/types.js +22 -0
- package/project/.sdk/tm/js/src/utility/CleanUtility.js +31 -0
- package/project/.sdk/tm/js/src/utility/DoneUtility.js +11 -4
- package/project/.sdk/tm/js/src/utility/FeatureAddUtility.js +42 -0
- package/project/.sdk/tm/js/src/utility/FeatureHookUtility.js +25 -0
- package/project/.sdk/tm/js/src/utility/FeatureInitUtility.js +11 -0
- package/project/.sdk/tm/js/src/utility/FetcherUtility.js +28 -0
- package/project/.sdk/tm/js/src/utility/MakeContextUtility.js +11 -0
- package/project/.sdk/tm/js/src/utility/MakeErrorUtility.js +55 -0
- package/project/.sdk/tm/js/src/utility/MakeFetchDefUtility.js +44 -0
- package/project/.sdk/tm/js/src/utility/MakeOptionsUtility.js +93 -0
- package/project/.sdk/tm/js/src/utility/MakePointUtility.js +77 -0
- package/project/.sdk/tm/js/src/utility/MakeRequestUtility.js +63 -0
- package/project/.sdk/tm/js/src/utility/MakeResponseUtility.js +55 -0
- package/project/.sdk/tm/js/src/utility/MakeResultUtility.js +54 -0
- package/project/.sdk/tm/js/src/utility/MakeSpecUtility.js +58 -0
- package/project/.sdk/tm/js/src/utility/MakeUrlUtility.js +40 -0
- package/project/.sdk/tm/js/src/utility/ParamUtility.js +61 -0
- package/project/.sdk/tm/js/src/utility/PrepareAuthUtility.js +41 -0
- package/project/.sdk/tm/js/src/utility/PrepareBodyUtility.js +25 -0
- package/project/.sdk/tm/js/src/utility/PrepareHeadersUtility.js +18 -0
- package/project/.sdk/tm/js/src/utility/{MethodUtility.js → PrepareMethodUtility.js} +7 -7
- package/project/.sdk/tm/js/src/utility/PrepareParamsUtility.js +25 -0
- package/project/.sdk/tm/js/src/utility/PreparePathUtility.js +13 -0
- package/project/.sdk/tm/js/src/utility/PrepareQueryUtility.js +26 -0
- package/project/.sdk/tm/js/src/utility/README.md +1 -0
- package/project/.sdk/tm/js/src/utility/ResultBasicUtility.js +34 -0
- package/project/.sdk/tm/js/src/utility/ResultBodyUtility.js +18 -0
- package/project/.sdk/tm/js/src/utility/ResultHeadersUtility.js +22 -0
- package/project/.sdk/tm/js/src/utility/StructUtility.js +2219 -1078
- package/project/.sdk/tm/js/src/utility/TransformRequestUtility.js +28 -0
- package/project/.sdk/tm/js/src/utility/TransformResponseUtility.js +31 -0
- package/project/.sdk/tm/js/src/utility/Utility.js +61 -61
- package/project/.sdk/tm/js/test/README.md +1 -0
- package/project/.sdk/tm/js/test/exists.test.js +16 -0
- package/project/.sdk/tm/js/test/runner.js +323 -107
- package/project/.sdk/tm/js/test/utility/Custom.test.js +41 -63
- package/project/.sdk/tm/js/test/utility/PrimaryUtility.test.js +390 -116
- package/project/.sdk/tm/js/test/utility/StructUtility.test.js +728 -175
- package/project/.sdk/tm/js/test/utility/index.js +9 -0
- package/project/.sdk/tm/js/test/utility.js +72 -0
- package/project/.sdk/tm/lua/test/primary_utility_test.lua +1213 -0
- package/project/.sdk/tm/lua/test/runner.lua +2 -2
- package/project/.sdk/tm/lua/test/struct_runner.lua +602 -0
- package/project/.sdk/tm/lua/test/struct_utility_test.lua +959 -0
- package/project/.sdk/tm/lua/utility/struct/struct.lua +10 -0
- package/project/.sdk/tm/php/feature/TestFeature.php +59 -96
- package/project/.sdk/tm/php/test/PrimaryUtilityTest.php +1309 -0
- package/project/.sdk/tm/php/test/Runner.php +24 -1
- package/project/.sdk/tm/php/test/StructRunner.php +275 -0
- package/project/.sdk/tm/php/test/StructUtilityTest.php +1336 -0
- package/project/.sdk/tm/php/utility/Fetcher.php +6 -2
- package/project/.sdk/tm/php/utility/MakeOptions.php +5 -1
- package/project/.sdk/tm/php/utility/MakeResult.php +3 -0
- package/project/.sdk/tm/php/utility/Param.php +9 -7
- package/project/.sdk/tm/php/utility/struct/Struct.php +312 -208
- package/project/.sdk/tm/py/test/runner.py +13 -0
- package/project/.sdk/tm/py/test/struct_runner.py +411 -0
- package/project/.sdk/tm/py/test/test_primary_utility.py +1101 -0
- package/project/.sdk/tm/py/test/test_struct_utility.py +751 -0
- package/project/.sdk/tm/rb/test/primary_utility_test.rb +1083 -0
- package/project/.sdk/tm/rb/test/runner.rb +5 -0
- package/project/.sdk/tm/rb/test/struct_runner.rb +309 -0
- package/project/.sdk/tm/rb/test/struct_utility_test.rb +670 -0
- package/src/cmp/Main.ts +1 -16
- package/project/.sdk/src/cmp/js/Quick_js.ts +0 -78
- package/project/.sdk/src/cmp/js/TestAcceptEntity_js.ts +0 -13
- package/project/.sdk/src/cmp/js/TestAccept_js.ts +0 -18
- package/project/.sdk/tm/js/src/utility/AuthUtility.js +0 -21
- package/project/.sdk/tm/js/src/utility/BodyUtility.js +0 -29
- package/project/.sdk/tm/js/src/utility/ErrorUtility.js +0 -33
- package/project/.sdk/tm/js/src/utility/FindparamUtility.js +0 -31
- package/project/.sdk/tm/js/src/utility/FullurlUtility.js +0 -39
- package/project/.sdk/tm/js/src/utility/HeadersUtility.js +0 -13
- package/project/.sdk/tm/js/src/utility/JoinurlUtility.js +0 -14
- package/project/.sdk/tm/js/src/utility/OperatorUtility.js +0 -44
- package/project/.sdk/tm/js/src/utility/OptionsUtility.js +0 -54
- package/project/.sdk/tm/js/src/utility/ParamsUtility.js +0 -21
- package/project/.sdk/tm/js/src/utility/QueryUtility.js +0 -21
- package/project/.sdk/tm/js/src/utility/ReqformUtility.js +0 -32
- package/project/.sdk/tm/js/src/utility/RequestUtility.js +0 -48
- package/project/.sdk/tm/js/src/utility/ResbasicUtility.js +0 -27
- package/project/.sdk/tm/js/src/utility/ResbodyUtility.js +0 -15
- package/project/.sdk/tm/js/src/utility/ResformUtility.js +0 -34
- package/project/.sdk/tm/js/src/utility/ResheadersUtility.js +0 -19
- package/project/.sdk/tm/js/src/utility/ResponseUtility.js +0 -37
- package/project/.sdk/tm/js/src/utility/ResultUtility.js +0 -28
- package/project/.sdk/tm/js/src/utility/SpecUtility.js +0 -35
package/bin/voxgig-sdkgen
CHANGED
package/dist/cmp/Main.js
CHANGED
|
@@ -6,18 +6,6 @@ const utility_1 = require("../utility");
|
|
|
6
6
|
const Main = (0, jostraca_1.cmp)(function Main(props) {
|
|
7
7
|
const { target, ctx$ } = props;
|
|
8
8
|
const { model, stdrep, log } = ctx$;
|
|
9
|
-
const copyOpts = {
|
|
10
|
-
// This folder is relative to the .sdk folder in the project, as that is where
|
|
11
|
-
// the sdk is generated from.
|
|
12
|
-
from: 'tm/' + target.name,
|
|
13
|
-
replace: {
|
|
14
|
-
...stdrep,
|
|
15
|
-
}
|
|
16
|
-
};
|
|
17
|
-
if (false === target.srcfeature) {
|
|
18
|
-
copyOpts.exclude = [/src\//];
|
|
19
|
-
}
|
|
20
|
-
(0, jostraca_1.Copy)(copyOpts);
|
|
21
9
|
const Main_sdk = (0, utility_1.requirePath)(ctx$, `cmp/${target.name}/Main_${target.name}`);
|
|
22
10
|
Main_sdk['Main']({ model, target, stdrep });
|
|
23
11
|
log.info({ point: 'generate-main', target, note: 'target:' + target.name });
|
package/dist/cmp/Main.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Main.js","sourceRoot":"","sources":["../../src/cmp/Main.ts"],"names":[],"mappings":";;;AACA,
|
|
1
|
+
{"version":3,"file":"Main.js","sourceRoot":"","sources":["../../src/cmp/Main.ts"],"names":[],"mappings":";;;AACA,uCAAqC;AAErC,wCAAwC;AAOxC,MAAM,IAAI,GAAG,IAAA,cAAG,EAAC,SAAS,IAAI,CAAC,KAAU;IACvC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,KAAK,CAAA;IAC9B,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,IAAI,CAAA;IAEnC,MAAM,QAAQ,GAAG,IAAA,qBAAW,EAAC,IAAI,EAAE,OAAO,MAAM,CAAC,IAAI,SAAS,MAAM,CAAC,IAAI,EAAE,CAAC,CAAA;IAE5E,QAAQ,CAAC,MAAM,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAA;IAE3C,GAAG,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,eAAe,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,CAAA;AAC7E,CAAC,CAAC,CAAA;AAIA,oBAAI"}
|
package/package.json
CHANGED
|
@@ -36,8 +36,12 @@ const Config = cmp(async function Config(props: any) {
|
|
|
36
36
|
const feature = getModelPath(model, `main.${KIT}.feature`)
|
|
37
37
|
|
|
38
38
|
const headers = getModelPath(model, `main.${KIT}.config.headers`) || {}
|
|
39
|
-
|
|
40
|
-
|
|
39
|
+
|
|
40
|
+
let authPrefix = ''
|
|
41
|
+
try { authPrefix = getModelPath(model, `main.${KIT}.config.auth.prefix`) } catch (_e) { }
|
|
42
|
+
|
|
43
|
+
let baseUrl = ''
|
|
44
|
+
try { baseUrl = getModelPath(model, `main.${KIT}.info.servers.0.url`) } catch (_e) { }
|
|
41
45
|
|
|
42
46
|
// Config is now in core/ package
|
|
43
47
|
File({ name: 'config.' + target.ext }, () => {
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
|
|
2
|
+
import * as Path from 'node:path'
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
cmp,
|
|
6
|
+
File, Folder, Fragment,
|
|
7
|
+
} from '@voxgig/sdkgen'
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
const EntityBase = cmp(async function EntityBase(props: any) {
|
|
12
|
+
|
|
13
|
+
// Needs type: target object
|
|
14
|
+
const { target } = props
|
|
15
|
+
const { model } = props.ctx$
|
|
16
|
+
|
|
17
|
+
File({ name: model.const.Name + 'EntityBase.' + target.name }, () => {
|
|
18
|
+
|
|
19
|
+
Fragment(
|
|
20
|
+
{
|
|
21
|
+
from:
|
|
22
|
+
Path.normalize(__dirname + '/../../../src/cmp/js/fragment/EntityBase.fragment.js'),
|
|
23
|
+
|
|
24
|
+
replace: {
|
|
25
|
+
...props.ctx$.stdrep,
|
|
26
|
+
}
|
|
27
|
+
})
|
|
28
|
+
})
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
export {
|
|
33
|
+
EntityBase
|
|
34
|
+
}
|
|
@@ -22,6 +22,7 @@ import { Package } from './Package_js'
|
|
|
22
22
|
import { Config } from './Config_js'
|
|
23
23
|
import { MainEntity } from './MainEntity_js'
|
|
24
24
|
import { SdkError } from './SdkError_js'
|
|
25
|
+
import { EntityBase } from './EntityBase_js'
|
|
25
26
|
|
|
26
27
|
|
|
27
28
|
const Main = cmp(async function Main(props: any) {
|
|
@@ -35,6 +36,13 @@ const Main = cmp(async function Main(props: any) {
|
|
|
35
36
|
|
|
36
37
|
Package({ target })
|
|
37
38
|
|
|
39
|
+
Copy({
|
|
40
|
+
from: 'tm/' + target.name,
|
|
41
|
+
replace: {
|
|
42
|
+
...props.ctx$.stdrep,
|
|
43
|
+
}
|
|
44
|
+
})
|
|
45
|
+
|
|
38
46
|
Folder({ name: 'src' }, () => {
|
|
39
47
|
|
|
40
48
|
SdkError({ target })
|
|
@@ -88,6 +96,8 @@ if (fres instanceof Promise) { await fres }
|
|
|
88
96
|
|
|
89
97
|
Config({ target })
|
|
90
98
|
|
|
99
|
+
EntityBase({ target })
|
|
100
|
+
|
|
91
101
|
})
|
|
92
102
|
})
|
|
93
103
|
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
|
|
2
|
+
import { cmp, Content } from '@voxgig/sdkgen'
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
const ReadmeExplanation = cmp(function ReadmeExplanation(props: any) {
|
|
6
|
+
const { target, ctx$: { model } } = props
|
|
7
|
+
|
|
8
|
+
Content(`### Module structure
|
|
9
|
+
|
|
10
|
+
\`\`\`
|
|
11
|
+
${model.name}/
|
|
12
|
+
├── src/
|
|
13
|
+
│ ├── ${model.Name}SDK.js # Main SDK class
|
|
14
|
+
│ ├── entity/ # Entity implementations
|
|
15
|
+
│ ├── feature/ # Built-in features (Base, Test, Log)
|
|
16
|
+
│ └── utility/ # Utility functions
|
|
17
|
+
└── test/ # Test suites
|
|
18
|
+
\`\`\`
|
|
19
|
+
|
|
20
|
+
Import the SDK from the package root:
|
|
21
|
+
|
|
22
|
+
\`\`\`js
|
|
23
|
+
const { ${model.Name}SDK } = require('${model.name}')
|
|
24
|
+
\`\`\`
|
|
25
|
+
|
|
26
|
+
`)
|
|
27
|
+
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
export {
|
|
32
|
+
ReadmeExplanation
|
|
33
|
+
}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
|
|
2
|
+
import { cmp, Content } from '@voxgig/sdkgen'
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
KIT,
|
|
6
|
+
getModelPath,
|
|
7
|
+
} from '@voxgig/apidef'
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
const ReadmeHowto = cmp(function ReadmeHowto(props: any) {
|
|
11
|
+
const { target, ctx$: { model } } = props
|
|
12
|
+
|
|
13
|
+
Content(`### Make a direct HTTP request
|
|
14
|
+
|
|
15
|
+
For endpoints not covered by entity methods:
|
|
16
|
+
|
|
17
|
+
\`\`\`js
|
|
18
|
+
const result = await client.direct({
|
|
19
|
+
path: '/api/resource/{id}',
|
|
20
|
+
method: 'GET',
|
|
21
|
+
params: { id: 'example' },
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
if (result.ok) {
|
|
25
|
+
console.log(result.status) // 200
|
|
26
|
+
console.log(result.data) // response body
|
|
27
|
+
}
|
|
28
|
+
\`\`\`
|
|
29
|
+
|
|
30
|
+
### Prepare a request without sending it
|
|
31
|
+
|
|
32
|
+
\`\`\`js
|
|
33
|
+
const fetchdef = await client.prepare({
|
|
34
|
+
path: '/api/resource/{id}',
|
|
35
|
+
method: 'DELETE',
|
|
36
|
+
params: { id: 'example' },
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
// Inspect before sending
|
|
40
|
+
console.log(fetchdef.url)
|
|
41
|
+
console.log(fetchdef.method)
|
|
42
|
+
console.log(fetchdef.headers)
|
|
43
|
+
\`\`\`
|
|
44
|
+
|
|
45
|
+
### Use test mode
|
|
46
|
+
|
|
47
|
+
Create a mock client for unit testing — no server required:
|
|
48
|
+
|
|
49
|
+
\`\`\`js
|
|
50
|
+
const client = ${model.const.Name}SDK.test()
|
|
51
|
+
|
|
52
|
+
const result = await client.Planet().load({ id: 'test01' })
|
|
53
|
+
// result.ok === true
|
|
54
|
+
// result.data contains mock response data
|
|
55
|
+
\`\`\`
|
|
56
|
+
|
|
57
|
+
You can also use the instance method:
|
|
58
|
+
|
|
59
|
+
\`\`\`js
|
|
60
|
+
const client = new ${model.const.Name}SDK({ apikey: '...' })
|
|
61
|
+
const testClient = client.tester()
|
|
62
|
+
\`\`\`
|
|
63
|
+
|
|
64
|
+
### Retain entity state across calls
|
|
65
|
+
|
|
66
|
+
Entity instances remember their last match and data:
|
|
67
|
+
|
|
68
|
+
\`\`\`js
|
|
69
|
+
const entity = client.Planet()
|
|
70
|
+
|
|
71
|
+
// First call sets internal match
|
|
72
|
+
await entity.load({ id: 'example' })
|
|
73
|
+
|
|
74
|
+
// Subsequent calls reuse the stored match
|
|
75
|
+
const data = entity.data()
|
|
76
|
+
console.log(data.id) // 'example'
|
|
77
|
+
\`\`\`
|
|
78
|
+
|
|
79
|
+
### Add custom middleware
|
|
80
|
+
|
|
81
|
+
Pass features via the \`extend\` option:
|
|
82
|
+
|
|
83
|
+
\`\`\`js
|
|
84
|
+
const logger = {
|
|
85
|
+
hooks: {
|
|
86
|
+
PreRequest: (ctx) => {
|
|
87
|
+
console.log('Requesting:', ctx.spec.method, ctx.spec.path)
|
|
88
|
+
},
|
|
89
|
+
PreResponse: (ctx) => {
|
|
90
|
+
console.log('Status:', ctx.out.request?.status)
|
|
91
|
+
},
|
|
92
|
+
},
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const client = new ${model.const.Name}SDK({
|
|
96
|
+
apikey: '...',
|
|
97
|
+
extend: [logger],
|
|
98
|
+
})
|
|
99
|
+
\`\`\`
|
|
100
|
+
|
|
101
|
+
### Run live tests
|
|
102
|
+
|
|
103
|
+
Create a \`.env.local\` file at the project root:
|
|
104
|
+
|
|
105
|
+
\`\`\`
|
|
106
|
+
${model.NAME}_TEST_LIVE=TRUE
|
|
107
|
+
${model.NAME}_APIKEY=<your-key>
|
|
108
|
+
\`\`\`
|
|
109
|
+
|
|
110
|
+
Then run:
|
|
111
|
+
|
|
112
|
+
\`\`\`bash
|
|
113
|
+
cd js && npm test
|
|
114
|
+
\`\`\`
|
|
115
|
+
|
|
116
|
+
`)
|
|
117
|
+
|
|
118
|
+
})
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
export {
|
|
122
|
+
ReadmeHowto
|
|
123
|
+
}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
|
|
2
|
+
import { cmp, each, Content } from '@voxgig/sdkgen'
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
KIT,
|
|
6
|
+
getModelPath,
|
|
7
|
+
} from '@voxgig/apidef'
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
const ReadmeModel = cmp(function ReadmeModel(props: any) {
|
|
11
|
+
const { target, ctx$: { model } } = props
|
|
12
|
+
|
|
13
|
+
const entity = getModelPath(model, `main.${KIT}.entity`)
|
|
14
|
+
const entityList = each(entity).filter((e: any) => e.active !== false)
|
|
15
|
+
|
|
16
|
+
Content(`### ${model.const.Name}SDK
|
|
17
|
+
|
|
18
|
+
#### Constructor
|
|
19
|
+
|
|
20
|
+
\`\`\`js
|
|
21
|
+
new ${model.const.Name}SDK(options?)
|
|
22
|
+
\`\`\`
|
|
23
|
+
|
|
24
|
+
| Option | Type | Description |
|
|
25
|
+
| --- | --- | --- |
|
|
26
|
+
| \`apikey\` | \`string\` | API key for authentication. |
|
|
27
|
+
| \`base\` | \`string\` | Base URL of the API server. |
|
|
28
|
+
| \`prefix\` | \`string\` | URL path prefix prepended to all requests. |
|
|
29
|
+
| \`suffix\` | \`string\` | URL path suffix appended to all requests. |
|
|
30
|
+
| \`feature\` | \`object\` | Feature activation flags (e.g. \`{ test: { active: true } }\`). |
|
|
31
|
+
| \`extend\` | \`Feature[]\` | Additional feature instances to load. |
|
|
32
|
+
|
|
33
|
+
#### Methods
|
|
34
|
+
|
|
35
|
+
| Method | Returns | Description |
|
|
36
|
+
| --- | --- | --- |
|
|
37
|
+
| \`options()\` | \`object\` | Deep copy of current SDK options. |
|
|
38
|
+
| \`utility()\` | \`Utility\` | Deep copy of the SDK utility object. |
|
|
39
|
+
| \`prepare(fetchargs?)\` | \`Promise<FetchDef>\` | Build an HTTP request definition without sending it. |
|
|
40
|
+
| \`direct(fetchargs?)\` | \`Promise<DirectResult>\` | Build and send an HTTP request. |
|
|
41
|
+
`)
|
|
42
|
+
|
|
43
|
+
each(entityList, (ent: any) => {
|
|
44
|
+
Content(`| \`${ent.Name}(data?)\` | \`${ent.Name}Entity\` | Create a ${ent.Name} entity instance. |
|
|
45
|
+
`)
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
Content(`| \`tester(testopts?, sdkopts?)\` | \`${model.const.Name}SDK\` | Create a test-mode client instance. |
|
|
49
|
+
|
|
50
|
+
#### Static methods
|
|
51
|
+
|
|
52
|
+
| Method | Returns | Description |
|
|
53
|
+
| --- | --- | --- |
|
|
54
|
+
| \`${model.const.Name}SDK.test(testopts?, sdkopts?)\` | \`${model.const.Name}SDK\` | Create a test-mode client. |
|
|
55
|
+
|
|
56
|
+
### Entity interface
|
|
57
|
+
|
|
58
|
+
All entities share the same interface.
|
|
59
|
+
|
|
60
|
+
#### Methods
|
|
61
|
+
|
|
62
|
+
| Method | Signature | Description |
|
|
63
|
+
| --- | --- | --- |
|
|
64
|
+
| \`load\` | \`load(reqmatch?, ctrl?): Promise<Result>\` | Load a single entity by match criteria. |
|
|
65
|
+
| \`list\` | \`list(reqmatch?, ctrl?): Promise<Result>\` | List entities matching the criteria. |
|
|
66
|
+
| \`create\` | \`create(reqdata?, ctrl?): Promise<Result>\` | Create a new entity. |
|
|
67
|
+
| \`update\` | \`update(reqdata?, ctrl?): Promise<Result>\` | Update an existing entity. |
|
|
68
|
+
| \`remove\` | \`remove(reqmatch?, ctrl?): Promise<Result>\` | Remove an entity. |
|
|
69
|
+
| \`data\` | \`data(data?): any\` | Get or set entity data. |
|
|
70
|
+
| \`match\` | \`match(match?): any\` | Get or set entity match criteria. |
|
|
71
|
+
| \`make\` | \`make(): Entity\` | Create a new instance with the same options. |
|
|
72
|
+
| \`client\` | \`client(): ${model.const.Name}SDK\` | Return the parent SDK client. |
|
|
73
|
+
| \`entopts\` | \`entopts(): object\` | Return a copy of the entity options. |
|
|
74
|
+
|
|
75
|
+
#### Result shape
|
|
76
|
+
|
|
77
|
+
All entity operations return a Result object:
|
|
78
|
+
|
|
79
|
+
\`\`\`js
|
|
80
|
+
{
|
|
81
|
+
ok: true, // true if the HTTP status is 2xx
|
|
82
|
+
status: 200, // HTTP status code
|
|
83
|
+
headers: {}, // response headers
|
|
84
|
+
data: {} // parsed JSON response body
|
|
85
|
+
}
|
|
86
|
+
\`\`\`
|
|
87
|
+
|
|
88
|
+
### DirectResult shape
|
|
89
|
+
|
|
90
|
+
The \`direct()\` method returns:
|
|
91
|
+
|
|
92
|
+
\`\`\`js
|
|
93
|
+
{
|
|
94
|
+
ok: true,
|
|
95
|
+
status: 200,
|
|
96
|
+
headers: {},
|
|
97
|
+
data: {}
|
|
98
|
+
}
|
|
99
|
+
\`\`\`
|
|
100
|
+
|
|
101
|
+
On error, \`ok\` is \`false\` and an \`err\` property contains the error.
|
|
102
|
+
|
|
103
|
+
### FetchDef shape
|
|
104
|
+
|
|
105
|
+
The \`prepare()\` method returns:
|
|
106
|
+
|
|
107
|
+
\`\`\`js
|
|
108
|
+
{
|
|
109
|
+
url: 'string',
|
|
110
|
+
method: 'string',
|
|
111
|
+
headers: {},
|
|
112
|
+
body: undefined
|
|
113
|
+
}
|
|
114
|
+
\`\`\`
|
|
115
|
+
|
|
116
|
+
### Entities
|
|
117
|
+
|
|
118
|
+
`)
|
|
119
|
+
|
|
120
|
+
each(entityList, (ent: any) => {
|
|
121
|
+
const fields = ent.fields || []
|
|
122
|
+
const opnames = Object.keys(ent.op || {})
|
|
123
|
+
const ops = ent.op || {}
|
|
124
|
+
const points = each(ops).map((op: any) =>
|
|
125
|
+
op.points ? each(op.points) : []
|
|
126
|
+
).flat()
|
|
127
|
+
const path = points.length > 0 ? (points[0] as any).orig || '' : ''
|
|
128
|
+
|
|
129
|
+
Content(`#### ${ent.Name}
|
|
130
|
+
|
|
131
|
+
| Field | Description |
|
|
132
|
+
| --- | --- |
|
|
133
|
+
`)
|
|
134
|
+
each(fields, (field: any) => {
|
|
135
|
+
Content(`| \`${field.name}\` | ${field.short || ''} |
|
|
136
|
+
`)
|
|
137
|
+
})
|
|
138
|
+
|
|
139
|
+
Content(`
|
|
140
|
+
Operations: ${opnames.join(', ')}.
|
|
141
|
+
|
|
142
|
+
API path: \`${path}\`
|
|
143
|
+
|
|
144
|
+
`)
|
|
145
|
+
})
|
|
146
|
+
|
|
147
|
+
})
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
export {
|
|
151
|
+
ReadmeModel
|
|
152
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
|
|
2
|
+
import { cmp, Content } from '@voxgig/sdkgen'
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
const ReadmeTopHowto = cmp(function ReadmeTopHowto(props: any) {
|
|
6
|
+
const { target } = props
|
|
7
|
+
|
|
8
|
+
Content(`**JavaScript:**
|
|
9
|
+
\`\`\`js
|
|
10
|
+
const result = await client.direct({
|
|
11
|
+
path: '/api/resource/{id}',
|
|
12
|
+
method: 'GET',
|
|
13
|
+
params: { id: 'example' },
|
|
14
|
+
})
|
|
15
|
+
console.log(result.data)
|
|
16
|
+
\`\`\`
|
|
17
|
+
|
|
18
|
+
`)
|
|
19
|
+
|
|
20
|
+
})
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
export {
|
|
24
|
+
ReadmeTopHowto
|
|
25
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
|
|
2
|
+
import { cmp, Content } from '@voxgig/sdkgen'
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
KIT,
|
|
6
|
+
getModelPath,
|
|
7
|
+
nom,
|
|
8
|
+
} from '@voxgig/apidef'
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
const ReadmeTopQuick = cmp(function ReadmeTopQuick(props: any) {
|
|
12
|
+
const { target, ctx$: { model } } = props
|
|
13
|
+
|
|
14
|
+
const entity = getModelPath(model, `main.${KIT}.entity`)
|
|
15
|
+
const exampleEntity = Object.values(entity).find((e: any) => e.active !== false) as any
|
|
16
|
+
|
|
17
|
+
Content(`\`\`\`js
|
|
18
|
+
const { ${model.const.Name}SDK } = require('${target.module.name}')
|
|
19
|
+
|
|
20
|
+
const client = new ${model.const.Name}SDK({
|
|
21
|
+
apikey: process.env.${model.NAME}_APIKEY,
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
`)
|
|
25
|
+
|
|
26
|
+
if (exampleEntity) {
|
|
27
|
+
const eName = nom(exampleEntity, 'Name')
|
|
28
|
+
const opnames = Object.keys(exampleEntity.op || {})
|
|
29
|
+
|
|
30
|
+
if (opnames.includes('list')) {
|
|
31
|
+
Content(`// List all ${eName.toLowerCase()}s
|
|
32
|
+
const ${eName.toLowerCase()}s = await client.${eName}().list()
|
|
33
|
+
`)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Find a nested entity for a more interesting example
|
|
37
|
+
const nestedEntity = Object.values(entity).find((e: any) =>
|
|
38
|
+
e.active !== false && e.ancestors && e.ancestors.length > 0
|
|
39
|
+
) as any
|
|
40
|
+
|
|
41
|
+
if (nestedEntity && opnames.includes('load')) {
|
|
42
|
+
const neName = nom(nestedEntity, 'Name')
|
|
43
|
+
const parentFields = (nestedEntity.fields || [])
|
|
44
|
+
.filter((f: any) => f.name !== 'id' && f.name.endsWith('_id'))
|
|
45
|
+
const parentParam = parentFields.length > 0 ? parentFields[0].name : 'parent_id'
|
|
46
|
+
|
|
47
|
+
Content(`
|
|
48
|
+
// Load a specific ${neName.toLowerCase()}
|
|
49
|
+
const ${neName.toLowerCase()} = await client.${neName}().load({
|
|
50
|
+
${parentParam}: 'example',
|
|
51
|
+
id: 'example_id',
|
|
52
|
+
})
|
|
53
|
+
`)
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
Content(`\`\`\`
|
|
58
|
+
`)
|
|
59
|
+
|
|
60
|
+
})
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
export {
|
|
64
|
+
ReadmeTopQuick
|
|
65
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
|
|
2
|
+
import { cmp, Content } from '@voxgig/sdkgen'
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
KIT,
|
|
6
|
+
getModelPath,
|
|
7
|
+
nom,
|
|
8
|
+
} from '@voxgig/apidef'
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
const ReadmeTopTest = cmp(function ReadmeTopTest(props: any) {
|
|
12
|
+
const { target, ctx$: { model } } = props
|
|
13
|
+
|
|
14
|
+
const entity = getModelPath(model, `main.${KIT}.entity`)
|
|
15
|
+
const exampleEntity = Object.values(entity).find((e: any) => e.active !== false) as any
|
|
16
|
+
|
|
17
|
+
Content(`\`\`\`js
|
|
18
|
+
const client = ${model.const.Name}SDK.test()
|
|
19
|
+
`)
|
|
20
|
+
|
|
21
|
+
if (exampleEntity) {
|
|
22
|
+
const eName = nom(exampleEntity, 'Name')
|
|
23
|
+
Content(`const result = await client.${eName}().load({ id: 'test01' })
|
|
24
|
+
// result.ok === true, result.data contains mock data
|
|
25
|
+
`)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
Content(`\`\`\`
|
|
29
|
+
`)
|
|
30
|
+
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
export {
|
|
35
|
+
ReadmeTopTest
|
|
36
|
+
}
|
|
@@ -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
|
|
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
|
|
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
|
}
|