@voxgig/apidef 0.1.4 → 0.3.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/run-apidef.js +178 -0
- package/bin/run-apidef.js~ +330 -0
- package/dist/apidef.d.ts +10 -1
- package/dist/apidef.js +166 -162
- package/dist/apidef.js.map +1 -1
- package/dist/transform/entity.d.ts +6 -0
- package/dist/transform/entity.js +35 -0
- package/dist/transform/entity.js.map +1 -0
- package/dist/transform/field.d.ts +6 -0
- package/dist/transform/field.js +144 -0
- package/dist/transform/field.js.map +1 -0
- package/dist/transform/fieldTransform.d.ts +5 -0
- package/dist/transform/fieldTransform.js +55 -0
- package/dist/transform/fieldTransform.js.map +1 -0
- package/dist/transform/manual.d.ts +6 -0
- package/dist/transform/manual.js +11 -0
- package/dist/transform/manual.js.map +1 -0
- package/dist/transform/operation.d.ts +6 -0
- package/dist/transform/operation.js +81 -0
- package/dist/transform/operation.js.map +1 -0
- package/dist/transform/top.d.ts +6 -0
- package/dist/transform/top.js +11 -0
- package/dist/transform/top.js.map +1 -0
- package/dist/transform.d.ts +26 -0
- package/dist/transform.js +111 -0
- package/dist/transform.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/model/guide.jsonic +32 -0
- package/package.json +14 -6
- package/src/apidef.ts +213 -233
- package/src/transform/entity.ts +54 -0
- package/src/transform/field.ts +185 -0
- package/src/transform/manual.ts +22 -0
- package/src/transform/operation.ts +125 -0
- package/src/transform/top.ts +21 -0
- package/src/transform.ts +193 -0
- package/model/guide.jsonic~ +0 -14
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const Path = require('node:path')
|
|
4
|
+
const { statSync } = require('node:fs')
|
|
5
|
+
const { parseArgs } = require('node:util')
|
|
6
|
+
|
|
7
|
+
const { Gubu, Fault, One } = require('gubu')
|
|
8
|
+
const { Aontu, Context } = require('aontu')
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
const Pkg = require('../package.json')
|
|
12
|
+
|
|
13
|
+
const { ApiDef } = require('../dist/apidef.js')
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
let CONSOLE = console
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
try {
|
|
20
|
+
let options = resolveOptions()
|
|
21
|
+
|
|
22
|
+
if(options.version) {
|
|
23
|
+
version()
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
if(options.help) {
|
|
27
|
+
help()
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
if(options.version || options.help) {
|
|
31
|
+
exit()
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
options = validateOptions(options)
|
|
35
|
+
|
|
36
|
+
generate(options)
|
|
37
|
+
|
|
38
|
+
}
|
|
39
|
+
catch(err) {
|
|
40
|
+
handleError(err)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
function exit(err) {
|
|
46
|
+
let code = 0
|
|
47
|
+
if(err) {
|
|
48
|
+
code = 1
|
|
49
|
+
}
|
|
50
|
+
process.exit(code)
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
function generate(options) {
|
|
55
|
+
const apidef = new ApiDef({
|
|
56
|
+
debug: options.debug
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
const spec = {
|
|
60
|
+
def: options.def,
|
|
61
|
+
kind: 'openapi-3',
|
|
62
|
+
model: Path.join(options.folder,'model/api.jsonic'),
|
|
63
|
+
meta: { name: options.name },
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if(options.watch) {
|
|
67
|
+
apidef.watch(spec)
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
apidef.generate(spec)
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
function resolveOptions() {
|
|
78
|
+
|
|
79
|
+
const args = parseArgs({
|
|
80
|
+
allowPositionals: true,
|
|
81
|
+
options: {
|
|
82
|
+
folder: {
|
|
83
|
+
type: 'string',
|
|
84
|
+
short: 'f',
|
|
85
|
+
default: '',
|
|
86
|
+
},
|
|
87
|
+
|
|
88
|
+
def: {
|
|
89
|
+
type: 'string',
|
|
90
|
+
short: 'd',
|
|
91
|
+
default: '',
|
|
92
|
+
},
|
|
93
|
+
|
|
94
|
+
watch: {
|
|
95
|
+
type: 'boolean',
|
|
96
|
+
short: 'w',
|
|
97
|
+
},
|
|
98
|
+
|
|
99
|
+
debug: {
|
|
100
|
+
type: 'string',
|
|
101
|
+
short: 'g',
|
|
102
|
+
default: 'info'
|
|
103
|
+
},
|
|
104
|
+
|
|
105
|
+
help: {
|
|
106
|
+
type: 'boolean',
|
|
107
|
+
short: 'h',
|
|
108
|
+
},
|
|
109
|
+
|
|
110
|
+
version: {
|
|
111
|
+
type: 'boolean',
|
|
112
|
+
short: 'v',
|
|
113
|
+
},
|
|
114
|
+
|
|
115
|
+
}
|
|
116
|
+
})
|
|
117
|
+
|
|
118
|
+
const options = {
|
|
119
|
+
name: args.positionals[0],
|
|
120
|
+
folder: '' === args.values.folder ? args.positionals[0] : args.values.folder,
|
|
121
|
+
def: args.values.def,
|
|
122
|
+
watch: !!args.values.watch,
|
|
123
|
+
debug: args.values.debug,
|
|
124
|
+
help: !!args.values.help,
|
|
125
|
+
version: !!args.values.version,
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
return options
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
function validateOptions(rawOptions) {
|
|
133
|
+
const optShape = Gubu({
|
|
134
|
+
name: Fault('The first argument should be the project name.', String),
|
|
135
|
+
folder: String,
|
|
136
|
+
def: '',
|
|
137
|
+
watch: Boolean,
|
|
138
|
+
debug: One(String,Boolean),
|
|
139
|
+
help: Boolean,
|
|
140
|
+
version: Boolean,
|
|
141
|
+
})
|
|
142
|
+
|
|
143
|
+
const err = []
|
|
144
|
+
const options = optShape(rawOptions,{err})
|
|
145
|
+
|
|
146
|
+
if(err[0]) {
|
|
147
|
+
throw new Error(err[0].text)
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
if('' !== options.def) {
|
|
151
|
+
options.def = Path.resolve(options.def)
|
|
152
|
+
const stat = statSync(options.def, {throwIfNoEntry:false})
|
|
153
|
+
if(null == stat) {
|
|
154
|
+
throw new Error('Definition file not found: '+options.def)
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
return options
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
function handleError(err) {
|
|
163
|
+
CONSOLE.log('Voxgig API Definition Error:')
|
|
164
|
+
CONSOLE.log(err)
|
|
165
|
+
|
|
166
|
+
exit(err)
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
function version() {
|
|
171
|
+
CONSOLE.log(Pkg.version)
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
function help() {
|
|
176
|
+
const s = 'TODO'
|
|
177
|
+
CONSOLE.log(s)
|
|
178
|
+
}
|
|
@@ -0,0 +1,330 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const Path = require('node:path')
|
|
4
|
+
const { statSync } = require('node:fs')
|
|
5
|
+
const { parseArgs } = require('node:util')
|
|
6
|
+
|
|
7
|
+
const { Gubu, Fault } = require('gubu')
|
|
8
|
+
const { Aontu, Context } = require('aontu')
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
const Pkg = require('../package.json')
|
|
12
|
+
|
|
13
|
+
const { CreateSdkGen } = require('../dist/create-sdkgen.js')
|
|
14
|
+
|
|
15
|
+
// const { Root } = require('../dist/standard/Root')
|
|
16
|
+
const rootpath = require.resolve('../dist/standard/Root')
|
|
17
|
+
|
|
18
|
+
let DEBUG = false
|
|
19
|
+
let CONSOLE = console
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
try {
|
|
23
|
+
let options = resolveOptions()
|
|
24
|
+
|
|
25
|
+
if(options.debug) {
|
|
26
|
+
DEBUG = true
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
if(options.version) {
|
|
30
|
+
version()
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if(options.help) {
|
|
34
|
+
help()
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if(options.version || options.help) {
|
|
38
|
+
exit()
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
options = validateOptions(options)
|
|
42
|
+
|
|
43
|
+
generate(options)
|
|
44
|
+
|
|
45
|
+
}
|
|
46
|
+
catch(err) {
|
|
47
|
+
handleError(err)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
function exit(err) {
|
|
53
|
+
let code = 0
|
|
54
|
+
if(err) {
|
|
55
|
+
code = 1
|
|
56
|
+
}
|
|
57
|
+
process.exit(code)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
function generate(options) {
|
|
62
|
+
const createSdkGen = CreateSdkGen({
|
|
63
|
+
folder: options.folder,
|
|
64
|
+
rootpath
|
|
65
|
+
})
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
const model = resolveModel(options)
|
|
69
|
+
|
|
70
|
+
const spec = {
|
|
71
|
+
// TODO: move to CreateSdkGen options
|
|
72
|
+
spec: options.spec,
|
|
73
|
+
model,
|
|
74
|
+
// root: Root,
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if(options.watch) {
|
|
78
|
+
spec.watch = [
|
|
79
|
+
'../tm',
|
|
80
|
+
'../feature',
|
|
81
|
+
'../def',
|
|
82
|
+
'../dist',
|
|
83
|
+
]
|
|
84
|
+
createSdkGen.watch(spec)
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
createSdkGen.generate(spec)
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
function resolveModel(options) {
|
|
94
|
+
|
|
95
|
+
const typespec = `
|
|
96
|
+
name: string
|
|
97
|
+
year: number
|
|
98
|
+
def: filepath: string
|
|
99
|
+
feature: &: {
|
|
100
|
+
active: *false | boolean
|
|
101
|
+
}
|
|
102
|
+
`
|
|
103
|
+
|
|
104
|
+
const features = options.feature.map(name=>`feature:${name}:active:true`)
|
|
105
|
+
|
|
106
|
+
const src = [
|
|
107
|
+
typespec,
|
|
108
|
+
`name: ${options.name}`,
|
|
109
|
+
`year: ${new Date().getFullYear()}`,
|
|
110
|
+
`def: filepath: "${options.def || 'def.yml'}"`,
|
|
111
|
+
'' === options.model ? '' : `@"${options.model}"`,
|
|
112
|
+
...(options.set||[]),
|
|
113
|
+
...(features||[]),
|
|
114
|
+
].join('\n')
|
|
115
|
+
const aopts = {}
|
|
116
|
+
const root = Aontu(src, aopts)
|
|
117
|
+
const hasErr = root.err && 0 < root.err.length
|
|
118
|
+
|
|
119
|
+
// TODO: collect all errors
|
|
120
|
+
if (hasErr) {
|
|
121
|
+
// console.log('ERROR ROOT', root.err)
|
|
122
|
+
throw root.err[0].msg
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
let genctx = new Context({ root })
|
|
126
|
+
const model = root.gen(genctx)
|
|
127
|
+
|
|
128
|
+
// TODO: collect all errors
|
|
129
|
+
if (genctx.err && 0 < genctx.err.length) {
|
|
130
|
+
// console.log(genctx.err)
|
|
131
|
+
// console.log('ERROR GEN', genctx.err)
|
|
132
|
+
throw new Error(JSON.stringify(genctx.err[0]))
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
model.def.filename = Path.basename(model.def.filepath)
|
|
136
|
+
|
|
137
|
+
// console.log('MODEL')
|
|
138
|
+
// console.dir(model,{depth:null})
|
|
139
|
+
|
|
140
|
+
return model
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
function resolveOptions() {
|
|
145
|
+
|
|
146
|
+
const args = parseArgs({
|
|
147
|
+
allowPositionals: true,
|
|
148
|
+
options: {
|
|
149
|
+
folder: {
|
|
150
|
+
type: 'string',
|
|
151
|
+
short: 'f',
|
|
152
|
+
default: '',
|
|
153
|
+
},
|
|
154
|
+
|
|
155
|
+
def: {
|
|
156
|
+
type: 'string',
|
|
157
|
+
short: 'd',
|
|
158
|
+
default: '',
|
|
159
|
+
},
|
|
160
|
+
|
|
161
|
+
set: {
|
|
162
|
+
type: 'string',
|
|
163
|
+
short: 's',
|
|
164
|
+
multiple: true,
|
|
165
|
+
},
|
|
166
|
+
|
|
167
|
+
model: {
|
|
168
|
+
type: 'string',
|
|
169
|
+
short: 'm',
|
|
170
|
+
default: '',
|
|
171
|
+
},
|
|
172
|
+
|
|
173
|
+
feature: {
|
|
174
|
+
type: 'string',
|
|
175
|
+
short: 't',
|
|
176
|
+
multiple: true,
|
|
177
|
+
},
|
|
178
|
+
|
|
179
|
+
watch: {
|
|
180
|
+
type: 'boolean',
|
|
181
|
+
short: 'w',
|
|
182
|
+
},
|
|
183
|
+
|
|
184
|
+
debug: {
|
|
185
|
+
type: 'boolean',
|
|
186
|
+
short: 'g',
|
|
187
|
+
},
|
|
188
|
+
|
|
189
|
+
help: {
|
|
190
|
+
type: 'boolean',
|
|
191
|
+
short: 'h',
|
|
192
|
+
},
|
|
193
|
+
|
|
194
|
+
version: {
|
|
195
|
+
type: 'boolean',
|
|
196
|
+
short: 'v',
|
|
197
|
+
},
|
|
198
|
+
|
|
199
|
+
}
|
|
200
|
+
})
|
|
201
|
+
|
|
202
|
+
const options = {
|
|
203
|
+
name: args.positionals[0],
|
|
204
|
+
folder: '' === args.values.folder ? args.positionals[0] : args.values.folder,
|
|
205
|
+
def: args.values.def,
|
|
206
|
+
model: args.values.model,
|
|
207
|
+
feature: args.values.feature,
|
|
208
|
+
set: args.values.set,
|
|
209
|
+
watch: !!args.values.watch,
|
|
210
|
+
debug: !!args.values.debug,
|
|
211
|
+
help: !!args.values.help,
|
|
212
|
+
version: !!args.values.version,
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
return options
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
function validateOptions(rawOptions) {
|
|
220
|
+
const optShape = Gubu({
|
|
221
|
+
name: Fault('The first argument should be the project name.', String),
|
|
222
|
+
folder: String,
|
|
223
|
+
def: '',
|
|
224
|
+
model: '',
|
|
225
|
+
feature: [String],
|
|
226
|
+
set: [String],
|
|
227
|
+
watch: Boolean,
|
|
228
|
+
debug: Boolean,
|
|
229
|
+
help: Boolean,
|
|
230
|
+
version: Boolean,
|
|
231
|
+
})
|
|
232
|
+
|
|
233
|
+
const err = []
|
|
234
|
+
const options = optShape(rawOptions,{err})
|
|
235
|
+
|
|
236
|
+
if(err[0]) {
|
|
237
|
+
throw new Error(err[0].text)
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
if('' !== options.def) {
|
|
241
|
+
options.def = Path.resolve(options.def)
|
|
242
|
+
const stat = statSync(options.def, {throwIfNoEntry:false})
|
|
243
|
+
if(null == stat) {
|
|
244
|
+
throw new Error('Definition file not found: '+options.def)
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
if('' !== options.model) {
|
|
249
|
+
options.model = Path.resolve(options.model)
|
|
250
|
+
const stat = statSync(options.model, {throwIfNoEntry:false})
|
|
251
|
+
if(null == stat) {
|
|
252
|
+
throw new Error('Model file not found: '+options.model)
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
return options
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
|
|
260
|
+
function handleError(err) {
|
|
261
|
+
CONSOLE.log('Voxgig SDK Generator Error:')
|
|
262
|
+
|
|
263
|
+
if(DEBUG) {
|
|
264
|
+
CONSOLE.log(err)
|
|
265
|
+
}
|
|
266
|
+
else {
|
|
267
|
+
CONSOLE.log(err.message)
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
exit(err)
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
|
|
274
|
+
function version() {
|
|
275
|
+
CONSOLE.log(Pkg.version)
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
|
|
279
|
+
function help() {
|
|
280
|
+
let s = `
|
|
281
|
+
Create a Voxgig SDK Generator project.
|
|
282
|
+
|
|
283
|
+
Usage: npm create @voxgig/sdkgen@latest <name> <args>
|
|
284
|
+
|
|
285
|
+
where <name> is the name of the SDK project. This is also used to
|
|
286
|
+
create a project folder if one is not explictly defined using the -f
|
|
287
|
+
argument. If run against an existing folder generated files will be
|
|
288
|
+
overwritten.
|
|
289
|
+
|
|
290
|
+
<args> are the command arguments:
|
|
291
|
+
|
|
292
|
+
--folder <folder> Specific the folder for the SDK project. Optional.
|
|
293
|
+
-f <folder> Default: <name> in current folder.
|
|
294
|
+
|
|
295
|
+
--def <file> Specify the API definition file (OpenAPI, Swagger, etc)
|
|
296
|
+
-d that defines the SDK. Optional.
|
|
297
|
+
|
|
298
|
+
--model <file> Specify the SDK model file to customize the SDK. Optional.
|
|
299
|
+
-m
|
|
300
|
+
|
|
301
|
+
--watch Run in watch mode. The SDK project will be updated if any of the
|
|
302
|
+
-w project inputs (such as the spec file) change.
|
|
303
|
+
|
|
304
|
+
--debug Print verbose logging.
|
|
305
|
+
-d
|
|
306
|
+
|
|
307
|
+
--help Print this help message.
|
|
308
|
+
-h
|
|
309
|
+
|
|
310
|
+
--version Print version number.
|
|
311
|
+
-v
|
|
312
|
+
|
|
313
|
+
|
|
314
|
+
Examples:
|
|
315
|
+
|
|
316
|
+
# Basic usage
|
|
317
|
+
> npm create @voxgig/sdkgen@latest foo
|
|
318
|
+
# Creates the SDK Project in the folder ./foo
|
|
319
|
+
|
|
320
|
+
|
|
321
|
+
# Custom project folder
|
|
322
|
+
> npm create @voxgig/sdkgen@latest foo -f ~/Projects/Foo
|
|
323
|
+
# Creates the SDK Project in the folder ~/Projects/Foo
|
|
324
|
+
|
|
325
|
+
|
|
326
|
+
See also: https://voxgig.com/sdkgen
|
|
327
|
+
`
|
|
328
|
+
|
|
329
|
+
CONSOLE.log(s)
|
|
330
|
+
}
|
package/dist/apidef.d.ts
CHANGED
|
@@ -1,9 +1,18 @@
|
|
|
1
|
+
import Pino from 'pino';
|
|
1
2
|
type ApiDefOptions = {
|
|
2
3
|
fs?: any;
|
|
4
|
+
pino?: ReturnType<typeof Pino>;
|
|
5
|
+
debug?: boolean | string;
|
|
6
|
+
};
|
|
7
|
+
type ApiDefSpec = {
|
|
8
|
+
def: string;
|
|
9
|
+
model: string;
|
|
10
|
+
kind: string;
|
|
11
|
+
meta: Record<string, any>;
|
|
3
12
|
};
|
|
4
13
|
declare function ApiDef(opts?: ApiDefOptions): {
|
|
5
14
|
watch: (spec: any) => Promise<void>;
|
|
6
|
-
generate: (spec:
|
|
15
|
+
generate: (spec: ApiDefSpec) => Promise<{
|
|
7
16
|
ok: boolean;
|
|
8
17
|
model: {
|
|
9
18
|
main: {
|