@basaltbytes/odoo-agentic-dev 0.1.0-beta.1

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 (134) hide show
  1. package/README.md +464 -0
  2. package/dist/cli.d.ts +2 -0
  3. package/dist/cli.js +73 -0
  4. package/dist/cli.js.map +1 -0
  5. package/dist/commands/compose.d.ts +19 -0
  6. package/dist/commands/compose.js +29 -0
  7. package/dist/commands/compose.js.map +1 -0
  8. package/dist/commands/doctor.d.ts +35 -0
  9. package/dist/commands/doctor.js +209 -0
  10. package/dist/commands/doctor.js.map +1 -0
  11. package/dist/commands/down.d.ts +23 -0
  12. package/dist/commands/down.js +46 -0
  13. package/dist/commands/down.js.map +1 -0
  14. package/dist/commands/info.d.ts +10 -0
  15. package/dist/commands/info.js +42 -0
  16. package/dist/commands/info.js.map +1 -0
  17. package/dist/commands/json-report.d.ts +45 -0
  18. package/dist/commands/json-report.js +55 -0
  19. package/dist/commands/json-report.js.map +1 -0
  20. package/dist/commands/link-source.d.ts +33 -0
  21. package/dist/commands/link-source.js +116 -0
  22. package/dist/commands/link-source.js.map +1 -0
  23. package/dist/commands/list.d.ts +29 -0
  24. package/dist/commands/list.js +117 -0
  25. package/dist/commands/list.js.map +1 -0
  26. package/dist/commands/logs.d.ts +17 -0
  27. package/dist/commands/logs.js +28 -0
  28. package/dist/commands/logs.js.map +1 -0
  29. package/dist/commands/prune.d.ts +54 -0
  30. package/dist/commands/prune.js +118 -0
  31. package/dist/commands/prune.js.map +1 -0
  32. package/dist/commands/psql.d.ts +8 -0
  33. package/dist/commands/psql.js +24 -0
  34. package/dist/commands/psql.js.map +1 -0
  35. package/dist/commands/reset-db.d.ts +34 -0
  36. package/dist/commands/reset-db.js +86 -0
  37. package/dist/commands/reset-db.js.map +1 -0
  38. package/dist/commands/resolve-context.d.ts +17 -0
  39. package/dist/commands/resolve-context.js +30 -0
  40. package/dist/commands/resolve-context.js.map +1 -0
  41. package/dist/commands/run.d.ts +31 -0
  42. package/dist/commands/run.js +83 -0
  43. package/dist/commands/run.js.map +1 -0
  44. package/dist/commands/setup.d.ts +46 -0
  45. package/dist/commands/setup.js +93 -0
  46. package/dist/commands/setup.js.map +1 -0
  47. package/dist/commands/shell.d.ts +20 -0
  48. package/dist/commands/shell.js +46 -0
  49. package/dist/commands/shell.js.map +1 -0
  50. package/dist/commands/state-hooks.d.ts +28 -0
  51. package/dist/commands/state-hooks.js +86 -0
  52. package/dist/commands/state-hooks.js.map +1 -0
  53. package/dist/commands/test.d.ts +24 -0
  54. package/dist/commands/test.js +70 -0
  55. package/dist/commands/test.js.map +1 -0
  56. package/dist/commands/trailing-args.d.ts +10 -0
  57. package/dist/commands/trailing-args.js +14 -0
  58. package/dist/commands/trailing-args.js.map +1 -0
  59. package/dist/commands/up.d.ts +23 -0
  60. package/dist/commands/up.js +62 -0
  61. package/dist/commands/up.js.map +1 -0
  62. package/dist/commands/update.d.ts +7 -0
  63. package/dist/commands/update.js +31 -0
  64. package/dist/commands/update.js.map +1 -0
  65. package/dist/commands/worktree.d.ts +97 -0
  66. package/dist/commands/worktree.js +355 -0
  67. package/dist/commands/worktree.js.map +1 -0
  68. package/dist/config/load-recipe.d.ts +14 -0
  69. package/dist/config/load-recipe.js +75 -0
  70. package/dist/config/load-recipe.js.map +1 -0
  71. package/dist/config/schema.d.ts +9 -0
  72. package/dist/config/schema.js +190 -0
  73. package/dist/config/schema.js.map +1 -0
  74. package/dist/core/command-plan.d.ts +34 -0
  75. package/dist/core/command-plan.js +112 -0
  76. package/dist/core/command-plan.js.map +1 -0
  77. package/dist/core/compose-model.d.ts +18 -0
  78. package/dist/core/compose-model.js +80 -0
  79. package/dist/core/compose-model.js.map +1 -0
  80. package/dist/core/compose-project.d.ts +3 -0
  81. package/dist/core/compose-project.js +15 -0
  82. package/dist/core/compose-project.js.map +1 -0
  83. package/dist/core/database-name.d.ts +15 -0
  84. package/dist/core/database-name.js +59 -0
  85. package/dist/core/database-name.js.map +1 -0
  86. package/dist/core/environment.d.ts +84 -0
  87. package/dist/core/environment.js +78 -0
  88. package/dist/core/environment.js.map +1 -0
  89. package/dist/core/port-allocator.d.ts +30 -0
  90. package/dist/core/port-allocator.js +58 -0
  91. package/dist/core/port-allocator.js.map +1 -0
  92. package/dist/core/project-recipe.d.ts +163 -0
  93. package/dist/core/project-recipe.js +13 -0
  94. package/dist/core/project-recipe.js.map +1 -0
  95. package/dist/core/safety.d.ts +11 -0
  96. package/dist/core/safety.js +16 -0
  97. package/dist/core/safety.js.map +1 -0
  98. package/dist/core/worktree-context.d.ts +32 -0
  99. package/dist/core/worktree-context.js +94 -0
  100. package/dist/core/worktree-context.js.map +1 -0
  101. package/dist/errors/errors.d.ts +124 -0
  102. package/dist/errors/errors.js +129 -0
  103. package/dist/errors/errors.js.map +1 -0
  104. package/dist/index.d.ts +3 -0
  105. package/dist/index.js +2 -0
  106. package/dist/index.js.map +1 -0
  107. package/dist/platform/command-runner.d.ts +30 -0
  108. package/dist/platform/command-runner.js +65 -0
  109. package/dist/platform/command-runner.js.map +1 -0
  110. package/dist/platform/docker-compose.d.ts +69 -0
  111. package/dist/platform/docker-compose.js +239 -0
  112. package/dist/platform/docker-compose.js.map +1 -0
  113. package/dist/platform/git.d.ts +10 -0
  114. package/dist/platform/git.js +35 -0
  115. package/dist/platform/git.js.map +1 -0
  116. package/dist/platform/odoo-lifecycle.d.ts +30 -0
  117. package/dist/platform/odoo-lifecycle.js +109 -0
  118. package/dist/platform/odoo-lifecycle.js.map +1 -0
  119. package/dist/platform/port-probe.d.ts +7 -0
  120. package/dist/platform/port-probe.js +13 -0
  121. package/dist/platform/port-probe.js.map +1 -0
  122. package/dist/platform/process-supervisor.d.ts +16 -0
  123. package/dist/platform/process-supervisor.js +23 -0
  124. package/dist/platform/process-supervisor.js.map +1 -0
  125. package/dist/platform/state-store.d.ts +37 -0
  126. package/dist/platform/state-store.js +122 -0
  127. package/dist/platform/state-store.js.map +1 -0
  128. package/dist/suppress-sqlite-warning.d.ts +1 -0
  129. package/dist/suppress-sqlite-warning.js +18 -0
  130. package/dist/suppress-sqlite-warning.js.map +1 -0
  131. package/dist/testing/fake-adapters.d.ts +34 -0
  132. package/dist/testing/fake-adapters.js +90 -0
  133. package/dist/testing/fake-adapters.js.map +1 -0
  134. package/package.json +78 -0
