@forgecart/cli 2.202610130131.0 → 2.202610130322.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/dist/src/admin-api/admin-api-refusal.error.d.ts +2 -2
- package/dist/src/admin-api/admin-api-refusal.error.js +2 -2
- package/dist/src/admin-api/admin-api.client.d.ts +8 -4
- package/dist/src/admin-api/admin-api.client.js +11 -9
- package/dist/src/admin-api/admin-api.client.js.map +1 -1
- package/dist/src/admin-api/admin-api.result.d.ts +4 -0
- package/dist/src/admin-api/admin-api.result.js +17 -0
- package/dist/src/admin-api/admin-api.result.js.map +1 -1
- package/dist/src/authorization/cli-authorization-flow.d.ts +21 -14
- package/dist/src/authorization/cli-authorization-flow.js +40 -31
- package/dist/src/authorization/cli-authorization-flow.js.map +1 -1
- package/dist/src/authorization/cli-credential-check.d.ts +6 -13
- package/dist/src/authorization/cli-credential-check.js +6 -23
- package/dist/src/authorization/cli-credential-check.js.map +1 -1
- package/dist/src/authorization/cli-credential-step.d.ts +74 -0
- package/dist/src/authorization/cli-credential-step.js +154 -0
- package/dist/src/authorization/cli-credential-step.js.map +1 -0
- package/dist/src/authorization/cli-unauthorized-refusal.d.ts +18 -8
- package/dist/src/authorization/cli-unauthorized-refusal.js +26 -11
- package/dist/src/authorization/cli-unauthorized-refusal.js.map +1 -1
- package/dist/src/authorization/type/cli-authorization.types.d.ts +36 -4
- package/dist/src/authorization/type/cli-authorization.types.js +16 -3
- package/dist/src/authorization/type/cli-authorization.types.js.map +1 -1
- package/dist/src/commands/init.d.ts +0 -10
- package/dist/src/commands/init.js +17 -42
- package/dist/src/commands/init.js.map +1 -1
- package/dist/src/commands/sync.js +2 -2
- package/dist/src/commands/sync.js.map +1 -1
- package/dist/src/deploy/deploy.runner.d.ts +15 -8
- package/dist/src/deploy/deploy.runner.js +19 -10
- package/dist/src/deploy/deploy.runner.js.map +1 -1
- package/dist/src/sync/sync-dotenv.file.d.ts +30 -22
- package/dist/src/sync/sync-dotenv.file.js +49 -54
- package/dist/src/sync/sync-dotenv.file.js.map +1 -1
- package/dist/src/sync/sync-env-channel.d.ts +47 -0
- package/dist/src/sync/sync-env-channel.js +106 -0
- package/dist/src/sync/sync-env-channel.js.map +1 -0
- package/dist/src/sync/sync-env.runner.d.ts +26 -10
- package/dist/src/sync/sync-env.runner.js +73 -40
- package/dist/src/sync/sync-env.runner.js.map +1 -1
- package/dist/src/sync/sync-record.file.d.ts +8 -6
- package/dist/src/sync/sync-record.file.js +18 -5
- package/dist/src/sync/sync-record.file.js.map +1 -1
- package/dist/src/sync/sync-round.d.ts +23 -13
- package/dist/src/sync/sync-round.js +73 -37
- package/dist/src/sync/sync-round.js.map +1 -1
- package/dist/src/sync/sync-watch.d.ts +2 -1
- package/dist/src/sync/sync-watch.js +2 -1
- package/dist/src/sync/sync-watch.js.map +1 -1
- package/dist/src/sync/sync.runner.d.ts +16 -6
- package/dist/src/sync/sync.runner.js +29 -19
- package/dist/src/sync/sync.runner.js.map +1 -1
- package/dist/src/sync/type/sync.types.d.ts +49 -16
- package/dist/src/sync/type/sync.types.js.map +1 -1
- package/dist/src/sync/workspace-sync.client.d.ts +14 -8
- package/dist/src/sync/workspace-sync.client.js +40 -17
- package/dist/src/sync/workspace-sync.client.js.map +1 -1
- package/dist/src/util/dotenv.util.d.ts +19 -5
- package/dist/src/util/dotenv.util.js +42 -5
- package/dist/src/util/dotenv.util.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { resolve } from 'node:path';
|
|
2
2
|
import { AdminApiClient } from '../admin-api/admin-api.client.js';
|
|
3
|
-
import {
|
|
3
|
+
import { CliCredentialStep } from '../authorization/cli-credential-step.js';
|
|
4
4
|
import { CliExitLadder, CliRefusal } from '../exit-ladder.js';
|
|
5
5
|
import { print } from '../output.js';
|
|
6
6
|
import { DeployFollowBound } from './deploy-follow-bound.js';
|
|
@@ -8,14 +8,19 @@ import { DeploymentFollow } from './deployment-follow.js';
|
|
|
8
8
|
import { DeploymentClient } from './deployment.client.js';
|
|
9
9
|
import { DeploymentEndStatus, } from './type/deploy.types.js';
|
|
10
10
|
/**
|
|
11
|
-
* `forgecart deploy [name]` (#411): publish what the board serves.
|
|
12
|
-
*
|
|
13
|
-
* environment, then the storefront's `.env`, then its
|
|
14
|
-
* exactly as `sync` reads them
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
11
|
+
* `forgecart deploy [name]` (#411): publish what the board serves. The run
|
|
12
|
+
* reads its four credentials through the credential step (launch#62 N3), from
|
|
13
|
+
* the environment, then the storefront's `.env`, then its
|
|
14
|
+
* `.forgecart/config.json`, exactly as `sync` reads them. When a key is in no
|
|
15
|
+
* source, the step authorizes this machine at `/authorize` and writes the four
|
|
16
|
+
* delivered keys into `.env` before any deploy request; when the admin API
|
|
17
|
+
* refuses the credentials, it authorizes the same way and deploys again on the
|
|
18
|
+
* delivered keys. Without a terminal the step prints the URL and the code,
|
|
19
|
+
* waits for the authorization's window, and exits 3. Then the run sends ONE
|
|
20
|
+
* `publishDeployment(type: storefront)` — the server builds and ships; the CLI
|
|
21
|
+
* builds nothing — and follows the deployment to its end: RUNNING prints its
|
|
22
|
+
* URL and exits 0, FAILED prints its error and exits 1. Ctrl-C and `--timeout`
|
|
23
|
+
* end the following, never the publish.
|
|
19
24
|
*/
|
|
20
25
|
export class DeployRunner {
|
|
21
26
|
name;
|
|
@@ -30,7 +35,11 @@ export class DeployRunner {
|
|
|
30
35
|
}
|
|
31
36
|
async run() {
|
|
32
37
|
const storefront = this.name ? resolve(process.cwd(), this.name) : process.cwd();
|
|
33
|
-
const
|
|
38
|
+
const step = new CliCredentialStep({ targetDir: storefront });
|
|
39
|
+
await step.run(async (credentials) => this.deploy(credentials));
|
|
40
|
+
}
|
|
41
|
+
/** ONE publish on the settled credentials, followed to its end. */
|
|
42
|
+
async deploy(credentials) {
|
|
34
43
|
const client = new DeploymentClient(new AdminApiClient(credentials, this.options.timeout));
|
|
35
44
|
const bound = new DeployFollowBound(this.options.timeout);
|
|
36
45
|
bound.listen();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"deploy.runner.js","sourceRoot":"","sources":["../../../src/deploy/deploy.runner.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAE,cAAc,EAAE,MAAM,kCAAkC,CAAC;AAClE,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"deploy.runner.js","sourceRoot":"","sources":["../../../src/deploy/deploy.runner.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAE,cAAc,EAAE,MAAM,kCAAkC,CAAC;AAClE,OAAO,EAAE,iBAAiB,EAAE,MAAM,yCAAyC,CAAC;AAE5E,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC9D,OAAO,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AAErC,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EACL,mBAAmB,GAGpB,MAAM,wBAAwB,CAAC;AAEhC;;;;;;;;;;;;;;GAcG;AACH,MAAM,OAAO,YAAY;IAMJ;IACA;IANnB;;;OAGG;IACH,YACmB,IAAwB,EACxB,OAAsB;QADtB,SAAI,GAAJ,IAAI,CAAoB;QACxB,YAAO,GAAP,OAAO,CAAe;IACtC,CAAC;IAEJ,KAAK,CAAC,GAAG;QACP,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC;QACjF,MAAM,IAAI,GAAG,IAAI,iBAAiB,CAAC,EAAE,SAAS,EAAE,UAAU,EAAE,CAAC,CAAC;QAC9D,MAAM,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,WAAW,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC;IAClE,CAAC;IAED,mEAAmE;IAC3D,KAAK,CAAC,MAAM,CAAC,WAA2B;QAC9C,MAAM,MAAM,GAAG,IAAI,gBAAgB,CAAC,IAAI,cAAc,CAAC,WAAW,EAAE,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC;QAC3F,MAAM,KAAK,GAAG,IAAI,iBAAiB,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QAC1D,KAAK,CAAC,MAAM,EAAE,CAAC;QACf,IAAI,CAAC;YACH,KAAK,CAAC,oBAAoB,IAAI,CAAC,IAAI,IAAI,GAAG,EAAE,CAAC,CAAC;YAC9C,KAAK,CAAC,+EAA+E,CAAC,CAAC;YACvF,MAAM,SAAS,GAAG,MAAM,MAAM,CAAC,OAAO,EAAE,CAAC;YACzC,KAAK,CAAC,UAAU,EAAE,CAAC;YACnB,IAAI,CAAC,MAAM,CAAC,MAAM,IAAI,gBAAgB,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC;QACxE,CAAC;gBAAS,CAAC;YACT,KAAK,CAAC,OAAO,EAAE,CAAC;QAClB,CAAC;IACH,CAAC;IAED,qGAAqG;IAC7F,MAAM,CAAC,KAA2B;QACxC,IAAI,KAAK,CAAC,MAAM,KAAK,mBAAmB,CAAC,MAAM,EAAE,CAAC;YAChD,MAAM,IAAI,UAAU,CAAC,aAAa,CAAC,KAAK,EAAE;gBACxC,0BAA0B,KAAK,CAAC,YAAY,IAAI,yCAAyC,EAAE;aAC5F,CAAC,CAAC;QACL,CAAC;QACD,KAAK,CAAC,gBAAgB,KAAK,CAAC,GAAG,IAAI,wDAAwD,EAAE,CAAC,CAAC;IACjG,CAAC;CACF"}
|
|
@@ -1,36 +1,44 @@
|
|
|
1
|
-
import { type
|
|
2
|
-
import type {
|
|
1
|
+
import { type StorefrontEnvFile } from '../util/dotenv.util.js';
|
|
2
|
+
import type { SyncDotenvOutgoing, SyncDotenvTaken } from './type/sync.types.js';
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
5
|
-
* lines travel — the platform's `FORGECART_*` keys never cross — and
|
|
6
|
-
* travel under init's merge rule: a key is refreshed in place, every other
|
|
7
|
-
* is kept verbatim, nothing is deleted.
|
|
4
|
+
* One of the laptop's env files, as `forgecart sync` carries it (#2781). Only
|
|
5
|
+
* merchant lines travel — the platform's `FORGECART_*` keys never cross — and
|
|
6
|
+
* they travel under init's merge rule: a key is refreshed in place, every other
|
|
7
|
+
* line is kept verbatim, nothing is deleted.
|
|
8
8
|
*
|
|
9
9
|
* A push carries the merchant lines changed since they last travelled, so a
|
|
10
10
|
* key the workspace changed meanwhile is not overwritten by a stale copy; a
|
|
11
|
-
* pull takes the workspace's lines for every key the laptop
|
|
12
|
-
*
|
|
13
|
-
*
|
|
11
|
+
* pull takes the workspace's lines of the same file for every key the laptop
|
|
12
|
+
* has not changed since. What travelled is recorded as a digest per key, never
|
|
13
|
+
* the value. A `recorded` of null is a first sync — no key counts as changed —
|
|
14
|
+
* and an empty one a file that never travelled.
|
|
14
15
|
*/
|
|
15
16
|
export declare class SyncDotenvFile {
|
|
17
|
+
readonly file: StorefrontEnvFile;
|
|
16
18
|
private readonly path;
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
19
|
+
/**
|
|
20
|
+
* @param storefront the storefront directory.
|
|
21
|
+
* @param file the env file this is.
|
|
22
|
+
*/
|
|
23
|
+
constructor(storefront: string, file: StorefrontEnvFile);
|
|
24
|
+
/**
|
|
25
|
+
* The merchant lines a push carries from this file — every one changed since
|
|
26
|
+
* `recorded` — and the digests to record once they land; null when the
|
|
27
|
+
* storefront holds no such file.
|
|
28
|
+
*/
|
|
29
|
+
outgoing(recorded: Readonly<Record<string, string>> | null): Promise<SyncDotenvOutgoing | null>;
|
|
30
|
+
/** The workspace's merchant lines a pull would take into this file — every key the laptop has not changed since `recorded`. */
|
|
31
|
+
incoming(workspaceLines: readonly string[], recorded: Readonly<Record<string, string>> | null): Promise<string[]>;
|
|
22
32
|
/**
|
|
23
33
|
* Take the workspace's merchant lines — for every key the laptop has not
|
|
24
|
-
* changed since `recorded` — and the
|
|
25
|
-
*
|
|
26
|
-
* and the digest it last travelled with, so
|
|
34
|
+
* changed since `recorded` — and the `platform` keys into this file, under
|
|
35
|
+
* init's merge rule; a file the laptop lacks is created. A key the laptop
|
|
36
|
+
* changed keeps the laptop's value and the digest it last travelled with, so
|
|
37
|
+
* the next push still carries it, and a key that did not travel keeps the
|
|
38
|
+
* digest it had — none for a key that never travelled.
|
|
27
39
|
*/
|
|
28
|
-
take(workspaceLines: readonly string[],
|
|
40
|
+
take(workspaceLines: readonly string[], platform: ReadonlyMap<string, string>, recorded: Readonly<Record<string, string>> | null): Promise<SyncDotenvTaken>;
|
|
29
41
|
/** The keys whose line differs from the one that last travelled — none before a first sync. */
|
|
30
42
|
private changedSince;
|
|
31
|
-
/** The four credentials as `.env` assignments, in the order init writes them. */
|
|
32
|
-
private credentialEntries;
|
|
33
43
|
private digestsOf;
|
|
34
|
-
/** The `.env` text — empty when the storefront has none; any other failure propagates. */
|
|
35
|
-
private read;
|
|
36
44
|
}
|
|
@@ -1,65 +1,80 @@
|
|
|
1
1
|
import { createHash } from 'node:crypto';
|
|
2
|
-
import {
|
|
2
|
+
import { writeFile } from 'node:fs/promises';
|
|
3
3
|
import { join } from 'node:path';
|
|
4
|
-
import {
|
|
5
|
-
import { dotenvValue, mergeDotenv, merchantAssignments } from '../util/dotenv.util.js';
|
|
4
|
+
import { dotenvValue, mergeDotenv, merchantAssignments, readDotenvFile, } from '../util/dotenv.util.js';
|
|
6
5
|
/**
|
|
7
|
-
*
|
|
8
|
-
* lines travel — the platform's `FORGECART_*` keys never cross — and
|
|
9
|
-
* travel under init's merge rule: a key is refreshed in place, every other
|
|
10
|
-
* is kept verbatim, nothing is deleted.
|
|
6
|
+
* One of the laptop's env files, as `forgecart sync` carries it (#2781). Only
|
|
7
|
+
* merchant lines travel — the platform's `FORGECART_*` keys never cross — and
|
|
8
|
+
* they travel under init's merge rule: a key is refreshed in place, every other
|
|
9
|
+
* line is kept verbatim, nothing is deleted.
|
|
11
10
|
*
|
|
12
11
|
* A push carries the merchant lines changed since they last travelled, so a
|
|
13
12
|
* key the workspace changed meanwhile is not overwritten by a stale copy; a
|
|
14
|
-
* pull takes the workspace's lines for every key the laptop
|
|
15
|
-
*
|
|
16
|
-
*
|
|
13
|
+
* pull takes the workspace's lines of the same file for every key the laptop
|
|
14
|
+
* has not changed since. What travelled is recorded as a digest per key, never
|
|
15
|
+
* the value. A `recorded` of null is a first sync — no key counts as changed —
|
|
16
|
+
* and an empty one a file that never travelled.
|
|
17
17
|
*/
|
|
18
18
|
export class SyncDotenvFile {
|
|
19
|
+
file;
|
|
19
20
|
path;
|
|
20
|
-
|
|
21
|
-
|
|
21
|
+
/**
|
|
22
|
+
* @param storefront the storefront directory.
|
|
23
|
+
* @param file the env file this is.
|
|
24
|
+
*/
|
|
25
|
+
constructor(storefront, file) {
|
|
26
|
+
this.file = file;
|
|
27
|
+
this.path = join(storefront, file);
|
|
22
28
|
}
|
|
23
|
-
/**
|
|
29
|
+
/**
|
|
30
|
+
* The merchant lines a push carries from this file — every one changed since
|
|
31
|
+
* `recorded` — and the digests to record once they land; null when the
|
|
32
|
+
* storefront holds no such file.
|
|
33
|
+
*/
|
|
24
34
|
async outgoing(recorded) {
|
|
25
|
-
const
|
|
35
|
+
const content = await readDotenvFile(this.path);
|
|
36
|
+
if (content === null)
|
|
37
|
+
return null;
|
|
38
|
+
const assignments = merchantAssignments(content.split('\n'));
|
|
26
39
|
const digests = this.digestsOf(assignments);
|
|
27
40
|
const lines = [...assignments]
|
|
28
41
|
.filter(([key]) => recorded?.[key] !== digests[key])
|
|
29
42
|
.map(([, line]) => line);
|
|
30
43
|
return { lines, digests };
|
|
31
44
|
}
|
|
32
|
-
/**
|
|
33
|
-
async
|
|
34
|
-
const changed = this.changedSince(await this.
|
|
35
|
-
|
|
36
|
-
|
|
45
|
+
/** The workspace's merchant lines a pull would take into this file — every key the laptop has not changed since `recorded`. */
|
|
46
|
+
async incoming(workspaceLines, recorded) {
|
|
47
|
+
const changed = this.changedSince((await readDotenvFile(this.path)) ?? '', recorded);
|
|
48
|
+
return [...merchantAssignments(workspaceLines)]
|
|
49
|
+
.filter(([key]) => !changed.has(key))
|
|
50
|
+
.map(([, line]) => line);
|
|
37
51
|
}
|
|
38
52
|
/**
|
|
39
53
|
* Take the workspace's merchant lines — for every key the laptop has not
|
|
40
|
-
* changed since `recorded` — and the
|
|
41
|
-
*
|
|
42
|
-
* and the digest it last travelled with, so
|
|
54
|
+
* changed since `recorded` — and the `platform` keys into this file, under
|
|
55
|
+
* init's merge rule; a file the laptop lacks is created. A key the laptop
|
|
56
|
+
* changed keeps the laptop's value and the digest it last travelled with, so
|
|
57
|
+
* the next push still carries it, and a key that did not travel keeps the
|
|
58
|
+
* digest it had — none for a key that never travelled.
|
|
43
59
|
*/
|
|
44
|
-
async take(workspaceLines,
|
|
45
|
-
const existing = await this.
|
|
60
|
+
async take(workspaceLines, platform, recorded) {
|
|
61
|
+
const existing = (await readDotenvFile(this.path)) ?? '';
|
|
46
62
|
const changed = this.changedSince(existing, recorded);
|
|
47
|
-
const taken = [...merchantAssignments(workspaceLines)]
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
const next = mergeDotenv(existing, managed);
|
|
63
|
+
const taken = new Map([...merchantAssignments(workspaceLines)]
|
|
64
|
+
.filter(([key]) => !changed.has(key))
|
|
65
|
+
.map(([key, line]) => [key, dotenvValue(line, key)]));
|
|
66
|
+
const managed = new Map([...platform, ...taken]);
|
|
67
|
+
const next = managed.size === 0 ? existing : mergeDotenv(existing, managed);
|
|
53
68
|
if (next !== existing)
|
|
54
69
|
await writeFile(this.path, next, 'utf8');
|
|
55
70
|
const merged = this.digestsOf(merchantAssignments(next.split('\n')));
|
|
56
71
|
const digests = {};
|
|
57
72
|
for (const [key, digest] of Object.entries(merged)) {
|
|
58
|
-
const
|
|
59
|
-
if (
|
|
60
|
-
digests[key] =
|
|
73
|
+
const travelled = taken.has(key) ? digest : recorded?.[key];
|
|
74
|
+
if (travelled !== undefined)
|
|
75
|
+
digests[key] = travelled;
|
|
61
76
|
}
|
|
62
|
-
return { taken: taken.
|
|
77
|
+
return { taken: taken.size, digests };
|
|
63
78
|
}
|
|
64
79
|
/** The keys whose line differs from the one that last travelled — none before a first sync. */
|
|
65
80
|
changedSince(content, recorded) {
|
|
@@ -68,28 +83,8 @@ export class SyncDotenvFile {
|
|
|
68
83
|
const digests = this.digestsOf(merchantAssignments(content.split('\n')));
|
|
69
84
|
return new Set(Object.keys(digests).filter((key) => recorded[key] !== digests[key]));
|
|
70
85
|
}
|
|
71
|
-
/** The four credentials as `.env` assignments, in the order init writes them. */
|
|
72
|
-
credentialEntries(credentials) {
|
|
73
|
-
return [
|
|
74
|
-
[CliCredentialKey.CHANNEL_TOKEN, credentials.channelToken],
|
|
75
|
-
[CliCredentialKey.SHOP_API_URL, credentials.shopApiUrl],
|
|
76
|
-
[CliCredentialKey.ADMIN_SECRET, credentials.adminSecret],
|
|
77
|
-
[CliCredentialKey.ADMIN_API_URL, credentials.adminApiUrl],
|
|
78
|
-
];
|
|
79
|
-
}
|
|
80
86
|
digestsOf(assignments) {
|
|
81
87
|
return Object.fromEntries([...assignments].map(([key, line]) => [key, createHash('sha256').update(line).digest('hex')]));
|
|
82
88
|
}
|
|
83
|
-
/** The `.env` text — empty when the storefront has none; any other failure propagates. */
|
|
84
|
-
async read() {
|
|
85
|
-
try {
|
|
86
|
-
return await readFile(this.path, 'utf8');
|
|
87
|
-
}
|
|
88
|
-
catch (error) {
|
|
89
|
-
if (error.code === 'ENOENT')
|
|
90
|
-
return '';
|
|
91
|
-
throw error;
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
89
|
}
|
|
95
90
|
//# sourceMappingURL=sync-dotenv.file.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sync-dotenv.file.js","sourceRoot":"","sources":["../../../src/sync/sync-dotenv.file.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"sync-dotenv.file.js","sourceRoot":"","sources":["../../../src/sync/sync-dotenv.file.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { type CliCredentials } from '../authorization/type/cli-authorization.types.js';
|
|
2
|
+
import type { SyncEnvDigests, SyncEnvFileLines, SyncOutgoingEnv, SyncTakenEnv } from './type/sync.types.js';
|
|
3
|
+
/**
|
|
4
|
+
* The laptop's side of `forgecart sync`'s env channel (#2781): EVERY env file a
|
|
5
|
+
* storefront reads — `.env`, `.env.local`, `.env.development`,
|
|
6
|
+
* `.env.development.local`, `.env.production`, `.env.production.local` — carried
|
|
7
|
+
* file for file, each one's merchant lines into the other side's file of the
|
|
8
|
+
* same name, so every key resolves in the workspace as it does on the laptop.
|
|
9
|
+
* The files are never flattened into one, and the platform's `FORGECART_*`
|
|
10
|
+
* keys never cross in any of them. What travelled is recorded per file and per
|
|
11
|
+
* key. A pull also writes the run's four credentials into `.env` — the `.env` a
|
|
12
|
+
* fresh pull writes.
|
|
13
|
+
*/
|
|
14
|
+
export declare class SyncEnvChannel {
|
|
15
|
+
private readonly files;
|
|
16
|
+
/** @param storefront the storefront directory. */
|
|
17
|
+
constructor(storefront: string);
|
|
18
|
+
/**
|
|
19
|
+
* The merchant lines a push carries — one entry per env file the laptop
|
|
20
|
+
* holds, its lines changed since `recorded` — and the digests to record once
|
|
21
|
+
* they land.
|
|
22
|
+
*/
|
|
23
|
+
outgoing(recorded: SyncEnvDigests | null): Promise<SyncOutgoingEnv>;
|
|
24
|
+
/**
|
|
25
|
+
* The workspace's merchant lines a pull would take — one entry per env file
|
|
26
|
+
* the workspace holds, its lines for every key the laptop has not changed
|
|
27
|
+
* since `recorded`.
|
|
28
|
+
*/
|
|
29
|
+
incoming(workspaceFiles: readonly SyncEnvFileLines[], recorded: SyncEnvDigests | null): Promise<SyncEnvFileLines[]>;
|
|
30
|
+
/**
|
|
31
|
+
* Take each workspace env file's merchant lines into the laptop file of the
|
|
32
|
+
* same name — created when the laptop lacks it — and the four credentials
|
|
33
|
+
* into `.env`. A file the workspace does not hold is left as it is, with the
|
|
34
|
+
* digests it last travelled with.
|
|
35
|
+
*/
|
|
36
|
+
take(workspaceFiles: readonly SyncEnvFileLines[], credentials: CliCredentials, recorded: SyncEnvDigests | null): Promise<SyncTakenEnv>;
|
|
37
|
+
/** Take into one file — null for a file with neither workspace lines nor credentials to take. */
|
|
38
|
+
private takeInto;
|
|
39
|
+
/**
|
|
40
|
+
* The platform keys a pull writes into `file`: the four credentials in
|
|
41
|
+
* `.env`, in the order init writes them; none elsewhere.
|
|
42
|
+
*/
|
|
43
|
+
private platformEntries;
|
|
44
|
+
/** The digests `file` last travelled with: null before a first sync, none for a file that never travelled. */
|
|
45
|
+
private recordOf;
|
|
46
|
+
private linesByFile;
|
|
47
|
+
}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { CliCredentialKey, } from '../authorization/type/cli-authorization.types.js';
|
|
2
|
+
import { STOREFRONT_ENV_FILES, StorefrontEnvFile } from '../util/dotenv.util.js';
|
|
3
|
+
import { SyncDotenvFile } from './sync-dotenv.file.js';
|
|
4
|
+
/**
|
|
5
|
+
* The laptop's side of `forgecart sync`'s env channel (#2781): EVERY env file a
|
|
6
|
+
* storefront reads — `.env`, `.env.local`, `.env.development`,
|
|
7
|
+
* `.env.development.local`, `.env.production`, `.env.production.local` — carried
|
|
8
|
+
* file for file, each one's merchant lines into the other side's file of the
|
|
9
|
+
* same name, so every key resolves in the workspace as it does on the laptop.
|
|
10
|
+
* The files are never flattened into one, and the platform's `FORGECART_*`
|
|
11
|
+
* keys never cross in any of them. What travelled is recorded per file and per
|
|
12
|
+
* key. A pull also writes the run's four credentials into `.env` — the `.env` a
|
|
13
|
+
* fresh pull writes.
|
|
14
|
+
*/
|
|
15
|
+
export class SyncEnvChannel {
|
|
16
|
+
files;
|
|
17
|
+
/** @param storefront the storefront directory. */
|
|
18
|
+
constructor(storefront) {
|
|
19
|
+
this.files = STOREFRONT_ENV_FILES.map((file) => new SyncDotenvFile(storefront, file));
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* The merchant lines a push carries — one entry per env file the laptop
|
|
23
|
+
* holds, its lines changed since `recorded` — and the digests to record once
|
|
24
|
+
* they land.
|
|
25
|
+
*/
|
|
26
|
+
async outgoing(recorded) {
|
|
27
|
+
const files = [];
|
|
28
|
+
const digests = {};
|
|
29
|
+
for (const envFile of this.files) {
|
|
30
|
+
const outgoing = await envFile.outgoing(this.recordOf(recorded, envFile.file));
|
|
31
|
+
if (outgoing === null)
|
|
32
|
+
continue;
|
|
33
|
+
files.push({ file: envFile.file, lines: outgoing.lines });
|
|
34
|
+
digests[envFile.file] = outgoing.digests;
|
|
35
|
+
}
|
|
36
|
+
return { files, digests };
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* The workspace's merchant lines a pull would take — one entry per env file
|
|
40
|
+
* the workspace holds, its lines for every key the laptop has not changed
|
|
41
|
+
* since `recorded`.
|
|
42
|
+
*/
|
|
43
|
+
async incoming(workspaceFiles, recorded) {
|
|
44
|
+
const workspace = this.linesByFile(workspaceFiles);
|
|
45
|
+
const files = [];
|
|
46
|
+
for (const envFile of this.files) {
|
|
47
|
+
const workspaceLines = workspace.get(envFile.file);
|
|
48
|
+
if (workspaceLines === undefined)
|
|
49
|
+
continue;
|
|
50
|
+
const lines = await envFile.incoming(workspaceLines, this.recordOf(recorded, envFile.file));
|
|
51
|
+
files.push({ file: envFile.file, lines });
|
|
52
|
+
}
|
|
53
|
+
return files;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Take each workspace env file's merchant lines into the laptop file of the
|
|
57
|
+
* same name — created when the laptop lacks it — and the four credentials
|
|
58
|
+
* into `.env`. A file the workspace does not hold is left as it is, with the
|
|
59
|
+
* digests it last travelled with.
|
|
60
|
+
*/
|
|
61
|
+
async take(workspaceFiles, credentials, recorded) {
|
|
62
|
+
const workspace = this.linesByFile(workspaceFiles);
|
|
63
|
+
const digests = {};
|
|
64
|
+
let taken = 0;
|
|
65
|
+
for (const envFile of this.files) {
|
|
66
|
+
const workspaceLines = workspace.get(envFile.file);
|
|
67
|
+
const result = await this.takeInto(envFile, workspaceLines, credentials, recorded);
|
|
68
|
+
const fileDigests = result?.digests ?? recorded?.[envFile.file];
|
|
69
|
+
if (fileDigests !== undefined)
|
|
70
|
+
digests[envFile.file] = fileDigests;
|
|
71
|
+
taken += result?.taken ?? 0;
|
|
72
|
+
}
|
|
73
|
+
return { taken, digests };
|
|
74
|
+
}
|
|
75
|
+
/** Take into one file — null for a file with neither workspace lines nor credentials to take. */
|
|
76
|
+
async takeInto(envFile, workspaceLines, credentials, recorded) {
|
|
77
|
+
const platform = this.platformEntries(envFile.file, credentials);
|
|
78
|
+
if (workspaceLines === undefined && platform.size === 0)
|
|
79
|
+
return null;
|
|
80
|
+
return envFile.take(workspaceLines ?? [], platform, this.recordOf(recorded, envFile.file));
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* The platform keys a pull writes into `file`: the four credentials in
|
|
84
|
+
* `.env`, in the order init writes them; none elsewhere.
|
|
85
|
+
*/
|
|
86
|
+
platformEntries(file, credentials) {
|
|
87
|
+
if (file !== StorefrontEnvFile.BASE)
|
|
88
|
+
return new Map();
|
|
89
|
+
return new Map([
|
|
90
|
+
[CliCredentialKey.CHANNEL_TOKEN, credentials.channelToken],
|
|
91
|
+
[CliCredentialKey.SHOP_API_URL, credentials.shopApiUrl],
|
|
92
|
+
[CliCredentialKey.ADMIN_SECRET, credentials.adminSecret],
|
|
93
|
+
[CliCredentialKey.ADMIN_API_URL, credentials.adminApiUrl],
|
|
94
|
+
]);
|
|
95
|
+
}
|
|
96
|
+
/** The digests `file` last travelled with: null before a first sync, none for a file that never travelled. */
|
|
97
|
+
recordOf(recorded, file) {
|
|
98
|
+
if (recorded === null)
|
|
99
|
+
return null;
|
|
100
|
+
return recorded[file] ?? {};
|
|
101
|
+
}
|
|
102
|
+
linesByFile(files) {
|
|
103
|
+
return new Map(files.map(({ file, lines }) => [file, lines]));
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
//# sourceMappingURL=sync-env-channel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sync-env-channel.js","sourceRoot":"","sources":["../../../src/sync/sync-env-channel.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
import type { SyncEnvOptions } from './type/sync.types.js';
|
|
2
2
|
/**
|
|
3
3
|
* `forgecart sync-env [name]` (#2781) — the workspace's side of `forgecart
|
|
4
|
-
* sync`, which the admin API runs in the pod
|
|
5
|
-
* storefront
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
4
|
+
* sync`, which the admin API runs in the pod. It reads EVERY env file the
|
|
5
|
+
* storefront holds — `.env`, `.env.local`, `.env.development`,
|
|
6
|
+
* `.env.development.local`, `.env.production`, `.env.production.local` — or,
|
|
7
|
+
* with `--merge`, merges the lines FORGECART_SYNC_ENV_FILES carries for each
|
|
8
|
+
* file into the storefront file of that name under init's merge rule, creating
|
|
9
|
+
* one the storefront lacks. The files stay apart, so the dev-server resolves
|
|
10
|
+
* every key as the laptop does. It prints ONE JSON report: one entry per env
|
|
11
|
+
* file the storefront holds — its merchant lines as they stand, and how many
|
|
12
|
+
* keys the merge carried in. The platform's own `FORGECART_*` keys are never
|
|
13
|
+
* read out and never written: a laptop's never land, the pod's never leave.
|
|
10
14
|
*/
|
|
11
15
|
export declare class SyncEnvRunner {
|
|
12
16
|
private readonly name;
|
|
@@ -17,13 +21,25 @@ export declare class SyncEnvRunner {
|
|
|
17
21
|
*/
|
|
18
22
|
constructor(name: string | undefined, options: SyncEnvOptions);
|
|
19
23
|
run(): Promise<void>;
|
|
20
|
-
/**
|
|
24
|
+
/**
|
|
25
|
+
* One env file once the run is done: the merchant keys carried for it merged
|
|
26
|
+
* in — the file created when the storefront lacks it — and its merchant lines
|
|
27
|
+
* as they then stand; null for a file the storefront does not hold.
|
|
28
|
+
*/
|
|
29
|
+
private settle;
|
|
30
|
+
/** A file nothing was merged into, as it stands — null when the storefront does not hold it. */
|
|
31
|
+
private held;
|
|
32
|
+
/**
|
|
33
|
+
* The merchant keys a merge carries for each env file, keyed to their values
|
|
34
|
+
* — platform keys and other lines dropped; none for a read.
|
|
35
|
+
*/
|
|
21
36
|
private incoming;
|
|
22
|
-
private
|
|
37
|
+
private managedOf;
|
|
38
|
+
private parseEntries;
|
|
39
|
+
/** One entry: an env file the storefront reads — never a path outside them — and its lines. */
|
|
40
|
+
private parseEntry;
|
|
23
41
|
private malformedMessage;
|
|
24
42
|
private merchantLines;
|
|
25
43
|
/** The report the admin API parses: ONE line of JSON on stdout. */
|
|
26
44
|
private report;
|
|
27
|
-
/** The `.env` text — empty when the storefront has none; any other failure propagates. */
|
|
28
|
-
private read;
|
|
29
45
|
}
|