@qlzt/dsh-app-boot 0.0.0-stage → 0.2.1-alpha.3
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/LICENSE +21 -0
- package/README.i18n.yaml +73 -0
- package/README.md +221 -2
- package/README.zh.md +222 -0
- package/lib/index.js +4293 -0
- package/lib/types/compatibility-preflight.d.ts +26 -0
- package/lib/types/config-schema/collect.d.ts +16 -0
- package/lib/types/config-schema/document.d.ts +13 -0
- package/lib/types/config-schema/index.d.ts +19 -0
- package/lib/types/config-schema/native.d.ts +9 -0
- package/lib/types/config-schema/pattern.d.ts +8 -0
- package/lib/types/config-schema/projector.d.ts +20 -0
- package/lib/types/config-schema/types.d.ts +95 -0
- package/lib/types/index.d.ts +327 -0
- package/lib/types/official-bundle-packages.d.ts +4 -0
- package/lib/types/official-bundles.d.ts +12 -0
- package/lib/types/official-bundles.generated.d.ts +5 -0
- package/lib/types/package-meta.d.ts +29 -0
- package/lib/types/plugin-compatibility.d.ts +35 -0
- package/lib/types/profile-compatibility.d.ts +50 -0
- package/lib/types/profile-context.d.ts +51 -0
- package/lib/types/profile-plugins.d.ts +60 -0
- package/lib/types/profile-resolution/legacy-links.d.ts +15 -0
- package/lib/types/profile-resolution/resolver.d.ts +45 -0
- package/lib/types/profile-resolution/service.d.ts +66 -0
- package/lib/types/profile-resolution/worker-bootstrap.d.ts +3 -0
- package/lib/types/profile-sanitize.d.ts +13 -0
- package/lib/types/profile.d.ts +277 -0
- package/lib/worker/profile-resolution-bootstrap.js +728 -0
- package/package.json +65 -4
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/** Independent profile metadata; neither package manifests nor Cordis patches carry grants. */
|
|
2
|
+
export declare const PROFILE_COMPATIBILITY_FILENAME = "compatibility.json";
|
|
3
|
+
/** Test whether an exemption names a canonical exact SemVer, including build metadata.
|
|
4
|
+
* @param value Version supplied by a manifest or user.
|
|
5
|
+
* @returns False for ranges, prefixes, whitespace, and malformed versions.
|
|
6
|
+
*/
|
|
7
|
+
export declare function isExactPluginVersion(value: string): boolean;
|
|
8
|
+
/** Validate one explicit exemption without granting it.
|
|
9
|
+
* @param packageVersion Exact npm package-name@version, never an installation spec or range.
|
|
10
|
+
* @param runtimeVersion Exact DSH version, including prerelease and build metadata.
|
|
11
|
+
* @throws When either identity is not canonical.
|
|
12
|
+
*/
|
|
13
|
+
export declare function validatePluginVersionExemption(packageVersion: string, runtimeVersion: string): void;
|
|
14
|
+
/** What one profile's compatibility file currently authorizes, and what is wrong with it. */
|
|
15
|
+
export interface ProfileCompatibility {
|
|
16
|
+
/** Accepted exact package-name@version keys mapped to their allowed DSH versions. */
|
|
17
|
+
readonly exemptions: Record<string, string[]>;
|
|
18
|
+
/** Human-readable problems; empty when every record was accepted. */
|
|
19
|
+
readonly warnings: string[];
|
|
20
|
+
/**
|
|
21
|
+
* Whether the file holds nothing this reader rejected, so a grant or revocation may rewrite it.
|
|
22
|
+
* A false value means writing would discard content the user must repair by hand.
|
|
23
|
+
*/
|
|
24
|
+
readonly rewritable: boolean;
|
|
25
|
+
}
|
|
26
|
+
/** Read the profile's independent compatibility file without loading plugins.
|
|
27
|
+
* A missing file authorizes nothing. An unreadable or unparsable file authorizes nothing and is
|
|
28
|
+
* reported instead of failing, so a bad file can never make the profile unusable; rejected records
|
|
29
|
+
* are skipped while the remaining valid ones still apply.
|
|
30
|
+
* @param profileDir Absolute profile directory.
|
|
31
|
+
* @returns Accepted exemptions plus every problem found; no manifest fallback is used.
|
|
32
|
+
*/
|
|
33
|
+
export declare function readProfileCompatibility(profileDir: string): ProfileCompatibility;
|
|
34
|
+
/** Read only the accepted exemptions of a profile.
|
|
35
|
+
* @param profileDir Absolute profile directory.
|
|
36
|
+
* @returns Exact package-name@version keys mapped to their allowed DSH versions.
|
|
37
|
+
*/
|
|
38
|
+
export declare function readProfileVersionExemptions(profileDir: string): Record<string, string[]>;
|
|
39
|
+
/** Persist one informed grant or revocation under the compatibility file's own lock.
|
|
40
|
+
* @param profileDir Profile directory; no package manifest is created or modified.
|
|
41
|
+
* @param packageVersion Exact manifest package-name@version.
|
|
42
|
+
* @param runtimeVersion Exact DSH version; grants must name the current runtime, revocations may name historical ones.
|
|
43
|
+
* @param enabled Whether to grant rather than revoke.
|
|
44
|
+
* @param acceptRisk Required true for grants after explicit acknowledgement of possible crashes or data loss.
|
|
45
|
+
* @returns After the atomic write. Existing plugin instances are not reloaded by this operation.
|
|
46
|
+
* @throws For invalid identities, missing consent, a stale runtime, or a file the reader rejected,
|
|
47
|
+
* which the user must repair by hand because rewriting it would discard their content.
|
|
48
|
+
*/
|
|
49
|
+
export declare function setProfileVersionExemption(profileDir: string, packageVersion: string, runtimeVersion: string, enabled: boolean, acceptRisk: boolean): Promise<void>;
|
|
50
|
+
//# sourceMappingURL=profile-compatibility.d.ts.map
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { type Profile } from './profile.ts';
|
|
2
|
+
import type { PatchOptions } from '@deepseek-ai/cordis-plugin-include';
|
|
3
|
+
/** Application-owned package manager executable; environment applies only to package operations. */
|
|
4
|
+
export interface ProfilePnpmInvocation {
|
|
5
|
+
readonly command: string;
|
|
6
|
+
readonly args: readonly string[];
|
|
7
|
+
readonly env: Readonly<Record<string, string>>;
|
|
8
|
+
}
|
|
9
|
+
/** Current profile facts; scheduling and mutation belong to their callers. */
|
|
10
|
+
export interface ProfileContext {
|
|
11
|
+
readonly name: string;
|
|
12
|
+
/** Packaged applications supply their bundled runtime instead of a PATH executable. */
|
|
13
|
+
readonly packageManager?: ProfilePnpmInvocation;
|
|
14
|
+
readonly dir: string;
|
|
15
|
+
readonly patchPath: string;
|
|
16
|
+
readonly installAnchor: string;
|
|
17
|
+
readonly cwd: string;
|
|
18
|
+
readonly home: string;
|
|
19
|
+
/** Bundle packages used to start this process, before any persisted edits. */
|
|
20
|
+
readonly startedBundles: readonly string[];
|
|
21
|
+
/** Parsed command-line overlays, applied above profile and home patches. */
|
|
22
|
+
readonly overlays: readonly PatchOptions[];
|
|
23
|
+
/** Launch-time DSH_TELEMETRY_DISABLED value; any non-empty value opts out. */
|
|
24
|
+
readonly telemetryDisabledEnv: string | undefined;
|
|
25
|
+
}
|
|
26
|
+
declare module '@deepseek-ai/cordis' {
|
|
27
|
+
interface Context {
|
|
28
|
+
/** Present only in a profile launched by dsh. */
|
|
29
|
+
profileContext: ProfileContext;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Resolve the telemetry opt-out switch into its boot patch. ANY non-empty
|
|
34
|
+
* value (including `'0'`/`'false'`) disables: a privacy switch prefers
|
|
35
|
+
* off-by-mistake over on-by-mistake. A composition without the telemetry row
|
|
36
|
+
* exports nothing, so the switch is then trivially satisfied and no patch is
|
|
37
|
+
* generated — custom profiles need not mount telemetry to run with the
|
|
38
|
+
* switch set.
|
|
39
|
+
* @param disabledEnv - the raw `DSH_TELEMETRY_DISABLED` value (`undefined` when unset).
|
|
40
|
+
* @param hasRow - whether the composition carries the telemetry row.
|
|
41
|
+
* @returns the disable patch, or `undefined` when no hard-disable patch is required.
|
|
42
|
+
*/
|
|
43
|
+
export declare function resolveTelemetryPatch(disabledEnv: string | undefined, hasRow: boolean): PatchOptions | undefined;
|
|
44
|
+
/** Read current bundle and user layers with the launch-time overlays.
|
|
45
|
+
* @param binName Diagnostic prefix for malformed or missing configuration.
|
|
46
|
+
* @param context Data supplied by the profile launcher.
|
|
47
|
+
* @param initialProfile Already loaded startup profile; omitted reads the current files.
|
|
48
|
+
* @returns Detached ordered patches; this function does not update the Loader.
|
|
49
|
+
*/
|
|
50
|
+
export declare function readProfilePatches(binName: string, context: ProfileContext, initialProfile?: Profile): PatchOptions[];
|
|
51
|
+
//# sourceMappingURL=profile-context.d.ts.map
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/** Installed profile dependencies and their bundle activation after package-manager operations. */
|
|
2
|
+
import { type ProfileManifest } from './profile.ts';
|
|
3
|
+
/** Profile directory and installation used by the shared bundle resolver. */
|
|
4
|
+
export interface ProfilePluginLocation {
|
|
5
|
+
/** Diagnostic prefix for profile manifest failures. */
|
|
6
|
+
readonly binName: string;
|
|
7
|
+
/** Profile package directory managed by pnpm. */
|
|
8
|
+
readonly profileDir: string;
|
|
9
|
+
/** Absolute package.json path of the owning dsh installation. */
|
|
10
|
+
readonly installAnchor: string;
|
|
11
|
+
}
|
|
12
|
+
/** One dependency under its package-manager key, including npm aliases. */
|
|
13
|
+
export interface ProfilePluginDependency {
|
|
14
|
+
/** Dependency key used in package.json and the bundle list. */
|
|
15
|
+
readonly name: string;
|
|
16
|
+
/** Installed version, or the dependency spec when installed metadata is unavailable. */
|
|
17
|
+
readonly version: string;
|
|
18
|
+
/** Whether the package selected by the bundle resolver declares a patch. */
|
|
19
|
+
readonly bundle: boolean;
|
|
20
|
+
/** Whether the dependency appears in the profile's active bundle list. */
|
|
21
|
+
readonly enabled: boolean;
|
|
22
|
+
}
|
|
23
|
+
/** Profile manifest and dependencies in manifest order. */
|
|
24
|
+
export interface ProfilePluginInventory {
|
|
25
|
+
readonly manifest: ProfileManifest;
|
|
26
|
+
readonly dependencies: readonly ProfilePluginDependency[];
|
|
27
|
+
}
|
|
28
|
+
/** Result of reconciling bundle activation after a successful package operation. */
|
|
29
|
+
export interface ProfilePluginReconciliation {
|
|
30
|
+
readonly plugins: ProfilePluginInventory;
|
|
31
|
+
/** Newly added ordinary dependencies, for optional caller-owned diagnostics. */
|
|
32
|
+
readonly addedPlainDependencies: readonly string[];
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Read installed versions and bundle declarations without requiring loadable plugin code.
|
|
36
|
+
* Missing or unreadable installed metadata leaves the dependency visible for repair or removal.
|
|
37
|
+
* @param location - profile and installation resolution inputs.
|
|
38
|
+
* @returns dependency records in package.json order and the profile manifest.
|
|
39
|
+
*/
|
|
40
|
+
export declare function readProfilePlugins(location: ProfilePluginLocation): ProfilePluginInventory;
|
|
41
|
+
/**
|
|
42
|
+
* Write a bundle list while preserving the supplied profile's other metadata.
|
|
43
|
+
* @param profileDir - directory whose package.json is updated.
|
|
44
|
+
* @param manifest - current profile manifest, read after the package operation when applicable.
|
|
45
|
+
* @param bundles - ordered active bundle names, including any template entries.
|
|
46
|
+
* @returns the written manifest.
|
|
47
|
+
*/
|
|
48
|
+
export declare function writeProfileBundles(profileDir: string, manifest: ProfileManifest, bundles: readonly string[]): ProfileManifest;
|
|
49
|
+
/**
|
|
50
|
+
* Reconcile installed bundle declarations after a successful package-manager operation.
|
|
51
|
+
* Dependency-managed entries disappear when removed or when their package loses its declaration;
|
|
52
|
+
* template entries retain their order and duplicates. New bundle dependencies activate automatically.
|
|
53
|
+
* @param options - location, inventory captured before pnpm, and whether explicitly disabled bundles remain disabled.
|
|
54
|
+
* @returns updated inventory and newly added ordinary dependencies for caller-owned warnings.
|
|
55
|
+
*/
|
|
56
|
+
export declare function reconcileProfilePlugins(options: ProfilePluginLocation & {
|
|
57
|
+
readonly before: ProfilePluginInventory;
|
|
58
|
+
readonly preserveDisabled: boolean;
|
|
59
|
+
}): ProfilePluginReconciliation;
|
|
60
|
+
//# sourceMappingURL=profile-plugins.d.ts.map
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/** Package directory and resource canonicalization through the active runtime carrier's filesystem. */
|
|
2
|
+
/**
|
|
3
|
+
* Resolve a directory through the active carrier's filesystem implementation.
|
|
4
|
+
* @param path - directory path to canonicalize.
|
|
5
|
+
* @returns the canonical directory path.
|
|
6
|
+
*/
|
|
7
|
+
export declare function realModuleDirectory(path: string): string;
|
|
8
|
+
/** Canonicalize a module resource, preserving physical file aliases.
|
|
9
|
+
* SEA archive files are symlink-free and support stat and reads, while their containing directories support realpath.
|
|
10
|
+
* @param path Existing module resource path.
|
|
11
|
+
* @returns Canonical resource path under the active carrier's filesystem.
|
|
12
|
+
* @throws When the resource or its directory cannot be inspected or resolved.
|
|
13
|
+
*/
|
|
14
|
+
export declare function realModuleFile(path: string): string;
|
|
15
|
+
//# sourceMappingURL=legacy-links.d.ts.map
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/** In-memory profile package routing for Node's default ESM and CommonJS loaders. */
|
|
2
|
+
import type { RuntimeResolution } from '../profile.ts';
|
|
3
|
+
/** Active interception in one Node isolate. */
|
|
4
|
+
export interface RuntimeInterception {
|
|
5
|
+
/**
|
|
6
|
+
* Locate a bare package without requiring one of its exports.
|
|
7
|
+
* A package subpath selects its package directory without resolving or validating the requested file.
|
|
8
|
+
* @param specifier - bare package or package-subpath specifier.
|
|
9
|
+
* @param parentURL - file URL whose lookup order applies.
|
|
10
|
+
* @returns selected package directory, or undefined when it is absent.
|
|
11
|
+
*/
|
|
12
|
+
packageDir(specifier: string, parentURL: string): string | undefined;
|
|
13
|
+
/**
|
|
14
|
+
* Atomically publish a complete successor and fresh caches. Profile-scoped mappings, local names, and linked
|
|
15
|
+
* roots may be removed; removed roots stop intercepting uncovered directories. Existing modules and Node caches
|
|
16
|
+
* remain intact, so callers remove a package only after its plugins stop.
|
|
17
|
+
* A retained profile mapping may change its declarer if its normalized directory, version, and scope stay unchanged.
|
|
18
|
+
* @param successor - fully constructed generation retaining the installation mappings.
|
|
19
|
+
* @throws when the profile scope, a retained directory, version, scope, or installation declarer changes;
|
|
20
|
+
* an installation mapping is removed; a new local name overrides an existing mapping; or a previously published
|
|
21
|
+
* link name selects a different real directory.
|
|
22
|
+
*/
|
|
23
|
+
replace(successor: RuntimeResolution): void;
|
|
24
|
+
/** Restore the native resolver methods. Interceptions dispose in reverse order. */
|
|
25
|
+
dispose(): void;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Split a bare request into its package name without allocating path segments.
|
|
29
|
+
* @param request - module specifier to classify.
|
|
30
|
+
* @returns the bare package name, or undefined for non-package requests.
|
|
31
|
+
*/
|
|
32
|
+
export declare function barePackageName(request: string): string | undefined;
|
|
33
|
+
/**
|
|
34
|
+
* Install one runtime resolution as the interception on Node's default ESM and CommonJS resolvers.
|
|
35
|
+
* @param resolution - complete package table and profile scope.
|
|
36
|
+
* @returns an interception that publishes a successor or restores the native methods.
|
|
37
|
+
*/
|
|
38
|
+
export declare function installRuntimeInterception(resolution: RuntimeResolution): RuntimeInterception;
|
|
39
|
+
/**
|
|
40
|
+
* Publish one runtime resolution for Harness-owned Workers.
|
|
41
|
+
* @param resolution - complete package table and profile scope.
|
|
42
|
+
* @returns a disposer restoring the previous thread environment data.
|
|
43
|
+
*/
|
|
44
|
+
export declare function registerWorkerResolution(resolution: RuntimeResolution): () => void;
|
|
45
|
+
//# sourceMappingURL=resolver.d.ts.map
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/** Package metadata resolved through one runtime interception. */
|
|
2
|
+
import { Service, type Context } from '@deepseek-ai/cordis';
|
|
3
|
+
import type { PluginLocalizedMeta } from '@qlzt/dsh-package-manifest';
|
|
4
|
+
import { type RuntimeResolution } from '../profile.ts';
|
|
5
|
+
declare module '@deepseek-ai/cordis' {
|
|
6
|
+
interface Context {
|
|
7
|
+
/** Deterministic package lookup for configured plugin specifiers. */
|
|
8
|
+
pluginPackages: PluginPackages;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
/** The package that owns a resolved module. */
|
|
12
|
+
export interface PluginPackage {
|
|
13
|
+
/** Manifest package name. */
|
|
14
|
+
name: string;
|
|
15
|
+
/** Manifest version when declared. */
|
|
16
|
+
version: string | undefined;
|
|
17
|
+
/** Absolute package directory. */
|
|
18
|
+
dir: string;
|
|
19
|
+
/** Absolute package.json path. */
|
|
20
|
+
manifestPath: string;
|
|
21
|
+
/** Parsed manifest shared by metadata readers. */
|
|
22
|
+
manifest: Record<string, unknown>;
|
|
23
|
+
}
|
|
24
|
+
/** Optional runtime interception installed and owned by {@link PluginPackages}. */
|
|
25
|
+
export interface PluginPackagesConfig {
|
|
26
|
+
/** Complete package table; omit it to expose native package lookup only. */
|
|
27
|
+
resolution?: RuntimeResolution;
|
|
28
|
+
}
|
|
29
|
+
/** Package lookup shared by metadata consumers in one profile process. */
|
|
30
|
+
export declare class PluginPackages extends Service {
|
|
31
|
+
private packages;
|
|
32
|
+
private readonly interception;
|
|
33
|
+
private disposeWorkerResolution;
|
|
34
|
+
private current;
|
|
35
|
+
constructor(ctx: Context, config?: PluginPackagesConfig);
|
|
36
|
+
/**
|
|
37
|
+
* Publish a complete successor generation for this process and subsequently created Workers.
|
|
38
|
+
* Profile mappings and local package names may be removed after their plugins stop; linked roots may also be removed.
|
|
39
|
+
* Retained profile mappings may change their declarer, but not their normalized directory, version, or scope;
|
|
40
|
+
* installation mappings must remain unchanged. Publication does not unload modules or clear Node caches.
|
|
41
|
+
* @param successor - fully constructed generation accepted by {@link RuntimeInterception.replace}.
|
|
42
|
+
*/
|
|
43
|
+
replace(successor: RuntimeResolution): void;
|
|
44
|
+
/**
|
|
45
|
+
* Publish the latest generation computed by the installed resolution through {@link replace}. Package contents
|
|
46
|
+
* and loaded modules are not reloaded.
|
|
47
|
+
* @throws when no resolution is installed, it is plain data rather than a {@link ProfileRuntimeResolution},
|
|
48
|
+
* reading the latest files fails, or the successor is rejected. A computed resolution without a profile can refresh.
|
|
49
|
+
*/
|
|
50
|
+
refresh(): Promise<void>;
|
|
51
|
+
/**
|
|
52
|
+
* Locate the package named by a specifier without requiring a package export.
|
|
53
|
+
* @param specifier - module specifier whose package owns the requested module.
|
|
54
|
+
* @param parentURL - URL whose Node lookup order applies.
|
|
55
|
+
* @returns the parsed package, or undefined when no package owns the request.
|
|
56
|
+
*/
|
|
57
|
+
packageOf(specifier: string, parentURL: string): PluginPackage | undefined;
|
|
58
|
+
/**
|
|
59
|
+
* Read display metadata without loading or activating the target plugin.
|
|
60
|
+
* @param specifier - configured package module, including package subpaths.
|
|
61
|
+
* @param parentURL - owning Loader tree's resolution base.
|
|
62
|
+
* @returns local display metadata or its diagnostic; undefined for non-package requests or absent metadata.
|
|
63
|
+
*/
|
|
64
|
+
metaOf(specifier: string, parentURL: string): PluginLocalizedMeta | undefined;
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=service.d.ts.map
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/** Filesystem recovery for callers that own profile shutdown and write exclusion. */
|
|
2
|
+
/**
|
|
3
|
+
* Back up the profile patch and retain only the caller's recovery bundles.
|
|
4
|
+
* The caller must stop the profile and exclude concurrent profile writes.
|
|
5
|
+
* Installed packages and other manifest fields are preserved; patches are never parsed.
|
|
6
|
+
* Failures propagate and may leave completed changes in place for a retry.
|
|
7
|
+
* @param binName - Diagnostic prefix for invalid profile manifests.
|
|
8
|
+
* @param profileDir - Profile directory to recover without loading its plugins.
|
|
9
|
+
* @param bundles - Ordered bundles to enable after recovery.
|
|
10
|
+
* @returns Backup path with a Unix millisecond timestamp and optional collision ordinal, or undefined if absent.
|
|
11
|
+
*/
|
|
12
|
+
export declare function sanitizeProfile(binName: string, profileDir: string, bundles: readonly string[]): string | undefined;
|
|
13
|
+
//# sourceMappingURL=profile-sanitize.d.ts.map
|
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Profile discovery, initialization, and patch-layer composition for the
|
|
3
|
+
* `dsh --profile` launcher family.
|
|
4
|
+
*
|
|
5
|
+
* A profile is a directory under `$DSH_HOME/profiles/<name>` holding a
|
|
6
|
+
* `package.json` (out-of-tree plugin dependencies plus the profile manifest
|
|
7
|
+
* `dsh.profile` with its ordered `bundles` list) and a `cordis.patch.yml`
|
|
8
|
+
* (the user's own patch layer, applied after every bundle layer). Bundles are
|
|
9
|
+
* npm packages whose manifest declares
|
|
10
|
+
* `"dsh": { "bundle": { "patch": "./cordis.patch.yml" } }` (one file, or an
|
|
11
|
+
* ordered list of files); the tree is composed by applying each bundle's patch
|
|
12
|
+
* lists in `dsh.profile.bundles` order over an empty entry list, then the
|
|
13
|
+
* profile's own patches, then any launcher layers (`--patch` files and
|
|
14
|
+
* flag-derived patches).
|
|
15
|
+
*
|
|
16
|
+
* Module resolution is two-anchor by construction: a bundle name resolves
|
|
17
|
+
* first from the dsh installation (the launcher's own package), then from the
|
|
18
|
+
* profile directory. Pnpm-managed entries in the profile's `node_modules`
|
|
19
|
+
* resolve first. The runtime resolution supplies packages carried by the
|
|
20
|
+
* installation and selected bundles to Node's ESM and CommonJS resolvers.
|
|
21
|
+
* @module @qlzt/dsh-app-boot/profile
|
|
22
|
+
*/
|
|
23
|
+
import type { EntryOptions } from '@deepseek-ai/cordis-plugin-loader';
|
|
24
|
+
import { type PatchOptions } from '@deepseek-ai/cordis-plugin-include';
|
|
25
|
+
import type { DshBundleManifest, DshPackageManifest } from '@qlzt/dsh-package-manifest';
|
|
26
|
+
/** Directory under the Harness home holding every profile. */
|
|
27
|
+
export declare const PROFILES_DIR = "profiles";
|
|
28
|
+
/** The user patch layer inside a profile directory (hot-reloaded on long-lived surfaces). */
|
|
29
|
+
export declare const PROFILE_PATCH_FILENAME = "cordis.patch.yml";
|
|
30
|
+
/** Installation-owned defaults used when a shipped profile is first opened. */
|
|
31
|
+
export interface ProfileTemplate {
|
|
32
|
+
/** Ordered bundle layer list. */
|
|
33
|
+
bundles: readonly string[];
|
|
34
|
+
}
|
|
35
|
+
/** Package metadata accepted by the profile reader; local profiles need no published identity. */
|
|
36
|
+
export type ProfileManifest = Partial<DshPackageManifest>;
|
|
37
|
+
/**
|
|
38
|
+
* The patch files a bundle declares, as written: one file for a string
|
|
39
|
+
* `patch`, the listed files in order for an array.
|
|
40
|
+
* @param bundle - the bundle's `dsh.bundle` declaration, as read from package.json.
|
|
41
|
+
* @returns the package-relative patch file paths in application order.
|
|
42
|
+
* @throws {Error} when `patch` is neither a string nor a list of strings.
|
|
43
|
+
*/
|
|
44
|
+
export declare function bundlePatchFiles(bundle: DshBundleManifest): string[];
|
|
45
|
+
/**
|
|
46
|
+
* Resolve a bundle declaration to its ordered absolute patch files.
|
|
47
|
+
* @param packageDir - absolute directory of the bundle package.
|
|
48
|
+
* @param bundle - the bundle's `dsh.bundle` declaration, as read from package.json.
|
|
49
|
+
* @returns the absolute patch file paths in application order.
|
|
50
|
+
* @throws {Error} when `patch` is neither a string nor a list of strings.
|
|
51
|
+
*/
|
|
52
|
+
export declare function bundlePatchPaths(packageDir: string, bundle: DshBundleManifest): string[];
|
|
53
|
+
/** One resolved bundle layer of a profile. */
|
|
54
|
+
export interface ProfileLayer {
|
|
55
|
+
/** The bundle's package name, as listed in `dsh.profile.bundles`. */
|
|
56
|
+
packageName: string;
|
|
57
|
+
/** Absolute directory of the resolved bundle package. */
|
|
58
|
+
packageDir: string;
|
|
59
|
+
/** Absolute paths of the bundle's patch files, in application order. */
|
|
60
|
+
patchPaths: readonly string[];
|
|
61
|
+
/** The parsed patch lists of every file, concatenated in application order. */
|
|
62
|
+
patches: PatchOptions[];
|
|
63
|
+
}
|
|
64
|
+
/** A loaded profile: resolved bundle layers plus the user's own patch layer. */
|
|
65
|
+
export interface Profile {
|
|
66
|
+
/** The profile name (its directory basename). */
|
|
67
|
+
name: string;
|
|
68
|
+
/** Absolute profile directory. */
|
|
69
|
+
dir: string;
|
|
70
|
+
/** Bundle layers in `dsh.profile.bundles` order. */
|
|
71
|
+
layers: ProfileLayer[];
|
|
72
|
+
/** Absolute path of the profile's own patch file. */
|
|
73
|
+
patchPath: string;
|
|
74
|
+
/** The profile's own patches; empty when the file is absent. */
|
|
75
|
+
patches: PatchOptions[];
|
|
76
|
+
/** Selected bundles that contributed no layer, in `dsh.profile.bundles` order, with why. */
|
|
77
|
+
skippedBundles: SkippedBundle[];
|
|
78
|
+
}
|
|
79
|
+
/** A selected bundle the profile could not load, or whose own DSH peers the profile does not exempt. */
|
|
80
|
+
export interface SkippedBundle {
|
|
81
|
+
/** The bundle's package name from `dsh.profile.bundles`. */
|
|
82
|
+
packageName: string;
|
|
83
|
+
/** The resolution, manifest, compatibility, or patch-loading failure. */
|
|
84
|
+
reason: string;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Print each skipped bundle once; loading never prints, so launchers call this once per start.
|
|
88
|
+
* @param binName - the diagnostic prefix.
|
|
89
|
+
* @param profile - the loaded profile.
|
|
90
|
+
*/
|
|
91
|
+
export declare function reportSkippedBundles(binName: string, profile: Pick<Profile, 'skippedBundles'>): void;
|
|
92
|
+
/** One package the runtime resolution supplies at the interception layer. */
|
|
93
|
+
export interface RuntimeResolutionEntry {
|
|
94
|
+
/** Bare package name. */
|
|
95
|
+
readonly name: string;
|
|
96
|
+
/** Package directory selected by the existing dependency traversal. */
|
|
97
|
+
readonly packageDir: string;
|
|
98
|
+
/** Selected package version when its manifest declares one. */
|
|
99
|
+
readonly version: string | undefined;
|
|
100
|
+
/** Manifest whose dependency edge selected this package. */
|
|
101
|
+
readonly declarer: string;
|
|
102
|
+
/** Whether every profile or only the active profile receives this entry. */
|
|
103
|
+
readonly scope: 'installation' | 'profile';
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* A profile node_modules entry linked to a directory outside the shared profiles tree and the active profile.
|
|
107
|
+
* Importers below `realPath` use Node's real ancestor chain, with peer mappings read at each node_modules position.
|
|
108
|
+
*/
|
|
109
|
+
export interface LinkedRoot {
|
|
110
|
+
/** Package name of the profile `node_modules` entry, including its scope. */
|
|
111
|
+
readonly name: string;
|
|
112
|
+
/** Real directory outside the shared profiles tree and active profile; a package.json is optional. */
|
|
113
|
+
readonly realPath: string;
|
|
114
|
+
}
|
|
115
|
+
/** Complete immutable package table for one profile launch. */
|
|
116
|
+
export interface RuntimeResolution {
|
|
117
|
+
/** Directory containing every profile; its node_modules is the interception layer. */
|
|
118
|
+
readonly profilesDir: string;
|
|
119
|
+
/** Active profile directory, when profile-scope entries were included. */
|
|
120
|
+
readonly profileDir: string | undefined;
|
|
121
|
+
/** Profile-declared packages installed in the profile's own node_modules. */
|
|
122
|
+
readonly localPackageNames: readonly string[];
|
|
123
|
+
/** Installation-scope entries followed by profile-scope entries in precedence order. */
|
|
124
|
+
readonly entries: readonly RuntimeResolutionEntry[];
|
|
125
|
+
/** Active profile links to external directories, sorted by name. */
|
|
126
|
+
readonly linkedRoots: readonly LinkedRoot[];
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Resolve a profile's directory under the Harness home.
|
|
130
|
+
* @param name - the profile name (`dsh --profile <name>`).
|
|
131
|
+
* @param home - the Harness home; defaults to {@link resolveDshHome}.
|
|
132
|
+
* @returns the absolute profile directory (which may not exist yet).
|
|
133
|
+
*/
|
|
134
|
+
export declare function resolveProfileDir(name: string, home?: string): string;
|
|
135
|
+
/** The shipped profile templates auto-initialized on first use, by name. */
|
|
136
|
+
export declare const PROFILE_TEMPLATES: Record<string, ProfileTemplate>;
|
|
137
|
+
/** The bundle list a `dsh plugin` init uses for a name with no shipped template. */
|
|
138
|
+
export declare const DEFAULT_PROFILE_BUNDLES: readonly string[];
|
|
139
|
+
/**
|
|
140
|
+
* The bundles the dsh installation ships for a person to switch on: each a
|
|
141
|
+
* runtime dependency of the installation that declares `dsh.bundle.patch`,
|
|
142
|
+
* an `icon`, and `./locale/*.json` display metadata, selected by no shipped
|
|
143
|
+
* template, and offered switched off by the plugin manager
|
|
144
|
+
* ([rationale](../../../../.agents/notes/implemented/process/2026-09-15-shipped-optional-bundles.md),
|
|
145
|
+
* [admission](../../../../.agents/notes/implemented/architecture/2026-09-21-experimental-capabilities-as-optional-bundles.md)).
|
|
146
|
+
*/
|
|
147
|
+
export declare const OPTIONAL_BUNDLES: readonly string[];
|
|
148
|
+
/**
|
|
149
|
+
* Initialize a profile directory: manifest, empty user patch layer, and the
|
|
150
|
+
* pnpm settings out-of-tree plugins need. Existing files are never touched,
|
|
151
|
+
* so re-running is a no-op on an initialized profile.
|
|
152
|
+
* @param dir - the profile directory from {@link resolveProfileDir}.
|
|
153
|
+
* @param bundles - the initial `dsh.profile.bundles` layer list.
|
|
154
|
+
*/
|
|
155
|
+
export declare function initProfile(dir: string, bundles: readonly string[]): void;
|
|
156
|
+
/**
|
|
157
|
+
* Remove the package projections a link-backend launch left in a profile.
|
|
158
|
+
* Only symlinks under the profile's `node_modules` whose target lies inside
|
|
159
|
+
* `<profile>/.dsh-module-fallback/node_modules` are unlinked, then that directory is removed;
|
|
160
|
+
* pnpm-installed packages and every other symlink stay. A profile without the directory is untouched.
|
|
161
|
+
* @param dir - the profile directory.
|
|
162
|
+
*/
|
|
163
|
+
export declare function removeLinkProjections(dir: string): void;
|
|
164
|
+
/** Inputs for {@link createRuntimeResolution}. */
|
|
165
|
+
export interface RuntimeResolutionOptions {
|
|
166
|
+
/** Absolute package.json path of the running dsh installation. */
|
|
167
|
+
installAnchor: string;
|
|
168
|
+
/** Loaded profile whose selected bundles may carry profile-local plugins. */
|
|
169
|
+
profile?: Profile;
|
|
170
|
+
/** Harness home; defaults to {@link resolveDshHome}. */
|
|
171
|
+
home?: string;
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Compute the runtime resolution without writing module-resolution files.
|
|
175
|
+
* @param options - installation anchor, optional loaded profile, and Harness home.
|
|
176
|
+
* @returns the complete immutable runtime resolution.
|
|
177
|
+
*/
|
|
178
|
+
export declare function createRuntimeResolution(options: RuntimeResolutionOptions): Promise<ProfileRuntimeResolution>;
|
|
179
|
+
/** Inputs a {@link ProfileRuntimeResolution} reuses to compute its successor. */
|
|
180
|
+
interface ResolutionSource {
|
|
181
|
+
installAnchor: string;
|
|
182
|
+
home: string;
|
|
183
|
+
profileDir: string | undefined;
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* A runtime resolution that remembers the inputs it was computed from. Worker environment data carries only its
|
|
187
|
+
* fields; the inputs stay private to the thread that computed it.
|
|
188
|
+
*/
|
|
189
|
+
export declare class ProfileRuntimeResolution implements RuntimeResolution {
|
|
190
|
+
#private;
|
|
191
|
+
readonly profilesDir: string;
|
|
192
|
+
readonly profileDir: string | undefined;
|
|
193
|
+
readonly localPackageNames: readonly string[];
|
|
194
|
+
readonly entries: readonly RuntimeResolutionEntry[];
|
|
195
|
+
readonly linkedRoots: readonly LinkedRoot[];
|
|
196
|
+
/**
|
|
197
|
+
* @param source - inputs of {@link createRuntimeResolution}, reused by {@link computeLatestResolution}.
|
|
198
|
+
* @param table - the computed package table.
|
|
199
|
+
*/
|
|
200
|
+
constructor(source: ResolutionSource, table: RuntimeResolution);
|
|
201
|
+
/**
|
|
202
|
+
* Compute the latest generation from the same installation, profile directory, and Harness home, rereading the
|
|
203
|
+
* profile's manifest, bundle selection, and installed packages from disk, without retaining synthetic layers.
|
|
204
|
+
* With no profile directory, only installation packages are recomputed. This instance is unchanged.
|
|
205
|
+
* @returns a new resolution for the latest generation.
|
|
206
|
+
*/
|
|
207
|
+
computeLatestResolution(): Promise<ProfileRuntimeResolution>;
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Read a profile's manifest.
|
|
211
|
+
* @param binName - the diagnostic prefix on the thrown error.
|
|
212
|
+
* @param dir - the profile directory.
|
|
213
|
+
* @returns the parsed manifest.
|
|
214
|
+
*/
|
|
215
|
+
export declare function readProfileManifest(binName: string, dir: string): ProfileManifest;
|
|
216
|
+
/**
|
|
217
|
+
* Write a profile's manifest back (2-space JSON, trailing newline).
|
|
218
|
+
* @param dir - the profile directory.
|
|
219
|
+
* @param manifest - the manifest value to persist.
|
|
220
|
+
*/
|
|
221
|
+
export declare function writeProfileManifest(dir: string, manifest: ProfileManifest): void;
|
|
222
|
+
/**
|
|
223
|
+
* Resolve one bundle package's directory: installation anchor first, then the
|
|
224
|
+
* profile directory. The installation-first order is the contract that
|
|
225
|
+
* `@qlzt/dsh-base` (and every other in-box bundle) always comes from
|
|
226
|
+
* the same installation as the running dsh, never from a profile-local copy.
|
|
227
|
+
* Resolution does not require the package to export `./package.json`.
|
|
228
|
+
* @param binName - the diagnostic prefix on the thrown error.
|
|
229
|
+
* @param packageName - the bundle's package name from `dsh.profile.bundles`.
|
|
230
|
+
* @param installAnchor - absolute path of a file inside the dsh app package (its package.json).
|
|
231
|
+
* @param profileDir - the profile directory (second anchor).
|
|
232
|
+
* @returns the bundle package's absolute directory.
|
|
233
|
+
*/
|
|
234
|
+
export declare function resolveBundleDir(binName: string, packageName: string, installAnchor: string, profileDir: string): string;
|
|
235
|
+
/**
|
|
236
|
+
* Load an already initialized profile directory without resolving it through
|
|
237
|
+
* the shared Harness home. This is used by application-owned profiles whose
|
|
238
|
+
* package project and lifecycle belong to that application.
|
|
239
|
+
* Retired bundles are removed from the stored bundle list first, rewriting the
|
|
240
|
+
* manifest when it listed one. Unreadable bundles, and bundles whose own dsh peers the profile does not exempt, are skipped
|
|
241
|
+
* without changing the manifest and listed in `skippedBundles`; nothing is printed.
|
|
242
|
+
* @param binName - the diagnostic prefix on thrown errors.
|
|
243
|
+
* @param dir - absolute profile package directory.
|
|
244
|
+
* @param installAnchor - absolute path of the owning dsh app's package.json.
|
|
245
|
+
* @param options - `userLayer: false` skips reading `cordis.patch.yml`.
|
|
246
|
+
* @returns the successfully loaded bundle layers and optional user patch layer.
|
|
247
|
+
*/
|
|
248
|
+
export declare function loadProfileDirectory(binName: string, dir: string, installAnchor: string, options?: {
|
|
249
|
+
userLayer?: boolean;
|
|
250
|
+
}): Profile;
|
|
251
|
+
/**
|
|
252
|
+
* Load a profile: resolve every `dsh.profile.bundles` entry to its patch
|
|
253
|
+
* layer and parse the profile's own patch file. Unreadable or incompatible bundles
|
|
254
|
+
* are skipped and listed in `skippedBundles`; profile manifest and user patch errors still throw.
|
|
255
|
+
* @param binName - the diagnostic prefix on thrown errors.
|
|
256
|
+
* @param name - the profile name.
|
|
257
|
+
* @param installAnchor - absolute path of the dsh app's package.json (first resolution anchor).
|
|
258
|
+
* @param home - the Harness home; defaults to {@link resolveDshHome}.
|
|
259
|
+
* @param options - `userLayer: false` skips reading `cordis.patch.yml`, so a
|
|
260
|
+
* bundles-only consumer (`--dump-default-config`, a recovery diagnostic)
|
|
261
|
+
* cannot fail on a broken user layer.
|
|
262
|
+
* @returns the loaded profile (empty `patches` when the user layer is skipped).
|
|
263
|
+
*/
|
|
264
|
+
export declare function loadProfile(binName: string, name: string, installAnchor: string, home?: string, options?: {
|
|
265
|
+
userLayer?: boolean;
|
|
266
|
+
}): Profile;
|
|
267
|
+
/**
|
|
268
|
+
* Compose patch layers into the effective entry list over an empty root —
|
|
269
|
+
* the same single `applyEntryPatches` call the boot include makes, so flag
|
|
270
|
+
* derivation and config dumps see exactly what mounts.
|
|
271
|
+
* @param layers - patch lists in application order.
|
|
272
|
+
* @param warn - sink for skipped-patch diagnostics; defaults to silent (boot repeats them).
|
|
273
|
+
* @returns the composed entry list.
|
|
274
|
+
*/
|
|
275
|
+
export declare function composeEntries(layers: readonly PatchOptions[][], warn?: (message: string) => void): EntryOptions[];
|
|
276
|
+
export {};
|
|
277
|
+
//# sourceMappingURL=profile.d.ts.map
|