@voxgig/apidef 2.4.0 → 3.0.2
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 +5 -1
- package/dist/apidef.js +197 -112
- package/dist/apidef.js.map +1 -1
- package/dist/builder/entity/entity.d.ts +3 -0
- package/dist/builder/entity/{apiEntity.js → entity.js} +12 -9
- package/dist/builder/entity/entity.js.map +1 -0
- package/dist/builder/entity/info.d.ts +3 -0
- package/dist/builder/entity/info.js +22 -0
- package/dist/builder/entity/info.js.map +1 -0
- package/dist/builder/entity.js +7 -21
- package/dist/builder/entity.js.map +1 -1
- package/dist/builder/flow/flowHeuristic01.js +21 -11
- package/dist/builder/flow/flowHeuristic01.js.map +1 -1
- package/dist/builder/flow.d.ts +2 -1
- package/dist/builder/flow.js +29 -4
- package/dist/builder/flow.js.map +1 -1
- package/dist/def.d.ts +62 -0
- package/dist/def.js +4 -0
- package/dist/def.js.map +1 -0
- package/dist/desc.d.ts +89 -0
- package/dist/desc.js +4 -0
- package/dist/desc.js.map +1 -0
- package/dist/guide/guide.d.ts +2 -1
- package/dist/guide/guide.js +161 -30
- package/dist/guide/guide.js.map +1 -1
- package/dist/guide/heuristic01.d.ts +2 -1
- package/dist/guide/heuristic01.js +1120 -234
- package/dist/guide/heuristic01.js.map +1 -1
- package/dist/model.d.ts +55 -0
- package/dist/model.js +4 -0
- package/dist/model.js.map +1 -0
- package/dist/parse.d.ts +1 -2
- package/dist/parse.js +8 -47
- package/dist/parse.js.map +1 -1
- package/dist/transform/args.d.ts +3 -0
- package/dist/transform/args.js +58 -0
- package/dist/transform/args.js.map +1 -0
- package/dist/transform/clean.js +27 -3
- package/dist/transform/clean.js.map +1 -1
- package/dist/transform/entity.d.ts +11 -3
- package/dist/transform/entity.js +57 -41
- package/dist/transform/entity.js.map +1 -1
- package/dist/transform/field.d.ts +3 -3
- package/dist/transform/field.js +90 -65
- package/dist/transform/field.js.map +1 -1
- package/dist/transform/operation.d.ts +1 -1
- package/dist/transform/operation.js +94 -296
- package/dist/transform/operation.js.map +1 -1
- package/dist/transform/select.d.ts +3 -0
- package/dist/transform/select.js +44 -0
- package/dist/transform/select.js.map +1 -0
- package/dist/transform/top.d.ts +9 -0
- package/dist/transform/top.js +11 -2
- package/dist/transform/top.js.map +1 -1
- package/dist/transform.js +4 -0
- package/dist/transform.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types.d.ts +112 -19
- package/dist/types.js +4 -2
- package/dist/types.js.map +1 -1
- package/dist/utility.d.ts +30 -2
- package/dist/utility.js +381 -6
- package/dist/utility.js.map +1 -1
- package/model/apidef.jsonic +75 -1
- package/model/guide.jsonic +14 -44
- package/package.json +19 -14
- package/src/apidef.ts +264 -121
- package/src/builder/entity/{apiEntity.ts → entity.ts} +18 -11
- package/src/builder/entity/info.ts +53 -0
- package/src/builder/entity.ts +9 -35
- package/src/builder/flow/flowHeuristic01.ts +46 -12
- package/src/builder/flow.ts +39 -5
- package/src/def.ts +91 -0
- package/src/desc.ts +143 -0
- package/src/guide/guide.ts +207 -134
- package/src/guide/heuristic01.ts +1651 -272
- package/src/model.ts +98 -0
- package/src/parse.ts +5 -61
- package/src/schematron.ts.off +317 -0
- package/src/transform/args.ts +102 -0
- package/src/transform/clean.ts +43 -8
- package/src/transform/entity.ts +100 -51
- package/src/transform/field.ts +150 -71
- package/src/transform/operation.ts +118 -414
- package/src/transform/select.ts +90 -0
- package/src/transform/top.ts +76 -3
- package/src/transform.ts +4 -0
- package/src/types.ts +185 -5
- package/src/utility.ts +481 -9
- package/dist/builder/entity/apiEntity.d.ts +0 -3
- package/dist/builder/entity/apiEntity.js.map +0 -1
- package/dist/builder/entity/def.d.ts +0 -3
- package/dist/builder/entity/def.js +0 -19
- package/dist/builder/entity/def.js.map +0 -1
- package/src/builder/entity/def.ts +0 -44
- package/src/guide.ts.off +0 -136
package/package.json
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@voxgig/apidef",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.2",
|
|
4
4
|
"main": "dist/apidef.js",
|
|
5
5
|
"type": "commonjs",
|
|
6
6
|
"types": "dist/apidef.d.ts",
|
|
7
7
|
"description": "Voxgig SDK Generator.",
|
|
8
8
|
"homepage": "https://github.com/voxgig/voxgig-apidef",
|
|
9
9
|
"keywords": [
|
|
10
|
-
"voxgig
|
|
11
|
-
"
|
|
10
|
+
"voxgig",
|
|
11
|
+
"apidef",
|
|
12
|
+
"api",
|
|
13
|
+
"sdk"
|
|
12
14
|
],
|
|
13
15
|
"author": "Richard Rodger (http://richardrodger.com)",
|
|
14
16
|
"repository": {
|
|
@@ -20,7 +22,7 @@
|
|
|
20
22
|
},
|
|
21
23
|
"scripts": {
|
|
22
24
|
"test": "node --enable-source-maps --test \"dist-test/**/*.test.js\"",
|
|
23
|
-
"test-some": "node --enable-source-maps --test-name-pattern=\"$
|
|
25
|
+
"test-some": "node --enable-source-maps --test-name-pattern=\"$TEST_PATTERN\" --test \"dist-test/**/*.test.js\"",
|
|
24
26
|
"watch": "tsc --build src test -w",
|
|
25
27
|
"build": "tsc --build src test",
|
|
26
28
|
"clean": "rm -rf dist dist-test node_modules yarn.lock package-lock.json",
|
|
@@ -40,22 +42,25 @@
|
|
|
40
42
|
"devDependencies": {
|
|
41
43
|
"@hapi/code": "^9.0.3",
|
|
42
44
|
"@types/js-yaml": "^4.0.9",
|
|
43
|
-
"@types/node": "
|
|
44
|
-
"aontu": "^0.28.0",
|
|
45
|
+
"@types/node": "25.0.2",
|
|
45
46
|
"json-schema-to-ts": "^3.1.1",
|
|
46
|
-
"
|
|
47
|
-
|
|
47
|
+
"typescript": "^5.9.3"
|
|
48
|
+
},
|
|
49
|
+
"peerDependencies": {
|
|
50
|
+
"aontu": ">=0.33.2",
|
|
51
|
+
"memfs": ">=4.51.1"
|
|
48
52
|
},
|
|
49
53
|
"dependencies": {
|
|
50
54
|
"@redocly/openapi-core": "1.34.5",
|
|
51
55
|
"@voxgig/struct": "^0.0.9",
|
|
52
|
-
"@voxgig/util": "^0.2.
|
|
53
|
-
"chokidar": "^
|
|
56
|
+
"@voxgig/util": "^0.2.1",
|
|
57
|
+
"chokidar": "^5.0.0",
|
|
58
|
+
"decircular": "^1.0.0",
|
|
54
59
|
"diff": "^8.0.2",
|
|
55
60
|
"gubu": "^9.0.0",
|
|
56
|
-
"jostraca": "^0.
|
|
57
|
-
"
|
|
58
|
-
"pino
|
|
59
|
-
"
|
|
61
|
+
"jostraca": "^0.25.1",
|
|
62
|
+
"ordu": "^4.1.1",
|
|
63
|
+
"pino": "^10.1.0",
|
|
64
|
+
"pino-pretty": "^13.1.3"
|
|
60
65
|
}
|
|
61
66
|
}
|
package/src/apidef.ts
CHANGED
|
@@ -1,13 +1,18 @@
|
|
|
1
1
|
/* Copyright (c) 2024-2025 Voxgig, MIT License */
|
|
2
2
|
|
|
3
|
+
|
|
3
4
|
import * as Fs from 'node:fs'
|
|
4
5
|
import Path from 'node:path'
|
|
5
|
-
import { inspect } from 'node:util'
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
|
|
8
|
+
import {
|
|
9
|
+
Jostraca, JostracaResult, Project, names
|
|
10
|
+
} from 'jostraca'
|
|
8
11
|
|
|
9
12
|
import { prettyPino } from '@voxgig/util'
|
|
10
13
|
|
|
14
|
+
import decircular from 'decircular'
|
|
15
|
+
|
|
11
16
|
|
|
12
17
|
import type {
|
|
13
18
|
ApiDefOptions,
|
|
@@ -18,10 +23,14 @@ import type {
|
|
|
18
23
|
ApiModel,
|
|
19
24
|
} from './types'
|
|
20
25
|
|
|
26
|
+
|
|
21
27
|
import {
|
|
28
|
+
KIT,
|
|
29
|
+
|
|
22
30
|
OpenModelShape,
|
|
23
31
|
OpenBuildShape,
|
|
24
32
|
OpenControlShape,
|
|
33
|
+
ApiDefContext,
|
|
25
34
|
} from './types'
|
|
26
35
|
|
|
27
36
|
|
|
@@ -32,7 +41,6 @@ import {
|
|
|
32
41
|
|
|
33
42
|
import {
|
|
34
43
|
parse,
|
|
35
|
-
rewrite,
|
|
36
44
|
} from './parse'
|
|
37
45
|
|
|
38
46
|
|
|
@@ -49,11 +57,17 @@ import {
|
|
|
49
57
|
import {
|
|
50
58
|
loadFile,
|
|
51
59
|
getdlog,
|
|
60
|
+
makeWarner,
|
|
61
|
+
formatJSONIC,
|
|
62
|
+
writeFileSyncWarn,
|
|
52
63
|
} from './utility'
|
|
53
64
|
|
|
65
|
+
|
|
54
66
|
import { topTransform } from './transform/top'
|
|
55
67
|
import { entityTransform } from './transform/entity'
|
|
56
68
|
import { operationTransform } from './transform/operation'
|
|
69
|
+
import { argsTransform } from './transform/args'
|
|
70
|
+
import { selectTransform } from './transform/select'
|
|
57
71
|
import { fieldTransform } from './transform/field'
|
|
58
72
|
import { cleanTransform } from './transform/clean'
|
|
59
73
|
|
|
@@ -66,168 +80,263 @@ const dlog = getdlog('apidef', __filename)
|
|
|
66
80
|
|
|
67
81
|
function ApiDef(opts: ApiDefOptions) {
|
|
68
82
|
|
|
69
|
-
|
|
70
83
|
// TODO: gubu opts!
|
|
71
84
|
const fs = opts.fs || Fs
|
|
72
85
|
const pino = prettyPino('apidef', opts)
|
|
73
86
|
const log = pino.child({ cmp: 'apidef' })
|
|
87
|
+
const warn = makeWarner({ point: 'warning', log })
|
|
74
88
|
|
|
75
89
|
opts.strategy = opts.strategy || 'heuristic01'
|
|
76
90
|
|
|
77
|
-
|
|
78
91
|
async function generate(spec: any): Promise<ApiDefResult> {
|
|
79
92
|
const start = Date.now()
|
|
80
93
|
const steps: string[] = []
|
|
81
|
-
// dlog('start')
|
|
82
94
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
95
|
+
let ctx: ApiDefContext | undefined = undefined
|
|
96
|
+
let ctrl: Control | undefined = undefined
|
|
97
|
+
let jres: JostracaResult | undefined = undefined
|
|
86
98
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
return { ok: false, steps, start, end: Date.now(), ctrl }
|
|
90
|
-
}
|
|
99
|
+
try {
|
|
100
|
+
ctrl = OpenControlShape(spec.ctrl || {}) as Control
|
|
91
101
|
|
|
92
|
-
|
|
102
|
+
const model: Model = OpenModelShape(spec.model || {})
|
|
103
|
+
const build: Build = OpenBuildShape(spec.build || {})
|
|
93
104
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
105
|
+
// Step: parse (API spec).
|
|
106
|
+
if (!ctrl.step.parse) {
|
|
107
|
+
return { ok: true, steps, start, end: Date.now(), ctrl }
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
names(model, model.name)
|
|
111
|
+
|
|
112
|
+
const apimodel: ApiModel = {
|
|
113
|
+
main: {
|
|
114
|
+
api: {},
|
|
115
|
+
[KIT]: {
|
|
116
|
+
info: {},
|
|
117
|
+
entity: {},
|
|
118
|
+
flow: {},
|
|
119
|
+
},
|
|
120
|
+
def: {},
|
|
98
121
|
},
|
|
99
|
-
|
|
100
|
-
},
|
|
101
|
-
}
|
|
122
|
+
}
|
|
102
123
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
let defpath = model.def
|
|
106
|
-
|
|
107
|
-
// TOOD: defpath should be independently defined
|
|
108
|
-
defpath = Path.join(buildspec.base, '..', 'def', defpath)
|
|
109
|
-
|
|
110
|
-
log.info({
|
|
111
|
-
point: 'generate-start',
|
|
112
|
-
note: defpath.replace(process.cwd(), '.'), defpath, start
|
|
113
|
-
})
|
|
114
|
-
|
|
115
|
-
// TODO: Validate spec
|
|
116
|
-
const ctx = {
|
|
117
|
-
fs,
|
|
118
|
-
log,
|
|
119
|
-
spec,
|
|
120
|
-
opts,
|
|
121
|
-
util: { fixName },
|
|
122
|
-
defpath: Path.dirname(defpath),
|
|
123
|
-
model,
|
|
124
|
-
apimodel,
|
|
125
|
-
guide: {},
|
|
126
|
-
def: undefined,
|
|
127
|
-
note: {}
|
|
128
|
-
}
|
|
124
|
+
const buildspec = build.spec
|
|
129
125
|
|
|
130
|
-
|
|
126
|
+
let defpath = model.def
|
|
131
127
|
|
|
132
|
-
|
|
128
|
+
// TOOD: defpath should be independently defined
|
|
129
|
+
defpath = Path.join(buildspec.base, '..', 'def', defpath)
|
|
133
130
|
|
|
134
|
-
|
|
131
|
+
log.info({
|
|
132
|
+
point: 'generate-start',
|
|
133
|
+
note: defpath.replace(process.cwd(), '.'),
|
|
134
|
+
defpath,
|
|
135
|
+
start
|
|
136
|
+
})
|
|
135
137
|
|
|
136
|
-
|
|
138
|
+
// TODO: Validate spec
|
|
139
|
+
ctx = {
|
|
140
|
+
fs,
|
|
141
|
+
log,
|
|
142
|
+
spec,
|
|
143
|
+
opts,
|
|
144
|
+
util: { fixName },
|
|
145
|
+
defpath: Path.dirname(defpath),
|
|
146
|
+
model,
|
|
147
|
+
apimodel,
|
|
148
|
+
guide: {},
|
|
149
|
+
def: undefined,
|
|
150
|
+
note: {},
|
|
151
|
+
warn,
|
|
152
|
+
|
|
153
|
+
// TODO: remove (moved to guide)
|
|
154
|
+
metrics: {
|
|
155
|
+
count: {
|
|
156
|
+
path: 0,
|
|
157
|
+
method: 0,
|
|
158
|
+
origcmprefs: {},
|
|
159
|
+
cmp: 0,
|
|
160
|
+
tag: 0,
|
|
161
|
+
entity: 0,
|
|
162
|
+
},
|
|
163
|
+
found: {
|
|
164
|
+
cmp: {},
|
|
165
|
+
tag: {}
|
|
166
|
+
}
|
|
167
|
+
},
|
|
137
168
|
|
|
138
|
-
|
|
169
|
+
work: {}
|
|
170
|
+
}
|
|
139
171
|
|
|
140
|
-
|
|
172
|
+
const defsrc = loadFile(defpath, 'def', fs, log)
|
|
141
173
|
|
|
174
|
+
const def = await parse('OpenAPI', defsrc, { file: defpath })
|
|
175
|
+
const defkeys = Object.keys(def)
|
|
142
176
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
177
|
+
log.info({
|
|
178
|
+
point: 'root-keys',
|
|
179
|
+
defpath,
|
|
180
|
+
note: defkeys.join(', ')
|
|
181
|
+
})
|
|
147
182
|
|
|
148
|
-
|
|
149
|
-
|
|
183
|
+
const safedef = decircular(def)
|
|
184
|
+
const fullsrc = JSON.stringify(safedef, null, 2)
|
|
150
185
|
|
|
151
|
-
|
|
186
|
+
fs.writeFileSync(defpath + '.full.json', fullsrc)
|
|
152
187
|
|
|
188
|
+
ctx.def = safedef
|
|
153
189
|
|
|
154
|
-
|
|
155
|
-
if (!ctrl.step.transformers) {
|
|
156
|
-
return { ok: false, steps, start, end: Date.now(), ctrl, guide: ctx.guide }
|
|
157
|
-
}
|
|
190
|
+
steps.push('parse')
|
|
158
191
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
operation: operationTransform,
|
|
164
|
-
field: fieldTransform,
|
|
165
|
-
clean: cleanTransform,
|
|
166
|
-
})
|
|
192
|
+
// Step: guide (derive).
|
|
193
|
+
if (!ctrl.step.guide) {
|
|
194
|
+
return { ok: false, steps, start, end: Date.now(), ctrl }
|
|
195
|
+
}
|
|
167
196
|
|
|
168
|
-
|
|
197
|
+
const guideModel = await buildGuide(ctx)
|
|
198
|
+
if (null == guideModel) {
|
|
199
|
+
throw new Error('Unable to build guide.')
|
|
200
|
+
}
|
|
169
201
|
|
|
170
|
-
|
|
171
|
-
if (!ctrl.step.builders) {
|
|
172
|
-
return { ok: false, steps, start, end: Date.now(), ctrl, guide: ctx.guide }
|
|
173
|
-
}
|
|
202
|
+
ctx.guide = guideModel.guide
|
|
174
203
|
|
|
175
|
-
|
|
176
|
-
entity: makeEntityBuilder,
|
|
177
|
-
flow: makeFlowBuilder,
|
|
178
|
-
})
|
|
204
|
+
steps.push('guide')
|
|
179
205
|
|
|
180
|
-
steps.push('builders')
|
|
181
206
|
|
|
207
|
+
// Step: transformers (transform spec and guide into core structures).
|
|
208
|
+
if (!ctrl.step.transformers) {
|
|
209
|
+
return { ok: true, steps, start, end: Date.now(), ctrl, guide: ctx.guide }
|
|
210
|
+
}
|
|
182
211
|
|
|
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
|
-
}
|
|
187
212
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
213
|
+
/*
|
|
214
|
+
const transres = await resolveElements(ctx, 'transform', 'openapi', {
|
|
215
|
+
top: topTransform,
|
|
216
|
+
entity: entityTransform,
|
|
217
|
+
operation: operationTransform,
|
|
218
|
+
args: argsTransform,
|
|
219
|
+
field: fieldTransform,
|
|
220
|
+
clean: cleanTransform,
|
|
221
|
+
})
|
|
222
|
+
*/
|
|
223
|
+
|
|
224
|
+
// const transformResult = await runTransform(ctx)
|
|
225
|
+
// if (null == transformResult) {
|
|
226
|
+
// throw new Error('Unable to run Transform.')
|
|
227
|
+
// }
|
|
193
228
|
|
|
194
|
-
|
|
229
|
+
await topTransform(ctx)
|
|
230
|
+
await entityTransform(ctx)
|
|
231
|
+
await operationTransform(ctx)
|
|
232
|
+
await argsTransform(ctx)
|
|
233
|
+
await selectTransform(ctx)
|
|
234
|
+
await fieldTransform(ctx)
|
|
235
|
+
await cleanTransform(ctx)
|
|
195
236
|
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
237
|
+
|
|
238
|
+
steps.push('transformers')
|
|
239
|
+
|
|
240
|
+
// Step: builders (build generated sub models).
|
|
241
|
+
if (!ctrl.step.builders) {
|
|
242
|
+
return { ok: true, steps, start, end: Date.now(), ctrl, guide: ctx.guide }
|
|
199
243
|
}
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
244
|
+
|
|
245
|
+
const builders = [
|
|
246
|
+
await makeEntityBuilder(ctx),
|
|
247
|
+
|
|
248
|
+
// TODO: move to sdkgen
|
|
249
|
+
await makeFlowBuilder(ctx),
|
|
250
|
+
]
|
|
251
|
+
|
|
252
|
+
steps.push('builders')
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
// Step: generate (generate model files).
|
|
256
|
+
if (!ctrl.step.generate) {
|
|
257
|
+
return { ok: true, steps, start, end: Date.now(), ctrl, guide: ctx.guide }
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
const jostraca = Jostraca({
|
|
261
|
+
now: spec.now,
|
|
262
|
+
fs: () => fs,
|
|
263
|
+
log,
|
|
264
|
+
})
|
|
265
|
+
|
|
266
|
+
const jmodel = {}
|
|
267
|
+
|
|
268
|
+
const root = () => Project({ folder: '.' }, async () => {
|
|
269
|
+
for (let builder of builders) {
|
|
270
|
+
builder()
|
|
271
|
+
}
|
|
272
|
+
})
|
|
273
|
+
|
|
274
|
+
jres = await jostraca.generate({
|
|
275
|
+
// folder: Path.dirname(opts.folder as string),
|
|
276
|
+
folder: opts.folder,
|
|
277
|
+
model: jmodel,
|
|
278
|
+
existing: { txt: { merge: true } }
|
|
279
|
+
}, root)
|
|
280
|
+
|
|
281
|
+
const dlogs = dlog.log()
|
|
282
|
+
if (0 < dlogs.length) {
|
|
283
|
+
for (let dlogentry of dlogs) {
|
|
284
|
+
log.debug({ point: 'generate-debug', dlogentry, note: String(dlogentry) })
|
|
285
|
+
}
|
|
213
286
|
}
|
|
214
|
-
}
|
|
215
287
|
|
|
216
|
-
|
|
288
|
+
steps.push('generate')
|
|
217
289
|
|
|
218
|
-
|
|
290
|
+
const hasWarnings = 0 < warn.history.length
|
|
291
|
+
const endnote =
|
|
292
|
+
hasWarnings ? `PARTIAL BUILD! There were ${warn.history.length} warnings (see above).` :
|
|
293
|
+
'success'
|
|
294
|
+
log[hasWarnings ? 'warn' : 'info']({ point: 'generate-end', note: endnote, break: true })
|
|
295
|
+
|
|
296
|
+
if (hasWarnings) {
|
|
297
|
+
writeFileSyncWarn(warn, fs, './apidef-warnings.txt',
|
|
298
|
+
warn.history.map(n => formatJSONIC(n)).join('\n\n'))
|
|
299
|
+
}
|
|
219
300
|
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
301
|
+
return {
|
|
302
|
+
ok: true,
|
|
303
|
+
err: null,
|
|
304
|
+
start,
|
|
305
|
+
end: Date.now(),
|
|
306
|
+
steps,
|
|
307
|
+
ctrl,
|
|
308
|
+
guide: ctx.guide,
|
|
309
|
+
apimodel: ctx.apimodel,
|
|
310
|
+
ctx,
|
|
311
|
+
jres,
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
catch (err: any) {
|
|
315
|
+
const endnote = '!! BUILD FAILED !! ' + err.message
|
|
316
|
+
log.error({ point: 'generate-end', err, note: endnote, break: true })
|
|
317
|
+
|
|
318
|
+
warn.history.push({
|
|
319
|
+
point: warn.point,
|
|
320
|
+
when: Date.now(),
|
|
321
|
+
err,
|
|
322
|
+
note: endnote
|
|
323
|
+
})
|
|
226
324
|
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
325
|
+
writeFileSyncWarn(warn, fs, './apidef-warnings.txt',
|
|
326
|
+
warn.history.map(n => formatJSONIC(n)).join('\n\n'))
|
|
327
|
+
|
|
328
|
+
return {
|
|
329
|
+
ok: false,
|
|
330
|
+
err,
|
|
331
|
+
start,
|
|
332
|
+
end: Date.now(),
|
|
333
|
+
steps,
|
|
334
|
+
ctrl,
|
|
335
|
+
guide: ctx?.guide,
|
|
336
|
+
apimodel: ctx?.apimodel,
|
|
337
|
+
ctx,
|
|
338
|
+
jres,
|
|
339
|
+
}
|
|
231
340
|
}
|
|
232
341
|
}
|
|
233
342
|
|
|
@@ -258,6 +367,7 @@ ApiDef.makeBuild = async function(opts: ApiDefOptions) {
|
|
|
258
367
|
outprefix: opts.outprefix,
|
|
259
368
|
strategy: opts.strategy,
|
|
260
369
|
pino: build.log,
|
|
370
|
+
why: opts.why,
|
|
261
371
|
})
|
|
262
372
|
}
|
|
263
373
|
|
|
@@ -280,8 +390,41 @@ export type {
|
|
|
280
390
|
ApiDefOptions,
|
|
281
391
|
}
|
|
282
392
|
|
|
393
|
+
export type {
|
|
394
|
+
PathDef,
|
|
395
|
+
MethodDef,
|
|
396
|
+
ServerDef,
|
|
397
|
+
ServerVariableDef,
|
|
398
|
+
ParameterDef,
|
|
399
|
+
SchemaDef,
|
|
400
|
+
} from './def'
|
|
401
|
+
|
|
402
|
+
export type {
|
|
403
|
+
CmpDesc,
|
|
404
|
+
BasicMethodDesc,
|
|
405
|
+
MethodDesc,
|
|
406
|
+
MethodEntityDesc,
|
|
407
|
+
EntityDesc,
|
|
408
|
+
EntityPathDesc,
|
|
409
|
+
PathDesc,
|
|
410
|
+
OpDesc,
|
|
411
|
+
} from './desc'
|
|
412
|
+
|
|
413
|
+
export type {
|
|
414
|
+
OpName,
|
|
415
|
+
ModelEntityRelations,
|
|
416
|
+
ModelOpMap,
|
|
417
|
+
ModelFieldOp,
|
|
418
|
+
ModelField,
|
|
419
|
+
ModelArg,
|
|
420
|
+
ModelAlt,
|
|
421
|
+
ModelOp,
|
|
422
|
+
ModelEntity,
|
|
423
|
+
} from './model'
|
|
424
|
+
|
|
283
425
|
|
|
284
426
|
export {
|
|
285
427
|
ApiDef,
|
|
286
428
|
parse,
|
|
429
|
+
formatJSONIC,
|
|
287
430
|
}
|
|
@@ -6,38 +6,45 @@ import { each, File, Folder, Content } from 'jostraca'
|
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
import type {
|
|
9
|
+
KitModel,
|
|
9
10
|
ApiDefOptions,
|
|
10
11
|
} from '../../types'
|
|
11
12
|
|
|
12
13
|
import {
|
|
13
|
-
|
|
14
|
+
KIT
|
|
15
|
+
} from '../../types'
|
|
16
|
+
|
|
17
|
+
import {
|
|
18
|
+
formatJSONIC,
|
|
14
19
|
} from '../../utility'
|
|
15
20
|
|
|
16
21
|
|
|
17
22
|
|
|
18
|
-
function
|
|
23
|
+
function resolveEntity(
|
|
19
24
|
apimodel: any,
|
|
20
25
|
opts: ApiDefOptions,
|
|
21
26
|
) {
|
|
27
|
+
const kit: KitModel = apimodel.main[KIT]
|
|
28
|
+
|
|
22
29
|
const barrel = [
|
|
23
30
|
'# Entity Models\n'
|
|
24
31
|
]
|
|
25
32
|
|
|
26
33
|
const entityFiles: { name: string, src: string }[] = []
|
|
27
34
|
|
|
28
|
-
each(
|
|
35
|
+
each(kit.entity, ((entity: any, entityName: string) => {
|
|
29
36
|
const entityFile = (null == opts.outprefix ? '' : opts.outprefix) + entityName + '.jsonic'
|
|
30
37
|
|
|
31
|
-
|
|
32
|
-
|
|
38
|
+
let entityJSONIC = formatJSONIC(entity).trim()
|
|
39
|
+
entityJSONIC = entityJSONIC.substring(1, entityJSONIC.length - 1)
|
|
33
40
|
|
|
34
41
|
const fieldAliasesSrc = fieldAliases(entity)
|
|
35
42
|
|
|
36
43
|
const entitySrc =
|
|
37
44
|
`# Entity: ${entity.name}\n\n` +
|
|
38
|
-
`main:
|
|
45
|
+
`main: ${KIT}: entity: ${entity.name}: {\n\n` +
|
|
39
46
|
` alias: field: ${fieldAliasesSrc}\n` +
|
|
40
|
-
|
|
47
|
+
entityJSONIC +
|
|
41
48
|
'\n\n}\n'
|
|
42
49
|
|
|
43
50
|
entityFiles.push({ name: entityFile, src: entitySrc })
|
|
@@ -45,10 +52,10 @@ function resolveApiEntity(
|
|
|
45
52
|
barrel.push(`@"${Path.basename(entityFile)}"`)
|
|
46
53
|
}))
|
|
47
54
|
|
|
48
|
-
const indexFile = (null == opts.outprefix ? '' : opts.outprefix) + '
|
|
55
|
+
const indexFile = (null == opts.outprefix ? '' : opts.outprefix) + 'entity-index.jsonic'
|
|
49
56
|
|
|
50
57
|
return function apiEntityBuilder() {
|
|
51
|
-
Folder({ name: '
|
|
58
|
+
Folder({ name: 'entity' }, () => {
|
|
52
59
|
each(entityFiles, (entityFile) => {
|
|
53
60
|
File({ name: entityFile.name }, () => Content(entityFile.src))
|
|
54
61
|
})
|
|
@@ -56,9 +63,9 @@ function resolveApiEntity(
|
|
|
56
63
|
File({ name: indexFile }, () => Content(barrel.join('\n')))
|
|
57
64
|
})
|
|
58
65
|
}
|
|
59
|
-
|
|
60
66
|
}
|
|
61
67
|
|
|
68
|
+
|
|
62
69
|
function fieldAliases(entity: any) {
|
|
63
70
|
// HEURISTIC: id may be name_id or nameId
|
|
64
71
|
const fieldAliases =
|
|
@@ -84,5 +91,5 @@ function fieldAliases(entity: any) {
|
|
|
84
91
|
|
|
85
92
|
|
|
86
93
|
export {
|
|
87
|
-
|
|
94
|
+
resolveEntity
|
|
88
95
|
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/* Copyright (c) 2025 Voxgig, MIT License */
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
import { formatJSONIC } from '../../utility'
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
import type {
|
|
8
|
+
KitModel,
|
|
9
|
+
|
|
10
|
+
ApiDefOptions,
|
|
11
|
+
ApiModel,
|
|
12
|
+
} from '../../types'
|
|
13
|
+
|
|
14
|
+
import {
|
|
15
|
+
KIT
|
|
16
|
+
} from '../../types'
|
|
17
|
+
|
|
18
|
+
import {
|
|
19
|
+
File,
|
|
20
|
+
Folder,
|
|
21
|
+
Content
|
|
22
|
+
} from 'jostraca'
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
function resolveInfo(
|
|
26
|
+
apimodel: any,
|
|
27
|
+
opts: ApiDefOptions,
|
|
28
|
+
) {
|
|
29
|
+
const kit: KitModel = apimodel.main[KIT]
|
|
30
|
+
|
|
31
|
+
const infoFile =
|
|
32
|
+
(null == opts.outprefix ? '' : opts.outprefix) + 'api-info.jsonic'
|
|
33
|
+
|
|
34
|
+
const modelInfo = { main: { info: kit.info } }
|
|
35
|
+
|
|
36
|
+
let modelDefSrc = formatJSONIC(modelInfo)
|
|
37
|
+
|
|
38
|
+
modelDefSrc =
|
|
39
|
+
'# API Information\n\n' +
|
|
40
|
+
modelDefSrc.substring(1, modelDefSrc.length - 1).replace(/\n /g, '\n')
|
|
41
|
+
|
|
42
|
+
return function infoBuilder() {
|
|
43
|
+
Folder({ name: 'api' }, () => {
|
|
44
|
+
File({ name: infoFile }, () => Content(modelDefSrc))
|
|
45
|
+
})
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
export {
|
|
52
|
+
resolveInfo
|
|
53
|
+
}
|