@akanjs/devkit 2.3.3-rc.1 → 2.3.4-rc.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -7,13 +7,7 @@ import { AkanAppConfig, AkanLibConfig } from "./akanConfig";
|
|
|
7
7
|
import type { DeepPartial, LibConfigResult } from "./types";
|
|
8
8
|
|
|
9
9
|
const akanPackageJson = JSON.parse(
|
|
10
|
-
fs.readFileSync(
|
|
11
|
-
path.join(
|
|
12
|
-
path.dirname(fileURLToPath(import.meta.url)),
|
|
13
|
-
"../../../akanjs/package.json",
|
|
14
|
-
),
|
|
15
|
-
"utf8",
|
|
16
|
-
),
|
|
10
|
+
fs.readFileSync(path.join(path.dirname(fileURLToPath(import.meta.url)), "../../../akanjs/package.json"), "utf8"),
|
|
17
11
|
) as PackageJson;
|
|
18
12
|
|
|
19
13
|
const packageJson: PackageJson = {
|
|
@@ -40,13 +34,7 @@ const baseDevEnv = {
|
|
|
40
34
|
|
|
41
35
|
describe("AkanAppConfig", () => {
|
|
42
36
|
test("applies defaults for route domains, i18n, image, mobile, and imports", () => {
|
|
43
|
-
const config = new AkanAppConfig(
|
|
44
|
-
app,
|
|
45
|
-
["shared"],
|
|
46
|
-
packageJson,
|
|
47
|
-
{},
|
|
48
|
-
baseDevEnv,
|
|
49
|
-
);
|
|
37
|
+
const config = new AkanAppConfig(app, ["shared"], packageJson, {}, baseDevEnv);
|
|
50
38
|
|
|
51
39
|
expect([...config.domains].sort()).toEqual([
|
|
52
40
|
"portal-debug.akanjs.com",
|
|
@@ -73,11 +61,7 @@ describe("AkanAppConfig", () => {
|
|
|
73
61
|
},
|
|
74
62
|
});
|
|
75
63
|
expect(config.barrelImports).toEqual(
|
|
76
|
-
expect.arrayContaining([
|
|
77
|
-
"@apps/portal/ui",
|
|
78
|
-
"@libs/shared/server",
|
|
79
|
-
"akanjs/common",
|
|
80
|
-
]),
|
|
64
|
+
expect.arrayContaining(["@apps/portal/ui", "@libs/shared/server", "akanjs/common", "akanjs/server"]),
|
|
81
65
|
);
|
|
82
66
|
expect(config.docker.content).toContain("ENV AKAN_PUBLIC_APP_NAME=portal");
|
|
83
67
|
expect(process.env.AKAN_PUBLIC_DEFAULT_LOCALE).toBe("en");
|
|
@@ -129,12 +113,7 @@ describe("AkanAppConfig", () => {
|
|
|
129
113
|
"admin.local",
|
|
130
114
|
"admin.main.local",
|
|
131
115
|
]);
|
|
132
|
-
expect([...config.branches].sort()).toEqual([
|
|
133
|
-
"debug",
|
|
134
|
-
"develop",
|
|
135
|
-
"main",
|
|
136
|
-
"qa",
|
|
137
|
-
]);
|
|
116
|
+
expect([...config.branches].sort()).toEqual(["debug", "develop", "main", "qa"]);
|
|
138
117
|
expect(config.i18n.defaultLocale).toBe("ko");
|
|
139
118
|
expect(config.images.qualities).toEqual([80, 90]);
|
|
140
119
|
expect(config.images.dangerouslyAllowSVG).toBe(true);
|
|
@@ -154,17 +133,9 @@ describe("AkanAppConfig", () => {
|
|
|
154
133
|
});
|
|
155
134
|
|
|
156
135
|
test("creates production package json and reports missing external versions", () => {
|
|
157
|
-
const config = new AkanAppConfig(
|
|
158
|
-
app,
|
|
159
|
-
[],
|
|
160
|
-
packageJson,
|
|
161
|
-
{ externalLibs: ["@external/runtime"] },
|
|
162
|
-
baseDevEnv,
|
|
163
|
-
);
|
|
136
|
+
const config = new AkanAppConfig(app, [], packageJson, { externalLibs: ["@external/runtime"] }, baseDevEnv);
|
|
164
137
|
|
|
165
|
-
expect(
|
|
166
|
-
config.getProductionPackageJson({ scripts: { start: "bun main.js" } }),
|
|
167
|
-
).toMatchObject({
|
|
138
|
+
expect(config.getProductionPackageJson({ scripts: { start: "bun main.js" } })).toMatchObject({
|
|
168
139
|
name: "portal",
|
|
169
140
|
main: "./main.js",
|
|
170
141
|
scripts: { start: "bun main.js" },
|
|
@@ -185,9 +156,7 @@ describe("AkanAppConfig", () => {
|
|
|
185
156
|
{ externalLibs: ["missing-lib"] },
|
|
186
157
|
baseDevEnv,
|
|
187
158
|
);
|
|
188
|
-
expect(() => brokenConfig.getProductionPackageJson()).toThrow(
|
|
189
|
-
"Dependency missing-lib not found",
|
|
190
|
-
);
|
|
159
|
+
expect(() => brokenConfig.getProductionPackageJson()).toThrow("Dependency missing-lib not found");
|
|
191
160
|
});
|
|
192
161
|
|
|
193
162
|
test("falls back to akanjs package versions for built-in runtime dependencies", () => {
|
|
@@ -213,8 +182,7 @@ describe("AkanAppConfig", () => {
|
|
|
213
182
|
expect(config.getProductionPackageJson().dependencies).toEqual({
|
|
214
183
|
react: runtimeDependencies.react,
|
|
215
184
|
"react-dom": runtimeDependencies["react-dom"],
|
|
216
|
-
"react-server-dom-webpack":
|
|
217
|
-
runtimeDependencies["react-server-dom-webpack"],
|
|
185
|
+
"react-server-dom-webpack": runtimeDependencies["react-server-dom-webpack"],
|
|
218
186
|
croner: runtimeDependencies.croner,
|
|
219
187
|
sharp: runtimeDependencies.sharp,
|
|
220
188
|
});
|
|
@@ -225,72 +193,36 @@ describe("AkanAppConfig", () => {
|
|
|
225
193
|
...akanPackageJson.dependencies,
|
|
226
194
|
...akanPackageJson.peerDependencies,
|
|
227
195
|
};
|
|
228
|
-
const singleConfig = new AkanAppConfig(
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
packageJson,
|
|
232
|
-
{ defaultDatabaseMode: "single" },
|
|
233
|
-
baseDevEnv,
|
|
234
|
-
);
|
|
235
|
-
const multipleConfig = new AkanAppConfig(
|
|
236
|
-
app,
|
|
237
|
-
[],
|
|
238
|
-
packageJson,
|
|
239
|
-
{ defaultDatabaseMode: "multiple" },
|
|
240
|
-
baseDevEnv,
|
|
241
|
-
);
|
|
242
|
-
const clusterConfig = new AkanAppConfig(
|
|
243
|
-
app,
|
|
244
|
-
[],
|
|
245
|
-
packageJson,
|
|
246
|
-
{ defaultDatabaseMode: "cluster" },
|
|
247
|
-
baseDevEnv,
|
|
248
|
-
);
|
|
196
|
+
const singleConfig = new AkanAppConfig(app, [], packageJson, { defaultDatabaseMode: "single" }, baseDevEnv);
|
|
197
|
+
const multipleConfig = new AkanAppConfig(app, [], packageJson, { defaultDatabaseMode: "multiple" }, baseDevEnv);
|
|
198
|
+
const clusterConfig = new AkanAppConfig(app, [], packageJson, { defaultDatabaseMode: "cluster" }, baseDevEnv);
|
|
249
199
|
|
|
250
200
|
expect(singleConfig.getProductionPackageJson().dependencies).toMatchObject({
|
|
251
201
|
croner: runtimeDependencies.croner,
|
|
252
202
|
});
|
|
253
|
-
expect(
|
|
254
|
-
|
|
255
|
-
).not.toHaveProperty("
|
|
256
|
-
expect(
|
|
257
|
-
|
|
258
|
-
).not.toHaveProperty("bullmq");
|
|
259
|
-
expect(
|
|
260
|
-
singleConfig.getProductionPackageJson().dependencies,
|
|
261
|
-
).not.toHaveProperty("@libsql/client");
|
|
262
|
-
expect(
|
|
263
|
-
singleConfig.getProductionPackageJson().dependencies,
|
|
264
|
-
).not.toHaveProperty("postgres");
|
|
265
|
-
expect(
|
|
266
|
-
singleConfig.getProductionPackageJson().dependencies,
|
|
267
|
-
).not.toHaveProperty("protobufjs");
|
|
203
|
+
expect(singleConfig.getProductionPackageJson().dependencies).not.toHaveProperty("ioredis");
|
|
204
|
+
expect(singleConfig.getProductionPackageJson().dependencies).not.toHaveProperty("bullmq");
|
|
205
|
+
expect(singleConfig.getProductionPackageJson().dependencies).not.toHaveProperty("@libsql/client");
|
|
206
|
+
expect(singleConfig.getProductionPackageJson().dependencies).not.toHaveProperty("postgres");
|
|
207
|
+
expect(singleConfig.getProductionPackageJson().dependencies).not.toHaveProperty("protobufjs");
|
|
268
208
|
|
|
269
|
-
expect(
|
|
270
|
-
multipleConfig.getProductionPackageJson().dependencies,
|
|
271
|
-
).toMatchObject({
|
|
209
|
+
expect(multipleConfig.getProductionPackageJson().dependencies).toMatchObject({
|
|
272
210
|
"@libsql/client": runtimeDependencies["@libsql/client"],
|
|
273
211
|
bullmq: runtimeDependencies.bullmq,
|
|
274
212
|
croner: runtimeDependencies.croner,
|
|
275
213
|
ioredis: runtimeDependencies.ioredis,
|
|
276
214
|
protobufjs: runtimeDependencies.protobufjs,
|
|
277
215
|
});
|
|
278
|
-
expect(
|
|
279
|
-
multipleConfig.getProductionPackageJson().dependencies,
|
|
280
|
-
).not.toHaveProperty("postgres");
|
|
216
|
+
expect(multipleConfig.getProductionPackageJson().dependencies).not.toHaveProperty("postgres");
|
|
281
217
|
|
|
282
|
-
expect(clusterConfig.getProductionPackageJson().dependencies).toMatchObject(
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
);
|
|
291
|
-
expect(
|
|
292
|
-
clusterConfig.getProductionPackageJson().dependencies,
|
|
293
|
-
).not.toHaveProperty("@libsql/client");
|
|
218
|
+
expect(clusterConfig.getProductionPackageJson().dependencies).toMatchObject({
|
|
219
|
+
bullmq: runtimeDependencies.bullmq,
|
|
220
|
+
croner: runtimeDependencies.croner,
|
|
221
|
+
ioredis: runtimeDependencies.ioredis,
|
|
222
|
+
postgres: runtimeDependencies.postgres,
|
|
223
|
+
protobufjs: runtimeDependencies.protobufjs,
|
|
224
|
+
});
|
|
225
|
+
expect(clusterConfig.getProductionPackageJson().dependencies).not.toHaveProperty("@libsql/client");
|
|
294
226
|
});
|
|
295
227
|
|
|
296
228
|
test("resolves database mode runtime packages and missing install specs", () => {
|
|
@@ -323,12 +255,7 @@ describe("AkanAppConfig", () => {
|
|
|
323
255
|
"ioredis",
|
|
324
256
|
"protobufjs",
|
|
325
257
|
]);
|
|
326
|
-
expect(config.getDatabaseModeRuntimePackages("cluster")).toEqual([
|
|
327
|
-
"bullmq",
|
|
328
|
-
"ioredis",
|
|
329
|
-
"postgres",
|
|
330
|
-
"protobufjs",
|
|
331
|
-
]);
|
|
258
|
+
expect(config.getDatabaseModeRuntimePackages("cluster")).toEqual(["bullmq", "ioredis", "postgres", "protobufjs"]);
|
|
332
259
|
expect(config.getMissingDatabaseModeDependencySpecs("multiple")).toEqual([
|
|
333
260
|
`@libsql/client@${runtimeDependencies["@libsql/client"]}`,
|
|
334
261
|
`protobufjs@${runtimeDependencies.protobufjs}`,
|
|
@@ -400,8 +327,6 @@ describe("AkanLibConfig", () => {
|
|
|
400
327
|
const config: DeepPartial<LibConfigResult> = {
|
|
401
328
|
externalLibs: ["firebase-admin"],
|
|
402
329
|
};
|
|
403
|
-
expect(new AkanLibConfig(lib, config).externalLibs).toEqual([
|
|
404
|
-
"firebase-admin",
|
|
405
|
-
]);
|
|
330
|
+
expect(new AkanLibConfig(lib, config).externalLibs).toEqual(["firebase-admin"]);
|
|
406
331
|
});
|
|
407
332
|
});
|
package/akanConfig/akanConfig.ts
CHANGED
|
@@ -19,7 +19,7 @@ import {
|
|
|
19
19
|
type LibConfigResult,
|
|
20
20
|
} from "./types";
|
|
21
21
|
|
|
22
|
-
const DEFAULT_BARREL_IMPORTS = ["akanjs/webkit", "akanjs/common", "akanjs/ui"];
|
|
22
|
+
const DEFAULT_BARREL_IMPORTS = ["akanjs/webkit", "akanjs/common", "akanjs/ui", "akanjs/server"];
|
|
23
23
|
const DEFAULT_OPTIMIZE_IMPORTS = [
|
|
24
24
|
"lucide-react",
|
|
25
25
|
"date-fns",
|
|
@@ -47,18 +47,8 @@ const DEFAULT_OPTIMIZE_IMPORTS = [
|
|
|
47
47
|
"mui-core",
|
|
48
48
|
"react-icons/*",
|
|
49
49
|
];
|
|
50
|
-
const WORKSPACE_BARREL_FACETS = [
|
|
51
|
-
|
|
52
|
-
"webkit",
|
|
53
|
-
"common",
|
|
54
|
-
"client",
|
|
55
|
-
"server",
|
|
56
|
-
] as const;
|
|
57
|
-
const SSR_RUNTIME_PACKAGES = [
|
|
58
|
-
"react",
|
|
59
|
-
"react-dom",
|
|
60
|
-
"react-server-dom-webpack",
|
|
61
|
-
] as const;
|
|
50
|
+
const WORKSPACE_BARREL_FACETS = ["ui", "webkit", "common", "client", "server"] as const;
|
|
51
|
+
const SSR_RUNTIME_PACKAGES = ["react", "react-dom", "react-server-dom-webpack"] as const;
|
|
62
52
|
const NATIVE_RUNTIME_PACKAGES = ["sharp"] as const;
|
|
63
53
|
const DEFAULT_BACKEND_RUNTIME_PACKAGES = ["croner"] as const;
|
|
64
54
|
const DATABASE_MODE_RUNTIME_PACKAGES = {
|
|
@@ -121,31 +111,19 @@ export class AkanAppConfig implements AppConfigResult {
|
|
|
121
111
|
this.barrelImports = [
|
|
122
112
|
...DEFAULT_BARREL_IMPORTS,
|
|
123
113
|
...WORKSPACE_BARREL_FACETS.map((facet) => `@apps/${app.name}/${facet}`),
|
|
124
|
-
...libs.flatMap((lib) =>
|
|
125
|
-
WORKSPACE_BARREL_FACETS.map((facet) => `@libs/${lib}/${facet}`),
|
|
126
|
-
),
|
|
114
|
+
...libs.flatMap((lib) => WORKSPACE_BARREL_FACETS.map((facet) => `@libs/${lib}/${facet}`)),
|
|
127
115
|
...(config?.barrelImports ?? []),
|
|
128
116
|
];
|
|
129
|
-
this.optimizeImports = [
|
|
130
|
-
|
|
131
|
-
...DEFAULT_OPTIMIZE_IMPORTS,
|
|
132
|
-
...(config?.optimizeImports ?? []),
|
|
133
|
-
]),
|
|
134
|
-
];
|
|
135
|
-
this.images = mergeImageConfig(
|
|
136
|
-
config?.images as Partial<AkanImageConfig> | undefined,
|
|
137
|
-
);
|
|
117
|
+
this.optimizeImports = [...new Set([...DEFAULT_OPTIMIZE_IMPORTS, ...(config?.optimizeImports ?? [])])];
|
|
118
|
+
this.images = mergeImageConfig(config?.images as Partial<AkanImageConfig> | undefined);
|
|
138
119
|
this.i18n = resolveAkanI18nConfig(config?.i18n);
|
|
139
120
|
process.env.AKAN_PUBLIC_DEFAULT_LOCALE = this.i18n.defaultLocale;
|
|
140
121
|
process.env.AKAN_PUBLIC_LOCALES = this.i18n.locales.join(",");
|
|
141
|
-
this.publicEnv =
|
|
142
|
-
(config?.publicEnv as string[] | undefined) ?? ([] as string[]);
|
|
122
|
+
this.publicEnv = (config?.publicEnv as string[] | undefined) ?? ([] as string[]);
|
|
143
123
|
this.mobile = this.#resolveMobileConfig(config.mobile);
|
|
144
124
|
this.docker = this.#makeDockerContent(config?.docker ?? {});
|
|
145
125
|
}
|
|
146
|
-
#resolveMobileConfig(
|
|
147
|
-
mobile: DeepPartial<AkanMobileConfig> | undefined,
|
|
148
|
-
): AkanMobileConfig {
|
|
126
|
+
#resolveMobileConfig(mobile: DeepPartial<AkanMobileConfig> | undefined): AkanMobileConfig {
|
|
149
127
|
const { targets: rawTargets, ...rawMobile } = mobile ?? {};
|
|
150
128
|
const appName = rawMobile.appName ?? this.app.name;
|
|
151
129
|
const appId = rawMobile.appId ?? `com.${this.app.name}.app`;
|
|
@@ -160,11 +138,8 @@ export class AkanAppConfig implements AppConfigResult {
|
|
|
160
138
|
const targets = Object.fromEntries(
|
|
161
139
|
targetEntries.map(([name, rawTarget]) => {
|
|
162
140
|
const target = rawTarget as DeepPartial<AkanMobileTargetConfig>;
|
|
163
|
-
const fallbackBasePath =
|
|
164
|
-
|
|
165
|
-
const basePath =
|
|
166
|
-
(target.basePath ?? fallbackBasePath)?.replace(/^\/+|\/+$/g, "") ||
|
|
167
|
-
undefined;
|
|
141
|
+
const fallbackBasePath = !rawTargets && this.basePaths.has(name) ? name : undefined;
|
|
142
|
+
const basePath = (target.basePath ?? fallbackBasePath)?.replace(/^\/+|\/+$/g, "") || undefined;
|
|
168
143
|
if (basePath && !this.basePaths.has(basePath)) {
|
|
169
144
|
throw new Error(
|
|
170
145
|
`Mobile target '${name}' uses unknown basePath '${basePath}' in apps/${this.app.name}/akan.config.ts`,
|
|
@@ -205,11 +180,8 @@ export class AkanAppConfig implements AppConfigResult {
|
|
|
205
180
|
plugins: rawMobile.plugins,
|
|
206
181
|
} as AkanMobileConfig;
|
|
207
182
|
}
|
|
208
|
-
#defaultMobileTargetName(
|
|
209
|
-
rawTargets
|
|
210
|
-
) {
|
|
211
|
-
if (rawTargets && Object.keys(rawTargets).length > 0)
|
|
212
|
-
return Object.keys(rawTargets)[0] as string;
|
|
183
|
+
#defaultMobileTargetName(rawTargets: DeepPartial<AkanMobileConfig>["targets"] | undefined) {
|
|
184
|
+
if (rawTargets && Object.keys(rawTargets).length > 0) return Object.keys(rawTargets)[0] as string;
|
|
213
185
|
return this.basePaths.has(this.app.name) ? this.app.name : "default";
|
|
214
186
|
}
|
|
215
187
|
#applyRoutes(routes: AkanRouteConfig[] = []) {
|
|
@@ -218,38 +190,28 @@ export class AkanAppConfig implements AppConfigResult {
|
|
|
218
190
|
const basePath = route.basePath.replace(/^\/+|\/+$/g, "");
|
|
219
191
|
this.basePaths.add(basePath);
|
|
220
192
|
const domains = this.subRoutes.getOrInsert(basePath, new Set());
|
|
221
|
-
Object.keys(route.domains).forEach(
|
|
222
|
-
(branch) => void this.branches.add(branch),
|
|
223
|
-
);
|
|
193
|
+
Object.keys(route.domains).forEach((branch) => void this.branches.add(branch));
|
|
224
194
|
Object.values(route.domains)
|
|
225
195
|
.flat()
|
|
226
196
|
.forEach((domain) => {
|
|
227
197
|
if (domain) domains.add(domain.toLowerCase().replace(/:\d+$/, ""));
|
|
228
198
|
});
|
|
229
199
|
} else {
|
|
230
|
-
Object.keys(route.domains).forEach(
|
|
231
|
-
(branch) => void this.branches.add(branch),
|
|
232
|
-
);
|
|
200
|
+
Object.keys(route.domains).forEach((branch) => void this.branches.add(branch));
|
|
233
201
|
Object.values(route.domains)
|
|
234
202
|
.flat()
|
|
235
203
|
.forEach((domain) => {
|
|
236
|
-
if (domain)
|
|
237
|
-
this.domains.add(domain.toLowerCase().replace(/:\d+$/, ""));
|
|
204
|
+
if (domain) this.domains.add(domain.toLowerCase().replace(/:\d+$/, ""));
|
|
238
205
|
});
|
|
239
206
|
}
|
|
240
207
|
}
|
|
241
208
|
const appName = this.app.name.toLowerCase();
|
|
242
209
|
const serveDomain = this.baseDevEnv.serveDomain.toLowerCase();
|
|
243
210
|
if (this.subRoutes.size === 0)
|
|
244
|
-
this.branches.forEach(
|
|
245
|
-
(branch) =>
|
|
246
|
-
void this.domains.add(`${appName}-${branch}.${serveDomain}`),
|
|
247
|
-
);
|
|
211
|
+
this.branches.forEach((branch) => void this.domains.add(`${appName}-${branch}.${serveDomain}`));
|
|
248
212
|
else
|
|
249
213
|
Array.from(this.subRoutes.entries()).forEach(([basePath, domains]) => {
|
|
250
|
-
this.branches.forEach(
|
|
251
|
-
(domain) => void domains.add(`${basePath}-${domain}.${serveDomain}`),
|
|
252
|
-
);
|
|
214
|
+
this.branches.forEach((domain) => void domains.add(`${basePath}-${domain}.${serveDomain}`));
|
|
253
215
|
});
|
|
254
216
|
}
|
|
255
217
|
#getDockerRunScripts(runs: (string | { [key in Arch]?: string })[]) {
|
|
@@ -265,15 +227,9 @@ export class AkanAppConfig implements AppConfigResult {
|
|
|
265
227
|
.join("\n");
|
|
266
228
|
});
|
|
267
229
|
}
|
|
268
|
-
#getDockerImageScript(
|
|
269
|
-
image: string | { [key in Arch]?: string },
|
|
270
|
-
defaultImage: string,
|
|
271
|
-
) {
|
|
230
|
+
#getDockerImageScript(image: string | { [key in Arch]?: string }, defaultImage: string) {
|
|
272
231
|
if (typeof image === "string") return `FROM ${image}`;
|
|
273
|
-
else
|
|
274
|
-
return archs
|
|
275
|
-
.map((arch) => `FROM ${image[arch] ?? defaultImage} AS ${arch}`)
|
|
276
|
-
.join("\n");
|
|
232
|
+
else return archs.map((arch) => `FROM ${image[arch] ?? defaultImage} AS ${arch}`).join("\n");
|
|
277
233
|
}
|
|
278
234
|
#makeDockerContent(docker: DeepPartial<DockerConfig>): DockerConfig {
|
|
279
235
|
if (docker.content)
|
|
@@ -326,9 +282,7 @@ CMD [${command.map((c) => `"${c}"`).join(",")}]`;
|
|
|
326
282
|
static async from(app: App) {
|
|
327
283
|
const [configImp, baseDevEnv, libs, rootPackageJson] = await Promise.all([
|
|
328
284
|
import(`${app.cwdPath}/akan.config.ts`).then((mod) => mod.default),
|
|
329
|
-
WorkspaceExecutor.getBaseDevEnv(
|
|
330
|
-
path.join(app.workspace.workspaceRoot, ".env"),
|
|
331
|
-
),
|
|
285
|
+
WorkspaceExecutor.getBaseDevEnv(path.join(app.workspace.workspaceRoot, ".env")),
|
|
332
286
|
app.workspace.getLibs(),
|
|
333
287
|
app.workspace.getPackageJson(),
|
|
334
288
|
]);
|
|
@@ -336,16 +290,11 @@ CMD [${command.map((c) => `"${c}"`).join(",")}]`;
|
|
|
336
290
|
return new AkanAppConfig(app, libs, rootPackageJson, config, baseDevEnv);
|
|
337
291
|
}
|
|
338
292
|
#resolveProductionDependencyVersion(lib: string) {
|
|
339
|
-
const rootVersion =
|
|
340
|
-
this.rootPackageJson.dependencies?.[lib] ??
|
|
341
|
-
this.rootPackageJson.devDependencies?.[lib];
|
|
293
|
+
const rootVersion = this.rootPackageJson.dependencies?.[lib] ?? this.rootPackageJson.devDependencies?.[lib];
|
|
342
294
|
if (rootVersion) return rootVersion;
|
|
343
295
|
const akanPackageJson = getAkanPackageJson();
|
|
344
296
|
if (AKAN_RUNTIME_PACKAGES.has(lib))
|
|
345
|
-
return
|
|
346
|
-
akanPackageJson.dependencies?.[lib] ??
|
|
347
|
-
akanPackageJson.peerDependencies?.[lib]
|
|
348
|
-
);
|
|
297
|
+
return akanPackageJson.dependencies?.[lib] ?? akanPackageJson.peerDependencies?.[lib];
|
|
349
298
|
}
|
|
350
299
|
#getProductionRuntimePackages() {
|
|
351
300
|
return [
|
|
@@ -356,14 +305,10 @@ CMD [${command.map((c) => `"${c}"`).join(",")}]`;
|
|
|
356
305
|
...this.getDatabaseModeRuntimePackages(),
|
|
357
306
|
];
|
|
358
307
|
}
|
|
359
|
-
getDatabaseModeRuntimePackages(
|
|
360
|
-
databaseMode: DatabaseMode = this.defaultDatabaseMode,
|
|
361
|
-
) {
|
|
308
|
+
getDatabaseModeRuntimePackages(databaseMode: DatabaseMode = this.defaultDatabaseMode) {
|
|
362
309
|
return [...DATABASE_MODE_RUNTIME_PACKAGES[databaseMode]];
|
|
363
310
|
}
|
|
364
|
-
getMissingDatabaseModeDependencySpecs(
|
|
365
|
-
databaseMode: DatabaseMode = this.defaultDatabaseMode,
|
|
366
|
-
) {
|
|
311
|
+
getMissingDatabaseModeDependencySpecs(databaseMode: DatabaseMode = this.defaultDatabaseMode) {
|
|
367
312
|
const rootDependencies = {
|
|
368
313
|
...this.rootPackageJson.dependencies,
|
|
369
314
|
...this.rootPackageJson.devDependencies,
|
|
@@ -372,8 +317,7 @@ CMD [${command.map((c) => `"${c}"`).join(",")}]`;
|
|
|
372
317
|
.filter((lib) => !rootDependencies[lib])
|
|
373
318
|
.map((lib) => {
|
|
374
319
|
const version = this.#resolveProductionDependencyVersion(lib);
|
|
375
|
-
if (!version)
|
|
376
|
-
throw new Error(`Dependency ${lib} not found in package.json`);
|
|
320
|
+
if (!version) throw new Error(`Dependency ${lib} not found in package.json`);
|
|
377
321
|
return `${lib}@${version}`;
|
|
378
322
|
});
|
|
379
323
|
}
|
|
@@ -386,8 +330,7 @@ CMD [${command.map((c) => `"${c}"`).join(",")}]`;
|
|
|
386
330
|
dependencies: Object.fromEntries(
|
|
387
331
|
[...new Set(this.#getProductionRuntimePackages())].map((lib) => {
|
|
388
332
|
const version = this.#resolveProductionDependencyVersion(lib);
|
|
389
|
-
if (!version)
|
|
390
|
-
throw new Error(`Dependency ${lib} not found in package.json`);
|
|
333
|
+
if (!version) throw new Error(`Dependency ${lib} not found in package.json`);
|
|
391
334
|
return [lib, version];
|
|
392
335
|
}),
|
|
393
336
|
),
|
|
@@ -413,9 +356,7 @@ function getAkanPackageJson() {
|
|
|
413
356
|
}
|
|
414
357
|
for (const packageJsonPath of packageJsonPaths) {
|
|
415
358
|
try {
|
|
416
|
-
akanPackageJson = JSON.parse(
|
|
417
|
-
fs.readFileSync(packageJsonPath, "utf8"),
|
|
418
|
-
) as PackageJson;
|
|
359
|
+
akanPackageJson = JSON.parse(fs.readFileSync(packageJsonPath, "utf8")) as PackageJson;
|
|
419
360
|
return akanPackageJson;
|
|
420
361
|
} catch {
|
|
421
362
|
// Try the next known layout: source package first, bundled CLI package second.
|
|
@@ -430,9 +371,7 @@ function getAkanPackageJson() {
|
|
|
430
371
|
return akanPackageJson;
|
|
431
372
|
}
|
|
432
373
|
|
|
433
|
-
function mergeImageConfig(
|
|
434
|
-
config: Partial<AkanImageConfig> = {},
|
|
435
|
-
): AkanImageConfig {
|
|
374
|
+
function mergeImageConfig(config: Partial<AkanImageConfig> = {}): AkanImageConfig {
|
|
436
375
|
return {
|
|
437
376
|
...DEFAULT_AKAN_IMAGE_CONFIG,
|
|
438
377
|
...config,
|
|
@@ -440,10 +379,8 @@ function mergeImageConfig(
|
|
|
440
379
|
imageSizes: config.imageSizes ?? DEFAULT_AKAN_IMAGE_CONFIG.imageSizes,
|
|
441
380
|
formats: config.formats ?? DEFAULT_AKAN_IMAGE_CONFIG.formats,
|
|
442
381
|
qualities: config.qualities ?? DEFAULT_AKAN_IMAGE_CONFIG.qualities,
|
|
443
|
-
remotePatterns:
|
|
444
|
-
|
|
445
|
-
localPatterns:
|
|
446
|
-
config.localPatterns ?? DEFAULT_AKAN_IMAGE_CONFIG.localPatterns,
|
|
382
|
+
remotePatterns: config.remotePatterns ?? DEFAULT_AKAN_IMAGE_CONFIG.remotePatterns,
|
|
383
|
+
localPatterns: config.localPatterns ?? DEFAULT_AKAN_IMAGE_CONFIG.localPatterns,
|
|
447
384
|
};
|
|
448
385
|
}
|
|
449
386
|
|
|
@@ -455,9 +392,7 @@ export class AkanLibConfig implements LibConfigResult {
|
|
|
455
392
|
this.externalLibs = config?.externalLibs ?? [];
|
|
456
393
|
}
|
|
457
394
|
static async from(lib: Lib) {
|
|
458
|
-
const [configImp] = await Promise.all([
|
|
459
|
-
import(`${lib.cwdPath}/akan.config.ts`).then((mod) => mod.default),
|
|
460
|
-
]);
|
|
395
|
+
const [configImp] = await Promise.all([import(`${lib.cwdPath}/akan.config.ts`).then((mod) => mod.default)]);
|
|
461
396
|
const config = typeof configImp === "function" ? configImp(lib) : configImp;
|
|
462
397
|
return new AkanLibConfig(lib, config);
|
|
463
398
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@akanjs/devkit",
|
|
3
|
-
"version": "2.3.
|
|
3
|
+
"version": "2.3.4-rc.0",
|
|
4
4
|
"sourceType": "module",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"publishConfig": {
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
"@langchain/openai": "^1.4.6",
|
|
33
33
|
"@tailwindcss/node": "^4.3.0",
|
|
34
34
|
"@trapezedev/project": "^7.1.4",
|
|
35
|
-
"akanjs": "2.3.
|
|
35
|
+
"akanjs": "2.3.4-rc.0",
|
|
36
36
|
"chalk": "^5.6.2",
|
|
37
37
|
"commander": "^14.0.3",
|
|
38
38
|
"daisyui": "^5.5.20",
|
|
@@ -45,7 +45,7 @@ describe("createExternalizeFrameworkPlugin", () => {
|
|
|
45
45
|
getTsConfig: async () => ({
|
|
46
46
|
compilerOptions: {
|
|
47
47
|
paths: {
|
|
48
|
-
|
|
48
|
+
akanjs: ["./pkgs/akanjs/index.ts"],
|
|
49
49
|
"akanjs/*": ["./pkgs/akanjs/*"],
|
|
50
50
|
"akanjs/server": ["./pkgs/akanjs/server/index.ts"],
|
|
51
51
|
"akanjs/server/*": ["./pkgs/akanjs/server/*"],
|
|
@@ -105,7 +105,7 @@ describe("createExternalizeFrameworkPlugin", () => {
|
|
|
105
105
|
getTsConfig: async () => ({
|
|
106
106
|
compilerOptions: {
|
|
107
107
|
paths: {
|
|
108
|
-
|
|
108
|
+
akanjs: ["./pkgs/akanjs/index.ts"],
|
|
109
109
|
"akanjs/*": ["./pkgs/akanjs/*"],
|
|
110
110
|
"akanjs/server": ["./pkgs/akanjs/server/index.ts"],
|
|
111
111
|
"akanjs/server/*": ["./pkgs/akanjs/server/*"],
|
|
@@ -156,7 +156,10 @@ describe("createExternalizeFrameworkPlugin", () => {
|
|
|
156
156
|
},
|
|
157
157
|
}),
|
|
158
158
|
);
|
|
159
|
-
await write(
|
|
159
|
+
await write(
|
|
160
|
+
path.join(root, "node_modules/akanjs/server/index.ts"),
|
|
161
|
+
'export const optionMarker = "published-option";\n',
|
|
162
|
+
);
|
|
160
163
|
|
|
161
164
|
const plugin = await createExternalizeFrameworkPlugin({
|
|
162
165
|
app: {
|
|
@@ -163,6 +163,30 @@ describe("BarrelAnalyzer and rewriteBarrelImports", () => {
|
|
|
163
163
|
expect(await rewriteBarrelImports(source, ["akanjs/server"], analyzer)).toBeNull();
|
|
164
164
|
});
|
|
165
165
|
|
|
166
|
+
test("rewrites akanjs/server value imports to leaf subpaths", async () => {
|
|
167
|
+
const analyzer = {
|
|
168
|
+
analyze: async () =>
|
|
169
|
+
new Map([
|
|
170
|
+
["AkanOption", { subpath: "akanjs/server/akanOption", originalName: "AkanOption" }],
|
|
171
|
+
["Try", { subpath: "akanjs/server/decorators", originalName: "Try" }],
|
|
172
|
+
]),
|
|
173
|
+
} as BarrelAnalyzer;
|
|
174
|
+
|
|
175
|
+
const rewritten = await rewriteBarrelImports(
|
|
176
|
+
'import { AkanOption, Try } from "akanjs/server";\nexport const option = new AkanOption();\n',
|
|
177
|
+
["akanjs/server"],
|
|
178
|
+
analyzer,
|
|
179
|
+
);
|
|
180
|
+
|
|
181
|
+
expect(rewritten).toBe(
|
|
182
|
+
[
|
|
183
|
+
'import { AkanOption } from "akanjs/server/akanOption";',
|
|
184
|
+
'import { Try } from "akanjs/server/decorators";',
|
|
185
|
+
"export const option = new AkanOption();\n",
|
|
186
|
+
].join("\n"),
|
|
187
|
+
);
|
|
188
|
+
});
|
|
189
|
+
|
|
166
190
|
test("rewrites single-package Akan facet barrels to leaf subpaths", async () => {
|
|
167
191
|
const analyzer = {
|
|
168
192
|
analyze: async () =>
|