@ethlete/cli 3.0.0-next.17 → 3.0.0-next.18

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.
Files changed (54) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/package.json +1 -1
  3. package/src/lib/api/api-context.d.ts +15 -0
  4. package/src/lib/api/api-context.js +23 -0
  5. package/src/lib/api/api-context.js.map +1 -0
  6. package/src/lib/api/api-state.d.ts +31 -0
  7. package/src/lib/api/api-state.js +80 -0
  8. package/src/lib/api/api-state.js.map +1 -0
  9. package/src/lib/api/definition.d.ts +37 -1
  10. package/src/lib/api/definition.js +6 -0
  11. package/src/lib/api/definition.js.map +1 -1
  12. package/src/lib/api/doctor.d.ts +16 -0
  13. package/src/lib/api/doctor.js +71 -0
  14. package/src/lib/api/doctor.js.map +1 -0
  15. package/src/lib/api/fingerprint.d.ts +18 -0
  16. package/src/lib/api/fingerprint.js +63 -0
  17. package/src/lib/api/fingerprint.js.map +1 -0
  18. package/src/lib/api/git.d.ts +2 -0
  19. package/src/lib/api/git.js +7 -1
  20. package/src/lib/api/git.js.map +1 -1
  21. package/src/lib/api/help.js +13 -0
  22. package/src/lib/api/help.js.map +1 -1
  23. package/src/lib/api/index.d.ts +3 -0
  24. package/src/lib/api/index.js +3 -0
  25. package/src/lib/api/index.js.map +1 -1
  26. package/src/lib/api/load-definitions.js +3 -0
  27. package/src/lib/api/load-definitions.js.map +1 -1
  28. package/src/lib/api/lock.d.ts +46 -0
  29. package/src/lib/api/lock.js +144 -0
  30. package/src/lib/api/lock.js.map +1 -0
  31. package/src/lib/api/parse-argv.d.ts +12 -0
  32. package/src/lib/api/parse-argv.js +31 -0
  33. package/src/lib/api/parse-argv.js.map +1 -0
  34. package/src/lib/api/run-locked.d.ts +14 -0
  35. package/src/lib/api/run-locked.js +62 -0
  36. package/src/lib/api/run-locked.js.map +1 -0
  37. package/src/lib/api/run-ready.d.ts +60 -0
  38. package/src/lib/api/run-ready.js +212 -0
  39. package/src/lib/api/run-ready.js.map +1 -0
  40. package/src/lib/api/run-snapshot.d.ts +33 -0
  41. package/src/lib/api/run-snapshot.js +124 -0
  42. package/src/lib/api/run-snapshot.js.map +1 -0
  43. package/src/lib/api/run-status.d.ts +9 -0
  44. package/src/lib/api/run-status.js +55 -0
  45. package/src/lib/api/run-status.js.map +1 -0
  46. package/src/lib/api/run.d.ts +1 -1
  47. package/src/lib/api/run.js +122 -8
  48. package/src/lib/api/run.js.map +1 -1
  49. package/src/lib/api/snapshot.d.ts +63 -0
  50. package/src/lib/api/snapshot.js +132 -0
  51. package/src/lib/api/snapshot.js.map +1 -0
  52. package/src/lib/api/validate-definition.d.ts +7 -0
  53. package/src/lib/api/validate-definition.js +79 -0
  54. package/src/lib/api/validate-definition.js.map +1 -0
