@gadgetinc/ggt 0.3.3 → 0.4.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/README.md +139 -76
- package/bin/dev.js +4 -7
- package/lib/__generated__/graphql.js.map +1 -1
- package/lib/commands/deploy.js +227 -0
- package/lib/commands/deploy.js.map +1 -0
- package/lib/commands/list.js +20 -16
- package/lib/commands/list.js.map +1 -1
- package/lib/commands/login.js +22 -20
- package/lib/commands/login.js.map +1 -1
- package/lib/commands/logout.js +13 -9
- package/lib/commands/logout.js.map +1 -1
- package/lib/commands/root.js +89 -56
- package/lib/commands/root.js.map +1 -1
- package/lib/commands/sync.js +253 -496
- package/lib/commands/sync.js.map +1 -1
- package/lib/commands/version.js +21 -0
- package/lib/commands/version.js.map +1 -0
- package/lib/commands/whoami.js +15 -11
- package/lib/commands/whoami.js.map +1 -1
- package/lib/main.js +4 -10
- package/lib/main.js.map +1 -1
- package/lib/services/{app.js → app/app.js} +8 -3
- package/lib/services/app/app.js.map +1 -0
- package/lib/services/app/arg.js +28 -0
- package/lib/services/app/arg.js.map +1 -0
- package/lib/services/app/edit-graphql.js +389 -0
- package/lib/services/app/edit-graphql.js.map +1 -0
- package/lib/services/command/arg.js +53 -0
- package/lib/services/command/arg.js.map +1 -0
- package/lib/services/command/command.js +27 -0
- package/lib/services/command/command.js.map +1 -0
- package/lib/services/command/context.js +60 -0
- package/lib/services/command/context.js.map +1 -0
- package/lib/services/{config.js → config/config.js} +29 -31
- package/lib/services/config/config.js.map +1 -0
- package/lib/services/config/env.js +22 -0
- package/lib/services/config/env.js.map +1 -0
- package/lib/services/config/package-json.js +9 -0
- package/lib/services/config/package-json.js.map +1 -0
- package/lib/services/filesync/changes.js +97 -0
- package/lib/services/filesync/changes.js.map +1 -0
- package/lib/services/filesync/conflicts.js +137 -0
- package/lib/services/filesync/conflicts.js.map +1 -0
- package/lib/services/filesync/directory.js +253 -0
- package/lib/services/filesync/directory.js.map +1 -0
- package/lib/services/filesync/error.js +67 -0
- package/lib/services/filesync/error.js.map +1 -0
- package/lib/services/filesync/file.js +3 -0
- package/lib/services/filesync/file.js.map +1 -0
- package/lib/services/filesync/filesync.js +675 -0
- package/lib/services/filesync/filesync.js.map +1 -0
- package/lib/services/filesync/hashes.js +150 -0
- package/lib/services/filesync/hashes.js.map +1 -0
- package/lib/services/http/auth.js +41 -0
- package/lib/services/http/auth.js.map +1 -0
- package/lib/services/http/http.js +64 -0
- package/lib/services/http/http.js.map +1 -0
- package/lib/services/output/log/field.js +3 -0
- package/lib/services/output/log/field.js.map +1 -0
- package/lib/services/output/log/format/format.js +8 -0
- package/lib/services/output/log/format/format.js.map +1 -0
- package/lib/services/output/log/format/json.js +45 -0
- package/lib/services/output/log/format/json.js.map +1 -0
- package/lib/services/output/log/format/pretty.js +147 -0
- package/lib/services/output/log/format/pretty.js.map +1 -0
- package/lib/services/output/log/level.js +41 -0
- package/lib/services/output/log/level.js.map +1 -0
- package/lib/services/output/log/logger.js +40 -0
- package/lib/services/output/log/logger.js.map +1 -0
- package/lib/services/output/log/printer.js +120 -0
- package/lib/services/output/log/printer.js.map +1 -0
- package/lib/services/output/log/structured.js +52 -0
- package/lib/services/output/log/structured.js.map +1 -0
- package/lib/services/{notify.js → output/notify.js} +7 -6
- package/lib/services/output/notify.js.map +1 -0
- package/lib/services/output/prompt.js +52 -0
- package/lib/services/output/prompt.js.map +1 -0
- package/lib/services/output/report.js +162 -0
- package/lib/services/output/report.js.map +1 -0
- package/lib/services/output/sprint.js +21 -0
- package/lib/services/output/sprint.js.map +1 -0
- package/lib/services/output/stream.js +54 -0
- package/lib/services/output/stream.js.map +1 -0
- package/lib/services/{version.js → output/update.js} +24 -16
- package/lib/services/output/update.js.map +1 -0
- package/lib/services/user/session.js +50 -0
- package/lib/services/user/session.js.map +1 -0
- package/lib/services/{user.js → user/user.js} +23 -14
- package/lib/services/user/user.js.map +1 -0
- package/lib/services/util/boolean.js +15 -0
- package/lib/services/util/boolean.js.map +1 -0
- package/lib/services/util/collection.js +38 -0
- package/lib/services/util/collection.js.map +1 -0
- package/lib/services/util/function.js +97 -0
- package/lib/services/util/function.js.map +1 -0
- package/lib/services/{is.js → util/is.js} +7 -0
- package/lib/services/util/is.js.map +1 -0
- package/lib/services/util/number.js +27 -0
- package/lib/services/util/number.js.map +1 -0
- package/lib/services/util/object.js +101 -0
- package/lib/services/util/object.js.map +1 -0
- package/lib/services/util/paths.js +36 -0
- package/lib/services/util/paths.js.map +1 -0
- package/lib/services/{promise.js → util/promise.js} +5 -7
- package/lib/services/util/promise.js.map +1 -0
- package/npm-shrinkwrap.json +2143 -1304
- package/package.json +50 -42
- package/lib/commands/index.js +0 -9
- package/lib/commands/index.js.map +0 -1
- package/lib/services/app.js.map +0 -1
- package/lib/services/args.js +0 -28
- package/lib/services/args.js.map +0 -1
- package/lib/services/collections.js +0 -17
- package/lib/services/collections.js.map +0 -1
- package/lib/services/config.js.map +0 -1
- package/lib/services/debounce.js +0 -21
- package/lib/services/debounce.js.map +0 -1
- package/lib/services/defaults.js +0 -8
- package/lib/services/defaults.js.map +0 -1
- package/lib/services/edit-graphql.js +0 -202
- package/lib/services/edit-graphql.js.map +0 -1
- package/lib/services/errors.js +0 -277
- package/lib/services/errors.js.map +0 -1
- package/lib/services/filesync.js +0 -404
- package/lib/services/filesync.js.map +0 -1
- package/lib/services/fs.js +0 -35
- package/lib/services/fs.js.map +0 -1
- package/lib/services/http.js +0 -53
- package/lib/services/http.js.map +0 -1
- package/lib/services/is.js.map +0 -1
- package/lib/services/log.js +0 -45
- package/lib/services/log.js.map +0 -1
- package/lib/services/noop.js +0 -4
- package/lib/services/noop.js.map +0 -1
- package/lib/services/notify.js.map +0 -1
- package/lib/services/output.js +0 -74
- package/lib/services/output.js.map +0 -1
- package/lib/services/promise.js.map +0 -1
- package/lib/services/prompt.js +0 -22
- package/lib/services/prompt.js.map +0 -1
- package/lib/services/session.js +0 -31
- package/lib/services/session.js.map +0 -1
- package/lib/services/sleep.js +0 -21
- package/lib/services/sleep.js.map +0 -1
- package/lib/services/timeout.js +0 -8
- package/lib/services/timeout.js.map +0 -1
- package/lib/services/user.js.map +0 -1
- package/lib/services/version.js.map +0 -1
|
@@ -1,44 +1,28 @@
|
|
|
1
|
-
import fs from "fs-extra";
|
|
2
1
|
import isWsl from "is-wsl";
|
|
3
2
|
import os from "node:os";
|
|
4
3
|
import path from "node:path";
|
|
5
4
|
import process from "node:process";
|
|
6
|
-
import {
|
|
7
|
-
import
|
|
8
|
-
|
|
9
|
-
* The root directory of the ggt package.
|
|
10
|
-
*/ export const workspaceRoot = path.join(path.dirname(fileURLToPath(import.meta.url)), "../../");
|
|
11
|
-
/**
|
|
12
|
-
* The package.json of the ggt package.
|
|
13
|
-
*/ export const pkgJson = await fs.readJson(path.join(workspaceRoot, "package.json"));
|
|
14
|
-
normalizePackageData(pkgJson, true);
|
|
15
|
-
/**
|
|
16
|
-
* Captures the name and nature of the environment
|
|
17
|
-
*/ export const env = {
|
|
18
|
-
get value () {
|
|
19
|
-
return process.env["GGT_ENV"] || "production";
|
|
20
|
-
},
|
|
21
|
-
get productionLike () {
|
|
22
|
-
return !this.developmentOrTestLike;
|
|
23
|
-
},
|
|
24
|
-
get developmentLike () {
|
|
25
|
-
return this.value.startsWith("development");
|
|
26
|
-
},
|
|
27
|
-
get testLike () {
|
|
28
|
-
return this.value.startsWith("test");
|
|
29
|
-
},
|
|
30
|
-
get developmentOrTestLike () {
|
|
31
|
-
return this.developmentLike || this.testLike;
|
|
32
|
-
}
|
|
33
|
-
};
|
|
5
|
+
import { Level, parseLevel } from "../output/log/level.js";
|
|
6
|
+
import { env } from "./env.js";
|
|
7
|
+
import { packageJson } from "./package-json.js";
|
|
34
8
|
export const config = {
|
|
35
9
|
get name () {
|
|
36
|
-
return
|
|
10
|
+
return packageJson.name;
|
|
37
11
|
},
|
|
38
12
|
get version () {
|
|
39
|
-
return
|
|
13
|
+
return packageJson.version;
|
|
14
|
+
},
|
|
15
|
+
get logLevel () {
|
|
16
|
+
return parseLevel(process.env["GGT_LOG_LEVEL"], Level.PRINT);
|
|
17
|
+
},
|
|
18
|
+
get logFormat () {
|
|
19
|
+
return process.env["GGT_LOG_FORMAT"] === "json" ? "json" : "pretty";
|
|
40
20
|
},
|
|
41
21
|
/**
|
|
22
|
+
* Returns the full version string including name, version, platform,
|
|
23
|
+
* arch, and Node.js version. This is passed as the user agent for all
|
|
24
|
+
* outgoing http requests.
|
|
25
|
+
*
|
|
42
26
|
* @example "ggt/1.2.3 darwin-arm64 node-v16.0.0"
|
|
43
27
|
*/ get versionFull () {
|
|
44
28
|
return `${this.name}/${this.version} ${this.platform}-${this.arch} node-${process.version}`;
|
|
@@ -134,5 +118,19 @@ export const config = {
|
|
|
134
118
|
}
|
|
135
119
|
}
|
|
136
120
|
};
|
|
121
|
+
/**
|
|
122
|
+
* Returns an absolute path within the {@linkcode config.configDir}
|
|
123
|
+
* directory.
|
|
124
|
+
*
|
|
125
|
+
* @param segments - The segments of the path to join.
|
|
126
|
+
* @returns The absolute path to the file or directory.
|
|
127
|
+
*/ export const configPath = (...segments)=>path.join(config.configDir, ...segments);
|
|
128
|
+
/**
|
|
129
|
+
* Returns an absolute path within the {@linkcode config.homeDir}
|
|
130
|
+
* directory.
|
|
131
|
+
*
|
|
132
|
+
* @param segments - The segments of the path to join.
|
|
133
|
+
* @returns The absolute path to the file or directory.
|
|
134
|
+
*/ export const homePath = (...segments)=>path.join(config.homeDir, ...segments);
|
|
137
135
|
|
|
138
136
|
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/services/config/config.ts"],"sourcesContent":["import isWsl from \"is-wsl\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport process from \"node:process\";\nimport { Level, parseLevel } from \"../output/log/level.js\";\nimport { env } from \"./env.js\";\nimport { packageJson } from \"./package-json.js\";\n\nexport const config = {\n get name(): string {\n return packageJson.name;\n },\n\n get version(): string {\n return packageJson.version;\n },\n\n get logLevel() {\n return parseLevel(process.env[\"GGT_LOG_LEVEL\"], Level.PRINT);\n },\n\n get logFormat() {\n return process.env[\"GGT_LOG_FORMAT\"] === \"json\" ? \"json\" : \"pretty\";\n },\n\n /**\n * Returns the full version string including name, version, platform,\n * arch, and Node.js version. This is passed as the user agent for all\n * outgoing http requests.\n *\n * @example \"ggt/1.2.3 darwin-arm64 node-v16.0.0\"\n */\n get versionFull(): string {\n return `${this.name}/${this.version} ${this.platform}-${this.arch} node-${process.version}`;\n },\n\n get arch(): string {\n return os.arch() === \"ia32\" ? \"x86\" : os.arch();\n },\n\n get platform(): string {\n return isWsl ? \"wsl\" : os.platform();\n },\n\n get windows(): boolean {\n return process.platform === \"win32\";\n },\n\n get macos(): boolean {\n return process.platform === \"darwin\";\n },\n\n get shell(): string | undefined {\n const SHELL = process.env[\"SHELL\"] ?? os.userInfo().shell?.split(path.sep).pop();\n if (SHELL) {\n return SHELL.split(\"/\").at(-1);\n }\n if (this.windows && process.env[\"COMSPEC\"]) {\n return process.env[\"COMSPEC\"].split(/\\\\|\\//).at(-1);\n }\n return \"unknown\";\n },\n\n get homeDir(): string {\n if (process.env[\"HOME\"]) {\n return process.env[\"HOME\"];\n }\n\n if (this.windows) {\n if (process.env[\"HOMEDRIVE\"] && process.env[\"HOMEPATH\"]) {\n return path.join(process.env[\"HOMEDRIVE\"], process.env[\"HOMEPATH\"]);\n }\n if (process.env[\"USERPROFILE\"]) {\n return process.env[\"USERPROFILE\"];\n }\n }\n\n return os.homedir() || os.tmpdir();\n },\n\n /**\n * - Unix: `~/.config/ggt`\n * - Windows: `%LOCALAPPDATA%\\ggt`\n *\n * Can be overridden by `GGT_CONFIG_DIR`\n */\n get configDir(): string {\n if (process.env[\"GGT_CONFIG_DIR\"]) {\n return process.env[\"GGT_CONFIG_DIR\"];\n }\n\n const base = process.env[\"XDG_CONFIG_HOME\"] || (this.windows && process.env[\"LOCALAPPDATA\"]) || path.join(this.homeDir, \".config\");\n return path.join(base, \"ggt\");\n },\n\n /**\n * - Linux: `~/.cache/ggt`\n * - macOS: `~/Library/Caches/ggt`\n * - Windows: `%LOCALAPPDATA%\\ggt`\n *\n * Can be overridden with `GGT_CACHE_DIR`\n */\n get cacheDir(): string {\n if (process.env[\"GGT_CACHE_DIR\"]) {\n return process.env[\"GGT_CACHE_DIR\"];\n }\n\n if (this.macos) {\n return path.join(this.homeDir, \"Library/Caches/ggt\");\n }\n\n const base = process.env[\"XDG_CACHE_HOME\"] || (this.windows && process.env[\"LOCALAPPDATA\"]) || path.join(this.homeDir, \".cache\");\n return path.join(base, \"ggt\");\n },\n\n /**\n * - Unix: `~/.local/share/ggt`\n * - Windows: `%LOCALAPPDATA%\\ggt`\n *\n * Can be overridden with `GGT_DATA_DIR`\n */\n get dataDir(): string {\n if (process.env[\"GGT_DATA_DIR\"]) {\n return process.env[\"GGT_DATA_DIR\"];\n }\n\n const base = process.env[\"XDG_DATA_HOME\"] || (this.windows && process.env[\"LOCALAPPDATA\"]) || path.join(this.homeDir, \".local/share\");\n return path.join(base, \"ggt\");\n },\n\n /**\n * Domains for various Gadget services.\n */\n domains: {\n /**\n * The domain for the Gadget applications. This is where the user's application is hosted.\n */\n get app() {\n return process.env[\"GGT_GADGET_APP_DOMAIN\"] || (env.productionLike ? \"gadget.app\" : \"ggt.pub\");\n },\n\n /**\n * The domain for the Gadget services. This is where Gadget's API is hosted.\n */\n get services() {\n return process.env[\"GGT_GADGET_SERVICES_DOMAIN\"] || (env.productionLike ? \"app.gadget.dev\" : \"app.ggt.dev\");\n },\n },\n};\n\n/**\n * Returns an absolute path within the {@linkcode config.configDir}\n * directory.\n *\n * @param segments - The segments of the path to join.\n * @returns The absolute path to the file or directory.\n */\nexport const configPath = (...segments: string[]): string => path.join(config.configDir, ...segments);\n\n/**\n * Returns an absolute path within the {@linkcode config.homeDir}\n * directory.\n *\n * @param segments - The segments of the path to join.\n * @returns The absolute path to the file or directory.\n */\nexport const homePath = (...segments: string[]): string => path.join(config.homeDir, ...segments);\n"],"names":["isWsl","os","path","process","Level","parseLevel","env","packageJson","config","name","version","logLevel","PRINT","logFormat","versionFull","platform","arch","windows","macos","shell","SHELL","userInfo","split","sep","pop","at","homeDir","join","homedir","tmpdir","configDir","base","cacheDir","dataDir","domains","app","productionLike","services","configPath","segments","homePath"],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import process from "node:process";
|
|
2
|
+
/**
|
|
3
|
+
* Captures the name and nature of the environment
|
|
4
|
+
*/ export const env = {
|
|
5
|
+
get value () {
|
|
6
|
+
return process.env["GGT_ENV"] || "production";
|
|
7
|
+
},
|
|
8
|
+
get productionLike () {
|
|
9
|
+
return !this.developmentOrTestLike;
|
|
10
|
+
},
|
|
11
|
+
get developmentLike () {
|
|
12
|
+
return this.value.startsWith("development");
|
|
13
|
+
},
|
|
14
|
+
get testLike () {
|
|
15
|
+
return this.value.startsWith("test");
|
|
16
|
+
},
|
|
17
|
+
get developmentOrTestLike () {
|
|
18
|
+
return this.developmentLike || this.testLike;
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
//# sourceMappingURL=env.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/services/config/env.ts"],"sourcesContent":["import process from \"node:process\";\n\n/**\n * Captures the name and nature of the environment\n */\nexport const env = {\n get value(): string {\n return process.env[\"GGT_ENV\"] || \"production\";\n },\n\n get productionLike(): boolean {\n return !this.developmentOrTestLike;\n },\n\n get developmentLike(): boolean {\n return this.value.startsWith(\"development\");\n },\n\n get testLike(): boolean {\n return this.value.startsWith(\"test\");\n },\n\n get developmentOrTestLike(): boolean {\n return this.developmentLike || this.testLike;\n },\n};\n"],"names":["process","env","value","productionLike","developmentOrTestLike","developmentLike","startsWith","testLike"],"mappings":"AAAA,OAAOA,aAAa,eAAe;AAEnC;;CAEC,GACD,OAAO,MAAMC,MAAM;IACjB,IAAIC,SAAgB;QAClB,OAAOF,QAAQC,GAAG,CAAC,UAAU,IAAI;IACnC;IAEA,IAAIE,kBAA0B;QAC5B,OAAO,CAAC,IAAI,CAACC,qBAAqB;IACpC;IAEA,IAAIC,mBAA2B;QAC7B,OAAO,IAAI,CAACH,KAAK,CAACI,UAAU,CAAC;IAC/B;IAEA,IAAIC,YAAoB;QACtB,OAAO,IAAI,CAACL,KAAK,CAACI,UAAU,CAAC;IAC/B;IAEA,IAAIF,yBAAiC;QACnC,OAAO,IAAI,CAACC,eAAe,IAAI,IAAI,CAACE,QAAQ;IAC9C;AACF,EAAE"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import fs from "fs-extra";
|
|
2
|
+
import normalizePackageData from "normalize-package-data";
|
|
3
|
+
import { workspacePath } from "../util/paths.js";
|
|
4
|
+
/**
|
|
5
|
+
* The package.json of the ggt package.
|
|
6
|
+
*/ export const packageJson = await fs.readJson(workspacePath("package.json"));
|
|
7
|
+
normalizePackageData(packageJson, true);
|
|
8
|
+
|
|
9
|
+
//# sourceMappingURL=package-json.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/services/config/package-json.ts"],"sourcesContent":["import fs from \"fs-extra\";\nimport type { Package } from \"normalize-package-data\";\nimport normalizePackageData from \"normalize-package-data\";\nimport { workspacePath } from \"../util/paths.js\";\n\n/**\n * The package.json of the ggt package.\n */\nexport const packageJson = (await fs.readJson(workspacePath(\"package.json\"))) as Package;\n\nnormalizePackageData(packageJson, true);\n"],"names":["fs","normalizePackageData","workspacePath","packageJson","readJson"],"mappings":"AAAA,OAAOA,QAAQ,WAAW;AAE1B,OAAOC,0BAA0B,yBAAyB;AAC1D,SAASC,aAAa,QAAQ,mBAAmB;AAEjD;;CAEC,GACD,OAAO,MAAMC,cAAe,MAAMH,GAAGI,QAAQ,CAACF,cAAc,iBAA6B;AAEzFD,qBAAqBE,aAAa"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import chalk from "chalk";
|
|
2
|
+
import pluralize from "pluralize";
|
|
3
|
+
import { config } from "../config/config.js";
|
|
4
|
+
import { Level } from "../output/log/level.js";
|
|
5
|
+
import { createLogger } from "../output/log/logger.js";
|
|
6
|
+
import { sprint } from "../output/sprint.js";
|
|
7
|
+
import { isNever, isString } from "../util/is.js";
|
|
8
|
+
const log = createLogger({
|
|
9
|
+
name: "changes"
|
|
10
|
+
});
|
|
11
|
+
export class Changes extends Map {
|
|
12
|
+
created() {
|
|
13
|
+
return Array.from(this.entries()).filter(([, change])=>change.type === "create").map(([path])=>path);
|
|
14
|
+
}
|
|
15
|
+
updated() {
|
|
16
|
+
return Array.from(this.entries()).filter(([, change])=>change.type === "update").map(([path])=>path);
|
|
17
|
+
}
|
|
18
|
+
deleted() {
|
|
19
|
+
return Array.from(this.entries()).filter(([, change])=>change.type === "delete").map(([path])=>path);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Prints the changes to the console.
|
|
24
|
+
*
|
|
25
|
+
* @param changes - The changes to print.
|
|
26
|
+
* @param tense - The tense to use for the change type.
|
|
27
|
+
* @param limit - The maximum number of changes to print.
|
|
28
|
+
*/ export const printChanges = ({ changes, tense, limit = Infinity, ...tableOptions })=>{
|
|
29
|
+
if (config.logLevel <= Level.TRACE) {
|
|
30
|
+
// print all changes when tracing
|
|
31
|
+
limit = Infinity;
|
|
32
|
+
}
|
|
33
|
+
const renamed = chalk.yellowBright((tense === "past" ? "renamed" : "rename") + " →");
|
|
34
|
+
const created = chalk.greenBright((tense === "past" ? "created" : "create") + " +");
|
|
35
|
+
const updated = chalk.blueBright((tense === "past" ? "updated" : "update") + " ±");
|
|
36
|
+
const deleted = chalk.redBright((tense === "past" ? "deleted" : "delete") + " -");
|
|
37
|
+
const rows = Array.from(changes.entries()).sort((a, b)=>a[0].localeCompare(b[0])).slice(0, limit).map(([path, change])=>{
|
|
38
|
+
switch(true){
|
|
39
|
+
case change.type === "create" && isString(change.oldPath):
|
|
40
|
+
return [
|
|
41
|
+
chalk.yellowBright(change.oldPath),
|
|
42
|
+
renamed,
|
|
43
|
+
chalk.yellowBright(path)
|
|
44
|
+
];
|
|
45
|
+
case change.type === "create":
|
|
46
|
+
return [
|
|
47
|
+
chalk.greenBright(path),
|
|
48
|
+
created
|
|
49
|
+
];
|
|
50
|
+
case change.type === "update":
|
|
51
|
+
return [
|
|
52
|
+
chalk.blueBright(path),
|
|
53
|
+
updated
|
|
54
|
+
];
|
|
55
|
+
case change.type === "delete":
|
|
56
|
+
return [
|
|
57
|
+
chalk.redBright(path),
|
|
58
|
+
deleted
|
|
59
|
+
];
|
|
60
|
+
default:
|
|
61
|
+
return isNever(change);
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
if (changes.size > limit) {
|
|
65
|
+
rows.push([
|
|
66
|
+
sprint`{gray … ${changes.size - limit} more}`,
|
|
67
|
+
""
|
|
68
|
+
]);
|
|
69
|
+
}
|
|
70
|
+
let footer;
|
|
71
|
+
if (changes.size >= 10) {
|
|
72
|
+
tableOptions.spaceY = 1;
|
|
73
|
+
footer = sprint`${pluralize("change", changes.size, true)} in total. `;
|
|
74
|
+
const breakdown = [];
|
|
75
|
+
const created = changes.created();
|
|
76
|
+
if (created.length > 0) {
|
|
77
|
+
breakdown.push(sprint`{greenBright ${pluralize("create", created.length, true)}}`);
|
|
78
|
+
}
|
|
79
|
+
const updated = changes.updated();
|
|
80
|
+
if (updated.length > 0) {
|
|
81
|
+
breakdown.push(sprint`{blueBright ${pluralize("update", updated.length, true)}}`);
|
|
82
|
+
}
|
|
83
|
+
const deleted = changes.deleted();
|
|
84
|
+
if (deleted.length > 0) {
|
|
85
|
+
breakdown.push(sprint`{redBright ${pluralize("delete", deleted.length, true)}}`);
|
|
86
|
+
}
|
|
87
|
+
footer += breakdown.join(", ");
|
|
88
|
+
footer += ".";
|
|
89
|
+
}
|
|
90
|
+
log.printTable({
|
|
91
|
+
rows,
|
|
92
|
+
footer,
|
|
93
|
+
...tableOptions
|
|
94
|
+
});
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
//# sourceMappingURL=changes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/services/filesync/changes.ts"],"sourcesContent":["import chalk from \"chalk\";\nimport pluralize from \"pluralize\";\nimport { config } from \"../config/config.js\";\nimport { Level } from \"../output/log/level.js\";\nimport { createLogger } from \"../output/log/logger.js\";\nimport type { PrintTableOptions } from \"../output/log/printer.js\";\nimport { sprint } from \"../output/sprint.js\";\nimport { isNever, isString } from \"../util/is.js\";\n\nconst log = createLogger({ name: \"changes\" });\n\nexport type Create = { type: \"create\"; oldPath?: string };\nexport type Update = { type: \"update\" };\nexport type Delete = { type: \"delete\" };\nexport type Change = Create | Update | Delete;\n\nexport class Changes extends Map<string, Change> {\n created(): string[] {\n return Array.from(this.entries())\n .filter(([, change]) => change.type === \"create\")\n .map(([path]) => path);\n }\n\n updated(): string[] {\n return Array.from(this.entries())\n .filter(([, change]) => change.type === \"update\")\n .map(([path]) => path);\n }\n\n deleted(): string[] {\n return Array.from(this.entries())\n .filter(([, change]) => change.type === \"delete\")\n .map(([path]) => path);\n }\n}\n\n/**\n * Prints the changes to the console.\n *\n * @param changes - The changes to print.\n * @param tense - The tense to use for the change type.\n * @param limit - The maximum number of changes to print.\n */\nexport const printChanges = ({\n changes,\n tense,\n limit = Infinity,\n ...tableOptions\n}: {\n changes: Changes;\n tense: \"past\" | \"present\";\n limit?: number;\n} & Partial<PrintTableOptions>): void => {\n if (config.logLevel <= Level.TRACE) {\n // print all changes when tracing\n limit = Infinity;\n }\n\n const renamed = chalk.yellowBright((tense === \"past\" ? \"renamed\" : \"rename\") + \" →\");\n const created = chalk.greenBright((tense === \"past\" ? \"created\" : \"create\") + \" +\");\n const updated = chalk.blueBright((tense === \"past\" ? \"updated\" : \"update\") + \" ±\");\n const deleted = chalk.redBright((tense === \"past\" ? \"deleted\" : \"delete\") + \" -\");\n\n const rows = Array.from(changes.entries())\n .sort((a, b) => a[0].localeCompare(b[0]))\n .slice(0, limit)\n .map(([path, change]) => {\n switch (true) {\n case change.type === \"create\" && isString(change.oldPath):\n return [chalk.yellowBright(change.oldPath), renamed, chalk.yellowBright(path)];\n case change.type === \"create\":\n return [chalk.greenBright(path), created];\n case change.type === \"update\":\n return [chalk.blueBright(path), updated];\n case change.type === \"delete\":\n return [chalk.redBright(path), deleted];\n default:\n return isNever(change);\n }\n });\n\n if (changes.size > limit) {\n rows.push([sprint`{gray … ${changes.size - limit} more}`, \"\"]);\n }\n\n let footer: string | undefined;\n if (changes.size >= 10) {\n tableOptions.spaceY = 1;\n\n footer = sprint`${pluralize(\"change\", changes.size, true)} in total. `;\n\n const breakdown = [];\n\n const created = changes.created();\n if (created.length > 0) {\n breakdown.push(sprint`{greenBright ${pluralize(\"create\", created.length, true)}}`);\n }\n\n const updated = changes.updated();\n if (updated.length > 0) {\n breakdown.push(sprint`{blueBright ${pluralize(\"update\", updated.length, true)}}`);\n }\n\n const deleted = changes.deleted();\n if (deleted.length > 0) {\n breakdown.push(sprint`{redBright ${pluralize(\"delete\", deleted.length, true)}}`);\n }\n\n footer += breakdown.join(\", \");\n footer += \".\";\n }\n\n log.printTable({ rows, footer, ...tableOptions });\n};\n"],"names":["chalk","pluralize","config","Level","createLogger","sprint","isNever","isString","log","name","Changes","Map","created","Array","from","entries","filter","change","type","map","path","updated","deleted","printChanges","changes","tense","limit","Infinity","tableOptions","logLevel","TRACE","renamed","yellowBright","greenBright","blueBright","redBright","rows","sort","a","b","localeCompare","slice","oldPath","size","push","footer","spaceY","breakdown","length","join","printTable"],"mappings":"AAAA,OAAOA,WAAW,QAAQ;AAC1B,OAAOC,eAAe,YAAY;AAClC,SAASC,MAAM,QAAQ,sBAAsB;AAC7C,SAASC,KAAK,QAAQ,yBAAyB;AAC/C,SAASC,YAAY,QAAQ,0BAA0B;AAEvD,SAASC,MAAM,QAAQ,sBAAsB;AAC7C,SAASC,OAAO,EAAEC,QAAQ,QAAQ,gBAAgB;AAElD,MAAMC,MAAMJ,aAAa;IAAEK,MAAM;AAAU;AAO3C,OAAO,MAAMC,gBAAgBC;IAC3BC,UAAoB;QAClB,OAAOC,MAAMC,IAAI,CAAC,IAAI,CAACC,OAAO,IAC3BC,MAAM,CAAC,CAAC,GAAGC,OAAO,GAAKA,OAAOC,IAAI,KAAK,UACvCC,GAAG,CAAC,CAAC,CAACC,KAAK,GAAKA;IACrB;IAEAC,UAAoB;QAClB,OAAOR,MAAMC,IAAI,CAAC,IAAI,CAACC,OAAO,IAC3BC,MAAM,CAAC,CAAC,GAAGC,OAAO,GAAKA,OAAOC,IAAI,KAAK,UACvCC,GAAG,CAAC,CAAC,CAACC,KAAK,GAAKA;IACrB;IAEAE,UAAoB;QAClB,OAAOT,MAAMC,IAAI,CAAC,IAAI,CAACC,OAAO,IAC3BC,MAAM,CAAC,CAAC,GAAGC,OAAO,GAAKA,OAAOC,IAAI,KAAK,UACvCC,GAAG,CAAC,CAAC,CAACC,KAAK,GAAKA;IACrB;AACF;AAEA;;;;;;CAMC,GACD,OAAO,MAAMG,eAAe,CAAC,EAC3BC,OAAO,EACPC,KAAK,EACLC,QAAQC,QAAQ,EAChB,GAAGC,cAKyB;IAC5B,IAAI1B,OAAO2B,QAAQ,IAAI1B,MAAM2B,KAAK,EAAE;QAClC,iCAAiC;QACjCJ,QAAQC;IACV;IAEA,MAAMI,UAAU/B,MAAMgC,YAAY,CAAC,AAACP,CAAAA,UAAU,SAAS,YAAY,QAAO,IAAK;IAC/E,MAAMb,UAAUZ,MAAMiC,WAAW,CAAC,AAACR,CAAAA,UAAU,SAAS,YAAY,QAAO,IAAK;IAC9E,MAAMJ,UAAUrB,MAAMkC,UAAU,CAAC,AAACT,CAAAA,UAAU,SAAS,YAAY,QAAO,IAAK;IAC7E,MAAMH,UAAUtB,MAAMmC,SAAS,CAAC,AAACV,CAAAA,UAAU,SAAS,YAAY,QAAO,IAAK;IAE5E,MAAMW,OAAOvB,MAAMC,IAAI,CAACU,QAAQT,OAAO,IACpCsB,IAAI,CAAC,CAACC,GAAGC,IAAMD,CAAC,CAAC,EAAE,CAACE,aAAa,CAACD,CAAC,CAAC,EAAE,GACtCE,KAAK,CAAC,GAAGf,OACTP,GAAG,CAAC,CAAC,CAACC,MAAMH,OAAO;QAClB,OAAQ;YACN,KAAKA,OAAOC,IAAI,KAAK,YAAYX,SAASU,OAAOyB,OAAO;gBACtD,OAAO;oBAAC1C,MAAMgC,YAAY,CAACf,OAAOyB,OAAO;oBAAGX;oBAAS/B,MAAMgC,YAAY,CAACZ;iBAAM;YAChF,KAAKH,OAAOC,IAAI,KAAK;gBACnB,OAAO;oBAAClB,MAAMiC,WAAW,CAACb;oBAAOR;iBAAQ;YAC3C,KAAKK,OAAOC,IAAI,KAAK;gBACnB,OAAO;oBAAClB,MAAMkC,UAAU,CAACd;oBAAOC;iBAAQ;YAC1C,KAAKJ,OAAOC,IAAI,KAAK;gBACnB,OAAO;oBAAClB,MAAMmC,SAAS,CAACf;oBAAOE;iBAAQ;YACzC;gBACE,OAAOhB,QAAQW;QACnB;IACF;IAEF,IAAIO,QAAQmB,IAAI,GAAGjB,OAAO;QACxBU,KAAKQ,IAAI,CAAC;YAACvC,MAAM,CAAC,QAAQ,EAAEmB,QAAQmB,IAAI,GAAGjB,MAAM,MAAM,CAAC;YAAE;SAAG;IAC/D;IAEA,IAAImB;IACJ,IAAIrB,QAAQmB,IAAI,IAAI,IAAI;QACtBf,aAAakB,MAAM,GAAG;QAEtBD,SAASxC,MAAM,CAAC,EAAEJ,UAAU,UAAUuB,QAAQmB,IAAI,EAAE,MAAM,WAAW,CAAC;QAEtE,MAAMI,YAAY,EAAE;QAEpB,MAAMnC,UAAUY,QAAQZ,OAAO;QAC/B,IAAIA,QAAQoC,MAAM,GAAG,GAAG;YACtBD,UAAUH,IAAI,CAACvC,MAAM,CAAC,aAAa,EAAEJ,UAAU,UAAUW,QAAQoC,MAAM,EAAE,MAAM,CAAC,CAAC;QACnF;QAEA,MAAM3B,UAAUG,QAAQH,OAAO;QAC/B,IAAIA,QAAQ2B,MAAM,GAAG,GAAG;YACtBD,UAAUH,IAAI,CAACvC,MAAM,CAAC,YAAY,EAAEJ,UAAU,UAAUoB,QAAQ2B,MAAM,EAAE,MAAM,CAAC,CAAC;QAClF;QAEA,MAAM1B,UAAUE,QAAQF,OAAO;QAC/B,IAAIA,QAAQ0B,MAAM,GAAG,GAAG;YACtBD,UAAUH,IAAI,CAACvC,MAAM,CAAC,WAAW,EAAEJ,UAAU,UAAUqB,QAAQ0B,MAAM,EAAE,MAAM,CAAC,CAAC;QACjF;QAEAH,UAAUE,UAAUE,IAAI,CAAC;QACzBJ,UAAU;IACZ;IAEArC,IAAI0C,UAAU,CAAC;QAAEd;QAAMS;QAAQ,GAAGjB,YAAY;IAAC;AACjD,EAAE"}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import chalk from "chalk";
|
|
2
|
+
import { createLogger } from "../output/log/logger.js";
|
|
3
|
+
import { ChangesWithHash, isEqualHash } from "./hashes.js";
|
|
4
|
+
const log = createLogger({
|
|
5
|
+
name: "conflicts"
|
|
6
|
+
});
|
|
7
|
+
/**
|
|
8
|
+
* A map of conflicting changes made between the user's local filesystem
|
|
9
|
+
* and Gadget's filesystem where the key is the path of the conflicting
|
|
10
|
+
* file and the value is an object containing the conflicting changes.
|
|
11
|
+
*/ export class Conflicts extends Map {
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Returns the conflicting changes between the user's local filesystem
|
|
15
|
+
* and Gadget's filesystem.
|
|
16
|
+
*/ export const getConflicts = ({ localChanges, gadgetChanges })=>{
|
|
17
|
+
const conflicts = new Conflicts();
|
|
18
|
+
for (const [filepath, localChange] of localChanges){
|
|
19
|
+
const gadgetChange = gadgetChanges.get(filepath);
|
|
20
|
+
if (!gadgetChange) {
|
|
21
|
+
continue;
|
|
22
|
+
}
|
|
23
|
+
if (localChange.type === "delete" && gadgetChange.type === "delete") {
|
|
24
|
+
continue;
|
|
25
|
+
}
|
|
26
|
+
if ("targetHash" in localChange && "targetHash" in gadgetChange && isEqualHash(localChange.targetHash, gadgetChange.targetHash)) {
|
|
27
|
+
continue;
|
|
28
|
+
}
|
|
29
|
+
// local and gadget both updated the same file with different
|
|
30
|
+
// content or one updated and the other deleted
|
|
31
|
+
conflicts.set(filepath, {
|
|
32
|
+
localChange,
|
|
33
|
+
gadgetChange
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
// ignore .gadget/ file conflicts and always use gadget's version
|
|
37
|
+
// since gadget is the source of truth for .gadget/ files
|
|
38
|
+
for (const filepath of conflicts.keys()){
|
|
39
|
+
if (filepath.startsWith(".gadget/")) {
|
|
40
|
+
conflicts.delete(filepath);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return conflicts;
|
|
44
|
+
};
|
|
45
|
+
/**
|
|
46
|
+
* Returns a new `Changes` object that contains only the changes that do
|
|
47
|
+
* not have conflicts.
|
|
48
|
+
*
|
|
49
|
+
* @param conflicts - The conflicts to check against.
|
|
50
|
+
* @param changes - The changes to filter.
|
|
51
|
+
* @returns A new `Changes` object without conflicts.
|
|
52
|
+
*/ export const withoutConflictingChanges = ({ conflicts, changes })=>{
|
|
53
|
+
const changesWithoutConflicts = new ChangesWithHash(changes);
|
|
54
|
+
for (const [filepath] of changesWithoutConflicts){
|
|
55
|
+
if (conflicts.has(filepath)) {
|
|
56
|
+
changesWithoutConflicts.delete(filepath);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return changesWithoutConflicts;
|
|
60
|
+
};
|
|
61
|
+
/**
|
|
62
|
+
* Prints a table of conflicts between local changes and gadget changes.
|
|
63
|
+
*/ export const printConflicts = ({ message, conflicts })=>{
|
|
64
|
+
const created = chalk.greenBright("+ created");
|
|
65
|
+
const updated = chalk.blueBright("± updated");
|
|
66
|
+
const deleted = chalk.redBright("- deleted");
|
|
67
|
+
log.printTable({
|
|
68
|
+
message,
|
|
69
|
+
colAligns: [
|
|
70
|
+
"left",
|
|
71
|
+
"center",
|
|
72
|
+
"center"
|
|
73
|
+
],
|
|
74
|
+
headers: [
|
|
75
|
+
"",
|
|
76
|
+
"You",
|
|
77
|
+
"Gadget"
|
|
78
|
+
],
|
|
79
|
+
spaceY: 1,
|
|
80
|
+
rows: Array.from(conflicts.entries()).sort((a, b)=>a[0].localeCompare(b[0])).map(([path, { localChange, gadgetChange }])=>{
|
|
81
|
+
switch(true){
|
|
82
|
+
case localChange.type === "create" && gadgetChange.type === "create":
|
|
83
|
+
return [
|
|
84
|
+
path,
|
|
85
|
+
created,
|
|
86
|
+
created
|
|
87
|
+
];
|
|
88
|
+
case localChange.type === "create" && gadgetChange.type === "update":
|
|
89
|
+
return [
|
|
90
|
+
path,
|
|
91
|
+
created,
|
|
92
|
+
updated
|
|
93
|
+
];
|
|
94
|
+
case localChange.type === "create" && gadgetChange.type === "delete":
|
|
95
|
+
return [
|
|
96
|
+
path,
|
|
97
|
+
created,
|
|
98
|
+
deleted
|
|
99
|
+
];
|
|
100
|
+
case localChange.type === "update" && gadgetChange.type === "create":
|
|
101
|
+
return [
|
|
102
|
+
path,
|
|
103
|
+
updated,
|
|
104
|
+
created
|
|
105
|
+
];
|
|
106
|
+
case localChange.type === "update" && gadgetChange.type === "update":
|
|
107
|
+
return [
|
|
108
|
+
path,
|
|
109
|
+
updated,
|
|
110
|
+
updated
|
|
111
|
+
];
|
|
112
|
+
case localChange.type === "update" && gadgetChange.type === "delete":
|
|
113
|
+
return [
|
|
114
|
+
path,
|
|
115
|
+
updated,
|
|
116
|
+
deleted
|
|
117
|
+
];
|
|
118
|
+
case localChange.type === "delete" && gadgetChange.type === "create":
|
|
119
|
+
return [
|
|
120
|
+
path,
|
|
121
|
+
deleted,
|
|
122
|
+
created
|
|
123
|
+
];
|
|
124
|
+
case localChange.type === "delete" && gadgetChange.type === "update":
|
|
125
|
+
return [
|
|
126
|
+
path,
|
|
127
|
+
deleted,
|
|
128
|
+
updated
|
|
129
|
+
];
|
|
130
|
+
default:
|
|
131
|
+
throw new Error(`Unexpected conflict: ${localChange.type} vs ${gadgetChange.type}`);
|
|
132
|
+
}
|
|
133
|
+
})
|
|
134
|
+
});
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
//# sourceMappingURL=conflicts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/services/filesync/conflicts.ts"],"sourcesContent":["import chalk from \"chalk\";\nimport { createLogger } from \"../output/log/logger.js\";\nimport { ChangesWithHash, isEqualHash, type ChangeWithHash } from \"./hashes.js\";\n\nconst log = createLogger({ name: \"conflicts\" });\n\n/**\n * A map of conflicting changes made between the user's local filesystem\n * and Gadget's filesystem where the key is the path of the conflicting\n * file and the value is an object containing the conflicting changes.\n */\nexport class Conflicts extends Map<string, { localChange: ChangeWithHash; gadgetChange: ChangeWithHash }> {}\n\n/**\n * Returns the conflicting changes between the user's local filesystem\n * and Gadget's filesystem.\n */\nexport const getConflicts = ({\n localChanges,\n gadgetChanges,\n}: {\n localChanges: ChangesWithHash;\n gadgetChanges: ChangesWithHash;\n}): Conflicts => {\n const conflicts = new Conflicts();\n\n for (const [filepath, localChange] of localChanges) {\n const gadgetChange = gadgetChanges.get(filepath);\n if (!gadgetChange) {\n // gadget doesn't have this change, so there's no conflict\n continue;\n }\n\n if (localChange.type === \"delete\" && gadgetChange.type === \"delete\") {\n // local and gadget both deleted the same file\n continue;\n }\n\n if (\"targetHash\" in localChange && \"targetHash\" in gadgetChange && isEqualHash(localChange.targetHash, gadgetChange.targetHash)) {\n // local and gadget both created/updated the same file with the same content\n continue;\n }\n\n // local and gadget both updated the same file with different\n // content or one updated and the other deleted\n conflicts.set(filepath, { localChange, gadgetChange });\n }\n\n // ignore .gadget/ file conflicts and always use gadget's version\n // since gadget is the source of truth for .gadget/ files\n for (const filepath of conflicts.keys()) {\n if (filepath.startsWith(\".gadget/\")) {\n conflicts.delete(filepath);\n }\n }\n\n return conflicts;\n};\n\n/**\n * Returns a new `Changes` object that contains only the changes that do\n * not have conflicts.\n *\n * @param conflicts - The conflicts to check against.\n * @param changes - The changes to filter.\n * @returns A new `Changes` object without conflicts.\n */\nexport const withoutConflictingChanges = ({ conflicts, changes }: { conflicts: Conflicts; changes: ChangesWithHash }): ChangesWithHash => {\n const changesWithoutConflicts = new ChangesWithHash(changes);\n\n for (const [filepath] of changesWithoutConflicts) {\n if (conflicts.has(filepath)) {\n changesWithoutConflicts.delete(filepath);\n }\n }\n\n return changesWithoutConflicts;\n};\n\n/**\n * Prints a table of conflicts between local changes and gadget changes.\n */\nexport const printConflicts = ({ message, conflicts }: { message: string; conflicts: Conflicts }): void => {\n const created = chalk.greenBright(\"+ created\");\n const updated = chalk.blueBright(\"± updated\");\n const deleted = chalk.redBright(\"- deleted\");\n\n log.printTable({\n message,\n colAligns: [\"left\", \"center\", \"center\"],\n headers: [\"\", \"You\", \"Gadget\"],\n spaceY: 1,\n rows: Array.from(conflicts.entries())\n .sort((a, b) => a[0].localeCompare(b[0]))\n .map(([path, { localChange, gadgetChange }]) => {\n switch (true) {\n case localChange.type === \"create\" && gadgetChange.type === \"create\":\n return [path, created, created];\n case localChange.type === \"create\" && gadgetChange.type === \"update\":\n return [path, created, updated];\n case localChange.type === \"create\" && gadgetChange.type === \"delete\":\n return [path, created, deleted];\n case localChange.type === \"update\" && gadgetChange.type === \"create\":\n return [path, updated, created];\n case localChange.type === \"update\" && gadgetChange.type === \"update\":\n return [path, updated, updated];\n case localChange.type === \"update\" && gadgetChange.type === \"delete\":\n return [path, updated, deleted];\n case localChange.type === \"delete\" && gadgetChange.type === \"create\":\n return [path, deleted, created];\n case localChange.type === \"delete\" && gadgetChange.type === \"update\":\n return [path, deleted, updated];\n default:\n throw new Error(`Unexpected conflict: ${localChange.type} vs ${gadgetChange.type}`);\n }\n }),\n });\n};\n"],"names":["chalk","createLogger","ChangesWithHash","isEqualHash","log","name","Conflicts","Map","getConflicts","localChanges","gadgetChanges","conflicts","filepath","localChange","gadgetChange","get","type","targetHash","set","keys","startsWith","delete","withoutConflictingChanges","changes","changesWithoutConflicts","has","printConflicts","message","created","greenBright","updated","blueBright","deleted","redBright","printTable","colAligns","headers","spaceY","rows","Array","from","entries","sort","a","b","localeCompare","map","path","Error"],"mappings":"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"}
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DO NOT MODIFY
|
|
3
|
+
*
|
|
4
|
+
* Everything in this file also exists in ggt to ensure that this logic
|
|
5
|
+
* is the same between the two projects.
|
|
6
|
+
*/ import { _ as _define_property } from "@swc/helpers/_/_define_property";
|
|
7
|
+
import fs from "fs-extra";
|
|
8
|
+
import ignore from "ignore";
|
|
9
|
+
import assert from "node:assert";
|
|
10
|
+
import { createHash } from "node:crypto";
|
|
11
|
+
import path from "node:path";
|
|
12
|
+
import { Transform } from "node:stream";
|
|
13
|
+
import { pipeline } from "node:stream/promises";
|
|
14
|
+
import normalizePath from "normalize-path";
|
|
15
|
+
/**
|
|
16
|
+
* Paths that are always ignored, regardless of the contents of the `.ignore` file.
|
|
17
|
+
*/ export const ALWAYS_IGNORE_PATHS = [
|
|
18
|
+
".DS_Store",
|
|
19
|
+
"node_modules",
|
|
20
|
+
".git"
|
|
21
|
+
];
|
|
22
|
+
/**
|
|
23
|
+
* Paths that are ignored when hashing the directory.
|
|
24
|
+
*
|
|
25
|
+
* NOTE: This is the _only_ thing that is allowed to be different between gadget and ggt.
|
|
26
|
+
*/ export const HASHING_IGNORE_PATHS = [
|
|
27
|
+
".gadget/sync.json",
|
|
28
|
+
".gadget/backup"
|
|
29
|
+
];
|
|
30
|
+
/**
|
|
31
|
+
* Represents a directory that is being synced.
|
|
32
|
+
*/ export class Directory {
|
|
33
|
+
/**
|
|
34
|
+
* Initializes a directory to be synced.
|
|
35
|
+
*
|
|
36
|
+
* If the directory does not exist, it is created.
|
|
37
|
+
*
|
|
38
|
+
* @param dir - The directory to initialize.
|
|
39
|
+
* @returns A Promise that resolves to a Directory instance.
|
|
40
|
+
*/ static async init(dir) {
|
|
41
|
+
const directory = new Directory(dir);
|
|
42
|
+
await directory.loadIgnoreFile();
|
|
43
|
+
return directory;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Returns the relative path from this directory to the specified path.
|
|
47
|
+
*
|
|
48
|
+
* @param to - The path to which the relative path is calculated.
|
|
49
|
+
* @returns The relative path from this directory to the specified path.
|
|
50
|
+
*/ relative(to) {
|
|
51
|
+
if (!path.isAbsolute(to)) {
|
|
52
|
+
// the filepath is already relative
|
|
53
|
+
return to;
|
|
54
|
+
}
|
|
55
|
+
return path.relative(this.path, to);
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Returns the absolute path by resolving the given path segments
|
|
59
|
+
* relative to the directory path.
|
|
60
|
+
*
|
|
61
|
+
* @param pathSegments The path segments to resolve.
|
|
62
|
+
* @returns The absolute path.
|
|
63
|
+
*/ absolute(...pathSegments) {
|
|
64
|
+
const result = path.resolve(this.path, ...pathSegments);
|
|
65
|
+
assert(result.startsWith(this.path), `expected ${result} to be within ${this.path}`);
|
|
66
|
+
return result;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Similar to {@linkcode relative} in that it converts an absolute
|
|
70
|
+
* path into a relative one from {@linkcode path}. However, it also
|
|
71
|
+
* changes any slashes to be posix/unix-like forward slashes,
|
|
72
|
+
* condenses repeated slashes into a single slash, and adds a trailing
|
|
73
|
+
* slash if the path is a directory.
|
|
74
|
+
*
|
|
75
|
+
* This is used when sending files to Gadget to ensure that the paths
|
|
76
|
+
* are consistent across platforms.
|
|
77
|
+
*
|
|
78
|
+
* @see https://www.npmjs.com/package/normalize-path
|
|
79
|
+
*/ normalize(filepath, isDirectory) {
|
|
80
|
+
if (path.isAbsolute(filepath)) {
|
|
81
|
+
filepath = this.relative(filepath);
|
|
82
|
+
}
|
|
83
|
+
// true = trim trailing slashes
|
|
84
|
+
filepath = normalizePath(filepath, true);
|
|
85
|
+
if (isDirectory) {
|
|
86
|
+
filepath += "/";
|
|
87
|
+
}
|
|
88
|
+
return filepath;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Loads the `.ignore` file in the directory. If the file does not
|
|
92
|
+
* exist, it is silently ignored.
|
|
93
|
+
*/ async loadIgnoreFile() {
|
|
94
|
+
this._ignorer = ignore.default();
|
|
95
|
+
this._ignorer.add(ALWAYS_IGNORE_PATHS);
|
|
96
|
+
try {
|
|
97
|
+
const content = await fs.readFile(this.absolute(".ignore"), "utf8");
|
|
98
|
+
this._ignorer.add(content);
|
|
99
|
+
} catch (error) {
|
|
100
|
+
swallowEnoent(error);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Determines if a file should be ignored based on its filepath.
|
|
105
|
+
*
|
|
106
|
+
* @param filepath - The filepath of the file to check.
|
|
107
|
+
* @returns True if the file should be ignored, false otherwise.
|
|
108
|
+
*/ ignores(filepath) {
|
|
109
|
+
filepath = this.relative(filepath);
|
|
110
|
+
if (filepath === "") {
|
|
111
|
+
// don't ignore the root dir
|
|
112
|
+
return false;
|
|
113
|
+
}
|
|
114
|
+
if (filepath.startsWith("..")) {
|
|
115
|
+
// anything above the root dir is ignored
|
|
116
|
+
return true;
|
|
117
|
+
}
|
|
118
|
+
// false = don't trim trailing slashes
|
|
119
|
+
filepath = normalizePath(filepath, false);
|
|
120
|
+
if (this._isHashing && HASHING_IGNORE_PATHS.some((ignored)=>filepath.startsWith(ignored))) {
|
|
121
|
+
// special case for hashing
|
|
122
|
+
return true;
|
|
123
|
+
}
|
|
124
|
+
return this._ignorer.ignores(filepath);
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Recursively walks through the directory and yields all non-ignored
|
|
128
|
+
* files and directories within it.
|
|
129
|
+
*
|
|
130
|
+
* @yields - The normalized path of each file and directory.
|
|
131
|
+
*/ async *walk({ dir = this.path } = {}) {
|
|
132
|
+
// don't yield the root directory
|
|
133
|
+
if (dir !== this.path) {
|
|
134
|
+
yield this.normalize(dir, true);
|
|
135
|
+
}
|
|
136
|
+
for await (const entry of (await fs.opendir(dir))){
|
|
137
|
+
const filepath = path.join(dir, entry.name);
|
|
138
|
+
if (this.ignores(filepath)) {
|
|
139
|
+
continue;
|
|
140
|
+
}
|
|
141
|
+
if (entry.isDirectory()) {
|
|
142
|
+
yield* this.walk({
|
|
143
|
+
dir: filepath
|
|
144
|
+
});
|
|
145
|
+
} else if (entry.isFile()) {
|
|
146
|
+
yield this.normalize(filepath, false);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Calculates the hash of each file and directory and returns an
|
|
152
|
+
* object containing the hashes keyed by the normalized file path.
|
|
153
|
+
*
|
|
154
|
+
* @returns A Promise that resolves to an object containing the hashes
|
|
155
|
+
* of each file.
|
|
156
|
+
*/ async hashes() {
|
|
157
|
+
try {
|
|
158
|
+
this._isHashing = true;
|
|
159
|
+
const files = {};
|
|
160
|
+
for await (const normalizedPath of this.walk()){
|
|
161
|
+
const absolutePath = this.absolute(normalizedPath);
|
|
162
|
+
files[normalizedPath] = await hash(absolutePath);
|
|
163
|
+
}
|
|
164
|
+
return files;
|
|
165
|
+
} finally{
|
|
166
|
+
this._isHashing = false;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
constructor(/**
|
|
170
|
+
* An absolute path to the directory that is being synced.
|
|
171
|
+
*/ path){
|
|
172
|
+
_define_property(this, "path", void 0);
|
|
173
|
+
/**
|
|
174
|
+
* A gitignore-style file parser used to determine which files to
|
|
175
|
+
* ignore while syncing.
|
|
176
|
+
*
|
|
177
|
+
* @see https://www.npmjs.com/package/ignore
|
|
178
|
+
*/ _define_property(this, "_ignorer", void 0);
|
|
179
|
+
/**
|
|
180
|
+
* Whether the directory is currently being hashed.
|
|
181
|
+
*/ _define_property(this, "_isHashing", void 0);
|
|
182
|
+
this.path = path;
|
|
183
|
+
this._isHashing = false;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Whether the current platform supports Unix-style file permissions.
|
|
188
|
+
*
|
|
189
|
+
* Windows doesn't support Unix-style file permissions and all file
|
|
190
|
+
* permissions retrieved via `node:fs` on Windows are translated to 666
|
|
191
|
+
* or 444.
|
|
192
|
+
*/ export const supportsPermissions = process.platform === "linux" || process.platform === "darwin";
|
|
193
|
+
/**
|
|
194
|
+
* Calculates the {@linkcode Hash} of the file or directory at the
|
|
195
|
+
* specified absolute path.
|
|
196
|
+
*
|
|
197
|
+
* @param absolutePath The absolute path to the file or directory.
|
|
198
|
+
* @returns A Promise that resolves to the {@linkcode Hash} of the file
|
|
199
|
+
* or directory.
|
|
200
|
+
*/ const hash = async (absolutePath)=>{
|
|
201
|
+
const sha1 = createHash("sha1");
|
|
202
|
+
sha1.update(path.basename(absolutePath));
|
|
203
|
+
const stats = await fs.stat(absolutePath);
|
|
204
|
+
let permissions;
|
|
205
|
+
if (supportsPermissions) {
|
|
206
|
+
// strip everything but the permissions
|
|
207
|
+
permissions = stats.mode & 0o777;
|
|
208
|
+
}
|
|
209
|
+
if (stats.isDirectory()) {
|
|
210
|
+
return {
|
|
211
|
+
sha1: sha1.digest("hex"),
|
|
212
|
+
permissions
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
// windows uses CRLF line endings whereas unix uses LF line endings so
|
|
216
|
+
// we always strip out CR bytes (0x0d) when hashing files. this does
|
|
217
|
+
// make us blind to files that only differ by CR bytes, but that's a
|
|
218
|
+
// tradeoff we're willing to make.
|
|
219
|
+
const removeCR = new Transform({
|
|
220
|
+
transform (chunk, _encoding, callback) {
|
|
221
|
+
if (!chunk.includes(0x0d)) {
|
|
222
|
+
callback(undefined, chunk);
|
|
223
|
+
return;
|
|
224
|
+
}
|
|
225
|
+
const filteredChunk = Buffer.alloc(chunk.length);
|
|
226
|
+
let i = 0;
|
|
227
|
+
for (const byte of chunk){
|
|
228
|
+
if (byte !== 0x0d) {
|
|
229
|
+
filteredChunk[i++] = byte;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
callback(undefined, filteredChunk.slice(0, i));
|
|
233
|
+
}
|
|
234
|
+
});
|
|
235
|
+
await pipeline(fs.createReadStream(absolutePath), removeCR, sha1);
|
|
236
|
+
return {
|
|
237
|
+
sha1: sha1.digest("hex"),
|
|
238
|
+
permissions
|
|
239
|
+
};
|
|
240
|
+
};
|
|
241
|
+
/**
|
|
242
|
+
* Swallows ENOENT errors and throws any other errors.
|
|
243
|
+
*
|
|
244
|
+
* @param error - The error to handle.
|
|
245
|
+
* @throws The original error if it is not an ENOENT error.
|
|
246
|
+
*/ export const swallowEnoent = (error)=>{
|
|
247
|
+
if (error && typeof error === "object" && "code" in error && error.code === "ENOENT") {
|
|
248
|
+
return;
|
|
249
|
+
}
|
|
250
|
+
throw error;
|
|
251
|
+
};
|
|
252
|
+
|
|
253
|
+
//# sourceMappingURL=directory.js.map
|