@adityaaria/spark 6.0.11 → 6.0.13

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adityaaria/spark",
3
- "version": "6.0.11",
3
+ "version": "6.0.13",
4
4
  "description": "SPARK skills and runtime bootstrap for coding agents",
5
5
  "type": "module",
6
6
  "publishConfig": {
@@ -43,7 +43,7 @@ export function stageCodexPlugin({ cwd = process.cwd(), packageRoot, dryRun = fa
43
43
  targetRoot,
44
44
  relativeTargetRoot: CODEX_PLUGIN_DIR,
45
45
  marketplaceRoot,
46
- relativeMarketplaceRoot: CODEX_MARKETPLACE_DIR,
46
+ relativeMarketplaceRoot: `./${CODEX_MARKETPLACE_DIR}`,
47
47
  };
48
48
  }
49
49
 
@@ -1,5 +1,7 @@
1
1
  import { spawnSync } from 'node:child_process';
2
2
  import { InstallerError } from '../errors.js';
3
+ import fs from 'node:fs';
4
+ import path from 'node:path';
3
5
 
4
6
  export function createAdapter({
5
7
  id,
@@ -49,6 +51,11 @@ export function createAdapter({
49
51
  throw new InstallerError(`${label} install is not fully automatable yet.`);
50
52
  }
51
53
 
54
+ const fsImpl = fs ?? nativeFs;
55
+ if (!dryRun) {
56
+ assertBinaryAvailability({ label, binaryNames, env, fsImpl });
57
+ }
58
+
52
59
  let metadata = {};
53
60
 
54
61
  if (typeof customInstall === 'function') {
@@ -85,6 +92,8 @@ export function createAdapter({
85
92
  };
86
93
  }
87
94
 
95
+ const nativeFs = fs;
96
+
88
97
  function normalizeCommandList(commands, command) {
89
98
  if (Array.isArray(commands) && commands.length > 0) {
90
99
  return commands;
@@ -97,6 +106,46 @@ function normalizeCommandList(commands, command) {
97
106
  return [];
98
107
  }
99
108
 
109
+ function assertBinaryAvailability({ label, binaryNames, env, fsImpl }) {
110
+ if (!binaryNames || binaryNames.length === 0) {
111
+ return;
112
+ }
113
+
114
+ for (const binaryName of binaryNames) {
115
+ if (commandExists(binaryName, env, fsImpl)) {
116
+ return;
117
+ }
118
+ }
119
+
120
+ throw new InstallerError(`${label} is not installed or not on PATH. Install ${label} first, then rerun SPARK install.`);
121
+ }
122
+
123
+ function commandExists(commandName, env, fsImpl) {
124
+ const paths = String(env.PATH ?? '').split(path.delimiter).filter(Boolean);
125
+ const exts = process.platform === 'win32'
126
+ ? String(env.PATHEXT ?? '.EXE;.CMD;.BAT;.COM').split(';').filter(Boolean)
127
+ : [''];
128
+
129
+ for (const dir of paths) {
130
+ for (const ext of exts) {
131
+ const candidate = path.join(dir, `${commandName}${ext}`);
132
+ try {
133
+ fsImpl.accessSync(candidate, fs.constants.X_OK);
134
+ return true;
135
+ } catch {
136
+ try {
137
+ fsImpl.accessSync(candidate, fs.constants.F_OK);
138
+ return true;
139
+ } catch {
140
+ continue;
141
+ }
142
+ }
143
+ }
144
+ }
145
+
146
+ return false;
147
+ }
148
+
100
149
  function interpolateArgs(args, metadata) {
101
150
  return args.map((arg) =>
102
151
  String(arg)