@@ -0,0 +1,63 @@
1
+ import { ApiProfile } from './definition';
2
+ export type ApiSnapshotConfig = NonNullable<ApiProfile['snapshot']>;
3
+ /** How to reach the container engine: the compose binary with its fixed arguments, in the API's compose directory. */
4
+ export type ComposeInvocation = {
5
+ binary: string;
6
+ prefix: string[];
7
+ cwd: string;
8
+ env: NodeJS.ProcessEnv;
9
+ };
10
+ export declare const SNAPSHOT_NAME: RegExp;
11
+ export declare const snapshotsDirectory: (root: string, api: string) => string;
12
+ export declare const snapshotFileName: (options: {
13
+ name: string;
14
+ fingerprint: string;
15
+ }) => string;
16
+ export declare const snapshotFilePath: (options: {
17
+ root: string;
18
+ api: string;
19
+ name: string;
20
+ fingerprint: string;
21
+ }) => string;
22
+ /** The snapshot files of one API, or only the ones made for `fingerprint`. */
23
+ export declare const listSnapshots: (options: {
24
+ root: string;
25
+ api: string;
26
+ fingerprint?: string;
27
+ }) => string[];
28
+ /** Pipes `producer`'s stdout through gzip into `file`, which appears only when the producer exits 0. */
29
+ export declare const pipeToGzipFile: (options: {
30
+ command: string;
31
+ args: string[];
32
+ cwd?: string;
33
+ env?: NodeJS.ProcessEnv;
34
+ file: string;
35
+ }) => Promise<number>;
36
+ /** Pipes the gunzipped `file` into the stdin of `consumer` and returns its exit code. */
37
+ export declare const pipeFromGzipFile: (options: {
38
+ command: string;
39
+ args: string[];
40
+ cwd?: string;
41
+ env?: NodeJS.ProcessEnv;
42
+ file: string;
43
+ }) => Promise<number>;
44
+ /** Dumps the profile's databases into `file`. Safe to call while holding the API lock. */
45
+ export declare const saveSnapshot: (options: {
46
+ file: string;
47
+ snapshot: ApiSnapshotConfig;
48
+ compose: ComposeInvocation;
49
+ }) => Promise<number>;
50
+ /**
51
+ * Loads `file` into the profile's databases. With `state`, a success records the API as clean for that
52
+ * profile and fingerprint and a failure marks it dirty. Safe to call while holding the API lock.
53
+ */
54
+ export declare const restoreSnapshot: (options: {
55
+ file: string;
56
+ snapshot: ApiSnapshotConfig;
57
+ compose: ComposeInvocation;
58
+ state?: {
59
+ directory: string;
60
+ profile: string;
61
+ fingerprint: string;
62
+ };
63
+ }) => Promise<number>;
@@ -0,0 +1,132 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.restoreSnapshot = exports.saveSnapshot = exports.pipeFromGzipFile = exports.pipeToGzipFile = exports.listSnapshots = exports.snapshotFilePath = exports.snapshotFileName = exports.snapshotsDirectory = exports.SNAPSHOT_NAME = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const child_process_1 = require("child_process");
6
+ const crypto_1 = require("crypto");
7
+ const fs_1 = require("fs");
8
+ const path_1 = require("path");
9
+ const promises_1 = require("stream/promises");
10
+ const zlib_1 = require("zlib");
11
+ const api_state_1 = require("./api-state");
12
+ const clone_1 = require("./clone");
13
+ const seeds_1 = require("./seeds");
14
+ const SNAPSHOT_SUFFIX = '.sql.gz';
15
+ exports.SNAPSHOT_NAME = /^[\w.-]+$/;
16
+ const snapshotsDirectory = (root, api) => (0, path_1.join)(root, clone_1.DEFAULT_CHECKOUT_DIR, 'snapshots', api);
17
+ exports.snapshotsDirectory = snapshotsDirectory;
18
+ const snapshotFileName = (options) => `${options.name}-${options.fingerprint}${SNAPSHOT_SUFFIX}`;
19
+ exports.snapshotFileName = snapshotFileName;
20
+ const snapshotFilePath = (options) => (0, path_1.join)((0, exports.snapshotsDirectory)(options.root, options.api), (0, exports.snapshotFileName)(options));
21
+ exports.snapshotFilePath = snapshotFilePath;
22
+ /** The snapshot files of one API, or only the ones made for `fingerprint`. */
23
+ const listSnapshots = (options) => {
24
+ const directory = (0, exports.snapshotsDirectory)(options.root, options.api);
25
+ if (!(0, fs_1.existsSync)(directory))
26
+ return [];
27
+ return (0, fs_1.readdirSync)(directory)
28
+ .filter((file) => file.endsWith(SNAPSHOT_SUFFIX))
29
+ .filter((file) => options.fingerprint === undefined || file.endsWith(`-${options.fingerprint}${SNAPSHOT_SUFFIX}`))
30
+ .sort();
31
+ };
32
+ exports.listSnapshots = listSnapshots;
33
+ const snapshotScript = (snapshot, line) => `export DATABASES=${(0, seeds_1.shellQuote)(snapshot.databases.join(' '))}\n${line}`;
34
+ const composeExecArgs = (options) => [
35
+ ...options.compose.prefix,
36
+ 'exec',
37
+ '-T',
38
+ options.snapshot.service,
39
+ 'sh',
40
+ '-c',
41
+ snapshotScript(options.snapshot, options.line),
42
+ ];
43
+ const exitCodeOf = (child) => new Promise((resolve) => {
44
+ child.once('error', (error) => {
45
+ console.error(`Could not run ${(0, path_1.basename)(child.spawnfile)}: ${error.message}`);
46
+ resolve(127);
47
+ });
48
+ child.once('close', (code, signal) => resolve(code !== null && code !== void 0 ? code : (signal ? 128 : 1)));
49
+ });
50
+ /** Pipes `producer`'s stdout through gzip into `file`, which appears only when the producer exits 0. */
51
+ const pipeToGzipFile = (options) => tslib_1.__awaiter(void 0, void 0, void 0, function* () {
52
+ const { command, args, cwd, env, file } = options;
53
+ const temporary = `${file}.${(0, crypto_1.randomUUID)()}.tmp`;
54
+ (0, fs_1.mkdirSync)((0, path_1.dirname)(file), { recursive: true });
55
+ const child = (0, child_process_1.spawn)(command, args, { cwd, env, stdio: ['ignore', 'pipe', 'inherit'] });
56
+ const code = exitCodeOf(child);
57
+ const written = child.stdout
58
+ ? (0, promises_1.pipeline)(child.stdout, (0, zlib_1.createGzip)(), (0, fs_1.createWriteStream)(temporary)).then(() => true, () => false)
59
+ : Promise.resolve(false);
60
+ const [exitCode, complete] = yield Promise.all([code, written]);
61
+ if (exitCode === 0 && complete) {
62
+ (0, fs_1.renameSync)(temporary, file);
63
+ return 0;
64
+ }
65
+ (0, fs_1.rmSync)(temporary, { force: true });
66
+ return exitCode === 0 ? 1 : exitCode;
67
+ });
68
+ exports.pipeToGzipFile = pipeToGzipFile;
69
+ /** Pipes the gunzipped `file` into the stdin of `consumer` and returns its exit code. */
70
+ const pipeFromGzipFile = (options) => tslib_1.__awaiter(void 0, void 0, void 0, function* () {
71
+ const { command, args, cwd, env, file } = options;
72
+ const child = (0, child_process_1.spawn)(command, args, { cwd, env, stdio: ['pipe', 'inherit', 'inherit'] });
73
+ const code = exitCodeOf(child);
74
+ const read = child.stdin
75
+ ? (0, promises_1.pipeline)((0, fs_1.createReadStream)(file), (0, zlib_1.createGunzip)(), child.stdin).then(() => true, () => false)
76
+ : Promise.resolve(false);
77
+ const [exitCode, complete] = yield Promise.all([code, read]);
78
+ return exitCode === 0 && !complete ? 1 : exitCode;
79
+ });
80
+ exports.pipeFromGzipFile = pipeFromGzipFile;
81
+ /** Dumps the profile's databases into `file`. Safe to call while holding the API lock. */
82
+ const saveSnapshot = (options) => tslib_1.__awaiter(void 0, void 0, void 0, function* () {
83
+ const { file, snapshot, compose } = options;
84
+ const code = yield (0, exports.pipeToGzipFile)({
85
+ command: compose.binary,
86
+ args: composeExecArgs({ compose, snapshot, line: snapshot.save }),
87
+ cwd: compose.cwd,
88
+ env: compose.env,
89
+ file,
90
+ });
91
+ if (code !== 0)
92
+ console.error(`Saving the snapshot failed with exit code ${code}. Nothing was written to ${file}.`);
93
+ return code;
94
+ });
95
+ exports.saveSnapshot = saveSnapshot;
96
+ /**
97
+ * Loads `file` into the profile's databases. With `state`, a success records the API as clean for that
98
+ * profile and fingerprint and a failure marks it dirty. Safe to call while holding the API lock.
99
+ */
100
+ const restoreSnapshot = (options) => tslib_1.__awaiter(void 0, void 0, void 0, function* () {
101
+ const { file, snapshot, compose, state } = options;
102
+ if (!(0, fs_1.existsSync)(file)) {
103
+ const directory = (0, path_1.dirname)(file);
104
+ const names = (0, fs_1.existsSync)(directory) ? (0, fs_1.readdirSync)(directory).filter((name) => name.endsWith(SNAPSHOT_SUFFIX)) : [];
105
+ console.error(names.length === 0
106
+ ? `No snapshot at ${file}, and none exist for this API.`
107
+ : `No snapshot at ${file}. These exist:\n\n${names.map((name) => ` ${name}`).join('\n')}`);
108
+ return 1;
109
+ }
110
+ const code = yield (0, exports.pipeFromGzipFile)({
111
+ command: compose.binary,
112
+ args: composeExecArgs({ compose, snapshot, line: snapshot.restore }),
113
+ cwd: compose.cwd,
114
+ env: compose.env,
115
+ file,
116
+ });
117
+ if (code !== 0) {
118
+ console.error(`Restoring the snapshot failed with exit code ${code}.`);
119
+ if (state)
120
+ (0, api_state_1.markApiStateDirty)(state.directory);
121
+ return code;
122
+ }
123
+ if (state) {
124
+ (0, api_state_1.writeApiState)({
125
+ directory: state.directory,
126
+ state: { profile: state.profile, fingerprint: state.fingerprint, dirty: false },
127
+ });
128
+ }
129
+ return 0;
130
+ });
131
+ exports.restoreSnapshot = restoreSnapshot;
132
+ //# sourceMappingURL=snapshot.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"snapshot.js","sourceRoot":"","sources":["../../../../../../libs/cli/src/lib/api/snapshot.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import { ApiDefinition } from './definition';
2
+ /** Throws an error naming the file, the API and the path of the first field of `ready` and `doctor` that has the wrong shape. */
3
+ export declare const validateApiDefinition: ({ fileName, name, api, }: {
4
+ fileName: string;
5
+ name: string;
6
+ api: ApiDefinition;
7
+ }) => undefined;
@@ -0,0 +1,79 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.validateApiDefinition = void 0;
4
+ const isRecord = (value) => typeof value === 'object' && value !== null && !Array.isArray(value);
5
+ const isText = (value) => typeof value === 'string' && value.trim() !== '';
6
+ /** Throws an error naming the file, the API and the path of the first field of `ready` and `doctor` that has the wrong shape. */
7
+ const validateApiDefinition = ({ fileName, name, api, }) => {
8
+ const fail = (path, problem) => {
9
+ throw new Error(`${fileName}: ${name}${path} ${problem}`);
10
+ };
11
+ const definition = isRecord(api) ? api : {};
12
+ const { checks, profiles, migrationsDir } = definition;
13
+ const services = Array.isArray(definition['services']) ? definition['services'] : [];
14
+ if (migrationsDir !== undefined && !isText(migrationsDir))
15
+ fail('.migrationsDir', 'must be a non-empty path');
16
+ if (checks !== undefined) {
17
+ if (!Array.isArray(checks))
18
+ fail('.checks', 'must be a list');
19
+ const names = new Set();
20
+ checks.forEach((entry, index) => {
21
+ const path = `.checks[${index}]`;
22
+ if (!isRecord(entry))
23
+ return fail(path, 'must be an object');
24
+ if (!isText(entry['name']))
25
+ fail(`${path}.name`, 'must be a non-empty string');
26
+ if (names.has(entry['name']))
27
+ fail(`${path}.name`, `"${entry['name']}" is declared twice`);
28
+ names.add(entry['name']);
29
+ if (!isText(entry['check']))
30
+ fail(`${path}.check`, 'must be a shell line');
31
+ if (entry['fix'] !== undefined && !isText(entry['fix']))
32
+ fail(`${path}.fix`, 'must be a shell line');
33
+ if (entry['host'] !== undefined && typeof entry['host'] !== 'boolean')
34
+ fail(`${path}.host`, 'must be a boolean');
35
+ if (entry['service'] !== undefined && !services.includes(entry['service'])) {
36
+ fail(`${path}.service`, `must be one of services: ${services.join(', ')}`);
37
+ }
38
+ });
39
+ }
40
+ if (profiles !== undefined) {
41
+ if (!isRecord(profiles))
42
+ fail('.profiles', 'must be an object');
43
+ for (const [profileName, profile] of Object.entries(profiles)) {
44
+ const path = `.profiles.${profileName}`;
45
+ if (!isRecord(profile))
46
+ return fail(path, 'must be an object');
47
+ const { seeds, health, snapshot } = profile;
48
+ if (!Array.isArray(seeds) || seeds.length === 0 || !seeds.every(isText)) {
49
+ fail(`${path}.seeds`, 'must be a non-empty list of seed names');
50
+ }
51
+ if (health !== undefined) {
52
+ if (!isRecord(health))
53
+ return fail(`${path}.health`, 'must be an object');
54
+ if (!isText(health['url']))
55
+ fail(`${path}.health.url`, 'must be a string');
56
+ if (health['expect'] !== undefined && !Number.isInteger(health['expect'])) {
57
+ fail(`${path}.health.expect`, 'must be an integer');
58
+ }
59
+ }
60
+ if (snapshot !== undefined) {
61
+ if (!isRecord(snapshot))
62
+ return fail(`${path}.snapshot`, 'must be an object');
63
+ if (!isText(snapshot['service']))
64
+ fail(`${path}.snapshot.service`, 'must be a service name');
65
+ if (!Array.isArray(snapshot['databases']) ||
66
+ snapshot['databases'].length === 0 ||
67
+ !snapshot['databases'].every(isText)) {
68
+ fail(`${path}.snapshot.databases`, 'must be a non-empty list of database names');
69
+ }
70
+ if (!isText(snapshot['save']))
71
+ fail(`${path}.snapshot.save`, 'must be a shell line');
72
+ if (!isText(snapshot['restore']))
73
+ fail(`${path}.snapshot.restore`, 'must be a shell line');
74
+ }
75
+ }
76
+ }
77
+ };
78
+ exports.validateApiDefinition = validateApiDefinition;
79
+ //# sourceMappingURL=validate-definition.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate-definition.js","sourceRoot":"","sources":["../../../../../../libs/cli/src/lib/api/validate-definition.ts"],"names":[],"mappings":"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"}