@voxgig/apidef 8.11.0 → 8.12.1

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.
Files changed (79) hide show
  1. package/dist/apidef.d.ts +4 -1
  2. package/dist/apidef.js +12 -34
  3. package/dist/apidef.js.map +1 -1
  4. package/dist/builder/entity/entity.js +0 -33
  5. package/dist/builder/entity/entity.js.map +1 -1
  6. package/dist/builder/entity/info.js +0 -4
  7. package/dist/builder/entity/info.js.map +1 -1
  8. package/dist/builder/flow.d.ts +4 -1
  9. package/dist/builder/flow.js +36 -27
  10. package/dist/builder/flow.js.map +1 -1
  11. package/dist/guide/graphql01.js +0 -55
  12. package/dist/guide/graphql01.js.map +1 -1
  13. package/dist/guide/guide.js +3 -126
  14. package/dist/guide/guide.js.map +1 -1
  15. package/dist/guide/heuristic01.js +40 -181
  16. package/dist/guide/heuristic01.js.map +1 -1
  17. package/dist/parse/graphql.js +0 -25
  18. package/dist/parse/graphql.js.map +1 -1
  19. package/dist/parse.js +51 -56
  20. package/dist/parse.js.map +1 -1
  21. package/dist/resolved.d.ts +23 -0
  22. package/dist/resolved.js +92 -0
  23. package/dist/resolved.js.map +1 -0
  24. package/dist/resolver.js +0 -2
  25. package/dist/resolver.js.map +1 -1
  26. package/dist/transform/args.js +2 -25
  27. package/dist/transform/args.js.map +1 -1
  28. package/dist/transform/casecollide.d.ts +3 -0
  29. package/dist/transform/casecollide.js +67 -0
  30. package/dist/transform/casecollide.js.map +1 -0
  31. package/dist/transform/contract.js +43 -38
  32. package/dist/transform/contract.js.map +1 -1
  33. package/dist/transform/entity.js +0 -56
  34. package/dist/transform/entity.js.map +1 -1
  35. package/dist/transform/field.js +1 -368
  36. package/dist/transform/field.js.map +1 -1
  37. package/dist/transform/flowstep.js +0 -49
  38. package/dist/transform/flowstep.js.map +1 -1
  39. package/dist/transform/graphql.js +0 -36
  40. package/dist/transform/graphql.js.map +1 -1
  41. package/dist/transform/operation.js +0 -23
  42. package/dist/transform/operation.js.map +1 -1
  43. package/dist/transform/top.js +1 -128
  44. package/dist/transform/top.js.map +1 -1
  45. package/dist/transform.js.map +1 -1
  46. package/dist/tsconfig.tsbuildinfo +1 -1
  47. package/dist/types.d.ts +2 -0
  48. package/dist/types.js.map +1 -1
  49. package/dist/utility.d.ts +2 -1
  50. package/dist/utility.js +17 -316
  51. package/dist/utility.js.map +1 -1
  52. package/model/apidef.aon +20 -113
  53. package/model/guide.aon +1 -32
  54. package/package.json +5 -5
  55. package/src/apidef.ts +22 -33
  56. package/src/builder/entity/entity.ts +0 -33
  57. package/src/builder/entity/info.ts +0 -4
  58. package/src/builder/flow.ts +39 -24
  59. package/src/desc.ts +0 -22
  60. package/src/guide/graphql01.ts +0 -75
  61. package/src/guide/guide.ts +5 -127
  62. package/src/guide/heuristic01.ts +47 -182
  63. package/src/model.ts +6 -85
  64. package/src/parse/graphql.ts +0 -25
  65. package/src/parse.ts +61 -56
  66. package/src/resolved.ts +136 -0
  67. package/src/resolver.ts +0 -2
  68. package/src/transform/args.ts +2 -25
  69. package/src/transform/casecollide.ts +80 -0
  70. package/src/transform/contract.ts +44 -34
  71. package/src/transform/entity.ts +0 -56
  72. package/src/transform/field.ts +2 -368
  73. package/src/transform/flowstep.ts +0 -49
  74. package/src/transform/graphql.ts +0 -36
  75. package/src/transform/operation.ts +0 -23
  76. package/src/transform/top.ts +1 -131
  77. package/src/transform.ts +0 -1
  78. package/src/types.ts +4 -13
  79. package/src/utility.ts +18 -314
