@decohere/core 0.0.1-dev.117 → 0.0.1-dev.119

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 (125) hide show
  1. package/commonjs/src/caching/cache-manager.js +3 -3
  2. package/commonjs/src/caching/index.js +1 -1
  3. package/commonjs/src/caching/map-cache.js +39 -0
  4. package/commonjs/src/io/io.js +0 -3
  5. package/es6/src/caching/cache-manager.js +3 -3
  6. package/es6/src/caching/index.js +1 -1
  7. package/es6/src/caching/map-cache.js +35 -0
  8. package/es6/src/caching/memoize.decorator.js +1 -1
  9. package/es6/src/io/io.js +0 -3
  10. package/package.json +6 -40
  11. package/types/src/caching/index.d.ts +1 -1
  12. package/types/src/caching/map-cache.d.ts +23 -0
  13. package/types/src/caching/memoize.decorator.d.ts +1 -1
  14. package/types/src/io/io.d.ts +0 -3
  15. package/commonjs/src/caching/node-cache-memoize.adapter.js +0 -49
  16. package/commonjs/src/cli/action.js +0 -65
  17. package/commonjs/src/cli/command.js +0 -127
  18. package/commonjs/src/cli/index.js +0 -61
  19. package/commonjs/src/cli/module.type.js +0 -18
  20. package/commonjs/src/cli/options.js +0 -115
  21. package/commonjs/src/diagnostics/index.js +0 -22
  22. package/commonjs/src/diagnostics/trace.js +0 -86
  23. package/commonjs/src/interop/docker/docker.js +0 -54
  24. package/commonjs/src/interop/errors/interop.error.js +0 -12
  25. package/commonjs/src/interop/git/git.js +0 -134
  26. package/commonjs/src/interop/git/git.types.js +0 -4
  27. package/commonjs/src/interop/index.js +0 -97
  28. package/commonjs/src/interop/node/index.js +0 -18
  29. package/commonjs/src/interop/node/node.js +0 -45
  30. package/commonjs/src/interop/npm/npm.js +0 -231
  31. package/commonjs/src/interop/npm/npm.types.js +0 -16
  32. package/commonjs/src/interop/pnpm/pnpm.js +0 -34
  33. package/commonjs/src/interop/pnpm/pnpm.types.js +0 -4
  34. package/commonjs/src/interop/shell/shell.argv.js +0 -45
  35. package/commonjs/src/interop/shell/shell.js +0 -105
  36. package/commonjs/src/interop/shell/shell.types.js +0 -4
  37. package/commonjs/src/interop/types/detect-package-manager.js +0 -71
  38. package/commonjs/src/interop/types/package-manager.js +0 -4
  39. package/commonjs/src/interop/yarn/yarn.js +0 -34
  40. package/commonjs/src/interop/yarn/yarn.types.js +0 -4
  41. package/commonjs/src/io/find-directories.js +0 -21
  42. package/commonjs/src/io/find-file.js +0 -45
  43. package/commonjs/src/io/watch.js +0 -261
  44. package/commonjs/src/semver/index.js +0 -18
  45. package/commonjs/src/semver/semver.js +0 -92
  46. package/commonjs/src/testing/flush-promises.js +0 -16
  47. package/commonjs/src/testing/glob-with-memfs.js +0 -22
  48. package/commonjs/src/testing/index.js +0 -22
  49. package/commonjs/src/testing/memfs.js +0 -52
  50. package/commonjs/src/testing/mock-logger.js +0 -36
  51. package/commonjs/src/testing/spy-on-constructor.js +0 -27
  52. package/es6/src/caching/node-cache-memoize.adapter.js +0 -37
  53. package/es6/src/cli/action.js +0 -47
  54. package/es6/src/cli/command.js +0 -106
  55. package/es6/src/cli/index.js +0 -4
  56. package/es6/src/cli/module.type.js +0 -11
  57. package/es6/src/cli/options.js +0 -76
  58. package/es6/src/diagnostics/index.js +0 -1
  59. package/es6/src/diagnostics/trace.js +0 -68
  60. package/es6/src/interop/docker/docker.js +0 -44
  61. package/es6/src/interop/errors/interop.error.js +0 -2
  62. package/es6/src/interop/git/git.js +0 -124
  63. package/es6/src/interop/git/git.types.js +0 -1
  64. package/es6/src/interop/index.js +0 -21
  65. package/es6/src/interop/node/index.js +0 -1
  66. package/es6/src/interop/node/node.js +0 -35
  67. package/es6/src/interop/npm/npm.js +0 -180
  68. package/es6/src/interop/npm/npm.types.js +0 -6
  69. package/es6/src/interop/pnpm/pnpm.js +0 -24
  70. package/es6/src/interop/pnpm/pnpm.types.js +0 -1
  71. package/es6/src/interop/shell/shell.argv.js +0 -35
  72. package/es6/src/interop/shell/shell.js +0 -95
  73. package/es6/src/interop/shell/shell.types.js +0 -1
  74. package/es6/src/interop/types/detect-package-manager.js +0 -50
  75. package/es6/src/interop/types/package-manager.js +0 -1
  76. package/es6/src/interop/yarn/yarn.js +0 -24
  77. package/es6/src/interop/yarn/yarn.types.js +0 -1
  78. package/es6/src/io/find-directories.js +0 -11
  79. package/es6/src/io/find-file.js +0 -27
  80. package/es6/src/io/watch.js +0 -238
  81. package/es6/src/semver/index.js +0 -1
  82. package/es6/src/semver/semver.js +0 -71
  83. package/es6/src/testing/flush-promises.js +0 -6
  84. package/es6/src/testing/glob-with-memfs.js +0 -20
  85. package/es6/src/testing/index.js +0 -5
  86. package/es6/src/testing/memfs.js +0 -25
  87. package/es6/src/testing/mock-logger.js +0 -26
  88. package/es6/src/testing/spy-on-constructor.js +0 -31
  89. package/types/src/caching/node-cache-memoize.adapter.d.ts +0 -22
  90. package/types/src/cli/action.d.ts +0 -36
  91. package/types/src/cli/command.d.ts +0 -34
  92. package/types/src/cli/index.d.ts +0 -7
  93. package/types/src/cli/module.type.d.ts +0 -36
  94. package/types/src/cli/options.d.ts +0 -28
  95. package/types/src/diagnostics/index.d.ts +0 -1
  96. package/types/src/diagnostics/trace.d.ts +0 -10
  97. package/types/src/interop/docker/docker.d.ts +0 -19
  98. package/types/src/interop/errors/interop.error.d.ts +0 -2
  99. package/types/src/interop/git/git.d.ts +0 -16
  100. package/types/src/interop/git/git.types.d.ts +0 -14
  101. package/types/src/interop/index.d.ts +0 -14
  102. package/types/src/interop/node/index.d.ts +0 -1
  103. package/types/src/interop/node/node.d.ts +0 -5
  104. package/types/src/interop/npm/npm.d.ts +0 -29
  105. package/types/src/interop/npm/npm.types.d.ts +0 -24
  106. package/types/src/interop/pnpm/pnpm.d.ts +0 -9
  107. package/types/src/interop/pnpm/pnpm.types.d.ts +0 -3
  108. package/types/src/interop/shell/shell.argv.d.ts +0 -5
  109. package/types/src/interop/shell/shell.d.ts +0 -6
  110. package/types/src/interop/shell/shell.types.d.ts +0 -9
  111. package/types/src/interop/types/detect-package-manager.d.ts +0 -4
  112. package/types/src/interop/types/package-manager.d.ts +0 -10
  113. package/types/src/interop/yarn/yarn.d.ts +0 -9
  114. package/types/src/interop/yarn/yarn.types.d.ts +0 -3
  115. package/types/src/io/find-directories.d.ts +0 -2
  116. package/types/src/io/find-file.d.ts +0 -9
  117. package/types/src/io/watch.d.ts +0 -16
  118. package/types/src/semver/index.d.ts +0 -1
  119. package/types/src/semver/semver.d.ts +0 -18
  120. package/types/src/testing/flush-promises.d.ts +0 -1
  121. package/types/src/testing/glob-with-memfs.d.ts +0 -3
  122. package/types/src/testing/index.d.ts +0 -5
  123. package/types/src/testing/memfs.d.ts +0 -5
  124. package/types/src/testing/mock-logger.d.ts +0 -13
  125. package/types/src/testing/spy-on-constructor.d.ts +0 -21
