@open-mercato/cli 0.5.1-develop.3036.f02c281f23 → 0.5.1-develop.3043.1a796c3920
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/.turbo/turbo-build.log +1 -1
- package/dist/agentic/shared/AGENTS.md.template +1 -1
- package/dist/lib/__integration__/TC-INT-007.spec.js +201 -0
- package/dist/lib/__integration__/TC-INT-007.spec.js.map +7 -0
- package/dist/lib/dev-env-reload.js +89 -0
- package/dist/lib/dev-env-reload.js.map +7 -0
- package/dist/lib/generators/extensions/ai-agents.js +218 -0
- package/dist/lib/generators/extensions/ai-agents.js.map +7 -0
- package/dist/lib/generators/extensions/ai-tools.js +56 -1
- package/dist/lib/generators/extensions/ai-tools.js.map +2 -2
- package/dist/lib/generators/extensions/index.js +2 -0
- package/dist/lib/generators/extensions/index.js.map +2 -2
- package/dist/lib/testing/integration-discovery.js +102 -5
- package/dist/lib/testing/integration-discovery.js.map +2 -2
- package/dist/mercato.js +85 -44
- package/dist/mercato.js.map +2 -2
- package/package.json +5 -5
- package/src/__tests__/mercato.test.ts +112 -0
- package/src/lib/__integration__/TC-INT-007.spec.ts +228 -0
- package/src/lib/__tests__/dev-env-reload.test.ts +62 -0
- package/src/lib/dev-env-reload.ts +110 -0
- package/src/lib/generators/__tests__/module-subset.test.ts +14 -0
- package/src/lib/generators/__tests__/output-snapshots.test.ts +17 -0
- package/src/lib/generators/__tests__/scanner.test.ts +1 -1
- package/src/lib/generators/__tests__/structural-contracts.test.ts +26 -0
- package/src/lib/generators/extensions/ai-agents.ts +240 -0
- package/src/lib/generators/extensions/ai-tools.ts +72 -1
- package/src/lib/generators/extensions/index.ts +2 -0
- package/src/lib/testing/__tests__/integration-discovery.test.ts +68 -0
- package/src/lib/testing/integration-discovery.ts +127 -3
- package/src/mercato.ts +100 -46
package/.turbo/turbo-build.log
CHANGED
|
@@ -152,7 +152,7 @@ Register in `src/modules.ts`: `{ id: '<id>', from: '@app' }`
|
|
|
152
152
|
8. **After the user adds a new module, offer to trim classic mode.** A fresh `create-mercato-app` scaffold enables every built-in module (classic mode). Once the user has added their own custom module, the defaults are usually dead weight. **Ask the user** (via a short `AskUserQuestion`) whether they want to disable built-in modules that are not needed for their project. If they say yes, invoke the `trim-unused-modules` skill — do NOT hand-craft the slimdown inside the AGENTS.md reading flow. If they say no, preserve classic mode silently.
|
|
153
153
|
|
|
154
154
|
**Dashboards fallback rule.** When the user (or the `trim-unused-modules` skill) disables the `dashboards` module, you MUST update `src/app/(backend)/backend/page.tsx` so it no longer renders `<DashboardScreen />`. Replace the dashboard render with a `redirect(...)` to the first enabled backend page for the current user — preferring pages already registered in the main sidebar group and respecting the admin/superadmin role of the caller. Otherwise `/backend` will crash at build or request time because the removed module no longer ships `DashboardScreen`. Always fall back to `/backend/profile` only if no other backend page is available.
|
|
155
|
-
9. **New features MUST be visible to
|
|
155
|
+
9. **New features MUST be visible to default roles immediately.** Every time you add a new feature ID (e.g. `my_module.view`, `my_module.manage`) to `src/modules/<module>/acl.ts`, you MUST also (a) add that feature to `defaultRoleFeatures` in the same module's `setup.ts` so the admin role and any other appropriate default roles get it on every tenant setup; and (b) run `yarn mercato auth sync-role-acls` so existing tenants pick up the new feature without a reinstall. Use `--tenant <tenantId>` only when the user asks to target one tenant. Do this automatically unless the user has explicitly said otherwise — the user should see the features you are building, not stare at a blank admin because their role is missing a grant. Feature IDs are FROZEN once shipped; if a rename is required, add the new ID alongside, grant it, and keep the old one as a deprecated alias.
|
|
156
156
|
10. **Strict Design System alignment for every UI change.** Any UI you add or edit MUST use the Open Mercato design system components and tokens. No hardcoded Tailwind status colors (`text-red-500`, `bg-green-100`, etc.) — use semantic tokens (`text-status-error-text`, `bg-status-success-bg`, …). No arbitrary text sizes (`text-[11px]`, `text-[13px]`) — use the Tailwind scale (`text-xs`, `text-sm`, `text-base`, `text-lg`, `text-xl`, `text-2xl`) or the `text-overline` token for 11px uppercase labels. In PAGE BODY UI, use `lucide-react` icons (never inline `<svg>`). Use `StatusBadge` for entity status, `Alert` for inline feedback, `FormField` for standalone form inputs, `SectionHeader` for detail-page section headings, `CollapsibleSection` for collapsible regions, `LoadingMessage`/`Spinner`/`DataLoader` for async states, and `EmptyState` (or DataTable's `emptyState` prop) for empty lists. For list pages, follow `.ai/skills/backend-ui-design/SKILL.md` and prefer the `DataTable` host pattern shown there (`entityId`, `apiPath`, stable `extensionTableId`, and explicit pagination props when you own the data source). Every dialog MUST support `Cmd/Ctrl+Enter` to submit and `Escape` to cancel. Every icon-only button MUST have an `aria-label`. These rules apply to `src/modules/<module>/backend/**` and `src/modules/<module>/frontend/**` alike.
|
|
157
157
|
11. **BEFORE writing ANY code**, you MUST:
|
|
158
158
|
- Match your task against the **Task → Context Map** above
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
import { expect, test } from "@playwright/test";
|
|
2
|
+
import { execFileSync } from "node:child_process";
|
|
3
|
+
import fs from "node:fs";
|
|
4
|
+
import os from "node:os";
|
|
5
|
+
import path from "node:path";
|
|
6
|
+
import { fileURLToPath } from "node:url";
|
|
7
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
8
|
+
const repoRoot = path.resolve(__dirname, "..", "..", "..", "..", "..");
|
|
9
|
+
const cliBin = path.join(repoRoot, "packages", "cli", "dist", "bin.js");
|
|
10
|
+
const fixtureModulePackage = path.join(
|
|
11
|
+
repoRoot,
|
|
12
|
+
"packages",
|
|
13
|
+
"cli",
|
|
14
|
+
"src",
|
|
15
|
+
"lib",
|
|
16
|
+
"__fixtures__",
|
|
17
|
+
"official-module-package"
|
|
18
|
+
);
|
|
19
|
+
function yarnBinary() {
|
|
20
|
+
return process.platform === "win32" ? "yarn.cmd" : "yarn";
|
|
21
|
+
}
|
|
22
|
+
function runCommand(command, args, cwd) {
|
|
23
|
+
const yarnCacheFolder = path.join(cwd, ".yarn", "cache");
|
|
24
|
+
return execFileSync(command, args, {
|
|
25
|
+
cwd,
|
|
26
|
+
encoding: "utf8",
|
|
27
|
+
env: {
|
|
28
|
+
...process.env,
|
|
29
|
+
FORCE_COLOR: "0",
|
|
30
|
+
NODE_NO_WARNINGS: "1",
|
|
31
|
+
YARN_CACHE_FOLDER: yarnCacheFolder,
|
|
32
|
+
YARN_ENABLE_GLOBAL_CACHE: "0",
|
|
33
|
+
YARN_ENABLE_IMMUTABLE_INSTALLS: "0",
|
|
34
|
+
YARN_NODE_LINKER: "node-modules"
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
function runMercato(args, cwd) {
|
|
39
|
+
return runCommand(process.execPath, [cliBin, ...args], cwd);
|
|
40
|
+
}
|
|
41
|
+
function writeFile(filePath, content) {
|
|
42
|
+
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
43
|
+
fs.writeFileSync(filePath, content);
|
|
44
|
+
}
|
|
45
|
+
function createCoreWorkspacePackage(rootDir, relativeDir) {
|
|
46
|
+
const coreDir = path.join(rootDir, relativeDir);
|
|
47
|
+
writeFile(
|
|
48
|
+
path.join(coreDir, "package.json"),
|
|
49
|
+
JSON.stringify(
|
|
50
|
+
{
|
|
51
|
+
name: "@open-mercato/core",
|
|
52
|
+
version: "0.4.7",
|
|
53
|
+
type: "module"
|
|
54
|
+
},
|
|
55
|
+
null,
|
|
56
|
+
2
|
|
57
|
+
)
|
|
58
|
+
);
|
|
59
|
+
return coreDir;
|
|
60
|
+
}
|
|
61
|
+
function createMonorepoFixture(rootDir) {
|
|
62
|
+
writeFile(
|
|
63
|
+
path.join(rootDir, "package.json"),
|
|
64
|
+
JSON.stringify(
|
|
65
|
+
{
|
|
66
|
+
name: "cli-module-monorepo-fixture",
|
|
67
|
+
private: true,
|
|
68
|
+
workspaces: ["apps/*", "packages/*"]
|
|
69
|
+
},
|
|
70
|
+
null,
|
|
71
|
+
2
|
|
72
|
+
)
|
|
73
|
+
);
|
|
74
|
+
writeFile(
|
|
75
|
+
path.join(rootDir, ".yarnrc.yml"),
|
|
76
|
+
["nodeLinker: node-modules", "enableGlobalCache: false", "cacheFolder: ./.yarn/cache", ""].join("\n")
|
|
77
|
+
);
|
|
78
|
+
createCoreWorkspacePackage(rootDir, path.join("packages", "core"));
|
|
79
|
+
const appDir = path.join(rootDir, "apps", "mercato");
|
|
80
|
+
writeFile(
|
|
81
|
+
path.join(appDir, "package.json"),
|
|
82
|
+
JSON.stringify(
|
|
83
|
+
{
|
|
84
|
+
name: "@open-mercato/app",
|
|
85
|
+
version: "0.0.0",
|
|
86
|
+
private: true
|
|
87
|
+
},
|
|
88
|
+
null,
|
|
89
|
+
2
|
|
90
|
+
)
|
|
91
|
+
);
|
|
92
|
+
writeFile(path.join(appDir, "src", "modules.ts"), "export const enabledModules = []\n");
|
|
93
|
+
return appDir;
|
|
94
|
+
}
|
|
95
|
+
function createStandaloneFixture(rootDir) {
|
|
96
|
+
writeFile(
|
|
97
|
+
path.join(rootDir, ".yarnrc.yml"),
|
|
98
|
+
["nodeLinker: node-modules", "enableGlobalCache: false", "cacheFolder: ./.yarn/cache", ""].join("\n")
|
|
99
|
+
);
|
|
100
|
+
createCoreWorkspacePackage(rootDir, path.join("vendor", "core"));
|
|
101
|
+
writeFile(
|
|
102
|
+
path.join(rootDir, "package.json"),
|
|
103
|
+
JSON.stringify(
|
|
104
|
+
{
|
|
105
|
+
name: "cli-module-standalone-fixture",
|
|
106
|
+
private: true,
|
|
107
|
+
dependencies: {
|
|
108
|
+
"@open-mercato/core": "file:./vendor/core"
|
|
109
|
+
}
|
|
110
|
+
},
|
|
111
|
+
null,
|
|
112
|
+
2
|
|
113
|
+
)
|
|
114
|
+
);
|
|
115
|
+
writeFile(path.join(rootDir, "src", "modules.ts"), "export const enabledModules = []\n");
|
|
116
|
+
return rootDir;
|
|
117
|
+
}
|
|
118
|
+
function readFile(filePath) {
|
|
119
|
+
return fs.readFileSync(filePath, "utf8");
|
|
120
|
+
}
|
|
121
|
+
test.describe("TC-INT-007: CLI official module install and eject flows", () => {
|
|
122
|
+
test("module add installs and registers a package-backed module in a monorepo app", () => {
|
|
123
|
+
const rootDir = fs.mkdtempSync(path.join(os.tmpdir(), "mercato-cli-monorepo-"));
|
|
124
|
+
try {
|
|
125
|
+
const appDir = createMonorepoFixture(rootDir);
|
|
126
|
+
runCommand(yarnBinary(), ["install"], rootDir);
|
|
127
|
+
runMercato(
|
|
128
|
+
[
|
|
129
|
+
"module",
|
|
130
|
+
"add",
|
|
131
|
+
`@open-mercato/test-package@file:${fixtureModulePackage}`
|
|
132
|
+
],
|
|
133
|
+
rootDir
|
|
134
|
+
);
|
|
135
|
+
const modulesSource = readFile(path.join(appDir, "src", "modules.ts"));
|
|
136
|
+
const cssSource = readFile(path.join(appDir, ".mercato", "generated", "module-package-sources.css"));
|
|
137
|
+
const appPackageJson = JSON.parse(readFile(path.join(appDir, "package.json")));
|
|
138
|
+
expect(modulesSource).toContain("{ id: 'test_package', from: '@open-mercato/test-package' }");
|
|
139
|
+
expect(cssSource).toContain("node_modules/@open-mercato/test-package/src/**/*.{ts,tsx}");
|
|
140
|
+
expect(appPackageJson.dependencies?.["@open-mercato/test-package"]).toBeTruthy();
|
|
141
|
+
} finally {
|
|
142
|
+
fs.rmSync(rootDir, { recursive: true, force: true });
|
|
143
|
+
}
|
|
144
|
+
});
|
|
145
|
+
test("module add --eject copies module source and omits package CSS entries", () => {
|
|
146
|
+
const appDir = fs.mkdtempSync(path.join(os.tmpdir(), "mercato-cli-standalone-source-"));
|
|
147
|
+
try {
|
|
148
|
+
createStandaloneFixture(appDir);
|
|
149
|
+
runCommand(yarnBinary(), ["install"], appDir);
|
|
150
|
+
runMercato(
|
|
151
|
+
[
|
|
152
|
+
"module",
|
|
153
|
+
"add",
|
|
154
|
+
`@open-mercato/test-package@file:${fixtureModulePackage}`,
|
|
155
|
+
"--eject"
|
|
156
|
+
],
|
|
157
|
+
appDir
|
|
158
|
+
);
|
|
159
|
+
const modulesSource = readFile(path.join(appDir, "src", "modules.ts"));
|
|
160
|
+
const cssSource = readFile(path.join(appDir, ".mercato", "generated", "module-package-sources.css"));
|
|
161
|
+
expect(modulesSource).toContain("{ id: 'test_package', from: '@app' }");
|
|
162
|
+
expect(fs.existsSync(path.join(appDir, "src", "modules", "test_package", "index.ts"))).toBe(true);
|
|
163
|
+
expect(cssSource).toBe("");
|
|
164
|
+
} finally {
|
|
165
|
+
fs.rmSync(appDir, { recursive: true, force: true });
|
|
166
|
+
}
|
|
167
|
+
});
|
|
168
|
+
test("module enable supports package-backed and ejected flows plus both eject entrypoints", () => {
|
|
169
|
+
const appDir = fs.mkdtempSync(path.join(os.tmpdir(), "mercato-cli-standalone-eject-"));
|
|
170
|
+
try {
|
|
171
|
+
createStandaloneFixture(appDir);
|
|
172
|
+
runCommand(yarnBinary(), ["install"], appDir);
|
|
173
|
+
runCommand(
|
|
174
|
+
yarnBinary(),
|
|
175
|
+
["add", `@open-mercato/test-package@file:${fixtureModulePackage}`],
|
|
176
|
+
appDir
|
|
177
|
+
);
|
|
178
|
+
runMercato(["module", "enable", "@open-mercato/test-package"], appDir);
|
|
179
|
+
expect(readFile(path.join(appDir, "src", "modules.ts"))).toContain(
|
|
180
|
+
"{ id: 'test_package', from: '@open-mercato/test-package' }"
|
|
181
|
+
);
|
|
182
|
+
writeFile(path.join(appDir, "src", "modules.ts"), "export const enabledModules = []\n");
|
|
183
|
+
fs.rmSync(path.join(appDir, "src", "modules", "test_package"), { recursive: true, force: true });
|
|
184
|
+
runMercato(["module", "enable", "@open-mercato/test-package", "--eject"], appDir);
|
|
185
|
+
expect(readFile(path.join(appDir, "src", "modules.ts"))).toContain("{ id: 'test_package', from: '@app' }");
|
|
186
|
+
expect(fs.existsSync(path.join(appDir, "src", "modules", "test_package", "index.ts"))).toBe(true);
|
|
187
|
+
expect(readFile(path.join(appDir, ".mercato", "generated", "module-package-sources.css"))).toBe("");
|
|
188
|
+
writeFile(path.join(appDir, "src", "modules.ts"), "export const enabledModules = [{ id: 'test_package', from: '@open-mercato/test-package' }]\n");
|
|
189
|
+
fs.rmSync(path.join(appDir, "src", "modules", "test_package"), { recursive: true, force: true });
|
|
190
|
+
runMercato(["module", "eject", "test_package"], appDir);
|
|
191
|
+
expect(readFile(path.join(appDir, "src", "modules.ts"))).toContain("{ id: 'test_package', from: '@app' }");
|
|
192
|
+
writeFile(path.join(appDir, "src", "modules.ts"), "export const enabledModules = [{ id: 'test_package', from: '@open-mercato/test-package' }]\n");
|
|
193
|
+
fs.rmSync(path.join(appDir, "src", "modules", "test_package"), { recursive: true, force: true });
|
|
194
|
+
runMercato(["eject", "test_package"], appDir);
|
|
195
|
+
expect(readFile(path.join(appDir, "src", "modules.ts"))).toContain("{ id: 'test_package', from: '@app' }");
|
|
196
|
+
} finally {
|
|
197
|
+
fs.rmSync(appDir, { recursive: true, force: true });
|
|
198
|
+
}
|
|
199
|
+
});
|
|
200
|
+
});
|
|
201
|
+
//# sourceMappingURL=TC-INT-007.spec.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/lib/__integration__/TC-INT-007.spec.ts"],
|
|
4
|
+
"sourcesContent": ["import { expect, test } from '@playwright/test'\nimport { execFileSync } from 'node:child_process'\nimport fs from 'node:fs'\nimport os from 'node:os'\nimport path from 'node:path'\nimport { fileURLToPath } from 'node:url'\n\nconst __dirname = path.dirname(fileURLToPath(import.meta.url))\nconst repoRoot = path.resolve(__dirname, '..', '..', '..', '..', '..')\nconst cliBin = path.join(repoRoot, 'packages', 'cli', 'dist', 'bin.js')\nconst fixtureModulePackage = path.join(\n repoRoot,\n 'packages',\n 'cli',\n 'src',\n 'lib',\n '__fixtures__',\n 'official-module-package',\n)\n\nfunction yarnBinary(): string {\n return process.platform === 'win32' ? 'yarn.cmd' : 'yarn'\n}\n\nfunction runCommand(command: string, args: string[], cwd: string): string {\n const yarnCacheFolder = path.join(cwd, '.yarn', 'cache')\n return execFileSync(command, args, {\n cwd,\n encoding: 'utf8',\n env: {\n ...process.env,\n FORCE_COLOR: '0',\n NODE_NO_WARNINGS: '1',\n YARN_CACHE_FOLDER: yarnCacheFolder,\n YARN_ENABLE_GLOBAL_CACHE: '0',\n YARN_ENABLE_IMMUTABLE_INSTALLS: '0',\n YARN_NODE_LINKER: 'node-modules',\n },\n })\n}\n\nfunction runMercato(args: string[], cwd: string): string {\n return runCommand(process.execPath, [cliBin, ...args], cwd)\n}\n\nfunction writeFile(filePath: string, content: string): void {\n fs.mkdirSync(path.dirname(filePath), { recursive: true })\n fs.writeFileSync(filePath, content)\n}\n\nfunction createCoreWorkspacePackage(rootDir: string, relativeDir: string): string {\n const coreDir = path.join(rootDir, relativeDir)\n writeFile(\n path.join(coreDir, 'package.json'),\n JSON.stringify(\n {\n name: '@open-mercato/core',\n version: '0.4.7',\n type: 'module',\n },\n null,\n 2,\n ),\n )\n return coreDir\n}\n\nfunction createMonorepoFixture(rootDir: string): string {\n writeFile(\n path.join(rootDir, 'package.json'),\n JSON.stringify(\n {\n name: 'cli-module-monorepo-fixture',\n private: true,\n workspaces: ['apps/*', 'packages/*'],\n },\n null,\n 2,\n ),\n )\n writeFile(\n path.join(rootDir, '.yarnrc.yml'),\n ['nodeLinker: node-modules', 'enableGlobalCache: false', 'cacheFolder: ./.yarn/cache', ''].join('\\n'),\n )\n createCoreWorkspacePackage(rootDir, path.join('packages', 'core'))\n\n const appDir = path.join(rootDir, 'apps', 'mercato')\n writeFile(\n path.join(appDir, 'package.json'),\n JSON.stringify(\n {\n name: '@open-mercato/app',\n version: '0.0.0',\n private: true,\n },\n null,\n 2,\n ),\n )\n writeFile(path.join(appDir, 'src', 'modules.ts'), 'export const enabledModules = []\\n')\n return appDir\n}\n\nfunction createStandaloneFixture(rootDir: string): string {\n writeFile(\n path.join(rootDir, '.yarnrc.yml'),\n ['nodeLinker: node-modules', 'enableGlobalCache: false', 'cacheFolder: ./.yarn/cache', ''].join('\\n'),\n )\n createCoreWorkspacePackage(rootDir, path.join('vendor', 'core'))\n writeFile(\n path.join(rootDir, 'package.json'),\n JSON.stringify(\n {\n name: 'cli-module-standalone-fixture',\n private: true,\n dependencies: {\n '@open-mercato/core': 'file:./vendor/core',\n },\n },\n null,\n 2,\n ),\n )\n writeFile(path.join(rootDir, 'src', 'modules.ts'), 'export const enabledModules = []\\n')\n return rootDir\n}\n\nfunction readFile(filePath: string): string {\n return fs.readFileSync(filePath, 'utf8')\n}\n\ntest.describe('TC-INT-007: CLI official module install and eject flows', () => {\n test('module add installs and registers a package-backed module in a monorepo app', () => {\n const rootDir = fs.mkdtempSync(path.join(os.tmpdir(), 'mercato-cli-monorepo-'))\n\n try {\n const appDir = createMonorepoFixture(rootDir)\n runCommand(yarnBinary(), ['install'], rootDir)\n\n runMercato(\n [\n 'module',\n 'add',\n `@open-mercato/test-package@file:${fixtureModulePackage}`,\n ],\n rootDir,\n )\n\n const modulesSource = readFile(path.join(appDir, 'src', 'modules.ts'))\n const cssSource = readFile(path.join(appDir, '.mercato', 'generated', 'module-package-sources.css'))\n const appPackageJson = JSON.parse(readFile(path.join(appDir, 'package.json'))) as {\n dependencies?: Record<string, string>\n }\n\n expect(modulesSource).toContain(\"{ id: 'test_package', from: '@open-mercato/test-package' }\")\n expect(cssSource).toContain('node_modules/@open-mercato/test-package/src/**/*.{ts,tsx}')\n expect(appPackageJson.dependencies?.['@open-mercato/test-package']).toBeTruthy()\n } finally {\n fs.rmSync(rootDir, { recursive: true, force: true })\n }\n })\n\n test('module add --eject copies module source and omits package CSS entries', () => {\n const appDir = fs.mkdtempSync(path.join(os.tmpdir(), 'mercato-cli-standalone-source-'))\n\n try {\n createStandaloneFixture(appDir)\n runCommand(yarnBinary(), ['install'], appDir)\n\n runMercato(\n [\n 'module',\n 'add',\n `@open-mercato/test-package@file:${fixtureModulePackage}`,\n '--eject',\n ],\n appDir,\n )\n\n const modulesSource = readFile(path.join(appDir, 'src', 'modules.ts'))\n const cssSource = readFile(path.join(appDir, '.mercato', 'generated', 'module-package-sources.css'))\n\n expect(modulesSource).toContain(\"{ id: 'test_package', from: '@app' }\")\n expect(fs.existsSync(path.join(appDir, 'src', 'modules', 'test_package', 'index.ts'))).toBe(true)\n expect(cssSource).toBe('')\n } finally {\n fs.rmSync(appDir, { recursive: true, force: true })\n }\n })\n\n test('module enable supports package-backed and ejected flows plus both eject entrypoints', () => {\n const appDir = fs.mkdtempSync(path.join(os.tmpdir(), 'mercato-cli-standalone-eject-'))\n\n try {\n createStandaloneFixture(appDir)\n runCommand(yarnBinary(), ['install'], appDir)\n runCommand(\n yarnBinary(),\n ['add', `@open-mercato/test-package@file:${fixtureModulePackage}`],\n appDir,\n )\n\n runMercato(['module', 'enable', '@open-mercato/test-package'], appDir)\n expect(readFile(path.join(appDir, 'src', 'modules.ts'))).toContain(\n \"{ id: 'test_package', from: '@open-mercato/test-package' }\",\n )\n\n writeFile(path.join(appDir, 'src', 'modules.ts'), 'export const enabledModules = []\\n')\n fs.rmSync(path.join(appDir, 'src', 'modules', 'test_package'), { recursive: true, force: true })\n runMercato(['module', 'enable', '@open-mercato/test-package', '--eject'], appDir)\n expect(readFile(path.join(appDir, 'src', 'modules.ts'))).toContain(\"{ id: 'test_package', from: '@app' }\")\n expect(fs.existsSync(path.join(appDir, 'src', 'modules', 'test_package', 'index.ts'))).toBe(true)\n expect(readFile(path.join(appDir, '.mercato', 'generated', 'module-package-sources.css'))).toBe('')\n\n writeFile(path.join(appDir, 'src', 'modules.ts'), \"export const enabledModules = [{ id: 'test_package', from: '@open-mercato/test-package' }]\\n\")\n fs.rmSync(path.join(appDir, 'src', 'modules', 'test_package'), { recursive: true, force: true })\n runMercato(['module', 'eject', 'test_package'], appDir)\n expect(readFile(path.join(appDir, 'src', 'modules.ts'))).toContain(\"{ id: 'test_package', from: '@app' }\")\n\n writeFile(path.join(appDir, 'src', 'modules.ts'), \"export const enabledModules = [{ id: 'test_package', from: '@open-mercato/test-package' }]\\n\")\n fs.rmSync(path.join(appDir, 'src', 'modules', 'test_package'), { recursive: true, force: true })\n runMercato(['eject', 'test_package'], appDir)\n expect(readFile(path.join(appDir, 'src', 'modules.ts'))).toContain(\"{ id: 'test_package', from: '@app' }\")\n } finally {\n fs.rmSync(appDir, { recursive: true, force: true })\n }\n })\n})\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,QAAQ,YAAY;AAC7B,SAAS,oBAAoB;AAC7B,OAAO,QAAQ;AACf,OAAO,QAAQ;AACf,OAAO,UAAU;AACjB,SAAS,qBAAqB;AAE9B,MAAM,YAAY,KAAK,QAAQ,cAAc,YAAY,GAAG,CAAC;AAC7D,MAAM,WAAW,KAAK,QAAQ,WAAW,MAAM,MAAM,MAAM,MAAM,IAAI;AACrE,MAAM,SAAS,KAAK,KAAK,UAAU,YAAY,OAAO,QAAQ,QAAQ;AACtE,MAAM,uBAAuB,KAAK;AAAA,EAChC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,SAAS,aAAqB;AAC5B,SAAO,QAAQ,aAAa,UAAU,aAAa;AACrD;AAEA,SAAS,WAAW,SAAiB,MAAgB,KAAqB;AACxE,QAAM,kBAAkB,KAAK,KAAK,KAAK,SAAS,OAAO;AACvD,SAAO,aAAa,SAAS,MAAM;AAAA,IACjC;AAAA,IACA,UAAU;AAAA,IACV,KAAK;AAAA,MACH,GAAG,QAAQ;AAAA,MACX,aAAa;AAAA,MACb,kBAAkB;AAAA,MAClB,mBAAmB;AAAA,MACnB,0BAA0B;AAAA,MAC1B,gCAAgC;AAAA,MAChC,kBAAkB;AAAA,IACpB;AAAA,EACF,CAAC;AACH;AAEA,SAAS,WAAW,MAAgB,KAAqB;AACvD,SAAO,WAAW,QAAQ,UAAU,CAAC,QAAQ,GAAG,IAAI,GAAG,GAAG;AAC5D;AAEA,SAAS,UAAU,UAAkB,SAAuB;AAC1D,KAAG,UAAU,KAAK,QAAQ,QAAQ,GAAG,EAAE,WAAW,KAAK,CAAC;AACxD,KAAG,cAAc,UAAU,OAAO;AACpC;AAEA,SAAS,2BAA2B,SAAiB,aAA6B;AAChF,QAAM,UAAU,KAAK,KAAK,SAAS,WAAW;AAC9C;AAAA,IACE,KAAK,KAAK,SAAS,cAAc;AAAA,IACjC,KAAK;AAAA,MACH;AAAA,QACE,MAAM;AAAA,QACN,SAAS;AAAA,QACT,MAAM;AAAA,MACR;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,sBAAsB,SAAyB;AACtD;AAAA,IACE,KAAK,KAAK,SAAS,cAAc;AAAA,IACjC,KAAK;AAAA,MACH;AAAA,QACE,MAAM;AAAA,QACN,SAAS;AAAA,QACT,YAAY,CAAC,UAAU,YAAY;AAAA,MACrC;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACA;AAAA,IACE,KAAK,KAAK,SAAS,aAAa;AAAA,IAChC,CAAC,4BAA4B,4BAA4B,8BAA8B,EAAE,EAAE,KAAK,IAAI;AAAA,EACtG;AACA,6BAA2B,SAAS,KAAK,KAAK,YAAY,MAAM,CAAC;AAEjE,QAAM,SAAS,KAAK,KAAK,SAAS,QAAQ,SAAS;AACnD;AAAA,IACE,KAAK,KAAK,QAAQ,cAAc;AAAA,IAChC,KAAK;AAAA,MACH;AAAA,QACE,MAAM;AAAA,QACN,SAAS;AAAA,QACT,SAAS;AAAA,MACX;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACA,YAAU,KAAK,KAAK,QAAQ,OAAO,YAAY,GAAG,oCAAoC;AACtF,SAAO;AACT;AAEA,SAAS,wBAAwB,SAAyB;AACxD;AAAA,IACE,KAAK,KAAK,SAAS,aAAa;AAAA,IAChC,CAAC,4BAA4B,4BAA4B,8BAA8B,EAAE,EAAE,KAAK,IAAI;AAAA,EACtG;AACA,6BAA2B,SAAS,KAAK,KAAK,UAAU,MAAM,CAAC;AAC/D;AAAA,IACE,KAAK,KAAK,SAAS,cAAc;AAAA,IACjC,KAAK;AAAA,MACH;AAAA,QACE,MAAM;AAAA,QACN,SAAS;AAAA,QACT,cAAc;AAAA,UACZ,sBAAsB;AAAA,QACxB;AAAA,MACF;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACA,YAAU,KAAK,KAAK,SAAS,OAAO,YAAY,GAAG,oCAAoC;AACvF,SAAO;AACT;AAEA,SAAS,SAAS,UAA0B;AAC1C,SAAO,GAAG,aAAa,UAAU,MAAM;AACzC;AAEA,KAAK,SAAS,2DAA2D,MAAM;AAC7E,OAAK,+EAA+E,MAAM;AACxF,UAAM,UAAU,GAAG,YAAY,KAAK,KAAK,GAAG,OAAO,GAAG,uBAAuB,CAAC;AAE9E,QAAI;AACF,YAAM,SAAS,sBAAsB,OAAO;AAC5C,iBAAW,WAAW,GAAG,CAAC,SAAS,GAAG,OAAO;AAE7C;AAAA,QACE;AAAA,UACE;AAAA,UACA;AAAA,UACA,mCAAmC,oBAAoB;AAAA,QACzD;AAAA,QACA;AAAA,MACF;AAEA,YAAM,gBAAgB,SAAS,KAAK,KAAK,QAAQ,OAAO,YAAY,CAAC;AACrE,YAAM,YAAY,SAAS,KAAK,KAAK,QAAQ,YAAY,aAAa,4BAA4B,CAAC;AACnG,YAAM,iBAAiB,KAAK,MAAM,SAAS,KAAK,KAAK,QAAQ,cAAc,CAAC,CAAC;AAI7E,aAAO,aAAa,EAAE,UAAU,4DAA4D;AAC5F,aAAO,SAAS,EAAE,UAAU,2DAA2D;AACvF,aAAO,eAAe,eAAe,4BAA4B,CAAC,EAAE,WAAW;AAAA,IACjF,UAAE;AACA,SAAG,OAAO,SAAS,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC;AAAA,IACrD;AAAA,EACF,CAAC;AAED,OAAK,yEAAyE,MAAM;AAClF,UAAM,SAAS,GAAG,YAAY,KAAK,KAAK,GAAG,OAAO,GAAG,gCAAgC,CAAC;AAEtF,QAAI;AACF,8BAAwB,MAAM;AAC9B,iBAAW,WAAW,GAAG,CAAC,SAAS,GAAG,MAAM;AAE5C;AAAA,QACE;AAAA,UACE;AAAA,UACA;AAAA,UACA,mCAAmC,oBAAoB;AAAA,UACvD;AAAA,QACF;AAAA,QACA;AAAA,MACF;AAEA,YAAM,gBAAgB,SAAS,KAAK,KAAK,QAAQ,OAAO,YAAY,CAAC;AACrE,YAAM,YAAY,SAAS,KAAK,KAAK,QAAQ,YAAY,aAAa,4BAA4B,CAAC;AAEnG,aAAO,aAAa,EAAE,UAAU,sCAAsC;AACtE,aAAO,GAAG,WAAW,KAAK,KAAK,QAAQ,OAAO,WAAW,gBAAgB,UAAU,CAAC,CAAC,EAAE,KAAK,IAAI;AAChG,aAAO,SAAS,EAAE,KAAK,EAAE;AAAA,IAC3B,UAAE;AACA,SAAG,OAAO,QAAQ,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC;AAAA,IACpD;AAAA,EACF,CAAC;AAED,OAAK,uFAAuF,MAAM;AAChG,UAAM,SAAS,GAAG,YAAY,KAAK,KAAK,GAAG,OAAO,GAAG,+BAA+B,CAAC;AAErF,QAAI;AACF,8BAAwB,MAAM;AAC9B,iBAAW,WAAW,GAAG,CAAC,SAAS,GAAG,MAAM;AAC5C;AAAA,QACE,WAAW;AAAA,QACX,CAAC,OAAO,mCAAmC,oBAAoB,EAAE;AAAA,QACjE;AAAA,MACF;AAEA,iBAAW,CAAC,UAAU,UAAU,4BAA4B,GAAG,MAAM;AACrE,aAAO,SAAS,KAAK,KAAK,QAAQ,OAAO,YAAY,CAAC,CAAC,EAAE;AAAA,QACvD;AAAA,MACF;AAEA,gBAAU,KAAK,KAAK,QAAQ,OAAO,YAAY,GAAG,oCAAoC;AACtF,SAAG,OAAO,KAAK,KAAK,QAAQ,OAAO,WAAW,cAAc,GAAG,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC;AAC/F,iBAAW,CAAC,UAAU,UAAU,8BAA8B,SAAS,GAAG,MAAM;AAChF,aAAO,SAAS,KAAK,KAAK,QAAQ,OAAO,YAAY,CAAC,CAAC,EAAE,UAAU,sCAAsC;AACzG,aAAO,GAAG,WAAW,KAAK,KAAK,QAAQ,OAAO,WAAW,gBAAgB,UAAU,CAAC,CAAC,EAAE,KAAK,IAAI;AAChG,aAAO,SAAS,KAAK,KAAK,QAAQ,YAAY,aAAa,4BAA4B,CAAC,CAAC,EAAE,KAAK,EAAE;AAElG,gBAAU,KAAK,KAAK,QAAQ,OAAO,YAAY,GAAG,8FAA8F;AAChJ,SAAG,OAAO,KAAK,KAAK,QAAQ,OAAO,WAAW,cAAc,GAAG,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC;AAC/F,iBAAW,CAAC,UAAU,SAAS,cAAc,GAAG,MAAM;AACtD,aAAO,SAAS,KAAK,KAAK,QAAQ,OAAO,YAAY,CAAC,CAAC,EAAE,UAAU,sCAAsC;AAEzG,gBAAU,KAAK,KAAK,QAAQ,OAAO,YAAY,GAAG,8FAA8F;AAChJ,SAAG,OAAO,KAAK,KAAK,QAAQ,OAAO,WAAW,cAAc,GAAG,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC;AAC/F,iBAAW,CAAC,SAAS,cAAc,GAAG,MAAM;AAC5C,aAAO,SAAS,KAAK,KAAK,QAAQ,OAAO,YAAY,CAAC,CAAC,EAAE,UAAU,sCAAsC;AAAA,IAC3G,UAAE;AACA,SAAG,OAAO,QAAQ,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC;AAAA,IACpD;AAAA,EACF,CAAC;AACH,CAAC;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import dotenv from "dotenv";
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
const DEV_ENV_PRIORITY = [
|
|
5
|
+
".env",
|
|
6
|
+
".env.development",
|
|
7
|
+
".env.local",
|
|
8
|
+
".env.development.local"
|
|
9
|
+
];
|
|
10
|
+
function resolveDevEnvFilePaths(appDir) {
|
|
11
|
+
return DEV_ENV_PRIORITY.map((fileName) => path.join(appDir, fileName));
|
|
12
|
+
}
|
|
13
|
+
function createDevEnvReloader(appDir, environment = process.env, baseEnvironmentEntries = Object.entries(environment)) {
|
|
14
|
+
const baseEnvironment = new Map(
|
|
15
|
+
Array.from(baseEnvironmentEntries, ([key, value]) => [key, value])
|
|
16
|
+
);
|
|
17
|
+
const managedKeys = /* @__PURE__ */ new Set();
|
|
18
|
+
const envFilePaths = resolveDevEnvFilePaths(appDir);
|
|
19
|
+
const resetManagedKeys = () => {
|
|
20
|
+
for (const key of managedKeys) {
|
|
21
|
+
const baseValue = baseEnvironment.get(key);
|
|
22
|
+
if (baseValue === void 0) {
|
|
23
|
+
delete environment[key];
|
|
24
|
+
} else {
|
|
25
|
+
environment[key] = baseValue;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
managedKeys.clear();
|
|
29
|
+
};
|
|
30
|
+
const reload = () => {
|
|
31
|
+
resetManagedKeys();
|
|
32
|
+
for (const envFilePath of envFilePaths) {
|
|
33
|
+
if (!fs.existsSync(envFilePath)) continue;
|
|
34
|
+
const parsed = dotenv.parse(fs.readFileSync(envFilePath));
|
|
35
|
+
for (const [key, value] of Object.entries(parsed)) {
|
|
36
|
+
if (baseEnvironment.has(key) && baseEnvironment.get(key) !== void 0) {
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
environment[key] = value;
|
|
40
|
+
managedKeys.add(key);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
return {
|
|
45
|
+
reload,
|
|
46
|
+
getWatchedFiles: () => [...envFilePaths]
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
function watchDevEnvFiles(appDir, onChange, options = {}) {
|
|
50
|
+
const debounceMs = options.debounceMs ?? 250;
|
|
51
|
+
const envFilePaths = resolveDevEnvFilePaths(appDir);
|
|
52
|
+
const timers = /* @__PURE__ */ new Map();
|
|
53
|
+
const watchers = envFilePaths.map((envFilePath) => {
|
|
54
|
+
const watchDir = path.dirname(envFilePath);
|
|
55
|
+
const watchFileName = path.basename(envFilePath);
|
|
56
|
+
if (!fs.existsSync(watchDir)) return null;
|
|
57
|
+
try {
|
|
58
|
+
return fs.watch(watchDir, (eventType, fileName) => {
|
|
59
|
+
if (eventType !== "change" && eventType !== "rename") return;
|
|
60
|
+
if (String(fileName ?? "") !== watchFileName) return;
|
|
61
|
+
const existingTimer = timers.get(envFilePath);
|
|
62
|
+
if (existingTimer) {
|
|
63
|
+
clearTimeout(existingTimer);
|
|
64
|
+
}
|
|
65
|
+
timers.set(envFilePath, setTimeout(() => {
|
|
66
|
+
timers.delete(envFilePath);
|
|
67
|
+
onChange(envFilePath);
|
|
68
|
+
}, debounceMs));
|
|
69
|
+
});
|
|
70
|
+
} catch {
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
}).filter((watcher) => watcher !== null);
|
|
74
|
+
return () => {
|
|
75
|
+
for (const timer of timers.values()) {
|
|
76
|
+
clearTimeout(timer);
|
|
77
|
+
}
|
|
78
|
+
timers.clear();
|
|
79
|
+
for (const watcher of watchers) {
|
|
80
|
+
watcher.close();
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
export {
|
|
85
|
+
createDevEnvReloader,
|
|
86
|
+
resolveDevEnvFilePaths,
|
|
87
|
+
watchDevEnvFiles
|
|
88
|
+
};
|
|
89
|
+
//# sourceMappingURL=dev-env-reload.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/lib/dev-env-reload.ts"],
|
|
4
|
+
"sourcesContent": ["import dotenv from 'dotenv'\nimport fs from 'node:fs'\nimport path from 'node:path'\n\nconst DEV_ENV_PRIORITY = [\n '.env',\n '.env.development',\n '.env.local',\n '.env.development.local',\n] as const\n\nexport type DevEnvReloader = {\n reload: () => void\n getWatchedFiles: () => string[]\n}\n\nexport function resolveDevEnvFilePaths(appDir: string): string[] {\n return DEV_ENV_PRIORITY.map((fileName) => path.join(appDir, fileName))\n}\n\nexport function createDevEnvReloader(\n appDir: string,\n environment: NodeJS.ProcessEnv = process.env,\n baseEnvironmentEntries: Iterable<[string, string | undefined]> = Object.entries(environment),\n): DevEnvReloader {\n const baseEnvironment = new Map<string, string | undefined>(\n Array.from(baseEnvironmentEntries, ([key, value]) => [key, value]),\n )\n const managedKeys = new Set<string>()\n const envFilePaths = resolveDevEnvFilePaths(appDir)\n\n const resetManagedKeys = () => {\n for (const key of managedKeys) {\n const baseValue = baseEnvironment.get(key)\n if (baseValue === undefined) {\n delete environment[key]\n } else {\n environment[key] = baseValue\n }\n }\n managedKeys.clear()\n }\n\n const reload = () => {\n resetManagedKeys()\n\n for (const envFilePath of envFilePaths) {\n if (!fs.existsSync(envFilePath)) continue\n\n const parsed = dotenv.parse(fs.readFileSync(envFilePath))\n for (const [key, value] of Object.entries(parsed)) {\n if (baseEnvironment.has(key) && baseEnvironment.get(key) !== undefined) {\n continue\n }\n environment[key] = value\n managedKeys.add(key)\n }\n }\n }\n\n return {\n reload,\n getWatchedFiles: () => [...envFilePaths],\n }\n}\n\nexport function watchDevEnvFiles(\n appDir: string,\n onChange: (filePath: string) => void,\n options: { debounceMs?: number } = {},\n): () => void {\n const debounceMs = options.debounceMs ?? 250\n const envFilePaths = resolveDevEnvFilePaths(appDir)\n const timers = new Map<string, NodeJS.Timeout>()\n const watchers = envFilePaths.map((envFilePath) => {\n const watchDir = path.dirname(envFilePath)\n const watchFileName = path.basename(envFilePath)\n\n if (!fs.existsSync(watchDir)) return null\n\n try {\n return fs.watch(watchDir, (eventType, fileName) => {\n if (eventType !== 'change' && eventType !== 'rename') return\n if (String(fileName ?? '') !== watchFileName) return\n\n const existingTimer = timers.get(envFilePath)\n if (existingTimer) {\n clearTimeout(existingTimer)\n }\n\n timers.set(envFilePath, setTimeout(() => {\n timers.delete(envFilePath)\n onChange(envFilePath)\n }, debounceMs))\n })\n } catch {\n return null\n }\n }).filter((watcher): watcher is fs.FSWatcher => watcher !== null)\n\n return () => {\n for (const timer of timers.values()) {\n clearTimeout(timer)\n }\n timers.clear()\n for (const watcher of watchers) {\n watcher.close()\n }\n }\n}\n"],
|
|
5
|
+
"mappings": "AAAA,OAAO,YAAY;AACnB,OAAO,QAAQ;AACf,OAAO,UAAU;AAEjB,MAAM,mBAAmB;AAAA,EACvB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAOO,SAAS,uBAAuB,QAA0B;AAC/D,SAAO,iBAAiB,IAAI,CAAC,aAAa,KAAK,KAAK,QAAQ,QAAQ,CAAC;AACvE;AAEO,SAAS,qBACd,QACA,cAAiC,QAAQ,KACzC,yBAAiE,OAAO,QAAQ,WAAW,GAC3E;AAChB,QAAM,kBAAkB,IAAI;AAAA,IAC1B,MAAM,KAAK,wBAAwB,CAAC,CAAC,KAAK,KAAK,MAAM,CAAC,KAAK,KAAK,CAAC;AAAA,EACnE;AACA,QAAM,cAAc,oBAAI,IAAY;AACpC,QAAM,eAAe,uBAAuB,MAAM;AAElD,QAAM,mBAAmB,MAAM;AAC7B,eAAW,OAAO,aAAa;AAC7B,YAAM,YAAY,gBAAgB,IAAI,GAAG;AACzC,UAAI,cAAc,QAAW;AAC3B,eAAO,YAAY,GAAG;AAAA,MACxB,OAAO;AACL,oBAAY,GAAG,IAAI;AAAA,MACrB;AAAA,IACF;AACA,gBAAY,MAAM;AAAA,EACpB;AAEA,QAAM,SAAS,MAAM;AACnB,qBAAiB;AAEjB,eAAW,eAAe,cAAc;AACtC,UAAI,CAAC,GAAG,WAAW,WAAW,EAAG;AAEjC,YAAM,SAAS,OAAO,MAAM,GAAG,aAAa,WAAW,CAAC;AACxD,iBAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,MAAM,GAAG;AACjD,YAAI,gBAAgB,IAAI,GAAG,KAAK,gBAAgB,IAAI,GAAG,MAAM,QAAW;AACtE;AAAA,QACF;AACA,oBAAY,GAAG,IAAI;AACnB,oBAAY,IAAI,GAAG;AAAA,MACrB;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AAAA,IACL;AAAA,IACA,iBAAiB,MAAM,CAAC,GAAG,YAAY;AAAA,EACzC;AACF;AAEO,SAAS,iBACd,QACA,UACA,UAAmC,CAAC,GACxB;AACZ,QAAM,aAAa,QAAQ,cAAc;AACzC,QAAM,eAAe,uBAAuB,MAAM;AAClD,QAAM,SAAS,oBAAI,IAA4B;AAC/C,QAAM,WAAW,aAAa,IAAI,CAAC,gBAAgB;AACjD,UAAM,WAAW,KAAK,QAAQ,WAAW;AACzC,UAAM,gBAAgB,KAAK,SAAS,WAAW;AAE/C,QAAI,CAAC,GAAG,WAAW,QAAQ,EAAG,QAAO;AAErC,QAAI;AACF,aAAO,GAAG,MAAM,UAAU,CAAC,WAAW,aAAa;AACjD,YAAI,cAAc,YAAY,cAAc,SAAU;AACtD,YAAI,OAAO,YAAY,EAAE,MAAM,cAAe;AAE9C,cAAM,gBAAgB,OAAO,IAAI,WAAW;AAC5C,YAAI,eAAe;AACjB,uBAAa,aAAa;AAAA,QAC5B;AAEA,eAAO,IAAI,aAAa,WAAW,MAAM;AACvC,iBAAO,OAAO,WAAW;AACzB,mBAAS,WAAW;AAAA,QACtB,GAAG,UAAU,CAAC;AAAA,MAChB,CAAC;AAAA,IACH,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF,CAAC,EAAE,OAAO,CAAC,YAAqC,YAAY,IAAI;AAEhE,SAAO,MAAM;AACX,eAAW,SAAS,OAAO,OAAO,GAAG;AACnC,mBAAa,KAAK;AAAA,IACpB;AACA,WAAO,MAAM;AACb,eAAW,WAAW,UAAU;AAC9B,cAAQ,MAAM;AAAA,IAChB;AAAA,EACF;AACF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
import { VariableDeclarationKind } from "ts-morph";
|
|
2
|
+
import {
|
|
3
|
+
arrayLiteral,
|
|
4
|
+
arrowFunction,
|
|
5
|
+
binaryExpression,
|
|
6
|
+
identifier,
|
|
7
|
+
methodCall,
|
|
8
|
+
objectLiteral,
|
|
9
|
+
parenthesized,
|
|
10
|
+
propertyAccess,
|
|
11
|
+
writeValue
|
|
12
|
+
} from "../ast/index.js";
|
|
13
|
+
import {
|
|
14
|
+
emptyArray,
|
|
15
|
+
emptyObject,
|
|
16
|
+
moduleEntry,
|
|
17
|
+
namespaceFallback,
|
|
18
|
+
renderGeneratedTsSource
|
|
19
|
+
} from "./shared.js";
|
|
20
|
+
function createAiAgentsExtension() {
|
|
21
|
+
const imports = [];
|
|
22
|
+
const entries = [];
|
|
23
|
+
return {
|
|
24
|
+
id: "registry.ai-agents",
|
|
25
|
+
outputFiles: ["ai-agents.generated.ts"],
|
|
26
|
+
scanModule(ctx) {
|
|
27
|
+
ctx.processStandaloneConfig({
|
|
28
|
+
roots: ctx.roots,
|
|
29
|
+
imps: ctx.imps,
|
|
30
|
+
modId: ctx.moduleId,
|
|
31
|
+
relativePath: "ai-agents.ts",
|
|
32
|
+
prefix: "AI_AGENTS",
|
|
33
|
+
importIdRef: ctx.importIdRef,
|
|
34
|
+
standaloneImports: imports,
|
|
35
|
+
standaloneEntries: entries,
|
|
36
|
+
writeConfig: ({ importName, moduleId }) => moduleEntry(moduleId, [
|
|
37
|
+
{
|
|
38
|
+
name: "agents",
|
|
39
|
+
value: namespaceFallback({
|
|
40
|
+
importName,
|
|
41
|
+
members: ["aiAgents", "default"],
|
|
42
|
+
fallback: emptyArray(),
|
|
43
|
+
castType: "unknown[]"
|
|
44
|
+
})
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
name: "overrides",
|
|
48
|
+
value: namespaceFallback({
|
|
49
|
+
importName,
|
|
50
|
+
members: ["aiAgentOverrides"],
|
|
51
|
+
fallback: emptyObject(),
|
|
52
|
+
castType: "Record<string, unknown>"
|
|
53
|
+
})
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
name: "extensions",
|
|
57
|
+
value: namespaceFallback({
|
|
58
|
+
importName,
|
|
59
|
+
members: ["aiAgentExtensions"],
|
|
60
|
+
fallback: emptyArray(),
|
|
61
|
+
castType: "unknown[]"
|
|
62
|
+
})
|
|
63
|
+
}
|
|
64
|
+
])
|
|
65
|
+
});
|
|
66
|
+
},
|
|
67
|
+
generateOutput() {
|
|
68
|
+
const output = renderGeneratedTsSource({
|
|
69
|
+
fileName: "ai-agents.generated.ts",
|
|
70
|
+
imports,
|
|
71
|
+
build(sourceFile) {
|
|
72
|
+
sourceFile.addTypeAlias({
|
|
73
|
+
name: "AiAgentConfigEntry",
|
|
74
|
+
type: "{ moduleId: string; agents: unknown[]; overrides: Record<string, unknown>; extensions: unknown[] }"
|
|
75
|
+
});
|
|
76
|
+
sourceFile.addTypeAlias({
|
|
77
|
+
name: "AiAgentOverrideConfigEntry",
|
|
78
|
+
type: "{ moduleId: string; overrides: Record<string, unknown> }"
|
|
79
|
+
});
|
|
80
|
+
sourceFile.addTypeAlias({
|
|
81
|
+
name: "AiAgentExtensionConfigEntry",
|
|
82
|
+
type: "{ moduleId: string; extensions: unknown[] }"
|
|
83
|
+
});
|
|
84
|
+
sourceFile.addVariableStatement({
|
|
85
|
+
declarationKind: VariableDeclarationKind.Const,
|
|
86
|
+
declarations: [
|
|
87
|
+
{
|
|
88
|
+
name: "aiAgentConfigEntriesRaw",
|
|
89
|
+
type: "AiAgentConfigEntry[]",
|
|
90
|
+
initializer: arrayLiteral(entries, writeValue)
|
|
91
|
+
}
|
|
92
|
+
]
|
|
93
|
+
});
|
|
94
|
+
sourceFile.addVariableStatement({
|
|
95
|
+
declarationKind: VariableDeclarationKind.Const,
|
|
96
|
+
isExported: true,
|
|
97
|
+
declarations: [
|
|
98
|
+
{
|
|
99
|
+
name: "aiAgentConfigEntries",
|
|
100
|
+
type: "AiAgentConfigEntry[]",
|
|
101
|
+
initializer: methodCall(identifier("aiAgentConfigEntriesRaw"), "filter", [
|
|
102
|
+
arrowFunction({
|
|
103
|
+
parameters: ["entry"],
|
|
104
|
+
body: binaryExpression(propertyAccess(propertyAccess(identifier("entry"), "agents"), "length"), ">", 0)
|
|
105
|
+
})
|
|
106
|
+
])
|
|
107
|
+
}
|
|
108
|
+
]
|
|
109
|
+
});
|
|
110
|
+
sourceFile.addVariableStatement({
|
|
111
|
+
declarationKind: VariableDeclarationKind.Const,
|
|
112
|
+
isExported: true,
|
|
113
|
+
declarations: [
|
|
114
|
+
{
|
|
115
|
+
name: "aiAgentExtensionEntries",
|
|
116
|
+
type: "AiAgentExtensionConfigEntry[]",
|
|
117
|
+
initializer: methodCall(
|
|
118
|
+
methodCall(identifier("aiAgentConfigEntriesRaw"), "filter", [
|
|
119
|
+
arrowFunction({
|
|
120
|
+
parameters: ["entry"],
|
|
121
|
+
body: binaryExpression(propertyAccess(propertyAccess(identifier("entry"), "extensions"), "length"), ">", 0)
|
|
122
|
+
})
|
|
123
|
+
]),
|
|
124
|
+
"map",
|
|
125
|
+
[
|
|
126
|
+
arrowFunction({
|
|
127
|
+
parameters: ["entry"],
|
|
128
|
+
body: parenthesized(
|
|
129
|
+
objectLiteral([
|
|
130
|
+
{ name: "moduleId", value: propertyAccess(identifier("entry"), "moduleId") },
|
|
131
|
+
{ name: "extensions", value: propertyAccess(identifier("entry"), "extensions") }
|
|
132
|
+
])
|
|
133
|
+
)
|
|
134
|
+
})
|
|
135
|
+
]
|
|
136
|
+
)
|
|
137
|
+
}
|
|
138
|
+
]
|
|
139
|
+
});
|
|
140
|
+
sourceFile.addVariableStatement({
|
|
141
|
+
declarationKind: VariableDeclarationKind.Const,
|
|
142
|
+
isExported: true,
|
|
143
|
+
declarations: [
|
|
144
|
+
{
|
|
145
|
+
name: "allAiAgentExtensions",
|
|
146
|
+
initializer: methodCall(identifier("aiAgentExtensionEntries"), "flatMap", [
|
|
147
|
+
arrowFunction({
|
|
148
|
+
parameters: ["entry"],
|
|
149
|
+
body: propertyAccess(identifier("entry"), "extensions")
|
|
150
|
+
})
|
|
151
|
+
])
|
|
152
|
+
}
|
|
153
|
+
]
|
|
154
|
+
});
|
|
155
|
+
sourceFile.addVariableStatement({
|
|
156
|
+
declarationKind: VariableDeclarationKind.Const,
|
|
157
|
+
isExported: true,
|
|
158
|
+
declarations: [
|
|
159
|
+
{
|
|
160
|
+
name: "allAiAgents",
|
|
161
|
+
initializer: methodCall(identifier("aiAgentConfigEntries"), "flatMap", [
|
|
162
|
+
arrowFunction({
|
|
163
|
+
parameters: ["entry"],
|
|
164
|
+
body: propertyAccess(identifier("entry"), "agents")
|
|
165
|
+
})
|
|
166
|
+
])
|
|
167
|
+
}
|
|
168
|
+
]
|
|
169
|
+
});
|
|
170
|
+
sourceFile.addVariableStatement({
|
|
171
|
+
declarationKind: VariableDeclarationKind.Const,
|
|
172
|
+
isExported: true,
|
|
173
|
+
declarations: [
|
|
174
|
+
{
|
|
175
|
+
name: "aiAgentOverrideEntries",
|
|
176
|
+
type: "AiAgentOverrideConfigEntry[]",
|
|
177
|
+
initializer: methodCall(
|
|
178
|
+
methodCall(identifier("aiAgentConfigEntriesRaw"), "filter", [
|
|
179
|
+
arrowFunction({
|
|
180
|
+
parameters: ["entry"],
|
|
181
|
+
body: binaryExpression(
|
|
182
|
+
propertyAccess(
|
|
183
|
+
methodCall(identifier("Object"), "keys", [
|
|
184
|
+
propertyAccess(identifier("entry"), "overrides")
|
|
185
|
+
]),
|
|
186
|
+
"length"
|
|
187
|
+
),
|
|
188
|
+
">",
|
|
189
|
+
0
|
|
190
|
+
)
|
|
191
|
+
})
|
|
192
|
+
]),
|
|
193
|
+
"map",
|
|
194
|
+
[
|
|
195
|
+
arrowFunction({
|
|
196
|
+
parameters: ["entry"],
|
|
197
|
+
body: parenthesized(
|
|
198
|
+
objectLiteral([
|
|
199
|
+
{ name: "moduleId", value: propertyAccess(identifier("entry"), "moduleId") },
|
|
200
|
+
{ name: "overrides", value: propertyAccess(identifier("entry"), "overrides") }
|
|
201
|
+
])
|
|
202
|
+
)
|
|
203
|
+
})
|
|
204
|
+
]
|
|
205
|
+
)
|
|
206
|
+
}
|
|
207
|
+
]
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
});
|
|
211
|
+
return /* @__PURE__ */ new Map([["ai-agents.generated.ts", output]]);
|
|
212
|
+
}
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
export {
|
|
216
|
+
createAiAgentsExtension
|
|
217
|
+
};
|
|
218
|
+
//# sourceMappingURL=ai-agents.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/lib/generators/extensions/ai-agents.ts"],
|
|
4
|
+
"sourcesContent": ["import { VariableDeclarationKind, type WriterFunction } from 'ts-morph'\nimport type { GeneratorExtension } from '../extension'\nimport {\n arrayLiteral,\n arrowFunction,\n binaryExpression,\n identifier,\n methodCall,\n objectLiteral,\n parenthesized,\n propertyAccess,\n writeValue,\n} from '../ast'\nimport {\n emptyArray,\n emptyObject,\n moduleEntry,\n namespaceFallback,\n namespaceImportSpec,\n renderGeneratedTsSource,\n} from './shared'\n\n/**\n * Generator extension for `<module>/ai-agents.ts` files.\n *\n * Each module's `ai-agents.ts` may export both base agent contributions\n * (`aiAgents`), additive extensions for existing agents\n * (`aiAgentExtensions`), AND cross-module override declarations\n * (`aiAgentOverrides`). The generator scans the file once, emits the\n * configuration entry with all fields, and produces filtered\n * exports inside `ai-agents.generated.ts`:\n *\n * - `aiAgentConfigEntries` (entries that declare base agents)\n * - `aiAgentExtensionEntries` / `allAiAgentExtensions` (entries that append to agents)\n * - `aiAgentOverrideEntries` (entries that declare overrides)\n *\n * The runtime (`@open-mercato/ai-assistant`) reads\n * `aiAgentConfigEntries` to populate the agent registry,\n * `aiAgentOverrideEntries` to apply cross-module replacements, and\n * `allAiAgentExtensions` to append safe metadata after the base load. See spec\n * `.ai/specs/2026-04-30-ai-overrides-and-module-disable.md`.\n */\nexport function createAiAgentsExtension(): GeneratorExtension {\n const imports = [] as Array<ReturnType<typeof namespaceImportSpec>>\n const entries: WriterFunction[] = []\n\n return {\n id: 'registry.ai-agents',\n outputFiles: ['ai-agents.generated.ts'],\n scanModule(ctx) {\n ctx.processStandaloneConfig({\n roots: ctx.roots,\n imps: ctx.imps,\n modId: ctx.moduleId,\n relativePath: 'ai-agents.ts',\n prefix: 'AI_AGENTS',\n importIdRef: ctx.importIdRef,\n standaloneImports: imports,\n standaloneEntries: entries,\n writeConfig: ({ importName, moduleId }) =>\n moduleEntry(moduleId, [\n {\n name: 'agents',\n value: namespaceFallback({\n importName,\n members: ['aiAgents', 'default'],\n fallback: emptyArray(),\n castType: 'unknown[]',\n }),\n },\n {\n name: 'overrides',\n value: namespaceFallback({\n importName,\n members: ['aiAgentOverrides'],\n fallback: emptyObject(),\n castType: 'Record<string, unknown>',\n }),\n },\n {\n name: 'extensions',\n value: namespaceFallback({\n importName,\n members: ['aiAgentExtensions'],\n fallback: emptyArray(),\n castType: 'unknown[]',\n }),\n },\n ]),\n })\n },\n generateOutput() {\n const output = renderGeneratedTsSource({\n fileName: 'ai-agents.generated.ts',\n imports,\n build(sourceFile) {\n sourceFile.addTypeAlias({\n name: 'AiAgentConfigEntry',\n type: '{ moduleId: string; agents: unknown[]; overrides: Record<string, unknown>; extensions: unknown[] }',\n })\n sourceFile.addTypeAlias({\n name: 'AiAgentOverrideConfigEntry',\n type: '{ moduleId: string; overrides: Record<string, unknown> }',\n })\n sourceFile.addTypeAlias({\n name: 'AiAgentExtensionConfigEntry',\n type: '{ moduleId: string; extensions: unknown[] }',\n })\n sourceFile.addVariableStatement({\n declarationKind: VariableDeclarationKind.Const,\n declarations: [\n {\n name: 'aiAgentConfigEntriesRaw',\n type: 'AiAgentConfigEntry[]',\n initializer: arrayLiteral(entries, writeValue),\n },\n ],\n })\n sourceFile.addVariableStatement({\n declarationKind: VariableDeclarationKind.Const,\n isExported: true,\n declarations: [\n {\n name: 'aiAgentConfigEntries',\n type: 'AiAgentConfigEntry[]',\n initializer: methodCall(identifier('aiAgentConfigEntriesRaw'), 'filter', [\n arrowFunction({\n parameters: ['entry'],\n body: binaryExpression(propertyAccess(propertyAccess(identifier('entry'), 'agents'), 'length'), '>', 0),\n }),\n ]),\n },\n ],\n })\n sourceFile.addVariableStatement({\n declarationKind: VariableDeclarationKind.Const,\n isExported: true,\n declarations: [\n {\n name: 'aiAgentExtensionEntries',\n type: 'AiAgentExtensionConfigEntry[]',\n initializer: methodCall(\n methodCall(identifier('aiAgentConfigEntriesRaw'), 'filter', [\n arrowFunction({\n parameters: ['entry'],\n body: binaryExpression(propertyAccess(propertyAccess(identifier('entry'), 'extensions'), 'length'), '>', 0),\n }),\n ]),\n 'map',\n [\n arrowFunction({\n parameters: ['entry'],\n body: parenthesized(\n objectLiteral([\n { name: 'moduleId', value: propertyAccess(identifier('entry'), 'moduleId') },\n { name: 'extensions', value: propertyAccess(identifier('entry'), 'extensions') },\n ]),\n ),\n }),\n ],\n ),\n },\n ],\n })\n sourceFile.addVariableStatement({\n declarationKind: VariableDeclarationKind.Const,\n isExported: true,\n declarations: [\n {\n name: 'allAiAgentExtensions',\n initializer: methodCall(identifier('aiAgentExtensionEntries'), 'flatMap', [\n arrowFunction({\n parameters: ['entry'],\n body: propertyAccess(identifier('entry'), 'extensions'),\n }),\n ]),\n },\n ],\n })\n sourceFile.addVariableStatement({\n declarationKind: VariableDeclarationKind.Const,\n isExported: true,\n declarations: [\n {\n name: 'allAiAgents',\n initializer: methodCall(identifier('aiAgentConfigEntries'), 'flatMap', [\n arrowFunction({\n parameters: ['entry'],\n body: propertyAccess(identifier('entry'), 'agents'),\n }),\n ]),\n },\n ],\n })\n sourceFile.addVariableStatement({\n declarationKind: VariableDeclarationKind.Const,\n isExported: true,\n declarations: [\n {\n name: 'aiAgentOverrideEntries',\n type: 'AiAgentOverrideConfigEntry[]',\n initializer: methodCall(\n methodCall(identifier('aiAgentConfigEntriesRaw'), 'filter', [\n arrowFunction({\n parameters: ['entry'],\n body: binaryExpression(\n propertyAccess(\n methodCall(identifier('Object'), 'keys', [\n propertyAccess(identifier('entry'), 'overrides'),\n ]),\n 'length',\n ),\n '>',\n 0,\n ),\n }),\n ]),\n 'map',\n [\n arrowFunction({\n parameters: ['entry'],\n body: parenthesized(\n objectLiteral([\n { name: 'moduleId', value: propertyAccess(identifier('entry'), 'moduleId') },\n { name: 'overrides', value: propertyAccess(identifier('entry'), 'overrides') },\n ]),\n ),\n }),\n ],\n ),\n },\n ],\n })\n },\n })\n\n return new Map([['ai-agents.generated.ts', output]])\n },\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|