@deepseek-ai/dsh-app-boot 0.2.2-alpha.3 → 0.2.2-rc.2
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/README.i18n.yaml +4 -4
- package/README.md +4 -2
- package/README.zh.md +4 -2
- package/lib/index.js +37 -17
- package/lib/types/bundle-platform.d.ts +4 -2
- package/lib/types/bundle-platform.d.ts.map +1 -0
- package/lib/types/bundle-platform.js.map +1 -0
- package/lib/types/compatibility-preflight.d.ts.map +1 -0
- package/lib/types/compatibility-preflight.js.map +1 -0
- package/lib/types/config-schema/collect.d.ts.map +1 -0
- package/lib/types/config-schema/collect.js.map +1 -0
- package/lib/types/config-schema/document.d.ts.map +1 -0
- package/lib/types/config-schema/document.js.map +1 -0
- package/lib/types/config-schema/index.d.ts.map +1 -0
- package/lib/types/config-schema/index.js.map +1 -0
- package/lib/types/config-schema/native.d.ts.map +1 -0
- package/lib/types/config-schema/native.js.map +1 -0
- package/lib/types/config-schema/pattern.d.ts.map +1 -0
- package/lib/types/config-schema/pattern.js.map +1 -0
- package/lib/types/config-schema/projector.d.ts.map +1 -0
- package/lib/types/config-schema/projector.js.map +1 -0
- package/lib/types/config-schema/types.d.ts.map +1 -0
- package/lib/types/config-schema/types.js.map +1 -0
- package/lib/types/index.d.ts +1 -1
- package/lib/types/index.d.ts.map +1 -0
- package/lib/types/index.js.map +1 -0
- package/lib/types/package-meta.d.ts.map +1 -0
- package/lib/types/package-meta.js.map +1 -0
- package/lib/types/plugin-compatibility.d.ts.map +1 -0
- package/lib/types/plugin-compatibility.js.map +1 -0
- package/lib/types/profile-compatibility.d.ts.map +1 -0
- package/lib/types/profile-compatibility.js.map +1 -0
- package/lib/types/profile-context.d.ts.map +1 -0
- package/lib/types/profile-context.js.map +1 -0
- package/lib/types/profile-plugins.d.ts.map +1 -0
- package/lib/types/profile-plugins.js.map +1 -0
- package/lib/types/profile-resolution/legacy-links.d.ts.map +1 -0
- package/lib/types/profile-resolution/legacy-links.js.map +1 -0
- package/lib/types/profile-resolution/resolver.d.ts.map +1 -0
- package/lib/types/profile-resolution/resolver.js.map +1 -0
- package/lib/types/profile-resolution/service.d.ts.map +1 -0
- package/lib/types/profile-resolution/service.js.map +1 -0
- package/lib/types/profile-resolution/worker-bootstrap.d.ts.map +1 -0
- package/lib/types/profile-resolution/worker-bootstrap.js.map +1 -0
- package/lib/types/profile-sanitize.d.ts.map +1 -0
- package/lib/types/profile-sanitize.js.map +1 -0
- package/lib/types/profile.d.ts.map +1 -0
- package/lib/types/profile.js.map +1 -0
- package/lib/types/startup-diagnostics.d.ts.map +1 -0
- package/lib/types/startup-diagnostics.js.map +1 -0
- package/package.json +25 -21
- package/src/bundle-platform.ts +35 -0
- package/src/compatibility-preflight.ts +187 -0
- package/src/config-schema/collect.ts +249 -0
- package/src/config-schema/document.ts +169 -0
- package/src/config-schema/index.ts +36 -0
- package/src/config-schema/native.ts +16 -0
- package/src/config-schema/pattern.ts +62 -0
- package/src/config-schema/projector.ts +455 -0
- package/src/config-schema/types.ts +95 -0
- package/src/index.ts +1286 -0
- package/src/package-meta.ts +200 -0
- package/src/plugin-compatibility.ts +117 -0
- package/src/profile-compatibility.ts +141 -0
- package/src/profile-context.ts +85 -0
- package/src/profile-plugins.ts +133 -0
- package/src/profile-resolution/legacy-links.ts +33 -0
- package/src/profile-resolution/resolver.ts +1072 -0
- package/src/profile-resolution/service.ts +148 -0
- package/src/profile-resolution/worker-bootstrap.ts +12 -0
- package/src/profile-sanitize.ts +34 -0
- package/src/profile.ts +762 -0
- package/src/startup-diagnostics.ts +104 -0
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
/** Package metadata resolved through one runtime interception. */
|
|
2
|
+
|
|
3
|
+
import { existsSync, readFileSync } from 'node:fs'
|
|
4
|
+
import { createRequire } from 'node:module'
|
|
5
|
+
import { join } from 'node:path'
|
|
6
|
+
import { Service, type Context } from '@deepseek-ai/cordis'
|
|
7
|
+
import type { PluginLocalizedMeta } from '@deepseek-ai/dsh-package-manifest'
|
|
8
|
+
import {
|
|
9
|
+
barePackageName,
|
|
10
|
+
installRuntimeInterception,
|
|
11
|
+
registerWorkerResolution,
|
|
12
|
+
type RuntimeInterception,
|
|
13
|
+
} from './resolver.ts'
|
|
14
|
+
import { ProfileRuntimeResolution, type RuntimeResolution } from '../profile.ts'
|
|
15
|
+
import { readPluginMeta } from '../package-meta.ts'
|
|
16
|
+
|
|
17
|
+
declare module '@deepseek-ai/cordis' {
|
|
18
|
+
interface Context {
|
|
19
|
+
/** Deterministic package lookup for configured plugin specifiers. */
|
|
20
|
+
pluginPackages: PluginPackages
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/** The package that owns a resolved module. */
|
|
25
|
+
export interface PluginPackage {
|
|
26
|
+
/** Manifest package name. */
|
|
27
|
+
name: string
|
|
28
|
+
/** Manifest version when declared. */
|
|
29
|
+
version: string | undefined
|
|
30
|
+
/** Absolute package directory. */
|
|
31
|
+
dir: string
|
|
32
|
+
/** Absolute package.json path. */
|
|
33
|
+
manifestPath: string
|
|
34
|
+
/** Parsed manifest shared by metadata readers. */
|
|
35
|
+
manifest: Record<string, unknown>
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/** Optional runtime interception installed and owned by {@link PluginPackages}. */
|
|
39
|
+
export interface PluginPackagesConfig {
|
|
40
|
+
/** Complete package table; omit it to expose native package lookup only. */
|
|
41
|
+
resolution?: RuntimeResolution
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function readPackage(dir: string, fallbackName: string): PluginPackage | undefined {
|
|
45
|
+
const manifestPath = join(dir, 'package.json')
|
|
46
|
+
if (!existsSync(manifestPath)) return undefined
|
|
47
|
+
const manifest = JSON.parse(readFileSync(manifestPath, 'utf8')) as Record<string, unknown>
|
|
48
|
+
const name = manifest.name
|
|
49
|
+
const version = manifest.version
|
|
50
|
+
return {
|
|
51
|
+
name: typeof name === 'string' ? name : fallbackName,
|
|
52
|
+
version: typeof version === 'string' ? version : undefined,
|
|
53
|
+
dir,
|
|
54
|
+
manifestPath,
|
|
55
|
+
manifest,
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/** Package lookup shared by metadata consumers in one profile process. */
|
|
60
|
+
export class PluginPackages extends Service {
|
|
61
|
+
private packages = new Map<string, PluginPackage | undefined>()
|
|
62
|
+
private readonly interception: RuntimeInterception | undefined
|
|
63
|
+
private disposeWorkerResolution: (() => void) | undefined
|
|
64
|
+
private current: RuntimeResolution | undefined
|
|
65
|
+
|
|
66
|
+
constructor(ctx: Context, config: PluginPackagesConfig = {}) {
|
|
67
|
+
super(ctx, 'pluginPackages')
|
|
68
|
+
if (config.resolution === undefined) return
|
|
69
|
+
this.current = config.resolution
|
|
70
|
+
const interception = installRuntimeInterception(config.resolution)
|
|
71
|
+
this.disposeWorkerResolution = registerWorkerResolution(config.resolution)
|
|
72
|
+
this.interception = interception
|
|
73
|
+
ctx.effect(() => () => {
|
|
74
|
+
this.disposeWorkerResolution?.()
|
|
75
|
+
interception.dispose()
|
|
76
|
+
}, 'profile package resolution')
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/** The published runtime resolution, or `undefined` when Node resolves packages alone. */
|
|
80
|
+
get resolution(): RuntimeResolution | undefined {
|
|
81
|
+
return this.current
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Publish a complete successor generation for this process and subsequently created Workers.
|
|
86
|
+
* Profile mappings and local package names may be removed after their plugins stop; linked roots may also be removed.
|
|
87
|
+
* Retained profile mappings may change their declarer and version, but not their normalized directory or scope;
|
|
88
|
+
* installation mappings must remain unchanged. Publication does not unload modules or clear Node caches.
|
|
89
|
+
* @param successor - fully constructed generation accepted by {@link RuntimeInterception.replace}.
|
|
90
|
+
*/
|
|
91
|
+
replace(successor: RuntimeResolution): void {
|
|
92
|
+
if (this.interception === undefined) throw new Error('plugin-packages: runtime resolution is not installed')
|
|
93
|
+
this.interception.replace(successor)
|
|
94
|
+
this.current = successor
|
|
95
|
+
this.packages = new Map()
|
|
96
|
+
this.disposeWorkerResolution?.()
|
|
97
|
+
this.disposeWorkerResolution = registerWorkerResolution(successor)
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Publish the latest generation computed by the installed resolution through {@link replace}. Package contents
|
|
102
|
+
* and loaded modules are not reloaded.
|
|
103
|
+
* @throws when no resolution is installed, it is plain data rather than a {@link ProfileRuntimeResolution},
|
|
104
|
+
* reading the latest files fails, or the successor is rejected. A computed resolution without a profile can refresh.
|
|
105
|
+
*/
|
|
106
|
+
async refresh(): Promise<void> {
|
|
107
|
+
if (!(this.current instanceof ProfileRuntimeResolution)) {
|
|
108
|
+
throw new Error('plugin-packages: the installed runtime resolution cannot be recomputed')
|
|
109
|
+
}
|
|
110
|
+
this.replace(await this.current.computeLatestResolution())
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Locate the package named by a specifier without requiring a package export.
|
|
115
|
+
* @param specifier - module specifier whose package owns the requested module.
|
|
116
|
+
* @param parentURL - URL whose Node lookup order applies.
|
|
117
|
+
* @returns the parsed package, or undefined when no package owns the request.
|
|
118
|
+
*/
|
|
119
|
+
packageOf(specifier: string, parentURL: string): PluginPackage | undefined {
|
|
120
|
+
const name = barePackageName(specifier)
|
|
121
|
+
if (name === undefined) return undefined
|
|
122
|
+
const dir = this.interception === undefined
|
|
123
|
+
? packageDirFromParent(name, parentURL)
|
|
124
|
+
: this.interception.packageDir(name, parentURL)
|
|
125
|
+
if (dir === undefined) return undefined
|
|
126
|
+
const key = JSON.stringify({ dir, name })
|
|
127
|
+
if (!this.packages.has(key)) this.packages.set(key, readPackage(dir, name))
|
|
128
|
+
return this.packages.get(key)
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Read display metadata without loading or activating the target plugin.
|
|
133
|
+
* @param specifier - configured package module, including package subpaths.
|
|
134
|
+
* @param parentURL - owning Loader tree's resolution base.
|
|
135
|
+
* @returns local display metadata or its diagnostic; undefined for non-package requests or absent metadata.
|
|
136
|
+
*/
|
|
137
|
+
metaOf(specifier: string, parentURL: string): PluginLocalizedMeta | undefined {
|
|
138
|
+
return readPluginMeta(specifier, parentURL)
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
function packageDirFromParent(name: string, parentURL: string): string | undefined {
|
|
143
|
+
for (const searchPath of createRequire(parentURL).resolve.paths(name) as string[]) {
|
|
144
|
+
const candidate = join(searchPath, name)
|
|
145
|
+
if (existsSync(join(candidate, 'package.json'))) return candidate
|
|
146
|
+
}
|
|
147
|
+
return undefined
|
|
148
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/** Install the inherited runtime resolution in one Harness-owned Worker. */
|
|
2
|
+
|
|
3
|
+
import { getEnvironmentData } from 'node:worker_threads'
|
|
4
|
+
import { installRuntimeInterception } from './resolver.ts'
|
|
5
|
+
import type { RuntimeResolution } from '../profile.ts'
|
|
6
|
+
|
|
7
|
+
const registration = getEnvironmentData(
|
|
8
|
+
'@deepseek-ai/dsh-app-boot/profile-resolution',
|
|
9
|
+
) as {
|
|
10
|
+
resolution: RuntimeResolution
|
|
11
|
+
} | undefined
|
|
12
|
+
if (registration !== undefined) installRuntimeInterception(registration.resolution)
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/** Filesystem recovery for callers that own profile shutdown and write exclusion. */
|
|
2
|
+
|
|
3
|
+
import { existsSync, renameSync } from 'node:fs'
|
|
4
|
+
import { join } from 'node:path'
|
|
5
|
+
import { PROFILE_PATCH_FILENAME, readProfileManifest } from './profile.ts'
|
|
6
|
+
import { writeProfileBundles } from './profile-plugins.ts'
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Back up the profile patch and retain only the caller's recovery bundles.
|
|
10
|
+
* The caller must stop the profile and exclude concurrent profile writes.
|
|
11
|
+
* Installed packages and other manifest fields are preserved; patches are never parsed.
|
|
12
|
+
* Failures propagate and may leave completed changes in place for a retry.
|
|
13
|
+
* @param binName - Diagnostic prefix for invalid profile manifests.
|
|
14
|
+
* @param profileDir - Profile directory to recover without loading its plugins.
|
|
15
|
+
* @param bundles - Ordered bundles to enable after recovery.
|
|
16
|
+
* @returns Backup path with a Unix millisecond timestamp and optional collision ordinal, or undefined if absent.
|
|
17
|
+
*/
|
|
18
|
+
export function sanitizeProfile(binName: string, profileDir: string, bundles: readonly string[]): string | undefined {
|
|
19
|
+
const manifest = existsSync(join(profileDir, 'package.json')) ? readProfileManifest(binName, profileDir) : undefined
|
|
20
|
+
const patchPath = join(profileDir, PROFILE_PATCH_FILENAME)
|
|
21
|
+
const backupBase = `${patchPath}.bak-${Date.now()}`
|
|
22
|
+
let backupPath: string | undefined = backupBase
|
|
23
|
+
let ordinal = 0
|
|
24
|
+
// Caller-owned write exclusion keeps the selected destination absent until rename.
|
|
25
|
+
while (existsSync(backupPath)) backupPath = `${backupBase}-${++ordinal}`
|
|
26
|
+
try {
|
|
27
|
+
renameSync(patchPath, backupPath)
|
|
28
|
+
} catch (error) {
|
|
29
|
+
if (!(error instanceof Error && 'code' in error && error.code === 'ENOENT')) throw error
|
|
30
|
+
backupPath = undefined
|
|
31
|
+
}
|
|
32
|
+
if (manifest !== undefined) writeProfileBundles(profileDir, manifest, bundles)
|
|
33
|
+
return backupPath
|
|
34
|
+
}
|