@@ -34,27 +34,11 @@ const entityTransform: Transform = async function(
34
34
 
35
35
  let msg = ''
36
36
 
37
- // Pre-pass: merge collection paths into the entity that owns the
38
- // per-instance paths. Heuristic01 sometimes assigns "/people" to a
39
- // separate "*_search" entity (because the response wraps Person in
40
- // a search/pagination component) while "/people/{id}" and
41
- // "/people/{id}/anime" land on "person". Result: the person entity has
42
- // no primary list endpoint, so direct-load tests can't bootstrap an
43
- // ID. Move "/people" onto person here; this also clears the way for
44
- // sensible flow generation (one entity, one collection, multiple
45
- // sub-resources).
46
- // Path-shaped collection merging is meaningless for root-field guides.
47
37
  if (true !== ctx.def?.graphql) {
48
38
  mergeCollectionPaths(guide, ctx.log)
49
39
  }
50
40
 
51
41
  each(guide.entity, (guideEntity: GuideEntity, entname: string) => {
52
- // `active: false` in guide.aontu drops the entity. The guide model has
53
- // always declared `active?: boolean` at entity, path and op level and the
54
- // docs call it the intended escape hatch, but nothing read it — so an
55
- // entity a heuristic invented (a response envelope classified as a
56
- // resource, say) could not be removed by the one file a user is meant to
57
- // edit. Absent means active, so existing guides are unaffected.
58
42
  if (!guideActive(guideEntity)) {
59
43
  ctx.log.debug({ point: 'guide-entity', note: entname, active: false })
60
44
  return
@@ -68,9 +52,6 @@ const entityTransform: Transform = async function(
68
52
  resolveFieldList(guideEntity, ctx.def) :
69
53
  resolvePathList(guideEntity, ctx.def)
70
54
 
71
- // Ancestry is inferred from literal/{param} path pairs, which root
72
- // fields do not have; GraphQL relations come from the schema instead
73
- // (see transform/graphql.ts).
74
55
  const relations = graphql ?
75
56
  { ancestors: [] } :
76
57
  buildRelations(guideEntity, paths$)
@@ -97,10 +78,6 @@ const entityTransform: Transform = async function(
97
78
  function mergeCollectionPaths(guide: any, log?: any) {
98
79
  const entities = guide.entity as Record<string, any>
99
80
 
100
- // First pass: build collectionRoot -> owner-entity-name map.
101
- // owner is the entity whose name contains "/X/{...}" paths; we prefer
102
- // the owner whose direct-load path is "/X/{id}" (no further segments)
103
- // so that nested-resource entities don't claim the root.
104
81
  const rootOwners: Record<string, { ename: string, depth: number }> = {}
105
82
 
106
83
  for (const [ename, entity] of Object.entries(entities)) {
@@ -110,8 +87,6 @@ function mergeCollectionPaths(guide: any, log?: any) {
110
87
  if (!m) continue
111
88
  const root = m[1]
112
89
  const trailing = m[2] ?? ''
113
- // Depth = number of segments after the {id} placeholder. Lower
114
- // depth wins (e.g. "/people/{id}" beats "/people/{id}/anime").
115
90
  const depth = trailing === '' ? 0 : trailing.split('/').filter(Boolean).length
116
91
 
117
92
  const cur = rootOwners[root]
@@ -149,11 +124,6 @@ function mergeCollectionPaths(guide: any, log?: any) {
149
124
  targetEntity.path[pathStr] = srcPath
150
125
  }
151
126
  else {
152
- // Target already owns this path under a different heuristic-discovered
153
- // entity (e.g. `/gists` GET on `base_gist`, `/gists` POST on `gist`).
154
- // Merge op/action/rename sets so no method is silently lost — without
155
- // this, the second source's contribution drops on the floor and the
156
- // base-guide loses paths that were in the original spec.
157
127
  if (srcPath?.op) {
158
128
  tgtPath.op = tgtPath.op ?? {}
159
129
  for (const opname of Object.keys(srcPath.op)) {
@@ -202,14 +172,6 @@ function resolvePathList(guideEntity: GuideEntity, def: { paths: Record<string,
202
172
  return
203
173
  }
204
174
 
205
- // THE path construction site (ADR-003). The split, the rename
206
- // application and the segment typing all happen here and nowhere else:
207
- // a second place that decides what a path segment is would be free to
208
- // decide differently.
209
- //
210
- // A segment is a literal or a variable. The braced form this replaces
211
- // could not tell a literal containing braces from a parameter, so the
212
- // brace test below is the LAST point at which that ambiguity exists.
213
175
  const rename = guidePath.rename ?? {}
214
176
 
215
177
  const segments: PathSegment[] = orig
@@ -220,12 +182,6 @@ function resolvePathList(guideEntity: GuideEntity, def: { paths: Record<string,
220
182
  return { lit: p }
221
183
  }
222
184
  const raw = p.slice(1, -1)
223
- // A WHOLE element is the placeholder, or it is a literal. `{a}.{b}`
224
- // is two parameters glued into one element with a separator that
225
- // belongs to neither; it is not one parameter called `a}.{b`, and
226
- // there is no honest `var` for it. `{}` names nothing. Both stay
227
- // literal — which is exactly what the braced-string form did with
228
- // them, since the rename lookup was a whole-element match too.
229
185
  if ('' === raw || raw.includes('{') || raw.includes('}')) {
230
186
  return { lit: p }
231
187
  }
@@ -303,18 +259,6 @@ function resolveFieldList(guideEntity: GuideEntity, def: any) {
303
259
 
304
260
 
305
261
  function buildRelations(guideEntity: any, paths$: PathDesc[]) {
306
- // An ancestor is a literal collection segment (e.g. "rems") followed by
307
- // a path-param placeholder that names an instance ID. We only collect
308
- // the literal parts — placeholder parts like "{año}" must be excluded
309
- // even when they're themselves followed by another placeholder, otherwise
310
- // downstream code treats `{año}` as an ancestor name and emits broken
311
- // idmap entries / match keys.
312
- //
313
- // Each captured segment is then normalised to its entity name —
314
- // depluralize+snakify — so that "files"/"audit-log" become "file"/"audit_log",
315
- // i.e. the same keys downstream code uses to look up entities. Without this,
316
- // `apimodel.main.kit.entity[ancestorName]` misses the parent entity for
317
- // pluralised path segments.
318
262
  let ancestors: any[] = paths$
319
263
  .map(pli => pli.segments
320
264
  .map((s, i) => {