@prestack/thread 0.0.3 → 0.1.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/CHANGELOG.md +98 -0
- package/dist/core/{asking.d.ts → answers.d.ts} +6 -14
- package/dist/core/{asking.js → answers.js} +13 -332
- package/dist/core/{asking.ts → answers.ts} +14 -357
- package/dist/core/attach.js +2 -2
- package/dist/core/attach.ts +2 -3
- package/dist/core/chain.js +4 -11
- package/dist/core/chain.ts +4 -3
- package/dist/core/client.d.ts +57 -0
- package/dist/core/client.js +186 -0
- package/dist/core/client.ts +227 -0
- package/dist/core/descend.d.ts +2 -0
- package/dist/core/descend.js +109 -16
- package/dist/core/descend.ts +120 -16
- package/dist/core/files.d.ts +45 -0
- package/dist/core/files.js +95 -0
- package/dist/core/files.ts +137 -0
- package/dist/core/init.d.ts +1 -0
- package/dist/core/init.js +10 -2
- package/dist/core/init.ts +8 -2
- package/dist/core/invoked.js +1 -1
- package/dist/core/invoked.ts +1 -1
- package/dist/core/rows.d.ts +2 -0
- package/dist/core/rows.js +65 -0
- package/dist/core/rows.ts +58 -0
- package/dist/core/tree.js +1 -1
- package/dist/core/tree.ts +1 -1
- package/dist/derivation/attach.js +0 -12
- package/dist/derivation/attach.ts +0 -12
- package/dist/derivation/generators/build.js +8 -7
- package/dist/derivation/generators/build.ts +8 -7
- package/dist/derivation/generators/release.d.ts +1 -1
- package/dist/derivation/generators/release.js +15 -23
- package/dist/derivation/generators/release.ts +15 -15
- package/dist/integrations/attach.js +1 -19
- package/dist/integrations/attach.ts +1 -19
- package/dist/integrations/generators/read.js +2 -2
- package/dist/integrations/generators/read.ts +4 -4
- package/dist/integrations/generators/vault.js +4 -12
- package/dist/integrations/generators/vault.ts +4 -4
- package/dist/integrations/module.js +5 -3
- package/dist/integrations/module.ts +5 -3
- package/dist/integrations/vault.js +5 -5
- package/dist/integrations/vault.ts +5 -5
- package/dist/integrity/attach.js +0 -12
- package/dist/integrity/attach.ts +0 -12
- package/dist/integrity/check-threads.js +1 -1
- package/dist/integrity/check-threads.ts +1 -1
- package/dist/integrity/constraint.d.ts +11 -2
- package/dist/integrity/constraint.js +163 -20
- package/dist/integrity/constraint.ts +174 -22
- package/dist/integrity/generators/compiler.js +1 -1
- package/dist/integrity/generators/compiler.ts +1 -1
- package/dist/integrity/generators/gate.js +8 -16
- package/dist/integrity/generators/gate.ts +8 -7
- package/dist/integrity/generators/publish.js +14 -26
- package/dist/integrity/generators/publish.ts +14 -17
- package/dist/integrity/generators/trial.d.ts +2 -2
- package/dist/integrity/generators/trial.js +108 -50
- package/dist/integrity/generators/trial.ts +107 -48
- package/dist/integrity/lint.js +3 -3
- package/dist/integrity/lint.ts +3 -3
- package/dist/integrity/lsp/diagnostics.js +1 -1
- package/dist/integrity/lsp/diagnostics.ts +1 -1
- package/dist/integrity/lsp/lint.js +1 -1
- package/dist/integrity/lsp/lint.ts +1 -1
- package/dist/integrity/slopnator.d.ts +1 -14
- package/dist/integrity/slopnator.js +8 -40
- package/dist/integrity/slopnator.ts +9 -51
- package/dist/integrity/slopnators/sl_broken_lineage.js +4 -2
- package/dist/integrity/slopnators/sl_broken_lineage.ts +4 -2
- package/dist/integrity/slopnators/sl_declared_elsewhere.js +24 -3
- package/dist/integrity/slopnators/sl_declared_elsewhere.ts +24 -3
- package/dist/integrity/slopnators/sl_derived_drift.js +10 -4
- package/dist/integrity/slopnators/sl_derived_drift.ts +10 -4
- package/dist/integrity/slopnators/sl_inert_island.js +7 -13
- package/dist/integrity/slopnators/sl_inert_island.ts +7 -16
- package/dist/integrity/slopnators/sl_inert_slopnator.js +8 -8
- package/dist/integrity/slopnators/sl_inert_slopnator.ts +8 -8
- package/dist/integrity/slopnators/sl_missing_row.js +14 -9
- package/dist/integrity/slopnators/sl_missing_row.ts +14 -10
- package/dist/integrity/slopnators/sl_no_child_process.js +8 -8
- package/dist/integrity/slopnators/sl_no_child_process.ts +8 -8
- package/dist/integrity/slopnators/sl_no_import_cycle.js +1 -1
- package/dist/integrity/slopnators/sl_no_import_cycle.ts +1 -1
- package/dist/integrity/slopnators/sl_no_such_command.js +20 -5
- package/dist/integrity/slopnators/sl_no_such_command.ts +22 -5
- package/dist/integrity/slopnators/sl_only_takes_a_literal.js +8 -8
- package/dist/integrity/slopnators/sl_only_takes_a_literal.ts +8 -8
- package/dist/integrity/slopnators/sl_stale_path.js +91 -18
- package/dist/integrity/slopnators/sl_stale_path.ts +97 -18
- package/dist/integrity/slopnators/sl_twice_meant.js +25 -2
- package/dist/integrity/slopnators/sl_twice_meant.ts +28 -2
- package/dist/integrity/slopnators/sl_twice_parented.js +26 -5
- package/dist/integrity/slopnators/sl_twice_parented.ts +26 -5
- package/dist/integrity/slopnators/sl_undeclared_node.js +18 -2
- package/dist/integrity/slopnators/sl_undeclared_node.ts +18 -2
- package/dist/integrity/slopnators/sl_undeclared_operation.js +3 -1
- package/dist/integrity/slopnators/sl_undeclared_operation.ts +3 -1
- package/dist/integrity/slopnators/sl_undeclared_variant.js +6 -2
- package/dist/integrity/slopnators/sl_undeclared_variant.ts +6 -2
- package/dist/integrity/slopnators/sl_ungoverned_island.js +3 -4
- package/dist/integrity/slopnators/sl_ungoverned_island.ts +3 -4
- package/dist/integrity/slopnators/sl_unkept_rows.js +1 -1
- package/dist/integrity/slopnators/sl_unkept_rows.ts +1 -1
- package/dist/integrity/slopnators/sl_unpaired_member.js +13 -8
- package/dist/integrity/slopnators/sl_unpaired_member.ts +16 -8
- package/dist/integrity/slopnators/sl_unpaired_slopnator.js +16 -3
- package/dist/integrity/slopnators/sl_unpaired_slopnator.ts +16 -3
- package/dist/integrity/slopnators/sl_unthreaded.d.ts +1 -0
- package/dist/integrity/slopnators/sl_unthreaded.js +18 -10
- package/dist/integrity/slopnators/sl_unthreaded.ts +19 -11
- package/dist/integrity/slopnators/sl_untranslated_key.js +1 -1
- package/dist/integrity/slopnators/sl_untranslated_key.ts +1 -1
- package/dist/integrity/slopnators/sl_unversioned.js +16 -2
- package/dist/integrity/slopnators/sl_unversioned.ts +16 -2
- package/dist/integrity/sweep.js +17 -3
- package/dist/integrity/sweep.ts +20 -3
- package/dist/knowledge/attach.js +0 -6
- package/dist/knowledge/attach.ts +0 -6
- package/dist/knowledge/generators/docsgen.js +12 -3
- package/dist/knowledge/generators/docsgen.ts +12 -2
- package/dist/knowledge/generators/glossary.js +1 -1
- package/dist/knowledge/generators/glossary.ts +1 -1
- package/dist/operations/attach.js +2 -26
- package/dist/operations/attach.ts +2 -27
- package/dist/operations/dispatch.js +2 -3
- package/dist/operations/dispatch.ts +2 -3
- package/dist/operations/generators/capability.js +4 -7
- package/dist/operations/generators/capability.ts +3 -6
- package/dist/operations/generators/compile.js +8 -13
- package/dist/operations/generators/compile.ts +8 -4
- package/dist/operations/generators/permits.js +4 -13
- package/dist/operations/generators/permits.ts +3 -3
- package/dist/operations/generators/seed.js +5 -2
- package/dist/operations/generators/seed.ts +6 -2
- package/dist/operations/generators/trial.js +10 -10
- package/dist/operations/generators/trial.ts +10 -10
- package/dist/operations/http.js +4 -1
- package/dist/operations/http.ts +6 -1
- package/package.json +2 -2
- package/dist/core/cli.d.ts +0 -2
- package/dist/core/cli.js +0 -1761
- package/dist/core/cli.ts +0 -2004
- package/dist/core/generators/meta.d.ts +0 -2
- package/dist/core/generators/meta.js +0 -829
- package/dist/core/generators/meta.ts +0 -1006
- package/dist/derivation/generators/derivation.d.ts +0 -3
- package/dist/derivation/generators/derivation.js +0 -273
- package/dist/derivation/generators/derivation.ts +0 -347
- package/dist/derivation/makers/release.d.ts +0 -1
- package/dist/derivation/makers/release.js +0 -107
- package/dist/derivation/makers/release.ts +0 -135
- package/dist/integrations/generators/secret.d.ts +0 -1
- package/dist/integrations/generators/secret.js +0 -233
- package/dist/integrations/generators/secret.ts +0 -289
- package/dist/integrations/generators/target.d.ts +0 -1
- package/dist/integrations/generators/target.js +0 -775
- package/dist/integrations/generators/target.ts +0 -944
- package/dist/integrity/generators/rule.d.ts +0 -2
- package/dist/integrity/generators/rule.js +0 -213
- package/dist/integrity/generators/rule.ts +0 -271
- package/dist/integrity/generators/seal.d.ts +0 -4
- package/dist/integrity/generators/seal.js +0 -101
- package/dist/integrity/generators/seal.ts +0 -117
- package/dist/integrity/sealed.d.ts +0 -1
- package/dist/integrity/sealed.js +0 -56
- package/dist/integrity/sealed.ts +0 -56
- package/dist/knowledge/generators/skills.d.ts +0 -1
- package/dist/knowledge/generators/skills.js +0 -222
- package/dist/knowledge/generators/skills.ts +0 -263
- package/dist/operations/generators/grant.d.ts +0 -1
- package/dist/operations/generators/grant.js +0 -267
- package/dist/operations/generators/grant.ts +0 -336
- package/dist/operations/generators/operation.d.ts +0 -1
- package/dist/operations/generators/operation.js +0 -811
- package/dist/operations/generators/operation.ts +0 -972
- package/dist/operations/makers/capability.d.ts +0 -1
- package/dist/operations/makers/capability.js +0 -117
- package/dist/operations/makers/capability.ts +0 -166
- package/dist/operations/makers/trial.d.ts +0 -1
- package/dist/operations/makers/trial.js +0 -413
- package/dist/operations/makers/trial.ts +0 -520
package/dist/core/descend.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { spawnSync } from 'node:child_process'
|
|
2
|
-
import { existsSync, readdirSync, readFileSync, realpathSync, statSync } from '
|
|
2
|
+
import { attached, existsSync, kind, readdirSync, readFileSync, realpathSync, statSync, writeFileSync } from './files.ts'
|
|
3
3
|
import { dirname, join, relative, resolve } from 'node:path'
|
|
4
4
|
|
|
5
5
|
import ts from 'typescript'
|
|
@@ -35,37 +35,46 @@ export const ROOT = TREE_AT?.at ?? NOWHERE
|
|
|
35
35
|
export const TREE = `${TREE_AT?.name ?? NOWHERE}/`
|
|
36
36
|
export const THREAD_AT = `${TREE_AT?.name ?? NOWHERE}/thread.ts`
|
|
37
37
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
38
|
+
let ignores: readonly string[] | undefined
|
|
39
|
+
let readIgnores = false
|
|
40
|
+
|
|
41
|
+
function ownIgnores(): readonly string[] | undefined {
|
|
42
|
+
if (readIgnores) return ignores
|
|
43
|
+
readIgnores = true
|
|
44
|
+
if (!attached() && spawnSync('git', ['rev-parse', '--is-inside-work-tree'], { cwd: ROOT, stdio: 'ignore' }).status === 0) {
|
|
45
|
+
return ignores
|
|
41
46
|
}
|
|
42
47
|
try {
|
|
43
|
-
|
|
48
|
+
ignores = readFileSync(join(ROOT, '.gitignore'), 'utf8')
|
|
44
49
|
.split('\n')
|
|
45
50
|
.map((one) => one.trim())
|
|
46
51
|
.filter((one) => one !== '' && !one.startsWith('#') && !one.startsWith('!'))
|
|
47
52
|
.map((one) => one.replace(/^\/+|\/+$/g, ''))
|
|
48
53
|
.filter((one) => one !== '' && !one.includes('*'))
|
|
49
54
|
} catch {
|
|
50
|
-
|
|
55
|
+
ignores = []
|
|
51
56
|
}
|
|
52
|
-
|
|
57
|
+
return ignores
|
|
58
|
+
}
|
|
53
59
|
|
|
54
60
|
const asked = new Map<string, boolean>()
|
|
55
61
|
|
|
56
62
|
export function unkept(at: string): boolean {
|
|
57
63
|
const held = asked.get(at)
|
|
58
64
|
if (held !== undefined) return held
|
|
65
|
+
const own = ownIgnores()
|
|
59
66
|
const found =
|
|
60
|
-
|
|
67
|
+
own === undefined
|
|
61
68
|
? spawnSync('git', ['check-ignore', '-q', '--', at], { cwd: ROOT, stdio: 'ignore' }).status === 0
|
|
62
|
-
:
|
|
69
|
+
: own.some((one) => at === one || at.startsWith(`${one}/`) || at.split('/').includes(one))
|
|
63
70
|
asked.set(at, found)
|
|
64
71
|
return found
|
|
65
72
|
}
|
|
66
73
|
|
|
67
74
|
export const LISTS = ['declares', 'derives', 'seeds'] as const
|
|
68
75
|
|
|
76
|
+
export const ROW_LISTS = [...LISTS, 'holds'] as const
|
|
77
|
+
|
|
69
78
|
const SOURCE = /\.(ts|tsx|mts|cts)$/
|
|
70
79
|
const RUNNER = /^(?:pnpm|npm|yarn) (?:run )?([\w:.-]+)/
|
|
71
80
|
|
|
@@ -198,12 +207,77 @@ const INVARIANT: ts.CompilerOptions = {
|
|
|
198
207
|
jsx: ts.JsxEmit.ReactJSX,
|
|
199
208
|
}
|
|
200
209
|
|
|
210
|
+
const NEVER: readonly string[] = ['node_modules', 'bower_components', 'jspm_packages']
|
|
211
|
+
|
|
212
|
+
interface Wanted {
|
|
213
|
+
readonly under: string
|
|
214
|
+
readonly ending: string
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
function bounds(from: string, one: string): Wanted {
|
|
218
|
+
const star = one.indexOf('*')
|
|
219
|
+
if (star === -1) return { under: resolve(from, one), ending: '' }
|
|
220
|
+
const head = one.slice(0, star)
|
|
221
|
+
const cut = head.lastIndexOf('/')
|
|
222
|
+
const tail = one.slice(star)
|
|
223
|
+
const dot = tail.lastIndexOf('.')
|
|
224
|
+
const end = dot === -1 ? '' : tail.slice(dot)
|
|
225
|
+
return {
|
|
226
|
+
under: resolve(from, cut === -1 ? '' : head.slice(0, cut)),
|
|
227
|
+
ending: end.includes('/') || end.includes('*') ? '' : end,
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
function wanted(at: string, only: readonly Wanted[]): boolean {
|
|
232
|
+
if (only.length === 0) return true
|
|
233
|
+
return only.some((one) => (at === one.under || at.startsWith(`${one.under}/`)) && at.endsWith(one.ending))
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
function listing(at: string, take: readonly string[], skip: readonly string[], only: readonly Wanted[], deep: number): readonly string[] {
|
|
237
|
+
const found: string[] = []
|
|
238
|
+
if (deep < 0 || !existsSync(at)) return found
|
|
239
|
+
for (const one of readdirSync(at, { withFileTypes: true })) {
|
|
240
|
+
const full = join(at, one.name)
|
|
241
|
+
if (skip.some((each) => full === each || full.startsWith(`${each}/`))) continue
|
|
242
|
+
if (one.isDirectory()) {
|
|
243
|
+
if (NEVER.includes(one.name)) continue
|
|
244
|
+
found.push(...listing(full, take, skip, only, deep - 1))
|
|
245
|
+
} else if (take.some((each) => one.name.endsWith(each)) && wanted(full, only)) {
|
|
246
|
+
found.push(full)
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
return found
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
function parsing(from: string): ts.ParseConfigHost {
|
|
253
|
+
return {
|
|
254
|
+
useCaseSensitiveFileNames: true,
|
|
255
|
+
fileExists: (at) => existsSync(at),
|
|
256
|
+
readFile: (at) => {
|
|
257
|
+
try {
|
|
258
|
+
return readFileSync(at)
|
|
259
|
+
} catch {
|
|
260
|
+
return undefined
|
|
261
|
+
}
|
|
262
|
+
},
|
|
263
|
+
readDirectory: (at, take, skip, only, deep) =>
|
|
264
|
+
listing(
|
|
265
|
+
at,
|
|
266
|
+
take,
|
|
267
|
+
(skip ?? []).map((one) => resolve(from, one.endsWith('/**') ? one.slice(0, -3) : one)),
|
|
268
|
+
only.map((one) => bounds(from, one)),
|
|
269
|
+
deep ?? Number.MAX_SAFE_INTEGER,
|
|
270
|
+
),
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
201
274
|
export function configured(): { readonly options: ts.CompilerOptions; readonly from: string; readonly trouble?: string } {
|
|
202
275
|
for (const name of CONFIGS) {
|
|
203
276
|
const at = join(ROOT, name)
|
|
204
|
-
if (!
|
|
277
|
+
if (!existsSync(at)) continue
|
|
205
278
|
|
|
206
|
-
const
|
|
279
|
+
const host = parsing(ROOT)
|
|
280
|
+
const held = ts.readConfigFile(at, host.readFile)
|
|
207
281
|
if (held.error !== undefined) {
|
|
208
282
|
return {
|
|
209
283
|
options: { ...FALLBACK, ...INVARIANT },
|
|
@@ -212,7 +286,7 @@ export function configured(): { readonly options: ts.CompilerOptions; readonly f
|
|
|
212
286
|
}
|
|
213
287
|
}
|
|
214
288
|
|
|
215
|
-
const parsed = ts.parseJsonConfigFileContent(held.config as object,
|
|
289
|
+
const parsed = ts.parseJsonConfigFileContent(held.config as object, host, dirname(at))
|
|
216
290
|
const complained = parsed.errors[0]
|
|
217
291
|
if (complained !== undefined) {
|
|
218
292
|
return {
|
|
@@ -227,13 +301,37 @@ export function configured(): { readonly options: ts.CompilerOptions; readonly f
|
|
|
227
301
|
return { options: { ...FALLBACK, ...INVARIANT }, from: '' }
|
|
228
302
|
}
|
|
229
303
|
|
|
304
|
+
export function hosting(options: ts.CompilerOptions): ts.CompilerHost {
|
|
305
|
+
const host = ts.createCompilerHost(options, true)
|
|
306
|
+
const lib = host.getDefaultLibLocation?.()
|
|
307
|
+
const toolchain = (at: string): boolean => lib !== undefined && (at === lib || at.startsWith(`${lib}/`))
|
|
308
|
+
return {
|
|
309
|
+
...host,
|
|
310
|
+
fileExists: (at) => (toolchain(at) ? host.fileExists(at) : kind(at) === 'file'),
|
|
311
|
+
directoryExists: (at) => (toolchain(at) ? (host.directoryExists?.(at) ?? false) : kind(at) === 'folder'),
|
|
312
|
+
readFile: (at) => (toolchain(at) ? host.readFile(at) : kind(at) === 'file' ? readFileSync(at) : undefined),
|
|
313
|
+
getSourceFile: (at, version) => {
|
|
314
|
+
if (toolchain(at)) return host.getSourceFile(at, version)
|
|
315
|
+
if (kind(at) !== 'file') return undefined
|
|
316
|
+
return ts.createSourceFile(at, readFileSync(at), version, true)
|
|
317
|
+
},
|
|
318
|
+
getDirectories: (at) =>
|
|
319
|
+
kind(at) === 'folder' ? readdirSync(at, { withFileTypes: true }).filter((one) => one.isDirectory()).map((one) => one.name) : [],
|
|
320
|
+
realpath: (at) => (toolchain(at) ? (host.realpath?.(at) ?? at) : realpathSync(at)),
|
|
321
|
+
writeFile: (at, said) => {
|
|
322
|
+
writeFileSync(at, said)
|
|
323
|
+
},
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
|
|
230
327
|
let built: { program: ts.Program; checker: ts.TypeChecker } | undefined
|
|
231
328
|
|
|
232
329
|
function compiled(): { program: ts.Program; checker: ts.TypeChecker } {
|
|
233
330
|
rooted()
|
|
234
331
|
if (built !== undefined) return built
|
|
235
332
|
const roots = [THREAD_AT, ...sources(), ...shipped()].filter((one) => SOURCE.test(one)).map((one) => resolve(ROOT, one))
|
|
236
|
-
const
|
|
333
|
+
const options = configured().options
|
|
334
|
+
const program = ts.createProgram([...new Set(roots)], options, hosting(options))
|
|
237
335
|
built = { program, checker: program.getTypeChecker() }
|
|
238
336
|
return built
|
|
239
337
|
}
|
|
@@ -659,6 +757,9 @@ export function forget(): void {
|
|
|
659
757
|
scanned = undefined
|
|
660
758
|
commands = undefined
|
|
661
759
|
source.clear()
|
|
760
|
+
asked.clear()
|
|
761
|
+
ignores = undefined
|
|
762
|
+
readIgnores = false
|
|
662
763
|
}
|
|
663
764
|
|
|
664
765
|
export function descend(): Pass {
|
|
@@ -846,7 +947,10 @@ export function descend(): Pass {
|
|
|
846
947
|
}
|
|
847
948
|
|
|
848
949
|
for (const one of value.elements) {
|
|
849
|
-
|
|
950
|
+
const declaration = ts.isIdentifier(one) ? checker.getSymbolAtLocation(one)?.valueDeclaration : undefined
|
|
951
|
+
const initial = declaration !== undefined && ts.isVariableDeclaration(declaration) ? unwrap(declaration.initializer) : undefined
|
|
952
|
+
const object = ts.isObjectLiteralExpression(one) ? one : initial !== undefined && ts.isObjectLiteralExpression(initial) ? initial : undefined
|
|
953
|
+
if (object === undefined) {
|
|
850
954
|
findings.push({
|
|
851
955
|
file: at,
|
|
852
956
|
detail: `\`${by}\` holds something in \`${list}\` that is not a row written out here`,
|
|
@@ -857,14 +961,14 @@ export function descend(): Pass {
|
|
|
857
961
|
rows += 1
|
|
858
962
|
const wanted = checker.getContextualType(one)
|
|
859
963
|
const kind = wanted === undefined ? undefined : elementOf(checker, wanted)
|
|
860
|
-
const row = rowOf(
|
|
964
|
+
const row = rowOf(object, kind === undefined ? type : checker.typeToString(kind), at, kind)
|
|
861
965
|
coin(row.id, row.describes, under, by)
|
|
862
966
|
judge(row, by, list, false)
|
|
863
967
|
if (row.at !== undefined) {
|
|
864
968
|
threaded.set(row.at, [...(threaded.get(row.at) ?? []), { list, by, row }])
|
|
865
969
|
if (list === 'derives' && row.id !== undefined) derived.set(row.id, row)
|
|
866
970
|
}
|
|
867
|
-
if (LISTS.some((name) => row.fields.has(name))) into(
|
|
971
|
+
if (LISTS.some((name) => row.fields.has(name))) into(object, row.type, at, under, by, true)
|
|
868
972
|
if (row.at !== undefined) open(row.at, wanted === undefined ? undefined : elementOf(checker, wanted), under, row.id ?? by, by)
|
|
869
973
|
}
|
|
870
974
|
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import * as disk from 'node:fs';
|
|
2
|
+
export type Kind = 'file' | 'folder' | 'other' | 'none';
|
|
3
|
+
export interface Listed {
|
|
4
|
+
readonly name: string;
|
|
5
|
+
readonly kind: Exclude<Kind, 'none'>;
|
|
6
|
+
}
|
|
7
|
+
export interface Measured {
|
|
8
|
+
readonly size: number;
|
|
9
|
+
readonly modified: number;
|
|
10
|
+
}
|
|
11
|
+
export interface Answering {
|
|
12
|
+
readonly kind: (at: string) => Kind;
|
|
13
|
+
readonly read: (at: string) => string;
|
|
14
|
+
readonly write: (at: string, said: string) => void;
|
|
15
|
+
readonly list: (at: string) => readonly Listed[];
|
|
16
|
+
readonly stat: (at: string) => Measured;
|
|
17
|
+
readonly remove: (at: string) => void;
|
|
18
|
+
readonly real: (at: string) => string;
|
|
19
|
+
}
|
|
20
|
+
export declare function answeredBy(one: Answering | undefined): void;
|
|
21
|
+
export declare function attached(): boolean;
|
|
22
|
+
export declare function kind(at: string): Kind;
|
|
23
|
+
export declare function existsSync(at: disk.PathLike): boolean;
|
|
24
|
+
export declare function readFileSync(at: disk.PathOrFileDescriptor, how?: BufferEncoding): string;
|
|
25
|
+
export declare function writeFileSync(at: disk.PathOrFileDescriptor, said: string, how?: BufferEncoding): void;
|
|
26
|
+
export interface Named {
|
|
27
|
+
readonly name: string;
|
|
28
|
+
readonly isFile: () => boolean;
|
|
29
|
+
readonly isDirectory: () => boolean;
|
|
30
|
+
}
|
|
31
|
+
export declare function readdirSync(at: disk.PathLike): string[];
|
|
32
|
+
export declare function readdirSync(at: disk.PathLike, how: {
|
|
33
|
+
readonly withFileTypes: true;
|
|
34
|
+
}): readonly Named[];
|
|
35
|
+
export interface Held extends Named, Measured {
|
|
36
|
+
readonly mtimeMs: number;
|
|
37
|
+
}
|
|
38
|
+
export declare function statSync(at: disk.PathLike): Held;
|
|
39
|
+
export declare function statSync(at: disk.PathLike, how: {
|
|
40
|
+
readonly throwIfNoEntry: false;
|
|
41
|
+
}): Held | undefined;
|
|
42
|
+
export declare function rmSync(at: disk.PathLike, how?: disk.RmOptions): void;
|
|
43
|
+
export declare function renameSync(from: disk.PathLike, to: disk.PathLike): void;
|
|
44
|
+
export declare function appendFileSync(at: disk.PathOrFileDescriptor, said: string): void;
|
|
45
|
+
export declare function realpathSync(at: disk.PathLike): string;
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import * as disk from 'node:fs';
|
|
2
|
+
import { dirname } from 'node:path';
|
|
3
|
+
let answering;
|
|
4
|
+
export function answeredBy(one) {
|
|
5
|
+
answering = one;
|
|
6
|
+
}
|
|
7
|
+
const asked = (at) => (typeof at === 'string' ? answering : undefined);
|
|
8
|
+
export function attached() {
|
|
9
|
+
return answering !== undefined;
|
|
10
|
+
}
|
|
11
|
+
export function kind(at) {
|
|
12
|
+
const one = answering;
|
|
13
|
+
if (one !== undefined)
|
|
14
|
+
return one.kind(at);
|
|
15
|
+
const held = disk.statSync(at, { throwIfNoEntry: false });
|
|
16
|
+
if (held === undefined)
|
|
17
|
+
return 'none';
|
|
18
|
+
return held.isFile() ? 'file' : held.isDirectory() ? 'folder' : 'other';
|
|
19
|
+
}
|
|
20
|
+
export function existsSync(at) {
|
|
21
|
+
return typeof at === 'string' ? kind(at) !== 'none' : disk.existsSync(at);
|
|
22
|
+
}
|
|
23
|
+
export function readFileSync(at, how) {
|
|
24
|
+
const one = asked(at);
|
|
25
|
+
return one === undefined ? disk.readFileSync(at, how ?? 'utf8') : one.read(at);
|
|
26
|
+
}
|
|
27
|
+
export function writeFileSync(at, said, how) {
|
|
28
|
+
const one = asked(at);
|
|
29
|
+
if (one !== undefined) {
|
|
30
|
+
one.write(at, said);
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
if (typeof at === 'string')
|
|
34
|
+
disk.mkdirSync(dirname(at), { recursive: true });
|
|
35
|
+
disk.writeFileSync(at, said, how ?? 'utf8');
|
|
36
|
+
}
|
|
37
|
+
export function readdirSync(at, how) {
|
|
38
|
+
const one = asked(at);
|
|
39
|
+
if (one === undefined)
|
|
40
|
+
return how === undefined ? disk.readdirSync(at) : disk.readdirSync(at, how);
|
|
41
|
+
const held = one.list(at);
|
|
42
|
+
return how === undefined
|
|
43
|
+
? held.map((each) => each.name)
|
|
44
|
+
: held.map((each) => ({ name: each.name, isFile: () => each.kind === 'file', isDirectory: () => each.kind === 'folder' }));
|
|
45
|
+
}
|
|
46
|
+
export function statSync(at, how) {
|
|
47
|
+
const one = asked(at);
|
|
48
|
+
if (one === undefined)
|
|
49
|
+
return (how === undefined ? disk.statSync(at) : disk.statSync(at, how));
|
|
50
|
+
const path = at;
|
|
51
|
+
const held = one.kind(path);
|
|
52
|
+
if (held === 'none') {
|
|
53
|
+
if (how !== undefined)
|
|
54
|
+
return undefined;
|
|
55
|
+
throw new Error(`${path} is not there, so nothing can be said about it.`);
|
|
56
|
+
}
|
|
57
|
+
const measured = one.stat(path);
|
|
58
|
+
return {
|
|
59
|
+
name: path,
|
|
60
|
+
size: measured.size,
|
|
61
|
+
modified: measured.modified,
|
|
62
|
+
mtimeMs: measured.modified,
|
|
63
|
+
isFile: () => held === 'file',
|
|
64
|
+
isDirectory: () => held === 'folder',
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
export function rmSync(at, how) {
|
|
68
|
+
const one = asked(at);
|
|
69
|
+
if (one === undefined)
|
|
70
|
+
disk.rmSync(at, how);
|
|
71
|
+
else
|
|
72
|
+
one.remove(at);
|
|
73
|
+
}
|
|
74
|
+
export function renameSync(from, to) {
|
|
75
|
+
const one = asked(from);
|
|
76
|
+
if (one === undefined) {
|
|
77
|
+
disk.renameSync(from, to);
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
one.write(to, one.read(from));
|
|
81
|
+
one.remove(from);
|
|
82
|
+
}
|
|
83
|
+
export function appendFileSync(at, said) {
|
|
84
|
+
const one = asked(at);
|
|
85
|
+
if (one === undefined) {
|
|
86
|
+
disk.appendFileSync(at, said);
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
const path = at;
|
|
90
|
+
one.write(path, `${one.kind(path) === 'none' ? '' : one.read(path)}${said}`);
|
|
91
|
+
}
|
|
92
|
+
export function realpathSync(at) {
|
|
93
|
+
const one = asked(at);
|
|
94
|
+
return one === undefined ? disk.realpathSync(at) : one.real(at);
|
|
95
|
+
}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import * as disk from 'node:fs'
|
|
2
|
+
import { dirname } from 'node:path'
|
|
3
|
+
|
|
4
|
+
export type Kind = 'file' | 'folder' | 'other' | 'none'
|
|
5
|
+
|
|
6
|
+
export interface Listed {
|
|
7
|
+
readonly name: string
|
|
8
|
+
readonly kind: Exclude<Kind, 'none'>
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface Measured {
|
|
12
|
+
readonly size: number
|
|
13
|
+
readonly modified: number
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface Answering {
|
|
17
|
+
readonly kind: (at: string) => Kind
|
|
18
|
+
readonly read: (at: string) => string
|
|
19
|
+
readonly write: (at: string, said: string) => void
|
|
20
|
+
readonly list: (at: string) => readonly Listed[]
|
|
21
|
+
readonly stat: (at: string) => Measured
|
|
22
|
+
readonly remove: (at: string) => void
|
|
23
|
+
readonly real: (at: string) => string
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
let answering: Answering | undefined
|
|
27
|
+
|
|
28
|
+
export function answeredBy(one: Answering | undefined): void {
|
|
29
|
+
answering = one
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const asked = (at: unknown): Answering | undefined => (typeof at === 'string' ? answering : undefined)
|
|
33
|
+
|
|
34
|
+
export function attached(): boolean {
|
|
35
|
+
return answering !== undefined
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export function kind(at: string): Kind {
|
|
39
|
+
const one = answering
|
|
40
|
+
if (one !== undefined) return one.kind(at)
|
|
41
|
+
const held = disk.statSync(at, { throwIfNoEntry: false })
|
|
42
|
+
if (held === undefined) return 'none'
|
|
43
|
+
return held.isFile() ? 'file' : held.isDirectory() ? 'folder' : 'other'
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export function existsSync(at: disk.PathLike): boolean {
|
|
47
|
+
return typeof at === 'string' ? kind(at) !== 'none' : disk.existsSync(at)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export function readFileSync(at: disk.PathOrFileDescriptor, how?: BufferEncoding): string {
|
|
51
|
+
const one = asked(at)
|
|
52
|
+
return one === undefined ? disk.readFileSync(at, how ?? 'utf8') : one.read(at as string)
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export function writeFileSync(at: disk.PathOrFileDescriptor, said: string, how?: BufferEncoding): void {
|
|
56
|
+
const one = asked(at)
|
|
57
|
+
if (one !== undefined) {
|
|
58
|
+
one.write(at as string, said)
|
|
59
|
+
return
|
|
60
|
+
}
|
|
61
|
+
if (typeof at === 'string') disk.mkdirSync(dirname(at), { recursive: true })
|
|
62
|
+
disk.writeFileSync(at, said, how ?? 'utf8')
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export interface Named {
|
|
66
|
+
readonly name: string
|
|
67
|
+
readonly isFile: () => boolean
|
|
68
|
+
readonly isDirectory: () => boolean
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export function readdirSync(at: disk.PathLike): string[]
|
|
72
|
+
export function readdirSync(at: disk.PathLike, how: { readonly withFileTypes: true }): readonly Named[]
|
|
73
|
+
export function readdirSync(at: disk.PathLike, how?: { readonly withFileTypes: true }): string[] | readonly Named[] {
|
|
74
|
+
const one = asked(at)
|
|
75
|
+
if (one === undefined) return how === undefined ? disk.readdirSync(at) : disk.readdirSync(at, how)
|
|
76
|
+
const held = one.list(at as string)
|
|
77
|
+
return how === undefined
|
|
78
|
+
? held.map((each) => each.name)
|
|
79
|
+
: held.map((each) => ({ name: each.name, isFile: () => each.kind === 'file', isDirectory: () => each.kind === 'folder' }))
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export interface Held extends Named, Measured {
|
|
83
|
+
readonly mtimeMs: number
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export function statSync(at: disk.PathLike): Held
|
|
87
|
+
export function statSync(at: disk.PathLike, how: { readonly throwIfNoEntry: false }): Held | undefined
|
|
88
|
+
export function statSync(at: disk.PathLike, how?: { readonly throwIfNoEntry: false }): Held | undefined {
|
|
89
|
+
const one = asked(at)
|
|
90
|
+
if (one === undefined) return (how === undefined ? disk.statSync(at) : disk.statSync(at, how)) as Held | undefined
|
|
91
|
+
const path = at as string
|
|
92
|
+
const held = one.kind(path)
|
|
93
|
+
if (held === 'none') {
|
|
94
|
+
if (how !== undefined) return undefined
|
|
95
|
+
throw new Error(`${path} is not there, so nothing can be said about it.`)
|
|
96
|
+
}
|
|
97
|
+
const measured = one.stat(path)
|
|
98
|
+
return {
|
|
99
|
+
name: path,
|
|
100
|
+
size: measured.size,
|
|
101
|
+
modified: measured.modified,
|
|
102
|
+
mtimeMs: measured.modified,
|
|
103
|
+
isFile: () => held === 'file',
|
|
104
|
+
isDirectory: () => held === 'folder',
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export function rmSync(at: disk.PathLike, how?: disk.RmOptions): void {
|
|
109
|
+
const one = asked(at)
|
|
110
|
+
if (one === undefined) disk.rmSync(at, how)
|
|
111
|
+
else one.remove(at as string)
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export function renameSync(from: disk.PathLike, to: disk.PathLike): void {
|
|
115
|
+
const one = asked(from)
|
|
116
|
+
if (one === undefined) {
|
|
117
|
+
disk.renameSync(from, to)
|
|
118
|
+
return
|
|
119
|
+
}
|
|
120
|
+
one.write(to as string, one.read(from as string))
|
|
121
|
+
one.remove(from as string)
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
export function appendFileSync(at: disk.PathOrFileDescriptor, said: string): void {
|
|
125
|
+
const one = asked(at)
|
|
126
|
+
if (one === undefined) {
|
|
127
|
+
disk.appendFileSync(at, said)
|
|
128
|
+
return
|
|
129
|
+
}
|
|
130
|
+
const path = at as string
|
|
131
|
+
one.write(path, `${one.kind(path) === 'none' ? '' : one.read(path)}${said}`)
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
export function realpathSync(at: disk.PathLike): string {
|
|
135
|
+
const one = asked(at)
|
|
136
|
+
return one === undefined ? disk.realpathSync(at as string) : one.real(at as string)
|
|
137
|
+
}
|
package/dist/core/init.d.ts
CHANGED
|
@@ -6,6 +6,7 @@ export declare class AlreadyThreadedError extends Error {
|
|
|
6
6
|
}
|
|
7
7
|
export declare const COMPILER = "tsconfig.json";
|
|
8
8
|
export declare const LOCKFILES: readonly ["package-lock.json", "pnpm-lock.yaml", "yarn.lock", "bun.lockb"];
|
|
9
|
+
export declare function manager(into: string): readonly string[];
|
|
9
10
|
export declare const MANIFEST = "package.json";
|
|
10
11
|
export declare const REGISTRY: string;
|
|
11
12
|
export declare const IGNORED: string;
|
package/dist/core/init.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { existsSync,
|
|
1
|
+
import { existsSync, readFileSync, writeFileSync } from "./files.js";
|
|
2
2
|
import { join, relative, resolve } from 'node:path';
|
|
3
3
|
import { quoted } from "./rows.js";
|
|
4
4
|
export const TREE = '_threads';
|
|
@@ -15,6 +15,15 @@ export class AlreadyThreadedError extends Error {
|
|
|
15
15
|
}
|
|
16
16
|
export const COMPILER = 'tsconfig.json';
|
|
17
17
|
export const LOCKFILES = ['package-lock.json', 'pnpm-lock.yaml', 'yarn.lock', 'bun.lockb'];
|
|
18
|
+
export function manager(into) {
|
|
19
|
+
if (existsSync(join(into, 'pnpm-lock.yaml')))
|
|
20
|
+
return ['pnpm', 'add'];
|
|
21
|
+
if (existsSync(join(into, 'yarn.lock')))
|
|
22
|
+
return ['yarn', 'add'];
|
|
23
|
+
if (existsSync(join(into, 'bun.lockb')))
|
|
24
|
+
return ['bun', 'add'];
|
|
25
|
+
return ['npm', 'install'];
|
|
26
|
+
}
|
|
18
27
|
export const MANIFEST = 'package.json';
|
|
19
28
|
const MODULE = 'module';
|
|
20
29
|
export const REGISTRY = '.npm' + 'rc';
|
|
@@ -104,7 +113,6 @@ export function init(into) {
|
|
|
104
113
|
const at = join(dir, ROOT);
|
|
105
114
|
if (existsSync(at))
|
|
106
115
|
throw new AlreadyThreadedError(relative(into, at));
|
|
107
|
-
mkdirSync(dir, { recursive: true });
|
|
108
116
|
const written = [];
|
|
109
117
|
const held = join(into, COMPILER);
|
|
110
118
|
if (!existsSync(held)) {
|
package/dist/core/init.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { existsSync,
|
|
1
|
+
import { existsSync, readFileSync, writeFileSync } from './files.ts'
|
|
2
2
|
import { join, relative, resolve } from 'node:path'
|
|
3
3
|
|
|
4
4
|
import { quoted } from './rows.ts'
|
|
@@ -24,6 +24,13 @@ export const COMPILER = 'tsconfig.json'
|
|
|
24
24
|
|
|
25
25
|
export const LOCKFILES = ['package-lock.json', 'pnpm-lock.yaml', 'yarn.lock', 'bun.lockb'] as const
|
|
26
26
|
|
|
27
|
+
export function manager(into: string): readonly string[] {
|
|
28
|
+
if (existsSync(join(into, 'pnpm-lock.yaml'))) return ['pnpm', 'add']
|
|
29
|
+
if (existsSync(join(into, 'yarn.lock'))) return ['yarn', 'add']
|
|
30
|
+
if (existsSync(join(into, 'bun.lockb'))) return ['bun', 'add']
|
|
31
|
+
return ['npm', 'install']
|
|
32
|
+
}
|
|
33
|
+
|
|
27
34
|
export const MANIFEST = 'package.json'
|
|
28
35
|
|
|
29
36
|
const MODULE = 'module'
|
|
@@ -134,7 +141,6 @@ export function init(into: string): readonly string[] {
|
|
|
134
141
|
const dir = resolve(into, TREE)
|
|
135
142
|
const at = join(dir, ROOT)
|
|
136
143
|
if (existsSync(at)) throw new AlreadyThreadedError(relative(into, at))
|
|
137
|
-
mkdirSync(dir, { recursive: true })
|
|
138
144
|
const written: string[] = []
|
|
139
145
|
|
|
140
146
|
const held = join(into, COMPILER)
|
package/dist/core/invoked.js
CHANGED
|
@@ -21,7 +21,7 @@ export const BESIDE = (name) => `${name}${SOURCE ? '.ts' : '.js'}`;
|
|
|
21
21
|
export const LOADER = SOURCE ? ['--import', 'tsx'] : [];
|
|
22
22
|
export const CLI = [
|
|
23
23
|
...LOADER,
|
|
24
|
-
join(dirname(fileURLToPath(import.meta.url)), BESIDE('cli')),
|
|
24
|
+
join(dirname(fileURLToPath(import.meta.url)), '..', '..', 'cli', BESIDE('cli')),
|
|
25
25
|
];
|
|
26
26
|
export const REFUSED = Symbol.for('thread.refused');
|
|
27
27
|
let sharing = false;
|
package/dist/core/invoked.ts
CHANGED
|
@@ -24,7 +24,7 @@ export const LOADER: readonly string[] = SOURCE ? ['--import', 'tsx'] : []
|
|
|
24
24
|
|
|
25
25
|
export const CLI: readonly string[] = [
|
|
26
26
|
...LOADER,
|
|
27
|
-
join(dirname(fileURLToPath(import.meta.url)), BESIDE('cli')),
|
|
27
|
+
join(dirname(fileURLToPath(import.meta.url)), '..', '..', 'cli', BESIDE('cli')),
|
|
28
28
|
]
|
|
29
29
|
|
|
30
30
|
export const REFUSED = Symbol.for('thread.refused')
|
package/dist/core/rows.d.ts
CHANGED
|
@@ -18,6 +18,8 @@ export declare function withRequires(text: string, where: Bounds, id: string, re
|
|
|
18
18
|
export declare function seedsIn(text: string, where: Bounds, id: string): Bounds | undefined;
|
|
19
19
|
export declare function afterRow(text: string, where: Bounds, follows: string, row: string): string | undefined;
|
|
20
20
|
export declare const quoted: (one: string) => string;
|
|
21
|
+
export declare function valuesIn(text: string): Readonly<Record<string, unknown>>;
|
|
22
|
+
export declare function unread(text: string): readonly string[];
|
|
21
23
|
export declare const STATED: string[];
|
|
22
24
|
export declare function reconciled(held: string, source: string, fields: readonly string[]): string;
|
|
23
25
|
export declare function fieldIn(text: string, where: Bounds, id: string, field: string): string | undefined;
|
package/dist/core/rows.js
CHANGED
|
@@ -239,6 +239,71 @@ function stated(node, field) {
|
|
|
239
239
|
return undefined;
|
|
240
240
|
}
|
|
241
241
|
export const quoted = (one) => `'${one.replace(/\\/g, '\\\\').replace(/'/g, "\\'").replace(/\n/g, '\\n')}'`;
|
|
242
|
+
const UNREAD = Symbol.for('thread.unread');
|
|
243
|
+
function valued(node) {
|
|
244
|
+
if (ts.isStringLiteral(node) || ts.isNoSubstitutionTemplateLiteral(node))
|
|
245
|
+
return node.text;
|
|
246
|
+
if (ts.isNumericLiteral(node))
|
|
247
|
+
return Number(node.text);
|
|
248
|
+
if (node.kind === ts.SyntaxKind.TrueKeyword)
|
|
249
|
+
return true;
|
|
250
|
+
if (node.kind === ts.SyntaxKind.FalseKeyword)
|
|
251
|
+
return false;
|
|
252
|
+
if (node.kind === ts.SyntaxKind.NullKeyword)
|
|
253
|
+
return null;
|
|
254
|
+
if (ts.isAsExpression(node) || ts.isSatisfiesExpression(node) || ts.isParenthesizedExpression(node))
|
|
255
|
+
return valued(node.expression);
|
|
256
|
+
if (ts.isPrefixUnaryExpression(node) && node.operator === ts.SyntaxKind.MinusToken) {
|
|
257
|
+
const held = valued(node.operand);
|
|
258
|
+
return typeof held === 'number' ? -held : UNREAD;
|
|
259
|
+
}
|
|
260
|
+
if (ts.isArrayLiteralExpression(node)) {
|
|
261
|
+
const held = [];
|
|
262
|
+
for (const one of node.elements) {
|
|
263
|
+
const each = valued(one);
|
|
264
|
+
if (each === UNREAD)
|
|
265
|
+
return UNREAD;
|
|
266
|
+
held.push(each);
|
|
267
|
+
}
|
|
268
|
+
return held;
|
|
269
|
+
}
|
|
270
|
+
if (ts.isObjectLiteralExpression(node)) {
|
|
271
|
+
const held = {};
|
|
272
|
+
for (const one of node.properties) {
|
|
273
|
+
if (!ts.isPropertyAssignment(one))
|
|
274
|
+
return UNREAD;
|
|
275
|
+
const key = keyed(one);
|
|
276
|
+
if (key === undefined)
|
|
277
|
+
return UNREAD;
|
|
278
|
+
const each = valued(one.initializer);
|
|
279
|
+
if (each === UNREAD)
|
|
280
|
+
return UNREAD;
|
|
281
|
+
held[key] = each;
|
|
282
|
+
}
|
|
283
|
+
return held;
|
|
284
|
+
}
|
|
285
|
+
return UNREAD;
|
|
286
|
+
}
|
|
287
|
+
function taken(text) {
|
|
288
|
+
const found = [];
|
|
289
|
+
walk(tree(text), (node) => {
|
|
290
|
+
if (!ts.isVariableDeclaration(node) || node.initializer === undefined || !ts.isIdentifier(node.name))
|
|
291
|
+
return;
|
|
292
|
+
found.push([node.name.text, valued(node.initializer)]);
|
|
293
|
+
});
|
|
294
|
+
return found;
|
|
295
|
+
}
|
|
296
|
+
export function valuesIn(text) {
|
|
297
|
+
const found = {};
|
|
298
|
+
for (const [name, held] of taken(text)) {
|
|
299
|
+
if (held !== UNREAD)
|
|
300
|
+
found[name] = held;
|
|
301
|
+
}
|
|
302
|
+
return found;
|
|
303
|
+
}
|
|
304
|
+
export function unread(text) {
|
|
305
|
+
return taken(text).filter(([, held]) => held === UNREAD).map(([name]) => name);
|
|
306
|
+
}
|
|
242
307
|
export const STATED = ['at', 'describes', 'version'];
|
|
243
308
|
export function reconciled(held, source, fields) {
|
|
244
309
|
const ships = headed(source);
|