@voxgig/apidef 2.4.1 → 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 +17 -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
|
@@ -1,475 +1,179 @@
|
|
|
1
1
|
|
|
2
2
|
|
|
3
|
-
import { each,
|
|
3
|
+
import { each, snakify } from 'jostraca'
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import { getelem, isempty } from '@voxgig/struct'
|
|
6
6
|
|
|
7
|
-
import type { TransformResult } from '../transform'
|
|
7
|
+
import type { TransformResult, Transform } from '../transform'
|
|
8
8
|
|
|
9
|
-
import { fixName
|
|
9
|
+
import { fixName } from '../transform'
|
|
10
10
|
|
|
11
|
-
import {
|
|
11
|
+
import { formatJSONIC } from '../utility'
|
|
12
12
|
|
|
13
|
+
import { KIT } from '../types'
|
|
13
14
|
|
|
14
|
-
|
|
15
|
-
ctx: any,
|
|
16
|
-
): Promise<TransformResult> {
|
|
17
|
-
const { apimodel, model, def, guide } = ctx
|
|
18
|
-
|
|
19
|
-
let msg = 'operations: '
|
|
20
|
-
|
|
21
|
-
const paramBuilder = (
|
|
22
|
-
paramMap: any,
|
|
23
|
-
paramDef: any,
|
|
24
|
-
opModel: any,
|
|
25
|
-
entityModel: any,
|
|
26
|
-
pathdef: any,
|
|
27
|
-
op: any,
|
|
28
|
-
path: any,
|
|
29
|
-
entity: any,
|
|
30
|
-
model: any
|
|
31
|
-
) => {
|
|
32
|
-
const paramSpec: any = paramMap[paramDef.name] = {
|
|
33
|
-
required: paramDef.required
|
|
34
|
-
}
|
|
35
|
-
fixName(paramSpec, paramDef.name)
|
|
15
|
+
import type { KitModel } from '../types'
|
|
36
16
|
|
|
37
|
-
|
|
38
|
-
|
|
17
|
+
import type {
|
|
18
|
+
GuideEntity,
|
|
19
|
+
} from './top'
|
|
39
20
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
21
|
+
import type {
|
|
22
|
+
GuideOp,
|
|
23
|
+
PathDesc,
|
|
24
|
+
} from '../desc'
|
|
43
25
|
|
|
26
|
+
import type {
|
|
27
|
+
OpName,
|
|
28
|
+
ModelOpMap,
|
|
29
|
+
ModelOp,
|
|
30
|
+
ModelAlt,
|
|
31
|
+
} from '../model'
|
|
44
32
|
|
|
45
|
-
const queryBuilder = (
|
|
46
|
-
queryMap: any,
|
|
47
|
-
queryDef: any,
|
|
48
|
-
opModel: any,
|
|
49
|
-
entityModel: any,
|
|
50
|
-
pathdef: any,
|
|
51
|
-
op: any,
|
|
52
|
-
path: any,
|
|
53
|
-
entity: any,
|
|
54
|
-
model: any
|
|
55
|
-
) => {
|
|
56
|
-
const querySpec: any = queryMap[queryDef.name] = {
|
|
57
|
-
required: queryDef.required
|
|
58
|
-
}
|
|
59
|
-
fixName(queryMap[queryDef.name], queryDef.name)
|
|
60
33
|
|
|
61
|
-
const type = queryDef.schema ? queryDef.schema.type : queryDef.type
|
|
62
|
-
fixName(queryMap[queryDef.name], type, 'type')
|
|
63
34
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
// Resolve the JSON structure of the request or response.
|
|
71
|
-
// NOTE: uses heuristics.
|
|
72
|
-
const resolveTransform = (
|
|
73
|
-
entityModel: any,
|
|
74
|
-
op: any,
|
|
75
|
-
kind: 'res' | 'req',
|
|
76
|
-
direction: 'resform' | 'reqform',
|
|
77
|
-
pathdef: any
|
|
78
|
-
) => {
|
|
79
|
-
let out
|
|
80
|
-
let why = 'none'
|
|
81
|
-
|
|
82
|
-
if (null != op.transform?.[direction]) {
|
|
83
|
-
out = op.transform[direction]
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
else {
|
|
87
|
-
const method = op.method
|
|
88
|
-
const mdef = pathdef[method]
|
|
89
|
-
|
|
90
|
-
// TODO: fix getx
|
|
91
|
-
// const content = 'res' === kind ?
|
|
92
|
-
const content = 'resform' === direction ?
|
|
93
|
-
(getx(mdef, 'responses.200.content') ||
|
|
94
|
-
getx(mdef, 'responses.201.content')) :
|
|
95
|
-
getx(mdef, 'requestBody.content')
|
|
96
|
-
|
|
97
|
-
if (content) {
|
|
98
|
-
|
|
99
|
-
const schema = content['application/json']?.schema
|
|
100
|
-
|
|
101
|
-
const propkeys = null == schema?.properties ? [] : Object.keys(schema.properties)
|
|
102
|
-
|
|
103
|
-
const resolveDirectionTransform =
|
|
104
|
-
'resform' === direction ? resolveResponseTransform : resolveRequestTransform
|
|
105
|
-
|
|
106
|
-
//const [transform, why]
|
|
107
|
-
;[out, why]
|
|
108
|
-
= resolveDirectionTransform(
|
|
109
|
-
entityModel,
|
|
110
|
-
op,
|
|
111
|
-
kind,
|
|
112
|
-
direction,
|
|
113
|
-
method,
|
|
114
|
-
mdef,
|
|
115
|
-
content,
|
|
116
|
-
schema,
|
|
117
|
-
propkeys
|
|
118
|
-
)
|
|
119
|
-
|
|
120
|
-
// out = JSON.stringify(transform)
|
|
121
|
-
// out = transform
|
|
122
|
-
}
|
|
123
|
-
else {
|
|
124
|
-
out = 'res' === kind ? '`body`' : '`reqdata`'
|
|
125
|
-
}
|
|
126
|
-
}
|
|
35
|
+
const operationTransform = async function(
|
|
36
|
+
ctx: any,
|
|
37
|
+
): Promise<TransformResult> {
|
|
38
|
+
const { apimodel, guide } = ctx
|
|
39
|
+
const kit = apimodel.main[KIT]
|
|
127
40
|
|
|
41
|
+
let msg = 'operation '
|
|
128
42
|
|
|
129
|
-
return [out, why]
|
|
130
|
-
}
|
|
131
43
|
|
|
44
|
+
each(guide.entity, (gent: GuideEntity, entname: string) => {
|
|
45
|
+
collectOps(gent)
|
|
132
46
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
content: any,
|
|
141
|
-
schema: any,
|
|
142
|
-
propkeys: any
|
|
143
|
-
): [any, string] => {
|
|
144
|
-
let why = 'default'
|
|
145
|
-
let transform: any = '`body`'
|
|
146
|
-
const properties = schema?.properties
|
|
147
|
-
|
|
148
|
-
if (null == content || null == schema || null == propkeys || null == properties) {
|
|
149
|
-
return [transform, why]
|
|
47
|
+
const opm: ModelOpMap = {
|
|
48
|
+
load: undefined,
|
|
49
|
+
list: undefined,
|
|
50
|
+
create: undefined,
|
|
51
|
+
update: undefined,
|
|
52
|
+
delete: undefined,
|
|
53
|
+
patch: undefined,
|
|
150
54
|
}
|
|
151
55
|
|
|
152
|
-
|
|
56
|
+
resolveLoad(opm, gent)
|
|
57
|
+
resolveList(opm, gent)
|
|
58
|
+
resolveCreate(opm, gent)
|
|
59
|
+
resolveUpdate(opm, gent)
|
|
60
|
+
resolveDelete(opm, gent)
|
|
61
|
+
resolvePatch(opm, gent)
|
|
153
62
|
|
|
154
|
-
|
|
155
|
-
if ('array' !== schema.type) {
|
|
156
|
-
if (1 === propkeys.length) {
|
|
157
|
-
why = 'list-single-prop:' + propkeys[0]
|
|
158
|
-
transform = '`body.' + propkeys[0] + '`'
|
|
159
|
-
}
|
|
160
|
-
else {
|
|
161
|
-
// Use sub property that is an array
|
|
162
|
-
for (let pk of propkeys) {
|
|
163
|
-
if ('array' === properties[pk]?.type) {
|
|
164
|
-
why = 'list-single-array:' + pk
|
|
165
|
-
transform = '`body.' + pk + '`'
|
|
166
|
-
|
|
167
|
-
// TODO: if each item has prop === name of entity, use that, get with $EACH
|
|
168
|
-
|
|
169
|
-
break
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
else {
|
|
176
|
-
if ('object' === schema.type) {
|
|
177
|
-
if (null == properties.id) {
|
|
178
|
-
if (1 === propkeys.length) {
|
|
179
|
-
why = 'map-single-prop:' + propkeys[0]
|
|
180
|
-
transform = '`body.' + propkeys[0] + '`'
|
|
181
|
-
}
|
|
182
|
-
else {
|
|
183
|
-
for (let pk of propkeys) {
|
|
184
|
-
if (properties[pk]?.properties?.id) {
|
|
185
|
-
why = 'map-sub-prop:' + pk
|
|
186
|
-
transform = '`body.' + pk + '`'
|
|
187
|
-
break
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
return [transform, why]
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
const resolveRequestTransform = (
|
|
200
|
-
entityModel: any,
|
|
201
|
-
op: any,
|
|
202
|
-
kind: 'res' | 'req',
|
|
203
|
-
direction: 'resform' | 'reqform',
|
|
204
|
-
method: string,
|
|
205
|
-
mdef: any,
|
|
206
|
-
content: any,
|
|
207
|
-
schema: any,
|
|
208
|
-
propkeys: any
|
|
209
|
-
): [any, string] => {
|
|
210
|
-
let transform: any = '`reqdata`'
|
|
211
|
-
let why = 'default'
|
|
212
|
-
const properties = schema?.properties
|
|
213
|
-
|
|
214
|
-
if (null == content || null == schema || null == propkeys || null == properties) {
|
|
215
|
-
return [transform, why]
|
|
216
|
-
}
|
|
63
|
+
kit.entity[entname].op = opm
|
|
217
64
|
|
|
218
|
-
|
|
65
|
+
msg += gent.name + ' '
|
|
66
|
+
})
|
|
219
67
|
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
if (1 === propkeys.length) {
|
|
223
|
-
why = 'list-single-prop:' + propkeys[0]
|
|
224
|
-
transform = { [propkeys[0]]: '`reqdata`' }
|
|
225
|
-
}
|
|
226
|
-
else {
|
|
227
|
-
// Use sub property that is an array
|
|
228
|
-
for (let pk of propkeys) {
|
|
229
|
-
if ('array' === properties[pk]?.type) {
|
|
230
|
-
why = 'list-single-array:' + pk
|
|
231
|
-
transform = { [pk]: '`reqdata`' }
|
|
232
|
-
break
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
else {
|
|
239
|
-
if ('object' === schema.type) {
|
|
240
|
-
if (null == properties.id) {
|
|
241
|
-
if (1 === propkeys.length) {
|
|
242
|
-
why = 'map-single-prop:' + propkeys[0]
|
|
243
|
-
transform = { [propkeys[0]]: '`reqdata`' }
|
|
244
|
-
}
|
|
245
|
-
else {
|
|
246
|
-
for (let pk of propkeys) {
|
|
247
|
-
if (properties[pk]?.properties?.id) {
|
|
248
|
-
why = 'map-sub-prop:' + pk
|
|
249
|
-
transform = { [pk]: '`reqdata`' }
|
|
250
|
-
break
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
}
|
|
68
|
+
return { ok: true, msg }
|
|
69
|
+
}
|
|
257
70
|
|
|
258
|
-
return [transform, why]
|
|
259
|
-
}
|
|
260
71
|
|
|
72
|
+
function collectOps(gent: GuideEntity) {
|
|
73
|
+
gent.opm$ = gent.opm$ ?? {}
|
|
74
|
+
each(gent.paths$, (pathdesc: PathDesc) => {
|
|
75
|
+
each(pathdesc.op, (gop: GuideOp, opname: OpName) => {
|
|
76
|
+
gent.opm$[opname] = gent.opm$[opname] ?? { paths: [] }
|
|
261
77
|
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
model: any
|
|
270
|
-
) => {
|
|
271
|
-
if (false === guidePath.active) {
|
|
272
|
-
return
|
|
78
|
+
const oppathdesc: PathDesc = {
|
|
79
|
+
orig: pathdesc.orig,
|
|
80
|
+
parts: pathdesc.parts,
|
|
81
|
+
rename: pathdesc.rename,
|
|
82
|
+
method: gop.method,
|
|
83
|
+
op: pathdesc.op,
|
|
84
|
+
def: pathdesc.def,
|
|
273
85
|
}
|
|
274
86
|
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
const existingOpModel = entityModel.op[opname]
|
|
280
|
-
const existingParam = existingOpModel?.param
|
|
281
|
-
|
|
282
|
-
const [resform, resform_COMMENT] =
|
|
283
|
-
resolveTransform(entityModel, guideOp, kind, 'resform', pathdef)
|
|
284
|
-
|
|
285
|
-
const [reqform, reqform_COMMENT] =
|
|
286
|
-
resolveTransform(entityModel, guideOp, kind, 'reqform', pathdef)
|
|
287
|
-
|
|
288
|
-
const opModel = {
|
|
289
|
-
path: guidePath.key$,
|
|
290
|
-
pathalt: ([] as any[]),
|
|
291
|
-
|
|
292
|
-
method,
|
|
293
|
-
kind,
|
|
294
|
-
param: existingParam || {},
|
|
295
|
-
query: {},
|
|
296
|
-
|
|
297
|
-
resform_COMMENT: 'derivation: ' + resform_COMMENT,
|
|
298
|
-
resform,
|
|
299
|
-
|
|
300
|
-
reqform_COMMENT: 'derivation: ' + reqform_COMMENT,
|
|
301
|
-
reqform,
|
|
302
|
-
|
|
303
|
-
validate: {
|
|
304
|
-
params: { '`$OPEN`': true }
|
|
305
|
-
}
|
|
306
|
-
}
|
|
87
|
+
gent.opm$[opname].paths.push(oppathdesc)
|
|
88
|
+
})
|
|
89
|
+
})
|
|
90
|
+
}
|
|
307
91
|
|
|
308
|
-
fixName(opModel, guideOp.key$)
|
|
309
92
|
|
|
310
|
-
let params: any[] = []
|
|
311
93
|
|
|
312
|
-
// Params are in the path
|
|
313
|
-
if (0 < guidePath.params$.length) {
|
|
314
|
-
let sharedparams = getx(pathdef, 'parameters?in=path') || []
|
|
315
|
-
params = sharedparams.concat(
|
|
316
|
-
getx(pathdef[method], 'parameters?in=path') || []
|
|
317
|
-
)
|
|
318
94
|
|
|
319
|
-
// if (Array.isArray(params)) {
|
|
320
|
-
params.reduce((a: any, p: any) =>
|
|
321
|
-
(paramBuilder(a, p, opModel, entityModel,
|
|
322
|
-
pathdef, guideOp, guidePath, guideEntity, model), a), opModel.param)
|
|
323
|
-
//}
|
|
324
|
-
}
|
|
325
95
|
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
(queryBuilder(a, p, opModel, entityModel,
|
|
331
|
-
pathdef, guideOp, guidePath, guideEntity, model), a), opModel.query)
|
|
332
|
-
|
|
333
|
-
let pathalt: any[] = []
|
|
334
|
-
const pathselector = makePathSelector(guidePath.key$)
|
|
335
|
-
|
|
336
|
-
let before = false
|
|
337
|
-
|
|
338
|
-
if (null != entityModel.op[opname]) {
|
|
339
|
-
pathalt = entityModel.op[opname].pathalt
|
|
340
|
-
|
|
341
|
-
// Ordering for pathalts: most to least paramrs, then alphanumberic
|
|
342
|
-
for (let i = 0; i < pathalt.length; i++) {
|
|
343
|
-
let current = pathalt[i]
|
|
344
|
-
before =
|
|
345
|
-
pathselector.pn$ > current.pn$ ||
|
|
346
|
-
(pathselector.pn$ === current.pn$ &&
|
|
347
|
-
pathselector.path <= current.path)
|
|
348
|
-
|
|
349
|
-
if (before) {
|
|
350
|
-
pathalt = [
|
|
351
|
-
...pathalt.slice(0, i),
|
|
352
|
-
pathselector,
|
|
353
|
-
...pathalt.slice(i),
|
|
354
|
-
]
|
|
355
|
-
break
|
|
356
|
-
}
|
|
357
|
-
}
|
|
358
|
-
}
|
|
96
|
+
function resolveLoad(opm: ModelOpMap, gent: GuideEntity): undefined | ModelOp {
|
|
97
|
+
const opdesc = opm.load = resolveOp('load', gent)
|
|
98
|
+
return opdesc
|
|
99
|
+
}
|
|
359
100
|
|
|
360
|
-
if (!before) {
|
|
361
|
-
pathalt.push(pathselector)
|
|
362
|
-
}
|
|
363
101
|
|
|
364
|
-
|
|
365
|
-
|
|
102
|
+
function resolveList(opm: ModelOpMap, gent: GuideEntity): undefined | ModelOp {
|
|
103
|
+
const opdesc = opm.list = resolveOp('list', gent)
|
|
104
|
+
return opdesc
|
|
105
|
+
}
|
|
366
106
|
|
|
367
|
-
entityModel.op[opname] = opModel
|
|
368
107
|
|
|
369
|
-
|
|
370
|
-
|
|
108
|
+
function resolveCreate(opm: ModelOpMap, gent: GuideEntity): undefined | ModelOp {
|
|
109
|
+
const opdesc = opm.create = resolveOp('create', gent)
|
|
110
|
+
return opdesc
|
|
111
|
+
}
|
|
371
112
|
|
|
372
113
|
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
114
|
+
function resolveUpdate(opm: ModelOpMap, gent: GuideEntity): undefined | ModelOp {
|
|
115
|
+
const opdesc = opm.update = resolveOp('update', gent)
|
|
116
|
+
return opdesc
|
|
117
|
+
}
|
|
376
118
|
|
|
377
|
-
load: (entityModel: any, pathdef: any, op: any, path: any, entity: any, model: any) => {
|
|
378
|
-
return opBuilder.any(entityModel, pathdef, op, path, entity, model)
|
|
379
|
-
},
|
|
380
119
|
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
120
|
+
function resolveDelete(opm: ModelOpMap, gent: GuideEntity): undefined | ModelOp {
|
|
121
|
+
const opdesc = opm.delete = resolveOp('delete', gent)
|
|
122
|
+
return opdesc
|
|
123
|
+
}
|
|
384
124
|
|
|
385
|
-
update: (entityModel: any, pathdef: any, op: any, path: any, entity: any, model: any) => {
|
|
386
|
-
return opBuilder.any(entityModel, pathdef, op, path, entity, model)
|
|
387
|
-
},
|
|
388
125
|
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
},
|
|
126
|
+
function resolvePatch(opm: ModelOpMap, gent: GuideEntity): undefined | ModelOp {
|
|
127
|
+
const opdesc = resolveOp('patch', gent)
|
|
392
128
|
|
|
129
|
+
// If patch is actually update, make it update!
|
|
130
|
+
if (null != opdesc && null == opm.update) {
|
|
131
|
+
opm.update = opdesc
|
|
132
|
+
opm.update.name = 'update'
|
|
133
|
+
}
|
|
134
|
+
else {
|
|
135
|
+
opm.patch = opdesc
|
|
393
136
|
}
|
|
394
137
|
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
transform({ guide }, {
|
|
398
|
-
entity: {
|
|
399
|
-
'`$PACK`': ['guide.entity', {
|
|
400
|
-
'`$KEY`': 'name',
|
|
401
|
-
op: {
|
|
402
|
-
// load: ['`$IF`', ['`$SELECT`',{path:{'`$ANY`':{op:{load:'`$EXISTS`'}}}}], {
|
|
403
|
-
load: ['`$IF`', 'path.*.op.load', {
|
|
404
|
-
path: () => 'foo'
|
|
405
|
-
}]
|
|
406
|
-
}
|
|
407
|
-
}]
|
|
408
|
-
}
|
|
409
|
-
}), { depth: null })
|
|
410
|
-
*/
|
|
138
|
+
return opdesc
|
|
139
|
+
}
|
|
411
140
|
|
|
412
|
-
each(guide.entity, (guideEntity: any) => {
|
|
413
|
-
let opcount = 0
|
|
414
|
-
const entityModel = apimodel.main.api.entity[guideEntity.key$]
|
|
415
|
-
each(guideEntity.path, (guidePath: any) => {
|
|
416
|
-
const pathdef = def.paths[guidePath.key$]
|
|
417
141
|
|
|
418
|
-
|
|
419
|
-
|
|
142
|
+
function resolveOp(opname: OpName, gent: GuideEntity): undefined | ModelOp {
|
|
143
|
+
let mop: undefined | ModelOp = undefined
|
|
144
|
+
let opdesc = gent.opm$[opname]
|
|
145
|
+
if (opdesc) {
|
|
146
|
+
// console.dir(opdesc, { depth: null })
|
|
420
147
|
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
})
|
|
426
|
-
})
|
|
148
|
+
mop = {
|
|
149
|
+
name: opname,
|
|
150
|
+
alts: opdesc.paths.map(p => {
|
|
151
|
+
const parts = applyRename(p)
|
|
427
152
|
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
// console.log('PA', params, pathalt)
|
|
435
|
-
// }
|
|
436
|
-
|
|
437
|
-
for (const pa of pathalt) {
|
|
438
|
-
for (const p of params) {
|
|
439
|
-
pa[p] = pa[p] || false
|
|
440
|
-
// if ('course' === entityModel.name) {
|
|
441
|
-
// console.log('PA-SET', p, pa)
|
|
442
|
-
// }
|
|
153
|
+
const malt: ModelAlt = {
|
|
154
|
+
orig: p.orig,
|
|
155
|
+
parts,
|
|
156
|
+
method: p.method,
|
|
157
|
+
args: {},
|
|
158
|
+
select: {}
|
|
443
159
|
}
|
|
444
|
-
}
|
|
445
|
-
})
|
|
446
160
|
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
})
|
|
453
|
-
|
|
454
|
-
return { ok: true, msg }
|
|
161
|
+
return malt
|
|
162
|
+
})
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
return mop
|
|
455
166
|
}
|
|
456
167
|
|
|
457
168
|
|
|
458
|
-
function
|
|
459
|
-
|
|
169
|
+
function applyRename(pathdesc: PathDesc): string[] {
|
|
170
|
+
const prn: Record<string, string> = pathdesc.rename?.param ?? {}
|
|
171
|
+
return pathdesc.parts.map(p => '{' === p[0] ? (prn[p.substring(1, p.length - 1)] ?? p) : p)
|
|
172
|
+
}
|
|
460
173
|
|
|
461
|
-
let pn$ = 0
|
|
462
|
-
for (const m of path.matchAll(/\/[^\/]+\/{([^}]+)\}/g)) {
|
|
463
|
-
const paramName = depluralize(snakify(m[1]))
|
|
464
|
-
out[paramName] = true
|
|
465
|
-
pn$++
|
|
466
|
-
}
|
|
467
|
-
out.pn$ = pn$
|
|
468
174
|
|
|
469
|
-
return out
|
|
470
|
-
}
|
|
471
175
|
|
|
472
176
|
|
|
473
177
|
export {
|
|
474
|
-
operationTransform
|
|
178
|
+
operationTransform,
|
|
475
179
|
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
import { each, snakify } from 'jostraca'
|
|
4
|
+
|
|
5
|
+
import type { TransformResult, Transform } from '../transform'
|
|
6
|
+
|
|
7
|
+
import { formatJSONIC, depluralize, validator } from '../utility'
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
import { KIT } from '../types'
|
|
11
|
+
|
|
12
|
+
import type {
|
|
13
|
+
KitModel,
|
|
14
|
+
Guide,
|
|
15
|
+
} from '../types'
|
|
16
|
+
|
|
17
|
+
import type {
|
|
18
|
+
PathDef,
|
|
19
|
+
ParameterDef,
|
|
20
|
+
MethodDef,
|
|
21
|
+
} from '../def'
|
|
22
|
+
|
|
23
|
+
import type {
|
|
24
|
+
OpName,
|
|
25
|
+
ModelOp,
|
|
26
|
+
ModelEntity,
|
|
27
|
+
ModelAlt,
|
|
28
|
+
ModelArg,
|
|
29
|
+
} from '../model'
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
const selectTransform = async function(
|
|
34
|
+
ctx: any,
|
|
35
|
+
): Promise<TransformResult> {
|
|
36
|
+
const { apimodel, def, guide } = ctx
|
|
37
|
+
const kit: KitModel = apimodel.main[KIT]
|
|
38
|
+
|
|
39
|
+
let msg = 'select '
|
|
40
|
+
|
|
41
|
+
each(kit.entity, (ment: ModelEntity, entname: string) => {
|
|
42
|
+
each(ment.op, (mop: ModelOp, opname: OpName) => {
|
|
43
|
+
each(mop.alts, (malt: ModelAlt) => {
|
|
44
|
+
const pdef: PathDef = def.paths[malt.orig]
|
|
45
|
+
resolveSelect(guide, ment, mop, malt, pdef)
|
|
46
|
+
})
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
msg += ment.name + ' '
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
return { ok: true, msg }
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
function resolveSelect(guide: Guide, ment: ModelEntity, mop: ModelOp, malt: ModelAlt, pdef: PathDef) {
|
|
57
|
+
const select: any = malt.select
|
|
58
|
+
const margs: any = malt.args
|
|
59
|
+
|
|
60
|
+
const argkinds = ['param', 'query', 'header', 'cookie']
|
|
61
|
+
|
|
62
|
+
argkinds.map((kind: string) => {
|
|
63
|
+
each(margs[kind], (marg: ModelArg) => {
|
|
64
|
+
select[kind] = (select[kind] ?? {})
|
|
65
|
+
|
|
66
|
+
if (marg.req) {
|
|
67
|
+
select[kind][marg.name] = true
|
|
68
|
+
}
|
|
69
|
+
})
|
|
70
|
+
})
|
|
71
|
+
|
|
72
|
+
const gent = guide.entity[ment.name]
|
|
73
|
+
const gpath = gent.path[malt.orig]
|
|
74
|
+
|
|
75
|
+
// console.log('GPATH', gpath)
|
|
76
|
+
|
|
77
|
+
if (gpath.action) {
|
|
78
|
+
const actname = Object.keys(gpath.action)[0]
|
|
79
|
+
|
|
80
|
+
if (null != actname) {
|
|
81
|
+
select.$action = actname
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
export {
|
|
89
|
+
selectTransform,
|
|
90
|
+
}
|