@voxgig/apidef 1.1.0 → 1.2.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-apidef +0 -2
- package/dist/apidef.d.ts +28 -13
- package/dist/apidef.js +175 -135
- package/dist/apidef.js.map +1 -1
- package/dist/transform/entity.js +2 -1
- package/dist/transform/entity.js.map +1 -1
- package/dist/transform/field.js +1 -1
- package/dist/transform/field.js.map +1 -1
- package/dist/transform/manual.js +1 -1
- package/dist/transform/manual.js.map +1 -1
- package/dist/transform/operation.js +1 -1
- package/dist/transform/operation.js.map +1 -1
- package/dist/transform/top.d.ts +1 -1
- package/dist/transform/top.js +2 -3
- package/dist/transform/top.js.map +1 -1
- package/dist/transform.d.ts +5 -3
- package/dist/transform.js +16 -9
- package/dist/transform.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/model/apidef.jsonic +41 -0
- package/package.json +7 -7
- package/src/apidef.ts +178 -168
- package/src/transform/entity.ts +3 -1
- package/src/transform/field.ts +1 -1
- package/src/transform/manual.ts +1 -1
- package/src/transform/operation.ts +1 -2
- package/src/transform/top.ts +2 -2
- package/src/transform.ts +21 -11
package/dist/transform.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
type TransformCtx = {
|
|
2
2
|
log: any;
|
|
3
3
|
spec: any;
|
|
4
|
-
|
|
4
|
+
model: any;
|
|
5
5
|
opts: any;
|
|
6
6
|
util: any;
|
|
7
7
|
defpath: string;
|
|
@@ -12,15 +12,17 @@ type TransformSpec = {
|
|
|
12
12
|
type TransformResult = {
|
|
13
13
|
ok: boolean;
|
|
14
14
|
msg: string;
|
|
15
|
+
err?: any;
|
|
16
|
+
transform?: any;
|
|
15
17
|
};
|
|
16
|
-
type Transform = (ctx: TransformCtx, tspec: TransformSpec,
|
|
18
|
+
type Transform = (ctx: TransformCtx, tspec: TransformSpec, apimodel: any, def: any) => Promise<TransformResult>;
|
|
17
19
|
type ProcessResult = {
|
|
18
20
|
ok: boolean;
|
|
19
21
|
msg: string;
|
|
20
22
|
results: TransformResult[];
|
|
21
23
|
};
|
|
22
24
|
declare function resolveTransforms(ctx: TransformCtx): Promise<TransformSpec>;
|
|
23
|
-
declare function processTransforms(ctx: TransformCtx, spec: TransformSpec,
|
|
25
|
+
declare function processTransforms(ctx: TransformCtx, spec: TransformSpec, apimodel: any, def: any): Promise<ProcessResult>;
|
|
24
26
|
declare function fixName(base: any, name: string, prop?: string): void;
|
|
25
27
|
export type { TransformCtx, TransformSpec, };
|
|
26
28
|
export { fixName, resolveTransforms, processTransforms, };
|
package/dist/transform.js
CHANGED
|
@@ -22,7 +22,8 @@ const TRANSFORM = {
|
|
|
22
22
|
manual: manual_1.manualTransform,
|
|
23
23
|
};
|
|
24
24
|
async function resolveTransforms(ctx) {
|
|
25
|
-
const { log,
|
|
25
|
+
const { log, model: { main: { guide } } } = ctx;
|
|
26
|
+
// console.dir(api, { depth: null })
|
|
26
27
|
const tspec = {
|
|
27
28
|
transform: []
|
|
28
29
|
};
|
|
@@ -32,18 +33,23 @@ async function resolveTransforms(ctx) {
|
|
|
32
33
|
.split(/\s*,\s*/)
|
|
33
34
|
.map((t) => t.trim())
|
|
34
35
|
.filter((t) => '' != t);
|
|
35
|
-
log.info({
|
|
36
|
+
log.info({
|
|
37
|
+
point: 'transform', note: 'order: ' + transformNames.join(';'),
|
|
38
|
+
order: transformNames
|
|
39
|
+
});
|
|
36
40
|
for (const tn of transformNames) {
|
|
37
|
-
log.debug({ what: 'transform', transform: tn });
|
|
41
|
+
log.debug({ what: 'transform', transform: tn, note: tn });
|
|
38
42
|
const transform = await resolveTransform(tn, ctx);
|
|
39
43
|
tspec.transform.push(transform);
|
|
40
44
|
}
|
|
45
|
+
// console.log('TSPEC', tspec)
|
|
41
46
|
return tspec;
|
|
42
47
|
}
|
|
43
48
|
async function resolveTransform(tn, ctx) {
|
|
44
|
-
const { log, defpath,
|
|
49
|
+
const { log, defpath, model: { guide } } = ctx;
|
|
45
50
|
let transform = TRANSFORM[tn];
|
|
46
51
|
if (transform) {
|
|
52
|
+
// console.log('resolveTransform', tn, transform)
|
|
47
53
|
return transform;
|
|
48
54
|
}
|
|
49
55
|
const tdef = guide.transform[tn];
|
|
@@ -70,7 +76,7 @@ async function resolveTransform(tn, ctx) {
|
|
|
70
76
|
}
|
|
71
77
|
return transform;
|
|
72
78
|
}
|
|
73
|
-
async function processTransforms(ctx, spec,
|
|
79
|
+
async function processTransforms(ctx, spec, apimodel, def) {
|
|
74
80
|
const pres = {
|
|
75
81
|
ok: true,
|
|
76
82
|
msg: '',
|
|
@@ -79,17 +85,18 @@ async function processTransforms(ctx, spec, model, def) {
|
|
|
79
85
|
for (let tI = 0; tI < spec.transform.length; tI++) {
|
|
80
86
|
const transform = spec.transform[tI];
|
|
81
87
|
try {
|
|
82
|
-
const tres = await transform(ctx, spec,
|
|
88
|
+
const tres = await transform(ctx, spec, apimodel, def);
|
|
83
89
|
pres.ok = pres.ok && tres.ok;
|
|
84
|
-
pres.msg += tres.msg + '\n';
|
|
85
90
|
pres.results.push(tres);
|
|
86
91
|
}
|
|
87
92
|
catch (err) {
|
|
88
93
|
pres.ok = false;
|
|
89
|
-
pres.msg += err.message + '\n';
|
|
94
|
+
pres.msg += transform.name + ': ' + err.message + '\n';
|
|
90
95
|
pres.results.push({
|
|
91
96
|
ok: false,
|
|
92
|
-
msg: err.message
|
|
97
|
+
msg: err.message,
|
|
98
|
+
err,
|
|
99
|
+
transform
|
|
93
100
|
});
|
|
94
101
|
}
|
|
95
102
|
}
|
package/dist/transform.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transform.js","sourceRoot":"","sources":["../src/transform.ts"],"names":[],"mappings":";AAAA,4CAA4C;;;;;
|
|
1
|
+
{"version":3,"file":"transform.js","sourceRoot":"","sources":["../src/transform.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"root":["../src/apidef.ts","../src/transform.ts","../src/transform/entity.ts","../src/transform/field.ts","../src/transform/manual.ts","../src/transform/operation.ts","../src/transform/top.ts"],"version":"5.
|
|
1
|
+
{"root":["../src/apidef.ts","../src/transform.ts","../src/transform/entity.ts","../src/transform/field.ts","../src/transform/manual.ts","../src/transform/operation.ts","../src/transform/top.ts"],"version":"5.7.2"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
|
|
2
|
+
main: guide: control: transform: &: {
|
|
3
|
+
order: string
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
main: guide: control: transform: openapi: {
|
|
7
|
+
order: *`
|
|
8
|
+
|
|
9
|
+
top,
|
|
10
|
+
entity,
|
|
11
|
+
operation,
|
|
12
|
+
field,
|
|
13
|
+
manual,
|
|
14
|
+
|
|
15
|
+
` | string
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
main: guide: transform: &: {
|
|
20
|
+
name: .$KEY
|
|
21
|
+
load: string
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
main: guide: transform: {
|
|
25
|
+
top: {}
|
|
26
|
+
entity: {}
|
|
27
|
+
operation: {}
|
|
28
|
+
field: {}
|
|
29
|
+
manual: {}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
main: guide: entity: &: {
|
|
34
|
+
name: .$KEY
|
|
35
|
+
path: &: {
|
|
36
|
+
op: {}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@voxgig/apidef",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"main": "dist/apidef.js",
|
|
5
5
|
"type": "commonjs",
|
|
6
6
|
"types": "dist/apidef.d.ts",
|
|
@@ -41,19 +41,19 @@
|
|
|
41
41
|
"devDependencies": {
|
|
42
42
|
"@hapi/code": "^9.0.3",
|
|
43
43
|
"@types/js-yaml": "^4.0.9",
|
|
44
|
-
"@types/node": "22.
|
|
45
|
-
"aontu": "^0.25.
|
|
44
|
+
"@types/node": "22.10.0",
|
|
45
|
+
"aontu": "^0.25.3",
|
|
46
46
|
"esbuild": "^0.24.0",
|
|
47
47
|
"json-schema-to-ts": "^3.1.1",
|
|
48
48
|
"memfs": "^4.14.0",
|
|
49
|
-
"typescript": "^5.
|
|
49
|
+
"typescript": "^5.7.2"
|
|
50
50
|
},
|
|
51
51
|
"dependencies": {
|
|
52
|
-
"@redocly/openapi-core": "^1.25.
|
|
53
|
-
"@voxgig/util": "^0.0.
|
|
52
|
+
"@redocly/openapi-core": "^1.25.14",
|
|
53
|
+
"@voxgig/util": "^0.0.7",
|
|
54
54
|
"chokidar": "^4.0.1",
|
|
55
55
|
"gubu": "^8.3.0",
|
|
56
|
-
"jostraca": "^0.
|
|
56
|
+
"jostraca": "^0.10.1",
|
|
57
57
|
"pino": "^9.5.0",
|
|
58
58
|
"pino-pretty": "^13.0.0",
|
|
59
59
|
"sonic-boom": "^4.2.0"
|
package/src/apidef.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import * as Fs from 'node:fs'
|
|
4
4
|
import Path from 'node:path'
|
|
5
|
-
|
|
5
|
+
import { inspect } from 'node:util'
|
|
6
6
|
|
|
7
7
|
import { bundleFromString, createConfig } from '@redocly/openapi-core'
|
|
8
8
|
import { FSWatcher } from 'chokidar'
|
|
@@ -19,88 +19,60 @@ import {
|
|
|
19
19
|
|
|
20
20
|
|
|
21
21
|
type ApiDefOptions = {
|
|
22
|
+
def?: string
|
|
22
23
|
fs?: any
|
|
23
24
|
pino?: ReturnType<typeof Pino>
|
|
24
25
|
debug?: boolean | string
|
|
26
|
+
folder?: string
|
|
27
|
+
meta?: Record<string, any>
|
|
25
28
|
}
|
|
26
29
|
|
|
27
30
|
|
|
28
|
-
type ApiDefSpec = {
|
|
29
|
-
def: string
|
|
30
|
-
model: string,
|
|
31
|
-
kind: string,
|
|
32
|
-
meta: Record<string, any>,
|
|
33
|
-
guide: any
|
|
34
|
-
}
|
|
35
31
|
|
|
36
32
|
|
|
37
|
-
function ApiDef(opts: ApiDefOptions
|
|
33
|
+
function ApiDef(opts: ApiDefOptions) {
|
|
38
34
|
const fs = opts.fs || Fs
|
|
39
35
|
const pino = prettyPino('apidef', opts)
|
|
40
36
|
|
|
41
37
|
const log = pino.child({ cmp: 'apidef' })
|
|
42
38
|
|
|
43
39
|
|
|
44
|
-
async function
|
|
45
|
-
log.info({ point: 'watch-start' })
|
|
46
|
-
log.debug({ point: 'watch-spec', spec })
|
|
47
|
-
|
|
48
|
-
await generate(spec)
|
|
49
|
-
|
|
50
|
-
const fsw = new FSWatcher()
|
|
51
|
-
|
|
52
|
-
fsw.on('change', (...args: any[]) => {
|
|
53
|
-
log.trace({ watch: 'change', file: args[0] })
|
|
54
|
-
generate(spec)
|
|
55
|
-
})
|
|
56
|
-
|
|
57
|
-
log.trace({ watch: 'add', what: 'def', file: spec.def })
|
|
58
|
-
fsw.add(spec.def)
|
|
59
|
-
|
|
60
|
-
log.trace({ watch: 'add', what: 'guide', file: spec.guide })
|
|
61
|
-
fsw.add(spec.guide)
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
async function generate(spec: ApiDefSpec) {
|
|
40
|
+
async function generate(spec: any) {
|
|
66
41
|
const start = Date.now()
|
|
67
42
|
|
|
68
|
-
|
|
43
|
+
const buildspec = spec.build.spec
|
|
69
44
|
|
|
70
|
-
|
|
45
|
+
let defpath = spec.model.def
|
|
71
46
|
|
|
72
|
-
|
|
73
|
-
|
|
47
|
+
// TOOD: defpath should be independently defined
|
|
48
|
+
defpath = Path.join(buildspec.base, '..', 'def', defpath)
|
|
49
|
+
|
|
50
|
+
log.info({
|
|
51
|
+
point: 'generate-start',
|
|
52
|
+
note: defpath.replace(process.cwd(), '.'), defpath, start
|
|
53
|
+
})
|
|
74
54
|
|
|
75
55
|
// TODO: Validate spec
|
|
76
56
|
const ctx = {
|
|
77
57
|
log,
|
|
78
58
|
spec,
|
|
79
|
-
guide: {},
|
|
80
59
|
opts,
|
|
81
60
|
util: { fixName },
|
|
82
|
-
defpath: Path.dirname(defpath)
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
const guide = await resolveGuide(spec, opts)
|
|
88
|
-
|
|
89
|
-
if (null == guide) {
|
|
90
|
-
return
|
|
61
|
+
defpath: Path.dirname(defpath),
|
|
62
|
+
model: spec.model
|
|
91
63
|
}
|
|
92
64
|
|
|
93
|
-
|
|
94
|
-
log.debug({ point: 'guide', guide })
|
|
95
|
-
|
|
96
|
-
ctx.guide = guide
|
|
97
65
|
const transformSpec = await resolveTransforms(ctx)
|
|
98
|
-
|
|
66
|
+
|
|
67
|
+
log.debug({
|
|
68
|
+
point: 'transform', spec: transformSpec,
|
|
69
|
+
note: log.levelVal <= 20 ? inspect(transformSpec) : ''
|
|
70
|
+
})
|
|
99
71
|
|
|
100
72
|
|
|
101
73
|
let source
|
|
102
74
|
try {
|
|
103
|
-
source = fs.readFileSync(
|
|
75
|
+
source = fs.readFileSync(defpath, 'utf8')
|
|
104
76
|
}
|
|
105
77
|
catch (err: any) {
|
|
106
78
|
log.error({ read: 'fail', what: 'def', file: defpath, err })
|
|
@@ -124,7 +96,7 @@ function ApiDef(opts: ApiDefOptions = {}) {
|
|
|
124
96
|
}
|
|
125
97
|
|
|
126
98
|
|
|
127
|
-
const
|
|
99
|
+
const apimodel = {
|
|
128
100
|
main: {
|
|
129
101
|
api: {
|
|
130
102
|
entity: {}
|
|
@@ -133,36 +105,39 @@ function ApiDef(opts: ApiDefOptions = {}) {
|
|
|
133
105
|
},
|
|
134
106
|
}
|
|
135
107
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
const processResult = await processTransforms(ctx, transformSpec, model, def)
|
|
108
|
+
const def = bundle.bundle.parsed
|
|
109
|
+
const processResult = await processTransforms(ctx, transformSpec, apimodel, def)
|
|
139
110
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
catch (err: any) {
|
|
149
|
-
log.error({ process: 'fail', what: 'transform', err })
|
|
150
|
-
throw err
|
|
111
|
+
if (!processResult.ok) {
|
|
112
|
+
log.error({
|
|
113
|
+
fail: 'process', point: 'transform-result',
|
|
114
|
+
result: processResult, note: processResult.msg,
|
|
115
|
+
err: processResult.results[0]?.err
|
|
116
|
+
})
|
|
117
|
+
|
|
118
|
+
return { ok: false, processResult }
|
|
151
119
|
}
|
|
152
120
|
|
|
153
|
-
const modelapi = { main: { api:
|
|
121
|
+
const modelapi = { main: { api: apimodel.main.api } }
|
|
154
122
|
let modelSrc = JSON.stringify(modelapi, null, 2)
|
|
155
|
-
modelSrc = modelSrc.substring(1, modelSrc.length - 1)
|
|
156
123
|
|
|
157
|
-
|
|
124
|
+
modelSrc =
|
|
125
|
+
'# GENERATED FILE - DO NOT EDIT\n\n' +
|
|
126
|
+
modelSrc.substring(1, modelSrc.length - 1).replace(/\n /g, '\n')
|
|
158
127
|
|
|
128
|
+
const modelPath = Path.normalize(spec.config.model)
|
|
129
|
+
// console.log('modelPath', modelPath)
|
|
130
|
+
writeChanged('api-model', modelPath, modelSrc)
|
|
159
131
|
|
|
160
|
-
const modelBasePath = Path.dirname(
|
|
161
|
-
const defFilePath = Path.join(modelBasePath, 'def.jsonic')
|
|
132
|
+
const modelBasePath = Path.dirname(modelPath)
|
|
133
|
+
const defFilePath = Path.join(modelBasePath, 'def-generated.jsonic')
|
|
162
134
|
|
|
163
|
-
const modelDef = { main: { def:
|
|
135
|
+
const modelDef = { main: { def: apimodel.main.def } }
|
|
164
136
|
let modelDefSrc = JSON.stringify(modelDef, null, 2)
|
|
165
|
-
|
|
137
|
+
|
|
138
|
+
modelDefSrc =
|
|
139
|
+
'# GENERATED FILE - DO NOT EDIT\n\n' +
|
|
140
|
+
modelDefSrc.substring(1, modelDefSrc.length - 1).replace(/\n /g, '\n')
|
|
166
141
|
|
|
167
142
|
writeChanged('def-model', defFilePath, modelDefSrc)
|
|
168
143
|
|
|
@@ -170,13 +145,12 @@ function ApiDef(opts: ApiDefOptions = {}) {
|
|
|
170
145
|
|
|
171
146
|
return {
|
|
172
147
|
ok: true,
|
|
173
|
-
|
|
148
|
+
apimodel,
|
|
174
149
|
}
|
|
175
150
|
}
|
|
176
151
|
|
|
177
152
|
|
|
178
|
-
|
|
179
|
-
function writeChanged(what: string, path: string, content: string) {
|
|
153
|
+
function writeChanged(point: string, path: string, content: string) {
|
|
180
154
|
let exists = false
|
|
181
155
|
let changed = false
|
|
182
156
|
let action = ''
|
|
@@ -193,10 +167,12 @@ function ApiDef(opts: ApiDefOptions = {}) {
|
|
|
193
167
|
|
|
194
168
|
changed = existingContent !== content
|
|
195
169
|
|
|
170
|
+
// console.log('WC', changed, path, existingContent, content)
|
|
171
|
+
|
|
196
172
|
log.info({
|
|
197
|
-
point: 'write-' +
|
|
198
|
-
note: 'changed
|
|
199
|
-
write: 'file',
|
|
173
|
+
point: 'write-' + point,
|
|
174
|
+
note: (changed ? '' : 'not-') + 'changed ' + path,
|
|
175
|
+
write: 'file', skip: !changed, exists, changed,
|
|
200
176
|
contentLength: content.length, file: path
|
|
201
177
|
})
|
|
202
178
|
|
|
@@ -207,116 +183,150 @@ function ApiDef(opts: ApiDefOptions = {}) {
|
|
|
207
183
|
}
|
|
208
184
|
catch (err: any) {
|
|
209
185
|
log.error({
|
|
210
|
-
fail: action,
|
|
186
|
+
fail: action, point, file: path, exists, changed,
|
|
211
187
|
contentLength: content.length, err
|
|
212
188
|
})
|
|
189
|
+
err.__logged__ = true
|
|
213
190
|
throw err
|
|
214
191
|
}
|
|
215
192
|
}
|
|
216
193
|
|
|
217
194
|
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
const path = Path.normalize(spec.guide)
|
|
225
|
-
let src: string
|
|
226
|
-
|
|
227
|
-
let action = ''
|
|
228
|
-
let exists = false
|
|
229
|
-
try {
|
|
230
|
-
|
|
231
|
-
action = 'exists'
|
|
232
|
-
let exists = fs.existsSync(path)
|
|
233
|
-
|
|
234
|
-
log.debug({ read: 'file', what: 'guide', file: path, exists })
|
|
235
|
-
|
|
236
|
-
if (exists) {
|
|
237
|
-
action = 'read'
|
|
238
|
-
src = fs.readFileSync(path, 'utf8')
|
|
195
|
+
/*
|
|
196
|
+
async function resolveGuide(spec: any, _opts: any) {
|
|
197
|
+
if (null == spec.guide) {
|
|
198
|
+
spec.guide = spec.def + '-guide.jsonic'
|
|
239
199
|
}
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
\`
|
|
257
|
-
|
|
258
|
-
`
|
|
259
|
-
action = 'write'
|
|
260
|
-
fs.writeFileSync(path, src)
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
catch (err: any) {
|
|
264
|
-
log.error({ fail: action, what: 'guide', file: path, exists, err })
|
|
265
|
-
throw err
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
const aopts = { path }
|
|
269
|
-
const root = Aontu(src, aopts)
|
|
270
|
-
const hasErr = root.err && 0 < root.err.length
|
|
271
|
-
|
|
272
|
-
if (hasErr) {
|
|
273
|
-
for (let serr of root.err) {
|
|
274
|
-
let err: any = new Error('Guide model: ' + serr.msg)
|
|
275
|
-
err.cause$ = [serr]
|
|
276
|
-
|
|
277
|
-
if ('syntax' === serr.why) {
|
|
278
|
-
err.uxmsg$ = true
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
log.error({ fail: 'parse', point: 'guide-parse', file: path, err })
|
|
282
|
-
|
|
283
|
-
if (err.uxmsg$) {
|
|
284
|
-
return
|
|
200
|
+
|
|
201
|
+
const path = Path.normalize(spec.guide)
|
|
202
|
+
let src: string
|
|
203
|
+
|
|
204
|
+
let action = ''
|
|
205
|
+
let exists = false
|
|
206
|
+
try {
|
|
207
|
+
|
|
208
|
+
action = 'exists'
|
|
209
|
+
let exists = fs.existsSync(path)
|
|
210
|
+
|
|
211
|
+
log.debug({ read: 'file', what: 'guide', file: path, exists })
|
|
212
|
+
|
|
213
|
+
if (exists) {
|
|
214
|
+
action = 'read'
|
|
215
|
+
src = fs.readFileSync(path, 'utf8')
|
|
285
216
|
}
|
|
286
217
|
else {
|
|
287
|
-
|
|
288
|
-
|
|
218
|
+
src = `
|
|
219
|
+
# API Specification Transform Guide
|
|
220
|
+
|
|
221
|
+
@"@voxgig/apidef/model/guide.jsonic"
|
|
222
|
+
|
|
223
|
+
guide: entity: {
|
|
224
|
+
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
guide: control: transform: openapi: order: \`
|
|
228
|
+
top,
|
|
229
|
+
entity,
|
|
230
|
+
operation,
|
|
231
|
+
field,
|
|
232
|
+
manual,
|
|
233
|
+
\`
|
|
234
|
+
|
|
235
|
+
`
|
|
236
|
+
action = 'write'
|
|
237
|
+
fs.writeFileSync(path, src)
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
catch (err: any) {
|
|
241
|
+
log.error({ fail: action, what: 'guide', file: path, exists, err })
|
|
242
|
+
throw err
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
const aopts = { path }
|
|
246
|
+
const root = Aontu(src, aopts)
|
|
247
|
+
const hasErr = root.err && 0 < root.err.length
|
|
248
|
+
|
|
249
|
+
if (hasErr) {
|
|
250
|
+
for (let serr of root.err) {
|
|
251
|
+
let err: any = new Error('Guide model: ' + serr.msg)
|
|
252
|
+
err.cause$ = [serr]
|
|
253
|
+
|
|
254
|
+
if ('syntax' === serr.why) {
|
|
255
|
+
err.uxmsg$ = true
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
log.error({ fail: 'parse', point: 'guide-parse', file: path, err })
|
|
259
|
+
|
|
260
|
+
if (err.uxmsg$) {
|
|
261
|
+
return
|
|
262
|
+
}
|
|
263
|
+
else {
|
|
264
|
+
err.rooterrs$ = root.err
|
|
265
|
+
throw err
|
|
266
|
+
}
|
|
289
267
|
}
|
|
290
268
|
}
|
|
269
|
+
|
|
270
|
+
let genctx = new Context({ root })
|
|
271
|
+
const guide = spec.guideModel = root.gen(genctx)
|
|
272
|
+
|
|
273
|
+
// TODO: collect all errors
|
|
274
|
+
if (genctx.err && 0 < genctx.err.length) {
|
|
275
|
+
const err: any = new Error('Guide build error:\n' +
|
|
276
|
+
(genctx.err.map((pe: any) => pe.msg)).join('\n'))
|
|
277
|
+
log.error({ fail: 'build', what: 'guide', file: path, err })
|
|
278
|
+
err.errs = () => genctx.err
|
|
279
|
+
throw err
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
const pathParts = Path.parse(path)
|
|
283
|
+
spec.guideModelPath = Path.join(pathParts.dir, pathParts.name + '.json')
|
|
284
|
+
|
|
285
|
+
const updatedSrc = JSON.stringify(guide, null, 2)
|
|
286
|
+
|
|
287
|
+
writeChanged('guide-model', spec.guideModelPath, updatedSrc)
|
|
288
|
+
|
|
289
|
+
return guide
|
|
291
290
|
}
|
|
291
|
+
*/
|
|
292
292
|
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
const err: any = new Error('Guide build error:\n' +
|
|
299
|
-
(genctx.err.map((pe: any) => pe.msg)).join('\n'))
|
|
300
|
-
log.error({ fail: 'build', what: 'guide', file: path, err })
|
|
301
|
-
err.errs = () => genctx.err
|
|
302
|
-
throw err
|
|
303
|
-
}
|
|
293
|
+
return {
|
|
294
|
+
// watch,
|
|
295
|
+
generate,
|
|
296
|
+
}
|
|
297
|
+
}
|
|
304
298
|
|
|
305
|
-
const pathParts = Path.parse(path)
|
|
306
|
-
spec.guideModelPath = Path.join(pathParts.dir, pathParts.name + '.json')
|
|
307
299
|
|
|
308
|
-
const updatedSrc = JSON.stringify(guide, null, 2)
|
|
309
300
|
|
|
310
|
-
|
|
301
|
+
ApiDef.makeBuild = async function(opts: ApiDefOptions) {
|
|
302
|
+
let apidef: any = undefined
|
|
311
303
|
|
|
312
|
-
|
|
304
|
+
const config = {
|
|
305
|
+
def: opts.def || 'no-def',
|
|
306
|
+
kind: 'openapi3',
|
|
307
|
+
model: opts.folder ? (opts.folder + '/api-generated.jsonic') : 'no-model',
|
|
308
|
+
meta: opts.meta || {},
|
|
313
309
|
}
|
|
314
310
|
|
|
311
|
+
const build = async function(model: any, build: any, ctx: any) {
|
|
312
|
+
// console.log('APIDEF build')
|
|
313
|
+
// console.dir(ctx, { depth: null })
|
|
314
|
+
// console.dir(build, { depth: null })
|
|
315
315
|
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
316
|
+
|
|
317
|
+
if (null == apidef) {
|
|
318
|
+
apidef = ApiDef({
|
|
319
|
+
...opts,
|
|
320
|
+
pino: build.log,
|
|
321
|
+
})
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
await apidef.generate({ model, build, config })
|
|
319
325
|
}
|
|
326
|
+
|
|
327
|
+
build.step = 'pre'
|
|
328
|
+
|
|
329
|
+
return build
|
|
320
330
|
}
|
|
321
331
|
|
|
322
332
|
|
|
@@ -324,7 +334,7 @@ guide: control: transform: openapi: order: \`
|
|
|
324
334
|
|
|
325
335
|
export type {
|
|
326
336
|
ApiDefOptions,
|
|
327
|
-
ApiDefSpec,
|
|
337
|
+
// ApiDefSpec,
|
|
328
338
|
}
|
|
329
339
|
|
|
330
340
|
|
package/src/transform/entity.ts
CHANGED
|
@@ -9,9 +9,11 @@ import { fixName } from '../transform'
|
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
async function entityTransform(ctx: TransformCtx, tspec: TransformSpec, model: any, def: any) {
|
|
12
|
-
const {
|
|
12
|
+
const { model: { main: { guide } } } = ctx
|
|
13
13
|
let msg = ''
|
|
14
14
|
|
|
15
|
+
// console.log('DEF', def)
|
|
16
|
+
|
|
15
17
|
each(guide.entity, (guideEntity: any) => {
|
|
16
18
|
|
|
17
19
|
const entityModel: any = model.main.api.entity[guideEntity.key$] = {
|