@voxgig/sdkgen 4.33.0 → 4.34.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 +1 -1
- package/dist/action/copies.d.ts +21 -0
- package/dist/action/copies.js +146 -0
- package/dist/action/copies.js.map +1 -0
- package/dist/action/doctor.d.ts +15 -2
- package/dist/action/doctor.js +169 -23
- package/dist/action/doctor.js.map +1 -1
- package/dist/action/edition.js +6 -2
- package/dist/action/edition.js.map +1 -1
- package/dist/action/feature.js +6 -2
- package/dist/action/feature.js.map +1 -1
- package/dist/action/package.js +28 -10
- package/dist/action/package.js.map +1 -1
- package/dist/action/remove.js +2 -0
- package/dist/action/remove.js.map +1 -1
- package/dist/action/resolve.d.ts +1 -0
- package/dist/action/resolve.js +10 -2
- package/dist/action/resolve.js.map +1 -1
- package/dist/action/target.js +6 -2
- package/dist/action/target.js.map +1 -1
- package/dist/sdkgen.d.ts +2 -1
- package/dist/sdkgen.js +36 -3
- package/dist/sdkgen.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/project/sdkgen-package.json +1 -1
- package/src/action/copies.ts +219 -0
- package/src/action/doctor.ts +247 -21
- package/src/action/edition.ts +10 -2
- package/src/action/feature.ts +11 -2
- package/src/action/package.ts +31 -10
- package/src/action/remove.ts +4 -0
- package/src/action/resolve.ts +16 -3
- package/src/action/target.ts +10 -2
- package/src/sdkgen.ts +45 -5
package/src/action/edition.ts
CHANGED
|
@@ -17,6 +17,9 @@ import { resolveKind, kindModel, kindIndex, kindTrees } from './kind'
|
|
|
17
17
|
import type { TreeDef } from './kind'
|
|
18
18
|
|
|
19
19
|
import { registerInstalled } from './resolve'
|
|
20
|
+
import type { Source } from './resolve'
|
|
21
|
+
|
|
22
|
+
import { recordCopies } from './copies'
|
|
20
23
|
|
|
21
24
|
import { aliasCmpTree, pruneStaleTemplates } from './target'
|
|
22
25
|
|
|
@@ -107,8 +110,12 @@ async function edition_add(
|
|
|
107
110
|
// Later items in the command read this in-memory registration.
|
|
108
111
|
registerInstalled('edition', edition, actx)
|
|
109
112
|
|
|
113
|
+
const installed: Source[] = []
|
|
114
|
+
|
|
110
115
|
const jres = await jostraca.generate(opts, () =>
|
|
111
|
-
EditionRoot({ edition, actx }))
|
|
116
|
+
EditionRoot({ edition, actx, installed }))
|
|
117
|
+
|
|
118
|
+
recordCopies(actx, jres, 'edition', installed)
|
|
112
119
|
|
|
113
120
|
return { jres }
|
|
114
121
|
}
|
|
@@ -139,7 +146,7 @@ function preflight(edition: string[], actx: ActionContext) {
|
|
|
139
146
|
|
|
140
147
|
|
|
141
148
|
const EditionRoot = cmp(function EditionRoot(props: any) {
|
|
142
|
-
const { ctx$, edition } = props
|
|
149
|
+
const { ctx$, edition, installed } = props
|
|
143
150
|
const { log } = ctx$
|
|
144
151
|
|
|
145
152
|
Project({}, () => {
|
|
@@ -153,6 +160,7 @@ const EditionRoot = cmp(function EditionRoot(props: any) {
|
|
|
153
160
|
const source = resolveKind(dref, 'edition', ctx$)
|
|
154
161
|
|
|
155
162
|
dnames.push(source.name)
|
|
163
|
+
installed?.push(source)
|
|
156
164
|
|
|
157
165
|
log.info({
|
|
158
166
|
point: 'edition-name', edition: source.name, folder: source.folder, ref: dref,
|
package/src/action/feature.ts
CHANGED
|
@@ -32,6 +32,9 @@ import { templateReplacements } from '../helpers/stdrep'
|
|
|
32
32
|
import { copyOpts } from '../helpers/junk'
|
|
33
33
|
|
|
34
34
|
import { resolveKind, kindModel, kindIndex } from './kind'
|
|
35
|
+
import type { Source } from './resolve'
|
|
36
|
+
|
|
37
|
+
import { recordCopies } from './copies'
|
|
35
38
|
|
|
36
39
|
|
|
37
40
|
import {
|
|
@@ -111,10 +114,15 @@ async function feature_add(features: string[], actx: ActionContext): Promise<Act
|
|
|
111
114
|
note: (actx.opts.dryrun ? '** DRY RUN **' : '')
|
|
112
115
|
})
|
|
113
116
|
|
|
114
|
-
const
|
|
117
|
+
const installed: Source[] = []
|
|
118
|
+
|
|
119
|
+
const jres = await jostraca.generate(opts, () =>
|
|
120
|
+
FeatureRoot({ features, installed }))
|
|
115
121
|
|
|
116
122
|
showChanges(opts.log, 'feature-result', jres)
|
|
117
123
|
|
|
124
|
+
recordCopies(actx, jres, 'feature', installed)
|
|
125
|
+
|
|
118
126
|
if (actx.opts.dryrun) {
|
|
119
127
|
showDryrun(opts.log, 'feature-result', jres, actx.folder)
|
|
120
128
|
}
|
|
@@ -131,7 +139,7 @@ async function feature_add(features: string[], actx: ActionContext): Promise<Act
|
|
|
131
139
|
|
|
132
140
|
|
|
133
141
|
const FeatureRoot = cmp(function FeatureRoot(props: any) {
|
|
134
|
-
const { ctx$, features } = props
|
|
142
|
+
const { ctx$, features, installed } = props
|
|
135
143
|
const { model, log } = ctx$
|
|
136
144
|
|
|
137
145
|
const fs = ctx$.fs()
|
|
@@ -167,6 +175,7 @@ const FeatureRoot = cmp(function FeatureRoot(props: any) {
|
|
|
167
175
|
|
|
168
176
|
const fname = source.name
|
|
169
177
|
fnames.push(fname)
|
|
178
|
+
installed?.push(source)
|
|
170
179
|
|
|
171
180
|
log.info({
|
|
172
181
|
point: 'feature-build',
|
package/src/action/package.ts
CHANGED
|
@@ -29,6 +29,8 @@ import { cmd_package_check } from './check'
|
|
|
29
29
|
|
|
30
30
|
import { doctor } from './doctor'
|
|
31
31
|
|
|
32
|
+
import { COPIES } from './copies'
|
|
33
|
+
|
|
32
34
|
import { resolveSource, registerInstalled, nameConflict } from './resolve'
|
|
33
35
|
import type { Source } from './resolve'
|
|
34
36
|
|
|
@@ -639,6 +641,16 @@ async function preCheck(
|
|
|
639
641
|
|
|
640
642
|
const report = res.report
|
|
641
643
|
|
|
644
|
+
// Unchanged since an add wrote them, so refreshing them loses nothing.
|
|
645
|
+
if (0 < report.outdated.length) {
|
|
646
|
+
actx.log.info({
|
|
647
|
+
point: 'package-update-outdated', package: pkgname,
|
|
648
|
+
files: report.outdated.length,
|
|
649
|
+
note: pkgname + ': ' + report.outdated.length + ' outdated file(s) ' +
|
|
650
|
+
'will be refreshed; ' + COPIES + ' shows nothing in them was changed'
|
|
651
|
+
})
|
|
652
|
+
}
|
|
653
|
+
|
|
642
654
|
const changed = [...report.forked, ...report.edited]
|
|
643
655
|
|
|
644
656
|
if (0 === changed.length) {
|
|
@@ -654,19 +666,28 @@ async function preCheck(
|
|
|
654
666
|
return
|
|
655
667
|
}
|
|
656
668
|
|
|
669
|
+
const unrecorded = new Set<string>(report.unrecorded)
|
|
670
|
+
const edited = changed.filter((file: string) => !unrecorded.has(file))
|
|
671
|
+
const unknown = changed.filter((file: string) => unrecorded.has(file))
|
|
672
|
+
|
|
657
673
|
throw new SdkGenError(
|
|
658
674
|
pkgname + ': ' + changed.length + ' file(s) differ from the installed ' +
|
|
659
675
|
'source, so updating would overwrite them:\n ' + changed.join('\n ') +
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
676
|
+
(0 === edited.length ? '' :
|
|
677
|
+
'\n\n ' + edited.length + ' of them changed in this project after ' +
|
|
678
|
+
'an add wrote them (' + COPIES + ' records what it wrote), so updating ' +
|
|
679
|
+
'would discard those edits.') +
|
|
680
|
+
(0 === unknown.length ? '' :
|
|
681
|
+
'\n\n ' + unknown.length + ' of them predate ' + COPIES + ', so ' +
|
|
682
|
+
'nothing tells these two apart:' +
|
|
683
|
+
'\n - they are LOCAL EDITS, and `--force` will discard them;' +
|
|
684
|
+
'\n - or ' + pkgname + ' was already updated out of band (an ' +
|
|
685
|
+
'`npm update` in another shell), in which case they are merely STALE ' +
|
|
686
|
+
'and nothing is at risk.' +
|
|
687
|
+
'\n If you updated it and changed nothing, --force is safe. To check ' +
|
|
688
|
+
'first, reinstall the version you had and re-run this command.') +
|
|
689
|
+
'\n\n Copy anything you want to keep into .sdk/model/, then re-run ' +
|
|
690
|
+
'with --force.')
|
|
670
691
|
}
|
|
671
692
|
|
|
672
693
|
|
package/src/action/remove.ts
CHANGED
|
@@ -29,6 +29,8 @@ import { removeIndexEntries } from './action'
|
|
|
29
29
|
|
|
30
30
|
import { doctor } from './doctor'
|
|
31
31
|
|
|
32
|
+
import { forgetCopies } from './copies'
|
|
33
|
+
|
|
32
34
|
|
|
33
35
|
// Everything one `remove` would touch, decided before anything is written.
|
|
34
36
|
type RemovePlan = {
|
|
@@ -121,6 +123,8 @@ async function kind_remove(
|
|
|
121
123
|
}
|
|
122
124
|
|
|
123
125
|
removed.push(...applyRemove(plan, actx, dryrun))
|
|
126
|
+
|
|
127
|
+
forgetCopies(actx, kind, plan.name)
|
|
124
128
|
}
|
|
125
129
|
|
|
126
130
|
log.info({
|
package/src/action/resolve.ts
CHANGED
|
@@ -30,6 +30,9 @@ type Source = {
|
|
|
30
30
|
// The sdkgen package that provided it, when the source has a manifest.
|
|
31
31
|
// Undefined for a bare `.sdk`-shaped folder, which stays legal.
|
|
32
32
|
package?: string
|
|
33
|
+
|
|
34
|
+
// That package's version, read from the same manifest.
|
|
35
|
+
version?: string
|
|
33
36
|
}
|
|
34
37
|
|
|
35
38
|
|
|
@@ -113,6 +116,8 @@ function resolveSource(ref: string, kind: string, ctx$: any): Source {
|
|
|
113
116
|
const nroot = Path.normalize(root)
|
|
114
117
|
const rootslash = nroot.endsWith(Path.sep) ? nroot : nroot + Path.sep
|
|
115
118
|
|
|
119
|
+
const owner = sourcePackage(fs, folder, kind, origname, ctx$)
|
|
120
|
+
|
|
116
121
|
return {
|
|
117
122
|
name,
|
|
118
123
|
origname,
|
|
@@ -125,14 +130,17 @@ function resolveSource(ref: string, kind: string, ctx$: any): Source {
|
|
|
125
130
|
// separator path that some readers handle and others do not.
|
|
126
131
|
model: definitionPathAny(fs, folder, kind, origname),
|
|
127
132
|
|
|
128
|
-
|
|
133
|
+
...(null == owner ? {} : {
|
|
134
|
+
package: owner.name,
|
|
135
|
+
...(null == owner.version ? {} : { version: owner.version }),
|
|
136
|
+
}),
|
|
129
137
|
}
|
|
130
138
|
}
|
|
131
139
|
|
|
132
140
|
|
|
133
141
|
function sourcePackage(
|
|
134
142
|
fs: any, folder: string, kind: string, origname: string, ctx$: any,
|
|
135
|
-
): string | undefined {
|
|
143
|
+
): { name: string, version?: string } | undefined {
|
|
136
144
|
const read = readManifest(fs, folder)
|
|
137
145
|
|
|
138
146
|
if (null != read.err) {
|
|
@@ -164,7 +172,12 @@ function sourcePackage(
|
|
|
164
172
|
return undefined
|
|
165
173
|
}
|
|
166
174
|
|
|
167
|
-
|
|
175
|
+
const version = read.manifest.version
|
|
176
|
+
|
|
177
|
+
return {
|
|
178
|
+
name: read.manifest.name,
|
|
179
|
+
...('string' === typeof version && '' !== version ? { version } : {}),
|
|
180
|
+
}
|
|
168
181
|
}
|
|
169
182
|
|
|
170
183
|
|
package/src/action/target.ts
CHANGED
|
@@ -56,6 +56,9 @@ import {
|
|
|
56
56
|
import { kindModel, kindIndex, resolveKind, escapeRe } from './kind'
|
|
57
57
|
|
|
58
58
|
import { BUNDLED, resolveSource, registerInstalled } from './resolve'
|
|
59
|
+
import type { Source } from './resolve'
|
|
60
|
+
|
|
61
|
+
import { recordCopies } from './copies'
|
|
59
62
|
|
|
60
63
|
|
|
61
64
|
const CMD_MAP: any = {
|
|
@@ -125,11 +128,15 @@ async function target_add(targets: string[], actx: ActionContext): Promise<Actio
|
|
|
125
128
|
...Object.keys(featuremodel).filter((n: string) => false !== featuremodel[n]?.active),
|
|
126
129
|
]))
|
|
127
130
|
|
|
131
|
+
const installed: Source[] = []
|
|
132
|
+
|
|
128
133
|
const jres = await jostraca.generate(opts, () =>
|
|
129
|
-
TargetRoot({ targets, features, actx }))
|
|
134
|
+
TargetRoot({ targets, features, actx, installed }))
|
|
130
135
|
|
|
131
136
|
showChanges(opts.log, 'target-result', jres)
|
|
132
137
|
|
|
138
|
+
recordCopies(actx, jres, 'target', installed)
|
|
139
|
+
|
|
133
140
|
if (actx.opts.dryrun) {
|
|
134
141
|
showDryrun(opts.log, 'target-result', jres, actx.folder)
|
|
135
142
|
}
|
|
@@ -152,7 +159,7 @@ async function target_add(targets: string[], actx: ActionContext): Promise<Actio
|
|
|
152
159
|
|
|
153
160
|
|
|
154
161
|
const TargetRoot = cmp(function TargetRoot(props: any) {
|
|
155
|
-
const { ctx$, targets, features, actx } = props
|
|
162
|
+
const { ctx$, targets, features, actx, installed } = props
|
|
156
163
|
const { model, log } = ctx$
|
|
157
164
|
|
|
158
165
|
const fs = ctx$.fs()
|
|
@@ -185,6 +192,7 @@ const TargetRoot = cmp(function TargetRoot(props: any) {
|
|
|
185
192
|
const source = resolveKind(tref, 'target', ctx$)
|
|
186
193
|
const { name: tname, folder: tfolder, origname: torigname, base } = source
|
|
187
194
|
tnames.push(tname)
|
|
195
|
+
installed?.push(source)
|
|
188
196
|
const targetNote = tname + (tname != tref ? ' ref:' + tref : '')
|
|
189
197
|
|
|
190
198
|
log.info({
|
package/src/sdkgen.ts
CHANGED
|
@@ -146,6 +146,7 @@ import {
|
|
|
146
146
|
import {
|
|
147
147
|
action_doctor,
|
|
148
148
|
doctor,
|
|
149
|
+
copyCheck,
|
|
149
150
|
} from './action/doctor'
|
|
150
151
|
import type { DoctorReport } from './action/doctor'
|
|
151
152
|
|
|
@@ -202,6 +203,16 @@ type ExternalOverride = {
|
|
|
202
203
|
const { Jostraca } = JostracaModule
|
|
203
204
|
|
|
204
205
|
|
|
206
|
+
// The `const` block every action's model carries, and so what an add
|
|
207
|
+
// substitutes into the copies it writes.
|
|
208
|
+
function projectConst(model: any): any {
|
|
209
|
+
const projectconst: any = { name: model.name }
|
|
210
|
+
names(projectconst, model.name)
|
|
211
|
+
projectconst.year = new Date().getFullYear()
|
|
212
|
+
return projectconst
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
|
|
205
216
|
function modelError(path: string, cause: any, rooterrs: any[]): any {
|
|
206
217
|
const detail = String(cause?.msg ?? cause?.message ?? cause ?? '').trim()
|
|
207
218
|
|
|
@@ -299,6 +310,10 @@ function SdkGen(opts: SdkGenOptions) {
|
|
|
299
310
|
|
|
300
311
|
const root = Path.resolve(folder)
|
|
301
312
|
|
|
313
|
+
// Generation renders from the copies in `.sdk`, not from the installed
|
|
314
|
+
// generator, so an outdated copy would otherwise be used without a word.
|
|
315
|
+
await warnCopies(root, model)
|
|
316
|
+
|
|
302
317
|
const externalOverride = resolveExternalOverride(opts, log)
|
|
303
318
|
// Snapshot the decision before preflight. In particular, do not check a
|
|
304
319
|
// missing optional destination once for safety and AGAIN before writing:
|
|
@@ -364,6 +379,34 @@ function SdkGen(opts: SdkGenOptions) {
|
|
|
364
379
|
}
|
|
365
380
|
|
|
366
381
|
|
|
382
|
+
// A warning, never a failure: a difference may be a deliberate edit, and a
|
|
383
|
+
// check that cannot run must not stop a build.
|
|
384
|
+
async function warnCopies(root: string, model: any) {
|
|
385
|
+
const sdk = Path.join(root, '.sdk')
|
|
386
|
+
|
|
387
|
+
try {
|
|
388
|
+
if (!fs.existsSync(Path.join(sdk, 'model'))) {
|
|
389
|
+
return
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
// Compared with the values an add substituted. Generation derives its
|
|
393
|
+
// own `const` later, in the project's Root.
|
|
394
|
+
const lines = await copyCheck({
|
|
395
|
+
fs: () => fs, log, folder: sdk,
|
|
396
|
+
model: { ...model, const: projectConst(model) },
|
|
397
|
+
url: '', jostraca, opts: { dryrun: !!opts.dryrun }, flags: {},
|
|
398
|
+
} as ActionContext)
|
|
399
|
+
|
|
400
|
+
for (const note of lines) {
|
|
401
|
+
log.warn({ point: 'generate-copies', note })
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
catch (err: any) {
|
|
405
|
+
log.debug({ point: 'generate-copies-unchecked', err: err?.message })
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
|
|
367
410
|
async function action(
|
|
368
411
|
args: string[], flags?: Record<string, any>,
|
|
369
412
|
): Promise<any> {
|
|
@@ -445,11 +488,7 @@ function SdkGen(opts: SdkGenOptions) {
|
|
|
445
488
|
throw modelError(path, errs[0], errs)
|
|
446
489
|
}
|
|
447
490
|
|
|
448
|
-
model.const =
|
|
449
|
-
|
|
450
|
-
names(model.const, model.name)
|
|
451
|
-
|
|
452
|
-
model.const.year = new Date().getFullYear()
|
|
491
|
+
model.const = projectConst(model)
|
|
453
492
|
|
|
454
493
|
return {
|
|
455
494
|
model,
|
|
@@ -1054,6 +1093,7 @@ export {
|
|
|
1054
1093
|
deriveEntityNames,
|
|
1055
1094
|
entityCollection,
|
|
1056
1095
|
guardModelNames,
|
|
1096
|
+
projectConst,
|
|
1057
1097
|
isReservedName,
|
|
1058
1098
|
safeVarName,
|
|
1059
1099
|
exampleVarName,
|