@astrale-os/sdk 0.5.0-beta.41 → 0.5.0-beta.43

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.
@@ -10,3 +10,5 @@ export type BunOutcome = {
10
10
  };
11
11
  /** Re-enter the published executable under Bun only when authored TypeScript must be imported. */
12
12
  export declare function runWithBun(executable: string, argv: readonly string[]): Promise<BunOutcome>;
13
+ /** Prefer the generated project's exact Bun package binary over an ambient executable or shim. */
14
+ export declare function resolveBunExecutable(cwd: string): string;
@@ -1,4 +1,7 @@
1
1
  import { spawn } from 'node:child_process';
2
+ import { lstatSync, readFileSync, realpathSync, statSync } from 'node:fs';
3
+ import { createRequire } from 'node:module';
4
+ import { dirname, isAbsolute, join, relative, resolve } from 'node:path';
2
5
  const FORWARDED_SIGNALS = ['SIGINT', 'SIGTERM'];
3
6
  export class BunRequiredError extends Error {
4
7
  constructor(options) {
@@ -9,7 +12,9 @@ export class BunRequiredError extends Error {
9
12
  /** Re-enter the published executable under Bun only when authored TypeScript must be imported. */
10
13
  export function runWithBun(executable, argv) {
11
14
  return new Promise((resolve, reject) => {
12
- const child = spawn('bun', [executable, ...argv], { stdio: 'inherit' });
15
+ const child = spawn(resolveBunExecutable(process.cwd()), [executable, ...argv], {
16
+ stdio: 'inherit',
17
+ });
13
18
  const handlers = FORWARDED_SIGNALS.map((signal) => [signal, () => child.kill(signal)]);
14
19
  for (const [signal, handler] of handlers)
15
20
  process.on(signal, handler);
@@ -35,3 +40,62 @@ export function runWithBun(executable, argv) {
35
40
  });
36
41
  });
37
42
  }
43
+ /** Prefer the generated project's exact Bun package binary over an ambient executable or shim. */
44
+ export function resolveBunExecutable(cwd) {
45
+ const projectRequire = createRequire(join(cwd, 'package.json'));
46
+ let manifestPath;
47
+ try {
48
+ manifestPath = projectRequire.resolve('bun/package.json');
49
+ }
50
+ catch (cause) {
51
+ if (isMissingPackage(cause) && !hasBunPackageEntry(projectRequire))
52
+ return 'bun';
53
+ throw new BunRequiredError({ cause });
54
+ }
55
+ try {
56
+ const manifest = JSON.parse(readFileSync(manifestPath, 'utf8'));
57
+ const declared = typeof manifest.bin === 'string' ? manifest.bin : manifest.bin?.bun;
58
+ if (typeof declared !== 'string' || declared.length === 0 || isAbsolute(declared)) {
59
+ throw new Error('The project-local Bun package has an invalid bun binary declaration.');
60
+ }
61
+ const root = dirname(manifestPath);
62
+ const candidate = resolve(root, declared);
63
+ const physicalRoot = realpathSync(root);
64
+ const physicalCandidate = realpathSync(candidate);
65
+ const fromRoot = relative(physicalRoot, physicalCandidate);
66
+ if (fromRoot === '' || fromRoot.startsWith('..') || isAbsolute(fromRoot)) {
67
+ throw new Error('The project-local Bun binary escapes its package directory.');
68
+ }
69
+ if (!statSync(physicalCandidate).isFile()) {
70
+ throw new Error('The project-local Bun binary is not a regular file.');
71
+ }
72
+ return physicalCandidate;
73
+ }
74
+ catch (cause) {
75
+ throw new BunRequiredError({ cause });
76
+ }
77
+ }
78
+ function hasBunPackageEntry(projectRequire) {
79
+ for (const searchRoot of projectRequire.resolve.paths('bun') ?? []) {
80
+ try {
81
+ lstatSync(join(searchRoot, 'bun'));
82
+ return true;
83
+ }
84
+ catch (error) {
85
+ if (!isMissingEntry(error))
86
+ throw error;
87
+ }
88
+ }
89
+ return false;
90
+ }
91
+ function isMissingEntry(error) {
92
+ return (error instanceof Error &&
93
+ 'code' in error &&
94
+ (error.code === 'ENOENT' ||
95
+ error.code === 'ENOTDIR'));
96
+ }
97
+ function isMissingPackage(error) {
98
+ return (error instanceof Error &&
99
+ 'code' in error &&
100
+ error.code === 'MODULE_NOT_FOUND');
101
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@astrale-os/sdk",
3
- "version": "0.5.0-beta.41",
3
+ "version": "0.5.0-beta.43",
4
4
  "description": "Schema-first SDK for defining, composing, and deploying Astrale domains",
5
5
  "keywords": [
6
6
  "astrale",