@akanjs/devkit 3.0.0-alpha.8 → 3.0.0-alpha.80
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/CHANGELOG.md +15 -0
- package/README.ko.md +1 -1
- package/README.md +1 -1
- package/agentsIndex.test.ts +10 -0
- package/agentsIndex.ts +47 -1
- package/aiEditor.ts +1 -1
- package/akanApp/BackendImportGraph.test.ts +120 -0
- package/akanApp/BackendImportGraph.ts +167 -0
- package/akanApp/akanApp.host.test.ts +16 -678
- package/akanApp/akanApp.host.ts +65 -562
- package/akanApp/devHostPolicy.test.ts +542 -0
- package/akanApp/devHostPolicy.ts +412 -0
- package/akanApp/index.ts +2 -0
- package/akanConfig/akanConfig.test.ts +182 -14
- package/akanConfig/akanConfig.ts +132 -47
- package/akanConfig/types.ts +8 -0
- package/akanContext.ts +70 -14
- package/akanMcpContract.ts +25 -4
- package/applicationBuildRunner.test.ts +1 -1
- package/applicationBuildRunner.ts +45 -21
- package/artifact/implicitRootLayout.test.ts +67 -0
- package/artifact/implicitRootLayout.ts +27 -7
- package/artifact/routeSeedIndex.test.ts +1 -0
- package/biome.base.json +340 -0
- package/biomeBase.ts +9 -0
- package/capacitorApp.ts +10 -0
- package/cloud/globalConfig.ts +9 -2
- package/commandDecorators/command.ts +30 -6
- package/commandDecorators/commandBuilder.ts +20 -5
- package/commandDecorators/commandDecorators.test.ts +115 -3
- package/dependencyScanner.test.ts +99 -0
- package/dependencyScanner.ts +27 -24
- package/devkitUtils.test.ts +0 -104
- package/executors.test.ts +132 -5
- package/executors.ts +89 -14
- package/fileEditor.ts +19 -19
- package/fleetConfig.ts +73 -0
- package/fleetGuard.test.ts +121 -0
- package/fleetGuard.ts +157 -0
- package/fleetSpoke.test.ts +390 -0
- package/fleetSpoke.ts +719 -0
- package/formSetterScanner.test.ts +80 -0
- package/formSetterScanner.ts +92 -0
- package/frontendBuild/autoImportSync.test.ts +58 -0
- package/frontendBuild/autoImportSync.ts +4 -0
- package/frontendBuild/buildRouteClient.test.ts +47 -24
- package/frontendBuild/clientBuildTypes.ts +4 -0
- package/frontendBuild/clientEntriesBundler.ts +4 -1
- package/frontendBuild/clientEntryDiscovery.ts +2 -2
- package/frontendBuild/csrArtifactBuilder.ts +116 -84
- package/frontendBuild/cssCompiler.ts +123 -12
- package/frontendBuild/cssImportResolver.ts +8 -7
- package/frontendBuild/fontOptimizer.ts +37 -18
- package/frontendBuild/fontPruner.test.ts +220 -0
- package/frontendBuild/fontPruner.ts +206 -0
- package/frontendBuild/frontendBuild.test.ts +178 -10
- package/frontendBuild/hmrWatcher.ts +1 -1
- package/frontendBuild/index.ts +1 -1
- package/frontendBuild/pagesBundleBuilder.ts +3 -3
- package/frontendBuild/pagesEntrySourceGenerator.ts +11 -88
- package/frontendBuild/routeClientBuilder.ts +12 -5
- package/frontendBuild/ssrBaseArtifactBuilder.ts +21 -4
- package/frontendBuild/styleContract.ts +14 -20
- package/frontendBuild/themeValidator.ts +22 -17
- package/frontendBuild/vendorSpecifiers.ts +1 -0
- package/incrementalBuilder/devWatchBatch.test.ts +18 -20
- package/incrementalBuilder/devWatchBatch.ts +6 -2
- package/incrementalBuilder/incrementalBuilder.host.ts +1 -1
- package/incrementalBuilder/incrementalBuilder.proc.ts +8 -4
- package/index.ts +0 -5
- package/integration/devStabilityHarness.ts +2 -10
- package/libSource.test.ts +109 -0
- package/libSource.ts +126 -0
- package/lint/__fixtures__/README.md +40 -0
- package/lint/__fixtures__/no-arbitrary-color/bad.tsx +3 -0
- package/lint/__fixtures__/no-arbitrary-color/good.tsx +4 -0
- package/lint/__fixtures__/no-async-component-in-ui/bad.tsx +4 -0
- package/lint/__fixtures__/no-async-component-in-ui/good.tsx +4 -0
- package/lint/__fixtures__/no-bang-comment-in-client/bad.tsx +4 -0
- package/lint/__fixtures__/no-bang-comment-in-client/fixture.json +1 -0
- package/lint/__fixtures__/no-bang-comment-in-client/good.tsx +3 -0
- package/lint/__fixtures__/no-daisyui-legacy-class/bad.tsx +7 -0
- package/lint/__fixtures__/no-daisyui-legacy-class/good.tsx +5 -0
- package/lint/__fixtures__/no-deep-internal-import/bad.tsx +3 -0
- package/lint/__fixtures__/no-deep-internal-import/fixture.json +1 -0
- package/lint/__fixtures__/no-deep-internal-import/good.tsx +3 -0
- package/lint/__fixtures__/no-deprecated-log-level/bad.tsx +4 -0
- package/lint/__fixtures__/no-deprecated-log-level/good.tsx +4 -0
- package/lint/__fixtures__/no-import-client-functions/bad.tsx +2 -0
- package/lint/__fixtures__/no-import-client-functions/good.tsx +4 -0
- package/lint/__fixtures__/no-import-client-in-server/bad.tsx +6 -0
- package/lint/__fixtures__/no-import-client-in-server/good.tsx +5 -0
- package/lint/__fixtures__/no-import-external-library/bad.tsx +4 -0
- package/lint/__fixtures__/no-import-external-library/good.tsx +5 -0
- package/lint/__fixtures__/no-import-server-in-client/bad.tsx +6 -0
- package/lint/__fixtures__/no-import-server-in-client/good.tsx +4 -0
- package/lint/__fixtures__/no-init-fetch-in-client/store-file/bad.ts +1 -0
- package/lint/__fixtures__/no-init-fetch-in-client/store-file/fixture.json +1 -0
- package/lint/__fixtures__/no-init-fetch-in-client/store-file/good.ts +1 -0
- package/lint/__fixtures__/no-init-fetch-in-client/use-client/bad.tsx +4 -0
- package/lint/__fixtures__/no-init-fetch-in-client/use-client/good.tsx +5 -0
- package/lint/__fixtures__/no-inline-color/bad.tsx +3 -0
- package/lint/__fixtures__/no-inline-color/good.tsx +3 -0
- package/lint/__fixtures__/no-interpolated-arbitrary-class/bad.tsx +3 -0
- package/lint/__fixtures__/no-interpolated-arbitrary-class/good.tsx +3 -0
- package/lint/__fixtures__/no-js-private-class-method/bad.tsx +3 -0
- package/lint/__fixtures__/no-js-private-class-method/good.tsx +3 -0
- package/lint/__fixtures__/no-model-type-in-util-zone/bad.tsx +3 -0
- package/lint/__fixtures__/no-model-type-in-util-zone/good.tsx +6 -0
- package/lint/__fixtures__/no-raw-palette-class/bad.tsx +6 -0
- package/lint/__fixtures__/no-raw-palette-class/good.tsx +8 -0
- package/lint/__fixtures__/no-redeclare-predefined-endpoint/bad.ts +10 -0
- package/lint/__fixtures__/no-redeclare-predefined-endpoint/fixture.json +1 -0
- package/lint/__fixtures__/no-redeclare-predefined-endpoint/good.ts +6 -0
- package/lint/__fixtures__/no-return-in-store-action/bad.tsx +2 -0
- package/lint/__fixtures__/no-return-in-store-action/good.tsx +6 -0
- package/lint/__fixtures__/no-throw-raw-error/bad.tsx +4 -0
- package/lint/__fixtures__/no-throw-raw-error/good.tsx +4 -0
- package/lint/__fixtures__/no-unpublished-form-setter/bad.tsx +3 -0
- package/lint/__fixtures__/no-unpublished-form-setter/good.tsx +5 -0
- package/lint/__fixtures__/no-use-client-in-server/bad.tsx +3 -0
- package/lint/__fixtures__/no-use-client-in-server/good.tsx +2 -0
- package/lint/__fixtures__/non-scalar-props-restricted/bad.tsx +5 -0
- package/lint/__fixtures__/non-scalar-props-restricted/good.tsx +4 -0
- package/lint/gritRules.test.ts +178 -0
- package/lint/no-arbitrary-color.grit +1 -1
- package/lint/no-async-component-in-ui.grit +35 -0
- package/lint/no-bang-comment-in-client.grit +23 -10
- package/lint/no-daisyui-legacy-class.grit +26 -9
- package/lint/no-deprecated-log-level.grit +17 -0
- package/lint/no-import-client-in-server.grit +48 -0
- package/lint/no-import-server-in-client.grit +45 -0
- package/lint/no-init-fetch-in-client.grit +47 -0
- package/lint/no-inline-color.grit +10 -8
- package/lint/no-interpolated-arbitrary-class.grit +3 -3
- package/lint/no-model-type-in-util-zone.grit +58 -0
- package/lint/no-raw-palette-class.grit +3 -3
- package/lint/no-unpublished-form-setter.grit +41 -0
- package/lint/non-scalar-props-restricted.grit +16 -7
- package/linter.test.ts +80 -0
- package/linter.ts +99 -25
- package/package.json +6 -6
- package/prompter.ts +9 -4
- package/qualityScanner.test.ts +116 -0
- package/qualityScanner.ts +89 -21
- package/recipeScanner.ts +4 -1
- package/repoIdentity.ts +42 -0
- package/scanInfo.ts +32 -26
- package/semver.test.ts +26 -0
- package/semver.ts +31 -0
- package/slicePlanner.test.ts +151 -0
- package/slicePlanner.ts +157 -0
- package/ssrScanner.test.ts +301 -0
- package/transforms/asyncDefaultExportDetector.ts +103 -0
- package/transforms/barrelImportsPlugin.ts +1 -1
- package/transforms/externalizeFrameworkPlugin.ts +0 -1
- package/transforms/transforms.test.ts +5 -5
- package/transforms/tsconfigPackageResolver.test.ts +230 -0
- package/tsconfig.json +6 -2
- package/typeChecker.ts +1 -1
- package/types.ts +1 -0
- package/ui/ScrollList.tsx +6 -8
- package/uploadRelease.ts +2 -2
- package/workflow/executor.test.ts +146 -0
- package/workspaceLayout.test.ts +56 -4
- package/workspaceLayout.ts +49 -4
- package/builder.ts +0 -164
- package/extractDeps.ts +0 -86
- package/frontendBuild/styleGuard.test.ts +0 -165
- package/frontendBuild/styleGuard.ts +0 -322
- package/getCredentials.ts +0 -19
- package/getModelFileData.ts +0 -62
- package/src/capacitorApp.ts +0 -282
- package/streamAi.ts +0 -45
|
@@ -7,7 +7,13 @@ import type {
|
|
|
7
7
|
ApplicationBuildResult,
|
|
8
8
|
} from "./applicationBuildReporter";
|
|
9
9
|
import type { App } from "./commandDecorators";
|
|
10
|
-
import {
|
|
10
|
+
import {
|
|
11
|
+
AllRoutesBuilder,
|
|
12
|
+
CsrArtifactBuilder,
|
|
13
|
+
FontPruner,
|
|
14
|
+
precompressArtifacts,
|
|
15
|
+
SsrBaseArtifactBuilder,
|
|
16
|
+
} from "./frontendBuild";
|
|
11
17
|
import { Spinner } from "./spinner";
|
|
12
18
|
|
|
13
19
|
export interface TypecheckOptions {
|
|
@@ -15,7 +21,7 @@ export interface TypecheckOptions {
|
|
|
15
21
|
incremental?: boolean;
|
|
16
22
|
}
|
|
17
23
|
|
|
18
|
-
export type BuildPhaseId = "prepare" | "typecheck" | "backend" | "ssr" | "csr" | "compress" | "metadata";
|
|
24
|
+
export type BuildPhaseId = "prepare" | "typecheck" | "backend" | "ssr" | "csr" | "assets" | "compress" | "metadata";
|
|
19
25
|
|
|
20
26
|
export type BuildPhaseResult = ApplicationBuildPhaseResult & { id: BuildPhaseId };
|
|
21
27
|
export type BuildResult = ApplicationBuildResult;
|
|
@@ -37,6 +43,7 @@ const BUILD_PHASE_EMOJIS: Record<BuildPhaseId, string> = {
|
|
|
37
43
|
backend: "📦",
|
|
38
44
|
ssr: "🧭",
|
|
39
45
|
csr: "🎨",
|
|
46
|
+
assets: "✂️",
|
|
40
47
|
compress: "🗜️",
|
|
41
48
|
metadata: "📝",
|
|
42
49
|
};
|
|
@@ -56,7 +63,6 @@ const SSR_RENDER_EXTERNALS = [
|
|
|
56
63
|
export const AKAN_OPTIONAL_BACKEND_EXTERNALS = [
|
|
57
64
|
"@libsql/client",
|
|
58
65
|
"bullmq",
|
|
59
|
-
"croner",
|
|
60
66
|
"ioredis",
|
|
61
67
|
"postgres",
|
|
62
68
|
"protobufjs",
|
|
@@ -78,6 +84,7 @@ export class ApplicationBuildRunner {
|
|
|
78
84
|
async build({ spinner = false }: BuildOptions = {}): Promise<BuildResult> {
|
|
79
85
|
// serial build is needed because of Bun.build is unstable for parallel build
|
|
80
86
|
const phaseOptions = { spinner };
|
|
87
|
+
const { web, assets } = await this.#app.getConfig();
|
|
81
88
|
await this.#runPhase("prepare", "Preparing output directory", () => this.#app.prepareCommand("build"), undefined, {
|
|
82
89
|
spinner,
|
|
83
90
|
});
|
|
@@ -92,18 +99,30 @@ export class ApplicationBuildRunner {
|
|
|
92
99
|
await this.#runPhase(
|
|
93
100
|
"ssr",
|
|
94
101
|
"Building SSR route artifacts",
|
|
95
|
-
() => this.#buildSsr(),
|
|
102
|
+
async () => (web.ssr ? await this.#buildSsr() : null),
|
|
96
103
|
(result) =>
|
|
97
104
|
result
|
|
98
105
|
? `${result.allRoutes.manifest.routeIds.length} routes, ${result.allRoutes.manifest.knownEntries.length} entries`
|
|
99
|
-
:
|
|
106
|
+
: web.ssr
|
|
107
|
+
? "skipped"
|
|
108
|
+
: "disabled by akan.config.ts web.ssr",
|
|
100
109
|
phaseOptions,
|
|
101
110
|
);
|
|
102
111
|
await this.#runPhase(
|
|
103
112
|
"csr",
|
|
104
113
|
"Building CSR assets",
|
|
105
|
-
() => this.#buildCsr(),
|
|
106
|
-
(result) => result?.outputDir ?? "skipped",
|
|
114
|
+
async () => (web.csr ? await this.#buildCsr() : null),
|
|
115
|
+
(result) => result?.outputDir ?? (web.csr ? "skipped" : "disabled by akan.config.ts web.csr"),
|
|
116
|
+
phaseOptions,
|
|
117
|
+
);
|
|
118
|
+
await this.#runPhase(
|
|
119
|
+
"assets",
|
|
120
|
+
"Trimming unread static assets",
|
|
121
|
+
async () => (assets.pruneFonts ? await new FontPruner(this.#app, assets).prune() : null),
|
|
122
|
+
(result) =>
|
|
123
|
+
result
|
|
124
|
+
? `${result.removed.length} font file(s) dropped, ${ApplicationBuildRunner.formatBytes(result.freedBytes)} freed; ${result.kept.length} kept`
|
|
125
|
+
: "disabled by akan.config.ts assets.pruneFonts",
|
|
107
126
|
phaseOptions,
|
|
108
127
|
);
|
|
109
128
|
await this.#runPhase(
|
|
@@ -166,7 +185,7 @@ export class ApplicationBuildRunner {
|
|
|
166
185
|
const akanConfig = await this.#app.getConfig();
|
|
167
186
|
await Promise.all([
|
|
168
187
|
this.#app.dist.writeJson("package.json", akanConfig.getProductionPackageJson()),
|
|
169
|
-
this.#app.dist.writeFile(`${this.#app.dist.cwdPath}/Dockerfile`, akanConfig.
|
|
188
|
+
this.#app.dist.writeFile(`${this.#app.dist.cwdPath}/Dockerfile`, akanConfig.dockerfile),
|
|
170
189
|
]);
|
|
171
190
|
}
|
|
172
191
|
|
|
@@ -175,6 +194,7 @@ export class ApplicationBuildRunner {
|
|
|
175
194
|
const backendExternals = [
|
|
176
195
|
...new Set([...akanConfig.externalLibs, ...SSR_RENDER_EXTERNALS, ...AKAN_OPTIONAL_BACKEND_EXTERNALS]),
|
|
177
196
|
];
|
|
197
|
+
const { web } = akanConfig;
|
|
178
198
|
const backendEntryPoints = [`${this.#app.cwdPath}/main.ts`, `${this.#app.cwdPath}/server.ts`];
|
|
179
199
|
for (const entrypoint of backendEntryPoints) {
|
|
180
200
|
if (!(await Bun.file(entrypoint).exists())) throw new Error(`Backend entrypoint not found: ${entrypoint}`);
|
|
@@ -188,17 +208,20 @@ export class ApplicationBuildRunner {
|
|
|
188
208
|
define: { "process.env.NODE_ENV": JSON.stringify("production") },
|
|
189
209
|
plugins: backendExternals.length > 0 ? [this.#createExternalSpecifiersPlugin(backendExternals)] : [],
|
|
190
210
|
});
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
211
|
+
// Nothing spawns the RSC worker without SSR, so an api-only image does not carry it.
|
|
212
|
+
const rscWorkerResult = web.ssr
|
|
213
|
+
? await this.#buildOrThrow("rsc-worker", {
|
|
214
|
+
entrypoints: [this.#resolveRscWorkerBuildEntry()],
|
|
215
|
+
outdir: this.#app.dist.cwdPath,
|
|
216
|
+
target: "bun",
|
|
217
|
+
minify: true,
|
|
218
|
+
naming: { entry: "[name].[ext]", chunk: "chunk-[hash].[ext]" },
|
|
219
|
+
conditions: ["react-server"],
|
|
220
|
+
// `akan build` must embed production react-server-dom regardless of the shell's NODE_ENV.
|
|
221
|
+
define: { "process.env.NODE_ENV": JSON.stringify("production") },
|
|
222
|
+
plugins: backendExternals.length > 0 ? [this.#createExternalSpecifiersPlugin(backendExternals)] : [],
|
|
223
|
+
})
|
|
224
|
+
: null;
|
|
202
225
|
const consoleRuntimeResult = await this.#buildOrThrow("console-runtime", {
|
|
203
226
|
entrypoints: [this.#resolveConsoleRuntimeBuildEntry()],
|
|
204
227
|
outdir: this.#app.dist.cwdPath,
|
|
@@ -209,8 +232,9 @@ export class ApplicationBuildRunner {
|
|
|
209
232
|
});
|
|
210
233
|
await this.#writeConsoleShim();
|
|
211
234
|
return {
|
|
212
|
-
entrypoints: backendEntryPoints.length + 2,
|
|
213
|
-
outputs:
|
|
235
|
+
entrypoints: backendEntryPoints.length + (rscWorkerResult ? 2 : 1),
|
|
236
|
+
outputs:
|
|
237
|
+
backendResult.outputs.length + (rscWorkerResult?.outputs.length ?? 0) + consoleRuntimeResult.outputs.length + 1,
|
|
214
238
|
};
|
|
215
239
|
}
|
|
216
240
|
|
|
@@ -102,4 +102,71 @@ describe("resolveSsrPageEntries", () => {
|
|
|
102
102
|
);
|
|
103
103
|
expect(generatedDictMacro).toContain("export const allDictionary = getAllDictionary();");
|
|
104
104
|
});
|
|
105
|
+
|
|
106
|
+
test("awaits an async grouped root layout in the CSR bundle instead of mounting it as JSX", async () => {
|
|
107
|
+
const appRoot = await makeTempRoot();
|
|
108
|
+
const pageRoot = path.join(appRoot, "page");
|
|
109
|
+
|
|
110
|
+
await write(path.join(appRoot, "env", "env.client.ts"), "export const env = {};\n");
|
|
111
|
+
await write(
|
|
112
|
+
path.join(pageRoot, "(user)", "_layout.tsx"),
|
|
113
|
+
"export default async function Layout({ children }) { await Promise.resolve(); return <div>{children}</div>; }\n",
|
|
114
|
+
);
|
|
115
|
+
await write(
|
|
116
|
+
path.join(pageRoot, "(sign)", "_layout.tsx"),
|
|
117
|
+
"export default function Layout({ children }) { return children; }\n",
|
|
118
|
+
);
|
|
119
|
+
|
|
120
|
+
const entries = await resolveSsrPageEntries({
|
|
121
|
+
appCwdPath: appRoot,
|
|
122
|
+
appName: "demo",
|
|
123
|
+
pageKeys: ["./(user)/_layout.tsx", "./(user)/self/_index.tsx", "./(sign)/_layout.tsx", "./(sign)/signin.tsx"],
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
const userRoot = entries.find((entry) => entry.key === "./(user)/__root_layout.tsx");
|
|
127
|
+
const userSource = await Bun.file(userRoot?.moduleAbsPath ?? "").text();
|
|
128
|
+
expect(userSource).toContain("<System.Provider");
|
|
129
|
+
expect(userSource).toContain("export default async function GeneratedLayout(");
|
|
130
|
+
expect(userSource).toContain('process.env.AKAN_PUBLIC_RENDER_ENV === "csr"');
|
|
131
|
+
expect(userSource).toContain("? await UserLayout({ params, searchParams, children })");
|
|
132
|
+
expect(userSource).toContain(": <UserLayout params={params} searchParams={searchParams}>{children}</UserLayout>;");
|
|
133
|
+
expect(userSource).toContain(" {layout}\n </System.Provider>");
|
|
134
|
+
|
|
135
|
+
const signRoot = entries.find((entry) => entry.key === "./(sign)/__root_layout.tsx");
|
|
136
|
+
const signSource = await Bun.file(signRoot?.moduleAbsPath ?? "").text();
|
|
137
|
+
expect(signSource).toContain("<System.Provider");
|
|
138
|
+
expect(signSource).toContain("export default function GeneratedLayout(");
|
|
139
|
+
expect(signSource).not.toContain("await UserLayout(");
|
|
140
|
+
expect(signSource).toContain(
|
|
141
|
+
" <UserLayout params={params} searchParams={searchParams}>{children}</UserLayout>\n </System.Provider>",
|
|
142
|
+
);
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
test("returns the awaited node directly for an async nested root boundary", async () => {
|
|
146
|
+
const appRoot = await makeTempRoot();
|
|
147
|
+
const pageRoot = path.join(appRoot, "page");
|
|
148
|
+
|
|
149
|
+
await write(path.join(appRoot, "env", "env.client.ts"), "export const env = {};\n");
|
|
150
|
+
await write(
|
|
151
|
+
path.join(pageRoot, "_layout.tsx"),
|
|
152
|
+
"export default function Layout({ children }) { return children; }\n",
|
|
153
|
+
);
|
|
154
|
+
await write(
|
|
155
|
+
path.join(pageRoot, "(home)", "_layout.tsx"),
|
|
156
|
+
"const Layout = async ({ children }) => children;\nexport default Layout;\n",
|
|
157
|
+
);
|
|
158
|
+
|
|
159
|
+
const entries = await resolveSsrPageEntries({
|
|
160
|
+
appCwdPath: appRoot,
|
|
161
|
+
appName: "demo",
|
|
162
|
+
pageKeys: ["./_layout.tsx", "./(home)/_layout.tsx", "./(home)/_index.tsx"],
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
const groupedRoot = entries.find((entry) => entry.key === "./(home)/__root_layout.tsx");
|
|
166
|
+
const generatedSource = await Bun.file(groupedRoot?.moduleAbsPath ?? "").text();
|
|
167
|
+
expect(generatedSource).not.toContain("<System.Provider");
|
|
168
|
+
expect(generatedSource).toContain("export default async function GeneratedLayout(");
|
|
169
|
+
expect(generatedSource).toContain("? await UserLayout({ params, searchParams, children })");
|
|
170
|
+
expect(generatedSource).toContain(" return layout;\n}");
|
|
171
|
+
});
|
|
105
172
|
});
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { mkdir } from "node:fs/promises";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import type { App } from "../commandDecorators";
|
|
4
|
+
import { AsyncDefaultExportDetector } from "../transforms/asyncDefaultExportDetector";
|
|
4
5
|
|
|
5
6
|
export interface PageEntry {
|
|
6
7
|
key: string;
|
|
@@ -55,7 +56,7 @@ interface RootBoundary {
|
|
|
55
56
|
segments: string[];
|
|
56
57
|
}
|
|
57
58
|
|
|
58
|
-
function getRootBoundarySegments(key: string): string[] | null {
|
|
59
|
+
export function getRootBoundarySegments(key: string): string[] | null {
|
|
59
60
|
const match = LAYOUT_KEY_RE.exec(key);
|
|
60
61
|
if (!match) return null;
|
|
61
62
|
const prefix = match[1]?.replace(/\/$/, "");
|
|
@@ -76,7 +77,7 @@ function implicitDictionaryMacroAbsPath(appCwdPath: string): string {
|
|
|
76
77
|
return path.join(path.resolve(appCwdPath), IMPLICIT_DICT_DIR, "useDict.ts");
|
|
77
78
|
}
|
|
78
79
|
|
|
79
|
-
function isRootBoundarySegments(segments: string[], basePaths: Iterable<string>): boolean {
|
|
80
|
+
export function isRootBoundarySegments(segments: string[], basePaths: Iterable<string>): boolean {
|
|
80
81
|
const firstVisibleIndex = segments.findIndex((segment) => !/^\(.+\)$/.test(segment));
|
|
81
82
|
if (firstVisibleIndex === -1) return segments.length <= 1;
|
|
82
83
|
if (segments.slice(firstVisibleIndex + 1).some((segment) => /^\(.+\)$/.test(segment))) return false;
|
|
@@ -191,6 +192,25 @@ async function writeGeneratedRootLayoutFile(opts: {
|
|
|
191
192
|
const userImport = sourceSpecifier
|
|
192
193
|
? `import UserLayout, * as userLayout from ${JSON.stringify(sourceSpecifier)};\n`
|
|
193
194
|
: "const UserLayout = ({ children }) => children;\nconst userLayout = {};\n";
|
|
195
|
+
const isAsyncUserLayout = opts.boundary.sourceAbsPath
|
|
196
|
+
? await AsyncDefaultExportDetector.detect(opts.boundary.sourceAbsPath)
|
|
197
|
+
: false;
|
|
198
|
+
const userLayoutElement = "<UserLayout params={params} searchParams={searchParams}>{children}</UserLayout>";
|
|
199
|
+
// React has no async client component, so the CSR bundle calls an async layout and awaits its node the way
|
|
200
|
+
// `RenderLayer` does for pages. The RSC render keeps the element: awaiting there would hold the shell behind
|
|
201
|
+
// the layout's own awaits instead of streaming it as its own Flight chunk.
|
|
202
|
+
const layoutSignature = isAsyncUserLayout
|
|
203
|
+
? "export default async function GeneratedLayout"
|
|
204
|
+
: "export default function GeneratedLayout";
|
|
205
|
+
const layoutBinding = isAsyncUserLayout
|
|
206
|
+
? ` const layout =
|
|
207
|
+
process.env.AKAN_PUBLIC_RENDER_ENV === "csr"
|
|
208
|
+
? await UserLayout({ params, searchParams, children })
|
|
209
|
+
: ${userLayoutElement};
|
|
210
|
+
`
|
|
211
|
+
: "";
|
|
212
|
+
const layoutChild = isAsyncUserLayout ? "{layout}" : userLayoutElement;
|
|
213
|
+
const layoutReturn = isAsyncUserLayout ? "layout" : userLayoutElement;
|
|
194
214
|
const source = opts.includeSystemProvider
|
|
195
215
|
? `import type { LayoutProps, PageProps } from "akanjs/client";
|
|
196
216
|
import { loadFonts } from "akanjs/client";
|
|
@@ -222,8 +242,8 @@ export const NotFound = userLayout.NotFound ?? inheritedLayout.NotFound;
|
|
|
222
242
|
export const Error = userLayout.Error ?? inheritedLayout.Error;
|
|
223
243
|
export const pageConfig = userLayout.pageConfig ?? inheritedLayout.pageConfig;
|
|
224
244
|
|
|
225
|
-
|
|
226
|
-
return (
|
|
245
|
+
${layoutSignature}({ children, params, searchParams }: LayoutProps) {
|
|
246
|
+
${layoutBinding} return (
|
|
227
247
|
<System.Provider
|
|
228
248
|
of={GeneratedLayout as never}
|
|
229
249
|
appName=${JSON.stringify(opts.appName)}
|
|
@@ -239,7 +259,7 @@ export default function GeneratedLayout({ children, params, searchParams }: Layo
|
|
|
239
259
|
wsConnect={userLayout.wsConnect ?? inheritedLayout.wsConnect ?? true}
|
|
240
260
|
allDictionary={process.env.AKAN_PUBLIC_RENDER_ENV === "ssr" ? allDictionary : undefined}
|
|
241
261
|
>
|
|
242
|
-
|
|
262
|
+
${layoutChild}
|
|
243
263
|
</System.Provider>
|
|
244
264
|
);
|
|
245
265
|
}
|
|
@@ -264,8 +284,8 @@ export const NotFound = userLayout.NotFound ?? inheritedLayout.NotFound;
|
|
|
264
284
|
export const Error = userLayout.Error ?? inheritedLayout.Error;
|
|
265
285
|
export const pageConfig = userLayout.pageConfig ?? inheritedLayout.pageConfig;
|
|
266
286
|
|
|
267
|
-
|
|
268
|
-
return
|
|
287
|
+
${layoutSignature}({ children, params, searchParams }: LayoutProps) {
|
|
288
|
+
${layoutBinding} return ${layoutReturn};
|
|
269
289
|
}
|
|
270
290
|
`;
|
|
271
291
|
await Bun.write(absPath, source);
|
package/biome.base.json
ADDED
|
@@ -0,0 +1,340 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://biomejs.dev/schemas/2.5.8/schema.json",
|
|
3
|
+
"vcs": {
|
|
4
|
+
"enabled": true,
|
|
5
|
+
"clientKind": "git",
|
|
6
|
+
"useIgnoreFile": false
|
|
7
|
+
},
|
|
8
|
+
"formatter": {
|
|
9
|
+
"enabled": true,
|
|
10
|
+
"indentStyle": "space",
|
|
11
|
+
"indentWidth": 2,
|
|
12
|
+
"lineWidth": 120
|
|
13
|
+
},
|
|
14
|
+
"linter": {
|
|
15
|
+
"enabled": true,
|
|
16
|
+
"rules": {
|
|
17
|
+
"preset": "recommended",
|
|
18
|
+
"suspicious": {
|
|
19
|
+
"noConsole": {
|
|
20
|
+
"level": "error",
|
|
21
|
+
"options": {
|
|
22
|
+
"allow": ["assert", "error", "info", "warn"]
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
"noArrayIndexKey": "off",
|
|
26
|
+
"noShadowRestrictedNames": "off",
|
|
27
|
+
"noUnnecessaryConditions": {
|
|
28
|
+
"level": "warn"
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
"correctness": {
|
|
32
|
+
"noUnusedFunctionParameters": "off",
|
|
33
|
+
"noUnusedImports": {
|
|
34
|
+
"level": "error",
|
|
35
|
+
"fix": "safe"
|
|
36
|
+
},
|
|
37
|
+
"useParseIntRadix": "off",
|
|
38
|
+
"useExhaustiveDependencies": "off",
|
|
39
|
+
"useHookAtTopLevel": "off"
|
|
40
|
+
},
|
|
41
|
+
"nursery": {
|
|
42
|
+
"useSortedClasses": {
|
|
43
|
+
"level": "error",
|
|
44
|
+
"fix": "safe",
|
|
45
|
+
"options": {
|
|
46
|
+
"attributes": ["classList"],
|
|
47
|
+
"functions": ["cn"]
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
"a11y": "off",
|
|
52
|
+
"complexity": {
|
|
53
|
+
"noStaticOnlyClass": "off"
|
|
54
|
+
},
|
|
55
|
+
"style": {
|
|
56
|
+
"useTemplate": {
|
|
57
|
+
"level": "warn",
|
|
58
|
+
"fix": "safe"
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
"domains": {
|
|
63
|
+
"project": "recommended",
|
|
64
|
+
"react": "recommended",
|
|
65
|
+
"test": "recommended",
|
|
66
|
+
"types": "all"
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
"javascript": {
|
|
70
|
+
"parser": {
|
|
71
|
+
"unsafeParameterDecoratorsEnabled": true
|
|
72
|
+
},
|
|
73
|
+
"formatter": {
|
|
74
|
+
"quoteStyle": "double"
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
"assist": {
|
|
78
|
+
"enabled": true,
|
|
79
|
+
"actions": {
|
|
80
|
+
"source": {
|
|
81
|
+
"organizeImports": "on"
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
},
|
|
85
|
+
"overrides": [
|
|
86
|
+
{
|
|
87
|
+
"includes": [
|
|
88
|
+
"**/env.client.local.ts",
|
|
89
|
+
"**/env.client.debug.ts",
|
|
90
|
+
"**/env.client.develop.ts",
|
|
91
|
+
"**/env.client.main.ts",
|
|
92
|
+
"**/env.client.testing.ts",
|
|
93
|
+
"**/env.server.local.ts",
|
|
94
|
+
"**/env.server.develop.ts",
|
|
95
|
+
"**/env.server.main.ts",
|
|
96
|
+
"**/env.server.testing.ts",
|
|
97
|
+
"**/env.server.type.ts",
|
|
98
|
+
"apps/*/lib/cnst.ts",
|
|
99
|
+
"apps/*/lib/dict.ts",
|
|
100
|
+
"apps/*/lib/db.ts",
|
|
101
|
+
"apps/*/lib/srv.ts",
|
|
102
|
+
"apps/*/lib/st.ts",
|
|
103
|
+
"apps/*/lib/sig.ts",
|
|
104
|
+
"apps/*/lib/useClient.ts",
|
|
105
|
+
"apps/*/lib/useServer.ts",
|
|
106
|
+
"apps/*/client.ts",
|
|
107
|
+
"apps/*/server.ts",
|
|
108
|
+
"apps/*/lib/*/index.tsx",
|
|
109
|
+
"libs/*/lib/cnst.ts",
|
|
110
|
+
"libs/*/lib/dict.ts",
|
|
111
|
+
"libs/*/lib/db.ts",
|
|
112
|
+
"libs/*/lib/srv.ts",
|
|
113
|
+
"libs/*/lib/st.ts",
|
|
114
|
+
"libs/*/lib/sig.ts",
|
|
115
|
+
"libs/*/lib/useClient.ts",
|
|
116
|
+
"libs/*/lib/useServer.ts",
|
|
117
|
+
"libs/*/client.ts",
|
|
118
|
+
"libs/*/server.ts",
|
|
119
|
+
"libs/*/index.ts",
|
|
120
|
+
"libs/*/lib/*/index.tsx",
|
|
121
|
+
"apps/*/lib/__lib/**",
|
|
122
|
+
"libs/*/lib/__lib/**"
|
|
123
|
+
],
|
|
124
|
+
"linter": { "enabled": false },
|
|
125
|
+
"formatter": { "enabled": false },
|
|
126
|
+
"assist": { "enabled": false }
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
"includes": [
|
|
130
|
+
"apps/**/*.ts",
|
|
131
|
+
"apps/**/*.tsx",
|
|
132
|
+
"libs/**/*.ts",
|
|
133
|
+
"libs/**/*.tsx",
|
|
134
|
+
"!**/*.test.ts",
|
|
135
|
+
"!**/*.test.tsx",
|
|
136
|
+
"!**/*.spec.ts",
|
|
137
|
+
"!**/*.spec.tsx",
|
|
138
|
+
"!**/*.constant.ts",
|
|
139
|
+
"!**/common/**",
|
|
140
|
+
"!**/env/**"
|
|
141
|
+
],
|
|
142
|
+
"plugins": ["./node_modules/@akanjs/devkit/lint/no-throw-raw-error.grit"]
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
"includes": [
|
|
146
|
+
"{apps,libs}/**/page/**/*.ts",
|
|
147
|
+
"{apps,libs}/**/page/**/*.tsx",
|
|
148
|
+
"{apps,libs}/**/*.Unit.tsx",
|
|
149
|
+
"{apps,libs}/**/*.View.tsx"
|
|
150
|
+
],
|
|
151
|
+
"plugins": [
|
|
152
|
+
"./node_modules/@akanjs/devkit/lint/no-import-client-functions.grit",
|
|
153
|
+
"./node_modules/@akanjs/devkit/lint/no-use-client-in-server.grit"
|
|
154
|
+
]
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
"includes": ["{apps,libs}/**/page/**/*.ts", "{apps,libs}/**/page/**/*.tsx"],
|
|
158
|
+
"plugins": ["./node_modules/@akanjs/devkit/lint/non-scalar-props-restricted.grit"]
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
"includes": [
|
|
162
|
+
"{apps,libs}/**/*.constant.ts",
|
|
163
|
+
"{apps,libs}/**/*.document.ts",
|
|
164
|
+
"{apps,libs}/**/*.service.ts",
|
|
165
|
+
"{apps,libs}/**/*.store.ts"
|
|
166
|
+
],
|
|
167
|
+
"plugins": ["./node_modules/@akanjs/devkit/lint/no-js-private-class-method.grit"]
|
|
168
|
+
},
|
|
169
|
+
{
|
|
170
|
+
"includes": ["{apps,libs}/**/*.store.ts"],
|
|
171
|
+
"plugins": ["./node_modules/@akanjs/devkit/lint/no-return-in-store-action.grit"]
|
|
172
|
+
},
|
|
173
|
+
{
|
|
174
|
+
"includes": ["{apps,libs}/**/*.ts", "{apps,libs}/**/*.tsx"],
|
|
175
|
+
"plugins": ["./node_modules/@akanjs/devkit/lint/no-deprecated-log-level.grit"]
|
|
176
|
+
},
|
|
177
|
+
{
|
|
178
|
+
"includes": ["{apps,libs}/**/*.signal.ts"],
|
|
179
|
+
"plugins": ["./node_modules/@akanjs/devkit/lint/no-redeclare-predefined-endpoint.grit"]
|
|
180
|
+
},
|
|
181
|
+
{
|
|
182
|
+
"includes": ["{apps,libs}/**/*.Util.tsx", "{apps,libs}/**/*.Zone.tsx"],
|
|
183
|
+
"plugins": ["./node_modules/@akanjs/devkit/lint/no-model-type-in-util-zone.grit"]
|
|
184
|
+
},
|
|
185
|
+
{
|
|
186
|
+
"includes": ["{apps,libs}/**/ui/**/*.tsx", "!**/*.test.tsx", "!**/*.spec.tsx"],
|
|
187
|
+
"plugins": ["./node_modules/@akanjs/devkit/lint/no-async-component-in-ui.grit"]
|
|
188
|
+
},
|
|
189
|
+
{
|
|
190
|
+
"includes": ["{apps,libs}/**/*.tsx", "!**/*.test.tsx", "!**/*.spec.tsx"],
|
|
191
|
+
"plugins": ["./node_modules/@akanjs/devkit/lint/no-unpublished-form-setter.grit"]
|
|
192
|
+
},
|
|
193
|
+
{
|
|
194
|
+
"includes": [
|
|
195
|
+
"{apps,libs}/**/*.ts",
|
|
196
|
+
"{apps,libs}/**/*.tsx",
|
|
197
|
+
"!**/*.test.ts",
|
|
198
|
+
"!**/*.test.tsx",
|
|
199
|
+
"!**/*.spec.ts",
|
|
200
|
+
"!**/*.spec.tsx"
|
|
201
|
+
],
|
|
202
|
+
"plugins": ["./node_modules/@akanjs/devkit/lint/no-init-fetch-in-client.grit"]
|
|
203
|
+
},
|
|
204
|
+
{
|
|
205
|
+
"includes": [
|
|
206
|
+
"**/ui/**/*.ts",
|
|
207
|
+
"**/ui/**/*.tsx",
|
|
208
|
+
"**/webkit/**/*.ts",
|
|
209
|
+
"**/webkit/**/*.tsx",
|
|
210
|
+
"**/common/**/*.ts",
|
|
211
|
+
"**/page/**/*.tsx",
|
|
212
|
+
"**/*.constant.ts",
|
|
213
|
+
"**/*.store.ts",
|
|
214
|
+
"**/*.Template.tsx",
|
|
215
|
+
"**/*.Unit.tsx",
|
|
216
|
+
"**/*.Util.tsx",
|
|
217
|
+
"**/*.View.tsx",
|
|
218
|
+
"**/*.Zone.tsx",
|
|
219
|
+
"!**/*.test.ts",
|
|
220
|
+
"!**/*.test.tsx",
|
|
221
|
+
"!**/*.spec.ts",
|
|
222
|
+
"!**/*.spec.tsx"
|
|
223
|
+
],
|
|
224
|
+
"plugins": ["./node_modules/@akanjs/devkit/lint/no-bang-comment-in-client.grit"]
|
|
225
|
+
},
|
|
226
|
+
{
|
|
227
|
+
"includes": [
|
|
228
|
+
"{apps,libs}/**/*.constant.ts",
|
|
229
|
+
"{apps,libs}/**/*.dictionary.ts",
|
|
230
|
+
"{apps,libs}/**/*.document.ts",
|
|
231
|
+
"{apps,libs}/**/*.service.ts",
|
|
232
|
+
"{apps,libs}/**/*.signal.ts",
|
|
233
|
+
"{apps,libs}/**/*.store.ts",
|
|
234
|
+
"{apps,libs}/**/*.Template.tsx",
|
|
235
|
+
"{apps,libs}/**/*.Unit.tsx",
|
|
236
|
+
"{apps,libs}/**/*.Util.tsx",
|
|
237
|
+
"{apps,libs}/**/*.View.tsx",
|
|
238
|
+
"{apps,libs}/**/*.Zone.tsx"
|
|
239
|
+
],
|
|
240
|
+
"plugins": ["./node_modules/@akanjs/devkit/lint/no-deep-internal-import.grit"]
|
|
241
|
+
},
|
|
242
|
+
{
|
|
243
|
+
"includes": [
|
|
244
|
+
"{apps,libs}/**/page/**/*.ts",
|
|
245
|
+
"{apps,libs}/**/page/**/*.tsx",
|
|
246
|
+
"{apps,libs}/**/index.ts",
|
|
247
|
+
"{apps,libs}/**/index.tsx",
|
|
248
|
+
"{apps,libs}/**/cnst.ts",
|
|
249
|
+
"{apps,libs}/**/db.ts",
|
|
250
|
+
"{apps,libs}/**/dict.ts",
|
|
251
|
+
"{apps,libs}/**/option.ts",
|
|
252
|
+
"{apps,libs}/**/sig.ts",
|
|
253
|
+
"{apps,libs}/**/srv.ts",
|
|
254
|
+
"{apps,libs}/**/st.ts",
|
|
255
|
+
"{apps,libs}/**/*.constant.ts",
|
|
256
|
+
"{apps,libs}/**/*.dictionary.ts",
|
|
257
|
+
"{apps,libs}/**/*.document.ts",
|
|
258
|
+
"{apps,libs}/**/*.service.ts",
|
|
259
|
+
"{apps,libs}/**/*.signal.ts",
|
|
260
|
+
"{apps,libs}/**/*.signal.test.ts",
|
|
261
|
+
"{apps,libs}/**/*.service.test.ts",
|
|
262
|
+
"{apps,libs}/**/*.store.ts",
|
|
263
|
+
"{apps,libs}/**/*.Template.tsx",
|
|
264
|
+
"{apps,libs}/**/*.Unit.tsx",
|
|
265
|
+
"{apps,libs}/**/*.Util.tsx",
|
|
266
|
+
"{apps,libs}/**/*.View.tsx",
|
|
267
|
+
"{apps,libs}/**/*.Zone.tsx"
|
|
268
|
+
],
|
|
269
|
+
"plugins": [
|
|
270
|
+
"./node_modules/@akanjs/devkit/lint/no-import-external-library.grit",
|
|
271
|
+
"./node_modules/@akanjs/devkit/lint/no-deep-internal-import.grit"
|
|
272
|
+
]
|
|
273
|
+
},
|
|
274
|
+
{
|
|
275
|
+
"includes": [
|
|
276
|
+
"apps/**/*.tsx",
|
|
277
|
+
"libs/**/*.tsx",
|
|
278
|
+
"apps/**/ui/**/*.ts",
|
|
279
|
+
"libs/**/ui/**/*.ts",
|
|
280
|
+
"apps/**/webkit/**/*.ts",
|
|
281
|
+
"libs/**/webkit/**/*.ts",
|
|
282
|
+
"apps/**/page/**/*.ts",
|
|
283
|
+
"libs/**/page/**/*.ts",
|
|
284
|
+
"apps/**/common/**/*.ts",
|
|
285
|
+
"libs/**/common/**/*.ts",
|
|
286
|
+
"apps/**/*.store.ts",
|
|
287
|
+
"libs/**/*.store.ts",
|
|
288
|
+
"apps/**/*.constant.ts",
|
|
289
|
+
"libs/**/*.constant.ts",
|
|
290
|
+
"!**/*.test.ts",
|
|
291
|
+
"!**/*.test.tsx",
|
|
292
|
+
"!**/*.spec.ts",
|
|
293
|
+
"!**/*.spec.tsx"
|
|
294
|
+
],
|
|
295
|
+
"plugins": ["./node_modules/@akanjs/devkit/lint/no-import-server-in-client.grit"]
|
|
296
|
+
},
|
|
297
|
+
{
|
|
298
|
+
"includes": [
|
|
299
|
+
"apps/**/*.document.ts",
|
|
300
|
+
"libs/**/*.document.ts",
|
|
301
|
+
"apps/**/*.dictionary.ts",
|
|
302
|
+
"libs/**/*.dictionary.ts",
|
|
303
|
+
"apps/**/*.service.ts",
|
|
304
|
+
"libs/**/*.service.ts",
|
|
305
|
+
"apps/**/*.signal.ts",
|
|
306
|
+
"libs/**/*.signal.ts",
|
|
307
|
+
"apps/**/srvkit/**/*.ts",
|
|
308
|
+
"libs/**/srvkit/**/*.ts",
|
|
309
|
+
"apps/**/common/**/*.ts",
|
|
310
|
+
"libs/**/common/**/*.ts",
|
|
311
|
+
"apps/**/*.constant.ts",
|
|
312
|
+
"libs/**/*.constant.ts",
|
|
313
|
+
"!**/*.test.ts",
|
|
314
|
+
"!**/*.test.tsx",
|
|
315
|
+
"!**/*.spec.ts",
|
|
316
|
+
"!**/*.spec.tsx"
|
|
317
|
+
],
|
|
318
|
+
"plugins": ["./node_modules/@akanjs/devkit/lint/no-import-client-in-server.grit"]
|
|
319
|
+
},
|
|
320
|
+
{
|
|
321
|
+
"includes": [
|
|
322
|
+
"apps/**/*.ts",
|
|
323
|
+
"apps/**/*.tsx",
|
|
324
|
+
"libs/**/*.ts",
|
|
325
|
+
"libs/**/*.tsx",
|
|
326
|
+
"!**/*.test.ts",
|
|
327
|
+
"!**/*.test.tsx",
|
|
328
|
+
"!**/*.spec.ts",
|
|
329
|
+
"!**/*.spec.tsx"
|
|
330
|
+
],
|
|
331
|
+
"plugins": [
|
|
332
|
+
"./node_modules/@akanjs/devkit/lint/no-raw-palette-class.grit",
|
|
333
|
+
"./node_modules/@akanjs/devkit/lint/no-arbitrary-color.grit",
|
|
334
|
+
"./node_modules/@akanjs/devkit/lint/no-daisyui-legacy-class.grit",
|
|
335
|
+
"./node_modules/@akanjs/devkit/lint/no-inline-color.grit",
|
|
336
|
+
"./node_modules/@akanjs/devkit/lint/no-interpolated-arbitrary-class.grit"
|
|
337
|
+
]
|
|
338
|
+
}
|
|
339
|
+
]
|
|
340
|
+
}
|
package/biomeBase.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/** `extends` target for a workspace `biome.json`; Biome resolves it through node_modules. */
|
|
2
|
+
export const biomeBaseConfig = "@akanjs/devkit/biome.base.json";
|
|
3
|
+
|
|
4
|
+
// Biome moves rules between groups across minors — `noUnnecessaryConditions` sat in `nursery` at 2.4 and moved to
|
|
5
|
+
// `suspicious` at 2.5 — and the stale position is a hard "unknown key" error, not a warning. A workspace whose
|
|
6
|
+
// Biome disagrees with the shipped base config therefore fails to load it at all, which is why the version is
|
|
7
|
+
// pinned here instead of resolved to latest at create time. Bump this and `biome.base.json` in one commit, and run
|
|
8
|
+
// `biome migrate --write` in the workspace root and in `pkgs/@akanjs/devkit` so both configs move together.
|
|
9
|
+
export const biomeVersion = "2.5.8";
|
package/capacitorApp.ts
CHANGED
|
@@ -123,6 +123,16 @@ interface MaterializeCapacitorConfigOptions {
|
|
|
123
123
|
}
|
|
124
124
|
type MobilePlatform = "ios" | "android";
|
|
125
125
|
|
|
126
|
+
/**
|
|
127
|
+
* `AppExecutor.spawn`'s own options plus the two the Capacitor config is written from before the spawn:
|
|
128
|
+
* the platform the command targets, and — for iOS — whether it targets a device or a simulator, which
|
|
129
|
+
* decide the `capacitor.config.json` that command reads.
|
|
130
|
+
*/
|
|
131
|
+
type SpawnMobileOptions = Parameters<AppExecutor["spawn"]>[2] & {
|
|
132
|
+
platform?: MobilePlatform;
|
|
133
|
+
iosRunTargetKind?: IosRunTargetKind;
|
|
134
|
+
};
|
|
135
|
+
|
|
126
136
|
export interface LocalDevHostResolution {
|
|
127
137
|
host: string;
|
|
128
138
|
source: "override" | "detected" | "loopback" | "platform";
|