@@ -1,106 +0,0 @@
1
- import { Command as CommanderType } from "commander";
2
- export const CommandResponse = {
3
- success (_ctx, responses) {
4
- return responses;
5
- },
6
- help () {
7
- return {};
8
- },
9
- fromAction (name, response) {
10
- return {
11
- [name]: response
12
- };
13
- }
14
- };
15
- /** Thrown when a command execution fails due to action errors. */ export class CommandError extends Error {
16
- }
17
- export class DecohereCommand extends CommanderType {
18
- get actions() {
19
- return [];
20
- }
21
- constructor(name, handler){
22
- super();
23
- if (typeof name === "string" || typeof name === "function") {
24
- this.name(this.parseCommandName(name));
25
- } else {
26
- this.name(this.parseCommandName(this.constructor));
27
- if (name) {
28
- this.registerSubcommand(name, handler);
29
- }
30
- }
31
- if (handler && !this.commands.length) {
32
- this.action(handler);
33
- }
34
- this.exitOverride();
35
- }
36
- /**
37
- * Whether the command, with these options, runs until it is stopped (`flux serve`,
38
- * `forge build --watch`). The CLI then listens for SIGINT and SIGTERM from the moment it
39
- * starts, so a stop during start-up still shuts down cleanly; other commands keep Node's
40
- * default, where Ctrl+C ends them at once.
41
- */ runsUntilStopped(_options) {
42
- return false;
43
- }
44
- async run(actions, options) {
45
- const responses = await this.runActions(actions, options);
46
- this.throwOnErrors(responses);
47
- return CommandResponse.success(options, responses);
48
- }
49
- registerSubcommand(commands, onAction) {
50
- if (typeof commands === "function") {
51
- const instance = new commands(commands, onAction);
52
- this.addCommand(instance);
53
- if (onAction && !instance.commands.length) {
54
- instance.action(onAction);
55
- }
56
- return;
57
- }
58
- for (const [key, command] of Object.entries(commands)){
59
- const instance = command instanceof DecohereCommand ? command : new command(key, onAction);
60
- this.addCommand(instance);
61
- if (onAction && !instance.commands.length) {
62
- instance.action(onAction);
63
- }
64
- }
65
- }
66
- async runActions(actions, options) {
67
- const selectedActions = this.getSelectedActions(actions);
68
- const responses = {};
69
- for (const [actionKey, action] of selectedActions){
70
- responses[actionKey] = await action.run(options);
71
- }
72
- return responses;
73
- }
74
- getSelectedActions(actions) {
75
- if (!this.actions.length) {
76
- return [];
77
- }
78
- const actionEntries = Object.entries(actions);
79
- return this.actions.map((ActionClass)=>{
80
- const selectedAction = actionEntries.find(([, action])=>action instanceof ActionClass);
81
- if (!selectedAction) {
82
- throw new CommandError(`${this.name()} command missing action instance for ${ActionClass.name}`);
83
- }
84
- return selectedAction;
85
- });
86
- }
87
- throwOnErrors(responses) {
88
- const failures = Object.entries(responses).filter(([, response])=>{
89
- if (!response) {
90
- return false;
91
- }
92
- return !response.succeeded && !response.skipped;
93
- });
94
- if (!failures.length) {
95
- return;
96
- }
97
- throw new CommandError(`${this.name()} command failed. ${failures.map(([actionName, response])=>`${actionName}: ${response?.message ?? "Unknown error"}`).join("\n")}`);
98
- }
99
- parseCommandName(stringLike) {
100
- const command = typeof stringLike === "string" ? stringLike : stringLike.name?.toLowerCase().replace("command", "") ?? "";
101
- if (command === "") {
102
- throw new CommandError(`Could not parse command name from ${stringLike.toString()}`);
103
- }
104
- return command;
105
- }
106
- }
@@ -1,4 +0,0 @@
1
- export { ActionMap, ActionResponse } from "./action.js";
2
- export { CommandError, CommandResponse, DecohereCommand } from "./command.js";
3
- export { ModuleManifest } from "./module.type.js";
4
- export { ConfigFileOption, ConfigurationOption, DryRunOption, EnvFileIfExistsOption, EnvFileOption, LogLevelOption, NoBuildOptions, NoCleanOptions, ProjectOption } from "./options.js";
@@ -1,11 +0,0 @@
1
- /**
2
- * Simple declaration interface for a CLI module.
3
- * Extend this and implement the four abstract members.
4
- */ export class ModuleManifest {
5
- /** Sub-command classes this module contributes. */ commands = {};
6
- /** Action classes this module contributes. */ actions = {};
7
- /** Register infrastructure services into the DI container. */ registerServices(_builder) {}
8
- /** Lazily create a workspace instance. Return null if this module does not use a workspace. */ createWorkspace(_options) {
9
- return Promise.resolve(null);
10
- }
11
- }
@@ -1,76 +0,0 @@
1
- import { Option } from "commander";
2
- function parseOptionalBoolean(input) {
3
- if (typeof input === "boolean") {
4
- return input;
5
- }
6
- const value = input.trim().toLowerCase();
7
- if ([
8
- "true",
9
- "1",
10
- "yes",
11
- "on"
12
- ].includes(value)) {
13
- return true;
14
- }
15
- if ([
16
- "false",
17
- "0",
18
- "no",
19
- "off"
20
- ].includes(value)) {
21
- return false;
22
- }
23
- throw new Error(`Invalid boolean value: "${input}". Use true/false.`);
24
- }
25
- export class ConfigurationOption extends Option {
26
- constructor(defaultValue){
27
- super("--configuration <configuration>", "Configuration name");
28
- this.default(defaultValue);
29
- }
30
- }
31
- export class ConfigFileOption extends Option {
32
- constructor(defaultValue = ".decohere.js"){
33
- super("--config-file <file>", "Path to Decohere config file");
34
- this.default(defaultValue);
35
- }
36
- }
37
- export class LogLevelOption extends Option {
38
- constructor(){
39
- super("--log-level <level>", "Log level (trace, debug, info, warn, error)");
40
- }
41
- }
42
- export class EnvFileOption extends Option {
43
- constructor(){
44
- super("--env-file <file>", "Load environment variables from this file before running");
45
- }
46
- }
47
- export class EnvFileIfExistsOption extends Option {
48
- constructor(){
49
- super("--env-file-if-exists <file>", "Like --env-file, but skip it when the file is missing");
50
- }
51
- }
52
- export class NoCleanOptions extends Option {
53
- constructor(defaultValue){
54
- super("--no-clean", "Will not clean the project directories");
55
- this.default(defaultValue);
56
- }
57
- }
58
- export class NoBuildOptions extends Option {
59
- constructor(defaultValue){
60
- super("--no-build", "Will not run the build step");
61
- this.default(defaultValue);
62
- }
63
- }
64
- export class DryRunOption extends Option {
65
- constructor(description, defaultValue = false){
66
- super("--dry-run [dryRun]", description);
67
- this.default(defaultValue);
68
- this.preset(true);
69
- this.argParser(parseOptionalBoolean);
70
- }
71
- }
72
- export class ProjectOption extends Option {
73
- constructor(){
74
- super("--project <project>", "Project name to target");
75
- }
76
- }
@@ -1 +0,0 @@
1
- export { Trace, timed, trace } from "./trace.js";
@@ -1,68 +0,0 @@
1
- import { isPromise } from "node:util/types";
2
- import { ConsoleAdapter, scribe } from "@decohere/scribe";
3
- // Keep existing behavior for now: trace mode is toggled via FORGE_TRACE.
4
- const isTraceEnabled = process.env.FORGE_TRACE != null;
5
- if (isTraceEnabled) {
6
- const hasExplicitLevel = process.env.LOG_LEVEL != null || process.env.SCRIBE_LOG_LEVEL != null || process.env.LOGGING_LEVEL != null;
7
- if (!hasExplicitLevel) {
8
- scribe.configure({
9
- adapter: new ConsoleAdapter(),
10
- options: {
11
- logLevel: "trace"
12
- }
13
- });
14
- }
15
- }
16
- function serializeArgs(args) {
17
- if (args.length === 0) return "";
18
- return args.map((arg)=>{
19
- if (Array.isArray(arg)) return `[${arg.map(String).join(", ")}]`;
20
- const s = String(arg);
21
- return s.length > 60 ? `${s.slice(0, 57)}...` : s;
22
- }).join(", ");
23
- }
24
- function wrapWithTiming(fn, className, methodName, logLevel) {
25
- let logger;
26
- return function(...args) {
27
- if (logger == null) {
28
- logger = scribe.logger(className);
29
- }
30
- const log = logger;
31
- const label = `${methodName}(${serializeArgs(args)})`;
32
- const start = performance.now();
33
- const logDuration = ()=>{
34
- log[logLevel](`${label}: ${(performance.now() - start).toFixed(2)}ms`);
35
- };
36
- const result = fn.apply(this, args);
37
- if (isPromise(result)) {
38
- return result.finally(logDuration);
39
- }
40
- logDuration();
41
- return result;
42
- };
43
- }
44
- export function trace(target, propertyKey, descriptor) {
45
- if (!isTraceEnabled) return descriptor;
46
- const className = target.constructor.name;
47
- descriptor.value = wrapWithTiming(descriptor.value, className, propertyKey, "trace");
48
- return descriptor;
49
- }
50
- /**
51
- * Always-on method timing. Logs duration at `info` regardless of `FORGE_TRACE`.
52
- * Use this to time a specific method without raising the process log level.
53
- */ export function timed(target, propertyKey, descriptor) {
54
- const className = target.constructor.name;
55
- descriptor.value = wrapWithTiming(descriptor.value, className, propertyKey, "info");
56
- return descriptor;
57
- }
58
- export function Trace(constructor) {
59
- if (!isTraceEnabled) return;
60
- const className = constructor.name;
61
- for (const key of Object.getOwnPropertyNames(constructor.prototype)){
62
- if (key === "constructor") continue;
63
- const descriptor = Object.getOwnPropertyDescriptor(constructor.prototype, key);
64
- if (descriptor == null || typeof descriptor.value !== "function") continue;
65
- descriptor.value = wrapWithTiming(descriptor.value, className, key, "trace");
66
- Object.defineProperty(constructor.prototype, key, descriptor);
67
- }
68
- }
@@ -1,44 +0,0 @@
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
- }
@@ -1,2 +0,0 @@
1
- export class InteropError extends Error {
2
- }
@@ -1,124 +0,0 @@
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
- }
@@ -1 +0,0 @@
1
- export { };
@@ -1,21 +0,0 @@
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";
@@ -1 +0,0 @@
1
- export * from "./node.js";
@@ -1,35 +0,0 @@
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
- }
@@ -1,180 +0,0 @@
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
- }