@mnemonik/local-setup 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/LICENSE ADDED
@@ -0,0 +1,38 @@
1
+ MNEMONIK PROPRIETARY SOFTWARE LICENSE
2
+
3
+ Copyright © 2026 JayDeeCo Limited. All rights reserved.
4
+
5
+ This licence applies to the Mnemonik software distributed with this file
6
+ (the "Software").
7
+
8
+ Subject to the Mnemonik Terms of Service and while you are an authorised
9
+ Mnemonik account holder, JayDeeCo Limited grants you a limited, revocable,
10
+ non-exclusive, non-transferable, non-sublicensable licence to download,
11
+ install, and run unmodified copies of the Software solely to access and use
12
+ the Mnemonik service. This permission applies to authorised free, trial, and
13
+ paid accounts.
14
+
15
+ You may not:
16
+
17
+ 1. modify the Software or create derivative works from it;
18
+ 2. reverse engineer, decompile, or disassemble the Software, except to the
19
+ extent that applicable law does not permit this restriction;
20
+ 3. redistribute, publish, sell, rent, lease, sublicense, or resell the
21
+ Software or access to it;
22
+ 4. use the Software to build or operate a product or service that competes
23
+ with Mnemonik;
24
+ 5. remove or alter any copyright, trade mark, attribution, or proprietary
25
+ notice; or
26
+ 6. bypass authentication, service limits, or technical restrictions.
27
+
28
+ JayDeeCo Limited and its licensors retain all right, title, and interest in
29
+ the Software. No rights are granted except those expressly stated here.
30
+
31
+ This licence ends automatically when your right to use Mnemonik ends or if
32
+ you breach this licence or the Mnemonik Terms of Service. When it ends, you
33
+ must stop using the Software and delete copies in your possession or control.
34
+
35
+ Third-party components remain subject to their own licences. The warranty
36
+ disclaimers, limitations of liability, termination terms, and governing law
37
+ in the Mnemonik Terms of Service at https://mnemonik.ai/terms apply to this
38
+ licence and the Software.
@@ -0,0 +1,76 @@
1
+ export interface Digest {
2
+ algorithmVersion: 1;
3
+ hash: string;
4
+ }
5
+ export type Owner = 'personal' | {
6
+ teamId: string;
7
+ };
8
+ /** Wire types mirror src/agent/projectSetup.ts, without importing server runtime. */
9
+ export interface SetupRequired {
10
+ status: 'project_setup_required';
11
+ state: string;
12
+ allowedActions: string[];
13
+ candidates?: Array<{
14
+ projectId: string;
15
+ displayName: string;
16
+ }>;
17
+ requestId?: string;
18
+ expiresAt?: string;
19
+ manualAction?: 'project_init' | 'project_setup';
20
+ }
21
+ export interface ActionRequired {
22
+ status: 'ACTION_REQUIRED';
23
+ state: string;
24
+ allowedActions: string[];
25
+ [key: string]: unknown;
26
+ }
27
+ export interface Evidence {
28
+ deviceRootContext: Digest;
29
+ repositoryFingerprint: Digest | null;
30
+ }
31
+ export interface ConsumeInput extends Evidence {
32
+ requestId: string;
33
+ action: 'create' | 'link' | 'restore';
34
+ projectId?: string;
35
+ operationId?: string;
36
+ displayName?: string;
37
+ owner?: Owner;
38
+ confirmCandidate?: string;
39
+ }
40
+ export type Complete = {
41
+ status: 'complete';
42
+ projectId: string;
43
+ displayName: string;
44
+ };
45
+ export interface SetupTransport {
46
+ /** POST /api/v1/project-setup/issue; caller supplies OAuth, never this package. */
47
+ issueSetupRequest(input: Evidence & {
48
+ projectId?: string;
49
+ }): Promise<SetupRequired | ActionRequired | Complete>;
50
+ /** POST /api/v1/project-setup/consume; caller supplies OAuth, never this package. */
51
+ consumeSetupRequest(input: ConsumeInput): Promise<Complete | ActionRequired>;
52
+ }
53
+ export interface EnsureOptions {
54
+ cwd: string;
55
+ owner?: Owner;
56
+ allowCreate: boolean;
57
+ allowNestedInherit: boolean;
58
+ nonGitSelected?: true;
59
+ intent?: {
60
+ action: 'link';
61
+ projectId: string;
62
+ replace?: true;
63
+ };
64
+ ignore?: true;
65
+ clearIgnore?: true;
66
+ }
67
+ export type SetupResult = ActionRequired | SetupRequired | {
68
+ status: 'done' | 'staged' | 'rolled_back' | 'ignored';
69
+ operationId: string;
70
+ root: string;
71
+ projectId?: string;
72
+ retainedRemoteUUID?: string;
73
+ permissionStatus: 'private' | 'acl_pending';
74
+ };
75
+ export declare const actionRequired: (state: string) => ActionRequired;
76
+ //# sourceMappingURL=contracts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contracts.d.ts","sourceRoot":"","sources":["../src/contracts.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,MAAM;IACrB,gBAAgB,EAAE,CAAC,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;CACd;AACD,MAAM,MAAM,KAAK,GAAG,UAAU,GAAG;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AACpD,qFAAqF;AACrF,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,wBAAwB,CAAC;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,UAAU,CAAC,EAAE,KAAK,CAAC;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC/D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,cAAc,GAAG,eAAe,CAAC;CACjD;AACD,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,iBAAiB,CAAC;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AACD,MAAM,WAAW,QAAQ;IACvB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,qBAAqB,EAAE,MAAM,GAAG,IAAI,CAAC;CACtC;AACD,MAAM,WAAW,YAAa,SAAQ,QAAQ;IAC5C,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,QAAQ,GAAG,MAAM,GAAG,SAAS,CAAC;IACtC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AACD,MAAM,MAAM,QAAQ,GAAG;IAAE,MAAM,EAAE,UAAU,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,CAAC;AACtF,MAAM,WAAW,cAAc;IAC7B,mFAAmF;IACnF,iBAAiB,CACf,KAAK,EAAE,QAAQ,GAAG;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,GACvC,OAAO,CAAC,aAAa,GAAG,cAAc,GAAG,QAAQ,CAAC,CAAC;IACtD,qFAAqF;IACrF,mBAAmB,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,QAAQ,GAAG,cAAc,CAAC,CAAC;CAC9E;AACD,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,WAAW,EAAE,OAAO,CAAC;IACrB,kBAAkB,EAAE,OAAO,CAAC;IAC5B,cAAc,CAAC,EAAE,IAAI,CAAC;IACtB,MAAM,CAAC,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,IAAI,CAAA;KAAE,CAAC;IAC/D,MAAM,CAAC,EAAE,IAAI,CAAC;IACd,WAAW,CAAC,EAAE,IAAI,CAAC;CACpB;AACD,MAAM,MAAM,WAAW,GACnB,cAAc,GACd,aAAa,GACb;IACE,MAAM,EAAE,MAAM,GAAG,QAAQ,GAAG,aAAa,GAAG,SAAS,CAAC;IACtD,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,gBAAgB,EAAE,SAAS,GAAG,aAAa,CAAC;CAC7C,CAAC;AACN,eAAO,MAAM,cAAc,UAAW,MAAM,KAAG,cAI7C,CAAC"}
@@ -0,0 +1,6 @@
1
+ export const actionRequired = (state) => ({
2
+ status: 'ACTION_REQUIRED',
3
+ state,
4
+ allowedActions: ['retry', 'cancel'],
5
+ });
6
+ //# sourceMappingURL=contracts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contracts.js","sourceRoot":"","sources":["../src/contracts.ts"],"names":[],"mappings":"AAgEA,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,KAAa,EAAkB,EAAE,CAAC,CAAC;IAChE,MAAM,EAAE,iBAAiB;IACzB,KAAK;IACL,cAAc,EAAE,CAAC,OAAO,EAAE,QAAQ,CAAC;CACpC,CAAC,CAAC"}
@@ -0,0 +1,66 @@
1
+ import { resolveProjectIdentity } from '@mnemonik/shared';
2
+ import { type Evidence, type SetupTransport, type EnsureOptions, type SetupResult, type Owner } from './contracts.js';
3
+ import { type Fault } from './storage.js';
4
+ export * from './contracts.js';
5
+ export * from './windowsPath.js';
6
+ export { stateDirectory, recordPath, protectStateFile, windowsCurrentUserAcl, windowsCurrentAccount, atomicWrite, withLock, type Fault, type PermissionStatus, type ExecFile, } from './storage.js';
7
+ type Step = {
8
+ complete: boolean;
9
+ started?: boolean;
10
+ beforeHash: string | null;
11
+ afterHash: string | null;
12
+ };
13
+ export interface SetupRecord {
14
+ schemaVersion: 1;
15
+ operationId: string;
16
+ root: string;
17
+ scopeKey: string;
18
+ owner?: Owner;
19
+ nonGitSelected?: true;
20
+ intent?: EnsureOptions['intent'];
21
+ ignored?: {
22
+ identityHash: string | null;
23
+ responseHash: string;
24
+ };
25
+ evidence?: Evidence;
26
+ remote?: {
27
+ projectId: string;
28
+ displayName?: string;
29
+ };
30
+ before: {
31
+ base64: string | null;
32
+ hash: string | null;
33
+ };
34
+ staged?: {
35
+ content: string;
36
+ hash: string;
37
+ };
38
+ steps: {
39
+ remote: Step & {
40
+ outcome?: 'created' | 'linked' | 'restored';
41
+ };
42
+ identity: Step;
43
+ rollback: Step;
44
+ };
45
+ }
46
+ export interface ExecutorDependencies {
47
+ resolver: {
48
+ resolveProjectIdentity: typeof resolveProjectIdentity;
49
+ };
50
+ transport: SetupTransport;
51
+ /** Non-secret authenticated user + device identity, stable across token refreshes. */
52
+ scopeKey: string;
53
+ /** Recompute locally using the device key and repository remote. Never return the key. */
54
+ bindContext(root: string): Promise<Evidence>;
55
+ stateDir?: string;
56
+ waitMs?: number;
57
+ /** Deterministic crash injection for filesystem/transport boundary tests. */
58
+ fault?: Fault;
59
+ }
60
+ export declare function createProjectSetupExecutor(deps: ExecutorDependencies): {
61
+ ensureProject: (options: EnsureOptions) => Promise<SetupResult>;
62
+ stage: (options: EnsureOptions) => Promise<SetupResult>;
63
+ apply: (options: EnsureOptions) => Promise<SetupResult>;
64
+ rollback: (options: EnsureOptions) => Promise<SetupResult>;
65
+ };
66
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAmB,sBAAsB,EAAE,MAAM,kBAAkB,CAAC;AAG3E,OAAO,EAEL,KAAK,QAAQ,EACb,KAAK,cAAc,EACnB,KAAK,aAAa,EAClB,KAAK,WAAW,EAChB,KAAK,KAAK,EACX,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAOL,KAAK,KAAK,EAEX,MAAM,cAAc,CAAC;AACtB,cAAc,gBAAgB,CAAC;AAC/B,cAAc,kBAAkB,CAAC;AACjC,OAAO,EACL,cAAc,EACd,UAAU,EACV,gBAAgB,EAChB,qBAAqB,EACrB,qBAAqB,EACrB,WAAW,EACX,QAAQ,EACR,KAAK,KAAK,EACV,KAAK,gBAAgB,EACrB,KAAK,QAAQ,GACd,MAAM,cAAc,CAAC;AAEtB,KAAK,IAAI,GAAG;IACV,QAAQ,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B,CAAC;AACF,MAAM,WAAW,WAAW;IAC1B,aAAa,EAAE,CAAC,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,cAAc,CAAC,EAAE,IAAI,CAAC;IACtB,MAAM,CAAC,EAAE,aAAa,CAAC,QAAQ,CAAC,CAAC;IACjC,OAAO,CAAC,EAAE;QAAE,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,YAAY,EAAE,MAAM,CAAA;KAAE,CAAC;IAChE,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,MAAM,CAAC,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACrD,MAAM,EAAE;QAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC;IACvD,MAAM,CAAC,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IAC3C,KAAK,EAAE;QACL,MAAM,EAAE,IAAI,GAAG;YAAE,OAAO,CAAC,EAAE,SAAS,GAAG,QAAQ,GAAG,UAAU,CAAA;SAAE,CAAC;QAC/D,QAAQ,EAAE,IAAI,CAAC;QACf,QAAQ,EAAE,IAAI,CAAC;KAChB,CAAC;CACH;AACD,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE;QAAE,sBAAsB,EAAE,OAAO,sBAAsB,CAAA;KAAE,CAAC;IACpE,SAAS,EAAE,cAAc,CAAC;IAC1B,sFAAsF;IACtF,QAAQ,EAAE,MAAM,CAAC;IACjB,0FAA0F;IAC1F,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC7C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,6EAA6E;IAC7E,KAAK,CAAC,EAAE,KAAK,CAAC;CACf;AA8CD,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,oBAAoB;IA0VjE,aAAa,YAAY,aAAa;IACtC,KAAK,YAAY,aAAa;IAC9B,KAAK,YAAY,aAAa;IAC9B,QAAQ,YAAY,aAAa;EAEpC"}
package/dist/index.js ADDED
@@ -0,0 +1,367 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ import { isCanonicalUuid } from '@mnemonik/shared';
3
+ import { realpath, unlink } from 'node:fs/promises';
4
+ import { basename, dirname, join } from 'node:path';
5
+ import { actionRequired, } from './contracts.js';
6
+ import { atomicWrite, hash, readBytes, recordPath, syncDirectory, withLock, } from './storage.js';
7
+ export * from './contracts.js';
8
+ export * from './windowsPath.js';
9
+ export { stateDirectory, recordPath, protectStateFile, windowsCurrentUserAcl, windowsCurrentAccount, atomicWrite, withLock, } from './storage.js';
10
+ const MAX_ORIGINAL_BYTES = 64 * 1024;
11
+ const validDisplayName = (value) => typeof value === 'string' && value.length <= 200 && !/[\p{C}\p{Zl}\p{Zp}@]/u.test(value);
12
+ const digest = (bytes) => (bytes === null ? null : hash(bytes));
13
+ const accessResponseHash = (response) => hash(JSON.stringify({
14
+ status: response.status,
15
+ state: response.state,
16
+ allowedActions: [...response.allowedActions].sort(),
17
+ candidates: response.candidates,
18
+ }));
19
+ const step = (beforeHash) => ({
20
+ complete: false,
21
+ beforeHash,
22
+ afterHash: null,
23
+ });
24
+ const nonGitSelectionRequired = () => ({
25
+ status: 'ACTION_REQUIRED',
26
+ state: 'non_git_selection_required',
27
+ allowedActions: ['select_non_git', 'cancel'],
28
+ manualAction: 'mnemonik project init <path>',
29
+ });
30
+ const recordedCandidate = (remote, root, state) => ({
31
+ status: 'project_setup_required',
32
+ state,
33
+ allowedActions: ['link', 'cancel'],
34
+ candidates: [
35
+ {
36
+ projectId: remote.projectId,
37
+ displayName: remote.displayName ?? basename(root),
38
+ },
39
+ ],
40
+ });
41
+ export function createProjectSetupExecutor(deps) {
42
+ async function execute(options, mode) {
43
+ let resolution = await deps.resolver.resolveProjectIdentity(options.cwd, options);
44
+ if (resolution.kind !== 'ok' && resolution.kind !== 'absent')
45
+ return actionRequired(resolution.kind);
46
+ const root = await realpath(resolution.root);
47
+ const path = recordPath(root, deps.stateDir);
48
+ if (resolution.repository.kind === 'plain' && !options.nonGitSelected) {
49
+ const prior = await readBytes(path);
50
+ if (!prior)
51
+ return nonGitSelectionRequired();
52
+ try {
53
+ if (JSON.parse(prior.toString()).nonGitSelected !== true)
54
+ return nonGitSelectionRequired();
55
+ }
56
+ catch {
57
+ return actionRequired('record_invalid');
58
+ }
59
+ }
60
+ return withLock(path, deps.waitMs ?? 60_000, async (assertOwned) => {
61
+ // The lock was acquired after resolving. Detect a changed identity/root before using it.
62
+ const fresh = await deps.resolver.resolveProjectIdentity(options.cwd, options);
63
+ if (fresh.kind !== 'ok' && fresh.kind !== 'absent')
64
+ return actionRequired(fresh.kind);
65
+ if ((await realpath(fresh.root)) !== root)
66
+ return actionRequired('identity_changed');
67
+ resolution = fresh;
68
+ const file = join(root, '.mnemonik.json');
69
+ const bytes = await readBytes(file);
70
+ const diskHash = digest(bytes);
71
+ const saved = await readBytes(path);
72
+ let record;
73
+ if (saved) {
74
+ try {
75
+ record = JSON.parse(saved.toString());
76
+ }
77
+ catch {
78
+ return actionRequired('record_invalid');
79
+ }
80
+ if (!record ||
81
+ record.schemaVersion !== 1 ||
82
+ record.root !== root ||
83
+ !record.operationId ||
84
+ !record.before ||
85
+ (record.before.base64 !== null && typeof record.before.base64 !== 'string') ||
86
+ (record.staged && typeof record.staged.content !== 'string') ||
87
+ !record.steps?.identity ||
88
+ !record.steps?.remote ||
89
+ !record.steps?.rollback ||
90
+ (record.ignored !== undefined &&
91
+ (!record.ignored ||
92
+ typeof record.ignored !== 'object' ||
93
+ (record.ignored.identityHash !== null &&
94
+ typeof record.ignored.identityHash !== 'string') ||
95
+ typeof record.ignored.responseHash !== 'string')) ||
96
+ (record.nonGitSelected !== undefined && record.nonGitSelected !== true) ||
97
+ (record.intent !== undefined &&
98
+ (record.intent.action !== 'link' ||
99
+ typeof record.intent.projectId !== 'string' ||
100
+ (record.intent.replace !== undefined && record.intent.replace !== true))))
101
+ return actionRequired('record_invalid');
102
+ if ((record.before.base64 !== null &&
103
+ record.before.hash !== hash(Buffer.from(record.before.base64, 'base64'))) ||
104
+ (record.before.base64 !== null &&
105
+ Buffer.from(record.before.base64, 'base64').length > MAX_ORIGINAL_BYTES) ||
106
+ (record.staged && hash(record.staged.content) !== record.staged.hash) ||
107
+ (record.remote && hash(JSON.stringify(record.remote)) !== record.steps.remote.afterHash))
108
+ return actionRequired('record_invalid');
109
+ if (record.scopeKey !== hash(deps.scopeKey) ||
110
+ (options.owner !== undefined &&
111
+ JSON.stringify(record.owner) !== JSON.stringify(options.owner)) ||
112
+ JSON.stringify(record.intent) !== JSON.stringify(options.intent)) {
113
+ if (record.ignored) {
114
+ delete record.ignored;
115
+ await atomicWrite(path, Buffer.from(JSON.stringify(record, null, 2) + '\n'), undefined, assertOwned);
116
+ }
117
+ return actionRequired('operation_context_changed');
118
+ }
119
+ }
120
+ else {
121
+ if (mode === 'apply' || mode === 'rollback')
122
+ return actionRequired('record_missing');
123
+ record = {
124
+ schemaVersion: 1,
125
+ operationId: randomUUID(),
126
+ root,
127
+ scopeKey: hash(deps.scopeKey),
128
+ owner: options.owner,
129
+ ...(resolution.repository.kind === 'plain' && options.nonGitSelected
130
+ ? { nonGitSelected: true }
131
+ : {}),
132
+ ...(options.intent ? { intent: options.intent } : {}),
133
+ before: {
134
+ base64: bytes && bytes.length <= MAX_ORIGINAL_BYTES ? bytes.toString('base64') : null,
135
+ hash: diskHash,
136
+ },
137
+ steps: { remote: step(diskHash), identity: step(diskHash), rollback: step(diskHash) },
138
+ };
139
+ }
140
+ if (resolution.repository.kind === 'plain' && record.nonGitSelected !== true) {
141
+ return nonGitSelectionRequired();
142
+ }
143
+ if (options.intent &&
144
+ resolution.kind === 'ok' &&
145
+ resolution.identity.projectId !== options.intent.projectId &&
146
+ !options.intent.replace)
147
+ return {
148
+ status: 'ACTION_REQUIRED',
149
+ state: 'identity_exists',
150
+ allowedActions: ['replace', 'cancel'],
151
+ };
152
+ let permissionStatus = 'private';
153
+ const save = async () => {
154
+ permissionStatus = await atomicWrite(path, Buffer.from(JSON.stringify(record, null, 2) + '\n'), undefined, assertOwned);
155
+ };
156
+ const result = (status) => ({
157
+ status,
158
+ operationId: record.operationId,
159
+ root,
160
+ permissionStatus,
161
+ projectId: record.remote?.projectId,
162
+ ...(status === 'rolled_back' ? { retainedRemoteUUID: record.remote?.projectId } : {}),
163
+ });
164
+ const clearIgnore = async () => {
165
+ if (!record.ignored)
166
+ return;
167
+ delete record.ignored;
168
+ await save();
169
+ };
170
+ const handleAccessResponse = async (response) => {
171
+ const responseHash = accessResponseHash(response);
172
+ if (options.ignore && response.allowedActions.includes('ignore')) {
173
+ record.ignored = { identityHash: diskHash, responseHash };
174
+ await save();
175
+ return result('ignored');
176
+ }
177
+ if (!record.ignored)
178
+ return response;
179
+ if (!options.clearIgnore &&
180
+ record.ignored.identityHash === diskHash &&
181
+ record.ignored.responseHash === responseHash)
182
+ return result('ignored');
183
+ await clearIgnore();
184
+ return response;
185
+ };
186
+ if ((bytes && bytes.length > MAX_ORIGINAL_BYTES) ||
187
+ (record.before.base64 === null && record.before.hash !== null)) {
188
+ if (!saved)
189
+ await save();
190
+ return actionRequired('identity_too_large');
191
+ }
192
+ if (record.ignored && record.ignored.identityHash !== diskHash) {
193
+ await clearIgnore();
194
+ return actionRequired('identity_changed');
195
+ }
196
+ if (diskHash !== record.before.hash && diskHash !== record.staged?.hash)
197
+ return actionRequired('identity_changed');
198
+ if (mode === 'rollback') {
199
+ // Durable undo intent precedes a write or removal, including crash recovery of undo.
200
+ record.steps.rollback.started = true;
201
+ record.steps.rollback.beforeHash = record.staged?.hash ?? record.before.hash;
202
+ record.steps.rollback.afterHash = record.before.hash;
203
+ await save();
204
+ if (diskHash !== record.before.hash) {
205
+ if (record.before.base64 === null) {
206
+ await assertOwned();
207
+ await unlink(file);
208
+ await syncDirectory(dirname(file));
209
+ }
210
+ else
211
+ await atomicWrite(file, Buffer.from(record.before.base64, 'base64'), deps.fault, assertOwned);
212
+ }
213
+ record.steps.rollback.complete = true;
214
+ record.steps.identity.complete = false;
215
+ await save();
216
+ return result('rolled_back');
217
+ }
218
+ if (record.steps.rollback.started)
219
+ return actionRequired(record.steps.rollback.complete ? 'operation_rolled_back' : 'rollback_in_progress');
220
+ const evidence = await deps.bindContext(root);
221
+ // A path-keyed journal can survive deletion of the repository it described.
222
+ // When the identity file is gone, only a matching usable fingerprint may
223
+ // authorize automatic reuse; otherwise the old UUID is display-only.
224
+ const remote = record.remote;
225
+ const resumingWithoutIdentity = !!remote && diskHash === record.before.hash && diskHash !== record.staged?.hash;
226
+ if (mode !== 'apply' && remote && resumingWithoutIdentity) {
227
+ const previousFingerprint = record.evidence?.repositoryFingerprint ?? null;
228
+ const currentFingerprint = evidence.repositoryFingerprint;
229
+ if (!previousFingerprint ||
230
+ !currentFingerprint ||
231
+ previousFingerprint.algorithmVersion !== currentFingerprint.algorithmVersion ||
232
+ previousFingerprint.hash !== currentFingerprint.hash) {
233
+ return recordedCandidate(remote, root, previousFingerprint && currentFingerprint
234
+ ? 'fingerprint_mismatch'
235
+ : 'confirmation_required');
236
+ }
237
+ }
238
+ if (!resumingWithoutIdentity &&
239
+ record.steps.identity.complete &&
240
+ diskHash !== record.staged?.hash)
241
+ return actionRequired('identity_changed');
242
+ if (!saved)
243
+ await save(); // Operation ID and before-state MUST be durable before any remote request.
244
+ if (record.evidence && JSON.stringify(record.evidence) !== JSON.stringify(evidence))
245
+ return actionRequired('operation_context_changed');
246
+ if (record.steps.identity.complete && mode === 'ensure' && record.remote) {
247
+ const validated = await deps.transport.issueSetupRequest({
248
+ ...evidence,
249
+ projectId: record.remote.projectId,
250
+ });
251
+ if (validated.status !== 'complete')
252
+ return handleAccessResponse(validated);
253
+ await clearIgnore();
254
+ if (validated.projectId !== record.remote.projectId)
255
+ return actionRequired('identity_changed');
256
+ }
257
+ if (!record.remote) {
258
+ if (mode === 'apply')
259
+ return actionRequired('not_staged');
260
+ record.evidence = evidence;
261
+ await save();
262
+ const identity = resolution.kind === 'ok' ? resolution.identity : null;
263
+ const issued = await deps.transport.issueSetupRequest({
264
+ ...evidence,
265
+ ...(options.intent
266
+ ? { projectId: options.intent.projectId }
267
+ : identity
268
+ ? { projectId: identity.projectId }
269
+ : {}),
270
+ });
271
+ if (issued.status !== 'complete') {
272
+ const handled = await handleAccessResponse(issued);
273
+ if (handled.status === 'ignored' || issued.status === 'ACTION_REQUIRED')
274
+ return handled;
275
+ }
276
+ else
277
+ await clearIgnore();
278
+ let remote;
279
+ let outcome = 'linked';
280
+ if (issued.status === 'complete')
281
+ remote = issued;
282
+ else if (options.intent && issued.requestId && issued.allowedActions.includes('link')) {
283
+ remote = await deps.transport.consumeSetupRequest({
284
+ ...evidence,
285
+ requestId: issued.requestId,
286
+ action: 'link',
287
+ projectId: options.intent.projectId,
288
+ });
289
+ if (remote.status === 'ACTION_REQUIRED')
290
+ return remote;
291
+ }
292
+ else {
293
+ // Candidate/archived/conflict/etc. decisions remain with the person and server.
294
+ if (issued.state !== 'missing' ||
295
+ issued.candidates?.length ||
296
+ !issued.requestId ||
297
+ resolution.kind !== 'absent' ||
298
+ !options.allowCreate ||
299
+ !issued.allowedActions.includes('create'))
300
+ return issued;
301
+ remote = await deps.transport.consumeSetupRequest({
302
+ ...evidence,
303
+ requestId: issued.requestId,
304
+ action: 'create',
305
+ operationId: record.operationId,
306
+ displayName: basename(root),
307
+ owner: record.owner,
308
+ });
309
+ if (remote.status === 'ACTION_REQUIRED')
310
+ return remote;
311
+ outcome = 'created';
312
+ }
313
+ await deps.fault?.('after_remote_response');
314
+ if (!isCanonicalUuid(remote.projectId))
315
+ return actionRequired('invalid_server_result');
316
+ record.remote = {
317
+ projectId: remote.projectId,
318
+ ...(validDisplayName(remote.displayName) ? { displayName: remote.displayName } : {}),
319
+ };
320
+ record.steps.remote = {
321
+ complete: true,
322
+ outcome,
323
+ beforeHash: record.before.hash,
324
+ afterHash: hash(JSON.stringify(record.remote)),
325
+ };
326
+ await save();
327
+ await deps.fault?.('after_remote_record');
328
+ }
329
+ if (!record.staged) {
330
+ const content = JSON.stringify({
331
+ schemaVersion: 1,
332
+ projectId: record.remote.projectId,
333
+ projectName: record.remote.displayName,
334
+ ...(record.evidence?.repositoryFingerprint
335
+ ? { repositoryFingerprint: record.evidence.repositoryFingerprint }
336
+ : {}),
337
+ }, null, 2) + '\n';
338
+ record.staged = { content, hash: hash(content) };
339
+ record.steps.identity.afterHash = record.staged.hash;
340
+ await save();
341
+ }
342
+ const current = digest(await readBytes(file));
343
+ if (current === record.staged.hash && !record.steps.identity.complete) {
344
+ record.steps.identity.complete = true;
345
+ await save();
346
+ }
347
+ if (mode === 'stage')
348
+ return result('staged');
349
+ if (current !== record.staged.hash) {
350
+ if (current !== record.before.hash)
351
+ return actionRequired('identity_changed');
352
+ await atomicWrite(file, Buffer.from(record.staged.content), deps.fault, assertOwned);
353
+ await deps.fault?.('after_identity_rename');
354
+ }
355
+ record.steps.identity.complete = true;
356
+ await save();
357
+ return result('done');
358
+ });
359
+ }
360
+ return {
361
+ ensureProject: (options) => execute(options, 'ensure'),
362
+ stage: (options) => execute(options, 'stage'),
363
+ apply: (options) => execute(options, 'apply'),
364
+ rollback: (options) => execute(options, 'rollback'),
365
+ };
366
+ }
367
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ import { windowsCurrentAccountSync } from '@mnemonik/shared/hook-runtime';
2
+ export declare const hash: (bytes: string | Buffer) => string;
3
+ export declare const codeIs: (error: unknown, code: string) => boolean;
4
+ export declare function stateDirectory(platform?: NodeJS.Platform, env?: NodeJS.ProcessEnv, home?: string): string;
5
+ export declare const recordPath: (root: string, state?: string) => string;
6
+ export declare function readBytes(path: string): Promise<Buffer | null>;
7
+ export declare function syncDirectory(path: string): Promise<void>;
8
+ export type PermissionStatus = 'private' | 'acl_pending';
9
+ export type ExecFile = (file: string, args: readonly string[], callback: (error: Error | null, stdout: string, stderr: string) => void) => unknown;
10
+ /** Resolve the process token: OpenSSH can advertise WORKGROUP as USERDOMAIN. */
11
+ export declare const windowsCurrentAccount: typeof windowsCurrentAccountSync;
12
+ export declare function windowsCurrentUserAcl(path: string, directory?: boolean, options?: {
13
+ execFile?: ExecFile;
14
+ username?: string;
15
+ }): Promise<void>;
16
+ export declare function protectStateFile(path: string, platform?: NodeJS.Platform, aclOptions?: {
17
+ execFile?: ExecFile;
18
+ username?: string;
19
+ }): Promise<PermissionStatus>;
20
+ export type Fault = (point: string) => void | Promise<void>;
21
+ export declare function atomicWrite(path: string, bytes: Buffer, fault?: Fault, assertOwned?: () => Promise<void>): Promise<PermissionStatus>;
22
+ /** Cooperative mkdir lease: all consumers must use these same stale/update values. */
23
+ export declare function withLock<T>(path: string, waitMs: number, work: (assertOwned: () => Promise<void>) => Promise<T>): Promise<T>;
24
+ //# sourceMappingURL=storage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../src/storage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,yBAAyB,EAAE,MAAM,+BAA+B,CAAC;AA8B1E,eAAO,MAAM,IAAI,UAAW,MAAM,GAAG,MAAM,KAAG,MACI,CAAC;AACnD,eAAO,MAAM,MAAM,UAAW,OAAO,QAAQ,MAAM,KAAG,OACN,CAAC;AACjD,wBAAgB,cAAc,CAC5B,QAAQ,kBAAmB,EAC3B,GAAG,oBAAc,EACjB,IAAI,SAAY,GACf,MAAM,CAMR;AACD,eAAO,MAAM,UAAU,SAAU,MAAM,qBAA6B,MAChB,CAAC;AACrD,wBAAsB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAQpE;AACD,wBAAsB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAS/D;AACD,MAAM,MAAM,gBAAgB,GAAG,SAAS,GAAG,aAAa,CAAC;AACzD,MAAM,MAAM,QAAQ,GAAG,CACrB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,KACpE,OAAO,CAAC;AACb,gFAAgF;AAChF,eAAO,MAAM,qBAAqB,kCAA4B,CAAC;AAC/D,wBAAsB,qBAAqB,CACzC,IAAI,EAAE,MAAM,EACZ,SAAS,UAAQ,EACjB,OAAO,GAAE;IAAE,QAAQ,CAAC,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAO,GACvD,OAAO,CAAC,IAAI,CAAC,CAUf;AACD,wBAAsB,gBAAgB,CACpC,IAAI,EAAE,MAAM,EACZ,QAAQ,kBAAmB,EAC3B,UAAU,CAAC,EAAE;IAAE,QAAQ,CAAC,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,GACtD,OAAO,CAAC,gBAAgB,CAAC,CAI3B;AACD,MAAM,MAAM,KAAK,GAAG,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAC5D,wBAAsB,WAAW,CAC/B,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,KAAK,CAAC,EAAE,KAAK,EACb,WAAW,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GAChC,OAAO,CAAC,gBAAgB,CAAC,CAoB3B;AACD,sFAAsF;AACtF,wBAAsB,QAAQ,CAAC,CAAC,EAC9B,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,CAAC,WAAW,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,GACrD,OAAO,CAAC,CAAC,CAAC,CA2EZ"}
@@ -0,0 +1,166 @@
1
+ import { windowsCurrentAccountSync } from '@mnemonik/shared/hook-runtime';
2
+ import { createHash, randomUUID } from 'node:crypto';
3
+ import { execFile as nodeExecFile } from 'node:child_process';
4
+ import fs from 'node:fs';
5
+ import { open, rename, readFile, mkdir, lstat, chmod, writeFile, unlink, rmdir, } from 'node:fs/promises';
6
+ import { homedir } from 'node:os';
7
+ import { dirname, join, win32, posix } from 'node:path';
8
+ import { setTimeout as delay } from 'node:timers/promises';
9
+ import { RuntimeError } from '@mnemonik/shared/hook-runtime';
10
+ const lockfileKey = Symbol.for('mnemonik.proper-lockfile');
11
+ function sharedLockfile() {
12
+ const shared = globalThis;
13
+ return (shared[lockfileKey] ??= import('proper-lockfile').then((module) => module.default));
14
+ }
15
+ export const hash = (bytes) => createHash('sha256').update(bytes).digest('hex');
16
+ export const codeIs = (error, code) => error.code === code;
17
+ export function stateDirectory(platform = process.platform, env = process.env, home = homedir()) {
18
+ if (env.MNEMONIK_STATE_DIR)
19
+ return env.MNEMONIK_STATE_DIR;
20
+ if (platform === 'win32')
21
+ return win32.join(env.LOCALAPPDATA || win32.join(home, 'AppData', 'Local'), 'Mnemonik');
22
+ if (platform === 'darwin')
23
+ return posix.join(home, 'Library', 'Application Support', 'Mnemonik');
24
+ return posix.join(env.XDG_STATE_HOME || posix.join(home, '.local', 'state'), 'mnemonik');
25
+ }
26
+ export const recordPath = (root, state = stateDirectory()) => join(state, 'project-setup', `${hash(root)}.json`);
27
+ export async function readBytes(path) {
28
+ try {
29
+ if (!(await lstat(path)).isFile())
30
+ throw new Error('setup_requires_regular_file');
31
+ return await readFile(path);
32
+ }
33
+ catch (error) {
34
+ if (codeIs(error, 'ENOENT'))
35
+ return null;
36
+ throw error;
37
+ }
38
+ }
39
+ export async function syncDirectory(path) {
40
+ // Windows does not expose directory fsync through Node. File fsync still runs.
41
+ if (process.platform === 'win32')
42
+ return;
43
+ const fd = await open(path, 'r');
44
+ try {
45
+ await fd.sync();
46
+ }
47
+ finally {
48
+ await fd.close();
49
+ }
50
+ }
51
+ /** Resolve the process token: OpenSSH can advertise WORKGROUP as USERDOMAIN. */
52
+ export const windowsCurrentAccount = windowsCurrentAccountSync;
53
+ export async function windowsCurrentUserAcl(path, directory = false, options = {}) {
54
+ const username = options.username ?? `*${windowsCurrentAccount().sid}`;
55
+ const grant = `${username}:${directory ? '(OI)(CI)F' : 'F'}`;
56
+ const execFile = options.execFile ?? nodeExecFile;
57
+ await new Promise((resolve, reject) => {
58
+ execFile('icacls.exe', [path, '/inheritance:r', '/grant:r', grant], (error) => {
59
+ if (error)
60
+ reject(error);
61
+ else
62
+ resolve();
63
+ });
64
+ });
65
+ }
66
+ export async function protectStateFile(path, platform = process.platform, aclOptions) {
67
+ if (platform === 'win32')
68
+ await windowsCurrentUserAcl(path, false, aclOptions);
69
+ else
70
+ await chmod(path, 0o600);
71
+ return 'private';
72
+ }
73
+ export async function atomicWrite(path, bytes, fault, assertOwned) {
74
+ await assertOwned?.();
75
+ const temp = `${path}.${randomUUID()}.tmp`;
76
+ const fd = await open(temp, 'wx', 0o600);
77
+ let permissionStatus;
78
+ try {
79
+ permissionStatus = await protectStateFile(temp);
80
+ const split = Math.ceil(bytes.length / 2);
81
+ await fd.writeFile(bytes.subarray(0, split));
82
+ await fault?.('mid_write');
83
+ await assertOwned?.();
84
+ await fd.writeFile(bytes.subarray(split));
85
+ await fd.sync();
86
+ }
87
+ finally {
88
+ await fd.close();
89
+ }
90
+ await assertOwned?.();
91
+ await rename(temp, path);
92
+ await syncDirectory(dirname(path));
93
+ return permissionStatus;
94
+ }
95
+ /** Cooperative mkdir lease: all consumers must use these same stale/update values. */
96
+ export async function withLock(path, waitMs, work) {
97
+ const lockfile = await sharedLockfile();
98
+ await mkdir(dirname(path), { recursive: true, mode: 0o700 });
99
+ const generation = randomUUID();
100
+ const owner = join(`${path}.lock`, 'owner');
101
+ let compromised = false;
102
+ let acquired = false;
103
+ const assertOwned = async () => {
104
+ if (compromised || (await readBytes(owner).catch(() => null))?.toString() !== generation) {
105
+ compromised = true;
106
+ throw new Error('lock_lost');
107
+ }
108
+ };
109
+ // Install the owner before proper-lockfile probes mtime; a later directory write
110
+ // would otherwise invalidate its heartbeat. Reclamation removes the owner too.
111
+ const leaseFs = {
112
+ ...fs,
113
+ mkdir: (dir, callback) => {
114
+ void mkdir(dir)
115
+ .then(() => writeFile(owner, generation, { mode: 0o600, flag: 'wx' }))
116
+ .then(() => callback(), callback);
117
+ },
118
+ rmdir: (dir, callback) => {
119
+ void unlink(join(dir, 'owner'))
120
+ .catch((error) => {
121
+ if (!codeIs(error, 'ENOENT'))
122
+ throw error;
123
+ })
124
+ .then(() => rmdir(dir))
125
+ .then(() => callback(), callback);
126
+ },
127
+ stat: (file, callback) => {
128
+ // A superseded holder must also stop heartbeating the replacement lease.
129
+ void (acquired ? assertOwned() : Promise.resolve()).then(() => fs.stat(file, callback), () => callback(Object.assign(new Error('lock_lost'), { code: 'ENOENT' })));
130
+ },
131
+ };
132
+ const deadline = performance.now() + waitMs;
133
+ let release;
134
+ while (!release) {
135
+ try {
136
+ release = await lockfile.lock(path, {
137
+ realpath: false,
138
+ stale: 30_000,
139
+ update: 5_000,
140
+ retries: 0,
141
+ fs: leaseFs,
142
+ onCompromised: () => {
143
+ compromised = true;
144
+ },
145
+ });
146
+ }
147
+ catch (error) {
148
+ if (!codeIs(error, 'ELOCKED'))
149
+ throw error;
150
+ if (performance.now() >= deadline)
151
+ throw new RuntimeError('lock_held');
152
+ await delay(Math.min(100, Math.max(1, deadline - performance.now())));
153
+ }
154
+ }
155
+ acquired = true;
156
+ try {
157
+ return await work(assertOwned);
158
+ }
159
+ finally {
160
+ // Never release a successor's lease. A lost holder's heartbeat observes the
161
+ // generation check above and stops through onCompromised.
162
+ if (await assertOwned().then(() => true, () => false))
163
+ await release();
164
+ }
165
+ }
166
+ //# sourceMappingURL=storage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage.js","sourceRoot":"","sources":["../src/storage.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ import type { ExecFile } from './storage.js';
2
+ /** Raw HKCU value: preserve expansion tokens, empty/absent values and registry type. */
3
+ export type WindowsPathValue = {
4
+ value: string;
5
+ kind: 'String' | 'ExpandString';
6
+ } | null;
7
+ export interface WindowsPathOptions {
8
+ execFile?: ExecFile;
9
+ env?: NodeJS.ProcessEnv;
10
+ }
11
+ export declare function windowsPathIncludes(path: string, directory: string, env?: NodeJS.ProcessEnv): boolean;
12
+ export declare function removeWindowsPathEntry(path: string, directory: string, preferredIndex: number, env?: NodeJS.ProcessEnv): string;
13
+ export declare function appendWindowsPath(before: WindowsPathValue, directory: string, env?: NodeJS.ProcessEnv): WindowsPathValue;
14
+ export declare function readWindowsUserPath(options?: WindowsPathOptions): Promise<WindowsPathValue>;
15
+ /** Compare-and-set in the same process; never overwrite a separately edited PATH. */
16
+ export declare function writeWindowsUserPath(before: WindowsPathValue, after: WindowsPathValue, options?: WindowsPathOptions): Promise<void>;
17
+ //# sourceMappingURL=windowsPath.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"windowsPath.d.ts","sourceRoot":"","sources":["../src/windowsPath.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAE7C,wFAAwF;AACxF,MAAM,MAAM,gBAAgB,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,QAAQ,GAAG,cAAc,CAAA;CAAE,GAAG,IAAI,CAAC;AACzF,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;CACzB;AAiBD,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,oBAAc,GAAG,OAAO,CAK/F;AAED,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,MAAM,EACjB,cAAc,EAAE,MAAM,EACtB,GAAG,oBAAc,GAChB,MAAM,CAQR;AAED,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,gBAAgB,EACxB,SAAS,EAAE,MAAM,EACjB,GAAG,oBAAc,GAChB,gBAAgB,CAQlB;AA+BD,wBAAsB,mBAAmB,CACvC,OAAO,GAAE,kBAAuB,GAC/B,OAAO,CAAC,gBAAgB,CAAC,CAkB3B;AAED,qFAAqF;AACrF,wBAAsB,oBAAoB,CACxC,MAAM,EAAE,gBAAgB,EACxB,KAAK,EAAE,gBAAgB,EACvB,OAAO,GAAE,kBAAuB,GAC/B,OAAO,CAAC,IAAI,CAAC,CAkBf"}
@@ -0,0 +1,81 @@
1
+ import { execFile as nodeExecFile } from 'node:child_process';
2
+ import { win32 } from 'node:path';
3
+ const normalizeWindowsPathEntry = (part, env) => win32
4
+ .normalize(part
5
+ .replace(/^"(.*)"$/, '$1')
6
+ .replace(/%([^%]+)%/g, (token, name) => Object.entries(env).find(([key]) => key.toLowerCase() === name.toLowerCase())?.[1] ??
7
+ token))
8
+ .replace(/[\\/]+$/, '')
9
+ .toLowerCase();
10
+ export function windowsPathIncludes(path, directory, env = process.env) {
11
+ const directoryKey = normalizeWindowsPathEntry(directory, env);
12
+ return path
13
+ .split(';')
14
+ .some((part) => part !== '' && normalizeWindowsPathEntry(part, env) === directoryKey);
15
+ }
16
+ export function removeWindowsPathEntry(path, directory, preferredIndex, env = process.env) {
17
+ const parts = path.split(';');
18
+ const directoryKey = normalizeWindowsPathEntry(directory, env);
19
+ const matches = (part) => part !== '' && normalizeWindowsPathEntry(part, env) === directoryKey;
20
+ const index = matches(parts[preferredIndex] ?? '') ? preferredIndex : parts.findIndex(matches);
21
+ if (index !== -1)
22
+ parts.splice(index, 1);
23
+ return parts.join(';');
24
+ }
25
+ export function appendWindowsPath(before, directory, env = process.env) {
26
+ if (windowsPathIncludes(before?.value ?? '', directory, env))
27
+ return before;
28
+ return {
29
+ value: before?.value
30
+ ? `${before.value}${before.value.endsWith(';') ? '' : ';'}${directory}`
31
+ : directory,
32
+ kind: before?.kind ?? 'ExpandString',
33
+ };
34
+ }
35
+ const readScript = `
36
+ $value = $key.GetValue('Path', $null, [Microsoft.Win32.RegistryValueOptions]::DoNotExpandEnvironmentNames)
37
+ $current = if ($null -eq $value) { $null } else { @{ value = [string]$value; kind = [string]$key.GetValueKind('Path') } }
38
+ `;
39
+ async function powershell(script, options) {
40
+ const executable = win32.join(options.env?.SystemRoot ?? process.env.SystemRoot ?? 'C:\\Windows', 'System32', 'WindowsPowerShell', 'v1.0', 'powershell.exe');
41
+ return new Promise((resolve, reject) => {
42
+ (options.execFile ?? nodeExecFile)(executable, [
43
+ '-NoProfile',
44
+ '-NonInteractive',
45
+ '-EncodedCommand',
46
+ Buffer.from(`$ErrorActionPreference = 'Stop'\n[Console]::OutputEncoding = [Text.UTF8Encoding]::new($false)\n${script}`, 'utf16le').toString('base64'),
47
+ ], (error, stdout) => (error ? reject(error) : resolve(stdout)));
48
+ });
49
+ }
50
+ export async function readWindowsUserPath(options = {}) {
51
+ const text = await powershell(`
52
+ $key = [Microsoft.Win32.Registry]::CurrentUser.OpenSubKey('Environment')
53
+ if ($null -eq $key) { 'null'; exit }
54
+ try { ${readScript}
55
+ ConvertTo-Json -InputObject $current -Compress
56
+ } finally { $key.Dispose() }
57
+ `, options);
58
+ const result = JSON.parse(text.trim());
59
+ if (result !== null &&
60
+ (typeof result.value !== 'string' || !['String', 'ExpandString'].includes(result.kind)))
61
+ throw new Error('user_path_invalid');
62
+ return result;
63
+ }
64
+ /** Compare-and-set in the same process; never overwrite a separately edited PATH. */
65
+ export async function writeWindowsUserPath(before, after, options = {}) {
66
+ const payload = Buffer.from(JSON.stringify({ before, after })).toString('base64');
67
+ await powershell(`
68
+ $change = [Text.Encoding]::UTF8.GetString([Convert]::FromBase64String('${payload}')) | ConvertFrom-Json
69
+ $key = [Microsoft.Win32.Registry]::CurrentUser.CreateSubKey('Environment')
70
+ try { ${readScript}
71
+ if (($null -eq $current) -ne ($null -eq $change.before) -or
72
+ ($null -ne $current -and ($current.value -cne $change.before.value -or $current.kind -cne $change.before.kind))) { throw 'user_path_changed' }
73
+ if ($null -eq $change.after) { $key.DeleteValue('Path', $false) }
74
+ else { $key.SetValue('Path', [string]$change.after.value, [Microsoft.Win32.RegistryValueKind]$change.after.kind) }
75
+ } finally { $key.Dispose() }
76
+ Add-Type -TypeDefinition 'using System; using System.Runtime.InteropServices; public static class MnemonikEnvironment { [DllImport("user32.dll", CharSet=CharSet.Unicode)] public static extern IntPtr SendMessageTimeout(IntPtr h, uint m, UIntPtr w, string l, uint f, uint t, out UIntPtr r); }'
77
+ $result = [UIntPtr]::Zero
78
+ [void][MnemonikEnvironment]::SendMessageTimeout([IntPtr]0xffff, 0x1a, [UIntPtr]::Zero, 'Environment', 2, 5000, [ref]$result)
79
+ `, options);
80
+ }
81
+ //# sourceMappingURL=windowsPath.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"windowsPath.js","sourceRoot":"","sources":["../src/windowsPath.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,39 @@
1
+ {
2
+ "name": "@mnemonik/local-setup",
3
+ "version": "0.1.0",
4
+ "repository": {
5
+ "type": "git",
6
+ "url": "git+https://github.com/JayDeeCo-Limited/mnemonik.git",
7
+ "directory": "packages/local-setup"
8
+ },
9
+ "type": "module",
10
+ "main": "dist/index.js",
11
+ "types": "dist/index.d.ts",
12
+ "exports": {
13
+ ".": {
14
+ "types": "./dist/index.d.ts",
15
+ "import": "./dist/index.js"
16
+ }
17
+ },
18
+ "files": [
19
+ "dist"
20
+ ],
21
+ "scripts": {
22
+ "build": "node ../../node_modules/@typescript/native/bin/tsc",
23
+ "typecheck": "node ../../node_modules/@typescript/native/bin/tsc --noEmit -p tsconfig.test.json",
24
+ "test": "vitest run --config vitest.config.ts tests/executor.test.ts",
25
+ "prepublishOnly": "npm run build"
26
+ },
27
+ "engines": {
28
+ "node": ">=24"
29
+ },
30
+ "license": "SEE LICENSE IN LICENSE",
31
+ "dependencies": {
32
+ "@mnemonik/shared": "7.98.0",
33
+ "proper-lockfile": "4.1.2"
34
+ },
35
+ "devDependencies": {
36
+ "@types/proper-lockfile": "4.1.4",
37
+ "@typescript/native": "npm:typescript@7.0.2"
38
+ }
39
+ }