@voxgig/apidef 2.0.0 → 2.1.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/dist/apidef.js +14 -20
- 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 +197 -117
- package/dist/guide/heuristic01.js.map +1 -1
- package/dist/guide.js +37 -11
- package/dist/guide.js.map +1 -1
- package/dist/parse.d.ts +2 -1
- package/dist/parse.js +81 -3
- package/dist/parse.js.map +1 -1
- package/dist/transform/clean.d.ts +3 -0
- package/dist/transform/clean.js +16 -0
- package/dist/transform/clean.js.map +1 -0
- package/dist/transform/entity.js +21 -2
- package/dist/transform/entity.js.map +1 -1
- package/dist/transform/field.js +24 -1
- package/dist/transform/field.js.map +1 -1
- package/dist/transform/operation.js +131 -47
- package/dist/transform/operation.js.map +1 -1
- package/dist/transform.d.ts +1 -8
- package/dist/transform.js +121 -95
- package/dist/transform.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +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 +7 -1
- package/dist/utility.js +85 -32
- package/dist/utility.js.map +1 -1
- package/model/apidef.jsonic +1 -0
- package/package.json +8 -9
- package/src/apidef.ts +23 -33
- package/src/builder/flow/flowHeuristic01.ts +44 -9
- package/src/builder/flow.ts +4 -3
- package/src/guide/heuristic01.ts +281 -124
- package/src/guide.ts +49 -14
- package/src/parse.ts +106 -4
- package/src/transform/clean.ts +28 -0
- package/src/transform/entity.ts +26 -3
- package/src/transform/field.ts +27 -1
- package/src/transform/operation.ts +203 -64
- package/src/transform.ts +29 -23
- package/src/types.ts +3 -2
- package/src/utility.ts +113 -1
- package/src/builder/flow/flowHeuristic01.ts~ +0 -45
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
|
|
2
2
|
|
|
3
|
-
import { each, getx } from 'jostraca'
|
|
3
|
+
import { each, getx, snakify } from 'jostraca'
|
|
4
|
+
|
|
5
|
+
import { transform, setprop, getprop } from '@voxgig/struct'
|
|
4
6
|
|
|
5
7
|
import type { TransformResult } from '../transform'
|
|
6
8
|
|
|
7
9
|
import { fixName, OPKIND } from '../transform'
|
|
8
10
|
|
|
11
|
+
import { depluralize } from '../utility'
|
|
9
12
|
|
|
10
13
|
|
|
11
14
|
const operationTransform = async function(
|
|
@@ -20,30 +23,52 @@ const operationTransform = async function(
|
|
|
20
23
|
|
|
21
24
|
let msg = 'operations: '
|
|
22
25
|
|
|
23
|
-
const paramBuilder = (
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
26
|
+
const paramBuilder = (
|
|
27
|
+
paramMap: any,
|
|
28
|
+
paramDef: any,
|
|
29
|
+
opModel: any,
|
|
30
|
+
entityModel: any,
|
|
31
|
+
pathdef: any,
|
|
32
|
+
op: any,
|
|
33
|
+
path: any,
|
|
34
|
+
entity: any,
|
|
35
|
+
model: any
|
|
36
|
+
) => {
|
|
37
|
+
const paramSpec: any = paramMap[paramDef.name] = {
|
|
28
38
|
required: paramDef.required
|
|
29
39
|
}
|
|
30
|
-
fixName(
|
|
40
|
+
fixName(paramSpec, paramDef.name)
|
|
31
41
|
|
|
32
42
|
const type = paramDef.schema ? paramDef.schema.type : paramDef.type
|
|
33
|
-
fixName(
|
|
43
|
+
fixName(paramSpec, type, 'type')
|
|
44
|
+
|
|
45
|
+
// Path params are always required.
|
|
46
|
+
opModel.validate.params[paramDef.name] = `\`$${paramSpec.TYPE}\``
|
|
34
47
|
}
|
|
35
48
|
|
|
36
49
|
|
|
37
|
-
const queryBuilder = (
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
50
|
+
const queryBuilder = (
|
|
51
|
+
queryMap: any,
|
|
52
|
+
queryDef: any,
|
|
53
|
+
opModel: any,
|
|
54
|
+
entityModel: any,
|
|
55
|
+
pathdef: any,
|
|
56
|
+
op: any,
|
|
57
|
+
path: any,
|
|
58
|
+
entity: any,
|
|
59
|
+
model: any
|
|
60
|
+
) => {
|
|
61
|
+
const querySpec: any = queryMap[queryDef.name] = {
|
|
41
62
|
required: queryDef.required
|
|
42
63
|
}
|
|
43
64
|
fixName(queryMap[queryDef.name], queryDef.name)
|
|
44
65
|
|
|
45
66
|
const type = queryDef.schema ? queryDef.schema.type : queryDef.type
|
|
46
67
|
fixName(queryMap[queryDef.name], type, 'type')
|
|
68
|
+
|
|
69
|
+
if (queryDef.required) {
|
|
70
|
+
opModel.validate.params[queryDef.name] = `\`$${querySpec.TYPE}\``
|
|
71
|
+
}
|
|
47
72
|
}
|
|
48
73
|
|
|
49
74
|
|
|
@@ -57,6 +82,7 @@ const operationTransform = async function(
|
|
|
57
82
|
pathdef: any
|
|
58
83
|
) => {
|
|
59
84
|
let out
|
|
85
|
+
let why = 'none'
|
|
60
86
|
|
|
61
87
|
if (null != op.transform?.[direction]) {
|
|
62
88
|
out = op.transform[direction]
|
|
@@ -67,16 +93,12 @@ const operationTransform = async function(
|
|
|
67
93
|
const mdef = pathdef[method]
|
|
68
94
|
|
|
69
95
|
// TODO: fix getx
|
|
70
|
-
const content = 'res' === kind ?
|
|
96
|
+
// const content = 'res' === kind ?
|
|
97
|
+
const content = 'resform' === direction ?
|
|
71
98
|
(getx(mdef, 'responses.200.content') ||
|
|
72
99
|
getx(mdef, 'responses.201.content')) :
|
|
73
100
|
getx(mdef, 'requestBody.content')
|
|
74
101
|
|
|
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
102
|
if (content) {
|
|
81
103
|
|
|
82
104
|
const schema = content['application/json']?.schema
|
|
@@ -86,18 +108,22 @@ const operationTransform = async function(
|
|
|
86
108
|
const resolveDirectionTransform =
|
|
87
109
|
'resform' === direction ? resolveResponseTransform : resolveRequestTransform
|
|
88
110
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
111
|
+
//const [transform, why]
|
|
112
|
+
;[out, why]
|
|
113
|
+
= resolveDirectionTransform(
|
|
114
|
+
entityModel,
|
|
115
|
+
op,
|
|
116
|
+
kind,
|
|
117
|
+
direction,
|
|
118
|
+
method,
|
|
119
|
+
mdef,
|
|
120
|
+
content,
|
|
121
|
+
schema,
|
|
122
|
+
propkeys
|
|
123
|
+
)
|
|
98
124
|
|
|
99
125
|
// out = JSON.stringify(transform)
|
|
100
|
-
out = transform
|
|
126
|
+
// out = transform
|
|
101
127
|
}
|
|
102
128
|
else {
|
|
103
129
|
out = 'res' === kind ? '`body`' : '`reqdata`'
|
|
@@ -105,23 +131,27 @@ const operationTransform = async function(
|
|
|
105
131
|
}
|
|
106
132
|
|
|
107
133
|
|
|
108
|
-
return out
|
|
134
|
+
return [out, why]
|
|
109
135
|
}
|
|
110
136
|
|
|
111
137
|
|
|
112
138
|
const resolveResponseTransform = (
|
|
139
|
+
entityModel: any,
|
|
113
140
|
op: any,
|
|
114
141
|
kind: 'res' | 'req',
|
|
142
|
+
direction: 'resform' | 'reqform',
|
|
115
143
|
method: string,
|
|
116
144
|
mdef: any,
|
|
117
145
|
content: any,
|
|
118
146
|
schema: any,
|
|
119
147
|
propkeys: any
|
|
120
|
-
) => {
|
|
148
|
+
): [any, string] => {
|
|
149
|
+
let why = 'default'
|
|
121
150
|
let transform: any = '`body`'
|
|
151
|
+
const properties = schema?.properties
|
|
122
152
|
|
|
123
|
-
if (null == content || null == schema || null == propkeys) {
|
|
124
|
-
return transform
|
|
153
|
+
if (null == content || null == schema || null == propkeys || null == properties) {
|
|
154
|
+
return [transform, why]
|
|
125
155
|
}
|
|
126
156
|
|
|
127
157
|
const opname = op.key$
|
|
@@ -129,13 +159,18 @@ const operationTransform = async function(
|
|
|
129
159
|
if ('list' === opname) {
|
|
130
160
|
if ('array' !== schema.type) {
|
|
131
161
|
if (1 === propkeys.length) {
|
|
162
|
+
why = 'list-single-prop:' + propkeys[0]
|
|
132
163
|
transform = '`body.' + propkeys[0] + '`'
|
|
133
164
|
}
|
|
134
165
|
else {
|
|
135
166
|
// Use sub property that is an array
|
|
136
167
|
for (let pk of propkeys) {
|
|
137
|
-
if ('array' ===
|
|
168
|
+
if ('array' === properties[pk]?.type) {
|
|
169
|
+
why = 'list-single-array:' + pk
|
|
138
170
|
transform = '`body.' + pk + '`'
|
|
171
|
+
|
|
172
|
+
// TODO: if each item has prop === name of entity, use that, get with $EACH
|
|
173
|
+
|
|
139
174
|
break
|
|
140
175
|
}
|
|
141
176
|
}
|
|
@@ -144,13 +179,15 @@ const operationTransform = async function(
|
|
|
144
179
|
}
|
|
145
180
|
else {
|
|
146
181
|
if ('object' === schema.type) {
|
|
147
|
-
if (null ==
|
|
182
|
+
if (null == properties.id) {
|
|
148
183
|
if (1 === propkeys.length) {
|
|
184
|
+
why = 'map-single-prop:' + propkeys[0]
|
|
149
185
|
transform = '`body.' + propkeys[0] + '`'
|
|
150
186
|
}
|
|
151
187
|
else {
|
|
152
188
|
for (let pk of propkeys) {
|
|
153
|
-
if (
|
|
189
|
+
if (properties[pk]?.properties?.id) {
|
|
190
|
+
why = 'map-sub-prop:' + pk
|
|
154
191
|
transform = '`body.' + pk + '`'
|
|
155
192
|
break
|
|
156
193
|
}
|
|
@@ -160,23 +197,27 @@ const operationTransform = async function(
|
|
|
160
197
|
}
|
|
161
198
|
}
|
|
162
199
|
|
|
163
|
-
return transform
|
|
200
|
+
return [transform, why]
|
|
164
201
|
}
|
|
165
202
|
|
|
166
203
|
|
|
167
204
|
const resolveRequestTransform = (
|
|
205
|
+
entityModel: any,
|
|
168
206
|
op: any,
|
|
169
207
|
kind: 'res' | 'req',
|
|
208
|
+
direction: 'resform' | 'reqform',
|
|
170
209
|
method: string,
|
|
171
210
|
mdef: any,
|
|
172
211
|
content: any,
|
|
173
212
|
schema: any,
|
|
174
213
|
propkeys: any
|
|
175
|
-
) => {
|
|
176
|
-
let transform: any = '`
|
|
214
|
+
): [any, string] => {
|
|
215
|
+
let transform: any = '`reqdata`'
|
|
216
|
+
let why = 'default'
|
|
217
|
+
const properties = schema?.properties
|
|
177
218
|
|
|
178
|
-
if (null == content || null == schema || null == propkeys) {
|
|
179
|
-
return transform
|
|
219
|
+
if (null == content || null == schema || null == propkeys || null == properties) {
|
|
220
|
+
return [transform, why]
|
|
180
221
|
}
|
|
181
222
|
|
|
182
223
|
const opname = op.key$
|
|
@@ -184,13 +225,15 @@ const operationTransform = async function(
|
|
|
184
225
|
if ('list' === opname) {
|
|
185
226
|
if ('array' !== schema.type) {
|
|
186
227
|
if (1 === propkeys.length) {
|
|
187
|
-
|
|
228
|
+
why = 'list-single-prop:' + propkeys[0]
|
|
229
|
+
transform = { [propkeys[0]]: '`reqdata`' }
|
|
188
230
|
}
|
|
189
231
|
else {
|
|
190
232
|
// Use sub property that is an array
|
|
191
233
|
for (let pk of propkeys) {
|
|
192
|
-
if ('array' ===
|
|
193
|
-
|
|
234
|
+
if ('array' === properties[pk]?.type) {
|
|
235
|
+
why = 'list-single-array:' + pk
|
|
236
|
+
transform = { [pk]: '`reqdata`' }
|
|
194
237
|
break
|
|
195
238
|
}
|
|
196
239
|
}
|
|
@@ -199,14 +242,16 @@ const operationTransform = async function(
|
|
|
199
242
|
}
|
|
200
243
|
else {
|
|
201
244
|
if ('object' === schema.type) {
|
|
202
|
-
if (null ==
|
|
245
|
+
if (null == properties.id) {
|
|
203
246
|
if (1 === propkeys.length) {
|
|
204
|
-
|
|
247
|
+
why = 'map-single-prop:' + propkeys[0]
|
|
248
|
+
transform = { [propkeys[0]]: '`reqdata`' }
|
|
205
249
|
}
|
|
206
250
|
else {
|
|
207
251
|
for (let pk of propkeys) {
|
|
208
|
-
if (
|
|
209
|
-
|
|
252
|
+
if (properties[pk]?.properties?.id) {
|
|
253
|
+
why = 'map-sub-prop:' + pk
|
|
254
|
+
transform = { [pk]: '`reqdata`' }
|
|
210
255
|
break
|
|
211
256
|
}
|
|
212
257
|
}
|
|
@@ -215,7 +260,7 @@ const operationTransform = async function(
|
|
|
215
260
|
}
|
|
216
261
|
}
|
|
217
262
|
|
|
218
|
-
return transform
|
|
263
|
+
return [transform, why]
|
|
219
264
|
}
|
|
220
265
|
|
|
221
266
|
|
|
@@ -225,37 +270,93 @@ const operationTransform = async function(
|
|
|
225
270
|
const method = op.method
|
|
226
271
|
const kind = OPKIND[opname]
|
|
227
272
|
|
|
228
|
-
const
|
|
273
|
+
const [resform, resform_COMMENT] =
|
|
274
|
+
resolveTransform(entityModel, op, kind, 'resform', pathdef)
|
|
275
|
+
|
|
276
|
+
const [reqform, reqform_COMMENT] =
|
|
277
|
+
resolveTransform(entityModel, op, kind, 'reqform', pathdef)
|
|
278
|
+
|
|
279
|
+
const opModel = {
|
|
229
280
|
path: path.key$,
|
|
281
|
+
pathalt: ([] as any[]),
|
|
282
|
+
|
|
230
283
|
method,
|
|
231
284
|
kind,
|
|
232
285
|
param: {},
|
|
233
286
|
query: {},
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
287
|
+
|
|
288
|
+
resform_COMMENT: 'derivation: ' + resform_COMMENT,
|
|
289
|
+
resform,
|
|
290
|
+
|
|
291
|
+
reqform_COMMENT: 'derivation: ' + reqform_COMMENT,
|
|
292
|
+
reqform,
|
|
293
|
+
|
|
294
|
+
validate: {
|
|
295
|
+
params: { '`$OPEN`': true }
|
|
296
|
+
}
|
|
238
297
|
}
|
|
239
298
|
|
|
240
|
-
fixName(
|
|
299
|
+
fixName(opModel, op.key$)
|
|
300
|
+
|
|
301
|
+
let params: any[] = []
|
|
241
302
|
|
|
242
303
|
// Params are in the path
|
|
243
304
|
if (0 < path.params$.length) {
|
|
244
|
-
let
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
305
|
+
let sharedparams = getx(pathdef, 'parameters?in=path') || []
|
|
306
|
+
params = sharedparams.concat(
|
|
307
|
+
getx(pathdef[method], 'parameters?in=path') || []
|
|
308
|
+
)
|
|
309
|
+
|
|
310
|
+
// if (Array.isArray(params)) {
|
|
311
|
+
params.reduce((a: any, p: any) =>
|
|
312
|
+
(paramBuilder(a, p, opModel, entityModel,
|
|
313
|
+
pathdef, op, path, entity, model), a), opModel.param)
|
|
314
|
+
//}
|
|
249
315
|
}
|
|
250
316
|
|
|
251
317
|
// Queries are after the ?
|
|
252
|
-
let
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
318
|
+
let sharedqueries = getx(pathdef, 'parameters?in!=path') || []
|
|
319
|
+
let queries = sharedqueries.concat(getx(pathdef[method], 'parameters?in!=path') || [])
|
|
320
|
+
queries.reduce((a: any, p: any) =>
|
|
321
|
+
(queryBuilder(a, p, opModel, entityModel,
|
|
322
|
+
pathdef, op, path, entity, model), a), opModel.query)
|
|
323
|
+
|
|
324
|
+
let pathalt: any[] = []
|
|
325
|
+
const pathselector = makePathSelector(path.key$) // , params)
|
|
326
|
+
let before = false
|
|
327
|
+
|
|
328
|
+
if (null != entityModel.op[opname]) {
|
|
329
|
+
pathalt = entityModel.op[opname].pathalt
|
|
330
|
+
|
|
331
|
+
// Ordering for pathalts: most to least paramrs, then alphanumberic
|
|
332
|
+
for (let i = 0; i < pathalt.length; i++) {
|
|
333
|
+
let current = pathalt[i]
|
|
334
|
+
before =
|
|
335
|
+
pathselector.pn$ > current.pn$ ||
|
|
336
|
+
(pathselector.pn$ === current.pn$ &&
|
|
337
|
+
pathselector.path <= current.path)
|
|
338
|
+
|
|
339
|
+
if (before) {
|
|
340
|
+
pathalt = [
|
|
341
|
+
...pathalt.slice(0, i),
|
|
342
|
+
pathselector,
|
|
343
|
+
...pathalt.slice(i),
|
|
344
|
+
]
|
|
345
|
+
break
|
|
346
|
+
}
|
|
347
|
+
}
|
|
256
348
|
}
|
|
257
349
|
|
|
258
|
-
|
|
350
|
+
if (!before) {
|
|
351
|
+
pathalt.push(pathselector)
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
opModel.path = pathalt[pathalt.length - 1].path
|
|
355
|
+
opModel.pathalt = pathalt
|
|
356
|
+
|
|
357
|
+
entityModel.op[opname] = opModel
|
|
358
|
+
|
|
359
|
+
return opModel
|
|
259
360
|
},
|
|
260
361
|
|
|
261
362
|
|
|
@@ -281,6 +382,22 @@ const operationTransform = async function(
|
|
|
281
382
|
|
|
282
383
|
}
|
|
283
384
|
|
|
385
|
+
/*
|
|
386
|
+
console.dir(
|
|
387
|
+
transform({ guide }, {
|
|
388
|
+
entity: {
|
|
389
|
+
'`$PACK`': ['guide.entity', {
|
|
390
|
+
'`$KEY`': 'name',
|
|
391
|
+
op: {
|
|
392
|
+
// load: ['`$IF`', ['`$SELECT`',{path:{'`$ANY`':{op:{load:'`$EXISTS`'}}}}], {
|
|
393
|
+
load: ['`$IF`', 'path.*.op.load', {
|
|
394
|
+
path: () => 'foo'
|
|
395
|
+
}]
|
|
396
|
+
}
|
|
397
|
+
}]
|
|
398
|
+
}
|
|
399
|
+
}), { depth: null })
|
|
400
|
+
*/
|
|
284
401
|
|
|
285
402
|
each(guide.entity, (guideEntity: any) => {
|
|
286
403
|
let opcount = 0
|
|
@@ -296,6 +413,8 @@ const operationTransform = async function(
|
|
|
296
413
|
opcount++
|
|
297
414
|
}
|
|
298
415
|
})
|
|
416
|
+
|
|
417
|
+
|
|
299
418
|
})
|
|
300
419
|
|
|
301
420
|
msg += guideEntity.name + '=' + opcount + ' '
|
|
@@ -305,6 +424,26 @@ const operationTransform = async function(
|
|
|
305
424
|
}
|
|
306
425
|
|
|
307
426
|
|
|
427
|
+
function makePathSelector(path: string) { // , params: any[]) {
|
|
428
|
+
let out: any = { path }
|
|
429
|
+
|
|
430
|
+
let pn$ = 0
|
|
431
|
+
for (const m of path.matchAll(/\/[^\/]+\/{([^}]+)\}/g)) {
|
|
432
|
+
const paramName = depluralize(snakify(m[1]))
|
|
433
|
+
out[paramName] = true
|
|
434
|
+
pn$++
|
|
435
|
+
}
|
|
436
|
+
out.pn$ = pn$
|
|
437
|
+
|
|
438
|
+
// for (let p of params) {
|
|
439
|
+
// setprop(out, p.name, getprop(out, p.name, false))
|
|
440
|
+
// console.log('SP', p.name, out[p.name])
|
|
441
|
+
// }
|
|
442
|
+
|
|
443
|
+
return out
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
|
|
308
447
|
export {
|
|
309
448
|
operationTransform
|
|
310
449
|
}
|
package/src/transform.ts
CHANGED
|
@@ -79,6 +79,7 @@ const GuideShape = Gubu({
|
|
|
79
79
|
type Guide = ReturnType<typeof GuideShape>
|
|
80
80
|
|
|
81
81
|
|
|
82
|
+
/*
|
|
82
83
|
async function resolveTransforms(ctx: TransformCtx): Promise<TransformSpec> {
|
|
83
84
|
const { log, model: { main: { api: { guide } } } } = ctx
|
|
84
85
|
|
|
@@ -89,28 +90,27 @@ async function resolveTransforms(ctx: TransformCtx): Promise<TransformSpec> {
|
|
|
89
90
|
// TODO: parameterize
|
|
90
91
|
const defkind = 'openapi'
|
|
91
92
|
const transformNames = guide.control.transform[defkind].order
|
|
92
|
-
.split(/\s*,\s
|
|
93
|
+
.split(/\s*,\s* /)
|
|
93
94
|
.map((t: string) => t.trim())
|
|
94
|
-
|
|
95
|
+
.filter((t: string) => '' != t)
|
|
95
96
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
97
|
+
log.info({
|
|
98
|
+
point: 'transform', note: 'order: ' + transformNames.join(';'),
|
|
99
|
+
order: transformNames
|
|
100
|
+
})
|
|
100
101
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
catch (err: any) {
|
|
109
|
-
console.log(err)
|
|
110
|
-
throw err
|
|
102
|
+
try {
|
|
103
|
+
for (const tn of transformNames) {
|
|
104
|
+
log.debug({ what: 'transform', transform: tn, note: tn })
|
|
105
|
+
const transform = await resolveTransform(tn, ctx)
|
|
106
|
+
tspec.transform.push(transform)
|
|
111
107
|
}
|
|
108
|
+
}
|
|
109
|
+
catch (err: any) {
|
|
110
|
+
throw err
|
|
111
|
+
}
|
|
112
112
|
|
|
113
|
-
|
|
113
|
+
return tspec
|
|
114
114
|
}
|
|
115
115
|
|
|
116
116
|
|
|
@@ -181,7 +181,7 @@ async function processTransforms(
|
|
|
181
181
|
}
|
|
182
182
|
catch (err: any) {
|
|
183
183
|
// TODO: fix: this error does not get printed
|
|
184
|
-
console.
|
|
184
|
+
console.error(err)
|
|
185
185
|
|
|
186
186
|
pres.ok = false
|
|
187
187
|
pres.msg += transform.name + ': ' + err.message + '\n'
|
|
@@ -196,13 +196,19 @@ async function processTransforms(
|
|
|
196
196
|
|
|
197
197
|
return pres
|
|
198
198
|
}
|
|
199
|
+
*/
|
|
199
200
|
|
|
200
201
|
|
|
201
202
|
|
|
202
203
|
function fixName(base: any, name: string, prop = 'name') {
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
204
|
+
if (null != base && 'object' === typeof base && 'string' === typeof name) {
|
|
205
|
+
base[prop.toLowerCase()] = name.toLowerCase()
|
|
206
|
+
base[camelify(prop)] = camelify(name)
|
|
207
|
+
base[prop.toUpperCase()] = name.toUpperCase()
|
|
208
|
+
}
|
|
209
|
+
else {
|
|
210
|
+
// record to a "wierds" log
|
|
211
|
+
}
|
|
206
212
|
}
|
|
207
213
|
|
|
208
214
|
|
|
@@ -222,6 +228,6 @@ export {
|
|
|
222
228
|
fixName,
|
|
223
229
|
OPKIND,
|
|
224
230
|
GuideShape,
|
|
225
|
-
resolveTransforms,
|
|
226
|
-
processTransforms,
|
|
231
|
+
// resolveTransforms,
|
|
232
|
+
// processTransforms,
|
|
227
233
|
}
|
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
|
@@ -8,6 +8,26 @@ import type {
|
|
|
8
8
|
} from './types'
|
|
9
9
|
|
|
10
10
|
|
|
11
|
+
function getdlog(
|
|
12
|
+
tagin?: string,
|
|
13
|
+
filepath?: string)
|
|
14
|
+
: ((...args: any[]) => void) &
|
|
15
|
+
{ tag: string, file: string, log: (fp?: string) => any[] } {
|
|
16
|
+
const tag = tagin || '-'
|
|
17
|
+
const file = Path.basename(filepath || '-')
|
|
18
|
+
const g = global as any
|
|
19
|
+
g.__dlog__ = (g.__dlog__ || [])
|
|
20
|
+
const dlog = (...args: any[]) =>
|
|
21
|
+
g.__dlog__.push([tag, file, Date.now(), ...args])
|
|
22
|
+
dlog.tag = tag
|
|
23
|
+
dlog.file = file
|
|
24
|
+
dlog.log = (filepath?: string, f?: string | null) =>
|
|
25
|
+
(f = null == filepath ? null : Path.basename(filepath),
|
|
26
|
+
g.__dlog__.filter((n: any[]) => n[0] === tag && (null == f || n[2] === f)))
|
|
27
|
+
return dlog
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
|
|
11
31
|
function loadFile(path: string, what: string, fs: FsUtil, log: Log) {
|
|
12
32
|
try {
|
|
13
33
|
const source = fs.readFileSync(path, 'utf8')
|
|
@@ -24,9 +44,97 @@ function formatJsonSrc(jsonsrc: string) {
|
|
|
24
44
|
return jsonsrc
|
|
25
45
|
.replace(/"([a-zA-Z_][a-zA-Z_0-9]*)": /g, '$1: ')
|
|
26
46
|
.replace(/},/g, '}\n')
|
|
47
|
+
// .replace(/([a-zA-Z_][a-zA-Z_0-9]*)_COMMENT:/g, '# $1')
|
|
48
|
+
.replace(/\n(\s*)([a-zA-Z_][a-zA-Z_0-9]*)_COMMENT:\s*"(.*)",/g, '\n\n$1# $2 $3')
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
function depluralize(word: string): string {
|
|
53
|
+
if (!word || word.length === 0) {
|
|
54
|
+
return word
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Common irregular plurals
|
|
58
|
+
const irregulars: Record<string, string> = {
|
|
59
|
+
'analyses': 'analysis',
|
|
60
|
+
'appendices': 'appendix',
|
|
61
|
+
'axes': 'axis',
|
|
62
|
+
'children': 'child',
|
|
63
|
+
'courses': 'course',
|
|
64
|
+
'crises': 'crisis',
|
|
65
|
+
'criteria': 'criterion',
|
|
66
|
+
'data': 'datum',
|
|
67
|
+
'diagnoses': 'diagnosis',
|
|
68
|
+
'feet': 'foot',
|
|
69
|
+
'furnace': 'furnaces',
|
|
70
|
+
'geese': 'goose',
|
|
71
|
+
'horses': 'horse',
|
|
72
|
+
'house': 'houses',
|
|
73
|
+
'indices': 'index',
|
|
74
|
+
'license': 'licenses',
|
|
75
|
+
'matrices': 'matrix',
|
|
76
|
+
'men': 'man',
|
|
77
|
+
'mice': 'mouse',
|
|
78
|
+
'notice': 'notices',
|
|
79
|
+
'oases': 'oasis',
|
|
80
|
+
'people': 'person',
|
|
81
|
+
'phenomena': 'phenomenon',
|
|
82
|
+
'practice': 'practices',
|
|
83
|
+
'promise': 'promises',
|
|
84
|
+
'teeth': 'tooth',
|
|
85
|
+
'theses': 'thesis',
|
|
86
|
+
'vertices': 'vertex',
|
|
87
|
+
'women': 'woman',
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
if (irregulars[word]) {
|
|
91
|
+
return irregulars[word]
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Rules for regular plurals (applied in order)
|
|
95
|
+
|
|
96
|
+
if (word.endsWith('ies') && word.length > 3) {
|
|
97
|
+
return word.slice(0, -3) + 'y'
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
// -ies -> -y (cities -> city)
|
|
102
|
+
if (word.endsWith('ies') && word.length > 3) {
|
|
103
|
+
return word.slice(0, -3) + 'y'
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// -ves -> -f or -fe (wolves -> wolf, knives -> knife)
|
|
107
|
+
if (word.endsWith('ves')) {
|
|
108
|
+
const stem = word.slice(0, -3)
|
|
109
|
+
// Check if it should be -fe (like knife, wife, life)
|
|
110
|
+
if (['kni', 'wi', 'li'].includes(stem)) {
|
|
111
|
+
return stem + 'fe'
|
|
112
|
+
}
|
|
113
|
+
return stem + 'f'
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// -oes -> -o (potatoes -> potato)
|
|
117
|
+
if (word.endsWith('oes')) {
|
|
118
|
+
return word.slice(0, -2)
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// -ses, -xes, -zes, -shes, -ches -> remove -es (boxes -> box)
|
|
122
|
+
if (word.endsWith('ses') || word.endsWith('xes') || word.endsWith('zes') ||
|
|
123
|
+
word.endsWith('shes') || word.endsWith('ches')) {
|
|
124
|
+
return word.slice(0, -2)
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// -s -> remove -s (cats -> cat)
|
|
128
|
+
if (word.endsWith('s') && !word.endsWith('ss')) {
|
|
129
|
+
return word.slice(0, -1)
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// If none of the rules apply, return as is
|
|
133
|
+
return word
|
|
27
134
|
}
|
|
28
135
|
|
|
29
136
|
|
|
137
|
+
/*
|
|
30
138
|
function writeChanged(
|
|
31
139
|
point: string, path: string, content: string,
|
|
32
140
|
fs: FsUtil, log: Log,
|
|
@@ -74,10 +182,14 @@ function writeChanged(
|
|
|
74
182
|
throw err
|
|
75
183
|
}
|
|
76
184
|
}
|
|
185
|
+
*/
|
|
77
186
|
|
|
78
187
|
|
|
79
188
|
export {
|
|
189
|
+
getdlog,
|
|
80
190
|
loadFile,
|
|
81
|
-
formatJsonSrc
|
|
191
|
+
formatJsonSrc,
|
|
192
|
+
depluralize,
|
|
193
|
+
|
|
82
194
|
// writeChanged,
|
|
83
195
|
}
|