@ethlete/cli 2.0.1-next.0 → 2.1.0-next.10
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/CHANGELOG.md +107 -0
- package/README.md +173 -6
- package/design/define-call.ts +92 -0
- package/design/web/env.d.ts +11 -0
- package/design/web/frame.html +17 -0
- package/design/web/frame.ts +38 -0
- package/design/web/host.css +494 -0
- package/design/web/host.ts +445 -0
- package/design/web/index.html +11 -0
- package/package.json +12 -1
- package/src/index.d.ts +1 -1
- package/src/index.js +96 -10
- package/src/index.js.map +1 -1
- package/src/lib/api/api-command.d.ts +5 -0
- package/src/lib/api/api-command.js +27 -0
- package/src/lib/api/api-command.js.map +1 -0
- package/src/lib/api/auth-hint.d.ts +16 -0
- package/src/lib/api/auth-hint.js +59 -0
- package/src/lib/api/auth-hint.js.map +1 -0
- package/src/lib/api/clear.d.ts +36 -0
- package/src/lib/api/clear.js +121 -0
- package/src/lib/api/clear.js.map +1 -0
- package/src/lib/api/clone.d.ts +12 -0
- package/src/lib/api/clone.js +24 -0
- package/src/lib/api/clone.js.map +1 -0
- package/src/lib/api/compose.d.ts +46 -0
- package/src/lib/api/compose.js +101 -0
- package/src/lib/api/compose.js.map +1 -0
- package/src/lib/api/definition.d.ts +37 -0
- package/src/lib/api/definition.js +33 -0
- package/src/lib/api/definition.js.map +1 -0
- package/src/lib/api/git.d.ts +25 -0
- package/src/lib/api/git.js +71 -0
- package/src/lib/api/git.js.map +1 -0
- package/src/lib/api/help.d.ts +11 -0
- package/src/lib/api/help.js +72 -0
- package/src/lib/api/help.js.map +1 -0
- package/src/lib/api/index.d.ts +15 -0
- package/src/lib/api/index.js +19 -0
- package/src/lib/api/index.js.map +1 -0
- package/src/lib/api/load-definitions.d.ts +16 -0
- package/src/lib/api/load-definitions.js +22 -0
- package/src/lib/api/load-definitions.js.map +1 -0
- package/src/lib/api/ports.d.ts +13 -0
- package/src/lib/api/ports.js +98 -0
- package/src/lib/api/ports.js.map +1 -0
- package/src/lib/api/resolve-checkout.d.ts +45 -0
- package/src/lib/api/resolve-checkout.js +91 -0
- package/src/lib/api/resolve-checkout.js.map +1 -0
- package/src/lib/api/run.d.ts +10 -0
- package/src/lib/api/run.js +332 -0
- package/src/lib/api/run.js.map +1 -0
- package/src/lib/api/setup.d.ts +15 -0
- package/src/lib/api/setup.js +41 -0
- package/src/lib/api/setup.js.map +1 -0
- package/src/lib/api/state.d.ts +20 -0
- package/src/lib/api/state.js +33 -0
- package/src/lib/api/state.js.map +1 -0
- package/src/lib/api/suggest.d.ts +7 -0
- package/src/lib/api/suggest.js +35 -0
- package/src/lib/api/suggest.js.map +1 -0
- package/src/lib/auth/auth-command.d.ts +11 -0
- package/src/lib/auth/auth-command.js +165 -0
- package/src/lib/auth/auth-command.js.map +1 -0
- package/src/lib/auth/composer-auth.d.ts +30 -0
- package/src/lib/auth/composer-auth.js +70 -0
- package/src/lib/auth/composer-auth.js.map +1 -0
- package/src/lib/auth/composer-repositories.d.ts +5 -0
- package/src/lib/auth/composer-repositories.js +33 -0
- package/src/lib/auth/composer-repositories.js.map +1 -0
- package/src/lib/auth/gitlab-token.d.ts +43 -0
- package/src/lib/auth/gitlab-token.js +72 -0
- package/src/lib/auth/gitlab-token.js.map +1 -0
- package/src/lib/auth/index.d.ts +4 -0
- package/src/lib/auth/index.js +8 -0
- package/src/lib/auth/index.js.map +1 -0
- package/src/lib/config/diagnose.d.ts +7 -0
- package/src/lib/config/diagnose.js +112 -0
- package/src/lib/config/diagnose.js.map +1 -0
- package/src/lib/config/index.d.ts +2 -0
- package/src/lib/config/index.js +6 -0
- package/src/lib/config/index.js.map +1 -0
- package/src/lib/config/local-config.d.ts +46 -0
- package/src/lib/config/local-config.js +57 -0
- package/src/lib/config/local-config.js.map +1 -0
- package/src/lib/design/calls-tsconfig.d.ts +6 -0
- package/src/lib/design/calls-tsconfig.js +37 -0
- package/src/lib/design/calls-tsconfig.js.map +1 -0
- package/src/lib/design/check.d.ts +11 -0
- package/src/lib/design/check.js +192 -0
- package/src/lib/design/check.js.map +1 -0
- package/src/lib/design/design-command.d.ts +10 -0
- package/src/lib/design/design-command.js +32 -0
- package/src/lib/design/design-command.js.map +1 -0
- package/src/lib/design/index.d.ts +5 -0
- package/src/lib/design/index.js +9 -0
- package/src/lib/design/index.js.map +1 -0
- package/src/lib/design/paths.d.ts +24 -0
- package/src/lib/design/paths.js +31 -0
- package/src/lib/design/paths.js.map +1 -0
- package/src/lib/design/serve.d.ts +7 -0
- package/src/lib/design/serve.js +144 -0
- package/src/lib/design/serve.js.map +1 -0
- package/src/lib/doctor/doctor-command.d.ts +7 -0
- package/src/lib/doctor/doctor-command.js +62 -0
- package/src/lib/doctor/doctor-command.js.map +1 -0
- package/src/lib/doctor/index.d.ts +1 -0
- package/src/lib/doctor/index.js +5 -0
- package/src/lib/doctor/index.js.map +1 -0
- package/src/lib/index.d.ts +7 -0
- package/src/lib/index.js +7 -0
- package/src/lib/index.js.map +1 -1
- package/src/lib/invocation.d.ts +9 -0
- package/src/lib/invocation.js +47 -0
- package/src/lib/invocation.js.map +1 -0
- package/src/lib/release.js +21 -3
- package/src/lib/release.js.map +1 -1
- package/src/lib/update/ai.d.ts +30 -0
- package/src/lib/update/ai.js +44 -0
- package/src/lib/update/ai.js.map +1 -0
- package/src/lib/update/args.d.ts +21 -0
- package/src/lib/update/args.js +89 -0
- package/src/lib/update/args.js.map +1 -0
- package/src/lib/update/index.d.ts +12 -0
- package/src/lib/update/index.js +16 -0
- package/src/lib/update/index.js.map +1 -0
- package/src/lib/update/migration-manifest.d.ts +40 -0
- package/src/lib/update/migration-manifest.js +137 -0
- package/src/lib/update/migration-manifest.js.map +1 -0
- package/src/lib/update/package-manager.d.ts +23 -0
- package/src/lib/update/package-manager.js +47 -0
- package/src/lib/update/package-manager.js.map +1 -0
- package/src/lib/update/packages.d.ts +65 -0
- package/src/lib/update/packages.js +147 -0
- package/src/lib/update/packages.js.map +1 -0
- package/src/lib/update/pending.d.ts +21 -0
- package/src/lib/update/pending.js +41 -0
- package/src/lib/update/pending.js.map +1 -0
- package/src/lib/update/plan.d.ts +51 -0
- package/src/lib/update/plan.js +101 -0
- package/src/lib/update/plan.js.map +1 -0
- package/src/lib/update/registry.d.ts +31 -0
- package/src/lib/update/registry.js +54 -0
- package/src/lib/update/registry.js.map +1 -0
- package/src/lib/update/run-migrations.d.ts +44 -0
- package/src/lib/update/run-migrations.js +73 -0
- package/src/lib/update/run-migrations.js.map +1 -0
- package/src/lib/update/semver.d.ts +19 -0
- package/src/lib/update/semver.js +79 -0
- package/src/lib/update/semver.js.map +1 -0
- package/src/lib/update/tasks.d.ts +58 -0
- package/src/lib/update/tasks.js +174 -0
- package/src/lib/update/tasks.js.map +1 -0
- package/src/lib/update/update-command.d.ts +12 -0
- package/src/lib/update/update-command.js +304 -0
- package/src/lib/update/update-command.js.map +1 -0
- package/src/lib/utils.d.ts +14 -0
- package/src/lib/utils.js +14 -1
- package/src/lib/utils.js.map +1 -1
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.gitUrlProjectPath = exports.gitHostFromInput = exports.gitUrlHost = exports.printPrivateDependencyHint = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* A private dependency that will not download is the most common way these commands fail, and git
|
|
6
|
+
* and the package managers report it as a bare 403 or a public-key error. This says what to check.
|
|
7
|
+
*/
|
|
8
|
+
const printPrivateDependencyHint = (options) => {
|
|
9
|
+
var _a;
|
|
10
|
+
const host = (_a = options.repoHost) !== null && _a !== void 0 ? _a : 'your git host';
|
|
11
|
+
console.error(`\nThat command may have failed because a private dependency could not be downloaded.\n` +
|
|
12
|
+
`Three things are worth checking:\n\n` +
|
|
13
|
+
` 1. A personal access token for ${host} with permission to DOWNLOAD code.\n` +
|
|
14
|
+
` Read access is not enough for a clone, and the server reports the difference as 403.\n` +
|
|
15
|
+
` 2. An SSH key this machine offers to ${host}, when the dependency is fetched over SSH.\n` +
|
|
16
|
+
` 3. That the token is where the package manager looks for it, not only in your shell.\n` +
|
|
17
|
+
` Composer, for example, reads ~/.composer/auth.json rather than the environment.`);
|
|
18
|
+
};
|
|
19
|
+
exports.printPrivateDependencyHint = printPrivateDependencyHint;
|
|
20
|
+
/** The host of a git url, for naming it in the hint. Undefined when the url has no host. */
|
|
21
|
+
const gitUrlHost = (repoUrl) => {
|
|
22
|
+
const scpLike = /^[^/]+@([^:]+):/.exec(repoUrl);
|
|
23
|
+
if (scpLike)
|
|
24
|
+
return scpLike[1];
|
|
25
|
+
try {
|
|
26
|
+
return new URL(repoUrl).hostname || undefined;
|
|
27
|
+
}
|
|
28
|
+
catch (_a) {
|
|
29
|
+
return undefined;
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
exports.gitUrlHost = gitUrlHost;
|
|
33
|
+
/**
|
|
34
|
+
* The host a user names on the command line, which is often pasted as a url: `https://git.example.com/`
|
|
35
|
+
* holds the same host as `git.example.com`. Undefined when there is no host name in it at all.
|
|
36
|
+
*/
|
|
37
|
+
const gitHostFromInput = (value) => {
|
|
38
|
+
var _a;
|
|
39
|
+
const trimmed = value.trim();
|
|
40
|
+
if (!trimmed || trimmed.startsWith('/'))
|
|
41
|
+
return undefined;
|
|
42
|
+
return (_a = (0, exports.gitUrlHost)(trimmed)) !== null && _a !== void 0 ? _a : (0, exports.gitUrlHost)(`https://${trimmed}`);
|
|
43
|
+
};
|
|
44
|
+
exports.gitHostFromInput = gitHostFromInput;
|
|
45
|
+
/** The `group/project` part of a git url, for addressing the project in a host's own API. */
|
|
46
|
+
const gitUrlProjectPath = (repoUrl) => {
|
|
47
|
+
var _a;
|
|
48
|
+
const scpLike = /^[^/]+@[^:]+:(.+)$/.exec(repoUrl);
|
|
49
|
+
if (scpLike)
|
|
50
|
+
return ((_a = scpLike[1]) !== null && _a !== void 0 ? _a : '').replace(/\.git$/, '') || undefined;
|
|
51
|
+
try {
|
|
52
|
+
return new URL(repoUrl).pathname.replace(/^\/+/, '').replace(/\.git$/, '') || undefined;
|
|
53
|
+
}
|
|
54
|
+
catch (_b) {
|
|
55
|
+
return undefined;
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
exports.gitUrlProjectPath = gitUrlProjectPath;
|
|
59
|
+
//# sourceMappingURL=auth-hint.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth-hint.js","sourceRoot":"","sources":["../../../../../../libs/cli/src/lib/api/auth-hint.ts"],"names":[],"mappings":";;;AAAA;;;GAGG;AACI,MAAM,0BAA0B,GAAG,CAAC,OAA8B,EAAE,EAAE;;IAC3E,MAAM,IAAI,GAAG,MAAA,OAAO,CAAC,QAAQ,mCAAI,eAAe,CAAC;IAEjD,OAAO,CAAC,KAAK,CACX,wFAAwF;QACtF,sCAAsC;QACtC,oCAAoC,IAAI,sCAAsC;QAC9E,6FAA6F;QAC7F,0CAA0C,IAAI,8CAA8C;QAC5F,0FAA0F;QAC1F,sFAAsF,CACzF,CAAC;AACJ,CAAC,CAAC;AAZW,QAAA,0BAA0B,8BAYrC;AAEF,4FAA4F;AACrF,MAAM,UAAU,GAAG,CAAC,OAAe,EAAE,EAAE;IAC5C,MAAM,OAAO,GAAG,iBAAiB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAEhD,IAAI,OAAO;QAAE,OAAO,OAAO,CAAC,CAAC,CAAC,CAAC;IAE/B,IAAI,CAAC;QACH,OAAO,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC,QAAQ,IAAI,SAAS,CAAC;IAChD,CAAC;IAAC,WAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC,CAAC;AAVW,QAAA,UAAU,cAUrB;AAEF;;;GAGG;AACI,MAAM,gBAAgB,GAAG,CAAC,KAAa,EAAE,EAAE;;IAChD,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;IAE7B,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,OAAO,SAAS,CAAC;IAE1D,OAAO,MAAA,IAAA,kBAAU,EAAC,OAAO,CAAC,mCAAI,IAAA,kBAAU,EAAC,WAAW,OAAO,EAAE,CAAC,CAAC;AACjE,CAAC,CAAC;AANW,QAAA,gBAAgB,oBAM3B;AAEF,6FAA6F;AACtF,MAAM,iBAAiB,GAAG,CAAC,OAAe,EAAE,EAAE;;IACnD,MAAM,OAAO,GAAG,oBAAoB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAEnD,IAAI,OAAO;QAAE,OAAO,CAAC,MAAA,OAAO,CAAC,CAAC,CAAC,mCAAI,EAAE,CAAC,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,IAAI,SAAS,CAAC;IAE1E,IAAI,CAAC;QACH,OAAO,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,IAAI,SAAS,CAAC;IAC1F,CAAC;IAAC,WAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC,CAAC;AAVW,QAAA,iBAAiB,qBAU5B"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { ApiDefinitions } from './definition';
|
|
2
|
+
export type ApiClearTarget = {
|
|
3
|
+
name: string;
|
|
4
|
+
/** Absolute path that would be removed. */
|
|
5
|
+
repoPath: string;
|
|
6
|
+
/** Directory that holds the compose file. */
|
|
7
|
+
composePath: string;
|
|
8
|
+
/** Whether any container of its compose project still exists. Those are taken down before the removal. */
|
|
9
|
+
hasContainers: boolean;
|
|
10
|
+
/** Why it must stay. Empty when it can be removed. */
|
|
11
|
+
blockers: string[];
|
|
12
|
+
};
|
|
13
|
+
export type ApiClearPlanOptions = {
|
|
14
|
+
apis: ApiDefinitions;
|
|
15
|
+
names: string[];
|
|
16
|
+
root: string;
|
|
17
|
+
invocation: string;
|
|
18
|
+
/** Skips the checks on uncommitted changes and unpushed commits. */
|
|
19
|
+
force: boolean;
|
|
20
|
+
/** Whether any container of the API's compose project exists. */
|
|
21
|
+
hasContainers: (composePath: string) => boolean;
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* What `clear` would do to each named API: the path it would remove, and every reason it must stay.
|
|
25
|
+
* An API without a managed checkout is left out, because there is nothing of ours to remove.
|
|
26
|
+
*/
|
|
27
|
+
export declare const planApiClear: (options: ApiClearPlanOptions) => ApiClearTarget[];
|
|
28
|
+
export type ApiClearOptions = ApiClearPlanOptions & {
|
|
29
|
+
/** Takes the containers of one compose project down. False when the compose command failed. */
|
|
30
|
+
takeDown: (composePath: string) => boolean;
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* Removes the managed checkout of each named API, after one question that defaults to no. It offers to
|
|
34
|
+
* take down the containers that still exist, and refuses an API with work only this checkout holds.
|
|
35
|
+
*/
|
|
36
|
+
export declare const clearApiCheckouts: (options: ApiClearOptions) => Promise<number>;
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.clearApiCheckouts = exports.planApiClear = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const fs_1 = require("fs");
|
|
6
|
+
const utils_1 = require("../utils");
|
|
7
|
+
const git_1 = require("./git");
|
|
8
|
+
const resolve_checkout_1 = require("./resolve-checkout");
|
|
9
|
+
const MAX_LISTED = 5;
|
|
10
|
+
/** The first few lines of a git listing, so a refusal shows what stands in the way. */
|
|
11
|
+
const listed = (lines) => [
|
|
12
|
+
...lines.slice(0, MAX_LISTED).map((line) => ` ${line}`),
|
|
13
|
+
...(lines.length > MAX_LISTED ? [` and ${lines.length - MAX_LISTED} more`] : []),
|
|
14
|
+
].join('\n');
|
|
15
|
+
/**
|
|
16
|
+
* What `clear` would do to each named API: the path it would remove, and every reason it must stay.
|
|
17
|
+
* An API without a managed checkout is left out, because there is nothing of ours to remove.
|
|
18
|
+
*/
|
|
19
|
+
const planApiClear = (options) => {
|
|
20
|
+
const { apis, names, root, invocation, force, hasContainers } = options;
|
|
21
|
+
return names.flatMap((name) => {
|
|
22
|
+
const api = apis[name];
|
|
23
|
+
if (!api)
|
|
24
|
+
return [];
|
|
25
|
+
const checkout = (0, resolve_checkout_1.resolveApiCheckout)({ root, name, api, needs: 'repo' });
|
|
26
|
+
if (!checkout.ok)
|
|
27
|
+
return [];
|
|
28
|
+
const { repoPath, composePath } = checkout.checkout;
|
|
29
|
+
const managed = (0, resolve_checkout_1.managedCheckoutPath)(root, name);
|
|
30
|
+
if (repoPath !== managed) {
|
|
31
|
+
return [
|
|
32
|
+
{
|
|
33
|
+
name,
|
|
34
|
+
repoPath,
|
|
35
|
+
composePath,
|
|
36
|
+
hasContainers: false,
|
|
37
|
+
blockers: [
|
|
38
|
+
`${repoPath} is your own checkout, not the one ${invocation} manages. ` +
|
|
39
|
+
`Remove it yourself, or drop apiRepoPaths.${name} first.`,
|
|
40
|
+
],
|
|
41
|
+
},
|
|
42
|
+
];
|
|
43
|
+
}
|
|
44
|
+
const changes = (0, git_1.uncommittedChanges)(repoPath);
|
|
45
|
+
const unpushed = (0, git_1.unpushedCommits)(repoPath);
|
|
46
|
+
return [
|
|
47
|
+
{
|
|
48
|
+
name,
|
|
49
|
+
repoPath,
|
|
50
|
+
composePath,
|
|
51
|
+
hasContainers: hasContainers(composePath),
|
|
52
|
+
blockers: [
|
|
53
|
+
...(!force && changes.length > 0
|
|
54
|
+
? [
|
|
55
|
+
`${repoPath} has uncommitted changes:\n\n${listed(changes)}\n\n` +
|
|
56
|
+
'Commit them, or pass --force to lose them.',
|
|
57
|
+
]
|
|
58
|
+
: []),
|
|
59
|
+
...(!force && unpushed.length > 0
|
|
60
|
+
? [
|
|
61
|
+
`${repoPath} has commits no remote holds:\n\n${listed(unpushed)}\n\n` +
|
|
62
|
+
'Push them, or pass --force to lose them.',
|
|
63
|
+
]
|
|
64
|
+
: []),
|
|
65
|
+
],
|
|
66
|
+
},
|
|
67
|
+
];
|
|
68
|
+
});
|
|
69
|
+
};
|
|
70
|
+
exports.planApiClear = planApiClear;
|
|
71
|
+
/**
|
|
72
|
+
* Removes the managed checkout of each named API, after one question that defaults to no. It offers to
|
|
73
|
+
* take down the containers that still exist, and refuses an API with work only this checkout holds.
|
|
74
|
+
*/
|
|
75
|
+
const clearApiCheckouts = (options) => tslib_1.__awaiter(void 0, void 0, void 0, function* () {
|
|
76
|
+
const { names, invocation, takeDown } = options;
|
|
77
|
+
const targets = (0, exports.planApiClear)(options);
|
|
78
|
+
const blocked = targets.filter(({ blockers }) => blockers.length > 0);
|
|
79
|
+
const removable = targets.filter(({ blockers }) => blockers.length === 0);
|
|
80
|
+
for (const { blockers } of blocked) {
|
|
81
|
+
console.error(blockers.join('\n\n'));
|
|
82
|
+
}
|
|
83
|
+
if (blocked.length > 0)
|
|
84
|
+
console.error('');
|
|
85
|
+
if (removable.length === 0) {
|
|
86
|
+
if (blocked.length === 0) {
|
|
87
|
+
console.log(`Nothing to remove. ${names.join(', ')} has no checkout ${invocation} manages.`);
|
|
88
|
+
}
|
|
89
|
+
return blocked.length > 0 ? 1 : 0;
|
|
90
|
+
}
|
|
91
|
+
const paths = removable.map(({ repoPath }) => ` ${repoPath}`).join('\n');
|
|
92
|
+
const running = removable.filter(({ hasContainers }) => hasContainers).map(({ name }) => name);
|
|
93
|
+
const stopped = running.join(', ');
|
|
94
|
+
const checkouts = removable.length === 1 ? 'the checkout' : 'the checkouts';
|
|
95
|
+
const accepted = yield (0, utils_1.confirm)({
|
|
96
|
+
problem: running.length > 0 ? `This takes ${stopped} down, then removes:\n\n${paths}` : `This removes:\n\n${paths}`,
|
|
97
|
+
question: running.length > 0
|
|
98
|
+
? `Take ${stopped} down and remove ${checkouts}?`
|
|
99
|
+
: `Remove ${removable.map(({ name }) => name).join(', ')}?`,
|
|
100
|
+
hint: running.length > 0
|
|
101
|
+
? `Re-run in a terminal to answer the question, or run "${invocation} down ${stopped}" and remove the ` +
|
|
102
|
+
'directories yourself.'
|
|
103
|
+
: 'Re-run in a terminal to answer the question, or remove the directories yourself.',
|
|
104
|
+
defaultsToYes: false,
|
|
105
|
+
});
|
|
106
|
+
if (!accepted)
|
|
107
|
+
return 1;
|
|
108
|
+
let failed = 0;
|
|
109
|
+
for (const { name, repoPath, composePath, hasContainers } of removable) {
|
|
110
|
+
if (hasContainers && !takeDown(composePath)) {
|
|
111
|
+
console.error(`Could not take ${name} down, so ${repoPath} stays.`);
|
|
112
|
+
failed += 1;
|
|
113
|
+
continue;
|
|
114
|
+
}
|
|
115
|
+
(0, fs_1.rmSync)(repoPath, { recursive: true, force: true });
|
|
116
|
+
console.log(`Removed ${repoPath}. Run "${invocation} clone ${name}" to get it back.`);
|
|
117
|
+
}
|
|
118
|
+
return blocked.length > 0 || failed > 0 ? 1 : 0;
|
|
119
|
+
});
|
|
120
|
+
exports.clearApiCheckouts = clearApiCheckouts;
|
|
121
|
+
//# sourceMappingURL=clear.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clear.js","sourceRoot":"","sources":["../../../../../../libs/cli/src/lib/api/clear.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export declare const DEFAULT_CHECKOUT_DIR = ".ethlete";
|
|
2
|
+
/** True when git would ignore the path, so a cloned checkout cannot be committed by accident. */
|
|
3
|
+
export declare const isGitIgnored: (root: string, path: string) => boolean;
|
|
4
|
+
export type CloneRequest = {
|
|
5
|
+
repoUrl: string;
|
|
6
|
+
/** Absolute path to clone into. */
|
|
7
|
+
into: string;
|
|
8
|
+
/** Branch to check out, from `apiRepoBranches`. */
|
|
9
|
+
branch?: string;
|
|
10
|
+
};
|
|
11
|
+
/** Clones an API repo into its managed directory. Git's own output and failures are passed through. */
|
|
12
|
+
export declare const cloneApiRepo: ({ repoUrl, into, branch }: CloneRequest) => number;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.cloneApiRepo = exports.isGitIgnored = exports.DEFAULT_CHECKOUT_DIR = void 0;
|
|
4
|
+
const child_process_1 = require("child_process");
|
|
5
|
+
const fs_1 = require("fs");
|
|
6
|
+
const path_1 = require("path");
|
|
7
|
+
const fs_2 = require("fs");
|
|
8
|
+
exports.DEFAULT_CHECKOUT_DIR = '.ethlete';
|
|
9
|
+
/** True when git would ignore the path, so a cloned checkout cannot be committed by accident. */
|
|
10
|
+
const isGitIgnored = (root, path) => (0, child_process_1.spawnSync)('git', ['check-ignore', '-q', path], { cwd: root }).status === 0;
|
|
11
|
+
exports.isGitIgnored = isGitIgnored;
|
|
12
|
+
/** Clones an API repo into its managed directory. Git's own output and failures are passed through. */
|
|
13
|
+
const cloneApiRepo = ({ repoUrl, into, branch }) => {
|
|
14
|
+
var _a;
|
|
15
|
+
if ((0, fs_1.existsSync)(into)) {
|
|
16
|
+
console.error(`${into} already exists.`);
|
|
17
|
+
return 1;
|
|
18
|
+
}
|
|
19
|
+
(0, fs_2.mkdirSync)((0, path_1.dirname)(into), { recursive: true });
|
|
20
|
+
const args = ['clone', ...(branch ? ['--branch', branch] : []), '--', repoUrl, into];
|
|
21
|
+
return (_a = (0, child_process_1.spawnSync)('git', args, { stdio: 'inherit' }).status) !== null && _a !== void 0 ? _a : 1;
|
|
22
|
+
};
|
|
23
|
+
exports.cloneApiRepo = cloneApiRepo;
|
|
24
|
+
//# sourceMappingURL=clone.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clone.js","sourceRoot":"","sources":["../../../../../../libs/cli/src/lib/api/clone.ts"],"names":[],"mappings":";;;AAAA,iDAA0C;AAC1C,2BAAgC;AAChC,+BAA+B;AAC/B,2BAA+B;AAElB,QAAA,oBAAoB,GAAG,UAAU,CAAC;AAE/C,iGAAiG;AAC1F,MAAM,YAAY,GAAG,CAAC,IAAY,EAAE,IAAY,EAAE,EAAE,CACzD,IAAA,yBAAS,EAAC,KAAK,EAAE,CAAC,cAAc,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC;AADhE,QAAA,YAAY,gBACoD;AAU7E,uGAAuG;AAChG,MAAM,YAAY,GAAG,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAgB,EAAE,EAAE;;IACtE,IAAI,IAAA,eAAU,EAAC,IAAI,CAAC,EAAE,CAAC;QACrB,OAAO,CAAC,KAAK,CAAC,GAAG,IAAI,kBAAkB,CAAC,CAAC;QAEzC,OAAO,CAAC,CAAC;IACX,CAAC;IAED,IAAA,cAAS,EAAC,IAAA,cAAO,EAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAE9C,MAAM,IAAI,GAAG,CAAC,OAAO,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;IAErF,OAAO,MAAA,IAAA,yBAAS,EAAC,KAAK,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC,MAAM,mCAAI,CAAC,CAAC;AAClE,CAAC,CAAC;AAZW,QAAA,YAAY,gBAYvB"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
export type ComposeTool = {
|
|
2
|
+
engine: string;
|
|
3
|
+
/** The binary and its fixed arguments. Non-empty, so the first entry is always the binary. */
|
|
4
|
+
compose: [string, ...string[]];
|
|
5
|
+
};
|
|
6
|
+
export declare const composeBinary: (compose: string[]) => string[];
|
|
7
|
+
/** Finds the first container tool on this machine that answers `<compose> version`. */
|
|
8
|
+
export declare const resolveComposeTool: (tools?: ComposeTool[]) => ComposeTool | undefined;
|
|
9
|
+
export declare const composeToolNames: (tools?: ComposeTool[]) => string[];
|
|
10
|
+
export declare const engineEnv: (engine: string) => {
|
|
11
|
+
CONTAINERS_REGISTRIES_CONF: string;
|
|
12
|
+
} | {
|
|
13
|
+
CONTAINERS_REGISTRIES_CONF?: undefined;
|
|
14
|
+
};
|
|
15
|
+
export declare const lanAddress: () => string | undefined;
|
|
16
|
+
/** Path of this machine's SSH key, for a compose file that mounts one into the API container. */
|
|
17
|
+
export declare const sshKeyPath: () => string | undefined;
|
|
18
|
+
export type ComposeCall = {
|
|
19
|
+
tool: ComposeTool;
|
|
20
|
+
/** Directory that holds the compose file. */
|
|
21
|
+
cwd: string;
|
|
22
|
+
env?: NodeJS.ProcessEnv;
|
|
23
|
+
};
|
|
24
|
+
/** Runs a compose command and captures its stdout. `undefined` when the tool itself failed. */
|
|
25
|
+
export declare const composeOutput: (options: ComposeCall & {
|
|
26
|
+
args: string[];
|
|
27
|
+
}) => string | undefined;
|
|
28
|
+
/** Container ids of a compose project, or `undefined` when the tool could not answer. */
|
|
29
|
+
export declare const composeContainerIds: (call: ComposeCall) => string[] | undefined;
|
|
30
|
+
export type PortMapping = {
|
|
31
|
+
host: number;
|
|
32
|
+
container: number;
|
|
33
|
+
};
|
|
34
|
+
export type ContainerState = {
|
|
35
|
+
id: string;
|
|
36
|
+
name: string;
|
|
37
|
+
/** Compose service, empty for a container compose did not start. */
|
|
38
|
+
service: string;
|
|
39
|
+
/** The engine's own words, for example `Up 42 minutes` or `Exited (1) 3 seconds ago`. */
|
|
40
|
+
status: string;
|
|
41
|
+
ports: PortMapping[];
|
|
42
|
+
};
|
|
43
|
+
/** True for a status the engine prints while the container runs. */
|
|
44
|
+
export declare const isRunningStatus: (status: string) => boolean;
|
|
45
|
+
/** Every container the engine knows, with its compose service and published ports. */
|
|
46
|
+
export declare const containerStates: (engine: string) => ContainerState[];
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.containerStates = exports.isRunningStatus = exports.composeContainerIds = exports.composeOutput = exports.sshKeyPath = exports.lanAddress = exports.engineEnv = exports.composeToolNames = exports.resolveComposeTool = exports.composeBinary = void 0;
|
|
4
|
+
const child_process_1 = require("child_process");
|
|
5
|
+
const fs_1 = require("fs");
|
|
6
|
+
const os_1 = require("os");
|
|
7
|
+
const path_1 = require("path");
|
|
8
|
+
/**
|
|
9
|
+
* SELinux denies a container read access to a bind mount that carries the host's own label, and API
|
|
10
|
+
* repos mount their checkout without the `:z` that would relabel it. Disabling the label from here
|
|
11
|
+
* keeps those checkouts untouched.
|
|
12
|
+
*/
|
|
13
|
+
const PODMAN_COMPOSE_ARGS = ['--podman-run-args=--security-opt label=disable'];
|
|
14
|
+
const COMPOSE_TOOLS = [
|
|
15
|
+
{ engine: 'docker', compose: ['docker', 'compose'] },
|
|
16
|
+
{ engine: 'container', compose: ['container', 'compose'] },
|
|
17
|
+
{ engine: 'podman', compose: ['podman-compose', ...PODMAN_COMPOSE_ARGS] },
|
|
18
|
+
{ engine: 'podman', compose: ['podman', 'compose', ...PODMAN_COMPOSE_ARGS] },
|
|
19
|
+
];
|
|
20
|
+
/**
|
|
21
|
+
* Podman refuses to resolve a short image name such as `mysql:8.0` without a TTY prompt when several
|
|
22
|
+
* unqualified search registries are configured. API compose files use short names, so point podman
|
|
23
|
+
* at one registry and turn the prompt off.
|
|
24
|
+
*/
|
|
25
|
+
const PODMAN_REGISTRIES_CONF = `unqualified-search-registries = ["docker.io"]\nshort-name-mode = "disabled"\n`;
|
|
26
|
+
let podmanRegistriesConfPath;
|
|
27
|
+
const writePodmanRegistriesConf = () => {
|
|
28
|
+
podmanRegistriesConfPath !== null && podmanRegistriesConfPath !== void 0 ? podmanRegistriesConfPath : (podmanRegistriesConfPath = (0, path_1.join)((0, fs_1.mkdtempSync)((0, path_1.join)((0, os_1.tmpdir)(), 'ethlete-api-')), 'registries.conf'));
|
|
29
|
+
(0, fs_1.writeFileSync)(podmanRegistriesConfPath, PODMAN_REGISTRIES_CONF, 'utf8');
|
|
30
|
+
return podmanRegistriesConfPath;
|
|
31
|
+
};
|
|
32
|
+
const composeBinary = (compose) => compose.filter((part) => !part.startsWith('--'));
|
|
33
|
+
exports.composeBinary = composeBinary;
|
|
34
|
+
const canRun = (command, args) => {
|
|
35
|
+
const result = (0, child_process_1.spawnSync)(command, args, { stdio: 'ignore' });
|
|
36
|
+
return result.error === undefined && result.status === 0;
|
|
37
|
+
};
|
|
38
|
+
/** Finds the first container tool on this machine that answers `<compose> version`. */
|
|
39
|
+
const resolveComposeTool = (tools = COMPOSE_TOOLS) => tools.find(({ compose }) => {
|
|
40
|
+
const [binary, ...rest] = (0, exports.composeBinary)(compose);
|
|
41
|
+
return binary !== undefined && canRun(binary, [...rest, 'version']);
|
|
42
|
+
});
|
|
43
|
+
exports.resolveComposeTool = resolveComposeTool;
|
|
44
|
+
const composeToolNames = (tools = COMPOSE_TOOLS) => tools.map(({ compose }) => (0, exports.composeBinary)(compose).join(' '));
|
|
45
|
+
exports.composeToolNames = composeToolNames;
|
|
46
|
+
const engineEnv = (engine) => engine === 'podman' ? { CONTAINERS_REGISTRIES_CONF: writePodmanRegistriesConf() } : {};
|
|
47
|
+
exports.engineEnv = engineEnv;
|
|
48
|
+
const lanAddress = () => {
|
|
49
|
+
var _a;
|
|
50
|
+
return (_a = Object.values((0, os_1.networkInterfaces)())
|
|
51
|
+
.flat()
|
|
52
|
+
.find((networkInterface) => (networkInterface === null || networkInterface === void 0 ? void 0 : networkInterface.family) === 'IPv4' && !networkInterface.internal)) === null || _a === void 0 ? void 0 : _a.address;
|
|
53
|
+
};
|
|
54
|
+
exports.lanAddress = lanAddress;
|
|
55
|
+
/** Path of this machine's SSH key, for a compose file that mounts one into the API container. */
|
|
56
|
+
const sshKeyPath = () => [(0, path_1.join)((0, os_1.homedir)(), '.ssh/id_ed25519'), (0, path_1.join)((0, os_1.homedir)(), '.ssh/id_rsa')].find((path) => (0, fs_1.existsSync)(path));
|
|
57
|
+
exports.sshKeyPath = sshKeyPath;
|
|
58
|
+
/** Runs a compose command and captures its stdout. `undefined` when the tool itself failed. */
|
|
59
|
+
const composeOutput = (options) => {
|
|
60
|
+
var _a;
|
|
61
|
+
const { tool, cwd, env, args } = options;
|
|
62
|
+
const [binary, ...prefix] = tool.compose;
|
|
63
|
+
const result = (0, child_process_1.spawnSync)(binary, [...prefix, ...args], { cwd, env, encoding: 'utf8' });
|
|
64
|
+
return result.error || result.status !== 0 ? undefined : ((_a = result.stdout) !== null && _a !== void 0 ? _a : '');
|
|
65
|
+
};
|
|
66
|
+
exports.composeOutput = composeOutput;
|
|
67
|
+
/** Container ids of a compose project, or `undefined` when the tool could not answer. */
|
|
68
|
+
const composeContainerIds = (call) => {
|
|
69
|
+
const stdout = (0, exports.composeOutput)(Object.assign(Object.assign({}, call), { args: ['ps', '-q'] }));
|
|
70
|
+
return stdout === undefined ? undefined : stdout.split('\n').filter((id) => id.trim() !== '');
|
|
71
|
+
};
|
|
72
|
+
exports.composeContainerIds = composeContainerIds;
|
|
73
|
+
const PUBLISHED_MAPPING = /(\d+)->(\d+)/g;
|
|
74
|
+
const parsePortMappings = (ports) => [...ports.matchAll(PUBLISHED_MAPPING)].map(([, host, container]) => ({
|
|
75
|
+
host: Number(host),
|
|
76
|
+
container: Number(container),
|
|
77
|
+
}));
|
|
78
|
+
const PS_FORMAT = '{{.ID}}\t{{.Names}}\t{{.Label "com.docker.compose.service"}}\t{{.Status}}\t{{.Ports}}';
|
|
79
|
+
/** True for a status the engine prints while the container runs. */
|
|
80
|
+
const isRunningStatus = (status) => /^up\b/i.test(status);
|
|
81
|
+
exports.isRunningStatus = isRunningStatus;
|
|
82
|
+
/** Every container the engine knows, with its compose service and published ports. */
|
|
83
|
+
const containerStates = (engine) => {
|
|
84
|
+
var _a;
|
|
85
|
+
const result = (0, child_process_1.spawnSync)(engine, ['ps', '-a', '--format', PS_FORMAT], { encoding: 'utf8' });
|
|
86
|
+
if (result.error || result.status !== 0)
|
|
87
|
+
return [];
|
|
88
|
+
return ((_a = result.stdout) !== null && _a !== void 0 ? _a : '')
|
|
89
|
+
.split('\n')
|
|
90
|
+
.map((line) => line.split('\t'))
|
|
91
|
+
.filter((columns) => columns.length >= 5 && columns[0])
|
|
92
|
+
.map(([id, name, service, status, ports]) => ({
|
|
93
|
+
id: id !== null && id !== void 0 ? id : '',
|
|
94
|
+
name: name !== null && name !== void 0 ? name : '',
|
|
95
|
+
service: service !== null && service !== void 0 ? service : '',
|
|
96
|
+
status: status !== null && status !== void 0 ? status : '',
|
|
97
|
+
ports: parsePortMappings(ports !== null && ports !== void 0 ? ports : ''),
|
|
98
|
+
}));
|
|
99
|
+
};
|
|
100
|
+
exports.containerStates = containerStates;
|
|
101
|
+
//# sourceMappingURL=compose.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compose.js","sourceRoot":"","sources":["../../../../../../libs/cli/src/lib/api/compose.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/** One API this repo can run locally. Everything here describes the API's own compose setup. */
|
|
2
|
+
export type ApiDefinition = {
|
|
3
|
+
/** Directory inside the API checkout that holds the compose file, for example `development`. */
|
|
4
|
+
composeDir: string;
|
|
5
|
+
/** Compose services to start. Leave out a service the app does not need, such as a bundled frontend. */
|
|
6
|
+
services: string[];
|
|
7
|
+
/** Service that `shell`, `logs` and every `exec` entry run in. */
|
|
8
|
+
execService: string;
|
|
9
|
+
/** Published host port, not the port inside the container. Used for the printed url. */
|
|
10
|
+
port: number;
|
|
11
|
+
/** File that must exist in `composeDir` before the API can start, for example `.env`. */
|
|
12
|
+
envFile?: string;
|
|
13
|
+
/** Command that creates `envFile`, run by `setup` in `composeDir`. */
|
|
14
|
+
setupCommand?: string;
|
|
15
|
+
/** External container network to create before the first `up`. */
|
|
16
|
+
network?: string;
|
|
17
|
+
/** Example path shown in the error that asks the developer to configure this API's checkout. */
|
|
18
|
+
examplePath?: string;
|
|
19
|
+
/** Where to clone this API from when the developer has no checkout of their own. */
|
|
20
|
+
repoUrl?: string;
|
|
21
|
+
/** localStorage key the app reads to pick its API. Printed by `--host`. */
|
|
22
|
+
envKey?: string;
|
|
23
|
+
/** Extra environment for every compose call. An undefined value is dropped rather than passed as "undefined". */
|
|
24
|
+
env?: () => Record<string, string | undefined>;
|
|
25
|
+
/** Named commands run in `execService`, for example `{ install: ['composer', 'install'] }`. */
|
|
26
|
+
exec?: Record<string, string[]>;
|
|
27
|
+
};
|
|
28
|
+
export type ApiDefinitions = Record<string, ApiDefinition>;
|
|
29
|
+
export declare const BUILT_IN_API_COMMANDS: readonly ["up", "down", "logs", "shell", "clone", "clear", "checkout", "pull", "setup"];
|
|
30
|
+
/** These act on the checkout itself, so they run before `setupCommand` and need no container engine. */
|
|
31
|
+
export declare const GIT_API_COMMANDS: string[];
|
|
32
|
+
/** Whether an exec entry downloads dependencies, which is the only failure the private-dependency hint explains. */
|
|
33
|
+
export declare const installsDependencies: (execCommand: readonly string[]) => boolean;
|
|
34
|
+
/** The exec entry that installs dependencies, so a failure in another entry can point at it. */
|
|
35
|
+
export declare const dependencyInstallCommandName: (api: ApiDefinition) => string | undefined;
|
|
36
|
+
/** `setup` is dropped for an API that declares no `setupCommand`, so nothing lists a command it cannot run. */
|
|
37
|
+
export declare const apiCommandNames: (api: ApiDefinition) => string[];
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.apiCommandNames = exports.dependencyInstallCommandName = exports.installsDependencies = exports.GIT_API_COMMANDS = exports.BUILT_IN_API_COMMANDS = void 0;
|
|
4
|
+
exports.BUILT_IN_API_COMMANDS = [
|
|
5
|
+
'up',
|
|
6
|
+
'down',
|
|
7
|
+
'logs',
|
|
8
|
+
'shell',
|
|
9
|
+
'clone',
|
|
10
|
+
'clear',
|
|
11
|
+
'checkout',
|
|
12
|
+
'pull',
|
|
13
|
+
'setup',
|
|
14
|
+
];
|
|
15
|
+
/** These act on the checkout itself, so they run before `setupCommand` and need no container engine. */
|
|
16
|
+
exports.GIT_API_COMMANDS = ['clone', 'checkout', 'pull'];
|
|
17
|
+
const DEPENDENCY_INSTALLERS = ['composer', 'npm', 'yarn', 'pnpm', 'bun', 'bundle', 'pip', 'pip3'];
|
|
18
|
+
/** Whether an exec entry downloads dependencies, which is the only failure the private-dependency hint explains. */
|
|
19
|
+
const installsDependencies = (execCommand) => { var _a; return DEPENDENCY_INSTALLERS.includes((_a = execCommand[0]) !== null && _a !== void 0 ? _a : ''); };
|
|
20
|
+
exports.installsDependencies = installsDependencies;
|
|
21
|
+
/** The exec entry that installs dependencies, so a failure in another entry can point at it. */
|
|
22
|
+
const dependencyInstallCommandName = (api) => { var _a; return Object.keys((_a = api.exec) !== null && _a !== void 0 ? _a : {}).find((name) => { var _a, _b; return (0, exports.installsDependencies)((_b = (_a = api.exec) === null || _a === void 0 ? void 0 : _a[name]) !== null && _b !== void 0 ? _b : []); }); };
|
|
23
|
+
exports.dependencyInstallCommandName = dependencyInstallCommandName;
|
|
24
|
+
/** `setup` is dropped for an API that declares no `setupCommand`, so nothing lists a command it cannot run. */
|
|
25
|
+
const apiCommandNames = (api) => {
|
|
26
|
+
var _a;
|
|
27
|
+
return [
|
|
28
|
+
...exports.BUILT_IN_API_COMMANDS.filter((command) => command !== 'setup' || api.setupCommand),
|
|
29
|
+
...Object.keys((_a = api.exec) !== null && _a !== void 0 ? _a : {}),
|
|
30
|
+
];
|
|
31
|
+
};
|
|
32
|
+
exports.apiCommandNames = apiCommandNames;
|
|
33
|
+
//# sourceMappingURL=definition.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"definition.js","sourceRoot":"","sources":["../../../../../../libs/cli/src/lib/api/definition.ts"],"names":[],"mappings":";;;AA8Ba,QAAA,qBAAqB,GAAG;IACnC,IAAI;IACJ,MAAM;IACN,MAAM;IACN,OAAO;IACP,OAAO;IACP,OAAO;IACP,UAAU;IACV,MAAM;IACN,OAAO;CACC,CAAC;AAEX,wGAAwG;AAC3F,QAAA,gBAAgB,GAAa,CAAC,OAAO,EAAE,UAAU,EAAE,MAAM,CAAC,CAAC;AAExE,MAAM,qBAAqB,GAAG,CAAC,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;AAElG,oHAAoH;AAC7G,MAAM,oBAAoB,GAAG,CAAC,WAA8B,EAAE,EAAE,WACrE,OAAA,qBAAqB,CAAC,QAAQ,CAAC,MAAA,WAAW,CAAC,CAAC,CAAC,mCAAI,EAAE,CAAC,CAAA,EAAA,CAAC;AAD1C,QAAA,oBAAoB,wBACsB;AAEvD,gGAAgG;AACzF,MAAM,4BAA4B,GAAG,CAAC,GAAkB,EAAE,EAAE,WACjE,OAAA,MAAM,CAAC,IAAI,CAAC,MAAA,GAAG,CAAC,IAAI,mCAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,eAAC,OAAA,IAAA,4BAAoB,EAAC,MAAA,MAAA,GAAG,CAAC,IAAI,0CAAG,IAAI,CAAC,mCAAI,EAAE,CAAC,CAAA,EAAA,CAAC,CAAA,EAAA,CAAC;AAD9E,QAAA,4BAA4B,gCACkD;AAE3F,+GAA+G;AACxG,MAAM,eAAe,GAAG,CAAC,GAAkB,EAAE,EAAE;;IAAC,OAAA;QACrD,GAAG,6BAAqB,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,KAAK,OAAO,IAAI,GAAG,CAAC,YAAY,CAAC;QACrF,GAAG,MAAM,CAAC,IAAI,CAAC,MAAA,GAAG,CAAC,IAAI,mCAAI,EAAE,CAAC;KAC/B,CAAA;CAAA,CAAC;AAHW,QAAA,eAAe,mBAG1B"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export type GitResult = {
|
|
2
|
+
status: number;
|
|
3
|
+
stdout: string;
|
|
4
|
+
stderr: string;
|
|
5
|
+
};
|
|
6
|
+
export declare const currentBranch: (cwd: string) => string | undefined;
|
|
7
|
+
/** Modified tracked files and untracked files, as git's own porcelain lines. */
|
|
8
|
+
export declare const uncommittedChanges: (cwd: string) => string[];
|
|
9
|
+
export declare const hasUncommittedChanges: (cwd: string) => boolean;
|
|
10
|
+
/** Commits on any local branch that no remote holds, so work is never removed with a checkout. */
|
|
11
|
+
export declare const unpushedCommits: (cwd: string) => string[];
|
|
12
|
+
/** Switches the API checkout to the branch configured for it. Git's own refusal is passed through. */
|
|
13
|
+
export declare const checkoutApiBranch: (options: {
|
|
14
|
+
repoPath: string;
|
|
15
|
+
branch: string;
|
|
16
|
+
}) => number;
|
|
17
|
+
/**
|
|
18
|
+
* Fast-forwards the checked-out branch. `force` throws away local commits and uncommitted tracked
|
|
19
|
+
* changes on it; untracked files such as `vendor/` and `.env` are never touched.
|
|
20
|
+
*/
|
|
21
|
+
export declare const pullApiBranch: (options: {
|
|
22
|
+
repoPath: string;
|
|
23
|
+
expectedBranch?: string;
|
|
24
|
+
force: boolean;
|
|
25
|
+
}) => number;
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.pullApiBranch = exports.checkoutApiBranch = exports.unpushedCommits = exports.hasUncommittedChanges = exports.uncommittedChanges = exports.currentBranch = void 0;
|
|
4
|
+
const child_process_1 = require("child_process");
|
|
5
|
+
const git = (cwd, args) => {
|
|
6
|
+
var _a, _b, _c;
|
|
7
|
+
const result = (0, child_process_1.spawnSync)('git', args, { cwd, encoding: 'utf8' });
|
|
8
|
+
return {
|
|
9
|
+
status: (_a = result.status) !== null && _a !== void 0 ? _a : 1,
|
|
10
|
+
stdout: ((_b = result.stdout) !== null && _b !== void 0 ? _b : '').trim(),
|
|
11
|
+
stderr: ((_c = result.stderr) !== null && _c !== void 0 ? _c : '').trim(),
|
|
12
|
+
};
|
|
13
|
+
};
|
|
14
|
+
const gitInherit = (cwd, args) => { var _a; return (_a = (0, child_process_1.spawnSync)('git', args, { cwd, stdio: 'inherit' }).status) !== null && _a !== void 0 ? _a : 1; };
|
|
15
|
+
const currentBranch = (cwd) => {
|
|
16
|
+
const result = git(cwd, ['rev-parse', '--abbrev-ref', 'HEAD']);
|
|
17
|
+
return result.status === 0 ? result.stdout : undefined;
|
|
18
|
+
};
|
|
19
|
+
exports.currentBranch = currentBranch;
|
|
20
|
+
/** Modified tracked files and untracked files, as git's own porcelain lines. */
|
|
21
|
+
const uncommittedChanges = (cwd) => {
|
|
22
|
+
const { stdout } = git(cwd, ['status', '--porcelain']);
|
|
23
|
+
return stdout.length > 0 ? stdout.split('\n') : [];
|
|
24
|
+
};
|
|
25
|
+
exports.uncommittedChanges = uncommittedChanges;
|
|
26
|
+
const hasUncommittedChanges = (cwd) => (0, exports.uncommittedChanges)(cwd).length > 0;
|
|
27
|
+
exports.hasUncommittedChanges = hasUncommittedChanges;
|
|
28
|
+
/** Commits on any local branch that no remote holds, so work is never removed with a checkout. */
|
|
29
|
+
const unpushedCommits = (cwd) => {
|
|
30
|
+
const { status, stdout } = git(cwd, ['log', '--branches', '--not', '--remotes', '--oneline']);
|
|
31
|
+
return status === 0 && stdout.length > 0 ? stdout.split('\n') : [];
|
|
32
|
+
};
|
|
33
|
+
exports.unpushedCommits = unpushedCommits;
|
|
34
|
+
/** Switches the API checkout to the branch configured for it. Git's own refusal is passed through. */
|
|
35
|
+
const checkoutApiBranch = (options) => {
|
|
36
|
+
const { repoPath, branch } = options;
|
|
37
|
+
if ((0, exports.currentBranch)(repoPath) === branch) {
|
|
38
|
+
console.log(`Already on ${branch}.`);
|
|
39
|
+
return 0;
|
|
40
|
+
}
|
|
41
|
+
return gitInherit(repoPath, ['checkout', branch]);
|
|
42
|
+
};
|
|
43
|
+
exports.checkoutApiBranch = checkoutApiBranch;
|
|
44
|
+
/**
|
|
45
|
+
* Fast-forwards the checked-out branch. `force` throws away local commits and uncommitted tracked
|
|
46
|
+
* changes on it; untracked files such as `vendor/` and `.env` are never touched.
|
|
47
|
+
*/
|
|
48
|
+
const pullApiBranch = (options) => {
|
|
49
|
+
const { repoPath, expectedBranch, force } = options;
|
|
50
|
+
const branch = (0, exports.currentBranch)(repoPath);
|
|
51
|
+
if (!branch) {
|
|
52
|
+
console.error(`${repoPath} is not a git checkout.`);
|
|
53
|
+
return 1;
|
|
54
|
+
}
|
|
55
|
+
if (expectedBranch && branch !== expectedBranch) {
|
|
56
|
+
console.warn(`On ${branch}, but apiRepoBranches expects ${expectedBranch}. Pulling ${branch}.\n`);
|
|
57
|
+
}
|
|
58
|
+
if (!force && (0, exports.hasUncommittedChanges)(repoPath)) {
|
|
59
|
+
console.error(`${repoPath} has uncommitted changes. Commit or stash them, or pass --force to discard them.`);
|
|
60
|
+
return 1;
|
|
61
|
+
}
|
|
62
|
+
const fetched = gitInherit(repoPath, ['fetch', 'origin', branch]);
|
|
63
|
+
if (fetched !== 0)
|
|
64
|
+
return fetched;
|
|
65
|
+
if (!force)
|
|
66
|
+
return gitInherit(repoPath, ['merge', '--ff-only', `origin/${branch}`]);
|
|
67
|
+
console.log(`Discarding local commits and tracked changes on ${branch}.`);
|
|
68
|
+
return gitInherit(repoPath, ['reset', '--hard', `origin/${branch}`]);
|
|
69
|
+
};
|
|
70
|
+
exports.pullApiBranch = pullApiBranch;
|
|
71
|
+
//# sourceMappingURL=git.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git.js","sourceRoot":"","sources":["../../../../../../libs/cli/src/lib/api/git.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { ApiDefinition, ApiDefinitions } from './definition';
|
|
2
|
+
/** The help text for `et api`, listing the built-in commands and what each API adds to them. */
|
|
3
|
+
export declare const apiHelp: (apis: ApiDefinitions, invocation: string) => string;
|
|
4
|
+
/** The help text for one API: every command it accepts, what each one runs, and where its files are. */
|
|
5
|
+
export declare const singleApiHelp: (options: {
|
|
6
|
+
name: string;
|
|
7
|
+
api: ApiDefinition;
|
|
8
|
+
invocation: string;
|
|
9
|
+
/** Where the checkout is, or what is wrong with it. */
|
|
10
|
+
checkout?: string;
|
|
11
|
+
}) => string;
|