@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.
- package/dist/apidef.d.ts +4 -1
- package/dist/apidef.js +12 -34
- package/dist/apidef.js.map +1 -1
- package/dist/builder/entity/entity.js +0 -33
- package/dist/builder/entity/entity.js.map +1 -1
- package/dist/builder/entity/info.js +0 -4
- package/dist/builder/entity/info.js.map +1 -1
- package/dist/builder/flow.d.ts +4 -1
- package/dist/builder/flow.js +36 -27
- package/dist/builder/flow.js.map +1 -1
- package/dist/guide/graphql01.js +0 -55
- package/dist/guide/graphql01.js.map +1 -1
- package/dist/guide/guide.js +3 -126
- package/dist/guide/guide.js.map +1 -1
- package/dist/guide/heuristic01.js +40 -181
- package/dist/guide/heuristic01.js.map +1 -1
- package/dist/parse/graphql.js +0 -25
- package/dist/parse/graphql.js.map +1 -1
- package/dist/parse.js +51 -56
- package/dist/parse.js.map +1 -1
- package/dist/resolved.d.ts +23 -0
- package/dist/resolved.js +92 -0
- package/dist/resolved.js.map +1 -0
- package/dist/resolver.js +0 -2
- package/dist/resolver.js.map +1 -1
- package/dist/transform/args.js +2 -25
- package/dist/transform/args.js.map +1 -1
- package/dist/transform/casecollide.d.ts +3 -0
- package/dist/transform/casecollide.js +67 -0
- package/dist/transform/casecollide.js.map +1 -0
- package/dist/transform/contract.js +43 -38
- package/dist/transform/contract.js.map +1 -1
- package/dist/transform/entity.js +0 -56
- package/dist/transform/entity.js.map +1 -1
- package/dist/transform/field.js +1 -368
- package/dist/transform/field.js.map +1 -1
- package/dist/transform/flowstep.js +0 -49
- package/dist/transform/flowstep.js.map +1 -1
- package/dist/transform/graphql.js +0 -36
- package/dist/transform/graphql.js.map +1 -1
- package/dist/transform/operation.js +0 -23
- package/dist/transform/operation.js.map +1 -1
- package/dist/transform/top.js +1 -128
- package/dist/transform/top.js.map +1 -1
- package/dist/transform.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types.d.ts +2 -0
- package/dist/types.js.map +1 -1
- package/dist/utility.d.ts +2 -1
- package/dist/utility.js +17 -316
- package/dist/utility.js.map +1 -1
- package/model/apidef.aon +20 -113
- package/model/guide.aon +1 -32
- package/package.json +5 -5
- package/src/apidef.ts +22 -33
- package/src/builder/entity/entity.ts +0 -33
- package/src/builder/entity/info.ts +0 -4
- package/src/builder/flow.ts +39 -24
- package/src/desc.ts +0 -22
- package/src/guide/graphql01.ts +0 -75
- package/src/guide/guide.ts +5 -127
- package/src/guide/heuristic01.ts +47 -182
- package/src/model.ts +6 -85
- package/src/parse/graphql.ts +0 -25
- package/src/parse.ts +61 -56
- package/src/resolved.ts +136 -0
- package/src/resolver.ts +0 -2
- package/src/transform/args.ts +2 -25
- package/src/transform/casecollide.ts +80 -0
- package/src/transform/contract.ts +44 -34
- package/src/transform/entity.ts +0 -56
- package/src/transform/field.ts +2 -368
- package/src/transform/flowstep.ts +0 -49
- package/src/transform/graphql.ts +0 -36
- package/src/transform/operation.ts +0 -23
- package/src/transform/top.ts +1 -131
- package/src/transform.ts +0 -1
- package/src/types.ts +4 -13
- package/src/utility.ts +18 -314
package/src/guide/guide.ts
CHANGED
|
@@ -29,6 +29,7 @@ import {
|
|
|
29
29
|
import {
|
|
30
30
|
getdlog,
|
|
31
31
|
debugpath,
|
|
32
|
+
debugpathOn,
|
|
32
33
|
formatJSONIC,
|
|
33
34
|
relativizePath,
|
|
34
35
|
} from '../utility'
|
|
@@ -45,27 +46,6 @@ const aontu = new Aontu()
|
|
|
45
46
|
|
|
46
47
|
|
|
47
48
|
|
|
48
|
-
// MIGRATE, DO NOT ABANDON. The guide is the one model file the user owns —
|
|
49
|
-
// entity renames, hides, method overrides, response transforms. Reading
|
|
50
|
-
// `guide.aon` without this would find nothing in any project created before
|
|
51
|
-
// the extension rename, silently discarding every customization in the 660
|
|
52
|
-
// generated repos that carry a guide.aontu.
|
|
53
|
-
//
|
|
54
|
-
// RENAMING THE FILE IS NOT ENOUGH, and doing only that was worse than doing
|
|
55
|
-
// nothing: a legacy guide `@`-includes two files BY THE OLD EXTENSION —
|
|
56
|
-
// `@voxgig/apidef/model/guide.aontu`, which this package no longer ships, and
|
|
57
|
-
// its sibling `<prefix>base-guide.aontu`, which is now written as `.aon`.
|
|
58
|
-
// Carried across byte-for-byte, both dangle, and every build of such a
|
|
59
|
-
// project dies on
|
|
60
|
-
//
|
|
61
|
-
// [aontu/multisource_not_found]: source not found:
|
|
62
|
-
// @voxgig/apidef/model/guide.aontu
|
|
63
|
-
//
|
|
64
|
-
// — which is what apidef-validate hit on all 14 of its real-world specs. So
|
|
65
|
-
// the two includes the rename invalidates are rewritten with it. Nothing else
|
|
66
|
-
// is touched: the rest of the file is the user's.
|
|
67
|
-
//
|
|
68
|
-
// Returns true when a migration actually happened.
|
|
69
49
|
function migrateLegacyGuide(fs: any, folder: string, guideprefix: string): boolean {
|
|
70
50
|
const guidepath = Path.join(folder, 'guide', guideprefix + 'guide.aon')
|
|
71
51
|
const legacyguide = Path.join(folder, 'guide', guideprefix + 'guide.aontu')
|
|
@@ -74,14 +54,6 @@ function migrateLegacyGuide(fs: any, folder: string, guideprefix: string): boole
|
|
|
74
54
|
return false
|
|
75
55
|
}
|
|
76
56
|
|
|
77
|
-
// EXACTLY the two includes the rename invalidates, and no others.
|
|
78
|
-
//
|
|
79
|
-
// The sibling is `<guideprefix>base-guide`, because that is the only
|
|
80
|
-
// base-guide this build writes. Matching any `*base-guide.aontu` instead
|
|
81
|
-
// would rewrite a user's own `@"shared-base-guide.aontu"` — a file nothing
|
|
82
|
-
// renamed — into a path that does not exist, breaking the guide while
|
|
83
|
-
// deleting the original. A plain split/join keeps the prefix a literal, so
|
|
84
|
-
// a prefix containing regex metacharacters cannot widen the match either.
|
|
85
57
|
const legacysrc = String(fs.readFileSync(legacyguide, 'utf8'))
|
|
86
58
|
const migrated = legacysrc
|
|
87
59
|
.replace(/@"@voxgig\/apidef\/model\/guide\.aontu"/g,
|
|
@@ -95,24 +67,6 @@ function migrateLegacyGuide(fs: any, folder: string, guideprefix: string): boole
|
|
|
95
67
|
return true
|
|
96
68
|
}
|
|
97
69
|
|
|
98
|
-
// Give the guide's sibling include a `./`, in place, once.
|
|
99
|
-
//
|
|
100
|
-
// `guide.aon` is PROJECT-OWNED — the scaffold writes it at init and never
|
|
101
|
-
// again, because it is two includes a user rarely edits. So the scaffold
|
|
102
|
-
// template gaining a `./` reaches new projects only, and every existing one
|
|
103
|
-
// keeps `@"base-guide.aon"`, which aontu 0.65 refuses: a bare single-segment
|
|
104
|
-
// include now names a PACKAGE (ADR-039).
|
|
105
|
-
//
|
|
106
|
-
// A file the toolchain writes and the toolchain then refuses to read has to
|
|
107
|
-
// be migrated by the toolchain. `migrateLegacyGuide` above does exactly this
|
|
108
|
-
// for the `.aontu` -> `.aon` rename; this is the same move for the same file.
|
|
109
|
-
//
|
|
110
|
-
// THE SIBLING ONLY, matched as a whole include with the prefix absent. The
|
|
111
|
-
// package include beside it (`@"@voxgig/apidef/model/guide.aon"`) is a real
|
|
112
|
-
// package reference and must stay bare, and a user's own `@"./something"` is
|
|
113
|
-
// already correct. Anything else in the file is the user's.
|
|
114
|
-
//
|
|
115
|
-
// Returns true when a migration actually happened.
|
|
116
70
|
function migrateGuideIncludePrefix(
|
|
117
71
|
fs: any, guidepath: string, guideprefix: string
|
|
118
72
|
): boolean {
|
|
@@ -136,12 +90,6 @@ function migrateGuideIncludePrefix(
|
|
|
136
90
|
|
|
137
91
|
|
|
138
92
|
|
|
139
|
-
// The first unresolved merge-conflict marker in a source, or null.
|
|
140
|
-
//
|
|
141
|
-
// Anchored at line start and requiring exactly the conventional seven
|
|
142
|
-
// characters: a guide legitimately contains `>>>>>>> GENERATED` inside the
|
|
143
|
-
// jostraca provenance comments it writes about itself, and `====` shows up in
|
|
144
|
-
// prose. Only a real marker at column zero counts.
|
|
145
93
|
function findConflict(src: string): { line: number, text: string } | null {
|
|
146
94
|
const lines = String(src || '').split('\n')
|
|
147
95
|
|
|
@@ -202,27 +150,6 @@ async function buildGuide(ctx: ApiDefContext): Promise<any> {
|
|
|
202
150
|
|
|
203
151
|
handleErrors(ctx, errs)
|
|
204
152
|
|
|
205
|
-
// A MERGE CONFLICT IN A GUIDE IS SAID OUT LOUD, HERE.
|
|
206
|
-
//
|
|
207
|
-
// The guide is 3-way merged: apidef regenerates the base guide from the
|
|
208
|
-
// spec and merges it over what the project already had. Change the spec
|
|
209
|
-
// enough — swap a 5-path definition for the API's whole 722-path one — and
|
|
210
|
-
// an edit the project made can no longer be reconciled, so the merge
|
|
211
|
-
// writes ordinary `<<<<<<<` / `=======` / `>>>>>>>` markers into the file.
|
|
212
|
-
//
|
|
213
|
-
// Nothing then read the file until aontu did, and aontu reports what it
|
|
214
|
-
// sees: `unexpected character(s): <<<<<<<`, thousands of lines into a
|
|
215
|
-
// generated file, with no hint that this is a merge conflict or which edit
|
|
216
|
-
// caused it. That cost a long detour — the failure was read as apidef
|
|
217
|
-
// hanging, and the real cause (one conflicted rename) sat two lines away
|
|
218
|
-
// from a marker nobody had looked for.
|
|
219
|
-
//
|
|
220
|
-
// The guide is a file apidef itself writes, so apidef is the right place to
|
|
221
|
-
// recognise its own merge output before handing it on.
|
|
222
|
-
// BOTH FILES, and the base guide is the one that usually has it: `guide.aon`
|
|
223
|
-
// is two @-includes a user rarely edits, while `base-guide.aon` is what
|
|
224
|
-
// apidef regenerates and merges. Checking only the top-level file found
|
|
225
|
-
// nothing and left aontu to report the marker.
|
|
226
153
|
const basepath = Path.join(folder, 'guide', guideprefix + 'base-guide.aon')
|
|
227
154
|
for (const checkpath of [guidepath, basepath]) {
|
|
228
155
|
let checksrc = ''
|
|
@@ -266,35 +193,10 @@ async function buildGuide(ctx: ApiDefContext): Promise<any> {
|
|
|
266
193
|
errs,
|
|
267
194
|
}
|
|
268
195
|
|
|
269
|
-
// Only forward a *genuinely injected* fs.
|
|
270
|
-
//
|
|
271
|
-
// aontu resolves `@`-includes through @tabnas/multisource, which does:
|
|
272
|
-
// const P = null != ctx.meta?.fs ? Path.posix : Path
|
|
273
|
-
// i.e. it switches to POSIX path semantics whenever an fs is present, on
|
|
274
|
-
// the assumption that an injected fs is memfs keyed by POSIX paths.
|
|
275
|
-
//
|
|
276
|
-
// apidef defaults ctx.fs to the real node:fs (`opts.fs || Fs`), so
|
|
277
|
-
// forwarding it unconditionally made multisource parse *Windows* paths
|
|
278
|
-
// with Path.posix. 'D:\...\guide\x-guide.aontu' contains no '/', so the
|
|
279
|
-
// include base resolved to '' and sibling includes were looked up against
|
|
280
|
-
// the cwd instead of the guide folder — every build failed on Windows
|
|
281
|
-
// with `source not found: <prefix>base-guide.aontu`. Linux and macOS were
|
|
282
|
-
// unaffected because there Path and Path.posix are the same module.
|
|
283
|
-
//
|
|
284
|
-
// Callers that supply a real memfs (e.g. apidef-validate) still get it,
|
|
285
|
-
// and still get the POSIX semantics they need.
|
|
286
|
-
//
|
|
287
|
-
// Uses the explicit ctx.fsInjected flag rather than `Fs !== ctx.fs`:
|
|
288
|
-
// esModuleInterop compiles `import * as Fs` to __importStar(), which
|
|
289
|
-
// builds a fresh wrapper per module, so identity comparison across
|
|
290
|
-
// modules is always false.
|
|
291
196
|
if (ctx.fsInjected) {
|
|
292
197
|
opts.fs = ctx.fs
|
|
293
198
|
}
|
|
294
199
|
|
|
295
|
-
// Record what was actually handed to aontu, not what we intended to hand
|
|
296
|
-
// it, so the regression test fails if this block is ever changed back to
|
|
297
|
-
// an unconditional assignment.
|
|
298
200
|
ctx.work.guideAontuFs = undefined !== opts.fs
|
|
299
201
|
|
|
300
202
|
const guideModel = aontu.generate(src, opts)
|
|
@@ -358,7 +260,6 @@ async function buildBaseGuide(ctx: ApiDefContext) {
|
|
|
358
260
|
|
|
359
261
|
const metrics = baseguide.metrics
|
|
360
262
|
|
|
361
|
-
// TODO: these should influence the IS_ENTCMP_METHOD_RATE etc. values
|
|
362
263
|
const epr =
|
|
363
264
|
0 < metrics.count.path ? (metrics.count.entity / metrics.count.path).toFixed(3) : -1
|
|
364
265
|
const emr =
|
|
@@ -404,8 +305,10 @@ async function buildBaseGuide(ctx: ApiDefContext) {
|
|
|
404
305
|
path: GuidePath
|
|
405
306
|
) => {
|
|
406
307
|
{
|
|
407
|
-
|
|
408
|
-
|
|
308
|
+
if (debugpathOn()) {
|
|
309
|
+
debugpath(entrykey, null, 'BASE-GUIDE', entname, entrykey,
|
|
310
|
+
formatJSONIC(path, { hsepd: 0, $: true, color: true }))
|
|
311
|
+
}
|
|
409
312
|
|
|
410
313
|
guideBlocks.push(` ${branch}: ${qs(entrykey)}: {` +
|
|
411
314
|
sw(0 < path.why_path.length ?
|
|
@@ -435,21 +338,10 @@ async function buildBaseGuide(ctx: ApiDefContext) {
|
|
|
435
338
|
if (null != op.optype) {
|
|
436
339
|
guideBlocks.push(` op: ${opname}: optype: *${op.optype}`)
|
|
437
340
|
}
|
|
438
|
-
// Each transform is emitted only when set, and each on its own terms.
|
|
439
|
-
// (An earlier req-GUARDED block pushed a second res line built from
|
|
440
|
-
// op.transform.res — emitting `transform: res: *undefined` whenever a
|
|
441
|
-
// request was wrapped but the response was not. Hence the separate
|
|
442
|
-
// null checks below rather than one shared guard.)
|
|
443
341
|
if (null != op.transform.res) {
|
|
444
342
|
guideBlocks.push(
|
|
445
343
|
` op: ${opname}: transform: res: *${qt(op.transform.res)}|top`)
|
|
446
344
|
}
|
|
447
|
-
// The req transform is a MAP of body property -> source expression
|
|
448
|
-
// (see closedBodyTransform), so it takes one line per property. THE
|
|
449
|
-
// SERIALISED GUIDE IS WHAT THE TRANSFORM STEP READS: a transform not
|
|
450
|
-
// written here never reaches the model, which is why restricting a
|
|
451
|
-
// closed request body had no effect until this existed. Only the map
|
|
452
|
-
// form is representable as aontu paths; a scalar req is left alone.
|
|
453
345
|
const reqmap: any = op.transform.req
|
|
454
346
|
if (null != reqmap && 'object' === typeof reqmap) {
|
|
455
347
|
items(reqmap).map(([bodykey, source]: [string, any]) => {
|
|
@@ -470,16 +362,6 @@ async function buildBaseGuide(ctx: ApiDefContext) {
|
|
|
470
362
|
guideBlocks.push(`
|
|
471
363
|
entity: ${entname}: {`)
|
|
472
364
|
|
|
473
|
-
// An entity the heuristic deactivated (today: an access-token exchange,
|
|
474
|
-
// which is credential plumbing rather than a resource) is EMITTED, not
|
|
475
|
-
// dropped, so the classification is visible and reversible in guide.aon
|
|
476
|
-
// — the only correction surface (ADR-002).
|
|
477
|
-
//
|
|
478
|
-
// `*false` — a DEFAULT, not a concrete value. aontu conflicts two
|
|
479
|
-
// concrete values rather than letting one win, so a concrete `active:
|
|
480
|
-
// false` here would make a user's `guide: entity: <name>: active: true`
|
|
481
|
-
// in guide.aon fail to unify instead of overriding it. That is the same
|
|
482
|
-
// trap the `method: *POST` entries above avoid.
|
|
483
365
|
if (false === entity.active) {
|
|
484
366
|
const why = (entity as any).why_inactive
|
|
485
367
|
guideBlocks.push(
|
|
@@ -530,10 +412,6 @@ async function buildBaseGuide(ctx: ApiDefContext) {
|
|
|
530
412
|
|
|
531
413
|
|
|
532
414
|
|
|
533
|
-
// GraphQL coverage guard: every Query/Mutation root field must either be
|
|
534
|
-
// assigned to an entity op or be deliberately excluded by the classifier
|
|
535
|
-
// (machinery types, scalar returns). Mirrors the REST PATH MISMATCH check —
|
|
536
|
-
// silence about an unclassified field is how an API silently loses surface.
|
|
537
415
|
function validateGraphqlBaseGuide(ctx: ApiDefContext, baseguide: any) {
|
|
538
416
|
const covered: Record<string, boolean> = {}
|
|
539
417
|
|