@decohere/core 0.0.1-dev.116
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/commonjs/src/caching/cache-manager.js +98 -0
- package/commonjs/src/caching/cache.decorator.js +69 -0
- package/commonjs/src/caching/cache.js +6 -0
- package/commonjs/src/caching/index.js +23 -0
- package/commonjs/src/caching/invalidate-cache.decorator.js +92 -0
- package/commonjs/src/caching/memoize.decorator.js +36 -0
- package/commonjs/src/caching/node-cache-memoize.adapter.js +49 -0
- package/commonjs/src/cli/action.js +65 -0
- package/commonjs/src/cli/command.js +127 -0
- package/commonjs/src/cli/index.js +61 -0
- package/commonjs/src/cli/module.type.js +18 -0
- package/commonjs/src/cli/options.js +115 -0
- package/commonjs/src/collections/collections.js +21 -0
- package/commonjs/src/collections/find-duplicates.js +35 -0
- package/commonjs/src/collections/index.js +52 -0
- package/commonjs/src/collections/merge-arrays.js +34 -0
- package/commonjs/src/collections/sum.js +63 -0
- package/commonjs/src/collections/unique-objects.js +39 -0
- package/commonjs/src/composition/index.js +4 -0
- package/commonjs/src/configuration/configuration.types.js +11 -0
- package/commonjs/src/configuration/index.js +18 -0
- package/commonjs/src/diagnostics/index.js +22 -0
- package/commonjs/src/diagnostics/trace.js +86 -0
- package/commonjs/src/extensibility/decorator-factory-base.js +22 -0
- package/commonjs/src/extensibility/decorator-factory.js +31 -0
- package/commonjs/src/extensibility/extension.js +37 -0
- package/commonjs/src/extensibility/index.js +23 -0
- package/commonjs/src/extensibility/mixwith.js +36 -0
- package/commonjs/src/extensibility/pipeline.js +56 -0
- package/commonjs/src/extensibility/step.js +18 -0
- package/commonjs/src/interop/docker/docker.js +54 -0
- package/commonjs/src/interop/errors/interop.error.js +12 -0
- package/commonjs/src/interop/git/git.js +134 -0
- package/commonjs/src/interop/git/git.types.js +4 -0
- package/commonjs/src/interop/index.js +97 -0
- package/commonjs/src/interop/node/index.js +18 -0
- package/commonjs/src/interop/node/node.js +45 -0
- package/commonjs/src/interop/npm/npm.js +231 -0
- package/commonjs/src/interop/npm/npm.types.js +16 -0
- package/commonjs/src/interop/pnpm/pnpm.js +34 -0
- package/commonjs/src/interop/pnpm/pnpm.types.js +4 -0
- package/commonjs/src/interop/shell/shell.argv.js +45 -0
- package/commonjs/src/interop/shell/shell.js +105 -0
- package/commonjs/src/interop/shell/shell.types.js +4 -0
- package/commonjs/src/interop/types/detect-package-manager.js +71 -0
- package/commonjs/src/interop/types/package-manager.js +4 -0
- package/commonjs/src/interop/yarn/yarn.js +34 -0
- package/commonjs/src/interop/yarn/yarn.types.js +4 -0
- package/commonjs/src/io/copy-file.js +25 -0
- package/commonjs/src/io/delete-file.js +21 -0
- package/commonjs/src/io/directory-exists.js +24 -0
- package/commonjs/src/io/file-exists.js +19 -0
- package/commonjs/src/io/find-directories.js +21 -0
- package/commonjs/src/io/find-file.js +45 -0
- package/commonjs/src/io/index.js +66 -0
- package/commonjs/src/io/io.js +28 -0
- package/commonjs/src/io/read-file.js +39 -0
- package/commonjs/src/io/remove-dir.js +22 -0
- package/commonjs/src/io/types/directory.type.js +4 -0
- package/commonjs/src/io/types/file.js +28 -0
- package/commonjs/src/io/types/index.js +19 -0
- package/commonjs/src/io/url-to-path.js +33 -0
- package/commonjs/src/io/watch.js +261 -0
- package/commonjs/src/io/write-file.js +30 -0
- package/commonjs/src/objects/deep-merge.js +67 -0
- package/commonjs/src/objects/index.js +11 -0
- package/commonjs/src/reflection/index.js +20 -0
- package/commonjs/src/reflection/types/index.js +18 -0
- package/commonjs/src/reflection/types/reflection.types.js +26 -0
- package/commonjs/src/reflection/utilities.js +118 -0
- package/commonjs/src/semver/index.js +18 -0
- package/commonjs/src/semver/semver.js +92 -0
- package/commonjs/src/system/camel-case.js +13 -0
- package/commonjs/src/system/debounce.js +19 -0
- package/commonjs/src/system/decorator.js +46 -0
- package/commonjs/src/system/environment.js +23 -0
- package/commonjs/src/system/function.types.js +18 -0
- package/commonjs/src/system/index.js +24 -0
- package/commonjs/src/system/retry.decorator.js +40 -0
- package/commonjs/src/system/sleep.js +13 -0
- package/commonjs/src/system/type.utils.js +4 -0
- package/commonjs/src/testing/flush-promises.js +16 -0
- package/commonjs/src/testing/glob-with-memfs.js +22 -0
- package/commonjs/src/testing/index.js +22 -0
- package/commonjs/src/testing/memfs.js +52 -0
- package/commonjs/src/testing/mock-logger.js +36 -0
- package/commonjs/src/testing/spy-on-constructor.js +27 -0
- package/es6/src/caching/cache-manager.js +82 -0
- package/es6/src/caching/cache.decorator.js +51 -0
- package/es6/src/caching/cache.js +3 -0
- package/es6/src/caching/index.js +6 -0
- package/es6/src/caching/invalidate-cache.decorator.js +71 -0
- package/es6/src/caching/memoize.decorator.js +27 -0
- package/es6/src/caching/node-cache-memoize.adapter.js +37 -0
- package/es6/src/cli/action.js +47 -0
- package/es6/src/cli/command.js +106 -0
- package/es6/src/cli/index.js +4 -0
- package/es6/src/cli/module.type.js +11 -0
- package/es6/src/cli/options.js +76 -0
- package/es6/src/collections/collections.js +4 -0
- package/es6/src/collections/find-duplicates.js +17 -0
- package/es6/src/collections/index.js +1 -0
- package/es6/src/collections/merge-arrays.js +16 -0
- package/es6/src/collections/sum.js +45 -0
- package/es6/src/collections/unique-objects.js +21 -0
- package/es6/src/composition/index.js +1 -0
- package/es6/src/configuration/configuration.types.js +1 -0
- package/es6/src/configuration/index.js +1 -0
- package/es6/src/diagnostics/index.js +1 -0
- package/es6/src/diagnostics/trace.js +68 -0
- package/es6/src/extensibility/decorator-factory-base.js +39 -0
- package/es6/src/extensibility/decorator-factory.js +21 -0
- package/es6/src/extensibility/extension.js +27 -0
- package/es6/src/extensibility/index.js +6 -0
- package/es6/src/extensibility/mixwith.js +26 -0
- package/es6/src/extensibility/pipeline.js +46 -0
- package/es6/src/extensibility/step.js +16 -0
- package/es6/src/interop/docker/docker.js +44 -0
- package/es6/src/interop/errors/interop.error.js +2 -0
- package/es6/src/interop/git/git.js +124 -0
- package/es6/src/interop/git/git.types.js +1 -0
- package/es6/src/interop/index.js +21 -0
- package/es6/src/interop/node/index.js +1 -0
- package/es6/src/interop/node/node.js +35 -0
- package/es6/src/interop/npm/npm.js +180 -0
- package/es6/src/interop/npm/npm.types.js +6 -0
- package/es6/src/interop/pnpm/pnpm.js +24 -0
- package/es6/src/interop/pnpm/pnpm.types.js +1 -0
- package/es6/src/interop/shell/shell.argv.js +35 -0
- package/es6/src/interop/shell/shell.js +95 -0
- package/es6/src/interop/shell/shell.types.js +1 -0
- package/es6/src/interop/types/detect-package-manager.js +50 -0
- package/es6/src/interop/types/package-manager.js +1 -0
- package/es6/src/interop/yarn/yarn.js +24 -0
- package/es6/src/interop/yarn/yarn.types.js +1 -0
- package/es6/src/io/copy-file.js +10 -0
- package/es6/src/io/delete-file.js +6 -0
- package/es6/src/io/directory-exists.js +9 -0
- package/es6/src/io/file-exists.js +9 -0
- package/es6/src/io/find-directories.js +11 -0
- package/es6/src/io/find-file.js +27 -0
- package/es6/src/io/index.js +2 -0
- package/es6/src/io/io.js +11 -0
- package/es6/src/io/read-file.js +13 -0
- package/es6/src/io/remove-dir.js +7 -0
- package/es6/src/io/types/directory.type.js +1 -0
- package/es6/src/io/types/file.js +18 -0
- package/es6/src/io/types/index.js +2 -0
- package/es6/src/io/url-to-path.js +15 -0
- package/es6/src/io/watch.js +238 -0
- package/es6/src/io/write-file.js +15 -0
- package/es6/src/objects/deep-merge.js +57 -0
- package/es6/src/objects/index.js +1 -0
- package/es6/src/reflection/index.js +3 -0
- package/es6/src/reflection/types/index.js +1 -0
- package/es6/src/reflection/types/reflection.types.js +8 -0
- package/es6/src/reflection/utilities.js +74 -0
- package/es6/src/semver/index.js +1 -0
- package/es6/src/semver/semver.js +71 -0
- package/es6/src/system/camel-case.js +3 -0
- package/es6/src/system/debounce.js +9 -0
- package/es6/src/system/decorator.js +30 -0
- package/es6/src/system/environment.js +5 -0
- package/es6/src/system/function.types.js +26 -0
- package/es6/src/system/index.js +7 -0
- package/es6/src/system/retry.decorator.js +30 -0
- package/es6/src/system/sleep.js +3 -0
- package/es6/src/system/type.utils.js +1 -0
- package/es6/src/testing/flush-promises.js +6 -0
- package/es6/src/testing/glob-with-memfs.js +20 -0
- package/es6/src/testing/index.js +5 -0
- package/es6/src/testing/memfs.js +25 -0
- package/es6/src/testing/mock-logger.js +26 -0
- package/es6/src/testing/spy-on-constructor.js +31 -0
- package/package.json +106 -0
- package/types/src/caching/cache-manager.d.ts +59 -0
- package/types/src/caching/cache.d.ts +11 -0
- package/types/src/caching/cache.decorator.d.ts +18 -0
- package/types/src/caching/index.d.ts +6 -0
- package/types/src/caching/invalidate-cache.decorator.d.ts +17 -0
- package/types/src/caching/memoize.decorator.d.ts +16 -0
- package/types/src/caching/node-cache-memoize.adapter.d.ts +22 -0
- package/types/src/cli/action.d.ts +36 -0
- package/types/src/cli/command.d.ts +34 -0
- package/types/src/cli/index.d.ts +7 -0
- package/types/src/cli/module.type.d.ts +36 -0
- package/types/src/cli/options.d.ts +28 -0
- package/types/src/collections/collections.d.ts +4 -0
- package/types/src/collections/find-duplicates.d.ts +2 -0
- package/types/src/collections/index.d.ts +1 -0
- package/types/src/collections/merge-arrays.d.ts +2 -0
- package/types/src/collections/sum.d.ts +4 -0
- package/types/src/collections/unique-objects.d.ts +2 -0
- package/types/src/composition/index.d.ts +37 -0
- package/types/src/configuration/configuration.types.d.ts +10 -0
- package/types/src/configuration/index.d.ts +1 -0
- package/types/src/diagnostics/index.d.ts +1 -0
- package/types/src/diagnostics/trace.d.ts +10 -0
- package/types/src/extensibility/decorator-factory-base.d.ts +39 -0
- package/types/src/extensibility/decorator-factory.d.ts +19 -0
- package/types/src/extensibility/extension.d.ts +9 -0
- package/types/src/extensibility/index.d.ts +6 -0
- package/types/src/extensibility/mixwith.d.ts +6 -0
- package/types/src/extensibility/pipeline.d.ts +12 -0
- package/types/src/extensibility/step.d.ts +16 -0
- package/types/src/interop/docker/docker.d.ts +19 -0
- package/types/src/interop/errors/interop.error.d.ts +2 -0
- package/types/src/interop/git/git.d.ts +16 -0
- package/types/src/interop/git/git.types.d.ts +14 -0
- package/types/src/interop/index.d.ts +14 -0
- package/types/src/interop/node/index.d.ts +1 -0
- package/types/src/interop/node/node.d.ts +5 -0
- package/types/src/interop/npm/npm.d.ts +29 -0
- package/types/src/interop/npm/npm.types.d.ts +24 -0
- package/types/src/interop/pnpm/pnpm.d.ts +9 -0
- package/types/src/interop/pnpm/pnpm.types.d.ts +3 -0
- package/types/src/interop/shell/shell.argv.d.ts +5 -0
- package/types/src/interop/shell/shell.d.ts +6 -0
- package/types/src/interop/shell/shell.types.d.ts +9 -0
- package/types/src/interop/types/detect-package-manager.d.ts +4 -0
- package/types/src/interop/types/package-manager.d.ts +10 -0
- package/types/src/interop/yarn/yarn.d.ts +9 -0
- package/types/src/interop/yarn/yarn.types.d.ts +3 -0
- package/types/src/io/copy-file.d.ts +4 -0
- package/types/src/io/delete-file.d.ts +1 -0
- package/types/src/io/directory-exists.d.ts +1 -0
- package/types/src/io/file-exists.d.ts +1 -0
- package/types/src/io/find-directories.d.ts +2 -0
- package/types/src/io/find-file.d.ts +9 -0
- package/types/src/io/index.d.ts +2 -0
- package/types/src/io/io.d.ts +11 -0
- package/types/src/io/read-file.d.ts +4 -0
- package/types/src/io/remove-dir.d.ts +5 -0
- package/types/src/io/types/directory.type.d.ts +4 -0
- package/types/src/io/types/file.d.ts +20 -0
- package/types/src/io/types/index.d.ts +2 -0
- package/types/src/io/url-to-path.d.ts +2 -0
- package/types/src/io/watch.d.ts +16 -0
- package/types/src/io/write-file.d.ts +5 -0
- package/types/src/objects/deep-merge.d.ts +41 -0
- package/types/src/objects/index.d.ts +1 -0
- package/types/src/reflection/index.d.ts +3 -0
- package/types/src/reflection/types/index.d.ts +1 -0
- package/types/src/reflection/types/reflection.types.d.ts +21 -0
- package/types/src/reflection/utilities.d.ts +27 -0
- package/types/src/semver/index.d.ts +1 -0
- package/types/src/semver/semver.d.ts +18 -0
- package/types/src/system/camel-case.d.ts +1 -0
- package/types/src/system/debounce.d.ts +1 -0
- package/types/src/system/decorator.d.ts +15 -0
- package/types/src/system/environment.d.ts +6 -0
- package/types/src/system/function.types.d.ts +55 -0
- package/types/src/system/index.d.ts +7 -0
- package/types/src/system/retry.decorator.d.ts +6 -0
- package/types/src/system/sleep.d.ts +1 -0
- package/types/src/system/type.utils.d.ts +1 -0
- package/types/src/testing/flush-promises.d.ts +1 -0
- package/types/src/testing/glob-with-memfs.d.ts +3 -0
- package/types/src/testing/index.d.ts +5 -0
- package/types/src/testing/memfs.d.ts +5 -0
- package/types/src/testing/mock-logger.d.ts +13 -0
- package/types/src/testing/spy-on-constructor.d.ts +21 -0
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
const BLOCKED_PROTOTYPE_KEYS = new Set([
|
|
2
|
+
"constructor",
|
|
3
|
+
"prototype",
|
|
4
|
+
"name",
|
|
5
|
+
"length"
|
|
6
|
+
]);
|
|
7
|
+
function copyPrototypeProperties(target, source) {
|
|
8
|
+
for (const key of Reflect.ownKeys(source)){
|
|
9
|
+
if (typeof key === "string" && BLOCKED_PROTOTYPE_KEYS.has(key)) {
|
|
10
|
+
continue;
|
|
11
|
+
}
|
|
12
|
+
const descriptor = Object.getOwnPropertyDescriptor(source, key);
|
|
13
|
+
if (descriptor == null) {
|
|
14
|
+
continue;
|
|
15
|
+
}
|
|
16
|
+
Object.defineProperty(target, key, descriptor);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
export function mixwith(...mixins) {
|
|
20
|
+
class Mixed {
|
|
21
|
+
}
|
|
22
|
+
for (const mixin of mixins){
|
|
23
|
+
copyPrototypeProperties(Mixed.prototype, mixin.prototype);
|
|
24
|
+
}
|
|
25
|
+
return Mixed;
|
|
26
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { scribe } from "@decohere/scribe";
|
|
2
|
+
export class Pipeline {
|
|
3
|
+
stack;
|
|
4
|
+
logger = scribe.logger(Pipeline.name);
|
|
5
|
+
currentStep;
|
|
6
|
+
constructor(...steps){
|
|
7
|
+
this.stack = steps;
|
|
8
|
+
}
|
|
9
|
+
[Symbol.dispose]() {
|
|
10
|
+
for (const [, step] of this.stack){
|
|
11
|
+
if (Symbol.dispose in step) {
|
|
12
|
+
step[Symbol.dispose]();
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
async start(context) {
|
|
17
|
+
const runStep = async (index)=>{
|
|
18
|
+
const [key, middleware, when] = this.stack[index] ?? [];
|
|
19
|
+
if (middleware == null) {
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
if (when != null && !when(context)) {
|
|
23
|
+
this.logger.info(`Skipping step ${key}`);
|
|
24
|
+
return await runStep(index + 1);
|
|
25
|
+
}
|
|
26
|
+
this.currentStep = key;
|
|
27
|
+
this.logger.info(`Running step ${key}`);
|
|
28
|
+
await middleware.run(context, async ()=>{
|
|
29
|
+
await runStep(index + 1);
|
|
30
|
+
});
|
|
31
|
+
};
|
|
32
|
+
try {
|
|
33
|
+
await runStep(0);
|
|
34
|
+
} catch (error) {
|
|
35
|
+
const step = this.currentStep ?? "unknown";
|
|
36
|
+
if (error instanceof Error) {
|
|
37
|
+
throw new Error(`Pipeline step '${step}' failed: ${error.message}`, {
|
|
38
|
+
cause: error
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
throw new Error(`Pipeline step '${step}' failed with non-Error value`, {
|
|
42
|
+
cause: error
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Wraps a pipeline step with an optional `when` predicate.
|
|
3
|
+
* When `when` is provided, the step only runs if `when(ctx)` returns `true`.
|
|
4
|
+
* If `when` returns `false`, the pipeline logs `"Skipping step <name>"` and
|
|
5
|
+
* advances to the next step without invoking `run()`.
|
|
6
|
+
*
|
|
7
|
+
* Predicates are declared in the command constructor via `addDisableStepOption`,
|
|
8
|
+
* keeping skip conditions co-located with the option that controls them.
|
|
9
|
+
*/ export class Step {
|
|
10
|
+
type;
|
|
11
|
+
when;
|
|
12
|
+
constructor(type, when){
|
|
13
|
+
this.type = type;
|
|
14
|
+
this.when = when;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { InteropError } from "../errors/interop.error.js";
|
|
2
|
+
import { Shell } from "../shell/shell.js";
|
|
3
|
+
export class Docker extends Shell {
|
|
4
|
+
name = "docker";
|
|
5
|
+
program = "docker";
|
|
6
|
+
async build(contextDir, options = {}) {
|
|
7
|
+
if (contextDir == null || contextDir.trim() === "") {
|
|
8
|
+
throw new InteropError("Docker build context is required");
|
|
9
|
+
}
|
|
10
|
+
const args = [
|
|
11
|
+
"build"
|
|
12
|
+
];
|
|
13
|
+
if (options.dockerfile) {
|
|
14
|
+
args.push("-f", options.dockerfile);
|
|
15
|
+
}
|
|
16
|
+
for (const tag of options.tags ?? []){
|
|
17
|
+
args.push("-t", tag);
|
|
18
|
+
}
|
|
19
|
+
for (const [key, value] of Object.entries(options.buildArgs ?? {})){
|
|
20
|
+
args.push("--build-arg", `${key}=${value}`);
|
|
21
|
+
}
|
|
22
|
+
for (const [id, env] of Object.entries(options.secrets ?? {})){
|
|
23
|
+
args.push("--secret", `id=${id},env=${env}`);
|
|
24
|
+
}
|
|
25
|
+
if (options.noCache) {
|
|
26
|
+
args.push("--no-cache");
|
|
27
|
+
}
|
|
28
|
+
if (options.pull) {
|
|
29
|
+
args.push("--pull");
|
|
30
|
+
}
|
|
31
|
+
args.push(contextDir);
|
|
32
|
+
return await this.run({
|
|
33
|
+
cwd: options.cwd
|
|
34
|
+
}, ...args);
|
|
35
|
+
}
|
|
36
|
+
async push(tag, options = {}) {
|
|
37
|
+
if (tag == null || tag.trim() === "") {
|
|
38
|
+
throw new InteropError("Docker tag is required");
|
|
39
|
+
}
|
|
40
|
+
return await this.run({
|
|
41
|
+
cwd: options.cwd
|
|
42
|
+
}, "push", tag);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { InteropError } from "../errors/interop.error.js";
|
|
2
|
+
import { Shell } from "../shell/shell.js";
|
|
3
|
+
const Commands = {
|
|
4
|
+
stage: "stage",
|
|
5
|
+
tag: "tag",
|
|
6
|
+
add: "add",
|
|
7
|
+
commit: "commit",
|
|
8
|
+
push: "push",
|
|
9
|
+
listFiles: "ls-files"
|
|
10
|
+
};
|
|
11
|
+
const defaultOptions = {
|
|
12
|
+
cwd: "./"
|
|
13
|
+
};
|
|
14
|
+
export class Git extends Shell {
|
|
15
|
+
program = "git";
|
|
16
|
+
async getModifiedFiles(options = defaultOptions) {
|
|
17
|
+
const args = [
|
|
18
|
+
Commands.listFiles,
|
|
19
|
+
"--modified"
|
|
20
|
+
];
|
|
21
|
+
const { cwd } = options;
|
|
22
|
+
const result = await this.run({
|
|
23
|
+
cwd
|
|
24
|
+
}, ...args);
|
|
25
|
+
return result.data;
|
|
26
|
+
}
|
|
27
|
+
async getBranchName(options = defaultOptions) {
|
|
28
|
+
const { cwd } = options;
|
|
29
|
+
const args = [
|
|
30
|
+
"rev-parse",
|
|
31
|
+
"--symbolic-full-name",
|
|
32
|
+
"--abbrev-ref",
|
|
33
|
+
"HEAD"
|
|
34
|
+
];
|
|
35
|
+
const result = await this.run({
|
|
36
|
+
cwd
|
|
37
|
+
}, ...args);
|
|
38
|
+
return result.data[0];
|
|
39
|
+
}
|
|
40
|
+
async tag(tag, options = defaultOptions) {
|
|
41
|
+
const args = [
|
|
42
|
+
Commands.tag,
|
|
43
|
+
tag
|
|
44
|
+
];
|
|
45
|
+
const { cwd } = options;
|
|
46
|
+
const result = await this.run({
|
|
47
|
+
cwd
|
|
48
|
+
}, ...args);
|
|
49
|
+
return result;
|
|
50
|
+
}
|
|
51
|
+
async pushTag(tag, options = defaultOptions) {
|
|
52
|
+
const { cwd, remote = "origin" } = options;
|
|
53
|
+
const result = await this.run({
|
|
54
|
+
cwd
|
|
55
|
+
}, Commands.push, remote, tag);
|
|
56
|
+
return result;
|
|
57
|
+
}
|
|
58
|
+
async commit(message, options) {
|
|
59
|
+
const optionsAndDefaults = {
|
|
60
|
+
...defaultOptions,
|
|
61
|
+
...options
|
|
62
|
+
};
|
|
63
|
+
const { cwd, files = [], all } = optionsAndDefaults;
|
|
64
|
+
const args = [
|
|
65
|
+
Commands.commit
|
|
66
|
+
];
|
|
67
|
+
if (files.length > 0 && all) {
|
|
68
|
+
throw new InteropError("Cannot commit all and files at the same time");
|
|
69
|
+
}
|
|
70
|
+
if (files.length > 0) {
|
|
71
|
+
await this.stage({
|
|
72
|
+
files
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
if (options.all) {
|
|
76
|
+
args.push("-a");
|
|
77
|
+
}
|
|
78
|
+
args.push("-m", message);
|
|
79
|
+
const result = await this.run({
|
|
80
|
+
cwd
|
|
81
|
+
}, ...args);
|
|
82
|
+
return result;
|
|
83
|
+
}
|
|
84
|
+
async push(branch, options) {
|
|
85
|
+
const optionsAndDefaults = {
|
|
86
|
+
...defaultOptions,
|
|
87
|
+
...options
|
|
88
|
+
};
|
|
89
|
+
const { cwd, setUpstream } = optionsAndDefaults;
|
|
90
|
+
const args = [
|
|
91
|
+
Commands.push
|
|
92
|
+
];
|
|
93
|
+
args.push("--set-upstream", setUpstream ?? "origin");
|
|
94
|
+
args.push(branch);
|
|
95
|
+
const result = await this.run({
|
|
96
|
+
cwd
|
|
97
|
+
}, ...args);
|
|
98
|
+
return result;
|
|
99
|
+
}
|
|
100
|
+
async pull(branch, options = defaultOptions) {
|
|
101
|
+
const { cwd } = options;
|
|
102
|
+
return this.run({
|
|
103
|
+
cwd
|
|
104
|
+
}, "pull", "--rebase", "origin", branch);
|
|
105
|
+
}
|
|
106
|
+
async stage(options) {
|
|
107
|
+
const optionsAndDefaults = {
|
|
108
|
+
...defaultOptions,
|
|
109
|
+
...options
|
|
110
|
+
};
|
|
111
|
+
const { cwd, files = [], all } = optionsAndDefaults;
|
|
112
|
+
if (all) {
|
|
113
|
+
await this.run({
|
|
114
|
+
cwd
|
|
115
|
+
}, Commands.stage, "-a");
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
for (const file of files){
|
|
119
|
+
await this.run({
|
|
120
|
+
cwd
|
|
121
|
+
}, Commands.stage, file);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
// << Git >>
|
|
2
|
+
// << Docker >>
|
|
3
|
+
export * from "./docker/docker.js";
|
|
4
|
+
export * from "./git/git.js";
|
|
5
|
+
export * as git from "./git/git.types.js";
|
|
6
|
+
// << Node >>
|
|
7
|
+
export * from "./node/node.js";
|
|
8
|
+
// << Npm >>
|
|
9
|
+
export * from "./npm/npm.js";
|
|
10
|
+
export * as npm from "./npm/npm.types.js";
|
|
11
|
+
// << Pnpm >>
|
|
12
|
+
export * from "./pnpm/pnpm.js";
|
|
13
|
+
export * as pnpm from "./pnpm/pnpm.types.js";
|
|
14
|
+
// << Shell >>
|
|
15
|
+
export * from "./shell/shell.js";
|
|
16
|
+
export * as shell from "./shell/shell.types.js";
|
|
17
|
+
export * from "./types/detect-package-manager.js";
|
|
18
|
+
export * from "./types/package-manager.js";
|
|
19
|
+
// << Yarn >>
|
|
20
|
+
export * from "./yarn/yarn.js";
|
|
21
|
+
export * as yarn from "./yarn/yarn.types.js";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./node.js";
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
import { Shell } from "../shell/shell.js";
|
|
3
|
+
export class Node extends Shell {
|
|
4
|
+
program = "node";
|
|
5
|
+
async runScript(script, ...args) {
|
|
6
|
+
const spawnOpt = {
|
|
7
|
+
cwd: ".",
|
|
8
|
+
stdio: "inherit",
|
|
9
|
+
env: {
|
|
10
|
+
...process.env
|
|
11
|
+
}
|
|
12
|
+
};
|
|
13
|
+
return new Promise((resolve, reject)=>{
|
|
14
|
+
const proc = spawn("node", [
|
|
15
|
+
script,
|
|
16
|
+
...args
|
|
17
|
+
], spawnOpt);
|
|
18
|
+
proc.on("exit", (code)=>{
|
|
19
|
+
if (code !== 0) {
|
|
20
|
+
reject();
|
|
21
|
+
}
|
|
22
|
+
resolve(null);
|
|
23
|
+
});
|
|
24
|
+
proc.on("close", (code)=>{
|
|
25
|
+
resolve(null);
|
|
26
|
+
if (code === 0) {
|
|
27
|
+
resolve({
|
|
28
|
+
message: `${script} completed`
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
reject(`Running '${script}' failed with code ${code}`);
|
|
32
|
+
});
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
import { InteropError } from "../errors/interop.error.js";
|
|
2
|
+
import { Shell } from "../shell/shell.js";
|
|
3
|
+
const Commands = {
|
|
4
|
+
publish: "publish",
|
|
5
|
+
version: "version",
|
|
6
|
+
link: "link",
|
|
7
|
+
install: "install"
|
|
8
|
+
};
|
|
9
|
+
export class Npm extends Shell {
|
|
10
|
+
name = "npm";
|
|
11
|
+
program = "npm";
|
|
12
|
+
async publish(directory, options = {
|
|
13
|
+
channel: "beta"
|
|
14
|
+
}) {
|
|
15
|
+
const { cwd, dryRun, skipIfPublished, channel, authToken, otp, provenance } = options;
|
|
16
|
+
if (directory == null) {
|
|
17
|
+
throw new InteropError("Directory is required");
|
|
18
|
+
}
|
|
19
|
+
if (skipIfPublished && !dryRun) {
|
|
20
|
+
const alreadyPublished = await this.isPublished(directory, {
|
|
21
|
+
cwd
|
|
22
|
+
});
|
|
23
|
+
if (alreadyPublished) {
|
|
24
|
+
return {
|
|
25
|
+
message: `Skipping publish — version already exists on registry`,
|
|
26
|
+
data: []
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
const args = [
|
|
31
|
+
Commands.publish,
|
|
32
|
+
directory
|
|
33
|
+
];
|
|
34
|
+
let tmpUserConfigPath;
|
|
35
|
+
args.push("--tag", channel ?? "beta");
|
|
36
|
+
if (provenance) {
|
|
37
|
+
args.push("--provenance");
|
|
38
|
+
}
|
|
39
|
+
// Explicit --token (local bootstrap). OIDC publish must not inherit cwd .npmrc / NODE_AUTH_TOKEN.
|
|
40
|
+
if (authToken?.trim()) {
|
|
41
|
+
tmpUserConfigPath = await this.createTempUserConfig(authToken.trim());
|
|
42
|
+
args.push("--userconfig", tmpUserConfigPath);
|
|
43
|
+
}
|
|
44
|
+
if (dryRun) {
|
|
45
|
+
args.push("--dry-run");
|
|
46
|
+
}
|
|
47
|
+
const env = {
|
|
48
|
+
...process.env
|
|
49
|
+
};
|
|
50
|
+
if (!authToken?.trim()) {
|
|
51
|
+
delete env.NODE_AUTH_TOKEN;
|
|
52
|
+
delete env.NPM_TOKEN;
|
|
53
|
+
env.NPM_CONFIG_USERCONFIG = "/dev/null";
|
|
54
|
+
}
|
|
55
|
+
if (otp) {
|
|
56
|
+
env.NPM_CONFIG_OTP = otp;
|
|
57
|
+
}
|
|
58
|
+
try {
|
|
59
|
+
return await this.run({
|
|
60
|
+
cwd,
|
|
61
|
+
env
|
|
62
|
+
}, ...args);
|
|
63
|
+
} catch (error) {
|
|
64
|
+
if (skipIfPublished && !dryRun && isAlreadyPublishedError(error)) {
|
|
65
|
+
return {
|
|
66
|
+
message: `Skipping publish — version already exists on registry`,
|
|
67
|
+
data: []
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
throw error;
|
|
71
|
+
} finally{
|
|
72
|
+
if (tmpUserConfigPath) {
|
|
73
|
+
await this.removeTempUserConfig(tmpUserConfigPath);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* @description Runs in the directory of the package
|
|
79
|
+
* @param options
|
|
80
|
+
* @returns
|
|
81
|
+
*/ async version(versionType, options) {
|
|
82
|
+
const { cwd, noTag, preid } = options;
|
|
83
|
+
const args = [
|
|
84
|
+
Commands.version,
|
|
85
|
+
versionType
|
|
86
|
+
];
|
|
87
|
+
if (noTag) {
|
|
88
|
+
args.push("--no-git-tag-version");
|
|
89
|
+
}
|
|
90
|
+
if (preid) {
|
|
91
|
+
args.push("--preid", preid);
|
|
92
|
+
}
|
|
93
|
+
return this.run({
|
|
94
|
+
cwd
|
|
95
|
+
}, ...args);
|
|
96
|
+
}
|
|
97
|
+
async link(directory, options = {
|
|
98
|
+
cwd: "./"
|
|
99
|
+
}) {
|
|
100
|
+
const { cwd } = options;
|
|
101
|
+
const args = [
|
|
102
|
+
Commands.link,
|
|
103
|
+
directory
|
|
104
|
+
];
|
|
105
|
+
return this.run({
|
|
106
|
+
cwd
|
|
107
|
+
}, ...args);
|
|
108
|
+
}
|
|
109
|
+
async install(options = {
|
|
110
|
+
cwd: "./"
|
|
111
|
+
}) {
|
|
112
|
+
const { cwd } = options;
|
|
113
|
+
return this.run({
|
|
114
|
+
cwd
|
|
115
|
+
}, Commands.install);
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Install only `dependencies` as real folders: `--omit=dev` skips devDependencies and
|
|
119
|
+
* `--no-bin-links` skips the `.bin` symlinks, so the result holds no symlinks at all.
|
|
120
|
+
*/ async installProduction(options = {
|
|
121
|
+
cwd: "./"
|
|
122
|
+
}) {
|
|
123
|
+
const { cwd } = options;
|
|
124
|
+
return this.run({
|
|
125
|
+
cwd
|
|
126
|
+
}, Commands.install, "--omit=dev", "--no-bin-links", "--no-audit", "--no-fund", "--loglevel=error");
|
|
127
|
+
}
|
|
128
|
+
async syncLockFile(options = {
|
|
129
|
+
cwd: "./"
|
|
130
|
+
}) {
|
|
131
|
+
const { cwd } = options;
|
|
132
|
+
return this.run({
|
|
133
|
+
cwd
|
|
134
|
+
}, Commands.install, "--package-lock-only", "--ignore-scripts");
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* True when package@version exists on the registry.
|
|
138
|
+
* Uses ambient npm config (cwd `.npmrc`); do not pass tokens on argv.
|
|
139
|
+
*/ async isPublished(directory, options) {
|
|
140
|
+
const { readFileSync } = await import("node:fs");
|
|
141
|
+
const { join } = await import("node:path");
|
|
142
|
+
try {
|
|
143
|
+
const pkgJson = JSON.parse(readFileSync(join(directory, "package.json"), "utf8"));
|
|
144
|
+
const spec = `${pkgJson.name}@${pkgJson.version}`;
|
|
145
|
+
await this.run(options, "view", spec, "version");
|
|
146
|
+
return true;
|
|
147
|
+
} catch {
|
|
148
|
+
return false;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
async createTempUserConfig(authToken) {
|
|
152
|
+
const { mkdtemp, writeFile } = await import("node:fs/promises");
|
|
153
|
+
const { tmpdir } = await import("node:os");
|
|
154
|
+
const { join } = await import("node:path");
|
|
155
|
+
const tempDir = await mkdtemp(join(tmpdir(), "decohere-npmrc-"));
|
|
156
|
+
const npmrcPath = join(tempDir, ".npmrc");
|
|
157
|
+
const npmrc = [
|
|
158
|
+
"registry=https://registry.npmjs.org/",
|
|
159
|
+
"always-auth=true",
|
|
160
|
+
`//registry.npmjs.org/:_authToken=${authToken}`
|
|
161
|
+
].join("\n");
|
|
162
|
+
await writeFile(npmrcPath, `${npmrc}\n`, {
|
|
163
|
+
mode: 0o600
|
|
164
|
+
});
|
|
165
|
+
return npmrcPath;
|
|
166
|
+
}
|
|
167
|
+
async removeTempUserConfig(npmrcPath) {
|
|
168
|
+
const { rm } = await import("node:fs/promises");
|
|
169
|
+
const { dirname } = await import("node:path");
|
|
170
|
+
const dir = dirname(npmrcPath);
|
|
171
|
+
await rm(dir, {
|
|
172
|
+
recursive: true,
|
|
173
|
+
force: true
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
function isAlreadyPublishedError(error) {
|
|
178
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
179
|
+
return /cannot publish over the previously published versions/i.test(message);
|
|
180
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Shell } from "../shell/shell.js";
|
|
2
|
+
const Commands = {
|
|
3
|
+
install: "install"
|
|
4
|
+
};
|
|
5
|
+
export class Pnpm extends Shell {
|
|
6
|
+
name = "pnpm";
|
|
7
|
+
program = "pnpm";
|
|
8
|
+
async install(options = {
|
|
9
|
+
cwd: "./"
|
|
10
|
+
}) {
|
|
11
|
+
const { cwd } = options;
|
|
12
|
+
return this.run({
|
|
13
|
+
cwd
|
|
14
|
+
}, Commands.install);
|
|
15
|
+
}
|
|
16
|
+
async syncLockFile(options = {
|
|
17
|
+
cwd: "./"
|
|
18
|
+
}) {
|
|
19
|
+
const { cwd } = options;
|
|
20
|
+
return this.run({
|
|
21
|
+
cwd
|
|
22
|
+
}, Commands.install, "--lockfile-only", "--ignore-scripts");
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { };
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
function fields(args) {
|
|
2
|
+
const positional = [];
|
|
3
|
+
const flags = {};
|
|
4
|
+
for(let i = 0; i < args.length; i++){
|
|
5
|
+
const arg = args[i];
|
|
6
|
+
if (arg === "--") {
|
|
7
|
+
positional.push(...args.slice(i + 1));
|
|
8
|
+
break;
|
|
9
|
+
}
|
|
10
|
+
if (arg.startsWith("--")) {
|
|
11
|
+
const body = arg.slice(2);
|
|
12
|
+
const eq = body.indexOf("=");
|
|
13
|
+
if (eq !== -1) {
|
|
14
|
+
flags[body.slice(0, eq)] = body.slice(eq + 1);
|
|
15
|
+
continue;
|
|
16
|
+
}
|
|
17
|
+
const next = args[i + 1];
|
|
18
|
+
if (next != null && !next.startsWith("-")) {
|
|
19
|
+
flags[body] = next;
|
|
20
|
+
i += 1;
|
|
21
|
+
} else {
|
|
22
|
+
flags[body] = true;
|
|
23
|
+
}
|
|
24
|
+
continue;
|
|
25
|
+
}
|
|
26
|
+
positional.push(arg);
|
|
27
|
+
}
|
|
28
|
+
return {
|
|
29
|
+
_: positional,
|
|
30
|
+
...flags
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
export const shellArgv = {
|
|
34
|
+
fields
|
|
35
|
+
};
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
import { scribe } from "@decohere/scribe";
|
|
3
|
+
import { InteropError } from "../errors/interop.error.js";
|
|
4
|
+
import { shellArgv } from "./shell.argv.js";
|
|
5
|
+
export class Shell {
|
|
6
|
+
async run(options, ...args) {
|
|
7
|
+
const logger = scribe.logger(Shell.name);
|
|
8
|
+
const argv = args ?? [];
|
|
9
|
+
const argvFields = shellArgv.fields(argv);
|
|
10
|
+
const positionals = Array.isArray(argvFields._) ? argvFields._ : [];
|
|
11
|
+
const commandName = [
|
|
12
|
+
this.program,
|
|
13
|
+
...positionals
|
|
14
|
+
].join(" ").trim();
|
|
15
|
+
logger.info("Running", {
|
|
16
|
+
program: this.program,
|
|
17
|
+
args: argvFields
|
|
18
|
+
});
|
|
19
|
+
return new Promise((resolve, reject)=>{
|
|
20
|
+
let settled = false;
|
|
21
|
+
const resolveOnce = (response)=>{
|
|
22
|
+
if (settled) {
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
settled = true;
|
|
26
|
+
resolve(response);
|
|
27
|
+
};
|
|
28
|
+
const rejectOnce = (error)=>{
|
|
29
|
+
if (settled) {
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
settled = true;
|
|
33
|
+
reject(error);
|
|
34
|
+
};
|
|
35
|
+
const { cwd, env } = options;
|
|
36
|
+
const spawnOpt = {
|
|
37
|
+
cwd: cwd ?? ".",
|
|
38
|
+
stdio: [
|
|
39
|
+
"inherit",
|
|
40
|
+
"pipe",
|
|
41
|
+
"pipe"
|
|
42
|
+
],
|
|
43
|
+
env: env ?? {
|
|
44
|
+
...process.env
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
const proc = spawn(this.program, argv, spawnOpt);
|
|
48
|
+
const responseData = [];
|
|
49
|
+
const errorData = [];
|
|
50
|
+
proc.on("close", (code, signal)=>{
|
|
51
|
+
if (code === 0) {
|
|
52
|
+
resolveOnce({
|
|
53
|
+
message: `${commandName} completed`,
|
|
54
|
+
data: responseData
|
|
55
|
+
});
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
const stderr = errorData.join("\n").trim();
|
|
59
|
+
const stdout = responseData.join("\n").trim();
|
|
60
|
+
const exitCodeText = code == null ? "unknown" : String(code);
|
|
61
|
+
const signalText = signal ? ` signal ${signal}` : "";
|
|
62
|
+
const base = `Running '${commandName}' failed with code ${exitCodeText}${signalText}`;
|
|
63
|
+
const details = [
|
|
64
|
+
stderr ? `stderr:\n${stderr}` : "",
|
|
65
|
+
!stderr && stdout ? `stdout:\n${stdout}` : ""
|
|
66
|
+
].filter(Boolean).join("\n");
|
|
67
|
+
rejectOnce(new InteropError(details ? `${base}\n${details}` : base));
|
|
68
|
+
});
|
|
69
|
+
proc.on("error", (err)=>{
|
|
70
|
+
rejectOnce(err);
|
|
71
|
+
});
|
|
72
|
+
proc.stdout.on("error", (err)=>{
|
|
73
|
+
rejectOnce(err);
|
|
74
|
+
});
|
|
75
|
+
proc.stdout.on("data", (data)=>{
|
|
76
|
+
const lines = this.parseStream(data);
|
|
77
|
+
console.log(data.toString());
|
|
78
|
+
responseData.push(...lines);
|
|
79
|
+
});
|
|
80
|
+
proc.stderr?.on("error", (err)=>{
|
|
81
|
+
rejectOnce(err);
|
|
82
|
+
});
|
|
83
|
+
proc.stderr?.on("data", (data)=>{
|
|
84
|
+
const lines = this.parseStream(data);
|
|
85
|
+
console.error(data.toString());
|
|
86
|
+
errorData.push(...lines);
|
|
87
|
+
});
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
parseStream(data) {
|
|
91
|
+
const dataStr = data.toString();
|
|
92
|
+
const lines = dataStr.split("\n").filter((l)=>l !== "");
|
|
93
|
+
return lines;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { };
|