@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 +38 -0
- package/dist/contracts.d.ts +76 -0
- package/dist/contracts.d.ts.map +1 -0
- package/dist/contracts.js +6 -0
- package/dist/contracts.js.map +1 -0
- package/dist/index.d.ts +66 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +367 -0
- package/dist/index.js.map +1 -0
- package/dist/storage.d.ts +24 -0
- package/dist/storage.d.ts.map +1 -0
- package/dist/storage.js +166 -0
- package/dist/storage.js.map +1 -0
- package/dist/windowsPath.d.ts +17 -0
- package/dist/windowsPath.d.ts.map +1 -0
- package/dist/windowsPath.js +81 -0
- package/dist/windowsPath.js.map +1 -0
- package/package.json +39 -0
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 @@
|
|
|
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"}
|
package/dist/index.d.ts
ADDED
|
@@ -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"}
|
package/dist/storage.js
ADDED
|
@@ -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
|
+
}
|