@akanjs/devkit 2.3.3-rc.1 → 2.3.3

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
- app,
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
- singleConfig.getProductionPackageJson().dependencies,
255
- ).not.toHaveProperty("ioredis");
256
- expect(
257
- singleConfig.getProductionPackageJson().dependencies,
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
- bullmq: runtimeDependencies.bullmq,
285
- croner: runtimeDependencies.croner,
286
- ioredis: runtimeDependencies.ioredis,
287
- postgres: runtimeDependencies.postgres,
288
- protobufjs: runtimeDependencies.protobufjs,
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
  });
@@ -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
- "ui",
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
- ...new Set([
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
- !rawTargets && this.basePaths.has(name) ? name : undefined;
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: DeepPartial<AkanMobileConfig>["targets"] | undefined,
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
- config.remotePatterns ?? DEFAULT_AKAN_IMAGE_CONFIG.remotePatterns,
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-rc.1",
3
+ "version": "2.3.3",
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.3-rc.1",
35
+ "akanjs": "2.3.3",
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
- "akanjs": ["./pkgs/akanjs/index.ts"],
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
- "akanjs": ["./pkgs/akanjs/index.ts"],
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(path.join(root, "node_modules/akanjs/server/index.ts"), 'export const optionMarker = "published-option";\n');
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 () =>