@directive-run/sandbox 0.3.12 → 0.4.0
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/README.md +36 -2
- package/dist/index.cjs +4 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +45 -2
- package/dist/index.d.ts +45 -2
- package/dist/index.js +4 -4
- package/dist/index.js.map +1 -1
- package/dist/worker.js +3 -3
- package/dist/worker.js.map +1 -1
- package/package.json +2 -2
package/dist/index.d.cts
CHANGED
|
@@ -24,6 +24,16 @@ interface RunInSandboxInput {
|
|
|
24
24
|
files?: PlaygroundFile[];
|
|
25
25
|
/** Wall-clock timeout in milliseconds. Defaults to 5000. Clamped to [100, 10000]. */
|
|
26
26
|
timeoutMs?: number;
|
|
27
|
+
/**
|
|
28
|
+
* Optional cancellation signal. Wire this to your HTTP request's
|
|
29
|
+
* AbortSignal (Next.js / Express both expose one) so a client that
|
|
30
|
+
* disconnects mid-flight releases its worker slot immediately
|
|
31
|
+
* instead of leaking it. Without a signal, an abandoned `runInSandbox`
|
|
32
|
+
* call still queues into the per-process worker cap and only frees
|
|
33
|
+
* when the worker times out — under load this drives the cap to
|
|
34
|
+
* permanent deadlock.
|
|
35
|
+
*/
|
|
36
|
+
signal?: AbortSignal;
|
|
27
37
|
}
|
|
28
38
|
interface SandboxResult {
|
|
29
39
|
/**
|
|
@@ -41,7 +51,7 @@ interface SandboxResult {
|
|
|
41
51
|
* Final `system.derive` snapshot — every derivation declared in the
|
|
42
52
|
* module config, evaluated by reading `system.derive[key]`. Empty
|
|
43
53
|
* when the module has no `derive:` block or when validation rejected
|
|
44
|
-
* before bundle. The
|
|
54
|
+
* before bundle. The June 2026 security audit flagged the original
|
|
45
55
|
* sandbox for snapshotting only facts; modules whose primary product
|
|
46
56
|
* is a derivation (`status`, `isReady`, etc.) returned an empty-
|
|
47
57
|
* looking transcript.
|
|
@@ -95,6 +105,39 @@ interface ValidationError {
|
|
|
95
105
|
message: string;
|
|
96
106
|
}
|
|
97
107
|
|
|
108
|
+
/**
|
|
109
|
+
* Host-side worker_threads orchestration. Mirrors the lint-runner
|
|
110
|
+
* pattern in `@directive-run/mcp`: spawn a fresh worker per call,
|
|
111
|
+
* race the response against a wall-clock timer, terminate on overrun.
|
|
112
|
+
*
|
|
113
|
+
* Workers are NOT pooled. Each call gets a clean process state — no
|
|
114
|
+
* carry-over globals between snippets, no shared `console` patches,
|
|
115
|
+
* no leaked timers from a prior run. Cold-start is ~5ms which is
|
|
116
|
+
* cheap relative to the 50-200ms a typical Directive demo actually
|
|
117
|
+
* spends in `system.settle()`.
|
|
118
|
+
*/
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Override the per-process worker cap. Pass `Infinity` to disable.
|
|
122
|
+
* Returns the previous value.
|
|
123
|
+
*
|
|
124
|
+
* Lowering the cap below `activeWorkers` does NOT terminate running
|
|
125
|
+
* workers — the new ceiling applies as those workers drain. New
|
|
126
|
+
* `acquireSlot()` callers queue until `activeWorkers` falls below
|
|
127
|
+
* the new cap. Raising the cap immediately drains any waiters the
|
|
128
|
+
* new ceiling can absorb.
|
|
129
|
+
*
|
|
130
|
+
* @example Cap the worker pool at boot for a Next.js API route
|
|
131
|
+
* ```ts
|
|
132
|
+
* // app/api/sandbox/route.ts — runs once per cold start
|
|
133
|
+
* import { setMaxConcurrentWorkers } from "@directive-run/sandbox";
|
|
134
|
+
* setMaxConcurrentWorkers(8);
|
|
135
|
+
* ```
|
|
136
|
+
*/
|
|
137
|
+
declare function setMaxConcurrentWorkers(value: number): number;
|
|
138
|
+
|
|
139
|
+
declare function sanitizeStack(s: string | undefined): string;
|
|
140
|
+
|
|
98
141
|
/**
|
|
99
142
|
* Public API for `@directive-run/sandbox`.
|
|
100
143
|
*
|
|
@@ -114,4 +157,4 @@ interface ValidationError {
|
|
|
114
157
|
|
|
115
158
|
declare function runInSandbox(input: RunInSandboxInput): Promise<SandboxResult>;
|
|
116
159
|
|
|
117
|
-
export { type PlaygroundFile, type RunInSandboxInput, SandboxError, type SandboxResult, type ValidationError, runInSandbox };
|
|
160
|
+
export { type PlaygroundFile, type RunInSandboxInput, SandboxError, type SandboxResult, type ValidationError, runInSandbox, sanitizeStack, setMaxConcurrentWorkers };
|
package/dist/index.d.ts
CHANGED
|
@@ -24,6 +24,16 @@ interface RunInSandboxInput {
|
|
|
24
24
|
files?: PlaygroundFile[];
|
|
25
25
|
/** Wall-clock timeout in milliseconds. Defaults to 5000. Clamped to [100, 10000]. */
|
|
26
26
|
timeoutMs?: number;
|
|
27
|
+
/**
|
|
28
|
+
* Optional cancellation signal. Wire this to your HTTP request's
|
|
29
|
+
* AbortSignal (Next.js / Express both expose one) so a client that
|
|
30
|
+
* disconnects mid-flight releases its worker slot immediately
|
|
31
|
+
* instead of leaking it. Without a signal, an abandoned `runInSandbox`
|
|
32
|
+
* call still queues into the per-process worker cap and only frees
|
|
33
|
+
* when the worker times out — under load this drives the cap to
|
|
34
|
+
* permanent deadlock.
|
|
35
|
+
*/
|
|
36
|
+
signal?: AbortSignal;
|
|
27
37
|
}
|
|
28
38
|
interface SandboxResult {
|
|
29
39
|
/**
|
|
@@ -41,7 +51,7 @@ interface SandboxResult {
|
|
|
41
51
|
* Final `system.derive` snapshot — every derivation declared in the
|
|
42
52
|
* module config, evaluated by reading `system.derive[key]`. Empty
|
|
43
53
|
* when the module has no `derive:` block or when validation rejected
|
|
44
|
-
* before bundle. The
|
|
54
|
+
* before bundle. The June 2026 security audit flagged the original
|
|
45
55
|
* sandbox for snapshotting only facts; modules whose primary product
|
|
46
56
|
* is a derivation (`status`, `isReady`, etc.) returned an empty-
|
|
47
57
|
* looking transcript.
|
|
@@ -95,6 +105,39 @@ interface ValidationError {
|
|
|
95
105
|
message: string;
|
|
96
106
|
}
|
|
97
107
|
|
|
108
|
+
/**
|
|
109
|
+
* Host-side worker_threads orchestration. Mirrors the lint-runner
|
|
110
|
+
* pattern in `@directive-run/mcp`: spawn a fresh worker per call,
|
|
111
|
+
* race the response against a wall-clock timer, terminate on overrun.
|
|
112
|
+
*
|
|
113
|
+
* Workers are NOT pooled. Each call gets a clean process state — no
|
|
114
|
+
* carry-over globals between snippets, no shared `console` patches,
|
|
115
|
+
* no leaked timers from a prior run. Cold-start is ~5ms which is
|
|
116
|
+
* cheap relative to the 50-200ms a typical Directive demo actually
|
|
117
|
+
* spends in `system.settle()`.
|
|
118
|
+
*/
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Override the per-process worker cap. Pass `Infinity` to disable.
|
|
122
|
+
* Returns the previous value.
|
|
123
|
+
*
|
|
124
|
+
* Lowering the cap below `activeWorkers` does NOT terminate running
|
|
125
|
+
* workers — the new ceiling applies as those workers drain. New
|
|
126
|
+
* `acquireSlot()` callers queue until `activeWorkers` falls below
|
|
127
|
+
* the new cap. Raising the cap immediately drains any waiters the
|
|
128
|
+
* new ceiling can absorb.
|
|
129
|
+
*
|
|
130
|
+
* @example Cap the worker pool at boot for a Next.js API route
|
|
131
|
+
* ```ts
|
|
132
|
+
* // app/api/sandbox/route.ts — runs once per cold start
|
|
133
|
+
* import { setMaxConcurrentWorkers } from "@directive-run/sandbox";
|
|
134
|
+
* setMaxConcurrentWorkers(8);
|
|
135
|
+
* ```
|
|
136
|
+
*/
|
|
137
|
+
declare function setMaxConcurrentWorkers(value: number): number;
|
|
138
|
+
|
|
139
|
+
declare function sanitizeStack(s: string | undefined): string;
|
|
140
|
+
|
|
98
141
|
/**
|
|
99
142
|
* Public API for `@directive-run/sandbox`.
|
|
100
143
|
*
|
|
@@ -114,4 +157,4 @@ interface ValidationError {
|
|
|
114
157
|
|
|
115
158
|
declare function runInSandbox(input: RunInSandboxInput): Promise<SandboxResult>;
|
|
116
159
|
|
|
117
|
-
export { type PlaygroundFile, type RunInSandboxInput, SandboxError, type SandboxResult, type ValidationError, runInSandbox };
|
|
160
|
+
export { type PlaygroundFile, type RunInSandboxInput, SandboxError, type SandboxResult, type ValidationError, runInSandbox, sanitizeStack, setMaxConcurrentWorkers };
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import{createRequire as
|
|
1
|
+
import{createRequire as G}from"module";import{pathToFileURL as H}from"url";import{build as X}from"esbuild";function Y(e){try{let o=G(import.meta.url).resolve(e);return H(o).href}catch{return null}}var E="src/main.ts",v="directive-sandbox-vfs",g=class extends Error{constructor(o,r){super(o);this.cause=r;this.name="BundleError"}};function J(e){let t=/(var\s+(system\d*)\s*=\s*createSystem\s*\([\s\S]*?\)\s*;)/,o=e.match(t);if(!o)return e;let r=o[1],n=`
|
|
2
2
|
(globalThis).__directiveSandbox_system__ = ${o[2]};
|
|
3
|
-
`;return
|
|
4
|
-
`);return{contents:a+
|
|
5
|
-
`)&&
|
|
3
|
+
`;return e.replace(r,r+n)}async function M(e){if(!e.find(r=>r.path===E))throw new g(`payload must include "${E}" \u2014 that's the entry point the runner targets`);let o=new Map;for(let r of e)o.set(r.path,r.source);try{let i=(await X({entryPoints:[`${v}:${E}`],bundle:!0,format:"esm",target:"node20",platform:"node",write:!1,logLevel:"silent",external:["@directive-run/*"],supported:{"top-level-await":!0},plugins:[{name:"directive-sandbox-vfs",setup(c){c.onResolve({filter:/.*/},s=>{if(s.kind==="entry-point")return{path:s.path.replace(`${v}:`,""),namespace:v};if(s.namespace!==v)return null;if(s.path.startsWith("@directive-run/")){let a=Y(s.path);return a?{external:!0,path:a}:{external:!0,path:s.path}}if(s.path.startsWith("./")||s.path.startsWith("../")){let a=s.importer.replace(/\/[^/]+$/,""),l=s.path.replace(/^\.\//,"").replace(/\.js$/,""),f=[`${a}/${l}.ts`,`${a}/${l}.js`,`${a}/${l}`,`${l}.ts`,`${l}.js`].map(d=>d.replace(/\/+/g,"/"));for(let d of f)if(o.has(d))return{path:d,namespace:v};throw new g(`cannot resolve "${s.path}" from "${s.importer}" \u2014 tried ${f.join(", ")}`)}throw new g(`unexpected import "${s.path}" from "${s.importer}" \u2014 only relative or @directive-run/* allowed`)}),c.onLoad({filter:/.*/,namespace:v},s=>{let a=o.get(s.path);if(a===void 0)throw new g(`virtual file missing: ${s.path}`);if(s.path===E){let l=["","// directive-sandbox: lift the runner's `system` binding","// onto a side-channel global so the worker can read","// system.facts.$store.toObject() after execution.","if (typeof system !== 'undefined') {"," (globalThis).__directiveSandbox_system__ = system;","}"].join(`
|
|
4
|
+
`);return{contents:a+l,loader:"ts"}}return{contents:a,loader:"ts"}})}}]})).outputFiles[0]?.text;if(!i)throw new g("esbuild produced no output");let n=J(i);return{source:n,bytes:Buffer.byteLength(n,"utf8")}}catch(r){throw r instanceof g?r:new g(`bundle failed: ${r.message??String(r)}`,r)}}import{existsSync as N,mkdtempSync as Z,rmSync as Q,writeFileSync as ee}from"fs";import{tmpdir as te}from"os";import{dirname as I,join as A}from"path";import{fileURLToPath as re,pathToFileURL as ne}from"url";import{Worker as oe}from"worker_threads";var se=100,ie=1e4,R=5e3,ae=Math.max(1,globalThis.navigator?.hardwareConcurrency??4),S=ae,y=0,T=[];function _(){for(;T.length>0&&y<S;){let e=T.shift();if(!(!e||e.aborted)){y++,e.resolve();return}}}function ce(e){let t=S;if(!Number.isFinite(e)&&e!==Number.POSITIVE_INFINITY)return t;for(S=Math.max(1,Math.floor(e));T.length>0&&y<S;)_();return t}function le(e){return e?.aborted?Promise.reject(e.reason instanceof Error?e.reason:new Error("sandbox: acquireSlot aborted")):y<S?(y++,Promise.resolve()):new Promise((t,o)=>{let r={resolve:t,reject:o,aborted:!1};if(T.push(r),e){let i=()=>{r.aborted=!0,o(e.reason instanceof Error?e.reason:new Error("sandbox: acquireSlot aborted"))};e.addEventListener("abort",i,{once:!0});let n=r.resolve,c=r.reject;r.resolve=()=>{e.removeEventListener("abort",i),n()},r.reject=s=>{e.removeEventListener("abort",i),c(s)}}})}function F(){y=Math.max(0,y-1),y<S&&_()}async function D(){try{let o=new URL("./worker.js",import.meta.url),r=re(o);if(N(r))return r}catch{}let{createRequire:e}=await import("module");return e(import.meta.url).resolve("@directive-run/sandbox/worker")}var x=class extends Error{constructor(o,r){super(o);this.code=r;this.name="WorkerExecError"}};function ue(e){let t=e??R;return Number.isFinite(t)?Math.min(ie,Math.max(se,Math.floor(t))):R}async function de(){let e=te();if(N(e))return e;let t=await D();return I(I(t))}async function pe(e){let t=await de(),o=Z(A(t,"directive-sandbox-")),r=A(o,"bundle.mjs");return ee(r,e,"utf8"),{bundlePath:r,cleanup:()=>{try{Q(o,{recursive:!0,force:!0})}catch{}}}}async function L(e){let t=ue(e.timeoutMs);await le(e.signal);let o,r,i;try{o=await D(),{bundlePath:r,cleanup:i}=await pe(e.bundledSource)}catch(d){throw F(),d}let n=new oe(o,{resourceLimits:{maxOldGenerationSizeMb:32,maxYoungGenerationSizeMb:8,codeRangeSizeMb:16},stderr:!1}),c=null,s=!1,a=!1,l=null,f=Date.now();try{return await new Promise((m,w)=>{let h=!1;n.once("message",b=>{h=!0,b.ok?m(b.result):w(new x(b.error,"worker-error"))}),n.once("error",b=>{h=!0,w(new x(b.message,"worker-error"))}),n.once("exit",b=>{!h&&b!==0&&b!==null&&w(new x(`worker exited with code ${b} before responding`,"worker-error"))}),c=setTimeout(()=>{s=!0,n.terminate(),w(new x(`wall-clock budget of ${t}ms elapsed`,"timeout"))},t),e.signal&&(l=()=>{h||(h=!0,a=!0,n.terminate(),w(new x("sandbox: aborted by caller signal","worker-error")))},e.signal.aborted?l():e.signal.addEventListener("abort",l,{once:!0}));let $={bundlePath:ne(r).href,timeoutMs:t,derivationKeys:e.derivationKeys};n.postMessage($)})}catch(d){if(d instanceof x&&d.code==="timeout")return{logs:[],facts:{},derived:{},errors:[d.message],durationMs:Date.now()-f,timedOut:!0};throw d}finally{c&&clearTimeout(c),l&&e.signal&&e.signal.removeEventListener("abort",l),await n.terminate().catch(()=>{}),i(),F()}}function fe(e,t){let o=0;for(let r=t;r<e.length;r++){let i=e[r];if(i==="{")o+=1;else if(i==="}"&&(o-=1,o===0))return r}return-1}function me(e){let t=[],o=0,r=0,i=0,n=0,c=s=>{let a=e.slice(o,s).trim();if(o=s+1,!a)return;let l=a.match(/^['"]?(\w+)['"]?\s*:/);l&&t.push(l[1])};for(let s=0;s<e.length;s++){let a=e[s];a==="{"?r+=1:a==="}"?r-=1:a==="("?i+=1:a===")"?i-=1:a==="["?n+=1:a==="]"?n-=1:(a===","||a===`
|
|
5
|
+
`)&&r===0&&i===0&&n===0&&c(s)}return c(e.length),t}function O(e,t){let o=new RegExp(`\\b${t}\\s*:\\s*\\{`),r=e.match(o);if(!r||r.index===void 0)return[];let i=e.indexOf("{",r.index);if(i===-1)return[];let n=fe(e,i);return n===-1?[]:me(e.slice(i+1,n))}function W(e){let t=new Set,o=[];for(let r of e){for(let i of O(r.source,"derive"))t.has(i)||(t.add(i),o.push(i));for(let i of O(r.source,"derivations"))t.has(i)||(t.add(i),o.push(i))}return o}var p=class extends Error{constructor(o,r){super(o);this.code=r;this.name="SandboxError"}};import{Project as ge,SyntaxKind as u}from"ts-morph";var j=new Set(["core","ai","query","el","react","vue","svelte","solid","lit","optimistic","timeline","mutator","knowledge","scaffold","claude-plugin","lint","sources"]),C=new Set(["cli","mcp","sandbox","vite-plugin-api-proxy"]);function K(e){let t=e.match(/^@directive-run\/([^/]+)/);return t?t[1]:null}function he(e){if(/^\.{1,2}\/.+\.js$/.test(e))return!0;let t=K(e);return t===null||C.has(t)?!1:j.has(t)}var B=new Set(["createSystem","system","console","Math","JSON","Object","Array","Number","String","Boolean","Symbol","Promise","Error","Date","Map","Set","WeakMap","WeakSet","Reflect","globalThis","undefined","null","NaN","Infinity"]),k=new Set(["process","require","module","__dirname","__filename","fetch","XMLHttpRequest","WebSocket","eval","Function","Buffer","setImmediate","queueMicrotask","setTimeout","setInterval","clearTimeout","clearInterval"]);function xe(e){let t=K(e);return t&&C.has(t)?`import "${e}" is denied \u2014 @directive-run/${t} is a build/CLI/sandbox tool, not for use inside a sandboxed demo`:`import "${e}" is not allowed in the sandbox. Allowed: relative "./X.js" paths or any of @directive-run/{${Array.from(j).sort().join(",")}}.`}function we(e,t,o){let r=t.getSourceFileOrThrow(e);for(let i of r.getImportDeclarations()){let n=i.getModuleSpecifierValue();if(!he(n)){let{line:c,column:s}=r.getLineAndColumnAtPos(i.getStart());o.push({path:e,line:c,column:s,message:xe(n)})}}}function be(e,t,o){let r=t.getSourceFileOrThrow(e);r.forEachDescendant(i=>{if(i.getKind()===u.ImportKeyword){let n=i.getParent();if(n&&n.getKind()===u.CallExpression){let{line:c,column:s}=r.getLineAndColumnAtPos(i.getStart());o.push({path:e,line:c,column:s,message:"dynamic import() is not allowed in the sandbox"})}}if(i.getKind()===u.NewExpression){let n=i.getText();if(/^new\s+Function\s*\(/.test(n)){let{line:c,column:s}=r.getLineAndColumnAtPos(i.getStart());o.push({path:e,line:c,column:s,message:"new Function(...) is not allowed in the sandbox"})}}})}function ye(e,t,o){let r=t.getSourceFileOrThrow(e),i=(c,s)=>{let{line:a,column:l}=r.getLineAndColumnAtPos(c.getStart());o.push({path:e,line:a,column:l,message:s})},n=c=>{let s=c.trim();return s.startsWith('"')&&s.endsWith('"')||s.startsWith("'")&&s.endsWith("'")||s.startsWith("`")&&s.endsWith("`")?s.slice(1,-1):null};r.forEachDescendant(c=>{let s=c.getKind();if(s===u.PropertyAccessExpression){let a=c.getName?.();if(!a)return;if(a==="constructor"){i(c,"`.constructor` access is denied in the sandbox (Function-constructor smuggle vector)");return}if(k.has(a)){i(c,`\`.${a}\` access is denied in the sandbox (FS/network/eval surface) \u2014 accessing a denied global via property syntax was the property-access bypass closed in v0.3.0`);return}}if(s===u.ElementAccessExpression){let a=c.getExpression?.(),l=c.getArgumentExpression?.(),f=a?.getText()??"",d=l?.getText()??"",m=n(d);if(f==="globalThis"&&m!==null){i(c,"bracket-access on `globalThis` with a string literal is denied in the sandbox (use direct identifier reference for allowlisted names)");return}if(m!==null&&(m==="constructor"||k.has(m))){i(c,`bracket-access \`["${m}"]\` is denied in the sandbox (would reach a denied name)`);return}}if(s===u.CallExpression){let l=c.getExpression?.()?.getText()??"";if(l==="Function"){i(c,"`Function(...)` call is denied in the sandbox");return}let f=l.match(/^(Reflect|Object)\.(\w+)$/);if(f){let m=c.getArguments?.()??[];if(m.length>=2){let w=m[0].getText(),h=n(m[1].getText());new Set(["get","has","getOwnPropertyDescriptor","getOwnPropertyDescriptors","ownKeys","getPrototypeOf"]).has(f[2])&&(w==="globalThis"||B.has(w))&&h!==null&&(h==="constructor"||k.has(h))&&i(c,`\`${f[1]}.${f[2]}(${w}, "${h}")\` would reach a denied name`)}}}})}function ve(e,t,o){let r=t.getSourceFileOrThrow(e),i=new Set;for(let n of r.getImportDeclarations()){for(let a of n.getNamedImports())i.add(a.getName());let c=n.getDefaultImport();c&&i.add(c.getText());let s=n.getNamespaceImport();s&&i.add(s.getText())}for(let n of r.getVariableDeclarations())i.add(n.getName());for(let n of r.getFunctions()){let c=n.getName();c&&i.add(c)}for(let n of r.getClasses()){let c=n.getName();c&&i.add(c)}r.forEachDescendant(n=>{if(n.getKind()!==u.Identifier)return;let c=n.getText();if(i.has(c)||B.has(c))return;let s=n.getParent();if(s){let a=s.getKind();if(a===u.PropertyAssignment&&s.getNameNode?.()===n||a===u.PropertyAccessExpression&&s.getNameNode?.()===n||a===u.MethodDeclaration||a===u.ImportSpecifier||a===u.ExportSpecifier||a===u.NamespaceImport||a===u.ImportClause||a===u.Parameter||a===u.TypeReference||a===u.TypeQuery)return}if(k.has(c)){let{line:a,column:l}=r.getLineAndColumnAtPos(n.getStart());o.push({path:e,line:a,column:l,message:`identifier "${c}" is denied in the sandbox (FS/network/eval surface)`})}})}function U(e){let t=[],o=new ge({useInMemoryFileSystem:!0,compilerOptions:{target:99,module:99,allowJs:!0,strict:!1}});for(let r of e)o.createSourceFile(r.path,r.source,{overwrite:!0});for(let r of e)we(r.path,o,t),be(r.path,o,t),ye(r.path,o,t),ve(r.path,o,t);return t}var V=`[^\\s)\\]>"',]`;function Se(e){if(!e)return"";let t=`${V}+`;return e.replace(new RegExp(`file:\\/\\/\\/${V}+`,"g"),"<sandbox>").replace(new RegExp(`\\\\\\\\${t}`,"g"),"<unc>").replace(/[A-Za-z]:\\Users\\[^\\\s)\]>"',]+/g,"<home>").replace(/[A-Za-z]:\\Documents and Settings\\[^\\\s)\]>"',]+/g,"<home>").replace(/[A-Za-z]:\\[^\\\s)\]>"',]+(?:\\[^\\\s)\]>"',]+)+/g,"<path>").replace(new RegExp(`\\/Users\\/${t}`,"g"),"/<home>").replace(new RegExp(`\\/home\\/${t}`,"g"),"/<home>").replace(new RegExp(`\\/private\\/var\\/${t}`,"g"),"<tmp>").replace(new RegExp(`\\/var\\/task\\/${t}`,"g"),"<task>").replace(new RegExp(`\\/tmp\\/${t}`,"g"),"<tmp>").replace(new RegExp(`\\/opt\\/${t}`,"g"),"<opt>").replace(new RegExp(`\\/usr\\/local\\/${t}`,"g"),"<usr-local>").replace(new RegExp(`\\/app\\/${t}`,"g"),"<app>").replace(new RegExp(`\\/srv\\/${t}`,"g"),"<srv>").replace(new RegExp(`\\/workspace\\/${t}`,"g"),"<workspace>").replace(new RegExp(`\\/data\\/${t}`,"g"),"<data>").replace(new RegExp(`\\/etc\\/${t}`,"g"),"<etc>").replace(new RegExp(`\\/root\\/${t}`,"g"),"<root>")}var q=2e5,z=10,P="src/main.ts";function Ee(e){if(e.files&&e.source)throw new p("pass either `source` or `files`, not both","input-invalid");if(!e.files&&!e.source)throw new p("must pass either `source` or `files`","input-invalid");let t=e.files?e.files:[{path:P,source:e.source??""}];if(t.length===0)throw new p("files array is empty","input-invalid");if(t.length>z)throw new p(`payload exceeds ${z} files`,"input-invalid");let o=0;for(let r of t){if(typeof r.path!="string"||r.path.length===0)throw new p("every file must have a non-empty path","input-invalid");if(typeof r.source!="string"||r.source.length===0)throw new p(`file "${r.path}" has empty source`,"input-invalid");o+=Buffer.byteLength(r.source,"utf8")}if(o>q)throw new p(`total payload is ${o} bytes (max ${q})`,"input-invalid");if(!t.some(r=>r.path===P))throw new p(`payload must include "${P}" \u2014 the runner entry point`,"input-invalid");return t}async function Ve(e){let t;try{t=Ee(e)}catch(n){if(n instanceof p)return{logs:[],facts:{},derived:{},errors:[n.message],durationMs:0,timedOut:!1};throw n}let o=U(t);if(o.length>0)return{logs:[],facts:{},derived:{},errors:o.map(n=>`${n.path}:${n.line}:${n.column} \u2014 ${n.message}`),durationMs:0,timedOut:!1};let r=W(t),i;try{i=await M(t)}catch(n){if(n instanceof g)return{logs:[],facts:{},derived:{},errors:[n.message],durationMs:0,timedOut:!1};throw n}try{return await L({bundledSource:i.source,derivationKeys:r,timeoutMs:e.timeoutMs,signal:e.signal})}catch(n){if(n instanceof x)return{logs:[],facts:{},derived:{},errors:[n.message],durationMs:0,timedOut:n.code==="timeout"};throw n}}export{p as SandboxError,Ve as runInSandbox,Se as sanitizeStack,ce as setMaxConcurrentWorkers};
|
|
6
6
|
//# sourceMappingURL=index.js.map
|