@voxgig/sdkgen 3.4.7 → 3.5.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/bin/voxgig-sdkgen +78 -10
- package/dist/action/action.d.ts +5 -2
- package/dist/action/action.js +113 -6
- package/dist/action/action.js.map +1 -1
- package/dist/action/check.d.ts +15 -0
- package/dist/action/check.js +347 -0
- package/dist/action/check.js.map +1 -0
- package/dist/action/dispatch.d.ts +8 -0
- package/dist/action/dispatch.js +74 -0
- package/dist/action/dispatch.js.map +1 -0
- package/dist/action/docs.d.ts +4 -0
- package/dist/action/docs.js +236 -0
- package/dist/action/docs.js.map +1 -0
- package/dist/action/doctor.d.ts +5 -2
- package/dist/action/doctor.js +526 -74
- package/dist/action/doctor.js.map +1 -1
- package/dist/action/feature.js +96 -17
- package/dist/action/feature.js.map +1 -1
- package/dist/action/kind.d.ts +30 -0
- package/dist/action/kind.js +258 -0
- package/dist/action/kind.js.map +1 -0
- package/dist/action/package.d.ts +25 -0
- package/dist/action/package.js +852 -0
- package/dist/action/package.js.map +1 -0
- package/dist/action/resolve.d.ts +18 -0
- package/dist/action/resolve.js +280 -0
- package/dist/action/resolve.js.map +1 -0
- package/dist/action/target.d.ts +7 -1
- package/dist/action/target.js +240 -97
- package/dist/action/target.js.map +1 -1
- package/dist/cmp/Docs.d.ts +4 -0
- package/dist/cmp/Docs.js +98 -0
- package/dist/cmp/Docs.js.map +1 -0
- package/dist/cmp/ExternalDocs.d.ts +2 -0
- package/dist/cmp/ExternalDocs.js +43 -0
- package/dist/cmp/ExternalDocs.js.map +1 -0
- package/dist/helpers/definition.d.ts +5 -0
- package/dist/helpers/definition.js +72 -0
- package/dist/helpers/definition.js.map +1 -0
- package/dist/helpers/featureSource.d.ts +8 -2
- package/dist/helpers/featureSource.js +61 -12
- package/dist/helpers/featureSource.js.map +1 -1
- package/dist/helpers/junk.d.ts +11 -0
- package/dist/helpers/junk.js +149 -0
- package/dist/helpers/junk.js.map +1 -0
- package/dist/helpers/manifest.d.ts +50 -0
- package/dist/helpers/manifest.js +328 -0
- package/dist/helpers/manifest.js.map +1 -0
- package/dist/helpers/modelcheck.d.ts +22 -0
- package/dist/helpers/modelcheck.js +203 -0
- package/dist/helpers/modelcheck.js.map +1 -0
- package/dist/helpers/semver.d.ts +4 -0
- package/dist/helpers/semver.js +174 -0
- package/dist/helpers/semver.js.map +1 -0
- package/dist/helpers/shipped.d.ts +4 -0
- package/dist/helpers/shipped.js +36 -0
- package/dist/helpers/shipped.js.map +1 -0
- package/dist/helpers/stdrep.d.ts +9 -1
- package/dist/helpers/stdrep.js +22 -0
- package/dist/helpers/stdrep.js.map +1 -1
- package/dist/sdkgen.d.ts +15 -3
- package/dist/sdkgen.js +233 -67
- package/dist/sdkgen.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types.d.ts +10 -2
- package/dist/utility.js +17 -0
- package/dist/utility.js.map +1 -1
- package/model/sdkgen.aontu +69 -0
- package/package.json +3 -2
- package/project/.sdk/model/feature/audit.aontu +1 -0
- package/project/.sdk/model/feature/cache.aontu +1 -0
- package/project/.sdk/model/feature/clienttrack.aontu +1 -0
- package/project/.sdk/model/feature/debug.aontu +1 -0
- package/project/.sdk/model/feature/idempotency.aontu +1 -0
- package/project/.sdk/model/feature/log.aontu +1 -0
- package/project/.sdk/model/feature/metrics.aontu +1 -0
- package/project/.sdk/model/feature/netsim.aontu +1 -0
- package/project/.sdk/model/feature/paging.aontu +1 -0
- package/project/.sdk/model/feature/proxy.aontu +1 -0
- package/project/.sdk/model/feature/ratelimit.aontu +1 -0
- package/project/.sdk/model/feature/rbac.aontu +1 -0
- package/project/.sdk/model/feature/retry.aontu +1 -0
- package/project/.sdk/model/feature/streaming.aontu +1 -0
- package/project/.sdk/model/feature/telemetry.aontu +1 -0
- package/project/.sdk/model/feature/test.aontu +1 -0
- package/project/.sdk/model/feature/timeout.aontu +1 -0
- package/project/.sdk/model/target/c.aontu +1 -0
- package/project/.sdk/model/target/clojure.aontu +1 -0
- package/project/.sdk/model/target/cpp.aontu +1 -0
- package/project/.sdk/model/target/dart.aontu +1 -0
- package/project/.sdk/model/target/elixir.aontu +1 -0
- package/project/.sdk/model/target/go-cli.aontu +1 -0
- package/project/.sdk/model/target/go-mcp.aontu +1 -0
- package/project/.sdk/model/target/go.aontu +1 -0
- package/project/.sdk/model/target/haskell.aontu +1 -0
- package/project/.sdk/model/target/java.aontu +1 -0
- package/project/.sdk/model/target/js.aontu +1 -0
- package/project/.sdk/model/target/kotlin.aontu +1 -0
- package/project/.sdk/model/target/lean.aontu +1 -0
- package/project/.sdk/model/target/lua.aontu +1 -0
- package/project/.sdk/model/target/ocaml.aontu +1 -0
- package/project/.sdk/model/target/perl.aontu +1 -0
- package/project/.sdk/model/target/php.aontu +1 -0
- package/project/.sdk/model/target/py-data.aontu +1 -0
- package/project/.sdk/model/target/py.aontu +1 -0
- package/project/.sdk/model/target/rb.aontu +1 -0
- package/project/.sdk/model/target/rust.aontu +1 -0
- package/project/.sdk/model/target/scala.aontu +1 -0
- package/project/.sdk/model/target/seneca-provider.aontu +1 -0
- package/project/.sdk/model/target/zig.aontu +1 -0
- package/project/.sdk/src/cmp/c/Config_c.ts +44 -0
- package/project/.sdk/src/cmp/c/fragment/Main.fragment.c +3 -1
- package/project/.sdk/src/cmp/clojure/Config_clojure.ts +37 -42
- package/project/.sdk/src/cmp/clojure/utility_clojure.ts +42 -0
- package/project/.sdk/src/cmp/cpp/Config_cpp.ts +18 -0
- package/project/.sdk/src/cmp/csharp/Config_csharp.ts +125 -52
- package/project/.sdk/src/cmp/csharp/fragment/Main.fragment.cs +3 -1
- package/project/.sdk/src/cmp/csharp/utility_csharp.ts +94 -6
- package/project/.sdk/src/cmp/dart/Config_dart.ts +43 -5
- package/project/.sdk/src/cmp/dart/fragment/Config.data.fragment.dart +74 -0
- package/project/.sdk/src/cmp/dart/fragment/Config.fragment.dart +6 -9
- package/project/.sdk/src/cmp/dart/fragment/Main.fragment.dart +16 -5
- package/project/.sdk/src/cmp/dart/utility_dart.ts +18 -0
- package/project/.sdk/src/cmp/elixir/Config_elixir.ts +128 -13
- package/project/.sdk/src/cmp/elixir/fragment/Main.fragment.ex +3 -1
- package/project/.sdk/src/cmp/elixir/utility_elixir.ts +6 -0
- package/project/.sdk/src/cmp/haskell/Config_haskell.ts +35 -52
- package/project/.sdk/src/cmp/haskell/Package_haskell.ts +1 -0
- package/project/.sdk/src/cmp/haskell/Test_haskell.ts +1 -1
- package/project/.sdk/src/cmp/haskell/utility_haskell.ts +15 -5
- package/project/.sdk/src/cmp/java/Config_java.ts +21 -0
- package/project/.sdk/src/cmp/kotlin/Config_kotlin.ts +15 -0
- package/project/.sdk/src/cmp/ocaml/Config_ocaml.ts +42 -39
- package/project/.sdk/src/cmp/perl/Config_perl.ts +15 -0
- package/project/.sdk/src/cmp/perl/fragment/Main.fragment.pm +3 -1
- package/project/.sdk/src/cmp/rust/Config_rust.ts +44 -0
- package/project/.sdk/src/cmp/rust/fragment/Main.fragment.rs +4 -2
- package/project/.sdk/src/cmp/scala/Config_scala.ts +15 -0
- package/project/.sdk/src/cmp/swift/Config_swift.ts +17 -0
- package/project/.sdk/src/cmp/swift/fragment/Main.fragment.swift +3 -1
- package/project/.sdk/src/cmp/zig/Config_zig.ts +44 -0
- package/project/.sdk/src/cmp/zig/TestEntity_zig.ts +9 -2
- package/project/.sdk/src/cmp/zig/fragment/Main.fragment.zig +3 -1
- package/project/.sdk/tm/c/core/sdk.h +1 -0
- package/project/.sdk/tm/c/utility/make_options.c +5 -1
- package/project/.sdk/tm/clojure/src/sdk/core.clj +51 -3
- package/project/.sdk/tm/cpp/core/types.hpp +4 -1
- package/project/.sdk/tm/cpp/utility/pipeline.hpp +5 -1
- package/project/.sdk/tm/csharp/test/PipelineTest.cs +15 -0
- package/project/.sdk/tm/csharp/utility/MakeOptions.cs +67 -1
- package/project/.sdk/tm/dart/lib/utility/MakeOptionsUtility.dart +43 -0
- package/project/.sdk/tm/elixir/lib/projectname/utility.ex +58 -2
- package/project/.sdk/tm/haskell/{test/TestJson.hs → src/SdkJson.hs} +8 -4
- package/project/.sdk/tm/haskell/src/SdkRuntime.hs +55 -2
- package/project/.sdk/tm/haskell/test/Runner.hs +1 -1
- package/project/.sdk/tm/haskell/test/StructCorpus.hs +1 -1
- package/project/.sdk/tm/java/core/SdkClient.java +3 -1
- package/project/.sdk/tm/java/utility/MakeOptions.java +5 -1
- package/project/.sdk/tm/kotlin/core/SdkClient.kt +3 -1
- package/project/.sdk/tm/kotlin/utility/MakeOptions.kt +5 -1
- package/project/.sdk/tm/ocaml/Makefile +3 -2
- package/project/.sdk/tm/ocaml/sdk_json.ml +106 -0
- package/project/.sdk/tm/ocaml/sdk_runtime.ml +56 -0
- package/project/.sdk/tm/ocaml/test/struct_corpus.ml +4 -86
- package/project/.sdk/tm/perl/utility/make_options.pm +5 -1
- package/project/.sdk/tm/rust/utility/make_options.rs +79 -1
- package/project/.sdk/tm/scala/core/SdkClient.scala +3 -1
- package/project/.sdk/tm/scala/utility/Make.scala +5 -1
- package/project/.sdk/tm/swift/Sources/ProjectNameSDK/utility/MakeOptions.swift +5 -1
- package/project/.sdk/tm/zig/core/utility.zig +85 -1
- package/project/sdkgen-package.json +57 -0
- package/src/action/action.ts +136 -6
- package/src/action/check.ts +495 -0
- package/src/action/dispatch.ts +105 -0
- package/src/action/docs.ts +310 -0
- package/src/action/doctor.ts +692 -81
- package/src/action/feature.ts +109 -17
- package/src/action/kind.ts +375 -0
- package/src/action/package.ts +1173 -0
- package/src/action/resolve.ts +362 -0
- package/src/action/target.ts +290 -108
- package/src/cmp/Docs.ts +125 -0
- package/src/cmp/ExternalDocs.ts +54 -0
- package/src/helpers/definition.ts +82 -0
- package/src/helpers/featureSource.ts +83 -13
- package/src/helpers/junk.ts +168 -0
- package/src/helpers/manifest.ts +474 -0
- package/src/helpers/modelcheck.ts +262 -0
- package/src/helpers/semver.ts +211 -0
- package/src/helpers/shipped.ts +41 -0
- package/src/helpers/stdrep.ts +70 -0
- package/src/sdkgen.ts +294 -66
- package/src/types.ts +33 -3
- package/src/utility.ts +17 -0
package/src/sdkgen.ts
CHANGED
|
@@ -5,7 +5,6 @@ import Path from 'node:path'
|
|
|
5
5
|
|
|
6
6
|
import { prettyPino, Pino } from '@voxgig/util'
|
|
7
7
|
|
|
8
|
-
import { Jsonic } from '@tabnas/jsonic'
|
|
9
8
|
import * as JostracaModule from 'jostraca'
|
|
10
9
|
import { Aontu } from 'aontu'
|
|
11
10
|
|
|
@@ -25,6 +24,8 @@ import { SdkGenError, requirePath, isAuthActive, resolveAuthPrefix,
|
|
|
25
24
|
|
|
26
25
|
import { Main } from './cmp/Main'
|
|
27
26
|
import { ExternalTarget } from './cmp/ExternalTarget'
|
|
27
|
+
import { Docs, DocsItem } from './cmp/Docs'
|
|
28
|
+
import { ExternalDocs } from './cmp/ExternalDocs'
|
|
28
29
|
|
|
29
30
|
import { KIT } from '@voxgig/apidef'
|
|
30
31
|
import { Deploy } from './cmp/Deploy'
|
|
@@ -73,6 +74,19 @@ import {
|
|
|
73
74
|
srcFeatureExcludes,
|
|
74
75
|
} from './helpers/featureSource'
|
|
75
76
|
import type { FeatureSource } from './helpers/featureSource'
|
|
77
|
+
import {
|
|
78
|
+
definitionPath,
|
|
79
|
+
definitionFolder,
|
|
80
|
+
definitionNames,
|
|
81
|
+
} from './helpers/definition'
|
|
82
|
+
import { isNoise, copyOpts } from './helpers/junk'
|
|
83
|
+
import {
|
|
84
|
+
MANIFEST,
|
|
85
|
+
manifestPath,
|
|
86
|
+
readManifest,
|
|
87
|
+
validateManifest,
|
|
88
|
+
} from './helpers/manifest'
|
|
89
|
+
import type { Manifest, ManifestRead } from './helpers/manifest'
|
|
76
90
|
import {
|
|
77
91
|
packageName,
|
|
78
92
|
installCommand,
|
|
@@ -117,6 +131,19 @@ import {
|
|
|
117
131
|
} from './action/doctor'
|
|
118
132
|
import type { DoctorReport } from './action/doctor'
|
|
119
133
|
|
|
134
|
+
import {
|
|
135
|
+
action_package,
|
|
136
|
+
package_add,
|
|
137
|
+
package_update,
|
|
138
|
+
} from './action/package'
|
|
139
|
+
|
|
140
|
+
import { cmd_package_check } from './action/check'
|
|
141
|
+
|
|
142
|
+
import { docs_add } from './action/docs'
|
|
143
|
+
|
|
144
|
+
// The verbs, built from the kind registry — see action/dispatch.
|
|
145
|
+
import { ACTION_MAP, actionNames, needsModel } from './action/dispatch'
|
|
146
|
+
|
|
120
147
|
|
|
121
148
|
|
|
122
149
|
// TODO: use shape
|
|
@@ -149,13 +176,6 @@ type SdkGenOptions = {
|
|
|
149
176
|
const { Jostraca } = JostracaModule
|
|
150
177
|
|
|
151
178
|
|
|
152
|
-
const ACTION_MAP: any = {
|
|
153
|
-
target: action_target,
|
|
154
|
-
feature: action_feature,
|
|
155
|
-
doctor: action_doctor,
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
|
|
159
179
|
const dlog = getdlog('sdkgen', __filename)
|
|
160
180
|
|
|
161
181
|
|
|
@@ -188,7 +208,12 @@ function SdkGen(opts: SdkGenOptions) {
|
|
|
188
208
|
write: true,
|
|
189
209
|
merge: false
|
|
190
210
|
}
|
|
191
|
-
}
|
|
211
|
+
},
|
|
212
|
+
// No copied tree carries a maintainer's `.DS_Store` or `__pycache__` into
|
|
213
|
+
// an SDK. Set here AND per call (see helpers/junk) — the actions run on
|
|
214
|
+
// whatever instance their caller supplies, so neither placement covers
|
|
215
|
+
// every path on its own.
|
|
216
|
+
cmp: copyOpts()
|
|
192
217
|
}
|
|
193
218
|
|
|
194
219
|
const jostraca = Jostraca(jopts)
|
|
@@ -229,6 +254,9 @@ function SdkGen(opts: SdkGenOptions) {
|
|
|
229
254
|
control: {
|
|
230
255
|
dryrun: !!opts.dryrun
|
|
231
256
|
},
|
|
257
|
+
// Per-call for the same reason as `control` above: an option the
|
|
258
|
+
// instance carries is not reliably the one a generate sees.
|
|
259
|
+
cmp: copyOpts(),
|
|
232
260
|
}
|
|
233
261
|
|
|
234
262
|
// Targets that write OUTSIDE the SDK repo (`output: path`) are generated
|
|
@@ -240,7 +268,7 @@ function SdkGen(opts: SdkGenOptions) {
|
|
|
240
268
|
// so resolve it ONCE: every destination is compared against it, and a
|
|
241
269
|
// comparison between a relative and an absolute path is meaningless.
|
|
242
270
|
const root = Path.resolve(folder)
|
|
243
|
-
const external =
|
|
271
|
+
const external = externalItems(model, root, ['target', 'docs'])
|
|
244
272
|
|
|
245
273
|
// Before ANY file is written, in-tree included: a destination that turns
|
|
246
274
|
// out to be wrong must abort the whole generation, not leave half of it
|
|
@@ -248,15 +276,85 @@ function SdkGen(opts: SdkGenOptions) {
|
|
|
248
276
|
checkExternalFolders(external, root, fs)
|
|
249
277
|
|
|
250
278
|
const jres = await jostraca.generate(
|
|
251
|
-
jopts, () => Root({ model: 0 === external.length ? model :
|
|
279
|
+
jopts, () => Root({ model: 0 === external.length ? model : withoutExternal(model, external) }))
|
|
252
280
|
|
|
253
281
|
showChanges(jopts.log, 'generate-result', jres, Path.dirname(process.cwd()))
|
|
254
282
|
|
|
283
|
+
// IN-TREE DOCS, in their own pass over the same root.
|
|
284
|
+
//
|
|
285
|
+
// The alternative is one `Kinds()` call in the consumer's `Root.ts` —
|
|
286
|
+
// which create-sdkgen writes once and never revisits, so every project
|
|
287
|
+
// scaffolded before the docs kind existed would have to be hand-edited
|
|
288
|
+
// before `docs add` did anything. A second pass costs one more changes
|
|
289
|
+
// report and makes the kind work in projects that predate it, which is
|
|
290
|
+
// the whole point of putting the destinations in packages.
|
|
291
|
+
//
|
|
292
|
+
// Items with `output: path` are excluded here and generated by the loop
|
|
293
|
+
// below, exactly as out-of-tree targets are.
|
|
294
|
+
const intreedocs = Object.keys(model?.main?.[KIT]?.docs ?? {})
|
|
295
|
+
.filter((name: string) => {
|
|
296
|
+
const item = model.main[KIT].docs[name]
|
|
297
|
+
const path = item?.output?.path
|
|
298
|
+
return false !== item?.active && (null == path || '' === path)
|
|
299
|
+
})
|
|
300
|
+
|
|
301
|
+
// AN IN-TREE DOCS ITEM AND A TARGET CANNOT SHARE A NAME.
|
|
302
|
+
//
|
|
303
|
+
// `docs` and `target` are separate namespaces — deliberately, so an item
|
|
304
|
+
// of each may be called `api` — and their `.sdk` trees are nested apart
|
|
305
|
+
// (`src/cmp/docs/<n>` vs `src/cmp/<n>`), so installing both is fine.
|
|
306
|
+
//
|
|
307
|
+
// Their GENERATED destinations are not separate. Both render into
|
|
308
|
+
// `<sdk-repo>/<name>/`, the docs pass runs second, and jostraca is
|
|
309
|
+
// last-write-wins — so a docs item named `go` would quietly overwrite the
|
|
310
|
+
// Go SDK's README, and whatever else the two have in common, leaving a
|
|
311
|
+
// corrupt SDK and a green run.
|
|
312
|
+
//
|
|
313
|
+
// Refused rather than reordered, and refused BEFORE the docs pass writes
|
|
314
|
+
// anything: this is the in-tree half of the rule `checkExternalFolders`
|
|
315
|
+
// enforces for out-of-tree destinations, and the fix is the same either
|
|
316
|
+
// way — give one of them `output: path`, or rename it.
|
|
317
|
+
const targets: any = model?.main?.[KIT]?.target ?? {}
|
|
318
|
+
|
|
319
|
+
for (const name of intreedocs) {
|
|
320
|
+
const target = targets[name]
|
|
321
|
+
|
|
322
|
+
if (null == target || false === target.active) {
|
|
323
|
+
continue
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
const tpath = target.output?.path
|
|
327
|
+
|
|
328
|
+
if (null != tpath && '' !== tpath) {
|
|
329
|
+
continue
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
throw new SdkGenError(
|
|
333
|
+
'Docs item "' + name + '" and target "' + name + '" would both ' +
|
|
334
|
+
'generate into <sdk-project>/' + name + '/.\n' +
|
|
335
|
+
' They are separate kinds, so sharing a name is legal — but they ' +
|
|
336
|
+
'share one output folder, and the docs pass runs second, so it ' +
|
|
337
|
+
'would overwrite the SDK.\n' +
|
|
338
|
+
' Give one of them `output: path`, or rename it.')
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
if (0 < intreedocs.length) {
|
|
342
|
+
log.info({
|
|
343
|
+
point: 'generate-docs-start', docs: intreedocs,
|
|
344
|
+
note: intreedocs.join(', ')
|
|
345
|
+
})
|
|
346
|
+
|
|
347
|
+
const dres = await jostraca.generate(jopts, () => Docs({ model }))
|
|
348
|
+
|
|
349
|
+
showChanges(jopts.log, 'generate-docs-result', dres,
|
|
350
|
+
Path.dirname(process.cwd()))
|
|
351
|
+
}
|
|
352
|
+
|
|
255
353
|
for (const ext of external) {
|
|
256
354
|
// `active: false` is the project's only lever to stop the generator
|
|
257
355
|
// writing into a repo it does not own, so it has to be honoured HERE —
|
|
258
356
|
// the consumer Root iterates targets raw and does not check it. The
|
|
259
|
-
// target is still removed from the in-tree model above (
|
|
357
|
+
// target is still removed from the in-tree model above (withoutExternal
|
|
260
358
|
// takes every `output: path` target, active or not), so switching one
|
|
261
359
|
// off generates it nowhere rather than relocating it into
|
|
262
360
|
// `<sdk-repo>/<target>/`.
|
|
@@ -273,15 +371,23 @@ function SdkGen(opts: SdkGenOptions) {
|
|
|
273
371
|
note: ext.name + ' -> ' + ext.folder
|
|
274
372
|
})
|
|
275
373
|
|
|
276
|
-
const
|
|
374
|
+
const sdkrelpath = externalSdkRel(ext, root, log)
|
|
375
|
+
|
|
376
|
+
const eres = 'docs' === ext.kind ?
|
|
377
|
+
await jostraca.generate(
|
|
378
|
+
{ ...jopts, folder: ext.folder },
|
|
379
|
+
() => ExternalDocs({
|
|
380
|
+
model, item: ext.target, cmpfolder: folder, sdkrelpath,
|
|
381
|
+
})) :
|
|
382
|
+
await jostraca.generate(
|
|
277
383
|
{ ...jopts, folder: ext.folder },
|
|
278
384
|
() => ExternalTarget({
|
|
279
385
|
model, target: ext.target, cmpfolder: folder,
|
|
280
|
-
// How to walk BACK to the SDK project from the destination.
|
|
281
|
-
//
|
|
386
|
+
// How to walk BACK to the SDK project from the destination. An
|
|
387
|
+
// item generating out of tree usually sits beside the SDK in a
|
|
282
388
|
// known layout, and its own docs, scripts and live tests need to
|
|
283
389
|
// name that path.
|
|
284
|
-
sdkrelpath
|
|
390
|
+
sdkrelpath,
|
|
285
391
|
}))
|
|
286
392
|
|
|
287
393
|
showChanges(jopts.log, 'generate-result', eres, Path.dirname(process.cwd()))
|
|
@@ -300,26 +406,47 @@ function SdkGen(opts: SdkGenOptions) {
|
|
|
300
406
|
}
|
|
301
407
|
|
|
302
408
|
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
409
|
+
// Action arguments are PATHS AND NAMES, and they reach the actions as the
|
|
410
|
+
// raw strings the shell gave us.
|
|
411
|
+
//
|
|
412
|
+
// They used to be mapped through `Jsonic(arg)` first, which parses each one
|
|
413
|
+
// as relaxed JSON — so a Windows absolute ref arrived as an OBJECT:
|
|
414
|
+
// `Jsonic('C:\\pkg\\go')` is `{ C: '\\pkg\\go' }`, and every downstream path
|
|
415
|
+
// join then missed. (`ts,py` also became `['ts','py']`, which is why
|
|
416
|
+
// parseAddNames still carries a non-string branch; it splits on commas
|
|
417
|
+
// itself, so nothing is lost by handing it strings.)
|
|
418
|
+
//
|
|
419
|
+
// Nothing here wants structured arguments: every action takes names and
|
|
420
|
+
// refs. Parsing them was pure loss.
|
|
421
|
+
//
|
|
422
|
+
// `flags` is the second parameter because `--only` and `--alias` are
|
|
423
|
+
// arguments to ONE command, not generator configuration: passing them
|
|
424
|
+
// through `SdkGen({…})` like `debug`/`dryrun` would make a later
|
|
425
|
+
// `action()` call on the same instance silently inherit them.
|
|
426
|
+
async function action(
|
|
427
|
+
args: string[], flags?: Record<string, any>,
|
|
428
|
+
): Promise<any> {
|
|
306
429
|
const actname = args[0]
|
|
307
430
|
const actionFunc = ACTION_MAP[actname]
|
|
308
431
|
|
|
309
432
|
if (null == actionFunc) {
|
|
310
|
-
throw new SdkGenError(
|
|
433
|
+
throw new SdkGenError(
|
|
434
|
+
'Unknown action: ' + actname +
|
|
435
|
+
' (expected: ' + actionNames().join(', ') + ')')
|
|
311
436
|
}
|
|
312
437
|
|
|
313
|
-
const ctx = resolveActionContext()
|
|
438
|
+
const ctx = resolveActionContext(flags, needsModel(args))
|
|
314
439
|
|
|
315
|
-
return await actionFunc(
|
|
440
|
+
return await actionFunc(args, ctx)
|
|
316
441
|
}
|
|
317
442
|
|
|
318
443
|
|
|
319
|
-
function resolveActionContext(
|
|
444
|
+
function resolveActionContext(
|
|
445
|
+
flags?: Record<string, any>, wantmodel?: boolean,
|
|
446
|
+
): ActionContext {
|
|
320
447
|
|
|
321
448
|
// TODO: use AsyncLocalStorage to avoid reloading model
|
|
322
|
-
const { model, url } = resolveModel()
|
|
449
|
+
const { model, url } = resolveModel(false !== wantmodel)
|
|
323
450
|
|
|
324
451
|
const ctx: ActionContext = {
|
|
325
452
|
fs: () => fs,
|
|
@@ -329,16 +456,25 @@ function SdkGen(opts: SdkGenOptions) {
|
|
|
329
456
|
url,
|
|
330
457
|
jostraca,
|
|
331
458
|
opts,
|
|
459
|
+
flags: flags ?? {},
|
|
332
460
|
}
|
|
333
461
|
|
|
334
462
|
return ctx
|
|
335
463
|
}
|
|
336
464
|
|
|
337
465
|
|
|
338
|
-
function resolveModel() {
|
|
466
|
+
function resolveModel(wanted: boolean) {
|
|
339
467
|
const path = './model/sdk.aontu'
|
|
340
468
|
const errs: any[] = []
|
|
341
469
|
|
|
470
|
+
// A verb that does not act on a project (see `needsModel`) is run where
|
|
471
|
+
// there is no project model, so its absence is not an error there. Its
|
|
472
|
+
// PRESENCE still is compiled — an author checking a package from inside a
|
|
473
|
+
// project should get the same model every other verb gets.
|
|
474
|
+
if (!wanted && !fs.existsSync(path)) {
|
|
475
|
+
return { model: { main: {} } as any, url: path }
|
|
476
|
+
}
|
|
477
|
+
|
|
342
478
|
if (null == aontu) {
|
|
343
479
|
aontu = new Aontu()
|
|
344
480
|
}
|
|
@@ -388,6 +524,47 @@ function SdkGen(opts: SdkGenOptions) {
|
|
|
388
524
|
}
|
|
389
525
|
}
|
|
390
526
|
|
|
527
|
+
// The third kind. sdkgen ships no docs items, so every ref here is a path
|
|
528
|
+
// into a package — see action/docs.
|
|
529
|
+
const docs = {
|
|
530
|
+
add: async (items: string[]): Promise<ActionResult> => {
|
|
531
|
+
const ctx = resolveActionContext()
|
|
532
|
+
return docs_add(items, ctx)
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
// The whole-package verbs. `flags` mirrors the CLI's `--only` / `--alias`,
|
|
537
|
+
// for the same reason they are `action`'s second parameter rather than
|
|
538
|
+
// constructor options: they are arguments to one call.
|
|
539
|
+
const packages = {
|
|
540
|
+
add: async (
|
|
541
|
+
refs: string[], flags?: Record<string, any>,
|
|
542
|
+
): Promise<ActionResult> => {
|
|
543
|
+
const ctx = resolveActionContext(flags)
|
|
544
|
+
return package_add(refs, ctx)
|
|
545
|
+
},
|
|
546
|
+
|
|
547
|
+
list: async (): Promise<ActionResult> => {
|
|
548
|
+
const ctx = resolveActionContext()
|
|
549
|
+
return action_package(['package', 'list'], ctx)
|
|
550
|
+
},
|
|
551
|
+
|
|
552
|
+
update: async (
|
|
553
|
+
names: string[], flags?: Record<string, any>,
|
|
554
|
+
): Promise<ActionResult> => {
|
|
555
|
+
const ctx = resolveActionContext(flags)
|
|
556
|
+
return package_update(names, ctx)
|
|
557
|
+
},
|
|
558
|
+
|
|
559
|
+
// Validate a package being AUTHORED — see action/check. The only verb
|
|
560
|
+
// here that does not need a project model, because it does not act on a
|
|
561
|
+
// project; `false` says so to `resolveActionContext`.
|
|
562
|
+
check: async (refs?: string[]): Promise<ActionResult> => {
|
|
563
|
+
const ctx = resolveActionContext(undefined, false)
|
|
564
|
+
return cmd_package_check(['package', 'check', ...(refs ?? [])], ctx)
|
|
565
|
+
},
|
|
566
|
+
}
|
|
567
|
+
|
|
391
568
|
// Has this project's `.sdk/` drifted from the scaffold? See action/doctor.
|
|
392
569
|
const check = async (): Promise<ActionResult> => {
|
|
393
570
|
const ctx = resolveActionContext()
|
|
@@ -401,8 +578,13 @@ function SdkGen(opts: SdkGenOptions) {
|
|
|
401
578
|
generate,
|
|
402
579
|
action,
|
|
403
580
|
check,
|
|
581
|
+
docs,
|
|
404
582
|
target,
|
|
405
583
|
feature,
|
|
584
|
+
|
|
585
|
+
// `package` is a reserved word in a strict-mode object shorthand, so the
|
|
586
|
+
// local binding is `packages` and the PUBLIC name matches the CLI verb.
|
|
587
|
+
package: packages,
|
|
406
588
|
}
|
|
407
589
|
|
|
408
590
|
}
|
|
@@ -437,6 +619,9 @@ SdkGen.makeBuild = async function(opts: SdkGenOptions) {
|
|
|
437
619
|
|
|
438
620
|
|
|
439
621
|
type ExternalSpec = {
|
|
622
|
+
// Which kind's collection this item came from — `target` or `docs`. The
|
|
623
|
+
// out-of-tree rules are the same for both; only the dispatch differs.
|
|
624
|
+
kind: string
|
|
440
625
|
name: string
|
|
441
626
|
target: any
|
|
442
627
|
folder: string
|
|
@@ -453,22 +638,36 @@ type ExternalSpec = {
|
|
|
453
638
|
// directory the command happened to be run from.
|
|
454
639
|
//
|
|
455
640
|
// An INACTIVE target is still listed: it must be taken out of the in-tree
|
|
456
|
-
// model (see
|
|
641
|
+
// model (see withoutExternal) so that switching it off does not silently
|
|
457
642
|
// relocate it into `<sdk-repo>/<target>/`. The generate loop skips it.
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
643
|
+
// Every item, of every kind, that generates OUTSIDE the SDK repo.
|
|
644
|
+
//
|
|
645
|
+
// Keyed by kind because `docs` needs exactly this and a second copy of it
|
|
646
|
+
// would drift: the out-of-tree rules — a destination must be outside the
|
|
647
|
+
// project, unclaimed, and either empty or previously generated into — are
|
|
648
|
+
// properties of WRITING SOMEWHERE ELSE, not of being a target.
|
|
649
|
+
//
|
|
650
|
+
// The claim map spanning kinds is the load-bearing part: a docs item and a
|
|
651
|
+
// target pointed at the same folder would otherwise silently overwrite each
|
|
652
|
+
// other, in whatever order the passes happen to run.
|
|
653
|
+
function externalItems(
|
|
654
|
+
model: any, folder: string, kinds: string[],
|
|
655
|
+
): ExternalSpec[] {
|
|
656
|
+
return kinds.flatMap((kind: string) => {
|
|
657
|
+
const items = model?.main?.[KIT]?.[kind] || {}
|
|
658
|
+
|
|
659
|
+
return Object.keys(items).sort()
|
|
660
|
+
.map((name: string) => ({ kind, name, target: items[name] }))
|
|
661
|
+
.filter((t: any) => {
|
|
662
|
+
const path = t.target?.output?.path
|
|
663
|
+
return null != path && '' !== path
|
|
664
|
+
})
|
|
665
|
+
.map((t: any) => ({
|
|
666
|
+
...t,
|
|
667
|
+
folder: Path.resolve(folder, String(t.target.output.path)),
|
|
668
|
+
active: false !== t.target.active,
|
|
669
|
+
}))
|
|
670
|
+
})
|
|
472
671
|
}
|
|
473
672
|
|
|
474
673
|
|
|
@@ -480,9 +679,12 @@ function externalTargets(model: any, folder: string): ExternalSpec[] {
|
|
|
480
679
|
const EXTERNAL_MARKER = '.jostraca'
|
|
481
680
|
|
|
482
681
|
// Entries that do not count as content when deciding whether a destination
|
|
483
|
-
// is empty. A `git init` (or a clone of an empty repo) leaves only `.git`,
|
|
484
|
-
//
|
|
485
|
-
|
|
682
|
+
// is empty. A `git init` (or a clone of an empty repo) leaves only `.git`, and
|
|
683
|
+
// that is exactly the destination a FIRST generation is aimed at — as is one
|
|
684
|
+
// the maintainer opened in the Finder on the way to declaring it.
|
|
685
|
+
//
|
|
686
|
+
// `isNoise`, not `isJunk`: a destination holding build output is not empty,
|
|
687
|
+
// whether or not sdkgen would ever copy such a thing. See helpers/junk.
|
|
486
688
|
|
|
487
689
|
|
|
488
690
|
// Refuse a destination the project cannot have meant.
|
|
@@ -517,39 +719,44 @@ function checkExternalFolders(external: ExternalSpec[], root: string, fs: any) {
|
|
|
517
719
|
// path valid.
|
|
518
720
|
if (!ext.active) continue
|
|
519
721
|
|
|
520
|
-
const
|
|
722
|
+
const label = ext.kind.charAt(0).toUpperCase() + ext.kind.slice(1)
|
|
723
|
+
|
|
724
|
+
const where = label + ' "' + ext.name + '" has output path "' +
|
|
521
725
|
ext.target.output.path + '", which resolves to: ' + ext.folder +
|
|
522
726
|
'\n (SDK project: ' + root + ')'
|
|
523
727
|
|
|
524
728
|
if (ext.folder === root || folderContains(root, ext.folder)) {
|
|
525
729
|
throw new SdkGenError(
|
|
526
|
-
'External
|
|
527
|
-
'\n
|
|
730
|
+
'External output path is inside the SDK project.\n ' + where +
|
|
731
|
+
'\n An item generating into the SDK project must leave `output: ' +
|
|
528
732
|
'path` unset — it is then generated in-tree, as <sdk-project>/' +
|
|
529
733
|
ext.name + '/.')
|
|
530
734
|
}
|
|
531
735
|
|
|
532
736
|
if (folderContains(ext.folder, root)) {
|
|
533
737
|
throw new SdkGenError(
|
|
534
|
-
'External
|
|
738
|
+
'External output path contains the SDK project.\n ' + where +
|
|
535
739
|
'\n Generation would write this package over the directory holding ' +
|
|
536
740
|
'the SDK project itself.')
|
|
537
741
|
}
|
|
538
742
|
|
|
743
|
+
// ACROSS KINDS, not within one: `docs` and `target` are separate
|
|
744
|
+
// namespaces, so an item of each may legitimately be called `api` — and
|
|
745
|
+
// pointing both at one folder is the mistake this catches.
|
|
539
746
|
if (null != claimed[ext.folder]) {
|
|
540
747
|
throw new SdkGenError(
|
|
541
|
-
'External
|
|
542
|
-
claimed[ext.folder] + '
|
|
543
|
-
'\n Two
|
|
544
|
-
'other, in
|
|
748
|
+
'External output path is already claimed by ' +
|
|
749
|
+
claimed[ext.folder] + '.\n ' + where +
|
|
750
|
+
'\n Two items generating into the same folder overwrite each ' +
|
|
751
|
+
'other, in whatever order the passes run.')
|
|
545
752
|
}
|
|
546
|
-
claimed[ext.folder] = ext.name
|
|
753
|
+
claimed[ext.folder] = ext.kind + ' "' + ext.name + '"'
|
|
547
754
|
|
|
548
755
|
if (!fs.existsSync(ext.folder)) continue
|
|
549
756
|
|
|
550
757
|
if (!fs.statSync(ext.folder).isDirectory()) {
|
|
551
758
|
throw new SdkGenError(
|
|
552
|
-
'External
|
|
759
|
+
'External output path is not a folder.\n ' + where)
|
|
553
760
|
}
|
|
554
761
|
|
|
555
762
|
if (true === ext.target.output.adopt) continue
|
|
@@ -559,7 +766,7 @@ function checkExternalFolders(external: ExternalSpec[], root: string, fs: any) {
|
|
|
559
766
|
|
|
560
767
|
if (entries.includes(EXTERNAL_MARKER)) continue
|
|
561
768
|
|
|
562
|
-
const content = entries.filter((entry) => !
|
|
769
|
+
const content = entries.filter((entry) => !isNoise(entry))
|
|
563
770
|
|
|
564
771
|
if (0 < content.length) {
|
|
565
772
|
throw new SdkGenError(
|
|
@@ -635,23 +842,32 @@ function externalSdkRel(ext: ExternalSpec, root: string, log: any): string {
|
|
|
635
842
|
// A shallow clone down to `target` only — the model is large, entities and
|
|
636
843
|
// features are shared with the external pass, and a deep copy would both
|
|
637
844
|
// cost and quietly break identity comparisons.
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
845
|
+
// The model the IN-TREE pass sees: every out-of-tree item removed, whatever
|
|
846
|
+
// its kind. Rendering one in both passes would ALSO write it into
|
|
847
|
+
// `<sdk-repo>/<name>/`, which is the folder the item asked not to use.
|
|
848
|
+
function withoutExternal(
|
|
849
|
+
model: any, external: { kind: string, name: string }[],
|
|
850
|
+
): any {
|
|
851
|
+
const drop = new Set(external.map((e) => e.kind + ':' + e.name))
|
|
852
|
+
|
|
853
|
+
const kit: any = { ...model.main[KIT] }
|
|
854
|
+
|
|
855
|
+
for (const kind of new Set(external.map((e) => e.kind))) {
|
|
856
|
+
const items = model?.main?.[KIT]?.[kind] || {}
|
|
857
|
+
const kept: any = {}
|
|
858
|
+
|
|
859
|
+
for (const name of Object.keys(items)) {
|
|
860
|
+
if (!drop.has(kind + ':' + name)) {
|
|
861
|
+
kept[name] = items[name]
|
|
862
|
+
}
|
|
646
863
|
}
|
|
864
|
+
|
|
865
|
+
kit[kind] = kept
|
|
647
866
|
}
|
|
648
867
|
|
|
649
868
|
return {
|
|
650
869
|
...model,
|
|
651
|
-
main: {
|
|
652
|
-
...model.main,
|
|
653
|
-
[KIT]: { ...model.main[KIT], target: kept },
|
|
654
|
-
},
|
|
870
|
+
main: { ...model.main, [KIT]: kit },
|
|
655
871
|
}
|
|
656
872
|
}
|
|
657
873
|
|
|
@@ -698,6 +914,8 @@ export type {
|
|
|
698
914
|
FeatureSource,
|
|
699
915
|
DoctorReport,
|
|
700
916
|
RegisterOptions,
|
|
917
|
+
Manifest,
|
|
918
|
+
ManifestRead,
|
|
701
919
|
}
|
|
702
920
|
|
|
703
921
|
export type {
|
|
@@ -838,6 +1056,16 @@ export {
|
|
|
838
1056
|
featureExcludes,
|
|
839
1057
|
fullsetExcludes,
|
|
840
1058
|
srcFeatureExcludes,
|
|
1059
|
+
|
|
1060
|
+
definitionPath,
|
|
1061
|
+
definitionFolder,
|
|
1062
|
+
definitionNames,
|
|
1063
|
+
|
|
1064
|
+
MANIFEST,
|
|
1065
|
+
manifestPath,
|
|
1066
|
+
readManifest,
|
|
1067
|
+
validateManifest,
|
|
1068
|
+
|
|
841
1069
|
jsProp,
|
|
842
1070
|
jsOptProp,
|
|
843
1071
|
jsKey,
|
package/src/types.ts
CHANGED
|
@@ -64,7 +64,7 @@ type ModelTarget = NameCases & {
|
|
|
64
64
|
// the SDK repo — see cmp/ExternalTarget and
|
|
65
65
|
// docs/explanation/out-of-tree-targets.
|
|
66
66
|
//
|
|
67
|
-
// Typed rather than left to the index signature because `
|
|
67
|
+
// Typed rather than left to the index signature because `externalItems()`
|
|
68
68
|
// decides from these keys whether to write OUTSIDE the repo, and a
|
|
69
69
|
// destination path read off a bare `any` is one a rename can silently
|
|
70
70
|
// change to undefined.
|
|
@@ -121,12 +121,41 @@ type ActionContext = {
|
|
|
121
121
|
model: SdkModel,
|
|
122
122
|
url: string,
|
|
123
123
|
opts: any,
|
|
124
|
-
jostraca: any
|
|
124
|
+
jostraca: any,
|
|
125
|
+
|
|
126
|
+
// PER-INVOCATION action arguments — `--only`, `--alias` — as opposed to
|
|
127
|
+
// generator configuration. `debug` and `dryrun` reach actions through the
|
|
128
|
+
// `SdkGen({…})` constructor because they describe the generator; these
|
|
129
|
+
// describe one command, so smuggling them through the constructor would
|
|
130
|
+
// make a second `action()` call on the same instance inherit them.
|
|
131
|
+
flags?: Record<string, any>
|
|
132
|
+
|
|
133
|
+
// How `package update` fetches a new version. Injectable so tests do not
|
|
134
|
+
// shell out, and so a caller with its own dependency management (a
|
|
135
|
+
// monorepo, a vendored checkout) can supply one. Defaults to npm.
|
|
136
|
+
fetchPackage?: (pkgname: string, actx: ActionContext) => Promise<void>
|
|
125
137
|
}
|
|
126
138
|
|
|
127
139
|
|
|
140
|
+
// An action either WROTE something or REPORTED something, and the two kinds
|
|
141
|
+
// of verb return different things: `target add` returns jostraca's result,
|
|
142
|
+
// while `doctor` and `package check` return a report the CLI turns into an
|
|
143
|
+
// exit code. Both optional, because neither verb has anything to say about
|
|
144
|
+
// the other's field — a check that invented an empty `jres` would be lying
|
|
145
|
+
// about having generated nothing.
|
|
128
146
|
type ActionResult = {
|
|
129
|
-
jres
|
|
147
|
+
jres?: JostracaResult
|
|
148
|
+
report?: ActionReport
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
// What a CHECKING verb returns. `ok` is the contract — `bin/voxgig-sdkgen`
|
|
153
|
+
// exits non-zero on `false` — and `summary` is the one line it prints, so the
|
|
154
|
+
// binary never has to know what any particular verb's findings look like.
|
|
155
|
+
type ActionReport = {
|
|
156
|
+
ok: boolean
|
|
157
|
+
summary?: string
|
|
158
|
+
[key: string]: any
|
|
130
159
|
}
|
|
131
160
|
|
|
132
161
|
|
|
@@ -138,6 +167,7 @@ export {
|
|
|
138
167
|
export type {
|
|
139
168
|
ActionContext,
|
|
140
169
|
ActionResult,
|
|
170
|
+
ActionReport,
|
|
141
171
|
SdkModel,
|
|
142
172
|
ModelKit,
|
|
143
173
|
ModelTarget,
|
package/src/utility.ts
CHANGED
|
@@ -133,6 +133,23 @@ export {
|
|
|
133
133
|
//
|
|
134
134
|
// The reader side is unchanged either way: make_config returns the same map,
|
|
135
135
|
// so nothing downstream can tell which representation it got.
|
|
136
|
+
//
|
|
137
|
+
// For two targets the literal is not merely expensive but IMPOSSIBLE past a
|
|
138
|
+
// point, which is what fixes the threshold rather than leaving it a taste
|
|
139
|
+
// question:
|
|
140
|
+
//
|
|
141
|
+
// haskell GHC 9.4.7 refuses a large static structure outright -
|
|
142
|
+
// "sorry! (unimplemented feature or known bug) ... Trying to
|
|
143
|
+
// allocate more than 129024 bytes ... Suggestion: read data from a
|
|
144
|
+
// file instead of having large static data structures in code"
|
|
145
|
+
// (GHC issue 4505). Measured: the CV literal compiles at 828 KB of
|
|
146
|
+
// model and fails at 1.4 MB, so 256 KB clears it by more than 3x.
|
|
147
|
+
//
|
|
148
|
+
// clojure a string literal is a constant-pool UTF-8 entry capped at 65,535
|
|
149
|
+
// bytes, so the DATA constant has to be chunked - see cljStringChunks.
|
|
150
|
+
//
|
|
151
|
+
// Anything above the threshold therefore takes the data path in every target,
|
|
152
|
+
// and the languages with a hard ceiling are the ones with the most margin.
|
|
136
153
|
const CONFIG_DATA_THRESHOLD = 256 * 1024
|
|
137
154
|
|
|
138
155
|
|