@opencode-ai/util 0.0.0-bootstrap.0 → 0.0.0-next-15994

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 (50) hide show
  1. package/dist/cross-spawn-spawner.d.ts +3 -0
  2. package/dist/cross-spawn-spawner.js +403 -0
  3. package/dist/effect/app-node-platform.d.ts +6 -0
  4. package/dist/effect/app-node-platform.js +8 -0
  5. package/dist/effect/app-node.d.ts +50 -0
  6. package/dist/effect/app-node.js +8 -0
  7. package/dist/effect/layer-node.d.ts +79 -0
  8. package/dist/effect/layer-node.js +181 -0
  9. package/dist/effect/memo-map.d.ts +2 -0
  10. package/dist/effect/memo-map.js +2 -0
  11. package/dist/effect/runtime.d.ts +8 -0
  12. package/dist/effect/runtime.js +16 -0
  13. package/dist/effect/service-use.d.ts +7 -0
  14. package/dist/effect/service-use.js +27 -0
  15. package/dist/effect-flock.d.ts +31 -0
  16. package/dist/effect-flock.js +185 -0
  17. package/dist/flock.d.ts +30 -0
  18. package/dist/flock.js +273 -0
  19. package/dist/fs-util.d.ts +139 -0
  20. package/dist/fs-util.js +224 -0
  21. package/dist/glob.d.ts +12 -0
  22. package/dist/glob.js +26 -0
  23. package/dist/global.d.ts +30 -0
  24. package/dist/global.js +57 -0
  25. package/dist/hash.d.ts +4 -0
  26. package/dist/hash.js +12 -0
  27. package/dist/npm-config.d.ts +4 -0
  28. package/dist/npm-config.js +32 -0
  29. package/dist/npm.d.ts +35 -0
  30. package/dist/npm.js +207 -0
  31. package/dist/observability/logging.d.ts +6 -0
  32. package/dist/observability/logging.js +67 -0
  33. package/dist/observability/otlp.d.ts +18 -0
  34. package/dist/observability/otlp.js +73 -0
  35. package/dist/observability/shared.d.ts +1 -0
  36. package/dist/observability/shared.js +1 -0
  37. package/dist/observability.d.ts +13 -0
  38. package/dist/observability.js +31 -0
  39. package/dist/patch.d.ts +42 -0
  40. package/dist/patch.js +206 -0
  41. package/dist/process.d.ts +54 -0
  42. package/dist/process.js +162 -0
  43. package/dist/runtime/import.bun.d.ts +2 -0
  44. package/dist/runtime/import.bun.js +6 -0
  45. package/dist/runtime/import.node.d.ts +2 -0
  46. package/dist/runtime/import.node.js +36 -0
  47. package/dist/runtime-import.d.ts +1 -0
  48. package/dist/runtime-import.js +1 -0
  49. package/package.json +56 -7
  50. package/index.js +0 -1
