@voxgig/apidef 2.3.1 → 2.4.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/dist/apidef.d.ts +2 -6
- package/dist/apidef.js +44 -11
- package/dist/apidef.js.map +1 -1
- package/dist/builder/flow/flowHeuristic01.js +1 -1
- package/dist/builder/flow/flowHeuristic01.js.map +1 -1
- package/dist/guide/guide.d.ts +2 -0
- package/dist/guide/guide.js +107 -0
- package/dist/guide/guide.js.map +1 -0
- package/dist/guide/heuristic01.js +149 -218
- package/dist/guide/heuristic01.js.map +1 -1
- package/dist/resolver.js +2 -2
- package/dist/resolver.js.map +1 -1
- package/dist/transform/entity.js +1 -2
- package/dist/transform/entity.js.map +1 -1
- package/dist/transform/field.js +1 -2
- package/dist/transform/field.js.map +1 -1
- package/dist/transform/operation.js +1 -2
- package/dist/transform/operation.js.map +1 -1
- package/dist/transform/top.js +0 -1
- package/dist/transform/top.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types.d.ts +297 -2
- package/dist/types.js +12 -1
- package/dist/types.js.map +1 -1
- package/dist/utility.d.ts +3 -1
- package/dist/utility.js +155 -0
- package/dist/utility.js.map +1 -1
- package/model/apidef.jsonic +1 -50
- package/model/guide.jsonic +53 -0
- package/package.json +6 -5
- package/src/apidef.ts +61 -15
- package/src/builder/flow/flowHeuristic01.ts +1 -1
- package/src/guide/guide.ts +274 -0
- package/src/guide/heuristic01.ts +173 -232
- package/src/{guide.ts → guide.ts.off} +8 -5
- package/src/resolver.ts +2 -2
- package/src/transform/entity.ts +1 -6
- package/src/transform/field.ts +1 -6
- package/src/transform/operation.ts +1 -2
- package/src/transform/top.ts +0 -6
- package/src/types.ts +31 -0
- package/src/utility.ts +184 -37
- package/dist/guide.d.ts +0 -2
- package/dist/guide.js +0 -95
- package/dist/guide.js.map +0 -1
package/model/apidef.jsonic
CHANGED
|
@@ -1,53 +1,4 @@
|
|
|
1
1
|
|
|
2
|
-
main: api:
|
|
3
|
-
|
|
4
|
-
transform: openapi: {
|
|
5
|
-
order: *`
|
|
6
|
-
top,
|
|
7
|
-
entity,
|
|
8
|
-
operation,
|
|
9
|
-
field,
|
|
10
|
-
clean,
|
|
11
|
-
` | string,
|
|
12
|
-
|
|
13
|
-
element: {
|
|
14
|
-
top: {}
|
|
15
|
-
entity: {}
|
|
16
|
-
operation: {}
|
|
17
|
-
field: {}
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
builder: standard: {
|
|
22
|
-
order: *`
|
|
23
|
-
entity,
|
|
24
|
-
flow,
|
|
25
|
-
` | string,
|
|
26
|
-
|
|
27
|
-
element: {
|
|
28
|
-
entity: {}
|
|
29
|
-
flow: {}
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
main: api: guide: entity: &: {
|
|
38
|
-
name: .$KEY
|
|
39
|
-
path: &: {
|
|
40
|
-
op: &: {
|
|
41
|
-
method: *'get' | string
|
|
42
|
-
transform: {
|
|
43
|
-
# TODO: make these work
|
|
44
|
-
# inward: *null | string | object
|
|
45
|
-
# outward: *null | string | object
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
|
|
2
|
+
main: api: {}
|
|
52
3
|
|
|
53
4
|
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
|
|
2
|
+
guide: control: {
|
|
3
|
+
|
|
4
|
+
transform: openapi: {
|
|
5
|
+
order: *`
|
|
6
|
+
top,
|
|
7
|
+
entity,
|
|
8
|
+
operation,
|
|
9
|
+
field,
|
|
10
|
+
clean,
|
|
11
|
+
` | string,
|
|
12
|
+
|
|
13
|
+
element: {
|
|
14
|
+
top: {}
|
|
15
|
+
entity: {}
|
|
16
|
+
operation: {}
|
|
17
|
+
field: {}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
builder: standard: {
|
|
22
|
+
order: *`
|
|
23
|
+
entity,
|
|
24
|
+
flow,
|
|
25
|
+
` | string,
|
|
26
|
+
|
|
27
|
+
element: {
|
|
28
|
+
entity: {}
|
|
29
|
+
flow: {}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
guide: entity: &: {
|
|
38
|
+
name: .$KEY
|
|
39
|
+
path: &: {
|
|
40
|
+
op: &: {
|
|
41
|
+
method: *'get' | string
|
|
42
|
+
transform: {
|
|
43
|
+
# TODO: make these work
|
|
44
|
+
# inward: *null | string | object
|
|
45
|
+
# outward: *null | string | object
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@voxgig/apidef",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.4.0",
|
|
4
4
|
"main": "dist/apidef.js",
|
|
5
5
|
"type": "commonjs",
|
|
6
6
|
"types": "dist/apidef.d.ts",
|
|
@@ -40,20 +40,21 @@
|
|
|
40
40
|
"devDependencies": {
|
|
41
41
|
"@hapi/code": "^9.0.3",
|
|
42
42
|
"@types/js-yaml": "^4.0.9",
|
|
43
|
-
"@types/node": "24.
|
|
43
|
+
"@types/node": "24.3.0",
|
|
44
44
|
"aontu": "^0.28.0",
|
|
45
45
|
"json-schema-to-ts": "^3.1.1",
|
|
46
|
-
"memfs": "^4.36.
|
|
46
|
+
"memfs": "^4.36.3",
|
|
47
47
|
"typescript": "^5.9.2"
|
|
48
48
|
},
|
|
49
49
|
"dependencies": {
|
|
50
50
|
"@redocly/openapi-core": "1.34.5",
|
|
51
|
-
"@voxgig/struct": "^0.0.
|
|
51
|
+
"@voxgig/struct": "^0.0.9",
|
|
52
52
|
"@voxgig/util": "^0.2.0",
|
|
53
53
|
"chokidar": "^4.0.3",
|
|
54
|
+
"diff": "^8.0.2",
|
|
54
55
|
"gubu": "^9.0.0",
|
|
55
56
|
"jostraca": "^0.24.1",
|
|
56
|
-
"pino": "^9.
|
|
57
|
+
"pino": "^9.9.0",
|
|
57
58
|
"pino-pretty": "^13.1.1",
|
|
58
59
|
"sonic-boom": "^4.2.0"
|
|
59
60
|
}
|
package/src/apidef.ts
CHANGED
|
@@ -11,6 +11,8 @@ import { prettyPino } from '@voxgig/util'
|
|
|
11
11
|
|
|
12
12
|
import type {
|
|
13
13
|
ApiDefOptions,
|
|
14
|
+
ApiDefResult,
|
|
15
|
+
Control,
|
|
14
16
|
Model,
|
|
15
17
|
Build,
|
|
16
18
|
ApiModel,
|
|
@@ -19,12 +21,13 @@ import type {
|
|
|
19
21
|
import {
|
|
20
22
|
OpenModelShape,
|
|
21
23
|
OpenBuildShape,
|
|
24
|
+
OpenControlShape,
|
|
22
25
|
} from './types'
|
|
23
26
|
|
|
24
27
|
|
|
25
28
|
import {
|
|
26
|
-
|
|
27
|
-
} from './guide'
|
|
29
|
+
buildGuide,
|
|
30
|
+
} from './guide/guide'
|
|
28
31
|
|
|
29
32
|
|
|
30
33
|
import {
|
|
@@ -72,12 +75,19 @@ function ApiDef(opts: ApiDefOptions) {
|
|
|
72
75
|
opts.strategy = opts.strategy || 'heuristic01'
|
|
73
76
|
|
|
74
77
|
|
|
75
|
-
async function generate(spec: any) {
|
|
78
|
+
async function generate(spec: any): Promise<ApiDefResult> {
|
|
76
79
|
const start = Date.now()
|
|
80
|
+
const steps: string[] = []
|
|
77
81
|
// dlog('start')
|
|
78
82
|
|
|
79
|
-
const
|
|
80
|
-
const
|
|
83
|
+
const ctrl: Control = OpenControlShape(spec.ctrl || {})
|
|
84
|
+
const model: Model = OpenModelShape(spec.model || {})
|
|
85
|
+
const build: Build = OpenBuildShape(spec.build || {})
|
|
86
|
+
|
|
87
|
+
// Step: parse (API spec).
|
|
88
|
+
if (!ctrl.step.parse) {
|
|
89
|
+
return { ok: false, steps, start, end: Date.now(), ctrl }
|
|
90
|
+
}
|
|
81
91
|
|
|
82
92
|
names(model, model.name)
|
|
83
93
|
|
|
@@ -112,7 +122,9 @@ function ApiDef(opts: ApiDefOptions) {
|
|
|
112
122
|
defpath: Path.dirname(defpath),
|
|
113
123
|
model,
|
|
114
124
|
apimodel,
|
|
115
|
-
|
|
125
|
+
guide: {},
|
|
126
|
+
def: undefined,
|
|
127
|
+
note: {}
|
|
116
128
|
}
|
|
117
129
|
|
|
118
130
|
const defsrc = loadFile(defpath, 'def', fs, log)
|
|
@@ -125,9 +137,24 @@ function ApiDef(opts: ApiDefOptions) {
|
|
|
125
137
|
|
|
126
138
|
ctx.def = def
|
|
127
139
|
|
|
140
|
+
steps.push('parse')
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
// Step: guide (derive).
|
|
144
|
+
if (!ctrl.step.guide) {
|
|
145
|
+
return { ok: false, steps, start, end: Date.now(), ctrl }
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
const guideModel = await buildGuide(ctx)
|
|
149
|
+
ctx.guide = guideModel.guide
|
|
150
|
+
|
|
151
|
+
steps.push('guide')
|
|
128
152
|
|
|
129
|
-
const guideBuilder = await resolveGuide(ctx)
|
|
130
153
|
|
|
154
|
+
// Step: transformers (transform spec and guide into core structures).
|
|
155
|
+
if (!ctrl.step.transformers) {
|
|
156
|
+
return { ok: false, steps, start, end: Date.now(), ctrl, guide: ctx.guide }
|
|
157
|
+
}
|
|
131
158
|
|
|
132
159
|
// const transformSpec = await resolveTransforms(ctx)
|
|
133
160
|
const transforms = await resolveElements(ctx, 'transform', 'openapi', {
|
|
@@ -138,11 +165,25 @@ function ApiDef(opts: ApiDefOptions) {
|
|
|
138
165
|
clean: cleanTransform,
|
|
139
166
|
})
|
|
140
167
|
|
|
168
|
+
steps.push('transformers')
|
|
169
|
+
|
|
170
|
+
// Step: builders (build generated sub models).
|
|
171
|
+
if (!ctrl.step.builders) {
|
|
172
|
+
return { ok: false, steps, start, end: Date.now(), ctrl, guide: ctx.guide }
|
|
173
|
+
}
|
|
174
|
+
|
|
141
175
|
const builders = await resolveElements(ctx, 'builder', 'standard', {
|
|
142
176
|
entity: makeEntityBuilder,
|
|
143
177
|
flow: makeFlowBuilder,
|
|
144
178
|
})
|
|
145
179
|
|
|
180
|
+
steps.push('builders')
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
// Step: generate (generate model files).
|
|
184
|
+
if (!ctrl.step.generate) {
|
|
185
|
+
return { ok: false, steps, start, end: Date.now(), ctrl, guide: ctx.guide }
|
|
186
|
+
}
|
|
146
187
|
|
|
147
188
|
const jostraca = Jostraca({
|
|
148
189
|
now: spec.now,
|
|
@@ -153,10 +194,6 @@ function ApiDef(opts: ApiDefOptions) {
|
|
|
153
194
|
const jmodel = {}
|
|
154
195
|
|
|
155
196
|
const root = () => Project({ folder: '.' }, async () => {
|
|
156
|
-
guideBuilder()
|
|
157
|
-
// entityBuilder()
|
|
158
|
-
// flowBuilder()
|
|
159
|
-
|
|
160
197
|
for (let builder of builders) {
|
|
161
198
|
builder()
|
|
162
199
|
}
|
|
@@ -176,12 +213,21 @@ function ApiDef(opts: ApiDefOptions) {
|
|
|
176
213
|
}
|
|
177
214
|
}
|
|
178
215
|
|
|
216
|
+
steps.push('generate')
|
|
217
|
+
|
|
179
218
|
log.info({ point: 'generate-end', note: 'success', break: true })
|
|
180
219
|
|
|
181
220
|
return {
|
|
182
221
|
ok: true,
|
|
183
|
-
|
|
222
|
+
start,
|
|
223
|
+
end: Date.now(),
|
|
224
|
+
steps,
|
|
225
|
+
ctrl,
|
|
226
|
+
|
|
227
|
+
guide: ctx.guide,
|
|
184
228
|
apimodel,
|
|
229
|
+
ctx,
|
|
230
|
+
jres,
|
|
185
231
|
}
|
|
186
232
|
}
|
|
187
233
|
|
|
@@ -194,8 +240,6 @@ function ApiDef(opts: ApiDefOptions) {
|
|
|
194
240
|
ApiDef.makeBuild = async function(opts: ApiDefOptions) {
|
|
195
241
|
let apidef: any = undefined
|
|
196
242
|
|
|
197
|
-
// const outprefix = null == opts.outprefix ? '' : opts.outprefix
|
|
198
|
-
|
|
199
243
|
const config = {
|
|
200
244
|
def: opts.def || 'no-def',
|
|
201
245
|
kind: 'openapi3',
|
|
@@ -217,7 +261,9 @@ ApiDef.makeBuild = async function(opts: ApiDefOptions) {
|
|
|
217
261
|
})
|
|
218
262
|
}
|
|
219
263
|
|
|
220
|
-
|
|
264
|
+
const ctrl = build.spec.buildargs?.apidef?.ctrl || {}
|
|
265
|
+
|
|
266
|
+
return await apidef.generate({ model, build, config, ctrl })
|
|
221
267
|
}
|
|
222
268
|
|
|
223
269
|
build.step = 'pre'
|
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
|
|
2
|
+
import Path from 'node:path'
|
|
3
|
+
|
|
4
|
+
import { Jostraca, Project, names, File, Content, each } from 'jostraca'
|
|
5
|
+
|
|
6
|
+
import { Aontu, Val, Nil, Context } from 'aontu'
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
import { items } from '@voxgig/struct'
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
import { heuristic01 } from './heuristic01'
|
|
13
|
+
|
|
14
|
+
import {
|
|
15
|
+
getdlog,
|
|
16
|
+
} from '../utility'
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
// Log non-fatal wierdness.
|
|
20
|
+
const dlog = getdlog('apidef', __filename)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
async function buildGuide(ctx: any): Promise<any> {
|
|
24
|
+
const errs: any[] = []
|
|
25
|
+
|
|
26
|
+
// console.log(ctx)
|
|
27
|
+
const folder = Path.resolve(ctx.opts.folder)
|
|
28
|
+
// console.log('GUIDE folder', folder)
|
|
29
|
+
|
|
30
|
+
try {
|
|
31
|
+
const basejres = await buildBaseGuide(ctx)
|
|
32
|
+
}
|
|
33
|
+
catch (err: any) {
|
|
34
|
+
errs.push(err)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
handleErrors(ctx, errs)
|
|
38
|
+
|
|
39
|
+
let src = ''
|
|
40
|
+
let guidePath = Path.join(folder, 'guide',
|
|
41
|
+
(null == ctx.opts.outprefix ? '' : ctx.opts.outprefix) + 'guide.jsonic')
|
|
42
|
+
|
|
43
|
+
try {
|
|
44
|
+
src = ctx.fs.readFileSync(guidePath, 'utf8')
|
|
45
|
+
}
|
|
46
|
+
catch (err: any) {
|
|
47
|
+
errs.push(err)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
handleErrors(ctx, errs)
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
const opts = {
|
|
54
|
+
path: guidePath
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const guideRoot = Aontu(src, opts)
|
|
58
|
+
errs.push(...guideRoot.err)
|
|
59
|
+
|
|
60
|
+
handleErrors(ctx, errs)
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
let genctx = new Context({ root: guideRoot })
|
|
64
|
+
const guideModel = guideRoot.gen(genctx)
|
|
65
|
+
|
|
66
|
+
errs.push(...genctx.err)
|
|
67
|
+
|
|
68
|
+
handleErrors(ctx, errs)
|
|
69
|
+
|
|
70
|
+
return guideModel
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
function handleErrors(ctx: any, errs: any[]) {
|
|
75
|
+
if (0 < errs.length) {
|
|
76
|
+
let topmsg: string[] = []
|
|
77
|
+
for (let err of errs) {
|
|
78
|
+
topmsg.push((err?.message?.split('\n')[0]) || '')
|
|
79
|
+
ctx.log.error({ err })
|
|
80
|
+
}
|
|
81
|
+
throw new Error('SUMMARY: ' + topmsg.join('; '))
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
async function buildBaseGuide(ctx: any) {
|
|
87
|
+
let baseguide: Record<string, any> = {}
|
|
88
|
+
|
|
89
|
+
if ('heuristic01' === ctx.opts.strategy) {
|
|
90
|
+
baseguide = await heuristic01(ctx)
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
throw new Error('Unknown guide strategy: ' + ctx.opts.strategy)
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const guideBlocks = [
|
|
97
|
+
'# Guide',
|
|
98
|
+
'',
|
|
99
|
+
'guide: {',
|
|
100
|
+
]
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
items(baseguide.entity).map(([entityname, entity]: any[]) => {
|
|
104
|
+
guideBlocks.push(`
|
|
105
|
+
entity: ${entityname}: {` +
|
|
106
|
+
(0 < entity.why_name.length ? ' # name:' + entity.why_name.join(';') : ''))
|
|
107
|
+
|
|
108
|
+
items(entity.path).map(([pathname, path]: any[]) => {
|
|
109
|
+
guideBlocks.push(` path: '${pathname}': op: {` +
|
|
110
|
+
(0 < path.why_ent.length ? ' # ent:' + path.why_ent.join(';') : ''))
|
|
111
|
+
|
|
112
|
+
items(path.op).map(([opname, op]: any[]) => {
|
|
113
|
+
guideBlocks.push(` '${opname}': method: ${op.method}` +
|
|
114
|
+
(0 < op.why_op.length ? ' # ' + op.why_op : ''))
|
|
115
|
+
if (op.transform?.reqform) {
|
|
116
|
+
guideBlocks.push(
|
|
117
|
+
` '${opname}': transform: reqform: ${JSON.stringify(op.transform.reqform)}`)
|
|
118
|
+
}
|
|
119
|
+
})
|
|
120
|
+
|
|
121
|
+
guideBlocks.push(` }`)
|
|
122
|
+
})
|
|
123
|
+
|
|
124
|
+
guideBlocks.push(` }`)
|
|
125
|
+
})
|
|
126
|
+
|
|
127
|
+
guideBlocks.push('', '}')
|
|
128
|
+
|
|
129
|
+
const guideSrc = guideBlocks.join('\n')
|
|
130
|
+
|
|
131
|
+
ctx.note.guide = { base: guideSrc }
|
|
132
|
+
|
|
133
|
+
const baseGuideFileName =
|
|
134
|
+
(null == ctx.opts.outprefix ? '' : ctx.opts.outprefix) + 'base-guide.jsonic'
|
|
135
|
+
|
|
136
|
+
const jostraca = Jostraca({
|
|
137
|
+
folder: ctx.opts.folder + '/guide',
|
|
138
|
+
now: ctx.spec.now,
|
|
139
|
+
fs: () => ctx.fs,
|
|
140
|
+
log: ctx.log,
|
|
141
|
+
})
|
|
142
|
+
|
|
143
|
+
const root = () => Project({ folder: '.' }, async () => {
|
|
144
|
+
File({ name: baseGuideFileName }, () => Content(guideSrc))
|
|
145
|
+
})
|
|
146
|
+
|
|
147
|
+
const jres = await jostraca.generate({
|
|
148
|
+
existing: { txt: { merge: true } }
|
|
149
|
+
}, root)
|
|
150
|
+
|
|
151
|
+
return jres
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
/*
|
|
156
|
+
async function resolveGuide(ctx: any) {
|
|
157
|
+
let baseguide: Record<string, any> = {}
|
|
158
|
+
let override: Record<string, any> = ctx.model.main.api.guide
|
|
159
|
+
|
|
160
|
+
if ('heuristic01' === ctx.opts.strategy) {
|
|
161
|
+
baseguide = await heuristic01(ctx)
|
|
162
|
+
}
|
|
163
|
+
else {
|
|
164
|
+
throw new Error('Unknown guide strategy: ' + ctx.opts.strategy)
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// Override generated base guide with custom hints
|
|
168
|
+
let guide = merge([{}, baseguide, override])
|
|
169
|
+
|
|
170
|
+
// TODO: this is a hack!!!
|
|
171
|
+
// Instead, update @voxgig/model, so that builders can request a reload of the entire
|
|
172
|
+
// model. This allows builders to modify the model for later buidlers
|
|
173
|
+
// during a single generation pass.
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
guide = cleanGuide(guide)
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
// TODO: FIX: sdk.jsonic should have final version of guide
|
|
180
|
+
if (ctx.model.main?.api) {
|
|
181
|
+
ctx.model.main.api.guide = guide
|
|
182
|
+
}
|
|
183
|
+
else {
|
|
184
|
+
dlog('missing', 'ctx.model.main.api')
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
const guideFile =
|
|
188
|
+
Path.join(ctx.opts.folder,
|
|
189
|
+
(null == ctx.opts.outprefix ? '' : ctx.opts.outprefix) + 'base-guide.jsonic')
|
|
190
|
+
|
|
191
|
+
const guideBlocks = [
|
|
192
|
+
'# Guide',
|
|
193
|
+
'',
|
|
194
|
+
'main: api: guide: {',
|
|
195
|
+
]
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
guideBlocks.push(...each(baseguide.entity, (entity, entityname) => {
|
|
199
|
+
guideBlocks.push(`
|
|
200
|
+
entity: ${entityname}: {` +
|
|
201
|
+
(0 < entity.why_name.length ? ' # name:' + entity.why_name.join(';') : ''))
|
|
202
|
+
|
|
203
|
+
items(entity.path).map((pathn) => {
|
|
204
|
+
const [pathname, path] = pathn
|
|
205
|
+
guideBlocks.push(` path: '${pathname}': op: {` +
|
|
206
|
+
(0 < path.why_ent.length ? ' # ent:' + path.why_ent.join(';') : ''))
|
|
207
|
+
|
|
208
|
+
items(path.op).map((opn) => {
|
|
209
|
+
const [opname, op] = opn
|
|
210
|
+
guideBlocks.push(` '${opname}': method: ${op.method}` +
|
|
211
|
+
(0 < op.why_op.length ? ' # ' + op.why_op : ''))
|
|
212
|
+
if (op.transform?.reqform) {
|
|
213
|
+
guideBlocks.push(
|
|
214
|
+
` '${opname}': transform: reqform: ${JSON.stringify(op.transform.reqform)}`)
|
|
215
|
+
}
|
|
216
|
+
})
|
|
217
|
+
|
|
218
|
+
guideBlocks.push(` }`)
|
|
219
|
+
})
|
|
220
|
+
|
|
221
|
+
guideBlocks.push(`}`)
|
|
222
|
+
}))
|
|
223
|
+
|
|
224
|
+
guideBlocks.push('}')
|
|
225
|
+
|
|
226
|
+
const guideSrc = guideBlocks.join('\n')
|
|
227
|
+
|
|
228
|
+
ctx.note.guide = { base: guideSrc }
|
|
229
|
+
|
|
230
|
+
return () => {
|
|
231
|
+
// Save base guide for reference
|
|
232
|
+
File({ name: '../def/' + Path.basename(guideFile) }, () => Content(guideSrc))
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
|
|
237
|
+
function cleanGuide(guide: Record<string, any>): Record<string, any> {
|
|
238
|
+
const clean: Record<string, any> = {
|
|
239
|
+
control: guide.control,
|
|
240
|
+
entity: {}
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
const exclude_entity = guide.exclude?.entity?.split(',') || []
|
|
244
|
+
const include_entity = guide.include?.entity?.split(',') || []
|
|
245
|
+
|
|
246
|
+
each(guide.entity, (entity: any, name: string) => {
|
|
247
|
+
if (exclude_entity.includes(name)) {
|
|
248
|
+
return
|
|
249
|
+
}
|
|
250
|
+
if (exclude_entity.includes('*')) {
|
|
251
|
+
if (!include_entity.includes(name)) {
|
|
252
|
+
return
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
let ent: any = clean.entity[name] = clean.entity[name] = {
|
|
257
|
+
name,
|
|
258
|
+
why_name: entity.why_name || [],
|
|
259
|
+
path: {}
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
each(entity.path, (path: any, pathname: string) => {
|
|
263
|
+
ent.path[pathname] = path
|
|
264
|
+
})
|
|
265
|
+
})
|
|
266
|
+
|
|
267
|
+
return clean
|
|
268
|
+
}
|
|
269
|
+
*/
|
|
270
|
+
|
|
271
|
+
|
|
272
|
+
export {
|
|
273
|
+
buildGuide
|
|
274
|
+
}
|