@akanjs/devkit 2.2.0-rc.4 → 2.2.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.
@@ -73,9 +73,15 @@ describe("resolveSsrPageEntries", () => {
73
73
  const generatedSource = await Bun.file(groupedRoot?.moduleAbsPath ?? "").text();
74
74
  expect(generatedSource).toContain("<System.Provider");
75
75
  expect(generatedSource).toContain("theme={userLayout.theme ?? inheritedLayout.theme}");
76
- expect(generatedSource).toContain("const getActiveLocaleDictionary =");
77
- expect(generatedSource).toContain('await import("@apps/demo/lib/dict")');
78
- expect(generatedSource).toContain("dictionary={getActiveLocaleDictionary ? getActiveLocaleDictionary(params.lang) : undefined}");
76
+ expect(generatedSource).toContain('import { allDictionary } from "../dict/useDict.ts";');
77
+ expect(generatedSource).toContain("dictionary={allDictionary[params.lang]}");
78
+ expect(generatedSource).not.toContain("getAllDictionary");
79
79
  expect(generatedSource).not.toContain("// export default function GeneratedLayout");
80
+
81
+ const generatedDictMacro = await Bun.file(path.join(appRoot, ".akan", "generated", "dict", "useDict.ts")).text();
82
+ expect(generatedDictMacro).toContain(
83
+ 'import { getAllDictionary } from "@apps/demo/lib/dict" with { type: "macro" };',
84
+ );
85
+ expect(generatedDictMacro).toContain("export const allDictionary = getAllDictionary();");
80
86
  });
81
87
  });
@@ -15,6 +15,7 @@ async function appHasStModule(appCwdPath: string): Promise<boolean> {
15
15
  }
16
16
 
17
17
  const IMPLICIT_LAYOUT_DIR = path.join(".akan", "generated", "root-layouts");
18
+ const IMPLICIT_DICT_DIR = path.join(".akan", "generated", "dict");
18
19
 
19
20
  interface RootBoundary {
20
21
  sourceKey: string | null;
@@ -39,6 +40,10 @@ function implicitRootLayoutAbsPath(appCwdPath: string, segments: string[]): stri
39
40
  return path.join(path.resolve(appCwdPath), IMPLICIT_LAYOUT_DIR, filename);
40
41
  }
41
42
 
43
+ function implicitDictionaryMacroAbsPath(appCwdPath: string): string {
44
+ return path.join(path.resolve(appCwdPath), IMPLICIT_DICT_DIR, "useDict.ts");
45
+ }
46
+
42
47
  function isRootBoundarySegments(segments: string[], basePaths: Iterable<string>): boolean {
43
48
  const firstVisibleIndex = segments.findIndex((segment) => !/^\(.+\)$/.test(segment));
44
49
  if (firstVisibleIndex === -1) return segments.length <= 1;
@@ -99,6 +104,19 @@ async function assertEnvClientConvention(appCwdPath: string, appName: string) {
99
104
  }
100
105
  }
101
106
 
107
+ async function writeGeneratedDictionaryMacroFile(appCwdPath: string, appName: string): Promise<string> {
108
+ const absPath = implicitDictionaryMacroAbsPath(appCwdPath);
109
+ await mkdir(path.dirname(absPath), { recursive: true });
110
+ await Bun.write(
111
+ absPath,
112
+ `import { getAllDictionary } from "@apps/${appName}/lib/dict" with { type: "macro" };
113
+
114
+ export const allDictionary = getAllDictionary();
115
+ `,
116
+ );
117
+ return absPath;
118
+ }
119
+
102
120
  async function writeGeneratedRootLayoutFile(opts: {
103
121
  appCwdPath: string;
104
122
  appName: string;
@@ -108,8 +126,15 @@ async function writeGeneratedRootLayoutFile(opts: {
108
126
  includeSystemProvider: boolean;
109
127
  }): Promise<string> {
110
128
  await assertEnvClientConvention(opts.appCwdPath, opts.appName);
129
+ const dictMacroAbsPath = opts.includeSystemProvider
130
+ ? await writeGeneratedDictionaryMacroFile(opts.appCwdPath, opts.appName)
131
+ : null;
111
132
  const absPath = implicitRootLayoutAbsPath(opts.appCwdPath, opts.boundary.segments);
112
133
  await mkdir(path.dirname(absPath), { recursive: true });
134
+ const dictMacroRel = dictMacroAbsPath
135
+ ? path.relative(path.dirname(absPath), dictMacroAbsPath).split(path.sep).join("/")
136
+ : null;
137
+ const dictMacroSpecifier = dictMacroRel ? (dictMacroRel.startsWith(".") ? dictMacroRel : `./${dictMacroRel}`) : null;
113
138
  const sourceRel = opts.boundary.sourceAbsPath
114
139
  ? path.relative(path.dirname(absPath), opts.boundary.sourceAbsPath).split(path.sep).join("/")
115
140
  : null;
@@ -139,12 +164,8 @@ async function writeGeneratedRootLayoutFile(opts: {
139
164
  import { loadFonts } from "akanjs/client";
140
165
  import { System } from "akanjs/ui";
141
166
  import { env } from "@apps/${opts.appName}/env/env.client";
167
+ import { allDictionary } from ${JSON.stringify(dictMacroSpecifier)};
142
168
  ${clientImport}${inheritedImport}${userImport}
143
- // SSR builds (target=bun) load the full dictionary server-side and pass only the active locale to the client.
144
- // CSR builds (target=browser) fold this branch to undefined, so the macro-seeded dictionary is used and the
145
- // server-only dict module (which pulls @libs/*/server) is dead-code-eliminated out of the browser bundle.
146
- const getActiveLocaleDictionary =
147
- process.env.AKAN_PUBLIC_RENDER_ENV === "ssr" ? (await import("@apps/${opts.appName}/lib/dict")).getDictionary : undefined;
148
169
  const userFonts = userLayout.fonts ?? inheritedLayout.fonts ?? [];
149
170
  const defaultFonts = userFonts.filter((font) => font.default);
150
171
  if (defaultFonts.length > 1) throw new Error("[route-convention] only one default font is allowed per root layout");
@@ -175,7 +196,7 @@ export default function GeneratedLayout({ children, params, searchParams }: Layo
175
196
  gaTrackingId={userLayout.gaTrackingId ?? inheritedLayout.gaTrackingId}
176
197
  layoutStyle={userLayout.layoutStyle ?? inheritedLayout.layoutStyle}
177
198
  reconnect={userLayout.reconnect ?? inheritedLayout.reconnect ?? false}
178
- dictionary={getActiveLocaleDictionary ? getActiveLocaleDictionary(params.lang) : undefined}
199
+ dictionary={allDictionary[params.lang]}
179
200
  >
180
201
  <UserLayout params={params} searchParams={searchParams}>{children}</UserLayout>
181
202
  </System.Provider>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@akanjs/devkit",
3
- "version": "2.2.0-rc.4",
3
+ "version": "2.2.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.2.0-rc.4",
35
+ "akanjs": "2.2.0",
36
36
  "chalk": "^5.6.2",
37
37
  "commander": "^14.0.3",
38
38
  "daisyui": "^5.5.20",