package/dist/patch.js ADDED
@@ -0,0 +1,206 @@
1
+ export * as Patch from "./patch.js";
2
+ import { Result, Schema } from "effect";
3
+ export class BoundaryError extends Schema.TaggedErrorClass()("Patch.BoundaryError", {
4
+ boundary: Schema.Literals(["first", "last"]),
5
+ }) {
6
+ get message() {
7
+ return `The ${this.boundary} line of the patch must be '${this.boundary === "first" ? "*** Begin Patch" : "*** End Patch"}'`;
8
+ }
9
+ }
10
+ export class InvalidHunkError extends Schema.TaggedErrorClass()("Patch.InvalidHunkError", {
11
+ line: Schema.String,
12
+ lineNumber: Schema.Number,
13
+ }) {
14
+ get message() {
15
+ return `Invalid hunk at line ${this.lineNumber}: '${this.line}' is not a valid hunk header. Valid hunk headers: '*** Add File: {path}', '*** Delete File: {path}', '*** Update File: {path}'`;
16
+ }
17
+ }
18
+ export function parse(patchText) {
19
+ const lines = stripHeredoc(patchText.trim())
20
+ .split("\n")
21
+ .map((line) => (line.endsWith("\r") ? line.slice(0, -1) : line));
22
+ const begin = lines[0]?.trim() === "*** Begin Patch" ? 0 : -1;
23
+ const end = lines.at(-1)?.trim() === "*** End Patch" ? lines.length - 1 : -1;
24
+ if (begin === -1)
25
+ return Result.fail(new BoundaryError({ boundary: "first" }));
26
+ if (end === -1 || begin >= end)
27
+ return Result.fail(new BoundaryError({ boundary: "last" }));
28
+ const hunks = [];
29
+ let index = begin + 1;
30
+ while (index < end) {
31
+ const line = lines[index];
32
+ const header = line.trim();
33
+ if (header.startsWith("*** Add File:")) {
34
+ const path = header.slice("*** Add File:".length).trim();
35
+ if (!path) {
36
+ index++;
37
+ continue;
38
+ }
39
+ const parsed = parseAdd(lines, index + 1, end);
40
+ hunks.push({ type: "add", path, contents: parsed.content });
41
+ index = parsed.next;
42
+ continue;
43
+ }
44
+ if (header.startsWith("*** Delete File:")) {
45
+ const path = header.slice("*** Delete File:".length).trim();
46
+ if (!path) {
47
+ index++;
48
+ continue;
49
+ }
50
+ hunks.push({ type: "delete", path });
51
+ index++;
52
+ continue;
53
+ }
54
+ if (header.startsWith("*** Update File:")) {
55
+ const path = header.slice("*** Update File:".length).trim();
56
+ if (!path) {
57
+ index++;
58
+ continue;
59
+ }
60
+ let next = index + 1;
61
+ let movePath;
62
+ if (lines[next]?.startsWith("*** Move to:")) {
63
+ movePath = lines[next].slice("*** Move to:".length).trim();
64
+ next++;
65
+ }
66
+ const parsed = parseUpdate(lines, next, end);
67
+ hunks.push({ type: "update", path, movePath, chunks: parsed.chunks });
68
+ index = parsed.next;
69
+ continue;
70
+ }
71
+ index++;
72
+ }
73
+ if (hunks.length === 0) {
74
+ const invalid = lines.findIndex((line, index) => index > begin && index < end && line.trim() !== "");
75
+ if (invalid !== -1) {
76
+ return Result.fail(new InvalidHunkError({ line: lines[invalid].trim(), lineNumber: invalid + 1 }));
77
+ }
78
+ }
79
+ return Result.succeed(hunks);
80
+ }
81
+ export function derive(path, chunks, original) {
82
+ const source = splitBom(original);
83
+ const lines = source.text.split("\n");
84
+ if (lines.at(-1) === "")
85
+ lines.pop();
86
+ const replacements = computeReplacements(lines, path, chunks);
87
+ const updated = [...lines];
88
+ for (const [start, remove, insert] of replacements.toReversed())
89
+ updated.splice(start, remove, ...insert);
90
+ if (updated.at(-1) !== "")
91
+ updated.push("");
92
+ const next = splitBom(updated.join("\n"));
93
+ return { content: next.text, bom: source.bom || next.bom };
94
+ }
95
+ export function joinBom(text, bom) {
96
+ const stripped = splitBom(text).text;
97
+ return bom ? `\uFEFF${stripped}` : stripped;
98
+ }
99
+ function parseAdd(lines, start, end) {
100
+ const content = [];
101
+ let index = start;
102
+ while (index < end && !lines[index].startsWith("***")) {
103
+ if (lines[index].startsWith("+"))
104
+ content.push(lines[index].slice(1));
105
+ index++;
106
+ }
107
+ return { content: content.join("\n"), next: index };
108
+ }
109
+ function parseUpdate(lines, start, end) {
110
+ const chunks = [];
111
+ let index = start;
112
+ while (index < end && !lines[index].startsWith("***")) {
113
+ if (!lines[index].startsWith("@@")) {
114
+ index++;
115
+ continue;
116
+ }
117
+ const changeContext = lines[index].slice(2).trim() || undefined;
118
+ const oldLines = [];
119
+ const newLines = [];
120
+ let endOfFile = false;
121
+ index++;
122
+ while (index < end && !lines[index].startsWith("@@") && !lines[index].startsWith("***")) {
123
+ const line = lines[index];
124
+ if (line.startsWith(" ")) {
125
+ oldLines.push(line.slice(1));
126
+ newLines.push(line.slice(1));
127
+ }
128
+ else if (line.startsWith("-"))
129
+ oldLines.push(line.slice(1));
130
+ else if (line.startsWith("+"))
131
+ newLines.push(line.slice(1));
132
+ index++;
133
+ }
134
+ if (lines[index]?.trim() === "*** End of File") {
135
+ endOfFile = true;
136
+ index++;
137
+ }
138
+ chunks.push({ oldLines, newLines, changeContext, endOfFile: endOfFile || undefined });
139
+ }
140
+ return { chunks, next: index };
141
+ }
142
+ function computeReplacements(lines, path, chunks) {
143
+ const replacements = [];
144
+ let lineIndex = 0;
145
+ for (const chunk of chunks) {
146
+ if (chunk.changeContext) {
147
+ const context = seek(lines, [chunk.changeContext], lineIndex);
148
+ if (context === -1)
149
+ throw new Error(`Failed to find context '${chunk.changeContext}' in ${path}`);
150
+ lineIndex = context + 1;
151
+ }
152
+ if (chunk.oldLines.length === 0) {
153
+ replacements.push([lines.length, 0, chunk.newLines]);
154
+ continue;
155
+ }
156
+ let oldLines = chunk.oldLines;
157
+ let newLines = chunk.newLines;
158
+ let found = seek(lines, oldLines, lineIndex, chunk.endOfFile);
159
+ if (found === -1 && oldLines.at(-1) === "") {
160
+ oldLines = oldLines.slice(0, -1);
161
+ if (newLines.at(-1) === "")
162
+ newLines = newLines.slice(0, -1);
163
+ found = seek(lines, oldLines, lineIndex, chunk.endOfFile);
164
+ }
165
+ if (found === -1)
166
+ throw new Error(`Failed to find expected lines in ${path}:\n${chunk.oldLines.join("\n")}`);
167
+ replacements.push([found, oldLines.length, newLines]);
168
+ lineIndex = found + oldLines.length;
169
+ }
170
+ return replacements.toSorted((left, right) => left[0] - right[0]);
171
+ }
172
+ function seek(lines, pattern, start, eof = false) {
173
+ if (pattern.length === 0)
174
+ return -1;
175
+ if (eof) {
176
+ const offset = lines.length - pattern.length;
177
+ if (offset < start)
178
+ return -1;
179
+ for (const compare of [exact, rstrip, trim, normalized]) {
180
+ if (matches(lines, pattern, offset, compare))
181
+ return offset;
182
+ }
183
+ return -1;
184
+ }
185
+ for (const compare of [exact, rstrip, trim, normalized]) {
186
+ for (let offset = start; offset <= lines.length - pattern.length; offset++) {
187
+ if (matches(lines, pattern, offset, compare))
188
+ return offset;
189
+ }
190
+ }
191
+ return -1;
192
+ }
193
+ function matches(lines, pattern, offset, compare) {
194
+ return pattern.every((line, index) => compare(lines[offset + index], line));
195
+ }
196
+ const exact = (left, right) => left === right;
197
+ const rstrip = (left, right) => left.trimEnd() === right.trimEnd();
198
+ const trim = (left, right) => left.trim() === right.trim();
199
+ const normalized = (left, right) => normalize(left.trim()) === normalize(right.trim());
200
+ const normalize = (value) => value
201
+ .replace(/[‘’‚‛]/g, "'")
202
+ .replace(/[“”„‟]/g, '"')
203
+ .replace(/[‐‑‒–—―−]/g, "-")
204
+ .replace(/[\u00A0\u2002-\u200A\u202F\u205F\u3000]/g, " ");
205
+ const splitBom = (text) => text.startsWith("\uFEFF") ? { bom: true, text: text.slice(1) } : { bom: false, text };
206
+ const stripHeredoc = (input) => input.match(/^(?:cat\s+)?<<['"]?(\w+)['"]?\s*\n([\s\S]*?)\n\1\s*$/)?.[2] ?? input;
@@ -0,0 +1,54 @@
1
+ import { Context, Duration, Effect, Schema, Stream } from "effect";
2
+ import type { PlatformError } from "effect/PlatformError";
3
+ import { ChildProcess } from "effect/unstable/process";
4
+ import { ChildProcessSpawner } from "effect/unstable/process/ChildProcessSpawner";
5
+ declare const AppProcessError_base: Schema.Class<AppProcessError, Schema.TaggedStruct<"AppProcessError", {
6
+ readonly command: Schema.String;
7
+ readonly exitCode: Schema.optional<Schema.Number>;
8
+ readonly stderr: Schema.optional<Schema.String>;
9
+ readonly cause: Schema.optional<Schema.Defect>;
10
+ }>, import("effect/Cause").YieldableError>;
11
+ export declare class AppProcessError extends AppProcessError_base {
12
+ get message(): string;
13
+ }
14
+ export interface RunOptions {
15
+ readonly combineOutput?: boolean;
16
+ readonly maxOutputBytes?: number;
17
+ readonly maxErrorBytes?: number;
18
+ readonly signal?: AbortSignal;
19
+ readonly timeout?: Duration.Input;
20
+ readonly stdin?: string | Uint8Array | Stream.Stream<Uint8Array, PlatformError>;
21
+ }
22
+ export interface RunStreamOptions {
23
+ readonly signal?: AbortSignal;
24
+ readonly includeStderr?: boolean;
25
+ readonly okExitCodes?: ReadonlyArray<number>;
26
+ readonly maxErrorBytes?: number;
27
+ }
28
+ export interface RunResult {
29
+ readonly command: string;
30
+ readonly exitCode: number;
31
+ readonly output?: Buffer;
32
+ readonly stdout: Buffer;
33
+ readonly stderr: Buffer;
34
+ readonly outputTruncated?: boolean;
35
+ readonly stdoutTruncated: boolean;
36
+ readonly stderrTruncated: boolean;
37
+ }
38
+ export type Interface = ChildProcessSpawner["Service"] & {
39
+ readonly run: (command: ChildProcess.Command, options?: RunOptions) => Effect.Effect<RunResult, AppProcessError>;
40
+ readonly runStream: (command: ChildProcess.Command, options?: RunStreamOptions) => Stream.Stream<string, AppProcessError>;
41
+ };
42
+ declare const Service_base: Context.ServiceClass<Service, "@opencode/AppProcess", Interface>;
43
+ export declare class Service extends Service_base {
44
+ }
45
+ export declare const requireSuccess: (result: RunResult) => Effect.Effect<RunResult, AppProcessError>;
46
+ export declare const requireExitIn: (codes: ReadonlyArray<number>) => (result: RunResult) => Effect.Effect<RunResult, AppProcessError>;
47
+ export declare const abortError: (signal: AbortSignal) => Error;
48
+ export declare const waitForAbort: (signal: AbortSignal) => Effect.Effect<never, Error, never>;
49
+ export declare const collectStream: (stream: Stream.Stream<Uint8Array, PlatformError>, maxOutputBytes: number | undefined) => Effect.Effect<{
50
+ buffer: Buffer<ArrayBuffer>;
51
+ truncated: boolean;
52
+ }, PlatformError, never>;
53
+ export declare const node: import("./effect/layer-node.js").Node<Service, never, import("./effect/layer-node.js").Tag<"global">>;
54
+ export * as AppProcess from "./process.js";
@@ -0,0 +1,162 @@
1
+ import { Context, Duration, Effect, Fiber, Layer, Schema, Stream } from "effect";
2
+ import { ChildProcess } from "effect/unstable/process";
3
+ import { ChildProcessSpawner } from "effect/unstable/process/ChildProcessSpawner";
4
+ import { CrossSpawnSpawner } from "./cross-spawn-spawner.js";
5
+ import { makeGlobalNode } from "./effect/app-node.js";
6
+ export class AppProcessError extends Schema.TaggedErrorClass()("AppProcessError", {
7
+ command: Schema.String,
8
+ exitCode: Schema.optional(Schema.Number),
9
+ stderr: Schema.optional(Schema.String),
10
+ cause: Schema.optional(Schema.Defect()),
11
+ }) {
12
+ get message() {
13
+ const detail = this.stderr?.trim() || (this.cause instanceof Error ? this.cause.message : this.cause && String(this.cause));
14
+ const status = this.exitCode === undefined ? "" : ` (exit ${this.exitCode})`;
15
+ return `Command failed${status}: ${this.command}${detail ? `: ${detail}` : ""}`;
16
+ }
17
+ }
18
+ export class Service extends Context.Service()("@opencode/AppProcess") {
19
+ }
20
+ export const requireSuccess = (result) => result.exitCode === 0
21
+ ? Effect.succeed(result)
22
+ : Effect.fail(new AppProcessError({
23
+ command: result.command,
24
+ exitCode: result.exitCode,
25
+ stderr: result.stderr.toString("utf8"),
26
+ }));
27
+ export const requireExitIn = (codes) => (result) => codes.includes(result.exitCode)
28
+ ? Effect.succeed(result)
29
+ : Effect.fail(new AppProcessError({
30
+ command: result.command,
31
+ exitCode: result.exitCode,
32
+ stderr: result.stderr.toString("utf8"),
33
+ }));
34
+ const describeCommand = (command) => {
35
+ if (command._tag === "StandardCommand") {
36
+ return command.args.length ? `${command.command} ${command.args.join(" ")}` : command.command;
37
+ }
38
+ return `${describeCommand(command.left)} | ${describeCommand(command.right)}`;
39
+ };
40
+ const wrapError = (description, cause) => cause instanceof AppProcessError ? cause : new AppProcessError({ command: description, cause });
41
+ export const abortError = (signal) => {
42
+ const reason = signal.reason;
43
+ if (reason instanceof Error)
44
+ return reason;
45
+ const err = new Error("Aborted");
46
+ err.name = "AbortError";
47
+ return err;
48
+ };
49
+ export const waitForAbort = (signal) => Effect.callback((resume) => {
50
+ if (signal.aborted) {
51
+ resume(Effect.fail(abortError(signal)));
52
+ return;
53
+ }
54
+ const onabort = () => resume(Effect.fail(abortError(signal)));
55
+ signal.addEventListener("abort", onabort, { once: true });
56
+ return Effect.sync(() => signal.removeEventListener("abort", onabort));
57
+ });
58
+ const normalizeStdin = (input) => typeof input === "string"
59
+ ? Stream.make(new TextEncoder().encode(input))
60
+ : input instanceof Uint8Array
61
+ ? Stream.make(input)
62
+ : input;
63
+ export const collectStream = (stream, maxOutputBytes) => Stream.runFold(stream, () => ({ chunks: [], bytes: 0, truncated: false }), (acc, chunk) => {
64
+ if (maxOutputBytes === undefined) {
65
+ acc.chunks.push(chunk);
66
+ acc.bytes += chunk.length;
67
+ return acc;
68
+ }
69
+ const remaining = maxOutputBytes - acc.bytes;
70
+ if (remaining > 0)
71
+ acc.chunks.push(remaining >= chunk.length ? chunk : chunk.slice(0, remaining));
72
+ acc.bytes += chunk.length;
73
+ acc.truncated = acc.truncated || acc.bytes > maxOutputBytes;
74
+ return acc;
75
+ }).pipe(Effect.map((x) => ({ buffer: Buffer.concat(x.chunks), truncated: x.truncated })));
76
+ const layer = Layer.effect(Service, Effect.gen(function* () {
77
+ const spawner = yield* ChildProcessSpawner;
78
+ const runCommand = (command, options) => {
79
+ const description = describeCommand(command);
80
+ const collect = Effect.scoped(Effect.gen(function* () {
81
+ const handle = yield* spawner.spawn(command);
82
+ if (options?.combineOutput) {
83
+ const [output, exitCode] = yield* Effect.all([collectStream(handle.all, options.maxOutputBytes), handle.exitCode], { concurrency: "unbounded" });
84
+ return {
85
+ command: description,
86
+ exitCode,
87
+ output: output.buffer,
88
+ stdout: Buffer.alloc(0),
89
+ stderr: Buffer.alloc(0),
90
+ outputTruncated: output.truncated,
91
+ stdoutTruncated: false,
92
+ stderrTruncated: false,
93
+ };
94
+ }
95
+ const [stdout, stderr, exitCode] = yield* Effect.all([
96
+ collectStream(handle.stdout, options?.maxOutputBytes),
97
+ collectStream(handle.stderr, options?.maxErrorBytes),
98
+ handle.exitCode,
99
+ ], { concurrency: "unbounded" });
100
+ return {
101
+ command: description,
102
+ exitCode,
103
+ stdout: stdout.buffer,
104
+ stderr: stderr.buffer,
105
+ stdoutTruncated: stdout.truncated,
106
+ stderrTruncated: stderr.truncated,
107
+ };
108
+ }));
109
+ const timed = options?.timeout
110
+ ? Effect.timeoutOrElse(collect, {
111
+ duration: options.timeout,
112
+ orElse: () => Effect.fail(new AppProcessError({ command: description, cause: new Error("Timed out") })),
113
+ })
114
+ : collect;
115
+ const aborted = options?.signal
116
+ ? timed.pipe(Effect.raceFirst(waitForAbort(options.signal).pipe(Effect.mapError((cause) => wrapError(description, cause)))))
117
+ : timed;
118
+ return aborted.pipe(Effect.catch((cause) => Effect.fail(wrapError(description, cause))));
119
+ };
120
+ const run = Effect.fn("AppProcess.run")(function* (command, options) {
121
+ if (options?.stdin === undefined)
122
+ return yield* runCommand(command, options);
123
+ if (command._tag !== "StandardCommand") {
124
+ return yield* new AppProcessError({
125
+ command: describeCommand(command),
126
+ cause: new Error("stdin option only supports StandardCommand; received PipedCommand"),
127
+ });
128
+ }
129
+ const next = ChildProcess.make(command.command, command.args, {
130
+ ...command.options,
131
+ stdin: normalizeStdin(options.stdin),
132
+ });
133
+ return yield* runCommand(next, options);
134
+ });
135
+ const runStream = (command, options) => {
136
+ const description = describeCommand(command);
137
+ const okExitCodes = options?.okExitCodes;
138
+ const built = Stream.unwrap(Effect.gen(function* () {
139
+ const handle = yield* spawner.spawn(command);
140
+ const stderrFiber = yield* Effect.forkScoped(collectStream(handle.stderr, options?.maxErrorBytes).pipe(Effect.map((x) => x.buffer.toString("utf8"))));
141
+ const source = options?.includeStderr === true ? handle.all : handle.stdout;
142
+ const lines = source.pipe(Stream.decodeText, Stream.splitLines, Stream.filter((line) => line.length > 0));
143
+ const tail = Stream.unwrap(Effect.gen(function* () {
144
+ const code = yield* handle.exitCode;
145
+ if (okExitCodes && okExitCodes.length > 0 && !okExitCodes.includes(code)) {
146
+ const stderr = yield* Fiber.join(stderrFiber);
147
+ return Stream.fail(new AppProcessError({ command: description, exitCode: code, stderr }));
148
+ }
149
+ return Stream.empty;
150
+ }));
151
+ return Stream.concat(lines, tail);
152
+ }));
153
+ const mapped = built.pipe(Stream.catch((cause) => Stream.fail(wrapError(description, cause))));
154
+ if (!options?.signal)
155
+ return mapped;
156
+ const signal = options.signal;
157
+ return mapped.pipe(Stream.interruptWhen(waitForAbort(signal).pipe(Effect.mapError((cause) => wrapError(description, cause)))));
158
+ };
159
+ return Service.of({ ...spawner, run, runStream });
160
+ }));
161
+ export const node = makeGlobalNode({ service: Service, layer: layer, deps: [CrossSpawnSpawner.node] });
162
+ export * as AppProcess from "./process.js";
@@ -0,0 +1,2 @@
1
+ export declare function importModule(specifier: string): Promise<unknown>;
2
+ export declare function resolveModule(specifier: string, directory: string): string;
@@ -0,0 +1,6 @@
1
+ export function importModule(specifier) {
2
+ return import(specifier);
3
+ }
4
+ export function resolveModule(specifier, directory) {
5
+ return import.meta.resolve(specifier, directory);
6
+ }
@@ -0,0 +1,2 @@
1
+ export declare function importModule(specifier: string): Promise<unknown>;
2
+ export declare function resolveModule(specifier: string, directory: string): string;
@@ -0,0 +1,36 @@
1
+ import { Script, constants } from "node:vm";
2
+ import { createRequire, registerHooks } from "node:module";
3
+ import path from "node:path";
4
+ import { pathToFileURL } from "node:url";
5
+ import { resolve } from "resolve.exports";
6
+ let conditions = [];
7
+ const conditionHooks = registerHooks({
8
+ resolve(specifier, context, nextResolve) {
9
+ conditions = context.conditions;
10
+ return nextResolve(specifier, context);
11
+ },
12
+ });
13
+ await new Script('import("node:module")', {
14
+ importModuleDynamically: constants.USE_MAIN_CONTEXT_DEFAULT_LOADER,
15
+ }).runInThisContext();
16
+ conditionHooks.deregister();
17
+ export async function importModule(specifier) {
18
+ const imported = (await new Script(`import(${JSON.stringify(specifier)})`, {
19
+ importModuleDynamically: constants.USE_MAIN_CONTEXT_DEFAULT_LOADER,
20
+ }).runInThisContext());
21
+ if (typeof imported !== "object" || imported === null)
22
+ return imported;
23
+ const module = imported;
24
+ const exports = module["module.exports"];
25
+ if (exports !== module.default || (typeof exports !== "object" && typeof exports !== "function") || exports === null)
26
+ return imported;
27
+ return Object.assign({}, module, exports);
28
+ }
29
+ export function resolveModule(specifier, directory) {
30
+ const pkg = createRequire(import.meta.url)(path.join(directory, "package.json"));
31
+ const target = resolve(pkg, specifier, { conditions, unsafe: true })?.[0];
32
+ if (target)
33
+ return pathToFileURL(path.resolve(directory, target)).href;
34
+ const legacyTarget = specifier === pkg.name ? directory : path.resolve(directory, specifier.slice(pkg.name.length + 1));
35
+ return pathToFileURL(createRequire(path.join(directory, "package.json")).resolve(legacyTarget)).href;
36
+ }
@@ -0,0 +1 @@
1
+ export { importModule, resolveModule } from "#runtime-import";
@@ -0,0 +1 @@
1
+ export { importModule, resolveModule } from "#runtime-import";
package/package.json CHANGED
@@ -1,17 +1,66 @@
1
1
  {
2
+ "$schema": "https://json.schemastore.org/package.json",
2
3
  "name": "@opencode-ai/util",
3
- "version": "0.0.0-bootstrap.0",
4
- "description": "OpenCode package namespace bootstrap",
4
+ "version": "0.0.0-next-15994",
5
+ "type": "module",
5
6
  "license": "MIT",
6
7
  "repository": {
7
8
  "type": "git",
8
- "url": "git+https://github.com/anomalyco/opencode.git"
9
+ "url": "git+https://github.com/anomalyco/opencode.git",
10
+ "directory": "packages/util"
9
11
  },
10
- "files": [
11
- "index.js"
12
- ],
13
- "exports": "./index.js",
14
12
  "publishConfig": {
15
13
  "access": "public"
14
+ },
15
+ "files": [
16
+ "dist"
17
+ ],
18
+ "exports": {
19
+ "./effect/layer-node": {
20
+ "import": "./dist/effect/layer-node.js",
21
+ "types": "./dist/effect/layer-node.d.ts"
22
+ },
23
+ "./*": {
24
+ "import": "./dist/*.js",
25
+ "types": "./dist/*.d.ts"
26
+ }
27
+ },
28
+ "imports": {
29
+ "#runtime-import": {
30
+ "bun": "./dist/runtime/import.bun.js",
31
+ "node": "./dist/runtime/import.node.js",
32
+ "default": "./dist/runtime/import.bun.js"
33
+ }
34
+ },
35
+ "scripts": {
36
+ "build": "bun run script/build.ts",
37
+ "typecheck": "tsgo --noEmit"
38
+ },
39
+ "dependencies": {
40
+ "@effect/opentelemetry": "4.0.0-beta.98",
41
+ "@effect/platform-node": "4.0.0-beta.98",
42
+ "@npmcli/arborist": "9.4.0",
43
+ "@npmcli/config": "10.8.1",
44
+ "@opentelemetry/api": "1.9.0",
45
+ "@opentelemetry/context-async-hooks": "2.6.1",
46
+ "@opentelemetry/exporter-trace-otlp-http": "0.214.0",
47
+ "@opentelemetry/sdk-trace-base": "2.6.1",
48
+ "cross-spawn": "7.0.6",
49
+ "effect": "4.0.0-beta.98",
50
+ "glob": "13.0.5",
51
+ "mime-types": "3.0.2",
52
+ "minimatch": "10.2.5",
53
+ "npm-package-arg": "13.0.2",
54
+ "resolve.exports": "2.0.3",
55
+ "xdg-basedir": "5.1.0"
56
+ },
57
+ "devDependencies": {
58
+ "@tsconfig/bun": "1.0.9",
59
+ "@types/bun": "1.3.13",
60
+ "@types/cross-spawn": "6.0.6",
61
+ "@types/node": "24.12.2",
62
+ "@types/npm-package-arg": "6.1.4",
63
+ "@types/npmcli__arborist": "6.3.3",
64
+ "@typescript/native-preview": "7.0.0-dev.20251207.1"
16
65
  }
17
66
  }
package/index.js DELETED
@@ -1 +0,0 @@
1
- export {}