@@ -0,0 +1,122 @@
1
+ import { mkdirSync } from "node:fs";
2
+ import { homedir } from "node:os";
3
+ import { dirname, join } from "node:path";
4
+ import { Context, Effect, Layer } from "effect";
5
+ import { StateError } from "../errors/errors.js";
6
+ export const StateStore = Context.Service("odoo-agentic-dev/StateStore");
7
+ /** Global registry location; `ODOO_AGENTIC_DEV_STATE_DB` overrides (tests). */
8
+ export const resolveStateDbPath = (env = process.env) => env["ODOO_AGENTIC_DEV_STATE_DB"] ??
9
+ join(env["XDG_DATA_HOME"] ?? join(homedir(), ".local", "share"), "odoo-agentic-dev", "state.db");
10
+ const SCHEMA_SQL = `
11
+ CREATE TABLE IF NOT EXISTS schema_meta (
12
+ version INTEGER PRIMARY KEY
13
+ );
14
+ CREATE TABLE IF NOT EXISTS environments (
15
+ compose_project TEXT PRIMARY KEY,
16
+ project_id TEXT NOT NULL,
17
+ database_name TEXT NOT NULL,
18
+ root_dir TEXT NOT NULL,
19
+ worktree_name TEXT NOT NULL,
20
+ branch TEXT,
21
+ odoo_http_port INTEGER NOT NULL,
22
+ shared INTEGER NOT NULL DEFAULT 0,
23
+ created_at TEXT NOT NULL,
24
+ last_used_at TEXT NOT NULL,
25
+ template_db TEXT,
26
+ template_key TEXT
27
+ );
28
+ INSERT OR IGNORE INTO schema_meta (version) VALUES (1);
29
+ `;
30
+ const UPSERT_SQL = `
31
+ INSERT INTO environments (
32
+ compose_project, project_id, database_name, root_dir, worktree_name,
33
+ branch, odoo_http_port, shared, created_at, last_used_at, template_db, template_key
34
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, NULL)
35
+ ON CONFLICT(compose_project) DO UPDATE SET
36
+ project_id = excluded.project_id,
37
+ database_name = excluded.database_name,
38
+ root_dir = excluded.root_dir,
39
+ worktree_name = excluded.worktree_name,
40
+ branch = excluded.branch,
41
+ odoo_http_port = excluded.odoo_http_port,
42
+ shared = excluded.shared,
43
+ last_used_at = excluded.last_used_at
44
+ `;
45
+ const toRow = (record) => ({
46
+ composeProject: String(record["compose_project"]),
47
+ projectId: String(record["project_id"]),
48
+ databaseName: String(record["database_name"]),
49
+ rootDir: String(record["root_dir"]),
50
+ worktreeName: String(record["worktree_name"]),
51
+ branch: record["branch"] === null ? null : String(record["branch"]),
52
+ odooHttpPort: Number(record["odoo_http_port"]),
53
+ shared: Number(record["shared"]) !== 0,
54
+ createdAt: String(record["created_at"]),
55
+ lastUsedAt: String(record["last_used_at"]),
56
+ templateDb: record["template_db"] === null ? null : String(record["template_db"]),
57
+ templateKey: record["template_key"] === null ? null : String(record["template_key"]),
58
+ });
59
+ // All effects happen lazily per-operation inside withDb (open → run → close,
60
+ // so parallel agent sessions never hold the registry open); building the
61
+ // service itself is pure.
62
+ export const StateStoreLive = Layer.effect(StateStore, Effect.sync(() => {
63
+ const attempt = (label, thunk) => Effect.try({
64
+ try: thunk,
65
+ catch: (cause) => new StateError({ reason: `${label}: ${String(cause)}` }),
66
+ });
67
+ let sqlitePromise;
68
+ const loadSqlite = () => Effect.tryPromise({
69
+ try: () => {
70
+ sqlitePromise ??= import("node:sqlite");
71
+ return sqlitePromise;
72
+ },
73
+ catch: (cause) => new StateError({ reason: `loading node:sqlite: ${String(cause)}` }),
74
+ });
75
+ const withDb = (label, thunk) => Effect.gen(function* () {
76
+ const sqlite = yield* loadSqlite();
77
+ return yield* attempt(label, () => {
78
+ const path = resolveStateDbPath();
79
+ mkdirSync(dirname(path), { recursive: true });
80
+ const db = new sqlite.DatabaseSync(path, { timeout: 5000 });
81
+ try {
82
+ db.exec("PRAGMA busy_timeout=5000;");
83
+ db.exec("PRAGMA journal_mode=WAL;");
84
+ db.exec(SCHEMA_SQL);
85
+ return thunk(db);
86
+ }
87
+ finally {
88
+ db.close();
89
+ }
90
+ });
91
+ });
92
+ return {
93
+ upsert: (env) => withDb("upsert", (db) => {
94
+ const now = env.now ?? new Date().toISOString();
95
+ db.prepare(UPSERT_SQL).run(env.composeProject, env.projectId, env.databaseName, env.rootDir, env.worktreeName, env.branch, env.odooHttpPort, env.shared ? 1 : 0, now, now);
96
+ }),
97
+ touch: (composeProject) => withDb("touch", (db) => {
98
+ db.prepare("UPDATE environments SET last_used_at = ? WHERE compose_project = ?").run(new Date().toISOString(), composeProject);
99
+ }),
100
+ get: (composeProject) => withDb("get", (db) => {
101
+ const record = db
102
+ .prepare("SELECT * FROM environments WHERE compose_project = ?")
103
+ .get(composeProject);
104
+ return record === undefined ? undefined : toRow(record);
105
+ }),
106
+ list: (filter) => withDb("list", (db) => {
107
+ const records = filter.projectId === undefined
108
+ ? db.prepare("SELECT * FROM environments ORDER BY compose_project").all()
109
+ : db
110
+ .prepare("SELECT * FROM environments WHERE project_id = ? ORDER BY compose_project")
111
+ .all(filter.projectId);
112
+ return records.map(toRow);
113
+ }),
114
+ remove: (composeProject) => withDb("remove", (db) => {
115
+ db.prepare("DELETE FROM environments WHERE compose_project = ?").run(composeProject);
116
+ }),
117
+ setTemplate: (composeProject, meta) => withDb("setTemplate", (db) => {
118
+ db.prepare("UPDATE environments SET template_db = ?, template_key = ? WHERE compose_project = ?").run(meta?.databaseName ?? null, meta?.key ?? null, composeProject);
119
+ }),
120
+ };
121
+ }));
122
+ //# sourceMappingURL=state-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state-store.js","sourceRoot":"","sources":["../../src/platform/state-store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Node 22 prints an ExperimentalWarning the first time `node:sqlite` loads.
3
+ * The state registry is core machinery, so that warning is pure noise — filter
4
+ * it (and ONLY it) by intercepting `process.emitWarning`.
5
+ *
6
+ * This module is imported for its side effect and MUST stay the first import
7
+ * of `cli.ts`: imports hoist, so any later import that transitively loads
8
+ * `node:sqlite` would otherwise emit before the filter is installed.
9
+ */
10
+ const originalEmitWarning = process.emitWarning.bind(process);
11
+ process.emitWarning = ((warning, ...rest) => {
12
+ const text = typeof warning === "string" ? warning : warning.message;
13
+ if (text.includes("SQLite is an experimental feature"))
14
+ return;
15
+ return originalEmitWarning(warning, ...rest);
16
+ });
17
+ export {};
18
+ //# sourceMappingURL=suppress-sqlite-warning.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"suppress-sqlite-warning.js","sourceRoot":"","sources":["../src/suppress-sqlite-warning.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,MAAM,mBAAmB,GAAG,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;AAE9D,OAAO,CAAC,WAAW,GAAG,CAAC,CAAC,OAAuB,EAAE,GAAG,IAA0B,EAAE,EAAE;IAChF,MAAM,IAAI,GAAG,OAAO,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC;IACrE,IAAI,IAAI,CAAC,QAAQ,CAAC,mCAAmC,CAAC;QAAE,OAAO;IAC/D,OAAQ,mBAAiE,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,CAAC;AAC9F,CAAC,CAA+B,CAAC;AAEjC,OAAO,EAAE,CAAC"}
@@ -0,0 +1,34 @@
1
+ import { Layer } from "effect";
2
+ import type { CommandRunnerApi, ExecResult, ExecSpec } from "../platform/command-runner.js";
3
+ import type { GitApi } from "../platform/git.js";
4
+ import type { PortProbeApi } from "../platform/port-probe.js";
5
+ import type { StateStoreApi } from "../platform/state-store.js";
6
+ import type { EnvironmentRow } from "../core/environment.js";
7
+ import type { GitState } from "../core/worktree-context.js";
8
+ /**
9
+ * CommandRunner fake: records every call; `script` may return a result per
10
+ * spec (default: exit 0, empty output).
11
+ */
12
+ export declare const makeRecordingRunner: (script?: (spec: ExecSpec) => ExecResult | undefined) => {
13
+ readonly calls: Array<ExecSpec>;
14
+ readonly layer: Layer.Layer<CommandRunnerApi>;
15
+ };
16
+ /**
17
+ * Git fake. `branchExists` consults `options.branches` when provided;
18
+ * without it every branch is reported as existing (the conservative default —
19
+ * nothing gets classified `gone-branch` by accident).
20
+ */
21
+ export declare const makeFakeGit: (state: GitState, options?: {
22
+ readonly branches?: ReadonlySet<string> | undefined;
23
+ }) => Layer.Layer<GitApi>;
24
+ /** PortProbe fake: ports in `busyPorts` are reported busy, everything else free. */
25
+ export declare const makeFakePortProbe: (busyPorts: ReadonlySet<number>) => Layer.Layer<PortProbeApi>;
26
+ /**
27
+ * StateStore fake backed by an in-memory Map keyed by compose project. Mirrors
28
+ * the live semantics exactly: upsert preserves createdAt/template fields on
29
+ * existing rows while refreshing everything mutable plus lastUsedAt.
30
+ */
31
+ export declare const makeFakeStateStore: (initial?: ReadonlyArray<EnvironmentRow>) => {
32
+ readonly rows: Map<string, EnvironmentRow>;
33
+ readonly layer: Layer.Layer<StateStoreApi>;
34
+ };
@@ -0,0 +1,90 @@
1
+ import { Effect, Layer } from "effect";
2
+ import { CommandRunner } from "../platform/command-runner.js";
3
+ import { Git } from "../platform/git.js";
4
+ import { PortProbe } from "../platform/port-probe.js";
5
+ import { StateStore } from "../platform/state-store.js";
6
+ /**
7
+ * CommandRunner fake: records every call; `script` may return a result per
8
+ * spec (default: exit 0, empty output).
9
+ */
10
+ export const makeRecordingRunner = (script) => {
11
+ const calls = [];
12
+ const respond = (spec) => {
13
+ calls.push(spec);
14
+ return script?.(spec) ?? { exitCode: 0, stdout: "", stderr: "" };
15
+ };
16
+ return {
17
+ calls,
18
+ layer: Layer.succeed(CommandRunner, {
19
+ run: (spec) => Effect.sync(() => respond(spec)),
20
+ runInherited: (spec) => Effect.sync(() => respond(spec).exitCode),
21
+ runInteractive: (spec) => Effect.sync(() => respond(spec).exitCode),
22
+ }),
23
+ };
24
+ };
25
+ /**
26
+ * Git fake. `branchExists` consults `options.branches` when provided;
27
+ * without it every branch is reported as existing (the conservative default —
28
+ * nothing gets classified `gone-branch` by accident).
29
+ */
30
+ export const makeFakeGit = (state, options) => Layer.succeed(Git, {
31
+ state: () => Effect.succeed(state),
32
+ branchExists: (_rootDir, branch) => Effect.succeed(options?.branches === undefined ? true : options.branches.has(branch)),
33
+ });
34
+ /** PortProbe fake: ports in `busyPorts` are reported busy, everything else free. */
35
+ export const makeFakePortProbe = (busyPorts) => Layer.succeed(PortProbe, { isFree: (port) => Effect.succeed(!busyPorts.has(port)) });
36
+ /**
37
+ * StateStore fake backed by an in-memory Map keyed by compose project. Mirrors
38
+ * the live semantics exactly: upsert preserves createdAt/template fields on
39
+ * existing rows while refreshing everything mutable plus lastUsedAt.
40
+ */
41
+ export const makeFakeStateStore = (initial = []) => {
42
+ const rows = new Map(initial.map((row) => [row.composeProject, row]));
43
+ return {
44
+ rows,
45
+ layer: Layer.succeed(StateStore, {
46
+ upsert: (env) => Effect.sync(() => {
47
+ const now = env.now ?? new Date().toISOString();
48
+ const existing = rows.get(env.composeProject);
49
+ rows.set(env.composeProject, {
50
+ composeProject: env.composeProject,
51
+ projectId: env.projectId,
52
+ databaseName: env.databaseName,
53
+ rootDir: env.rootDir,
54
+ worktreeName: env.worktreeName,
55
+ branch: env.branch,
56
+ odooHttpPort: env.odooHttpPort,
57
+ shared: env.shared,
58
+ createdAt: existing?.createdAt ?? now,
59
+ lastUsedAt: now,
60
+ templateDb: existing?.templateDb ?? null,
61
+ templateKey: existing?.templateKey ?? null,
62
+ });
63
+ }),
64
+ touch: (composeProject) => Effect.sync(() => {
65
+ const existing = rows.get(composeProject);
66
+ if (existing !== undefined) {
67
+ rows.set(composeProject, { ...existing, lastUsedAt: new Date().toISOString() });
68
+ }
69
+ }),
70
+ get: (composeProject) => Effect.sync(() => rows.get(composeProject)),
71
+ list: (filter) => Effect.sync(() => [...rows.values()]
72
+ .filter((row) => filter.projectId === undefined || row.projectId === filter.projectId)
73
+ .sort((a, b) => a.composeProject.localeCompare(b.composeProject))),
74
+ remove: (composeProject) => Effect.sync(() => {
75
+ rows.delete(composeProject);
76
+ }),
77
+ setTemplate: (composeProject, meta) => Effect.sync(() => {
78
+ const existing = rows.get(composeProject);
79
+ if (existing !== undefined) {
80
+ rows.set(composeProject, {
81
+ ...existing,
82
+ templateDb: meta?.databaseName ?? null,
83
+ templateKey: meta?.key ?? null,
84
+ });
85
+ }
86
+ }),
87
+ }),
88
+ };
89
+ };
90
+ //# sourceMappingURL=fake-adapters.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fake-adapters.js","sourceRoot":"","sources":["../../src/testing/fake-adapters.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,78 @@
1
+ {
2
+ "name": "@basaltbytes/odoo-agentic-dev",
3
+ "version": "0.1.0-beta.1",
4
+ "description": "Agent-friendly local Odoo development runtime: worktree-isolated databases, ports, and Docker Compose stacks",
5
+ "keywords": [
6
+ "agentic",
7
+ "cli",
8
+ "development-environment",
9
+ "devtools",
10
+ "docker",
11
+ "docker-compose",
12
+ "effect",
13
+ "git-worktree",
14
+ "odoo"
15
+ ],
16
+ "homepage": "https://github.com/basaltbytes/odoo-agentic-dev#readme",
17
+ "bugs": {
18
+ "url": "https://github.com/basaltbytes/odoo-agentic-dev/issues"
19
+ },
20
+ "license": "MIT",
21
+ "repository": {
22
+ "type": "git",
23
+ "url": "git+https://github.com/basaltbytes/odoo-agentic-dev.git"
24
+ },
25
+ "bin": {
26
+ "oad": "./dist/cli.js",
27
+ "odoo-agentic-dev": "./dist/cli.js"
28
+ },
29
+ "files": [
30
+ "dist"
31
+ ],
32
+ "type": "module",
33
+ "main": "./dist/index.js",
34
+ "types": "./dist/index.d.ts",
35
+ "exports": {
36
+ ".": {
37
+ "types": "./dist/index.d.ts",
38
+ "default": "./dist/index.js"
39
+ },
40
+ "./package.json": "./package.json"
41
+ },
42
+ "publishConfig": {
43
+ "access": "public",
44
+ "tag": "beta"
45
+ },
46
+ "dependencies": {
47
+ "@effect/platform-node": "4.0.0-beta.78",
48
+ "effect": "4.0.0-beta.78",
49
+ "jiti": "^2.7.0"
50
+ },
51
+ "devDependencies": {
52
+ "@types/node": "^25.9.2",
53
+ "oxfmt": "^0.54.0",
54
+ "oxlint": "^1.69.0",
55
+ "typescript": "^6.0.3",
56
+ "vitest": "^4.1.8",
57
+ "yaml": "^2.9.0"
58
+ },
59
+ "devEngines": {
60
+ "packageManager": {
61
+ "name": "pnpm",
62
+ "version": "11.0.8",
63
+ "onFail": "download"
64
+ }
65
+ },
66
+ "engines": {
67
+ "node": ">=22.15"
68
+ },
69
+ "scripts": {
70
+ "build": "tsc -p tsconfig.build.json",
71
+ "lint": "oxlint .",
72
+ "format": "oxfmt --write .",
73
+ "format:check": "oxfmt --check .",
74
+ "test": "vitest run",
75
+ "test:watch": "vitest",
76
+ "typecheck": "tsc -p tsconfig.json"
77
+ }
78
+ }