@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
|
@@ -24,7 +24,7 @@ function resolveBasicEntityFlow(ctx: any, entity: any) {
|
|
|
24
24
|
const apiEntity = apimodel.main.api.entity[entity.name]
|
|
25
25
|
|
|
26
26
|
const flow: any = {
|
|
27
|
-
name: 'Basic' + apiEntity.Name
|
|
27
|
+
name: 'Basic' + apiEntity.Name + 'Flow'
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
const refs = [
|
|
@@ -36,18 +36,21 @@ function resolveBasicEntityFlow(ctx: any, entity: any) {
|
|
|
36
36
|
const idmap = refs.reduce((a: any, ref) => (a[ref] = ref.toUpperCase(), a), {})
|
|
37
37
|
|
|
38
38
|
flow.model = ({
|
|
39
|
-
name: flow.
|
|
39
|
+
name: flow.name,
|
|
40
|
+
active: true,
|
|
40
41
|
param: {
|
|
41
|
-
[`${model.NAME}_TEST_${apiEntity.NAME}_ENTID`]: idmap
|
|
42
|
+
[`${model.NAME}_TEST_${apiEntity.NAME}_ENTID`]: idmap,
|
|
43
|
+
[`${model.NAME}_TEST_LIVE`]: "FALSE",
|
|
44
|
+
[`${model.NAME}_TEST_EXPLAIN`]: "FALSE",
|
|
42
45
|
},
|
|
43
|
-
test: { entity: { [apiEntity.
|
|
46
|
+
test: { entity: { [apiEntity.name]: {} } },
|
|
44
47
|
step: []
|
|
45
48
|
} as any)
|
|
46
49
|
|
|
47
50
|
names(flow, flow.name)
|
|
48
51
|
|
|
49
52
|
|
|
50
|
-
const data = flow.model.test.entity[apiEntity.
|
|
53
|
+
const data = flow.model.test.entity[apiEntity.name]
|
|
51
54
|
|
|
52
55
|
refs.map((ref, i) => {
|
|
53
56
|
const id = idmap[ref]
|
|
@@ -73,7 +76,34 @@ function resolveBasicEntityFlow(ctx: any, entity: any) {
|
|
|
73
76
|
let num = 0
|
|
74
77
|
let name
|
|
75
78
|
|
|
79
|
+
const am: any = {}
|
|
80
|
+
|
|
76
81
|
if (apiEntity.op.load) {
|
|
82
|
+
|
|
83
|
+
// Get additional required match properties
|
|
84
|
+
each(apiEntity.op.load.param, (param: any) => {
|
|
85
|
+
if (param.required) {
|
|
86
|
+
let ancestorName = param.name
|
|
87
|
+
let ancestorEntity = apimodel.main.api.entity[ancestorName]
|
|
88
|
+
|
|
89
|
+
if (null == ancestorEntity) {
|
|
90
|
+
ancestorName = ancestorName.replace('_id', '')
|
|
91
|
+
ancestorEntity = apimodel.main.api.entity[ancestorName]
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
if (ancestorEntity && ancestorName !== apiEntity.name) {
|
|
95
|
+
flow.model.param[`${model.NAME}_TEST_${ancestorEntity.NAME}_ENTID`] = {
|
|
96
|
+
[ancestorEntity.name + '01']: ancestorEntity.NAME + '01'
|
|
97
|
+
}
|
|
98
|
+
am[param.name] =
|
|
99
|
+
`\`dm$=p.${model.NAME}_TEST_${ancestorEntity.NAME}_ENTID.${ancestorEntity.name}01\``
|
|
100
|
+
|
|
101
|
+
data[`${apiEntity.NAME}01`][param.name] = ancestorEntity.NAME + '01'
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
})
|
|
105
|
+
|
|
106
|
+
|
|
77
107
|
name = `load_${apiEntity.name}${num}`
|
|
78
108
|
steps.push({
|
|
79
109
|
name,
|
|
@@ -81,11 +111,13 @@ function resolveBasicEntityFlow(ctx: any, entity: any) {
|
|
|
81
111
|
entity: `${apiEntity.name}`,
|
|
82
112
|
action: 'load',
|
|
83
113
|
match: {
|
|
84
|
-
id: `\`dm$=p.${model.NAME}_TEST_${apiEntity.NAME}_ENTID.${apiEntity.name}01
|
|
114
|
+
id: `\`dm$=p.${model.NAME}_TEST_${apiEntity.NAME}_ENTID.${apiEntity.name}01\``,
|
|
115
|
+
...am,
|
|
85
116
|
},
|
|
86
117
|
valid: {
|
|
87
118
|
'`$OPEN`': true,
|
|
88
|
-
id: `\`dm$=s.${name}.match.id
|
|
119
|
+
id: `\`dm$=s.${name}.match.id\``,
|
|
120
|
+
...am,
|
|
89
121
|
}
|
|
90
122
|
})
|
|
91
123
|
}
|
|
@@ -105,6 +137,7 @@ function resolveBasicEntityFlow(ctx: any, entity: any) {
|
|
|
105
137
|
valid: {
|
|
106
138
|
'`$OPEN`': true,
|
|
107
139
|
id: `\`dm$=s.${loadref}.match.id\``,
|
|
140
|
+
...am,
|
|
108
141
|
...valid
|
|
109
142
|
}
|
|
110
143
|
})
|
|
@@ -118,11 +151,13 @@ function resolveBasicEntityFlow(ctx: any, entity: any) {
|
|
|
118
151
|
entity: `${apiEntity.name}`,
|
|
119
152
|
action: 'load',
|
|
120
153
|
match: {
|
|
121
|
-
id: `\`dm$=p.${model.NAME}_TEST_${apiEntity.NAME}_ENTID.${apiEntity.name}01
|
|
154
|
+
id: `\`dm$=p.${model.NAME}_TEST_${apiEntity.NAME}_ENTID.${apiEntity.name}01\``,
|
|
155
|
+
...am,
|
|
122
156
|
},
|
|
123
157
|
valid: {
|
|
124
158
|
'`$OPEN`': true,
|
|
125
159
|
id: `\`dm$=s.${loadref}.match.id\``,
|
|
160
|
+
...am,
|
|
126
161
|
...valid
|
|
127
162
|
}
|
|
128
163
|
})
|
|
@@ -136,7 +171,7 @@ function resolveBasicEntityFlow(ctx: any, entity: any) {
|
|
|
136
171
|
|
|
137
172
|
function makeUpdateData(name: string, apiEntity: any, flow: any, id: string) {
|
|
138
173
|
const ud: any = {}
|
|
139
|
-
const data = flow.model.test.entity[apiEntity.
|
|
174
|
+
const data = flow.model.test.entity[apiEntity.name]
|
|
140
175
|
|
|
141
176
|
const dataFields = each(apiEntity.field).filter(f => 'id' !== f.name && !f.name.includes('_id'))
|
|
142
177
|
const stringFields = each(dataFields).filter(f => 'string' === f.type)
|
package/src/builder/flow.ts
CHANGED
|
@@ -21,6 +21,7 @@ async function makeFlowBuilder(ctx: any) {
|
|
|
21
21
|
throw new Error('Unknown guide strategy: ' + ctx.opts.strategy)
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
+
|
|
24
25
|
return function flowBuilder() {
|
|
25
26
|
|
|
26
27
|
Folder({ name: 'flow' }, () => {
|
|
@@ -32,13 +33,13 @@ async function makeFlowBuilder(ctx: any) {
|
|
|
32
33
|
let flowfile =
|
|
33
34
|
Path.join(ctx.opts.folder, 'flow',
|
|
34
35
|
(null == ctx.opts.outprefix ? '' : ctx.opts.outprefix) +
|
|
35
|
-
flow.Name + '
|
|
36
|
+
flow.Name + '.jsonic')
|
|
36
37
|
|
|
37
38
|
let flowModelSrc = formatJsonSrc(JSON.stringify(flow.model, null, 2))
|
|
38
39
|
|
|
39
|
-
let flowsrc = `# ${flow.Name}
|
|
40
|
+
let flowsrc = `# ${flow.Name}
|
|
40
41
|
|
|
41
|
-
main: sdk: flow: ${flow.Name}
|
|
42
|
+
main: sdk: flow: ${flow.Name}:
|
|
42
43
|
` + flowModelSrc
|
|
43
44
|
|
|
44
45
|
barrel.push(`@"${Path.basename(flowfile)}"`)
|
package/src/guide/heuristic01.ts
CHANGED
|
@@ -3,6 +3,21 @@
|
|
|
3
3
|
import { each, snakify, names } from 'jostraca'
|
|
4
4
|
|
|
5
5
|
|
|
6
|
+
import { depluralize } from '../utility'
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
type EntityDesc = {
|
|
10
|
+
name: string
|
|
11
|
+
origname: string
|
|
12
|
+
plural: string
|
|
13
|
+
path: Record<string, EntityPathDesc>
|
|
14
|
+
alias: Record<string, string>
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
type EntityPathDesc = {
|
|
19
|
+
op: Record<string, any>
|
|
20
|
+
}
|
|
6
21
|
|
|
7
22
|
async function heuristic01(ctx: any): Promise<Record<string, any>> {
|
|
8
23
|
let guide = ctx.model.main.api.guide
|
|
@@ -35,29 +50,14 @@ function resolveEntityDescs(ctx: any) {
|
|
|
35
50
|
const entityDescs: Record<string, any> = {}
|
|
36
51
|
const paths = ctx.def.paths
|
|
37
52
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
const m = pathname.match(/\/([a-zA-Z0-1_-]+)\/\{([a-zA-Z0-1_-]+)\}$/)
|
|
41
|
-
if (m) {
|
|
42
|
-
let origentname = snakify(m[1])
|
|
43
|
-
let entname = depluralize(origentname)
|
|
44
|
-
|
|
45
|
-
let entdesc = (entityDescs[entname] = entityDescs[entname] || { name: entname })
|
|
46
|
-
entdesc.plural = origentname
|
|
47
|
-
|
|
48
|
-
names(entdesc, entname)
|
|
53
|
+
// Analyze paths ending in .../foo/{foo}
|
|
54
|
+
each(paths, (pathdef, pathstr) => {
|
|
49
55
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
entdesc.alias[m[2]] = 'id'
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
entdesc.path = (entdesc.path || {})
|
|
56
|
+
// Look for rightmmost /entname/{entid}.
|
|
57
|
+
const m = pathstr.match(/\/([a-zA-Z0-1_-]+)\/\{([a-zA-Z0-1_-]+)\}$/)
|
|
58
|
+
if (m) {
|
|
59
|
+
const entdesc = resolveEntity(entityDescs, pathstr, m[1], m[2])
|
|
58
60
|
|
|
59
|
-
const op: Record<string, any> = {}
|
|
60
|
-
entdesc.path[pathname] = { op }
|
|
61
61
|
|
|
62
62
|
each(pathdef, (mdef, method) => {
|
|
63
63
|
const opname = METHOD_IDOP[method]
|
|
@@ -71,27 +71,27 @@ function resolveEntityDescs(ctx: any) {
|
|
|
71
71
|
const resokdef = mdef.responses[200] || mdef.responses[201]
|
|
72
72
|
const resbody = resokdef?.content?.['application/json']?.schema
|
|
73
73
|
if (resbody) {
|
|
74
|
-
if (resbody[
|
|
75
|
-
|
|
76
|
-
// transform.resform = '`body."'+origentname+'"`'
|
|
77
|
-
transform.resform = '`body.' + origentname + '`'
|
|
74
|
+
if (resbody[entdesc.origname]) {
|
|
75
|
+
transform.resform = '`body.' + entdesc.origname + '`'
|
|
78
76
|
}
|
|
79
|
-
else if (resbody[
|
|
80
|
-
transform.resform = '`body.' +
|
|
77
|
+
else if (resbody[entdesc.name]) {
|
|
78
|
+
transform.resform = '`body.' + entdesc.name + '`'
|
|
81
79
|
}
|
|
82
80
|
}
|
|
83
81
|
|
|
84
82
|
const reqdef = mdef.requestBody?.content?.['application/json']?.schema?.properties
|
|
85
83
|
if (reqdef) {
|
|
86
|
-
if (reqdef[
|
|
87
|
-
transform.reqform = { [
|
|
84
|
+
if (reqdef[entdesc.origname]) {
|
|
85
|
+
transform.reqform = { [entdesc.origname]: '`reqdata`' }
|
|
88
86
|
}
|
|
89
|
-
else if (reqdef[
|
|
90
|
-
transform.reqform = { [
|
|
87
|
+
else if (reqdef[entdesc.origname]) {
|
|
88
|
+
transform.reqform = { [entdesc.origname]: '`reqdata`' }
|
|
91
89
|
}
|
|
92
90
|
|
|
93
91
|
}
|
|
94
92
|
|
|
93
|
+
const op = entdesc.path[pathstr].op
|
|
94
|
+
|
|
95
95
|
op[opname] = {
|
|
96
96
|
// TODO: in actual guide, remove "standard" method ops since redundant
|
|
97
97
|
method,
|
|
@@ -104,41 +104,33 @@ function resolveEntityDescs(ctx: any) {
|
|
|
104
104
|
}
|
|
105
105
|
})
|
|
106
106
|
|
|
107
|
+
// Analyze paths ending in .../foo
|
|
108
|
+
each(paths, (pathdef, pathstr) => {
|
|
107
109
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
const m = pathname.match(/\/([a-zA-Z0-1_-]+)$/)
|
|
110
|
+
// Look for rightmmost /entname.
|
|
111
|
+
const m = pathstr.match(/\/([a-zA-Z0-1_-]+)$/)
|
|
111
112
|
if (m) {
|
|
112
|
-
|
|
113
|
-
let entname = depluralize(origentname)
|
|
114
|
-
|
|
115
|
-
let entdesc = entityDescs[entname]
|
|
116
|
-
|
|
117
|
-
if (entdesc) {
|
|
118
|
-
entdesc.path = (entdesc.path || {})
|
|
119
|
-
|
|
120
|
-
if (pathdef.get) {
|
|
121
|
-
const op: Record<string, any> = { list: { method: 'get' } }
|
|
122
|
-
entdesc.path[pathname] = { op }
|
|
123
|
-
|
|
124
|
-
const transform: Record<string, any> = {}
|
|
125
|
-
const mdef = pathdef.get
|
|
126
|
-
const resokdef = mdef.responses[200] || mdef.responses[201]
|
|
127
|
-
const resbody = resokdef?.content?.['application/json']?.schema
|
|
128
|
-
if (resbody) {
|
|
129
|
-
if (resbody[origentname]) {
|
|
130
|
-
// TODO: use quotes when @voxgig/struct updated to support them
|
|
131
|
-
// transform.resform = '`body."'+origentname+'"`'
|
|
132
|
-
transform.resform = '`body.' + origentname + '`'
|
|
133
|
-
}
|
|
134
|
-
else if (resbody[entname]) {
|
|
135
|
-
transform.resform = '`body.' + entname + '`'
|
|
136
|
-
}
|
|
137
|
-
}
|
|
113
|
+
const entdesc = resolveEntity(entityDescs, pathstr, m[1])
|
|
138
114
|
|
|
139
|
-
|
|
140
|
-
|
|
115
|
+
if (pathdef.get) {
|
|
116
|
+
const op: Record<string, any> = { list: { method: 'get' } }
|
|
117
|
+
entdesc.path[pathstr] = { op }
|
|
118
|
+
|
|
119
|
+
const transform: Record<string, any> = {}
|
|
120
|
+
const mdef = pathdef.get
|
|
121
|
+
const resokdef = mdef.responses[200] || mdef.responses[201]
|
|
122
|
+
const resbody = resokdef?.content?.['application/json']?.schema
|
|
123
|
+
if (resbody) {
|
|
124
|
+
if (resbody[entdesc.origname]) {
|
|
125
|
+
transform.resform = '`body.' + entdesc.origname + '`'
|
|
141
126
|
}
|
|
127
|
+
else if (resbody[entdesc.name]) {
|
|
128
|
+
transform.resform = '`body.' + entdesc.name + '`'
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
if (0 < Object.entries(transform).length) {
|
|
133
|
+
op.transform = transform
|
|
142
134
|
}
|
|
143
135
|
}
|
|
144
136
|
}
|
|
@@ -148,75 +140,36 @@ function resolveEntityDescs(ctx: any) {
|
|
|
148
140
|
}
|
|
149
141
|
|
|
150
142
|
|
|
151
|
-
function
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
'women': 'woman',
|
|
161
|
-
'teeth': 'tooth',
|
|
162
|
-
'feet': 'foot',
|
|
163
|
-
'geese': 'goose',
|
|
164
|
-
'mice': 'mouse',
|
|
165
|
-
'people': 'person',
|
|
166
|
-
'data': 'datum',
|
|
167
|
-
'criteria': 'criterion',
|
|
168
|
-
'phenomena': 'phenomenon',
|
|
169
|
-
'indices': 'index',
|
|
170
|
-
'matrices': 'matrix',
|
|
171
|
-
'vertices': 'vertex',
|
|
172
|
-
'analyses': 'analysis',
|
|
173
|
-
'axes': 'axis',
|
|
174
|
-
'crises': 'crisis',
|
|
175
|
-
'diagnoses': 'diagnosis',
|
|
176
|
-
'oases': 'oasis',
|
|
177
|
-
'theses': 'thesis',
|
|
178
|
-
'appendices': 'appendix'
|
|
179
|
-
}
|
|
143
|
+
function resolveEntity(
|
|
144
|
+
entityDescs: Record<string, EntityDesc>,
|
|
145
|
+
pathStr: string,
|
|
146
|
+
pathName: string,
|
|
147
|
+
pathParam?: string
|
|
148
|
+
)
|
|
149
|
+
: EntityDesc {
|
|
150
|
+
let origentname = snakify(pathName)
|
|
151
|
+
let entname = depluralize(origentname)
|
|
180
152
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
153
|
+
let entdesc = (entityDescs[entname] = entityDescs[entname] || { name: entname })
|
|
154
|
+
entdesc.plural = origentname
|
|
155
|
+
entdesc.origname = origentname
|
|
184
156
|
|
|
185
|
-
|
|
157
|
+
names(entdesc, entname)
|
|
186
158
|
|
|
187
|
-
|
|
188
|
-
if (word.endsWith('ies') && word.length > 3) {
|
|
189
|
-
return word.slice(0, -3) + 'y'
|
|
190
|
-
}
|
|
159
|
+
entdesc.alias = entdesc.alias || {}
|
|
191
160
|
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
return stem + 'fe'
|
|
161
|
+
if (null != pathParam) {
|
|
162
|
+
const pathParamCanon = snakify(pathParam)
|
|
163
|
+
if ('id' != pathParamCanon) {
|
|
164
|
+
entdesc.alias.id = pathParamCanon
|
|
165
|
+
entdesc.alias[pathParamCanon] = 'id'
|
|
198
166
|
}
|
|
199
|
-
return stem + 'f'
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
// -oes -> -o (potatoes -> potato)
|
|
203
|
-
if (word.endsWith('oes')) {
|
|
204
|
-
return word.slice(0, -2)
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
// -ses, -xes, -zes, -shes, -ches -> remove -es (boxes -> box)
|
|
208
|
-
if (word.endsWith('ses') || word.endsWith('xes') || word.endsWith('zes') ||
|
|
209
|
-
word.endsWith('shes') || word.endsWith('ches')) {
|
|
210
|
-
return word.slice(0, -2)
|
|
211
167
|
}
|
|
212
168
|
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
return word.slice(0, -1)
|
|
216
|
-
}
|
|
169
|
+
entdesc.path = (entdesc.path || {})
|
|
170
|
+
entdesc.path[pathStr] = { op: {} }
|
|
217
171
|
|
|
218
|
-
|
|
219
|
-
return word
|
|
172
|
+
return entdesc
|
|
220
173
|
}
|
|
221
174
|
|
|
222
175
|
|
package/src/guide.ts
CHANGED
|
@@ -8,8 +8,6 @@ import { heuristic01 } from './guide/heuristic01'
|
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
async function resolveGuide(ctx: any) {
|
|
11
|
-
// console.log('GUIDE CTX', ctx)
|
|
12
|
-
|
|
13
11
|
let guide: Record<string, any> = ctx.model.main.api.guide
|
|
14
12
|
|
|
15
13
|
if ('heuristic01' === ctx.opts.strategy) {
|
|
@@ -36,10 +34,10 @@ async function resolveGuide(ctx: any) {
|
|
|
36
34
|
|
|
37
35
|
|
|
38
36
|
guideBlocks.push(...each(guide.entity, (entity, entityname) => {
|
|
39
|
-
guideBlocks.push(`\nentity: ${entityname}:
|
|
37
|
+
guideBlocks.push(`\nentity: ${entityname}: {`)
|
|
40
38
|
|
|
41
39
|
each(entity.path, (path, pathname) => {
|
|
42
|
-
guideBlocks.push(` '${pathname}': op: {`)
|
|
40
|
+
guideBlocks.push(` path: '${pathname}': op: {`)
|
|
43
41
|
|
|
44
42
|
each(path.op, (op, opname) => {
|
|
45
43
|
guideBlocks.push(` '${opname}': method: ${op.method}`)
|
|
@@ -59,8 +57,6 @@ async function resolveGuide(ctx: any) {
|
|
|
59
57
|
|
|
60
58
|
const guideSrc = guideBlocks.join('\n')
|
|
61
59
|
|
|
62
|
-
// console.log(guideSrc)
|
|
63
|
-
|
|
64
60
|
return () => {
|
|
65
61
|
File({ name: Path.basename(guideFile) }, () => Content(guideSrc))
|
|
66
62
|
|
package/src/transform/entity.ts
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
|
|
2
2
|
|
|
3
|
-
import { each } from 'jostraca'
|
|
3
|
+
import { each, snakify } from 'jostraca'
|
|
4
4
|
|
|
5
5
|
import type { TransformResult, Transform } from '../transform'
|
|
6
6
|
|
|
7
7
|
import { fixName } from '../transform'
|
|
8
8
|
|
|
9
|
+
import { depluralize } from '../utility'
|
|
10
|
+
|
|
9
11
|
|
|
10
12
|
const entityTransform: Transform = async function(
|
|
11
13
|
ctx: any,
|
|
@@ -30,12 +32,16 @@ const entityTransform: Transform = async function(
|
|
|
30
32
|
id: {
|
|
31
33
|
name: 'id',
|
|
32
34
|
field: 'id',
|
|
33
|
-
}
|
|
35
|
+
},
|
|
36
|
+
ancestors: []
|
|
34
37
|
}
|
|
35
38
|
|
|
36
39
|
fixName(entityModel, guideEntity.key$)
|
|
37
40
|
|
|
38
|
-
|
|
41
|
+
let ancestors: string[] = []
|
|
42
|
+
let ancestorsDone = false
|
|
43
|
+
|
|
44
|
+
each(guideEntity.path, (guidePath: any, pathStr: string) => {
|
|
39
45
|
const path = guidePath.key$
|
|
40
46
|
const pathdef = def.paths[path]
|
|
41
47
|
|
|
@@ -50,8 +56,25 @@ const entityTransform: Transform = async function(
|
|
|
50
56
|
.filter((p: string) => p.startsWith('{'))
|
|
51
57
|
.map((p: string) => p.substring(1, p.length - 1))
|
|
52
58
|
|
|
59
|
+
if (!ancestorsDone) {
|
|
60
|
+
// Find all path sections matching /foo/{..param..} and build ancestors array
|
|
61
|
+
const paramRegex = /\/([a-zA-Z0-9_-]+)\/\{[a-zA-Z0-9_-]+\}/g
|
|
62
|
+
let m
|
|
63
|
+
while ((m = paramRegex.exec(pathStr)) !== null) {
|
|
64
|
+
// Skip if this is the last section (the entity itself)
|
|
65
|
+
const remainingPath = pathStr.substring(m.index + m[0].length)
|
|
66
|
+
if (remainingPath.length > 0) {
|
|
67
|
+
const ancestorName = depluralize(snakify(m[1]))
|
|
68
|
+
ancestors.push(ancestorName)
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
ancestorsDone = true
|
|
73
|
+
}
|
|
53
74
|
})
|
|
54
75
|
|
|
76
|
+
entityModel.ancestors = ancestors
|
|
77
|
+
|
|
55
78
|
msg += guideEntity.name + ' '
|
|
56
79
|
})
|
|
57
80
|
|