@voxgig/apidef 2.0.0 → 2.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.js +0 -19
- package/dist/apidef.js.map +1 -1
- package/dist/builder/flow/flowHeuristic01.js +37 -9
- package/dist/builder/flow/flowHeuristic01.js.map +1 -1
- package/dist/builder/flow.js +3 -3
- package/dist/builder/flow.js.map +1 -1
- package/dist/guide/heuristic01.js +51 -110
- package/dist/guide/heuristic01.js.map +1 -1
- package/dist/guide.js +2 -4
- package/dist/guide.js.map +1 -1
- package/dist/transform/entity.js +21 -2
- package/dist/transform/entity.js.map +1 -1
- package/dist/transform/operation.js +46 -27
- package/dist/transform/operation.js.map +1 -1
- package/dist/transform.js +1 -2
- package/dist/transform.js.map +1 -1
- package/dist/types.d.ts +9 -0
- package/dist/types.js +3 -2
- package/dist/types.js.map +1 -1
- package/dist/utility.d.ts +2 -1
- package/dist/utility.js +61 -36
- package/dist/utility.js.map +1 -1
- package/package.json +4 -4
- package/src/apidef.ts +0 -31
- package/src/builder/flow/flowHeuristic01.ts +44 -9
- package/src/builder/flow.ts +4 -3
- package/src/guide/heuristic01.ts +76 -123
- package/src/guide.ts +2 -6
- package/src/transform/entity.ts +26 -3
- package/src/transform/operation.ts +90 -38
- package/src/transform.ts +1 -2
- package/src/types.ts +3 -2
- package/src/utility.ts +79 -1
- package/src/builder/flow/flowHeuristic01.ts~ +0 -45
|
@@ -20,30 +20,53 @@ const operationTransform = async function(
|
|
|
20
20
|
|
|
21
21
|
let msg = 'operations: '
|
|
22
22
|
|
|
23
|
-
const paramBuilder = (
|
|
24
|
-
|
|
25
|
-
|
|
23
|
+
const paramBuilder = (
|
|
24
|
+
paramMap: any,
|
|
25
|
+
paramDef: any,
|
|
26
|
+
opModel: any,
|
|
27
|
+
entityModel: any,
|
|
28
|
+
pathdef: any,
|
|
29
|
+
op: any,
|
|
30
|
+
path: any,
|
|
31
|
+
entity: any,
|
|
32
|
+
model: any
|
|
33
|
+
) => {
|
|
26
34
|
|
|
27
|
-
paramMap[paramDef.name] = {
|
|
35
|
+
const paramSpec: any = paramMap[paramDef.name] = {
|
|
28
36
|
required: paramDef.required
|
|
29
37
|
}
|
|
30
|
-
fixName(
|
|
38
|
+
fixName(paramSpec, paramDef.name)
|
|
31
39
|
|
|
32
40
|
const type = paramDef.schema ? paramDef.schema.type : paramDef.type
|
|
33
|
-
fixName(
|
|
41
|
+
fixName(paramSpec, type, 'type')
|
|
42
|
+
|
|
43
|
+
// Path params are always required.
|
|
44
|
+
opModel.validate.params[paramDef.name] = `\`$${paramSpec.TYPE}\``
|
|
34
45
|
}
|
|
35
46
|
|
|
36
47
|
|
|
37
|
-
const queryBuilder = (
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
48
|
+
const queryBuilder = (
|
|
49
|
+
queryMap: any,
|
|
50
|
+
queryDef: any,
|
|
51
|
+
opModel: any,
|
|
52
|
+
entityModel: any,
|
|
53
|
+
pathdef: any,
|
|
54
|
+
op: any,
|
|
55
|
+
path: any,
|
|
56
|
+
entity: any,
|
|
57
|
+
model: any
|
|
58
|
+
) => {
|
|
59
|
+
const querySpec: any = queryMap[queryDef.name] = {
|
|
41
60
|
required: queryDef.required
|
|
42
61
|
}
|
|
43
62
|
fixName(queryMap[queryDef.name], queryDef.name)
|
|
44
63
|
|
|
45
64
|
const type = queryDef.schema ? queryDef.schema.type : queryDef.type
|
|
46
65
|
fixName(queryMap[queryDef.name], type, 'type')
|
|
66
|
+
|
|
67
|
+
if (queryDef.required) {
|
|
68
|
+
opModel.validate.params[queryDef.name] = `\`$${querySpec.TYPE}\``
|
|
69
|
+
}
|
|
47
70
|
}
|
|
48
71
|
|
|
49
72
|
|
|
@@ -57,6 +80,7 @@ const operationTransform = async function(
|
|
|
57
80
|
pathdef: any
|
|
58
81
|
) => {
|
|
59
82
|
let out
|
|
83
|
+
let why = 'none'
|
|
60
84
|
|
|
61
85
|
if (null != op.transform?.[direction]) {
|
|
62
86
|
out = op.transform[direction]
|
|
@@ -67,16 +91,12 @@ const operationTransform = async function(
|
|
|
67
91
|
const mdef = pathdef[method]
|
|
68
92
|
|
|
69
93
|
// TODO: fix getx
|
|
70
|
-
const content = 'res' === kind ?
|
|
94
|
+
// const content = 'res' === kind ?
|
|
95
|
+
const content = 'resform' === direction ?
|
|
71
96
|
(getx(mdef, 'responses.200.content') ||
|
|
72
97
|
getx(mdef, 'responses.201.content')) :
|
|
73
98
|
getx(mdef, 'requestBody.content')
|
|
74
99
|
|
|
75
|
-
// console.log(entityModel)
|
|
76
|
-
// console.log(mdef)
|
|
77
|
-
// console.log(getx(mdef, 'responses.200.content'))
|
|
78
|
-
// console.log(kind, method, pathdef, content)
|
|
79
|
-
|
|
80
100
|
if (content) {
|
|
81
101
|
|
|
82
102
|
const schema = content['application/json']?.schema
|
|
@@ -86,18 +106,22 @@ const operationTransform = async function(
|
|
|
86
106
|
const resolveDirectionTransform =
|
|
87
107
|
'resform' === direction ? resolveResponseTransform : resolveRequestTransform
|
|
88
108
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
109
|
+
//const [transform, why]
|
|
110
|
+
;[out, why]
|
|
111
|
+
= resolveDirectionTransform(
|
|
112
|
+
entityModel,
|
|
113
|
+
op,
|
|
114
|
+
kind,
|
|
115
|
+
direction,
|
|
116
|
+
method,
|
|
117
|
+
mdef,
|
|
118
|
+
content,
|
|
119
|
+
schema,
|
|
120
|
+
propkeys
|
|
121
|
+
)
|
|
98
122
|
|
|
99
123
|
// out = JSON.stringify(transform)
|
|
100
|
-
out = transform
|
|
124
|
+
// out = transform
|
|
101
125
|
}
|
|
102
126
|
else {
|
|
103
127
|
out = 'res' === kind ? '`body`' : '`reqdata`'
|
|
@@ -105,19 +129,22 @@ const operationTransform = async function(
|
|
|
105
129
|
}
|
|
106
130
|
|
|
107
131
|
|
|
108
|
-
return out
|
|
132
|
+
return [out, why]
|
|
109
133
|
}
|
|
110
134
|
|
|
111
135
|
|
|
112
136
|
const resolveResponseTransform = (
|
|
137
|
+
entityModel: any,
|
|
113
138
|
op: any,
|
|
114
139
|
kind: 'res' | 'req',
|
|
140
|
+
direction: 'resform' | 'reqform',
|
|
115
141
|
method: string,
|
|
116
142
|
mdef: any,
|
|
117
143
|
content: any,
|
|
118
144
|
schema: any,
|
|
119
145
|
propkeys: any
|
|
120
146
|
) => {
|
|
147
|
+
let why = 'default'
|
|
121
148
|
let transform: any = '`body`'
|
|
122
149
|
|
|
123
150
|
if (null == content || null == schema || null == propkeys) {
|
|
@@ -129,12 +156,14 @@ const operationTransform = async function(
|
|
|
129
156
|
if ('list' === opname) {
|
|
130
157
|
if ('array' !== schema.type) {
|
|
131
158
|
if (1 === propkeys.length) {
|
|
159
|
+
why = 'list-single-prop:' + propkeys[0]
|
|
132
160
|
transform = '`body.' + propkeys[0] + '`'
|
|
133
161
|
}
|
|
134
162
|
else {
|
|
135
163
|
// Use sub property that is an array
|
|
136
164
|
for (let pk of propkeys) {
|
|
137
165
|
if ('array' === schema.properties[pk]?.type) {
|
|
166
|
+
why = 'list-single-array:' + pk
|
|
138
167
|
transform = '`body.' + pk + '`'
|
|
139
168
|
break
|
|
140
169
|
}
|
|
@@ -146,11 +175,13 @@ const operationTransform = async function(
|
|
|
146
175
|
if ('object' === schema.type) {
|
|
147
176
|
if (null == schema.properties.id) {
|
|
148
177
|
if (1 === propkeys.length) {
|
|
178
|
+
why = 'map-single-prop:' + propkeys[0]
|
|
149
179
|
transform = '`body.' + propkeys[0] + '`'
|
|
150
180
|
}
|
|
151
181
|
else {
|
|
152
182
|
for (let pk of propkeys) {
|
|
153
183
|
if (schema.properties[pk].properties?.id) {
|
|
184
|
+
why = 'map-sub-prop:' + pk
|
|
154
185
|
transform = '`body.' + pk + '`'
|
|
155
186
|
break
|
|
156
187
|
}
|
|
@@ -160,13 +191,15 @@ const operationTransform = async function(
|
|
|
160
191
|
}
|
|
161
192
|
}
|
|
162
193
|
|
|
163
|
-
return transform
|
|
194
|
+
return [transform, why]
|
|
164
195
|
}
|
|
165
196
|
|
|
166
197
|
|
|
167
198
|
const resolveRequestTransform = (
|
|
199
|
+
entityModel: any,
|
|
168
200
|
op: any,
|
|
169
201
|
kind: 'res' | 'req',
|
|
202
|
+
direction: 'resform' | 'reqform',
|
|
170
203
|
method: string,
|
|
171
204
|
mdef: any,
|
|
172
205
|
content: any,
|
|
@@ -174,6 +207,7 @@ const operationTransform = async function(
|
|
|
174
207
|
propkeys: any
|
|
175
208
|
) => {
|
|
176
209
|
let transform: any = '`data`'
|
|
210
|
+
let why = 'default'
|
|
177
211
|
|
|
178
212
|
if (null == content || null == schema || null == propkeys) {
|
|
179
213
|
return transform
|
|
@@ -184,12 +218,14 @@ const operationTransform = async function(
|
|
|
184
218
|
if ('list' === opname) {
|
|
185
219
|
if ('array' !== schema.type) {
|
|
186
220
|
if (1 === propkeys.length) {
|
|
221
|
+
why = 'list-single-prop:' + propkeys[0]
|
|
187
222
|
transform = { [propkeys[0]]: '`data`' }
|
|
188
223
|
}
|
|
189
224
|
else {
|
|
190
225
|
// Use sub property that is an array
|
|
191
226
|
for (let pk of propkeys) {
|
|
192
227
|
if ('array' === schema.properties[pk]?.type) {
|
|
228
|
+
why = 'list-single-array:' + pk
|
|
193
229
|
transform = { [pk]: '`data`' }
|
|
194
230
|
break
|
|
195
231
|
}
|
|
@@ -201,11 +237,13 @@ const operationTransform = async function(
|
|
|
201
237
|
if ('object' === schema.type) {
|
|
202
238
|
if (null == schema.properties.id) {
|
|
203
239
|
if (1 === propkeys.length) {
|
|
240
|
+
why = 'map-single-prop:' + propkeys[0]
|
|
204
241
|
transform = { [propkeys[0]]: '`data`' }
|
|
205
242
|
}
|
|
206
243
|
else {
|
|
207
244
|
for (let pk of propkeys) {
|
|
208
245
|
if (schema.properties[pk].properties?.id) {
|
|
246
|
+
why = 'map-sub-prop:' + pk
|
|
209
247
|
transform = { [pk]: '`data`' }
|
|
210
248
|
break
|
|
211
249
|
}
|
|
@@ -215,7 +253,7 @@ const operationTransform = async function(
|
|
|
215
253
|
}
|
|
216
254
|
}
|
|
217
255
|
|
|
218
|
-
return transform
|
|
256
|
+
return [transform, why]
|
|
219
257
|
}
|
|
220
258
|
|
|
221
259
|
|
|
@@ -225,26 +263,39 @@ const operationTransform = async function(
|
|
|
225
263
|
const method = op.method
|
|
226
264
|
const kind = OPKIND[opname]
|
|
227
265
|
|
|
228
|
-
const
|
|
266
|
+
const [resform, resform_COMMENT] =
|
|
267
|
+
resolveTransform(entityModel, op, kind, 'resform', pathdef)
|
|
268
|
+
|
|
269
|
+
const [reqform, reqform_COMMENT] =
|
|
270
|
+
resolveTransform(entityModel, op, kind, 'reqform', pathdef)
|
|
271
|
+
|
|
272
|
+
const opModel = entityModel.op[opname] = {
|
|
229
273
|
path: path.key$,
|
|
230
274
|
method,
|
|
231
275
|
kind,
|
|
232
276
|
param: {},
|
|
233
277
|
query: {},
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
278
|
+
|
|
279
|
+
resform_COMMENT: 'derivation: ' + resform_COMMENT,
|
|
280
|
+
resform,
|
|
281
|
+
|
|
282
|
+
reqform_COMMENT: 'derivation: ' + reqform_COMMENT,
|
|
283
|
+
reqform,
|
|
284
|
+
|
|
285
|
+
validate: {
|
|
286
|
+
params: { '`$OPEN`': true }
|
|
287
|
+
}
|
|
238
288
|
}
|
|
239
289
|
|
|
240
|
-
fixName(
|
|
290
|
+
fixName(opModel, op.key$)
|
|
241
291
|
|
|
242
292
|
// Params are in the path
|
|
243
293
|
if (0 < path.params$.length) {
|
|
244
294
|
let params = getx(pathdef[method], 'parameters?in=path') || []
|
|
245
295
|
if (Array.isArray(params)) {
|
|
246
296
|
params.reduce((a: any, p: any) =>
|
|
247
|
-
|
|
297
|
+
(paramBuilder(a, p, opModel, entityModel,
|
|
298
|
+
pathdef, op, path, entity, model), a), opModel.param)
|
|
248
299
|
}
|
|
249
300
|
}
|
|
250
301
|
|
|
@@ -252,10 +303,11 @@ const operationTransform = async function(
|
|
|
252
303
|
let queries = getx(pathdef[op.val$], 'parameters?in!=path') || []
|
|
253
304
|
if (Array.isArray(queries)) {
|
|
254
305
|
queries.reduce((a: any, p: any) =>
|
|
255
|
-
|
|
306
|
+
(queryBuilder(a, p, opModel, entityModel,
|
|
307
|
+
pathdef, op, path, entity, model), a), opModel.query)
|
|
256
308
|
}
|
|
257
309
|
|
|
258
|
-
return
|
|
310
|
+
return opModel
|
|
259
311
|
},
|
|
260
312
|
|
|
261
313
|
|
package/src/transform.ts
CHANGED
|
@@ -106,7 +106,6 @@ async function resolveTransforms(ctx: TransformCtx): Promise<TransformSpec> {
|
|
|
106
106
|
}
|
|
107
107
|
}
|
|
108
108
|
catch (err: any) {
|
|
109
|
-
console.log(err)
|
|
110
109
|
throw err
|
|
111
110
|
}
|
|
112
111
|
|
|
@@ -181,7 +180,7 @@ async function processTransforms(
|
|
|
181
180
|
}
|
|
182
181
|
catch (err: any) {
|
|
183
182
|
// TODO: fix: this error does not get printed
|
|
184
|
-
console.
|
|
183
|
+
console.error(err)
|
|
185
184
|
|
|
186
185
|
pres.ok = false
|
|
187
186
|
pres.msg += transform.name + ': ' + err.message + '\n'
|
package/src/types.ts
CHANGED
|
@@ -29,11 +29,12 @@ const ModelShape = Gubu({
|
|
|
29
29
|
sdk: {},
|
|
30
30
|
def: {},
|
|
31
31
|
api: {
|
|
32
|
-
guide: {}
|
|
32
|
+
guide: {},
|
|
33
|
+
entity: {},
|
|
33
34
|
},
|
|
34
35
|
}
|
|
35
36
|
})
|
|
36
|
-
const OpenModelShape = Gubu(Open(ModelShape))
|
|
37
|
+
const OpenModelShape = Gubu(Open(ModelShape), { name: 'Model' })
|
|
37
38
|
|
|
38
39
|
type Model = ReturnType<typeof ModelShape>
|
|
39
40
|
|
package/src/utility.ts
CHANGED
|
@@ -24,9 +24,84 @@ function formatJsonSrc(jsonsrc: string) {
|
|
|
24
24
|
return jsonsrc
|
|
25
25
|
.replace(/"([a-zA-Z_][a-zA-Z_0-9]*)": /g, '$1: ')
|
|
26
26
|
.replace(/},/g, '}\n')
|
|
27
|
+
// .replace(/([a-zA-Z_][a-zA-Z_0-9]*)_COMMENT:/g, '# $1')
|
|
28
|
+
.replace(/\n(\s*)([a-zA-Z_][a-zA-Z_0-9]*)_COMMENT:\s*"(.*)",/g, '\n\n$1# $2 $3')
|
|
27
29
|
}
|
|
28
30
|
|
|
29
31
|
|
|
32
|
+
function depluralize(word: string): string {
|
|
33
|
+
if (!word || word.length === 0) {
|
|
34
|
+
return word
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Common irregular plurals
|
|
38
|
+
const irregulars: Record<string, string> = {
|
|
39
|
+
'children': 'child',
|
|
40
|
+
'men': 'man',
|
|
41
|
+
'women': 'woman',
|
|
42
|
+
'teeth': 'tooth',
|
|
43
|
+
'feet': 'foot',
|
|
44
|
+
'geese': 'goose',
|
|
45
|
+
'mice': 'mouse',
|
|
46
|
+
'people': 'person',
|
|
47
|
+
'data': 'datum',
|
|
48
|
+
'criteria': 'criterion',
|
|
49
|
+
'phenomena': 'phenomenon',
|
|
50
|
+
'indices': 'index',
|
|
51
|
+
'matrices': 'matrix',
|
|
52
|
+
'vertices': 'vertex',
|
|
53
|
+
'analyses': 'analysis',
|
|
54
|
+
'axes': 'axis',
|
|
55
|
+
'crises': 'crisis',
|
|
56
|
+
'diagnoses': 'diagnosis',
|
|
57
|
+
'oases': 'oasis',
|
|
58
|
+
'theses': 'thesis',
|
|
59
|
+
'appendices': 'appendix'
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (irregulars[word]) {
|
|
63
|
+
return irregulars[word]
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Rules for regular plurals (applied in order)
|
|
67
|
+
|
|
68
|
+
// -ies -> -y (cities -> city)
|
|
69
|
+
if (word.endsWith('ies') && word.length > 3) {
|
|
70
|
+
return word.slice(0, -3) + 'y'
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// -ves -> -f or -fe (wolves -> wolf, knives -> knife)
|
|
74
|
+
if (word.endsWith('ves')) {
|
|
75
|
+
const stem = word.slice(0, -3)
|
|
76
|
+
// Check if it should be -fe (like knife, wife, life)
|
|
77
|
+
if (['kni', 'wi', 'li'].includes(stem)) {
|
|
78
|
+
return stem + 'fe'
|
|
79
|
+
}
|
|
80
|
+
return stem + 'f'
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// -oes -> -o (potatoes -> potato)
|
|
84
|
+
if (word.endsWith('oes')) {
|
|
85
|
+
return word.slice(0, -2)
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// -ses, -xes, -zes, -shes, -ches -> remove -es (boxes -> box)
|
|
89
|
+
if (word.endsWith('ses') || word.endsWith('xes') || word.endsWith('zes') ||
|
|
90
|
+
word.endsWith('shes') || word.endsWith('ches')) {
|
|
91
|
+
return word.slice(0, -2)
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// -s -> remove -s (cats -> cat)
|
|
95
|
+
if (word.endsWith('s') && !word.endsWith('ss')) {
|
|
96
|
+
return word.slice(0, -1)
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// If none of the rules apply, return as is
|
|
100
|
+
return word
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
/*
|
|
30
105
|
function writeChanged(
|
|
31
106
|
point: string, path: string, content: string,
|
|
32
107
|
fs: FsUtil, log: Log,
|
|
@@ -74,10 +149,13 @@ function writeChanged(
|
|
|
74
149
|
throw err
|
|
75
150
|
}
|
|
76
151
|
}
|
|
152
|
+
*/
|
|
77
153
|
|
|
78
154
|
|
|
79
155
|
export {
|
|
80
156
|
loadFile,
|
|
81
|
-
formatJsonSrc
|
|
157
|
+
formatJsonSrc,
|
|
158
|
+
depluralize,
|
|
159
|
+
|
|
82
160
|
// writeChanged,
|
|
83
161
|
}
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
import { each, snakify, names } from 'jostraca'
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
async function flowHeuristic01(ctx: any): Promise<any[]> {
|
|
8
|
-
let entity = ctx.model.main.api.guide.entity
|
|
9
|
-
|
|
10
|
-
const flows: any[] = []
|
|
11
|
-
|
|
12
|
-
each(entity, (entity: any) => {
|
|
13
|
-
flows.push(resolveBasicEntityFlow(ctx, entity))
|
|
14
|
-
})
|
|
15
|
-
|
|
16
|
-
return flows
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
function resolveBasicEntityFlow(ctx: any, entity: any) {
|
|
23
|
-
const apiEntity = ctx.apimodel.main.api.entity[entity.name]
|
|
24
|
-
|
|
25
|
-
const flow: any = {
|
|
26
|
-
name: 'Basic' + apiEntity.Name
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
flow.model = ({
|
|
30
|
-
name: flow.Name,
|
|
31
|
-
param: {},
|
|
32
|
-
test: { entity: { [apiEntity.Name]: {} } },
|
|
33
|
-
step: []
|
|
34
|
-
} as any)
|
|
35
|
-
|
|
36
|
-
names(flow, flow.name)
|
|
37
|
-
|
|
38
|
-
return flow
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
export {
|
|
44
|
-
flowHeuristic01
|
|
45
|
-
}
|