@akanjs/cli 2.1.0-rc.9 → 2.1.1-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.
- package/README.ko.md +63 -0
- package/README.md +62 -0
- package/guidelines/componentRule/componentRule.generate.json +4 -10
- package/guidelines/cssRule/cssRule.generate.json +4 -10
- package/guidelines/docPageRule/docPageRule.generate.json +4 -10
- package/guidelines/docPageRule/docPageRule.instruction.md +1 -1
- package/guidelines/docSyncRule/docSyncRule.generate.json +4 -10
- package/guidelines/enumConstant/enumConstant.generate.json +4 -10
- package/guidelines/fieldRule/fieldRule.generate.json +4 -10
- package/guidelines/framework/framework.generate.json +4 -10
- package/guidelines/modelConstant/modelConstant.generate.json +4 -10
- package/guidelines/modelDictionary/modelDictionary.generate.json +4 -10
- package/guidelines/modelDocument/modelDocument.generate.json +4 -10
- package/guidelines/modelService/modelService.generate.json +4 -10
- package/guidelines/modelSignal/modelSignal.generate.json +4 -10
- package/guidelines/modelStore/modelStore.generate.json +4 -10
- package/guidelines/modelTemplate/modelTemplate.generate.json +4 -10
- package/guidelines/modelUnit/modelUnit.generate.json +4 -10
- package/guidelines/modelUtil/modelUtil.generate.json +4 -10
- package/guidelines/modelView/modelView.generate.json +4 -10
- package/guidelines/modelZone/modelZone.generate.json +4 -10
- package/guidelines/moduleCodegen/moduleCodegen.generate.json +4 -10
- package/guidelines/moduleOverview/moduleOverview.generate.json +4 -10
- package/guidelines/scalarConstant/scalarConstant.generate.json +4 -10
- package/guidelines/scalarDictionary/scalarDictionary.generate.json +4 -10
- package/guidelines/scalarModule/scalarModule.generate.json +4 -10
- package/guidelines/sharedUiUsage/sharedUiUsage.generate.json +4 -10
- package/guidelines/utilUiUsage/utilUiUsage.generate.json +4 -10
- package/incrementalBuilder.proc.js +237 -71
- package/index.js +586 -128
- package/package.json +3 -2
- package/templates/libRoot/lib/___libName__/__libName__.signal.ts +15 -0
package/index.js
CHANGED
|
@@ -22,9 +22,12 @@ import { mkdir } from "fs/promises";
|
|
|
22
22
|
var basePath = `${Bun.env.HOME ?? Bun.env.USERPROFILE}/.akan`;
|
|
23
23
|
var configPath = `${basePath}/config.json`;
|
|
24
24
|
var akanCloudHost = process.env.AKAN_PUBLIC_OPERATION_MODE === "local" ? "http://localhost" : "https://cloud.akanjs.com";
|
|
25
|
-
var akanCloudUrl = `${akanCloudHost}${process.env.AKAN_PUBLIC_OPERATION_MODE === "local" ? ":8282" : ""}
|
|
25
|
+
var akanCloudUrl = `${akanCloudHost}${process.env.AKAN_PUBLIC_OPERATION_MODE === "local" ? ":8282" : ""}/api`;
|
|
26
26
|
var defaultHostConfig = {};
|
|
27
|
-
var defaultAkanGlobalConfig = {
|
|
27
|
+
var defaultAkanGlobalConfig = {
|
|
28
|
+
cloudHost: {},
|
|
29
|
+
llm: null
|
|
30
|
+
};
|
|
28
31
|
|
|
29
32
|
// pkgs/@akanjs/devkit/fileSys.ts
|
|
30
33
|
import { stat } from "fs/promises";
|
|
@@ -484,7 +487,18 @@ var DEFAULT_OPTIMIZE_IMPORTS = [
|
|
|
484
487
|
var WORKSPACE_BARREL_FACETS = ["ui", "webkit", "common", "client", "server"];
|
|
485
488
|
var SSR_RUNTIME_PACKAGES = ["react", "react-dom", "react-server-dom-webpack"];
|
|
486
489
|
var NATIVE_RUNTIME_PACKAGES = ["sharp"];
|
|
487
|
-
var
|
|
490
|
+
var DEFAULT_BACKEND_RUNTIME_PACKAGES = ["croner"];
|
|
491
|
+
var DATABASE_MODE_RUNTIME_PACKAGES = {
|
|
492
|
+
single: [],
|
|
493
|
+
multiple: ["@libsql/client", "bullmq", "ioredis", "protobufjs"],
|
|
494
|
+
cluster: ["bullmq", "ioredis", "postgres", "protobufjs"]
|
|
495
|
+
};
|
|
496
|
+
var AKAN_RUNTIME_PACKAGES = new Set([
|
|
497
|
+
...SSR_RUNTIME_PACKAGES,
|
|
498
|
+
...NATIVE_RUNTIME_PACKAGES,
|
|
499
|
+
...DEFAULT_BACKEND_RUNTIME_PACKAGES,
|
|
500
|
+
...Object.values(DATABASE_MODE_RUNTIME_PACKAGES).flat()
|
|
501
|
+
]);
|
|
488
502
|
var DEFAULT_AKAN_IMAGE_CONFIG = {
|
|
489
503
|
deviceSizes: [640, 750, 828, 1080, 1200, 1920, 2048, 3840],
|
|
490
504
|
imageSizes: [32, 48, 64, 96, 128, 256, 384],
|
|
@@ -693,13 +707,22 @@ CMD [${command.map((c) => `"${c}"`).join(",")}]`;
|
|
|
693
707
|
if (AKAN_RUNTIME_PACKAGES.has(lib))
|
|
694
708
|
return akanPackageJson.dependencies?.[lib] ?? akanPackageJson.peerDependencies?.[lib];
|
|
695
709
|
}
|
|
710
|
+
#getProductionRuntimePackages() {
|
|
711
|
+
return [
|
|
712
|
+
...this.externalLibs,
|
|
713
|
+
...SSR_RUNTIME_PACKAGES,
|
|
714
|
+
...NATIVE_RUNTIME_PACKAGES,
|
|
715
|
+
...DEFAULT_BACKEND_RUNTIME_PACKAGES,
|
|
716
|
+
...DATABASE_MODE_RUNTIME_PACKAGES[this.defaultDatabaseMode]
|
|
717
|
+
];
|
|
718
|
+
}
|
|
696
719
|
getProductionPackageJson(data = {}) {
|
|
697
720
|
return {
|
|
698
721
|
name: this.app.name,
|
|
699
722
|
description: this.app.name,
|
|
700
723
|
version: "1.0.0",
|
|
701
724
|
main: "./main.js",
|
|
702
|
-
dependencies: Object.fromEntries([...new Set(
|
|
725
|
+
dependencies: Object.fromEntries([...new Set(this.#getProductionRuntimePackages())].map((lib) => {
|
|
703
726
|
const version = this.#resolveProductionDependencyVersion(lib);
|
|
704
727
|
if (!version)
|
|
705
728
|
throw new Error(`Dependency ${lib} not found in package.json`);
|
|
@@ -2118,7 +2141,6 @@ class Executor {
|
|
|
2118
2141
|
this.logger = new Logger4(name);
|
|
2119
2142
|
this.logs = [];
|
|
2120
2143
|
this.cwdPath = cwdPath;
|
|
2121
|
-
//! TODO: 테스트 확인 필요
|
|
2122
2144
|
}
|
|
2123
2145
|
#stdout(data) {
|
|
2124
2146
|
if (Executor.verbose)
|
|
@@ -3960,6 +3982,16 @@ function findRootBoundaries(pageKeys, appCwdPath, basePaths) {
|
|
|
3960
3982
|
}
|
|
3961
3983
|
return [...boundaries.values()].sort((a, b) => a.segments.join("/").localeCompare(b.segments.join("/")));
|
|
3962
3984
|
}
|
|
3985
|
+
function hasAncestorRootBoundary(boundary, boundaries) {
|
|
3986
|
+
return boundaries.some((candidate) => candidate !== boundary && candidate.segments.length < boundary.segments.length && candidate.segments.every((segment, index) => boundary.segments[index] === segment));
|
|
3987
|
+
}
|
|
3988
|
+
function findExplicitRootLayoutAbsPath(pageKeys, appCwdPath) {
|
|
3989
|
+
const rootLayoutKey = pageKeys.find((key) => {
|
|
3990
|
+
const segments = getRootBoundarySegments(key);
|
|
3991
|
+
return segments !== null && segments.length === 0;
|
|
3992
|
+
});
|
|
3993
|
+
return rootLayoutKey ? path10.resolve(appCwdPath, "page", rootLayoutKey.replace(/^\.\//, "")) : null;
|
|
3994
|
+
}
|
|
3963
3995
|
function routePrefixForSegments(segments) {
|
|
3964
3996
|
const visible = segments.filter((segment) => !/^\(.+\)$/.test(segment));
|
|
3965
3997
|
return visible[0] ?? null;
|
|
@@ -3976,21 +4008,27 @@ async function writeGeneratedRootLayoutFile(opts) {
|
|
|
3976
4008
|
await mkdir3(path10.dirname(absPath), { recursive: true });
|
|
3977
4009
|
const sourceRel = opts.boundary.sourceAbsPath ? path10.relative(path10.dirname(absPath), opts.boundary.sourceAbsPath).split(path10.sep).join("/") : null;
|
|
3978
4010
|
const sourceSpecifier = sourceRel ? sourceRel.startsWith(".") ? sourceRel : `./${sourceRel}` : null;
|
|
4011
|
+
const inheritedSourceAbsPath = opts.rootSourceAbsPath && opts.rootSourceAbsPath !== opts.boundary.sourceAbsPath ? opts.rootSourceAbsPath : null;
|
|
4012
|
+
const inheritedSourceRel = inheritedSourceAbsPath ? path10.relative(path10.dirname(absPath), inheritedSourceAbsPath).split(path10.sep).join("/") : null;
|
|
4013
|
+
const inheritedSourceSpecifier = inheritedSourceRel ? inheritedSourceRel.startsWith(".") ? inheritedSourceRel : `./${inheritedSourceRel}` : null;
|
|
3979
4014
|
const clientImport = opts.includeStInit ? `import { st } from "@apps/${opts.appName}/client";
|
|
3980
4015
|
void st;
|
|
3981
4016
|
` : `import "@apps/${opts.appName}/client";
|
|
4017
|
+
`;
|
|
4018
|
+
const inheritedImport = inheritedSourceSpecifier ? `import * as inheritedLayout from ${JSON.stringify(inheritedSourceSpecifier)};
|
|
4019
|
+
` : `const inheritedLayout = {};
|
|
3982
4020
|
`;
|
|
3983
4021
|
const prefix = routePrefixForSegments(opts.boundary.segments);
|
|
3984
4022
|
const userImport = sourceSpecifier ? `import UserLayout, * as userLayout from ${JSON.stringify(sourceSpecifier)};
|
|
3985
4023
|
` : `const UserLayout = ({ children }) => children;
|
|
3986
4024
|
const userLayout = {};
|
|
3987
4025
|
`;
|
|
3988
|
-
const source = `import type { LayoutProps, PageProps } from "akanjs/client";
|
|
4026
|
+
const source = opts.includeSystemProvider ? `import type { LayoutProps, PageProps } from "akanjs/client";
|
|
3989
4027
|
import { loadFonts } from "akanjs/client";
|
|
3990
4028
|
import { System } from "akanjs/ui";
|
|
3991
4029
|
import { env } from "@apps/${opts.appName}/env/env.client";
|
|
3992
|
-
${clientImport}${userImport}
|
|
3993
|
-
const userFonts = userLayout.fonts ?? [];
|
|
4030
|
+
${clientImport}${inheritedImport}${userImport}
|
|
4031
|
+
const userFonts = userLayout.fonts ?? inheritedLayout.fonts ?? [];
|
|
3994
4032
|
const defaultFonts = userFonts.filter((font) => font.default);
|
|
3995
4033
|
if (defaultFonts.length > 1) throw new Error("[route-convention] only one default font is allowed per root layout");
|
|
3996
4034
|
const defaultFont = defaultFonts[0];
|
|
@@ -3998,7 +4036,9 @@ const defaultFontClassName = defaultFont ? (defaultFont.className ?? \`font-\${d
|
|
|
3998
4036
|
|
|
3999
4037
|
export async function generateHead(props: PageProps) {
|
|
4000
4038
|
if (userLayout.generateHead) return userLayout.generateHead(props);
|
|
4001
|
-
return userLayout.head;
|
|
4039
|
+
if (userLayout.head !== undefined) return userLayout.head;
|
|
4040
|
+
if (inheritedLayout.generateHead) return inheritedLayout.generateHead(props);
|
|
4041
|
+
return inheritedLayout.head;
|
|
4002
4042
|
}
|
|
4003
4043
|
|
|
4004
4044
|
export default function GeneratedLayout({ children, params, searchParams }: LayoutProps) {
|
|
@@ -4008,19 +4048,31 @@ export default function GeneratedLayout({ children, params, searchParams }: Layo
|
|
|
4008
4048
|
appName=${JSON.stringify(opts.appName)}
|
|
4009
4049
|
${prefix ? `prefix=${JSON.stringify(prefix)}
|
|
4010
4050
|
` : ""}params={params}
|
|
4011
|
-
manifest={userLayout.manifest}
|
|
4051
|
+
manifest={userLayout.manifest ?? inheritedLayout.manifest}
|
|
4012
4052
|
env={env}
|
|
4013
|
-
theme={userLayout.theme}
|
|
4053
|
+
theme={userLayout.theme ?? inheritedLayout.theme}
|
|
4014
4054
|
fonts={loadFonts(userFonts)}
|
|
4015
4055
|
className={defaultFontClassName}
|
|
4016
|
-
gaTrackingId={userLayout.gaTrackingId}
|
|
4017
|
-
layoutStyle={userLayout.layoutStyle}
|
|
4018
|
-
reconnect={userLayout.reconnect ?? false}
|
|
4056
|
+
gaTrackingId={userLayout.gaTrackingId ?? inheritedLayout.gaTrackingId}
|
|
4057
|
+
layoutStyle={userLayout.layoutStyle ?? inheritedLayout.layoutStyle}
|
|
4058
|
+
reconnect={userLayout.reconnect ?? inheritedLayout.reconnect ?? false}
|
|
4019
4059
|
>
|
|
4020
4060
|
<UserLayout params={params} searchParams={searchParams}>{children}</UserLayout>
|
|
4021
4061
|
</System.Provider>
|
|
4022
4062
|
);
|
|
4023
4063
|
}
|
|
4064
|
+
` : `import type { LayoutProps, PageProps } from "akanjs/client";
|
|
4065
|
+
${inheritedImport}${userImport}
|
|
4066
|
+
export async function generateHead(props: PageProps) {
|
|
4067
|
+
if (userLayout.generateHead) return userLayout.generateHead(props);
|
|
4068
|
+
if (userLayout.head !== undefined) return userLayout.head;
|
|
4069
|
+
if (inheritedLayout.generateHead) return inheritedLayout.generateHead(props);
|
|
4070
|
+
return inheritedLayout.head;
|
|
4071
|
+
}
|
|
4072
|
+
|
|
4073
|
+
export default function GeneratedLayout({ children, params, searchParams }: LayoutProps) {
|
|
4074
|
+
return <UserLayout params={params} searchParams={searchParams}>{children}</UserLayout>;
|
|
4075
|
+
}
|
|
4024
4076
|
`;
|
|
4025
4077
|
await Bun.write(absPath, source);
|
|
4026
4078
|
return absPath;
|
|
@@ -4029,6 +4081,8 @@ async function resolveSsrPageEntries(opts) {
|
|
|
4029
4081
|
const absPageDir = path10.resolve(opts.appCwdPath, "page");
|
|
4030
4082
|
const hasSt = await appHasStModule(opts.appCwdPath);
|
|
4031
4083
|
const basePaths = opts.basePaths ?? [];
|
|
4084
|
+
const rootSourceAbsPath = findExplicitRootLayoutAbsPath(opts.pageKeys, opts.appCwdPath);
|
|
4085
|
+
const rootBoundaries = findRootBoundaries(opts.pageKeys, opts.appCwdPath, basePaths);
|
|
4032
4086
|
const rootLayoutKeys = new Set(opts.pageKeys.filter((key) => {
|
|
4033
4087
|
const segments = getRootBoundarySegments(key);
|
|
4034
4088
|
return segments !== null && isRootBoundarySegments(segments, basePaths);
|
|
@@ -4037,15 +4091,17 @@ async function resolveSsrPageEntries(opts) {
|
|
|
4037
4091
|
key,
|
|
4038
4092
|
moduleAbsPath: path10.resolve(absPageDir, key)
|
|
4039
4093
|
}));
|
|
4040
|
-
const generated = await Promise.all(
|
|
4094
|
+
const generated = await Promise.all(rootBoundaries.map(async (boundary) => ({
|
|
4041
4095
|
key: implicitRootLayoutKey(boundary.segments),
|
|
4042
4096
|
moduleAbsPath: await writeGeneratedRootLayoutFile({
|
|
4043
4097
|
appCwdPath: opts.appCwdPath,
|
|
4044
4098
|
appName: opts.appName,
|
|
4045
4099
|
boundary,
|
|
4046
|
-
|
|
4100
|
+
rootSourceAbsPath,
|
|
4101
|
+
includeStInit: hasSt && boundary.segments.length === 0,
|
|
4102
|
+
includeSystemProvider: !hasAncestorRootBoundary(boundary, rootBoundaries)
|
|
4047
4103
|
}),
|
|
4048
|
-
seedAbsPaths:
|
|
4104
|
+
seedAbsPaths: [...new Set([boundary.sourceAbsPath, rootSourceAbsPath].filter((absPath) => absPath !== null))]
|
|
4049
4105
|
})));
|
|
4050
4106
|
const entries = [...base, ...generated];
|
|
4051
4107
|
entries.sort((a, b) => a.key.localeCompare(b.key));
|
|
@@ -7020,6 +7076,13 @@ function formatBytes(bytes) {
|
|
|
7020
7076
|
}
|
|
7021
7077
|
// pkgs/@akanjs/devkit/frontendBuild/ssrBaseArtifactBuilder.ts
|
|
7022
7078
|
import path30 from "path";
|
|
7079
|
+
import { optimize } from "@tailwindcss/node";
|
|
7080
|
+
function prepareCssAsset(command, basePath2, cssText) {
|
|
7081
|
+
if (command !== "build")
|
|
7082
|
+
return cssText;
|
|
7083
|
+
return optimize(cssText, { file: `${basePath2 || "root"}.css`, minify: true }).code;
|
|
7084
|
+
}
|
|
7085
|
+
|
|
7023
7086
|
class SsrBaseArtifactBuilder {
|
|
7024
7087
|
#app;
|
|
7025
7088
|
#command;
|
|
@@ -7111,14 +7174,15 @@ class SsrBaseArtifactBuilder {
|
|
|
7111
7174
|
}
|
|
7112
7175
|
async#writeCssAsset(basePath2, cssText) {
|
|
7113
7176
|
const cssAssetName = basePath2 || "root";
|
|
7177
|
+
const preparedCssText = await prepareCssAsset(this.#command, basePath2, cssText);
|
|
7114
7178
|
const cssHash = Bun.hash(`${basePath2}
|
|
7115
|
-
${
|
|
7179
|
+
${preparedCssText}`).toString(36);
|
|
7116
7180
|
const [cssRelPath, cssUrl] = [
|
|
7117
7181
|
`styles/${cssAssetName}-${cssHash}.css`,
|
|
7118
7182
|
`/_akan/styles/${cssAssetName}-${cssHash}.css`
|
|
7119
7183
|
];
|
|
7120
|
-
await Bun.write(path30.join(this.#absArtifactDir, cssRelPath),
|
|
7121
|
-
this.#app.verbose(`[base-artifact] wrote ${
|
|
7184
|
+
await Bun.write(path30.join(this.#absArtifactDir, cssRelPath), preparedCssText);
|
|
7185
|
+
this.#app.verbose(`[base-artifact] wrote ${preparedCssText.length} bytes of CSS for ${basePath2} -> ${cssRelPath}`);
|
|
7122
7186
|
return [basePath2, { cssUrl, cssRelPath }];
|
|
7123
7187
|
}
|
|
7124
7188
|
}
|
|
@@ -7166,9 +7230,19 @@ var SSR_RENDER_EXTERNALS = [
|
|
|
7166
7230
|
"react/jsx-dev-runtime",
|
|
7167
7231
|
"react-dom",
|
|
7168
7232
|
"react-dom/server.browser",
|
|
7233
|
+
"react-server-dom-webpack",
|
|
7234
|
+
"react-server-dom-webpack/server.node",
|
|
7169
7235
|
"react-server-dom-webpack/client.node",
|
|
7170
7236
|
"react-server-dom-webpack/client.browser"
|
|
7171
7237
|
];
|
|
7238
|
+
var AKAN_OPTIONAL_BACKEND_EXTERNALS = [
|
|
7239
|
+
"@libsql/client",
|
|
7240
|
+
"bullmq",
|
|
7241
|
+
"croner",
|
|
7242
|
+
"ioredis",
|
|
7243
|
+
"postgres",
|
|
7244
|
+
"protobufjs"
|
|
7245
|
+
];
|
|
7172
7246
|
|
|
7173
7247
|
class ApplicationBuildRunner {
|
|
7174
7248
|
#app;
|
|
@@ -7237,7 +7311,9 @@ class ApplicationBuildRunner {
|
|
|
7237
7311
|
}
|
|
7238
7312
|
async#buildBackend() {
|
|
7239
7313
|
const akanConfig2 = await this.#app.getConfig();
|
|
7240
|
-
const backendExternals = [
|
|
7314
|
+
const backendExternals = [
|
|
7315
|
+
...new Set([...akanConfig2.externalLibs, ...SSR_RENDER_EXTERNALS, ...AKAN_OPTIONAL_BACKEND_EXTERNALS])
|
|
7316
|
+
];
|
|
7241
7317
|
const backendEntryPoints = [`${this.#app.cwdPath}/main.ts`, `${this.#app.cwdPath}/server.ts`];
|
|
7242
7318
|
for (const entrypoint of backendEntryPoints) {
|
|
7243
7319
|
if (!await Bun.file(entrypoint).exists())
|
|
@@ -7259,7 +7335,7 @@ class ApplicationBuildRunner {
|
|
|
7259
7335
|
naming: { entry: "[name].[ext]", chunk: "chunk-[hash].[ext]" },
|
|
7260
7336
|
conditions: ["react-server"],
|
|
7261
7337
|
define: { "process.env.NODE_ENV": JSON.stringify("production") },
|
|
7262
|
-
plugins:
|
|
7338
|
+
plugins: backendExternals.length > 0 ? [this.#createExternalSpecifiersPlugin(backendExternals)] : []
|
|
7263
7339
|
});
|
|
7264
7340
|
return {
|
|
7265
7341
|
entrypoints: backendEntryPoints.length + 1,
|
|
@@ -7607,10 +7683,31 @@ class ApplicationReleasePackager {
|
|
|
7607
7683
|
`;
|
|
7608
7684
|
}
|
|
7609
7685
|
}
|
|
7686
|
+
// pkgs/@akanjs/devkit/applicationTestPreload.ts
|
|
7687
|
+
import path33 from "path";
|
|
7688
|
+
var SIGNAL_TEST_PRELOAD_PATH = "test/signalTest.preload.ts";
|
|
7689
|
+
async function resolveSignalTestPreloadPath(target) {
|
|
7690
|
+
const candidates = [];
|
|
7691
|
+
const addResolvedPackageCandidate = (basePath2) => {
|
|
7692
|
+
try {
|
|
7693
|
+
candidates.push(path33.join(path33.dirname(Bun.resolveSync("akanjs/package.json", basePath2)), SIGNAL_TEST_PRELOAD_PATH));
|
|
7694
|
+
} catch {}
|
|
7695
|
+
};
|
|
7696
|
+
addResolvedPackageCandidate(target.cwdPath);
|
|
7697
|
+
addResolvedPackageCandidate(process.cwd());
|
|
7698
|
+
addResolvedPackageCandidate(path33.dirname(Bun.main));
|
|
7699
|
+
addResolvedPackageCandidate(import.meta.dir);
|
|
7700
|
+
candidates.push(path33.join(target.cwdPath, "../../node_modules/akanjs", SIGNAL_TEST_PRELOAD_PATH), path33.join(target.cwdPath, "../../pkgs/akanjs", SIGNAL_TEST_PRELOAD_PATH), path33.join(process.cwd(), "node_modules/akanjs", SIGNAL_TEST_PRELOAD_PATH), path33.join(process.cwd(), "pkgs/akanjs", SIGNAL_TEST_PRELOAD_PATH), path33.join(path33.dirname(Bun.main), "../../akanjs", SIGNAL_TEST_PRELOAD_PATH), path33.resolve(import.meta.dir, "../../akanjs", SIGNAL_TEST_PRELOAD_PATH));
|
|
7701
|
+
for (const candidate of [...new Set(candidates)]) {
|
|
7702
|
+
if (await Bun.file(candidate).exists())
|
|
7703
|
+
return candidate;
|
|
7704
|
+
}
|
|
7705
|
+
throw new Error(`Failed to locate ${SIGNAL_TEST_PRELOAD_PATH} from ${target.cwdPath}`);
|
|
7706
|
+
}
|
|
7610
7707
|
// pkgs/@akanjs/devkit/builder.ts
|
|
7611
7708
|
import { existsSync as existsSync2 } from "fs";
|
|
7612
7709
|
import { mkdir as mkdir9 } from "fs/promises";
|
|
7613
|
-
import
|
|
7710
|
+
import path34 from "path";
|
|
7614
7711
|
var SKIP_ENTRY_DIR_SET = new Set(["node_modules", "dist", "build", ".git", ".next"]);
|
|
7615
7712
|
var assetExtensions = [".css", ".md", ".js", ".png", ".ico", ".svg", ".json", ".template"];
|
|
7616
7713
|
var assetLoader = Object.fromEntries(assetExtensions.map((ext) => [ext, "file"]));
|
|
@@ -7627,14 +7724,14 @@ class Builder {
|
|
|
7627
7724
|
#globEntrypoints(cwd, pattern) {
|
|
7628
7725
|
const glob = new Bun.Glob(pattern);
|
|
7629
7726
|
return Array.from(glob.scanSync({ cwd, onlyFiles: true })).filter((relativePath) => {
|
|
7630
|
-
const segments = relativePath.split(
|
|
7727
|
+
const segments = relativePath.split(path34.sep);
|
|
7631
7728
|
return !segments.some((segment) => SKIP_ENTRY_DIR_SET.has(segment));
|
|
7632
|
-
}).map((rel) =>
|
|
7729
|
+
}).map((rel) => path34.join(cwd, rel));
|
|
7633
7730
|
}
|
|
7634
7731
|
#globFiles(cwd, pattern = "**/*.*") {
|
|
7635
7732
|
const glob = new Bun.Glob(pattern);
|
|
7636
7733
|
return Array.from(glob.scanSync({ cwd, onlyFiles: true })).filter((relativePath) => {
|
|
7637
|
-
const segments = relativePath.split(
|
|
7734
|
+
const segments = relativePath.split(path34.sep);
|
|
7638
7735
|
return !segments.some((segment) => SKIP_ENTRY_DIR_SET.has(segment));
|
|
7639
7736
|
});
|
|
7640
7737
|
}
|
|
@@ -7642,17 +7739,17 @@ class Builder {
|
|
|
7642
7739
|
const out = [];
|
|
7643
7740
|
for (const p of additionalEntryPoints) {
|
|
7644
7741
|
if (p.includes("*")) {
|
|
7645
|
-
const rel = p.startsWith(`${cwd}/`) || p.startsWith(`${cwd}${
|
|
7742
|
+
const rel = p.startsWith(`${cwd}/`) || p.startsWith(`${cwd}${path34.sep}`) ? p.slice(cwd.length + 1) : p;
|
|
7646
7743
|
out.push(...this.#globEntrypoints(cwd, rel));
|
|
7647
7744
|
} else
|
|
7648
|
-
out.push(
|
|
7745
|
+
out.push(path34.isAbsolute(p) ? p : path34.join(cwd, p));
|
|
7649
7746
|
}
|
|
7650
7747
|
return out;
|
|
7651
7748
|
}
|
|
7652
7749
|
#getBuildOptions({ bundle = false, additionalEntryPoints = [] } = {}) {
|
|
7653
7750
|
const cwd = this.#executor.cwdPath;
|
|
7654
7751
|
const entrypoints = [
|
|
7655
|
-
...bundle ? [
|
|
7752
|
+
...bundle ? [path34.join(cwd, "index.ts")] : this.#globEntrypoints(cwd, "**/*.{ts,tsx}"),
|
|
7656
7753
|
...this.#resolveAdditionalEntrypoints(cwd, additionalEntryPoints)
|
|
7657
7754
|
];
|
|
7658
7755
|
return {
|
|
@@ -7673,9 +7770,9 @@ class Builder {
|
|
|
7673
7770
|
for (const relativePath of this.#globFiles(cwd)) {
|
|
7674
7771
|
if (relativePath === "package.json")
|
|
7675
7772
|
continue;
|
|
7676
|
-
const sourcePath =
|
|
7677
|
-
const targetPath =
|
|
7678
|
-
await mkdir9(
|
|
7773
|
+
const sourcePath = path34.join(cwd, relativePath);
|
|
7774
|
+
const targetPath = path34.join(this.#distExecutor.cwdPath, relativePath);
|
|
7775
|
+
await mkdir9(path34.dirname(targetPath), { recursive: true });
|
|
7679
7776
|
await Bun.write(targetPath, Bun.file(sourcePath));
|
|
7680
7777
|
}
|
|
7681
7778
|
}
|
|
@@ -7686,13 +7783,13 @@ class Builder {
|
|
|
7686
7783
|
return withoutFormatDir;
|
|
7687
7784
|
if (!hasDotSlash && withoutFormatDir === publishedPath)
|
|
7688
7785
|
return publishedPath;
|
|
7689
|
-
const parsed =
|
|
7786
|
+
const parsed = path34.posix.parse(withoutFormatDir);
|
|
7690
7787
|
if (![".js", ".mjs", ".cjs"].includes(parsed.ext))
|
|
7691
7788
|
return withoutFormatDir;
|
|
7692
|
-
const withoutExt =
|
|
7789
|
+
const withoutExt = path34.posix.join(parsed.dir, parsed.name);
|
|
7693
7790
|
const sourcePath = withoutExt.startsWith("./") ? withoutExt.slice(2) : withoutExt;
|
|
7694
7791
|
const sourceCandidates = [`${sourcePath}.ts`, `${sourcePath}.tsx`];
|
|
7695
|
-
const matchedSource = sourceCandidates.find((candidate) => existsSync2(
|
|
7792
|
+
const matchedSource = sourceCandidates.find((candidate) => existsSync2(path34.join(this.#executor.cwdPath, candidate)));
|
|
7696
7793
|
if (!matchedSource)
|
|
7697
7794
|
return withoutFormatDir;
|
|
7698
7795
|
return hasDotSlash ? `./${matchedSource}` : matchedSource;
|
|
@@ -7742,7 +7839,7 @@ class Builder {
|
|
|
7742
7839
|
}
|
|
7743
7840
|
// pkgs/@akanjs/devkit/capacitorApp.ts
|
|
7744
7841
|
import { cp as cp2, mkdir as mkdir10, rm as rm4 } from "fs/promises";
|
|
7745
|
-
import
|
|
7842
|
+
import path35 from "path";
|
|
7746
7843
|
import { MobileProject } from "@trapezedev/project";
|
|
7747
7844
|
import { capitalize as capitalize2 } from "akanjs/common";
|
|
7748
7845
|
|
|
@@ -7936,10 +8033,10 @@ class CapacitorApp {
|
|
|
7936
8033
|
constructor(app, target) {
|
|
7937
8034
|
this.app = app;
|
|
7938
8035
|
this.target = target;
|
|
7939
|
-
this.targetRootPath =
|
|
7940
|
-
this.targetRoot =
|
|
7941
|
-
this.targetWebRoot =
|
|
7942
|
-
this.targetAssetRoot =
|
|
8036
|
+
this.targetRootPath = path35.posix.join("mobile", this.target.name);
|
|
8037
|
+
this.targetRoot = path35.join(this.app.cwdPath, this.targetRootPath);
|
|
8038
|
+
this.targetWebRoot = path35.join(this.targetRoot, "www");
|
|
8039
|
+
this.targetAssetRoot = path35.join(this.targetRoot, "assets");
|
|
7943
8040
|
this.project = new MobileProject(this.app.cwdPath, {
|
|
7944
8041
|
android: { path: this.androidRootPath },
|
|
7945
8042
|
ios: { path: this.iosProjectPath }
|
|
@@ -7955,9 +8052,9 @@ class CapacitorApp {
|
|
|
7955
8052
|
await this.#writeCapacitorConfig();
|
|
7956
8053
|
if (regenerate) {
|
|
7957
8054
|
if (!platform || platform === "ios")
|
|
7958
|
-
await rm4(
|
|
8055
|
+
await rm4(path35.join(this.app.cwdPath, this.iosRootPath), { recursive: true, force: true });
|
|
7959
8056
|
if (!platform || platform === "android")
|
|
7960
|
-
await rm4(
|
|
8057
|
+
await rm4(path35.join(this.app.cwdPath, this.androidRootPath), { recursive: true, force: true });
|
|
7961
8058
|
}
|
|
7962
8059
|
const project = this.project;
|
|
7963
8060
|
await this.project.load();
|
|
@@ -8019,7 +8116,7 @@ class CapacitorApp {
|
|
|
8019
8116
|
await this.#spawnMobile("npx", ["cap", "sync", "android"], { operation, env });
|
|
8020
8117
|
}
|
|
8021
8118
|
async#updateAndroidBuildTypes() {
|
|
8022
|
-
const appGradle = await FileEditor.create(
|
|
8119
|
+
const appGradle = await FileEditor.create(path35.join(this.app.cwdPath, this.androidRootPath, "app/build.gradle"));
|
|
8023
8120
|
const buildTypesBlock = `
|
|
8024
8121
|
debug {
|
|
8025
8122
|
applicationIdSuffix ".debug"
|
|
@@ -8062,7 +8159,7 @@ class CapacitorApp {
|
|
|
8062
8159
|
const gradleCommand = isWindows ? "gradlew.bat" : "./gradlew";
|
|
8063
8160
|
await this.app.spawn(gradleCommand, [assembleType === "apk" ? "assembleRelease" : "bundleRelease"], {
|
|
8064
8161
|
stdio: "inherit",
|
|
8065
|
-
cwd:
|
|
8162
|
+
cwd: path35.join(this.app.cwdPath, this.androidRootPath),
|
|
8066
8163
|
env: this.#commandEnv("release", env)
|
|
8067
8164
|
});
|
|
8068
8165
|
}
|
|
@@ -8091,12 +8188,12 @@ class CapacitorApp {
|
|
|
8091
8188
|
await this.#prepareAndroid({ operation: "release", env: "main" });
|
|
8092
8189
|
}
|
|
8093
8190
|
async prepareWww() {
|
|
8094
|
-
const htmlSource =
|
|
8191
|
+
const htmlSource = path35.join(this.app.dist.cwdPath, "csr", targetHtmlFilename(this.target));
|
|
8095
8192
|
if (!await Bun.file(htmlSource).exists())
|
|
8096
8193
|
throw new Error(`CSR html for mobile target '${this.target.name}' not found: ${htmlSource}`);
|
|
8097
8194
|
await rm4(this.targetWebRoot, { recursive: true, force: true });
|
|
8098
8195
|
await mkdir10(this.targetWebRoot, { recursive: true });
|
|
8099
|
-
await Bun.write(
|
|
8196
|
+
await Bun.write(path35.join(this.targetWebRoot, "index.html"), this.#injectMobileTargetMeta(await Bun.file(htmlSource).text()));
|
|
8100
8197
|
}
|
|
8101
8198
|
#injectMobileTargetMeta(html) {
|
|
8102
8199
|
const basePath2 = this.target.basePath?.replace(/^\/+|\/+$/g, "") ?? "";
|
|
@@ -8108,7 +8205,7 @@ class CapacitorApp {
|
|
|
8108
8205
|
}
|
|
8109
8206
|
async#writeCapacitorConfig() {
|
|
8110
8207
|
await mkdir10(this.targetRoot, { recursive: true });
|
|
8111
|
-
const appInfoPath =
|
|
8208
|
+
const appInfoPath = path35.relative(this.app.cwdPath, path35.join(this.app.cwdPath, "akan.app.json")).split(path35.sep).join("/");
|
|
8112
8209
|
const content = `import type { AppScanResult } from "akanjs";
|
|
8113
8210
|
import { withBase } from "akanjs/capacitor.base.config";
|
|
8114
8211
|
import appInfo from "${appInfoPath.startsWith(".") ? appInfoPath : `./${appInfoPath}`}";
|
|
@@ -8129,18 +8226,18 @@ export default withBase(
|
|
|
8129
8226
|
appInfo as AppScanResult,
|
|
8130
8227
|
);
|
|
8131
8228
|
`;
|
|
8132
|
-
await Bun.write(
|
|
8229
|
+
await Bun.write(path35.join(this.app.cwdPath, "capacitor.config.ts"), content);
|
|
8133
8230
|
}
|
|
8134
8231
|
async#prepareTargetAssets() {
|
|
8135
8232
|
if (!this.target.assets)
|
|
8136
8233
|
return;
|
|
8137
8234
|
await mkdir10(this.targetAssetRoot, { recursive: true });
|
|
8138
8235
|
if (this.target.assets.icon)
|
|
8139
|
-
await cp2(
|
|
8236
|
+
await cp2(path35.join(this.app.cwdPath, this.target.assets.icon), path35.join(this.targetAssetRoot, "icon.png"), {
|
|
8140
8237
|
force: true
|
|
8141
8238
|
});
|
|
8142
8239
|
if (this.target.assets.splash)
|
|
8143
|
-
await cp2(
|
|
8240
|
+
await cp2(path35.join(this.app.cwdPath, this.target.assets.splash), path35.join(this.targetAssetRoot, "splash.png"), {
|
|
8144
8241
|
force: true
|
|
8145
8242
|
});
|
|
8146
8243
|
}
|
|
@@ -8148,11 +8245,11 @@ export default withBase(
|
|
|
8148
8245
|
const files = this.target.files?.[platform];
|
|
8149
8246
|
if (!files)
|
|
8150
8247
|
return;
|
|
8151
|
-
const platformRoot =
|
|
8248
|
+
const platformRoot = path35.join(this.app.cwdPath, platform === "ios" ? this.iosRootPath : this.androidRootPath);
|
|
8152
8249
|
await Promise.all(Object.entries(files).map(async ([to, from]) => {
|
|
8153
|
-
const targetPath =
|
|
8154
|
-
await mkdir10(
|
|
8155
|
-
await cp2(
|
|
8250
|
+
const targetPath = path35.join(platformRoot, to);
|
|
8251
|
+
await mkdir10(path35.dirname(targetPath), { recursive: true });
|
|
8252
|
+
await cp2(path35.join(this.app.cwdPath, from), targetPath, { force: true });
|
|
8156
8253
|
}));
|
|
8157
8254
|
}
|
|
8158
8255
|
async#generateAssets({ operation, env }) {
|
|
@@ -8162,7 +8259,7 @@ export default withBase(
|
|
|
8162
8259
|
"@capacitor/assets",
|
|
8163
8260
|
"generate",
|
|
8164
8261
|
"--assetPath",
|
|
8165
|
-
|
|
8262
|
+
path35.posix.join(this.targetRootPath, "assets"),
|
|
8166
8263
|
"--iosProject",
|
|
8167
8264
|
this.iosProjectPath,
|
|
8168
8265
|
"--androidProject",
|
|
@@ -8347,7 +8444,7 @@ var Pkg = createInternalArgToken("Pkg");
|
|
|
8347
8444
|
var Module = createInternalArgToken("Module");
|
|
8348
8445
|
var Workspace = createInternalArgToken("Workspace");
|
|
8349
8446
|
// pkgs/@akanjs/devkit/commandDecorators/command.ts
|
|
8350
|
-
import
|
|
8447
|
+
import path36 from "path";
|
|
8351
8448
|
import { confirm, input as input2, select as select2 } from "@inquirer/prompts";
|
|
8352
8449
|
import { Logger as Logger11 } from "akanjs/common";
|
|
8353
8450
|
import chalk6 from "chalk";
|
|
@@ -8847,7 +8944,7 @@ var runCommands = async (...commands) => {
|
|
|
8847
8944
|
process.exit(1);
|
|
8848
8945
|
});
|
|
8849
8946
|
const __dirname2 = getDirname(import.meta.url);
|
|
8850
|
-
const packageJsonCandidates = [`${
|
|
8947
|
+
const packageJsonCandidates = [`${path36.dirname(Bun.main)}/package.json`, `${__dirname2}/../package.json`];
|
|
8851
8948
|
let cliPackageJson = null;
|
|
8852
8949
|
for (const packageJsonPath of packageJsonCandidates) {
|
|
8853
8950
|
if (!await FileSys.fileExists(packageJsonPath))
|
|
@@ -9123,8 +9220,8 @@ var scanModuleSpecifiers = (source, filePath, includeExports) => {
|
|
|
9123
9220
|
return importSpecifiers;
|
|
9124
9221
|
};
|
|
9125
9222
|
var parseTsConfig = (tsConfigPath = "./tsconfig.json") => {
|
|
9126
|
-
const configFile = ts6.readConfigFile(tsConfigPath, (
|
|
9127
|
-
return ts6.sys.readFile(
|
|
9223
|
+
const configFile = ts6.readConfigFile(tsConfigPath, (path37) => {
|
|
9224
|
+
return ts6.sys.readFile(path37);
|
|
9128
9225
|
});
|
|
9129
9226
|
return ts6.parseJsonConfigFileContent(configFile.config, ts6.sys, realpathSync(tsConfigPath).replace(/[^/\\]+$/, ""));
|
|
9130
9227
|
};
|
|
@@ -9352,6 +9449,75 @@ import { Box as Box2, Newline, Text as Text2, useInput as useInput2 } from "ink"
|
|
|
9352
9449
|
import { useEffect as useEffect3, useState as useState3 } from "react";
|
|
9353
9450
|
import { jsxDEV as jsxDEV2, Fragment as Fragment2 } from "react/jsx-dev-runtime";
|
|
9354
9451
|
"use client";
|
|
9452
|
+
// pkgs/@akanjs/devkit/cloud/cloudApi.ts
|
|
9453
|
+
class HttpClient2 {
|
|
9454
|
+
baseUrl;
|
|
9455
|
+
constructor(baseUrl) {
|
|
9456
|
+
this.baseUrl = baseUrl;
|
|
9457
|
+
}
|
|
9458
|
+
async get(url, { headers } = {}) {
|
|
9459
|
+
const response = await fetch(`${this.baseUrl}${url}`, {
|
|
9460
|
+
headers: { "Content-Type": "application/json", ...headers }
|
|
9461
|
+
});
|
|
9462
|
+
return response.json();
|
|
9463
|
+
}
|
|
9464
|
+
async post(url, data, { headers } = {}) {
|
|
9465
|
+
const isFormData = data instanceof FormData;
|
|
9466
|
+
const response = await fetch(`${this.baseUrl}${url}`, {
|
|
9467
|
+
method: "POST",
|
|
9468
|
+
body: isFormData ? data : JSON.stringify(data),
|
|
9469
|
+
headers: isFormData ? headers : { "Content-Type": "application/json", ...headers }
|
|
9470
|
+
});
|
|
9471
|
+
return response.json();
|
|
9472
|
+
}
|
|
9473
|
+
}
|
|
9474
|
+
|
|
9475
|
+
class CloudApi {
|
|
9476
|
+
api;
|
|
9477
|
+
#accessToken = null;
|
|
9478
|
+
constructor(host, { accessToken } = {}) {
|
|
9479
|
+
this.api = new HttpClient2(`${host}/api`);
|
|
9480
|
+
this.#accessToken = accessToken ?? null;
|
|
9481
|
+
}
|
|
9482
|
+
async uploadEnv(devProjectId, fileStream) {
|
|
9483
|
+
const formData = new FormData;
|
|
9484
|
+
formData.append("devProjectId", devProjectId);
|
|
9485
|
+
formData.append("fileStream", await new Response(fileStream).blob());
|
|
9486
|
+
const response = await this.api.post(`/uploadEnv/${devProjectId}`, formData);
|
|
9487
|
+
return response.success;
|
|
9488
|
+
}
|
|
9489
|
+
async downloadEnv(devProjectId) {
|
|
9490
|
+
const response = await this.api.get(`/downloadEnv/${devProjectId}`);
|
|
9491
|
+
return response.success;
|
|
9492
|
+
}
|
|
9493
|
+
async getRemoteAuthToken(remoteId) {
|
|
9494
|
+
if (this.#needRefreshToken())
|
|
9495
|
+
return await this.refreshAuthToken();
|
|
9496
|
+
else if (this.#accessToken)
|
|
9497
|
+
return this.#accessToken;
|
|
9498
|
+
const accessToken = await this.api.get(`/getRemoteAuthToken/${remoteId}`);
|
|
9499
|
+
this.#accessToken = {
|
|
9500
|
+
jwt: accessToken.jwt,
|
|
9501
|
+
refreshToken: accessToken.refreshToken,
|
|
9502
|
+
expiresAt: new Date(accessToken.expiresAt)
|
|
9503
|
+
};
|
|
9504
|
+
return accessToken;
|
|
9505
|
+
}
|
|
9506
|
+
async refreshAuthToken() {
|
|
9507
|
+
const response = await this.api.post(`/refreshRemoteAuthToken`, {
|
|
9508
|
+
refreshToken: this.#accessToken?.refreshToken
|
|
9509
|
+
});
|
|
9510
|
+
this.#accessToken = {
|
|
9511
|
+
jwt: response.jwt,
|
|
9512
|
+
refreshToken: response.refreshToken,
|
|
9513
|
+
expiresAt: new Date(response.expiresAt)
|
|
9514
|
+
};
|
|
9515
|
+
return response;
|
|
9516
|
+
}
|
|
9517
|
+
#needRefreshToken() {
|
|
9518
|
+
return !!(this.#accessToken?.expiresAt && this.#accessToken.expiresAt.getTime() < Date.now() - 1000 * 60 * 60);
|
|
9519
|
+
}
|
|
9520
|
+
}
|
|
9355
9521
|
// pkgs/@akanjs/cli/application/application.command.ts
|
|
9356
9522
|
import { select as select6 } from "@inquirer/prompts";
|
|
9357
9523
|
|
|
@@ -9469,7 +9635,6 @@ class LibraryScript extends script("library", [LibraryRunner]) {
|
|
|
9469
9635
|
}
|
|
9470
9636
|
|
|
9471
9637
|
// pkgs/@akanjs/cli/application/application.runner.ts
|
|
9472
|
-
import path36 from "path";
|
|
9473
9638
|
import { confirm as confirm2, input as input4, select as select5 } from "@inquirer/prompts";
|
|
9474
9639
|
import { StringOutputParser } from "@langchain/core/output_parsers";
|
|
9475
9640
|
import { PromptTemplate as PromptTemplate2 } from "@langchain/core/prompts";
|
|
@@ -9535,14 +9700,14 @@ class ApplicationRunner extends runner("application") {
|
|
|
9535
9700
|
}
|
|
9536
9701
|
async test(exec2) {
|
|
9537
9702
|
const isSignalTarget = exec2 instanceof AppExecutor || exec2 instanceof LibExecutor;
|
|
9538
|
-
const preloadPath =
|
|
9703
|
+
const preloadPath = isSignalTarget ? await resolveSignalTestPreloadPath(exec2) : null;
|
|
9539
9704
|
const env = isSignalTarget ? {
|
|
9540
9705
|
AKAN_TEST_SIGNAL: "1",
|
|
9541
9706
|
AKAN_TEST_TARGET_TYPE: exec2.type,
|
|
9542
9707
|
AKAN_TEST_TARGET_NAME: exec2.name,
|
|
9543
9708
|
AKAN_TEST_LIBS: exec2.getScanInfo({ allowEmpty: true })?.getLibs().join(",") ?? ""
|
|
9544
9709
|
} : {};
|
|
9545
|
-
const args =
|
|
9710
|
+
const args = preloadPath ? ["test", "--isolate", "--preload", preloadPath] : ["test", "--isolate"];
|
|
9546
9711
|
await exec2.spawn("bun", args, {
|
|
9547
9712
|
...isSignalTarget ? { env: { ...process.env, ...env } } : {},
|
|
9548
9713
|
stdio: "inherit"
|
|
@@ -9841,12 +10006,17 @@ class ApplicationScript extends script("application", [ApplicationRunner, Librar
|
|
|
9841
10006
|
}
|
|
9842
10007
|
}
|
|
9843
10008
|
async test(exec2, { write = true } = {}) {
|
|
10009
|
+
if (exec2 instanceof LibExecutor) {
|
|
10010
|
+
await this.libraryScript.syncLibrary(exec2);
|
|
10011
|
+
const spinner3 = exec2.spinning(`Preparing ${exec2.name}...`);
|
|
10012
|
+
spinner3.succeed(`${exec2.name} prepared`);
|
|
10013
|
+
await this.applicationRunner.test(exec2);
|
|
10014
|
+
return;
|
|
10015
|
+
}
|
|
9844
10016
|
const spinner2 = exec2.spinning(`Preparing ${exec2.name}...`);
|
|
9845
10017
|
try {
|
|
9846
10018
|
if (exec2 instanceof PkgExecutor)
|
|
9847
10019
|
await exec2.scan({ refresh: true });
|
|
9848
|
-
else if (exec2 instanceof LibExecutor)
|
|
9849
|
-
await this.libraryScript.syncLibrary(exec2);
|
|
9850
10020
|
else
|
|
9851
10021
|
await exec2.scanSync({ write });
|
|
9852
10022
|
spinner2.succeed(`${exec2.name} prepared`);
|
|
@@ -10181,6 +10351,10 @@ class PackageRunner extends runner("package") {
|
|
|
10181
10351
|
pkg.generateTsconfigJson()
|
|
10182
10352
|
]);
|
|
10183
10353
|
}
|
|
10354
|
+
await this.#copyPackageReadmes(pkg);
|
|
10355
|
+
}
|
|
10356
|
+
async#copyPackageReadmes(pkg) {
|
|
10357
|
+
await Promise.all(["README.md", "README.ko.md"].map((fileName) => pkg.cp(fileName, `${pkg.dist.cwdPath}/${fileName}`)));
|
|
10184
10358
|
}
|
|
10185
10359
|
async updateWorskpaceRootPackageJson(workspace, rootPackageJson) {
|
|
10186
10360
|
const templatePath = "pkgs/@akanjs/cli/templates/workspaceRoot/package.json.template";
|
|
@@ -10229,17 +10403,21 @@ class PackageScript extends script("package", [PackageRunner]) {
|
|
|
10229
10403
|
}
|
|
10230
10404
|
|
|
10231
10405
|
// pkgs/@akanjs/cli/cloud/cloud.runner.ts
|
|
10406
|
+
import path38 from "path";
|
|
10232
10407
|
import { confirm as confirm3 } from "@inquirer/prompts";
|
|
10233
10408
|
import { Logger as Logger15, sleep } from "akanjs/common";
|
|
10234
10409
|
import chalk7 from "chalk";
|
|
10235
10410
|
import * as QRcode from "qrcode";
|
|
10236
10411
|
|
|
10237
10412
|
// pkgs/@akanjs/cli/npmRegistry.ts
|
|
10238
|
-
|
|
10239
|
-
|
|
10413
|
+
var defaultNpmRegistry = "https://registry.npmjs.org";
|
|
10414
|
+
var getNpmRegistryUrl = (registryUrl = process.env.AKAN_NPM_REGISTRY ?? defaultNpmRegistry) => registryUrl.replace(/\/+$/, "");
|
|
10415
|
+
async function getLatestPackageVersion(packageName, tag = "latest", registryUrl) {
|
|
10416
|
+
const registry = getNpmRegistryUrl(registryUrl);
|
|
10417
|
+
const url = `${registry}/${encodeURIComponent(packageName).replace(/^%40/, "@")}`;
|
|
10240
10418
|
const res = await fetch(url);
|
|
10241
10419
|
if (!res.ok)
|
|
10242
|
-
throw new Error(`Failed to fetch ${packageName} metadata from
|
|
10420
|
+
throw new Error(`Failed to fetch ${packageName} metadata from ${registry}`);
|
|
10243
10421
|
const metadata = await res.json();
|
|
10244
10422
|
const version = metadata["dist-tags"]?.[tag];
|
|
10245
10423
|
if (!version)
|
|
@@ -10249,6 +10427,29 @@ async function getLatestPackageVersion(packageName, tag = "latest") {
|
|
|
10249
10427
|
|
|
10250
10428
|
// pkgs/@akanjs/cli/cloud/cloud.runner.ts
|
|
10251
10429
|
class CloudRunner extends runner("cloud") {
|
|
10430
|
+
#akanFrameworkPackages = new Set([
|
|
10431
|
+
"akanjs",
|
|
10432
|
+
"@akanjs/devkit",
|
|
10433
|
+
"@akanjs/cli",
|
|
10434
|
+
"create-akan-workspace"
|
|
10435
|
+
]);
|
|
10436
|
+
#getRegistryArgs(registryUrl) {
|
|
10437
|
+
return registryUrl ? ["--registry", getNpmRegistryUrl(registryUrl)] : [];
|
|
10438
|
+
}
|
|
10439
|
+
#getLocalRegistryAuthArgs(registryUrl) {
|
|
10440
|
+
if (!registryUrl)
|
|
10441
|
+
return [];
|
|
10442
|
+
const { host, pathname } = new URL(getNpmRegistryUrl(registryUrl));
|
|
10443
|
+
const registryPath = pathname === "/" ? "/" : `${pathname.replace(/\/+$/, "")}/`;
|
|
10444
|
+
return [`--//${host}${registryPath}:_authToken=akan-local-registry`];
|
|
10445
|
+
}
|
|
10446
|
+
#getRegistryEnv(registryUrl) {
|
|
10447
|
+
return registryUrl ? {
|
|
10448
|
+
...process.env,
|
|
10449
|
+
AKAN_NPM_REGISTRY: getNpmRegistryUrl(registryUrl),
|
|
10450
|
+
NPM_CONFIG_REGISTRY: getNpmRegistryUrl(registryUrl)
|
|
10451
|
+
} : process.env;
|
|
10452
|
+
}
|
|
10252
10453
|
async login() {
|
|
10253
10454
|
const config = await getHostConfig();
|
|
10254
10455
|
const self = config.auth ? await getSelf(config.auth.token) : null;
|
|
@@ -10327,15 +10528,16 @@ ${chalk7.green("\u27A4")} Authentication Required`));
|
|
|
10327
10528
|
const pkgs = await workspace.getPkgs();
|
|
10328
10529
|
return pkgs.filter((pkg) => pkg === "akanjs" || pkg === "create-akan-workspace" || pkg.startsWith("@akanjs/"));
|
|
10329
10530
|
}
|
|
10330
|
-
async deployAkan(workspace, akanPkgs) {
|
|
10531
|
+
async deployAkan(workspace, akanPkgs, { registryUrl, confirmPublish = true, tag: distTag } = {}) {
|
|
10532
|
+
const registry = registryUrl ? getNpmRegistryUrl(registryUrl) : undefined;
|
|
10331
10533
|
const akanPackageJson2 = await workspace.readJson("pkgs/akanjs/package.json");
|
|
10332
10534
|
const [majorVersion, minorVersion, patchVersion, devPatchVersion] = akanPackageJson2.version.split(".");
|
|
10333
10535
|
const isOfficialRelease = !devPatchVersion;
|
|
10334
10536
|
const targetVersionPrefix = isOfficialRelease ? `${majorVersion}.${minorVersion}` : `${majorVersion}.${minorVersion}.${patchVersion}`;
|
|
10335
|
-
const tag = isOfficialRelease ? "latest" : patchVersion.split("-").at(1) ?? "dev";
|
|
10537
|
+
const tag = distTag ?? (isOfficialRelease ? "latest" : patchVersion.split("-").at(1) ?? "dev");
|
|
10336
10538
|
const getNextVersion = async (prefix, tag2) => {
|
|
10337
10539
|
try {
|
|
10338
|
-
const latestPublishedVersion2 = await getLatestPackageVersion("akanjs", tag2);
|
|
10540
|
+
const latestPublishedVersion2 = await getLatestPackageVersion("akanjs", tag2, registry);
|
|
10339
10541
|
const latestPatch = latestPublishedVersion2.startsWith(prefix) ? parseInt(latestPublishedVersion2.split(".").at(-1) ?? "-1") : -1;
|
|
10340
10542
|
const nextVersion2 = `${prefix}.${latestPatch + 1}`;
|
|
10341
10543
|
return { nextVersion: nextVersion2, latestPublishedVersion: latestPublishedVersion2 };
|
|
@@ -10348,37 +10550,59 @@ ${chalk7.green("\u27A4")} Authentication Required`));
|
|
|
10348
10550
|
Logger15.info(`Next version of akanjs: ${nextVersion}`);
|
|
10349
10551
|
for (const library of akanPkgs) {
|
|
10350
10552
|
const packageJson = await workspace.readJson(`pkgs/${library}/package.json`);
|
|
10351
|
-
const newPackageJsonStr = JSON.stringify(
|
|
10553
|
+
const newPackageJsonStr = JSON.stringify(this.#normalizeAkanPackageJson(packageJson, library, nextVersion), null, 2);
|
|
10352
10554
|
await workspace.writeFile(`pkgs/${library}/package.json`, newPackageJsonStr);
|
|
10353
10555
|
const distPackageJson = await workspace.readJson(`dist/pkgs/${library}/package.json`);
|
|
10354
|
-
const newDistPackageJson =
|
|
10556
|
+
const newDistPackageJson = this.#normalizeAkanPackageJson(distPackageJson, library, nextVersion);
|
|
10355
10557
|
await workspace.writeJson(`dist/pkgs/${library}/package.json`, newDistPackageJson);
|
|
10356
10558
|
}
|
|
10357
|
-
|
|
10358
|
-
|
|
10359
|
-
|
|
10360
|
-
|
|
10361
|
-
|
|
10362
|
-
|
|
10559
|
+
if (confirmPublish) {
|
|
10560
|
+
const isDeployConfirmed = await confirm3({
|
|
10561
|
+
message: "Are you sure you want to deploy the libraries?"
|
|
10562
|
+
});
|
|
10563
|
+
if (!isDeployConfirmed) {
|
|
10564
|
+
Logger15.error("Deployment cancelled");
|
|
10565
|
+
return;
|
|
10566
|
+
}
|
|
10363
10567
|
}
|
|
10364
10568
|
await Promise.all(akanPkgs.map(async (library) => {
|
|
10365
|
-
Logger15.info(`Publishing ${library}@${nextVersion} to npm...`);
|
|
10366
|
-
await workspace.
|
|
10367
|
-
|
|
10569
|
+
Logger15.info(`Publishing ${library}@${nextVersion} to ${registry ?? "npm"}...`);
|
|
10570
|
+
await workspace.spawn("npm", [
|
|
10571
|
+
"publish",
|
|
10572
|
+
"--tag",
|
|
10573
|
+
tag,
|
|
10574
|
+
...this.#getRegistryArgs(registry),
|
|
10575
|
+
...this.#getLocalRegistryAuthArgs(registry)
|
|
10576
|
+
], {
|
|
10577
|
+
cwd: path38.join(workspace.workspaceRoot, "dist/pkgs", library),
|
|
10578
|
+
env: this.#getRegistryEnv(registry),
|
|
10579
|
+
stdio: "inherit"
|
|
10580
|
+
});
|
|
10581
|
+
Logger15.info(`${library}@${nextVersion} is published to ${registry ?? "npm"}`);
|
|
10368
10582
|
}));
|
|
10369
|
-
Logger15.info(
|
|
10583
|
+
Logger15.info(`All libraries are published to ${registry ?? "npm"}`);
|
|
10370
10584
|
}
|
|
10371
|
-
async update(workspace, tag = "latest") {
|
|
10585
|
+
async update(workspace, tag = "latest", { registryUrl } = {}) {
|
|
10586
|
+
const registry = registryUrl ? getNpmRegistryUrl(registryUrl) : undefined;
|
|
10587
|
+
const registryArgs = this.#getRegistryArgs(registry);
|
|
10588
|
+
const env = this.#getRegistryEnv(registry);
|
|
10372
10589
|
if (!await workspace.exists("package.json"))
|
|
10373
|
-
await workspace.spawn("bun", ["update", "-g", "akanjs", "--latest", `--tag=${tag}
|
|
10590
|
+
await workspace.spawn("bun", ["update", "-g", "akanjs", "--latest", `--tag=${tag}`, ...registryArgs], { env });
|
|
10374
10591
|
else
|
|
10375
10592
|
await Promise.all([
|
|
10376
|
-
workspace.spawn("bun", [
|
|
10377
|
-
|
|
10593
|
+
workspace.spawn("bun", [
|
|
10594
|
+
"update",
|
|
10595
|
+
"-g",
|
|
10596
|
+
"akanjs",
|
|
10597
|
+
"--latest",
|
|
10598
|
+
`--tag=${tag}`,
|
|
10599
|
+
...registryArgs
|
|
10600
|
+
], { env }),
|
|
10601
|
+
this.#updateAkanPkgs(workspace, tag, registry)
|
|
10378
10602
|
]);
|
|
10379
10603
|
}
|
|
10380
|
-
async#updateAkanPkgs(workspace, tag = "latest") {
|
|
10381
|
-
const latestPublishedVersion = await getLatestPackageVersion("akanjs", tag);
|
|
10604
|
+
async#updateAkanPkgs(workspace, tag = "latest", registryUrl) {
|
|
10605
|
+
const latestPublishedVersion = await getLatestPackageVersion("akanjs", tag, registryUrl);
|
|
10382
10606
|
const rootPackageJson = await workspace.getPackageJson();
|
|
10383
10607
|
if (!rootPackageJson.dependencies)
|
|
10384
10608
|
throw new Error("No dependencies found in package.json");
|
|
@@ -10390,13 +10614,51 @@ ${chalk7.green("\u27A4")} Authentication Required`));
|
|
|
10390
10614
|
rootPackageJson.dependencies["@akanjs/devkit"] = latestPublishedVersion;
|
|
10391
10615
|
if (rootPackageJson.devDependencies?.["@akanjs/devkit"])
|
|
10392
10616
|
rootPackageJson.devDependencies["@akanjs/devkit"] = latestPublishedVersion;
|
|
10393
|
-
workspace.setPackageJson(rootPackageJson);
|
|
10394
|
-
await workspace.spawn("bun", ["install"]
|
|
10617
|
+
await workspace.setPackageJson(rootPackageJson);
|
|
10618
|
+
await workspace.spawn("bun", ["install", ...this.#getRegistryArgs(registryUrl)], {
|
|
10619
|
+
env: this.#getRegistryEnv(registryUrl)
|
|
10620
|
+
});
|
|
10395
10621
|
}
|
|
10622
|
+
#normalizeAkanPackageJson(packageJson, packageName, version) {
|
|
10623
|
+
const normalized = { ...packageJson, version };
|
|
10624
|
+
for (const field of [
|
|
10625
|
+
"dependencies",
|
|
10626
|
+
"devDependencies",
|
|
10627
|
+
"peerDependencies",
|
|
10628
|
+
"optionalDependencies"
|
|
10629
|
+
]) {
|
|
10630
|
+
const dependencies = normalized[field];
|
|
10631
|
+
if (!dependencies)
|
|
10632
|
+
continue;
|
|
10633
|
+
normalized[field] = Object.fromEntries(Object.entries(dependencies).map(([dep, depVersion]) => [
|
|
10634
|
+
dep,
|
|
10635
|
+
dep !== packageName && this.#akanFrameworkPackages.has(dep) ? version : depVersion
|
|
10636
|
+
]));
|
|
10637
|
+
}
|
|
10638
|
+
return normalized;
|
|
10639
|
+
}
|
|
10640
|
+
async downloadEnv(workspace) {
|
|
10641
|
+
const repoName = workspace.repoName;
|
|
10642
|
+
const config = await getHostConfig();
|
|
10643
|
+
const self = config.auth ? await getSelf(config.auth.token) : null;
|
|
10644
|
+
if (!self)
|
|
10645
|
+
throw new Error("Not logged in");
|
|
10646
|
+
const res = await fetch(`${akanCloudUrl}/api/akasys/akasys/${repoName}`, {
|
|
10647
|
+
headers: { Authorization: `Bearer ${config.auth?.token}` }
|
|
10648
|
+
});
|
|
10649
|
+
const env = await res.json();
|
|
10650
|
+
Logger15.info(`Downloading environment variables from cloud...`);
|
|
10651
|
+
Logger15.info(`Environment variables: ${JSON.stringify(env.env, null, 2)}`);
|
|
10652
|
+
}
|
|
10653
|
+
async uploadEnv(workspace) {}
|
|
10396
10654
|
}
|
|
10397
10655
|
|
|
10398
10656
|
// pkgs/@akanjs/cli/cloud/cloud.script.ts
|
|
10399
|
-
class CloudScript extends script("cloud", [
|
|
10657
|
+
class CloudScript extends script("cloud", [
|
|
10658
|
+
CloudRunner,
|
|
10659
|
+
ApplicationScript,
|
|
10660
|
+
PackageScript
|
|
10661
|
+
]) {
|
|
10400
10662
|
async login(workspace) {
|
|
10401
10663
|
await this.cloudRunner.login();
|
|
10402
10664
|
}
|
|
@@ -10413,7 +10675,13 @@ class CloudScript extends script("cloud", [CloudRunner, ApplicationScript, Packa
|
|
|
10413
10675
|
const session = new AiSession("general", { workspace, isContinued: true });
|
|
10414
10676
|
await session.ask(question);
|
|
10415
10677
|
}
|
|
10416
|
-
async
|
|
10678
|
+
async downloadEnv(workspace) {
|
|
10679
|
+
await this.cloudRunner.downloadEnv(workspace);
|
|
10680
|
+
}
|
|
10681
|
+
async uploadEnv(workspace) {
|
|
10682
|
+
await this.cloudRunner.uploadEnv(workspace);
|
|
10683
|
+
}
|
|
10684
|
+
async deployAkan(workspace, { test = true, registryUrl } = {}) {
|
|
10417
10685
|
const akanPkgs = await this.cloudRunner.getAkanPkgs(workspace);
|
|
10418
10686
|
await this.packageScript.updateWorskpaceRootPackageJson(workspace);
|
|
10419
10687
|
const pkgs = akanPkgs.map((pkgName) => PkgExecutor.from(workspace, pkgName));
|
|
@@ -10422,11 +10690,11 @@ class CloudScript extends script("cloud", [CloudRunner, ApplicationScript, Packa
|
|
|
10422
10690
|
await this.applicationScript.test(pkg);
|
|
10423
10691
|
for (const pkg of pkgs)
|
|
10424
10692
|
await this.packageScript.buildPackage(pkg);
|
|
10425
|
-
await this.cloudRunner.deployAkan(workspace, akanPkgs);
|
|
10693
|
+
await this.cloudRunner.deployAkan(workspace, akanPkgs, { registryUrl });
|
|
10426
10694
|
}
|
|
10427
|
-
async update(workspace, tag = "latest") {
|
|
10695
|
+
async update(workspace, tag = "latest", { registryUrl } = {}) {
|
|
10428
10696
|
const spinner2 = workspace.spinning("Updating Akan.js packages and CLI...");
|
|
10429
|
-
await this.cloudRunner.update(workspace, tag);
|
|
10697
|
+
await this.cloudRunner.update(workspace, tag, { registryUrl });
|
|
10430
10698
|
spinner2.succeed("Akan.js packages and CLI updated, global version is below");
|
|
10431
10699
|
Logger16.raw("> Akan version: ");
|
|
10432
10700
|
await workspace.spawn("akan", ["--version"], { stdio: "inherit" });
|
|
@@ -10434,6 +10702,9 @@ class CloudScript extends script("cloud", [CloudRunner, ApplicationScript, Packa
|
|
|
10434
10702
|
}
|
|
10435
10703
|
|
|
10436
10704
|
// pkgs/@akanjs/cli/cloud/cloud.command.ts
|
|
10705
|
+
var localRegistryUrl = () => process.env.AKAN_NPM_REGISTRY ?? "http://127.0.0.1:4873";
|
|
10706
|
+
var resolveRegistryUrl = (registry) => registry === "local" ? localRegistryUrl() : undefined;
|
|
10707
|
+
|
|
10437
10708
|
class CloudCommand extends command("cloud", [CloudScript], ({ public: target }) => ({
|
|
10438
10709
|
login: target({ desc: "Login to Akan Cloud services" }).with(Workspace).exec(async function(workspace) {
|
|
10439
10710
|
await this.cloudScript.login(workspace);
|
|
@@ -10450,15 +10721,43 @@ class CloudCommand extends command("cloud", [CloudScript], ({ public: target })
|
|
|
10450
10721
|
ask: target({ desc: "Ask AI assistant a question about your project" }).option("question", String, { ask: "question to ask" }).with(Workspace).exec(async function(question, workspace) {
|
|
10451
10722
|
await this.cloudScript.ask(question, workspace);
|
|
10452
10723
|
}),
|
|
10453
|
-
deployAkan: target({
|
|
10454
|
-
|
|
10724
|
+
deployAkan: target({
|
|
10725
|
+
devOnly: true,
|
|
10726
|
+
desc: "Deploy Akan.js framework to cloud (internal use)"
|
|
10727
|
+
}).option("test", Boolean, { desc: "test the deployment", default: true }).option("registry", String, {
|
|
10728
|
+
desc: "registry target for publishing Akan packages",
|
|
10729
|
+
ask: "Select a registry target",
|
|
10730
|
+
enum: [
|
|
10731
|
+
{ label: "local", value: "local" },
|
|
10732
|
+
{ label: "npm", value: "npm" }
|
|
10733
|
+
]
|
|
10734
|
+
}).with(Workspace).exec(async function(test, registry, workspace) {
|
|
10735
|
+
await this.cloudScript.deployAkan(workspace, {
|
|
10736
|
+
test,
|
|
10737
|
+
registryUrl: resolveRegistryUrl(registry)
|
|
10738
|
+
});
|
|
10455
10739
|
}),
|
|
10456
10740
|
update: target({ desc: "Update Akan.js framework to the latest version" }).with(Workspace).option("tag", String, {
|
|
10457
10741
|
desc: "tag of the update",
|
|
10458
10742
|
default: "latest",
|
|
10459
10743
|
enum: ["latest", "dev", "canary", "beta", "rc", "alpha"]
|
|
10460
|
-
}).
|
|
10461
|
-
|
|
10744
|
+
}).option("registry", String, {
|
|
10745
|
+
desc: "registry target for resolving Akan packages",
|
|
10746
|
+
ask: "Select a registry target",
|
|
10747
|
+
enum: [
|
|
10748
|
+
{ label: "npm", value: "npm" },
|
|
10749
|
+
{ label: "local", value: "local" }
|
|
10750
|
+
]
|
|
10751
|
+
}).exec(async function(workspace, tag, registry) {
|
|
10752
|
+
await this.cloudScript.update(workspace, tag, {
|
|
10753
|
+
registryUrl: resolveRegistryUrl(registry)
|
|
10754
|
+
});
|
|
10755
|
+
}),
|
|
10756
|
+
downloadEnv: target({ desc: "Download environment variables from cloud" }).with(Workspace).exec(async function(workspace) {
|
|
10757
|
+
await this.cloudScript.downloadEnv(workspace);
|
|
10758
|
+
}),
|
|
10759
|
+
uploadEnv: target({ desc: "Upload environment variables to cloud" }).with(Workspace).exec(async function(workspace) {
|
|
10760
|
+
await this.cloudScript.uploadEnv(workspace);
|
|
10462
10761
|
})
|
|
10463
10762
|
})) {
|
|
10464
10763
|
}
|
|
@@ -10479,19 +10778,19 @@ class GuidelinePrompt extends Prompter {
|
|
|
10479
10778
|
return page;
|
|
10480
10779
|
if (page.endsWith(".tsx"))
|
|
10481
10780
|
return page;
|
|
10482
|
-
return `apps/
|
|
10781
|
+
return `apps/akan/page${page}`;
|
|
10483
10782
|
}
|
|
10484
10783
|
async#getScanFilePaths(matchPattern, { avoidDirs = ["node_modules", ".next"], filterText } = {}) {
|
|
10485
10784
|
const glob = new Bun.Glob(matchPattern);
|
|
10486
10785
|
const paths = [];
|
|
10487
|
-
for await (const
|
|
10488
|
-
if (avoidDirs.some((dir) =>
|
|
10786
|
+
for await (const path39 of glob.scan({ cwd: this.workspace.workspaceRoot, absolute: true })) {
|
|
10787
|
+
if (avoidDirs.some((dir) => path39.includes(dir)))
|
|
10489
10788
|
continue;
|
|
10490
|
-
const fileContent = await FileSys.readText(
|
|
10789
|
+
const fileContent = await FileSys.readText(path39);
|
|
10491
10790
|
const textFilter = filterText ? new RegExp(filterText) : null;
|
|
10492
10791
|
if (filterText && !textFilter?.test(fileContent))
|
|
10493
10792
|
continue;
|
|
10494
|
-
paths.push(
|
|
10793
|
+
paths.push(path39);
|
|
10495
10794
|
}
|
|
10496
10795
|
return paths;
|
|
10497
10796
|
}
|
|
@@ -10786,6 +11085,147 @@ class LibraryCommand extends command("library", [LibraryScript], ({ public: targ
|
|
|
10786
11085
|
})) {
|
|
10787
11086
|
}
|
|
10788
11087
|
|
|
11088
|
+
// pkgs/@akanjs/cli/localRegistry/localRegistry.runner.ts
|
|
11089
|
+
import { mkdir as mkdir11, rm as rm5 } from "fs/promises";
|
|
11090
|
+
import path39 from "path";
|
|
11091
|
+
import { Logger as Logger17 } from "akanjs/common";
|
|
11092
|
+
var defaultLocalRegistryUrl = "http://127.0.0.1:4873";
|
|
11093
|
+
var containerName = "akan-verdaccio";
|
|
11094
|
+
var smokeRepoName = "akan-local-smoke";
|
|
11095
|
+
var smokeAppName = "demo";
|
|
11096
|
+
|
|
11097
|
+
class LocalRegistryRunner extends runner("localRegistry") {
|
|
11098
|
+
getRegistryUrl(registryUrl = process.env.AKAN_NPM_REGISTRY ?? defaultLocalRegistryUrl) {
|
|
11099
|
+
return getNpmRegistryUrl(registryUrl);
|
|
11100
|
+
}
|
|
11101
|
+
async start(workspace, { registryUrl } = {}) {
|
|
11102
|
+
const registry = this.getRegistryUrl(registryUrl);
|
|
11103
|
+
try {
|
|
11104
|
+
await workspace.spawn("docker", ["inspect", containerName]);
|
|
11105
|
+
Logger17.info(`Local registry is already running at ${registry}`);
|
|
11106
|
+
return registry;
|
|
11107
|
+
} catch {}
|
|
11108
|
+
const configPath2 = path39.join(workspace.workspaceRoot, "pkgs/@akanjs/cli/localRegistry/verdaccio.yaml");
|
|
11109
|
+
const storagePath = path39.join(workspace.workspaceRoot, ".akan/verdaccio/storage");
|
|
11110
|
+
await mkdir11(storagePath, { recursive: true });
|
|
11111
|
+
await workspace.spawn("docker", [
|
|
11112
|
+
"run",
|
|
11113
|
+
"--rm",
|
|
11114
|
+
"-d",
|
|
11115
|
+
"--name",
|
|
11116
|
+
containerName,
|
|
11117
|
+
"-p",
|
|
11118
|
+
"4873:4873",
|
|
11119
|
+
"-v",
|
|
11120
|
+
`${configPath2}:/verdaccio/conf/config.yaml:ro`,
|
|
11121
|
+
"-v",
|
|
11122
|
+
`${storagePath}:/verdaccio/storage`,
|
|
11123
|
+
"verdaccio/verdaccio:6"
|
|
11124
|
+
], { stdio: "inherit" });
|
|
11125
|
+
Logger17.info(`Local registry is running at ${registry}`);
|
|
11126
|
+
return registry;
|
|
11127
|
+
}
|
|
11128
|
+
async reset(workspace) {
|
|
11129
|
+
try {
|
|
11130
|
+
await workspace.spawn("docker", ["rm", "-f", containerName], { stdio: "inherit" });
|
|
11131
|
+
} catch {}
|
|
11132
|
+
await rm5(path39.join(workspace.workspaceRoot, ".akan/verdaccio"), { recursive: true, force: true });
|
|
11133
|
+
Logger17.info("Local registry storage has been reset");
|
|
11134
|
+
}
|
|
11135
|
+
async smoke(workspace, { registryUrl } = {}) {
|
|
11136
|
+
const registry = this.getRegistryUrl(registryUrl);
|
|
11137
|
+
const smokeRoot = path39.join(workspace.workspaceRoot, ".akan/e2e");
|
|
11138
|
+
await rm5(path39.join(smokeRoot, smokeRepoName), { recursive: true, force: true });
|
|
11139
|
+
await workspace.spawn(process.execPath, [
|
|
11140
|
+
"dist/pkgs/create-akan-workspace/index.js",
|
|
11141
|
+
smokeRepoName,
|
|
11142
|
+
"--app",
|
|
11143
|
+
smokeAppName,
|
|
11144
|
+
"--dir",
|
|
11145
|
+
".akan/e2e",
|
|
11146
|
+
"--init",
|
|
11147
|
+
"true",
|
|
11148
|
+
"--registry",
|
|
11149
|
+
registry
|
|
11150
|
+
], {
|
|
11151
|
+
env: { ...process.env, AKAN_NPM_REGISTRY: registry, NPM_CONFIG_REGISTRY: registry },
|
|
11152
|
+
stdio: "inherit"
|
|
11153
|
+
});
|
|
11154
|
+
await workspace.spawn("akan", ["build", smokeAppName], {
|
|
11155
|
+
cwd: path39.join(smokeRoot, smokeRepoName),
|
|
11156
|
+
env: { ...process.env, AKAN_NPM_REGISTRY: registry, NPM_CONFIG_REGISTRY: registry },
|
|
11157
|
+
stdio: "inherit"
|
|
11158
|
+
});
|
|
11159
|
+
Logger17.info(`Local registry smoke test completed for ${smokeRepoName}/${smokeAppName}`);
|
|
11160
|
+
}
|
|
11161
|
+
}
|
|
11162
|
+
|
|
11163
|
+
// pkgs/@akanjs/cli/localRegistry/localRegistry.script.ts
|
|
11164
|
+
class LocalRegistryScript extends script("localRegistry", [
|
|
11165
|
+
LocalRegistryRunner,
|
|
11166
|
+
CloudRunner,
|
|
11167
|
+
ApplicationScript,
|
|
11168
|
+
PackageScript
|
|
11169
|
+
]) {
|
|
11170
|
+
async start(workspace, { registryUrl } = {}) {
|
|
11171
|
+
const spinner2 = workspace.spinning("Starting local npm registry...");
|
|
11172
|
+
const registry = await this.localRegistryRunner.start(workspace, { registryUrl });
|
|
11173
|
+
spinner2.succeed(`Local npm registry is ready at ${registry}`);
|
|
11174
|
+
}
|
|
11175
|
+
async reset(workspace) {
|
|
11176
|
+
const spinner2 = workspace.spinning("Resetting local npm registry...");
|
|
11177
|
+
await this.localRegistryRunner.reset(workspace);
|
|
11178
|
+
spinner2.succeed("Local npm registry reset");
|
|
11179
|
+
}
|
|
11180
|
+
async smoke(workspace, { tag = "rc", test = true, registryUrl } = {}) {
|
|
11181
|
+
const registry = await this.localRegistryRunner.start(workspace, { registryUrl });
|
|
11182
|
+
const akanPkgs = await this.cloudRunner.getAkanPkgs(workspace);
|
|
11183
|
+
await this.#preparePackages(workspace, akanPkgs, { test });
|
|
11184
|
+
await this.cloudRunner.deployAkan(workspace, akanPkgs, {
|
|
11185
|
+
registryUrl: registry,
|
|
11186
|
+
confirmPublish: false,
|
|
11187
|
+
tag
|
|
11188
|
+
});
|
|
11189
|
+
await this.localRegistryRunner.smoke(workspace, { registryUrl: registry });
|
|
11190
|
+
}
|
|
11191
|
+
async#preparePackages(workspace, akanPkgs, { test = true } = {}) {
|
|
11192
|
+
await this.packageScript.updateWorskpaceRootPackageJson(workspace);
|
|
11193
|
+
const pkgs = akanPkgs.map((pkgName) => PkgExecutor.from(workspace, pkgName));
|
|
11194
|
+
if (test)
|
|
11195
|
+
for (const pkg of pkgs)
|
|
11196
|
+
await this.applicationScript.test(pkg);
|
|
11197
|
+
for (const pkg of pkgs)
|
|
11198
|
+
await this.packageScript.buildPackage(pkg, { showSpinner: false });
|
|
11199
|
+
}
|
|
11200
|
+
}
|
|
11201
|
+
|
|
11202
|
+
// pkgs/@akanjs/cli/localRegistry/localRegistry.command.ts
|
|
11203
|
+
class LocalRegistryCommand extends command("local-registry", [LocalRegistryScript], ({ public: target }) => ({
|
|
11204
|
+
startRegistry: target({ devOnly: true, desc: "Start the local Verdaccio npm registry" }).with(Workspace).option("registry", String, {
|
|
11205
|
+
desc: "local npm registry URL",
|
|
11206
|
+
default: process.env.AKAN_NPM_REGISTRY ?? "http://127.0.0.1:4873"
|
|
11207
|
+
}).exec(async function(workspace, registry) {
|
|
11208
|
+
await this.localRegistryScript.start(workspace, { registryUrl: registry });
|
|
11209
|
+
}),
|
|
11210
|
+
resetRegistry: target({ devOnly: true, desc: "Stop and clear the local Verdaccio npm registry" }).with(Workspace).exec(async function(workspace) {
|
|
11211
|
+
await this.localRegistryScript.reset(workspace);
|
|
11212
|
+
}),
|
|
11213
|
+
smokeRegistry: target({ devOnly: true, desc: "Publish to local registry and build a generated workspace" }).with(Workspace).option("tag", String, {
|
|
11214
|
+
flag: "g",
|
|
11215
|
+
desc: "dist-tag for local registry publish",
|
|
11216
|
+
default: "rc"
|
|
11217
|
+
}).option("test", Boolean, {
|
|
11218
|
+
desc: "run package tests before publishing",
|
|
11219
|
+
default: true
|
|
11220
|
+
}).option("registry", String, {
|
|
11221
|
+
desc: "local npm registry URL",
|
|
11222
|
+
default: process.env.AKAN_NPM_REGISTRY
|
|
11223
|
+
}).exec(async function(workspace, tag, test, registry) {
|
|
11224
|
+
await this.localRegistryScript.smoke(workspace, { tag, test, registryUrl: registry });
|
|
11225
|
+
})
|
|
11226
|
+
})) {
|
|
11227
|
+
}
|
|
11228
|
+
|
|
10789
11229
|
// pkgs/@akanjs/cli/module/module.command.ts
|
|
10790
11230
|
import { lowerlize } from "akanjs/common";
|
|
10791
11231
|
|
|
@@ -11581,11 +12021,11 @@ class ScalarCommand extends command("scalar", [ScalarScript], ({ public: target
|
|
|
11581
12021
|
}
|
|
11582
12022
|
|
|
11583
12023
|
// pkgs/@akanjs/cli/workspace/workspace.script.ts
|
|
11584
|
-
import
|
|
11585
|
-
import { Logger as
|
|
12024
|
+
import path41 from "path";
|
|
12025
|
+
import { Logger as Logger18 } from "akanjs/common";
|
|
11586
12026
|
|
|
11587
12027
|
// pkgs/@akanjs/cli/workspace/workspace.runner.ts
|
|
11588
|
-
import
|
|
12028
|
+
import path40 from "path";
|
|
11589
12029
|
var defaultWorkspacePeerDependencies = new Set([
|
|
11590
12030
|
"@radix-ui/react-dialog",
|
|
11591
12031
|
"@react-spring/web",
|
|
@@ -11605,20 +12045,29 @@ var defaultWorkspacePeerDependencies = new Set([
|
|
|
11605
12045
|
]);
|
|
11606
12046
|
|
|
11607
12047
|
class WorkspaceRunner extends runner("workspace") {
|
|
11608
|
-
async createWorkspace(repoName, appName, {
|
|
12048
|
+
async createWorkspace(repoName, appName, {
|
|
12049
|
+
dirname: dirname3 = ".",
|
|
12050
|
+
init = true,
|
|
12051
|
+
akanVersion,
|
|
12052
|
+
registryUrl
|
|
12053
|
+
}) {
|
|
11609
12054
|
const cwdPath = process.cwd();
|
|
11610
|
-
const workspaceRoot =
|
|
12055
|
+
const workspaceRoot = path40.join(cwdPath, dirname3, repoName);
|
|
12056
|
+
const normalizedRegistryUrl = registryUrl ? getNpmRegistryUrl(registryUrl) : undefined;
|
|
11611
12057
|
const workspace = WorkspaceExecutor.fromRoot({ workspaceRoot, repoName });
|
|
11612
12058
|
const templateSpinner = workspace.spinning(`Creating workspace template files in ${dirname3}/${repoName}...`);
|
|
11613
12059
|
const [latestBiomeVersion, latestTypesBunVersion] = await Promise.all([
|
|
11614
|
-
getLatestPackageVersion("@biomejs/biome"),
|
|
11615
|
-
getLatestPackageVersion("@types/bun")
|
|
12060
|
+
getLatestPackageVersion("@biomejs/biome", "latest", normalizedRegistryUrl),
|
|
12061
|
+
getLatestPackageVersion("@types/bun", "latest", normalizedRegistryUrl)
|
|
11616
12062
|
]);
|
|
11617
12063
|
await workspace.applyTemplate({
|
|
11618
12064
|
basePath: ".",
|
|
11619
12065
|
template: "workspaceRoot",
|
|
11620
12066
|
dict: { repoName, appName, serveDomain: "localhost" }
|
|
11621
12067
|
});
|
|
12068
|
+
if (normalizedRegistryUrl)
|
|
12069
|
+
await workspace.writeFile(".npmrc", `registry=${normalizedRegistryUrl}/
|
|
12070
|
+
`);
|
|
11622
12071
|
templateSpinner.succeed(`Workspace files created in ${dirname3}/${repoName}`);
|
|
11623
12072
|
const [rootPackageJson, peerDependencies] = await Promise.all([
|
|
11624
12073
|
workspace.getPackageJson(),
|
|
@@ -11659,9 +12108,9 @@ class WorkspaceRunner extends runner("workspace") {
|
|
|
11659
12108
|
}
|
|
11660
12109
|
async#getCliPackageJson() {
|
|
11661
12110
|
const packageJsonCandidates = [
|
|
11662
|
-
|
|
11663
|
-
|
|
11664
|
-
|
|
12111
|
+
path40.join(import.meta.dir, "../package.json"),
|
|
12112
|
+
path40.join(import.meta.dir, "package.json"),
|
|
12113
|
+
path40.join(path40.dirname(Bun.main), "package.json")
|
|
11665
12114
|
];
|
|
11666
12115
|
try {
|
|
11667
12116
|
packageJsonCandidates.unshift(Bun.resolveSync("@akanjs/cli/package.json", import.meta.dir));
|
|
@@ -11677,9 +12126,9 @@ class WorkspaceRunner extends runner("workspace") {
|
|
|
11677
12126
|
}
|
|
11678
12127
|
async#getAkanPackageJson() {
|
|
11679
12128
|
const packageJsonCandidates = [
|
|
11680
|
-
|
|
11681
|
-
|
|
11682
|
-
|
|
12129
|
+
path40.join(import.meta.dir, "../../../akanjs/package.json"),
|
|
12130
|
+
path40.join(process.cwd(), "pkgs/akanjs/package.json"),
|
|
12131
|
+
path40.join(path40.dirname(Bun.main), "node_modules/akanjs/package.json")
|
|
11683
12132
|
];
|
|
11684
12133
|
try {
|
|
11685
12134
|
packageJsonCandidates.unshift(Bun.resolveSync("akanjs/package.json", import.meta.dir));
|
|
@@ -11693,13 +12142,13 @@ class WorkspaceRunner extends runner("workspace") {
|
|
|
11693
12142
|
}
|
|
11694
12143
|
let current = import.meta.dir;
|
|
11695
12144
|
for (let depth = 0;depth < 6; depth++) {
|
|
11696
|
-
const packageJsonPath =
|
|
12145
|
+
const packageJsonPath = path40.join(current, "package.json");
|
|
11697
12146
|
if (await Bun.file(packageJsonPath).exists()) {
|
|
11698
12147
|
const packageJson = await FileSys.readJson(packageJsonPath);
|
|
11699
12148
|
if (packageJson.name === "akanjs")
|
|
11700
12149
|
return packageJson;
|
|
11701
12150
|
}
|
|
11702
|
-
const parent =
|
|
12151
|
+
const parent = path40.dirname(current);
|
|
11703
12152
|
if (parent === current)
|
|
11704
12153
|
break;
|
|
11705
12154
|
current = parent;
|
|
@@ -11723,12 +12172,18 @@ class WorkspaceScript extends script("workspace", [
|
|
|
11723
12172
|
LibraryScript,
|
|
11724
12173
|
PackageScript
|
|
11725
12174
|
]) {
|
|
11726
|
-
async createWorkspace(repoName, appName, {
|
|
12175
|
+
async createWorkspace(repoName, appName, {
|
|
12176
|
+
dirname: dirname3 = ".",
|
|
12177
|
+
installLibs = false,
|
|
12178
|
+
init = true,
|
|
12179
|
+
registryUrl
|
|
12180
|
+
}) {
|
|
11727
12181
|
const akanVersion = await this.packageScript.version(null, { log: false });
|
|
11728
12182
|
const workspace = await this.workspaceRunner.createWorkspace(repoName, appName, {
|
|
11729
12183
|
dirname: dirname3,
|
|
11730
12184
|
init,
|
|
11731
|
-
akanVersion
|
|
12185
|
+
akanVersion,
|
|
12186
|
+
...registryUrl ? { registryUrl } : {}
|
|
11732
12187
|
});
|
|
11733
12188
|
if (installLibs) {
|
|
11734
12189
|
await this.libraryScript.installLibrary(workspace, "util");
|
|
@@ -11742,11 +12197,11 @@ class WorkspaceScript extends script("workspace", [
|
|
|
11742
12197
|
} catch (_) {
|
|
11743
12198
|
gitSpinner.fail("Git repository initialization failed. It's not fatal, you can commit manually");
|
|
11744
12199
|
}
|
|
11745
|
-
const workspacePath =
|
|
11746
|
-
|
|
12200
|
+
const workspacePath = path41.join(dirname3, repoName);
|
|
12201
|
+
Logger18.rawLog(`
|
|
11747
12202
|
\uD83C\uDF89 Welcome aboard! Workspace created in ${dirname3}/${repoName}`);
|
|
11748
|
-
|
|
11749
|
-
|
|
12203
|
+
Logger18.rawLog(`\uD83D\uDE80 Run \`cd ${workspacePath} && akan start ${appName}\` to start the development server.`);
|
|
12204
|
+
Logger18.rawLog(`
|
|
11750
12205
|
\uD83D\uDC4B Happy coding!`);
|
|
11751
12206
|
}
|
|
11752
12207
|
async lint(exec2, workspace, { fix = true } = {}) {
|
|
@@ -11801,9 +12256,12 @@ class WorkspaceCommand extends command("workspace", [WorkspaceScript], ({ public
|
|
|
11801
12256
|
}).option("init", Boolean, {
|
|
11802
12257
|
desc: "Do you want to initialize the workspace? (Recommended)",
|
|
11803
12258
|
default: true
|
|
11804
|
-
}).
|
|
12259
|
+
}).option("registry", String, {
|
|
12260
|
+
desc: "npm registry URL for installing Akan packages",
|
|
12261
|
+
default: process.env.AKAN_NPM_REGISTRY
|
|
12262
|
+
}).exec(async function(workspaceName, app, dir, libs, init, registry) {
|
|
11805
12263
|
const appName = app || "app";
|
|
11806
|
-
await this.workspaceScript.createWorkspace(workspaceName.toLowerCase().replace(/ /g, "-"), appName.toLowerCase().replace(/ /g, "-"), { dirname: dir, installLibs: libs, init });
|
|
12264
|
+
await this.workspaceScript.createWorkspace(workspaceName.toLowerCase().replace(/ /g, "-"), appName.toLowerCase().replace(/ /g, "-"), { dirname: dir, installLibs: libs, init, ...registry ? { registryUrl: registry } : {} });
|
|
11807
12265
|
}),
|
|
11808
12266
|
lint: target({ desc: "Lint and fix code in a specific app/lib/pkg" }).with(Exec).option("fix", Boolean, { default: true }).with(Workspace).exec(async function(exec2, fix, workspace) {
|
|
11809
12267
|
await this.workspaceScript.lint(exec2, workspace, { fix });
|
|
@@ -11818,4 +12276,4 @@ class WorkspaceCommand extends command("workspace", [WorkspaceScript], ({ public
|
|
|
11818
12276
|
}
|
|
11819
12277
|
|
|
11820
12278
|
// pkgs/@akanjs/cli/index.ts
|
|
11821
|
-
runCommands(WorkspaceCommand, ApplicationCommand, LibraryCommand, PackageCommand, ModuleCommand, PageCommand, CloudCommand, GuidelineCommand, ScalarCommand);
|
|
12279
|
+
runCommands(WorkspaceCommand, ApplicationCommand, LibraryCommand, LocalRegistryCommand, PackageCommand, ModuleCommand, PageCommand, CloudCommand, GuidelineCommand, ScalarCommand);
|