@akanjs/cli 0.0.89 → 0.0.90
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/index.js +1094 -336
- package/package.json +1 -1
- package/pkgs/@akanjs/cli/src/application/application.command.d.ts +2 -2
- package/pkgs/@akanjs/cli/src/application/application.runner.d.ts +3 -1
- package/pkgs/@akanjs/cli/src/application/application.script.d.ts +3 -1
- package/pkgs/@akanjs/cli/src/cloud/cloud.command.d.ts +3 -0
- package/pkgs/@akanjs/cli/src/cloud/cloud.runner.d.ts +2 -0
- package/pkgs/@akanjs/cli/src/cloud/cloud.script.d.ts +3 -0
- package/pkgs/@akanjs/cli/src/library/library.command.d.ts +1 -1
- package/pkgs/@akanjs/cli/src/library/library.runner.d.ts +2 -0
- package/pkgs/@akanjs/cli/src/library/library.script.d.ts +2 -0
- package/pkgs/@akanjs/cli/src/module/module.prompt.d.ts +17 -8
- package/pkgs/@akanjs/cli/src/module/module.runner.d.ts +1 -3
- package/pkgs/@akanjs/cli/src/module/module.script.d.ts +1 -1
- package/pkgs/@akanjs/cli/src/package/package.command.d.ts +1 -1
- package/pkgs/@akanjs/cli/src/package/package.runner.d.ts +1 -0
- package/pkgs/@akanjs/cli/src/package/package.script.d.ts +1 -0
- package/pkgs/@akanjs/devkit/src/aiEditor.d.ts +14 -0
- package/pkgs/@akanjs/devkit/src/constants.d.ts +8 -1
- package/pkgs/@akanjs/devkit/src/executors.d.ts +21 -1
- package/pkgs/@akanjs/devkit/src/getRelatedCnsts.d.ts +52 -8
- package/src/templates/workspaceRoot/package.json.template +5 -0
- /package/pkgs/@akanjs/cli/src/{package/page → page}/page.command.d.ts +0 -0
- /package/pkgs/@akanjs/cli/src/{package/page → page}/page.runner.d.ts +0 -0
- /package/pkgs/@akanjs/cli/src/{package/page → page}/page.script.d.ts +0 -0
package/index.js
CHANGED
|
@@ -58,8 +58,8 @@ var createTunnel = async ({ app, environment, port = 27017 }) => {
|
|
|
58
58
|
};
|
|
59
59
|
|
|
60
60
|
// pkgs/@akanjs/devkit/src/getCredentials.ts
|
|
61
|
-
var import_fs = __toESM(require("fs")
|
|
62
|
-
var import_js_yaml = __toESM(require("js-yaml")
|
|
61
|
+
var import_fs = __toESM(require("fs"));
|
|
62
|
+
var import_js_yaml = __toESM(require("js-yaml"));
|
|
63
63
|
var getCredentials = (app, environment) => {
|
|
64
64
|
const secret = import_js_yaml.default.load(
|
|
65
65
|
import_fs.default.readFileSync(`${app.workspace.workspaceRoot}/infra/app/values/${app.name}-secret.yaml`, "utf-8")
|
|
@@ -68,9 +68,9 @@ var getCredentials = (app, environment) => {
|
|
|
68
68
|
};
|
|
69
69
|
|
|
70
70
|
// pkgs/@akanjs/devkit/src/uploadRelease.ts
|
|
71
|
-
var import_axios = __toESM(require("axios")
|
|
72
|
-
var import_form_data = __toESM(require("form-data")
|
|
73
|
-
var import_fs2 = __toESM(require("fs")
|
|
71
|
+
var import_axios = __toESM(require("axios"));
|
|
72
|
+
var import_form_data = __toESM(require("form-data"));
|
|
73
|
+
var import_fs2 = __toESM(require("fs"));
|
|
74
74
|
var uploadRelease = async (projectName, {
|
|
75
75
|
workspaceRoot,
|
|
76
76
|
environment,
|
|
@@ -119,58 +119,96 @@ var uploadRelease = async (projectName, {
|
|
|
119
119
|
};
|
|
120
120
|
|
|
121
121
|
// pkgs/@akanjs/devkit/src/getModelFileData.ts
|
|
122
|
-
var import_fs3 = __toESM(require("fs")
|
|
123
|
-
var getModelFileData = (modulePath, modelName) => {
|
|
124
|
-
const moduleType = modulePath.startsWith("apps") ? "app" : "lib";
|
|
125
|
-
const moduleName = modulePath.split("/")[1];
|
|
126
|
-
const constantFilePath = `${modulePath}/lib/${modelName}/${modelName}.constant.ts`;
|
|
127
|
-
const unitFilePath = `${modulePath}/lib/${modelName}/${modelName}.Unit.tsx`;
|
|
128
|
-
const viewFilePath = `${modulePath}/lib/${modelName}/${modelName}.View.tsx`;
|
|
129
|
-
const constantFileStr = import_fs3.default.readFileSync(constantFilePath, "utf8");
|
|
130
|
-
const unitFileStr = import_fs3.default.readFileSync(unitFilePath, "utf8");
|
|
131
|
-
const viewFileStr = import_fs3.default.readFileSync(viewFilePath, "utf8");
|
|
132
|
-
const constantFileLines = constantFileStr.split("\n");
|
|
133
|
-
const importLibNames = constantFileLines.filter((line) => line.startsWith("import { cnst as ")).map((line) => line.split("cnst as ")[1].split(" ")[0]);
|
|
134
|
-
const importLocalPaths = constantFileLines.filter((line) => line.startsWith("import { ") && line.includes('from "../')).map((line) => line.split("from ")[1].split('"')[1]);
|
|
135
|
-
const importModelNames = importLocalPaths.map((path7) => path7.split("/")[1]).filter((name) => !name.startsWith("_"));
|
|
136
|
-
const hasImportScalar = !!importLocalPaths.map((path7) => path7.split("/")[1]).filter((name) => name.startsWith("_")).length;
|
|
137
|
-
return {
|
|
138
|
-
moduleType,
|
|
139
|
-
moduleName,
|
|
140
|
-
modelName,
|
|
141
|
-
constantFilePath,
|
|
142
|
-
unitFilePath,
|
|
143
|
-
viewFilePath,
|
|
144
|
-
importModelNames,
|
|
145
|
-
hasImportScalar,
|
|
146
|
-
importLibNames,
|
|
147
|
-
constantFileStr,
|
|
148
|
-
unitFileStr,
|
|
149
|
-
viewFileStr
|
|
150
|
-
};
|
|
151
|
-
};
|
|
122
|
+
var import_fs3 = __toESM(require("fs"));
|
|
152
123
|
|
|
153
124
|
// pkgs/@akanjs/devkit/src/getRelatedCnsts.ts
|
|
154
|
-
var
|
|
155
|
-
var import_ora = __toESM(require("ora")
|
|
156
|
-
var ts = __toESM(require("typescript")
|
|
157
|
-
var
|
|
158
|
-
const tsConfigPath = `./tsconfig.json`;
|
|
125
|
+
var fs4 = __toESM(require("fs"));
|
|
126
|
+
var import_ora = __toESM(require("ora"));
|
|
127
|
+
var ts = __toESM(require("typescript"));
|
|
128
|
+
var parseTsConfig = (tsConfigPath = "./tsconfig.json") => {
|
|
159
129
|
const configFile = ts.readConfigFile(tsConfigPath, (path7) => {
|
|
160
130
|
return ts.sys.readFile(path7);
|
|
161
131
|
});
|
|
162
|
-
|
|
132
|
+
return ts.parseJsonConfigFileContent(
|
|
163
133
|
configFile.config,
|
|
164
134
|
ts.sys,
|
|
165
|
-
|
|
135
|
+
fs4.realpathSync(tsConfigPath).replace(/[^/\\]+$/, "")
|
|
166
136
|
);
|
|
137
|
+
};
|
|
138
|
+
var collectImportedFiles = (constantFilePath, parsedConfig) => {
|
|
139
|
+
const allFilesToAnalyze = /* @__PURE__ */ new Set([constantFilePath]);
|
|
140
|
+
const analyzedFiles = /* @__PURE__ */ new Set();
|
|
141
|
+
const spinner = (0, import_ora.default)("Collecting related files...");
|
|
142
|
+
spinner.start();
|
|
143
|
+
function collectImported(filePath) {
|
|
144
|
+
if (analyzedFiles.has(filePath))
|
|
145
|
+
return;
|
|
146
|
+
analyzedFiles.add(filePath);
|
|
147
|
+
const tempProgram = ts.createProgram([filePath], parsedConfig.options);
|
|
148
|
+
const source = tempProgram.getSourceFile(filePath);
|
|
149
|
+
if (!source)
|
|
150
|
+
return;
|
|
151
|
+
function collectImports(node) {
|
|
152
|
+
if (ts.isImportDeclaration(node) && ts.isStringLiteral(node.moduleSpecifier)) {
|
|
153
|
+
const importPath = node.moduleSpecifier.text;
|
|
154
|
+
if (importPath.startsWith(".")) {
|
|
155
|
+
const resolved = ts.resolveModuleName(importPath, filePath, parsedConfig.options, ts.sys).resolvedModule?.resolvedFileName;
|
|
156
|
+
if (resolved && !allFilesToAnalyze.has(resolved)) {
|
|
157
|
+
allFilesToAnalyze.add(resolved);
|
|
158
|
+
collectImported(resolved);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
ts.forEachChild(node, collectImports);
|
|
163
|
+
}
|
|
164
|
+
collectImports(source);
|
|
165
|
+
}
|
|
166
|
+
collectImported(constantFilePath);
|
|
167
|
+
spinner.succeed(`Found ${allFilesToAnalyze.size} related files.`);
|
|
168
|
+
return {
|
|
169
|
+
allFilesToAnalyze,
|
|
170
|
+
analyzedFiles
|
|
171
|
+
};
|
|
172
|
+
};
|
|
173
|
+
var createTsProgram = (filePaths, options) => {
|
|
174
|
+
const spinner = (0, import_ora.default)("Creating TypeScript program for all files...");
|
|
175
|
+
spinner.start();
|
|
176
|
+
const program2 = ts.createProgram(Array.from(filePaths), options);
|
|
177
|
+
const checker = program2.getTypeChecker();
|
|
178
|
+
spinner.succeed("TypeScript program created.");
|
|
179
|
+
return {
|
|
180
|
+
program: program2,
|
|
181
|
+
checker
|
|
182
|
+
};
|
|
183
|
+
};
|
|
184
|
+
var createSymbolCache = (checker) => {
|
|
185
|
+
const symbolCache = /* @__PURE__ */ new Map();
|
|
186
|
+
return (node) => {
|
|
187
|
+
const cacheKey = `${node.getSourceFile().fileName}:${node.pos}:${node.end}`;
|
|
188
|
+
if (!symbolCache.has(cacheKey)) {
|
|
189
|
+
symbolCache.set(cacheKey, checker.getSymbolAtLocation(node));
|
|
190
|
+
}
|
|
191
|
+
return symbolCache.get(cacheKey);
|
|
192
|
+
};
|
|
193
|
+
};
|
|
194
|
+
var analyzeProperties = (filesToAnalyze, program2, checker) => {
|
|
167
195
|
const propertyMap = /* @__PURE__ */ new Map();
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
196
|
+
const analyzedFiles = /* @__PURE__ */ new Set();
|
|
197
|
+
const sourceLineCache = /* @__PURE__ */ new Map();
|
|
198
|
+
const getCachedSymbol = createSymbolCache(checker);
|
|
199
|
+
const spinner = (0, import_ora.default)("Analyzing property relationships...");
|
|
200
|
+
spinner.start();
|
|
201
|
+
function analyzeFileProperties(filePath) {
|
|
202
|
+
if (analyzedFiles.has(filePath))
|
|
203
|
+
return;
|
|
204
|
+
analyzedFiles.add(filePath);
|
|
171
205
|
const source = program2.getSourceFile(filePath);
|
|
172
206
|
if (!source)
|
|
173
|
-
return
|
|
207
|
+
return;
|
|
208
|
+
if (!sourceLineCache.has(filePath)) {
|
|
209
|
+
sourceLineCache.set(filePath, source.getFullText().split("\n"));
|
|
210
|
+
}
|
|
211
|
+
const sourceLines = sourceLineCache.get(filePath);
|
|
174
212
|
function visit(node) {
|
|
175
213
|
if (!source)
|
|
176
214
|
return;
|
|
@@ -178,37 +216,38 @@ var getRelatedCnsts = (constantFilePath) => {
|
|
|
178
216
|
const left = node.expression;
|
|
179
217
|
const right = node.name;
|
|
180
218
|
const { line } = ts.getLineAndCharacterOfPosition(source, node.getStart());
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
const symbol = checker.getSymbolAtLocation(right);
|
|
219
|
+
if (ts.isIdentifier(left) && sourceLines && sourceLines.length > line && (sourceLines[line].includes(`@Field.Prop(() => ${left.text}.${right.text}`) || sourceLines[line].includes(`base.Filter(${left.text}.${right.text},`))) {
|
|
220
|
+
const symbol = getCachedSymbol(right);
|
|
184
221
|
if (symbol?.declarations && symbol.declarations.length > 0) {
|
|
185
222
|
const key = symbol.declarations[0].getSourceFile().fileName.split("/").pop()?.split(".")[0] ?? "";
|
|
186
223
|
const property = propertyMap.get(key);
|
|
187
224
|
const isScalar = symbol.declarations[0].getSourceFile().fileName.includes("_");
|
|
188
|
-
const
|
|
225
|
+
const symbolFilePath = symbol.declarations[0].getSourceFile().fileName.replace(`${ts.sys.getCurrentDirectory()}/`, "");
|
|
189
226
|
if (property) {
|
|
190
227
|
propertyMap.set(`${left.text}.${right.text}`, {
|
|
191
|
-
filePath:
|
|
228
|
+
filePath: symbolFilePath,
|
|
192
229
|
isLibModule: true,
|
|
193
230
|
isImport: false,
|
|
194
231
|
libName: left.text,
|
|
232
|
+
source: fs4.readFileSync(symbolFilePath, "utf-8"),
|
|
195
233
|
isScalar
|
|
196
234
|
});
|
|
197
|
-
} else
|
|
235
|
+
} else {
|
|
198
236
|
propertyMap.set(key, {
|
|
199
|
-
filePath:
|
|
237
|
+
filePath: symbolFilePath,
|
|
200
238
|
isLibModule: true,
|
|
201
239
|
isImport: false,
|
|
202
240
|
libName: left.text,
|
|
203
|
-
isScalar
|
|
241
|
+
isScalar,
|
|
242
|
+
source: fs4.readFileSync(symbolFilePath, "utf-8")
|
|
204
243
|
});
|
|
205
|
-
|
|
244
|
+
}
|
|
206
245
|
}
|
|
207
246
|
}
|
|
208
|
-
} else if (ts.isImportDeclaration(node)) {
|
|
209
|
-
const importPath = node.moduleSpecifier.
|
|
247
|
+
} else if (ts.isImportDeclaration(node) && ts.isStringLiteral(node.moduleSpecifier)) {
|
|
248
|
+
const importPath = node.moduleSpecifier.text;
|
|
210
249
|
if (importPath.startsWith(".")) {
|
|
211
|
-
const resolved = ts.resolveModuleName(importPath, filePath,
|
|
250
|
+
const resolved = ts.resolveModuleName(importPath, filePath, program2.getCompilerOptions(), ts.sys).resolvedModule?.resolvedFileName;
|
|
212
251
|
const moduleName = importPath.split("/").pop()?.split(".")[0] ?? "";
|
|
213
252
|
const property = propertyMap.get(moduleName);
|
|
214
253
|
const isScalar = importPath.includes("_");
|
|
@@ -217,87 +256,38 @@ var getRelatedCnsts = (constantFilePath) => {
|
|
|
217
256
|
filePath: resolved,
|
|
218
257
|
isLibModule: false,
|
|
219
258
|
isImport: true,
|
|
220
|
-
isScalar
|
|
259
|
+
isScalar,
|
|
260
|
+
source: fs4.readFileSync(resolved, "utf-8")
|
|
221
261
|
});
|
|
222
|
-
findPropertyOriginAll(resolved);
|
|
223
262
|
}
|
|
224
263
|
}
|
|
225
264
|
}
|
|
226
265
|
ts.forEachChild(node, visit);
|
|
227
266
|
}
|
|
228
267
|
visit(source);
|
|
229
|
-
return propertyMap;
|
|
230
268
|
}
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
const checker = program2.getTypeChecker();
|
|
234
|
-
const source = program2.getSourceFile(filePath);
|
|
235
|
-
const propertyMap2 = /* @__PURE__ */ new Map();
|
|
236
|
-
if (!source)
|
|
237
|
-
return null;
|
|
238
|
-
function visit(node) {
|
|
239
|
-
if (ts.isPropertyAccessExpression(node)) {
|
|
240
|
-
const left = node.expression;
|
|
241
|
-
const right = node.name;
|
|
242
|
-
if (ts.isIdentifier(left) && left.text === aliasName && right.text === libName) {
|
|
243
|
-
const symbol = checker.getSymbolAtLocation(right);
|
|
244
|
-
if (symbol?.declarations && symbol.declarations.length > 0) {
|
|
245
|
-
return symbol.declarations[0].getSourceFile().fileName;
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
return ts.forEachChild(node, visit) || null;
|
|
250
|
-
}
|
|
251
|
-
return visit(source);
|
|
269
|
+
for (const filePath of filesToAnalyze) {
|
|
270
|
+
analyzeFileProperties(filePath);
|
|
252
271
|
}
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
272
|
+
spinner.succeed(`Analysis complete. Found ${propertyMap.size} properties.`);
|
|
273
|
+
return propertyMap;
|
|
274
|
+
};
|
|
275
|
+
var getRelatedCnsts = (constantFilePath) => {
|
|
276
|
+
const parsedConfig = parseTsConfig();
|
|
277
|
+
const { allFilesToAnalyze } = collectImportedFiles(constantFilePath, parsedConfig);
|
|
278
|
+
const { program: program2, checker } = createTsProgram(allFilesToAnalyze, parsedConfig.options);
|
|
279
|
+
const propertyMap = analyzeProperties(allFilesToAnalyze, program2, checker);
|
|
280
|
+
return Array.from(propertyMap.entries()).map(([key, value]) => ({ key, ...value }));
|
|
258
281
|
};
|
|
259
282
|
|
|
260
283
|
// pkgs/@akanjs/devkit/src/selectModel.ts
|
|
261
284
|
var import_prompts = require("@inquirer/prompts");
|
|
262
|
-
var
|
|
285
|
+
var import_fs4 = __toESM(require("fs"));
|
|
263
286
|
|
|
264
287
|
// pkgs/@akanjs/devkit/src/streamAi.ts
|
|
265
288
|
var import_prompts2 = require("@langchain/core/prompts");
|
|
266
289
|
var import_runnables = require("@langchain/core/runnables");
|
|
267
290
|
var import_openai = require("@langchain/openai");
|
|
268
|
-
var streamAi = async (question, callback = (chunk) => {
|
|
269
|
-
process.stdout.write(chunk);
|
|
270
|
-
}) => {
|
|
271
|
-
const createStreamingModel = (apiKey = process.env.DEEPSEEK_API_KEY) => {
|
|
272
|
-
if (!apiKey)
|
|
273
|
-
throw new Error(`process.env.DEEPSEEK_API_KEY is not set`);
|
|
274
|
-
return new import_openai.ChatOpenAI({
|
|
275
|
-
modelName: "deepseek-reasoner",
|
|
276
|
-
temperature: 0.7,
|
|
277
|
-
streaming: true,
|
|
278
|
-
// Enable streaming
|
|
279
|
-
configuration: { baseURL: "https://api.deepseek.com/v1", apiKey }
|
|
280
|
-
});
|
|
281
|
-
};
|
|
282
|
-
const createProcessingChain = () => {
|
|
283
|
-
return import_runnables.RunnableSequence.from([import_prompts2.PromptTemplate.fromTemplate(`Answer concisely: {question}`), createStreamingModel()]);
|
|
284
|
-
};
|
|
285
|
-
try {
|
|
286
|
-
const chain = createProcessingChain();
|
|
287
|
-
const stream = await chain.stream({ question });
|
|
288
|
-
let fullResponse = "";
|
|
289
|
-
for await (const chunk of stream) {
|
|
290
|
-
const content = chunk.content;
|
|
291
|
-
if (typeof content === "string") {
|
|
292
|
-
fullResponse += content;
|
|
293
|
-
callback(content);
|
|
294
|
-
}
|
|
295
|
-
}
|
|
296
|
-
return { content: fullResponse };
|
|
297
|
-
} catch (error) {
|
|
298
|
-
throw new Error("Failed to stream response");
|
|
299
|
-
}
|
|
300
|
-
};
|
|
301
291
|
|
|
302
292
|
// pkgs/@akanjs/common/isDayjs.ts
|
|
303
293
|
var import_dayjs = require("dayjs");
|
|
@@ -483,7 +473,7 @@ var sleep = async (ms) => {
|
|
|
483
473
|
};
|
|
484
474
|
|
|
485
475
|
// pkgs/@akanjs/config/src/akanConfig.ts
|
|
486
|
-
var
|
|
476
|
+
var import_fs5 = __toESM(require("fs"));
|
|
487
477
|
var import_path2 = __toESM(require("path"));
|
|
488
478
|
|
|
489
479
|
// pkgs/@akanjs/config/src/nextConfig.ts
|
|
@@ -698,7 +688,7 @@ CMD ["npm", "start"]`,
|
|
|
698
688
|
};
|
|
699
689
|
var getAppConfig = async (appRoot, props) => {
|
|
700
690
|
const akanConfigPath = import_path2.default.join(appRoot, "akan.config.ts");
|
|
701
|
-
if (!
|
|
691
|
+
if (!import_fs5.default.existsSync(akanConfigPath))
|
|
702
692
|
throw new Error(`application akan.config.ts is not found ${appRoot}`);
|
|
703
693
|
const configImp = (await import(`${appRoot}/akan.config.ts`)).default;
|
|
704
694
|
const config = typeof configImp === "function" ? configImp(props) : configImp;
|
|
@@ -718,7 +708,7 @@ var makeLibConfig = (config, props) => {
|
|
|
718
708
|
};
|
|
719
709
|
var getLibConfig = async (libRoot, props) => {
|
|
720
710
|
const akanConfigPath = import_path2.default.join(libRoot, "akan.config.ts");
|
|
721
|
-
if (!
|
|
711
|
+
if (!import_fs5.default.existsSync(akanConfigPath))
|
|
722
712
|
throw new Error(`library akan.config.ts is not found ${libRoot}`);
|
|
723
713
|
const configImp = (await import(`${libRoot}/akan.config.ts`)).default;
|
|
724
714
|
const config = typeof configImp === "function" ? configImp(props) : configImp;
|
|
@@ -764,15 +754,15 @@ var getDefaultFileScan = () => ({
|
|
|
764
754
|
|
|
765
755
|
// pkgs/@akanjs/devkit/src/executors.ts
|
|
766
756
|
var import_child_process = require("child_process");
|
|
767
|
-
var import_dotenv = __toESM(require("dotenv")
|
|
768
|
-
var
|
|
769
|
-
var import_promises = __toESM(require("fs/promises")
|
|
770
|
-
var import_path3 = __toESM(require("path")
|
|
757
|
+
var import_dotenv = __toESM(require("dotenv"));
|
|
758
|
+
var import_fs6 = __toESM(require("fs"));
|
|
759
|
+
var import_promises = __toESM(require("fs/promises"));
|
|
760
|
+
var import_path3 = __toESM(require("path"));
|
|
771
761
|
|
|
772
762
|
// pkgs/@akanjs/devkit/src/dependencyScanner.ts
|
|
773
|
-
var fs7 = __toESM(require("fs")
|
|
774
|
-
var path3 = __toESM(require("path")
|
|
775
|
-
var ts2 = __toESM(require("typescript")
|
|
763
|
+
var fs7 = __toESM(require("fs"));
|
|
764
|
+
var path3 = __toESM(require("path"));
|
|
765
|
+
var ts2 = __toESM(require("typescript"));
|
|
776
766
|
var TypeScriptDependencyScanner = class {
|
|
777
767
|
constructor(directory) {
|
|
778
768
|
this.directory = directory;
|
|
@@ -923,8 +913,8 @@ var Executor = class {
|
|
|
923
913
|
constructor(name, cwdPath) {
|
|
924
914
|
this.logger = new Logger(name);
|
|
925
915
|
this.cwdPath = cwdPath;
|
|
926
|
-
if (!
|
|
927
|
-
|
|
916
|
+
if (!import_fs6.default.existsSync(cwdPath))
|
|
917
|
+
import_fs6.default.mkdirSync(cwdPath, { recursive: true });
|
|
928
918
|
}
|
|
929
919
|
exec(command, options = {}) {
|
|
930
920
|
const proc = (0, import_child_process.exec)(command, { cwd: this.cwdPath, ...options });
|
|
@@ -983,31 +973,31 @@ var Executor = class {
|
|
|
983
973
|
}
|
|
984
974
|
mkdir(dirPath) {
|
|
985
975
|
const writePath = this.#getPath(dirPath);
|
|
986
|
-
if (!
|
|
987
|
-
|
|
976
|
+
if (!import_fs6.default.existsSync(writePath))
|
|
977
|
+
import_fs6.default.mkdirSync(writePath, { recursive: true });
|
|
988
978
|
this.logger.verbose(`Make directory ${writePath}`);
|
|
989
979
|
return this;
|
|
990
980
|
}
|
|
991
981
|
exists(filePath) {
|
|
992
982
|
const readPath = this.#getPath(filePath);
|
|
993
|
-
return
|
|
983
|
+
return import_fs6.default.existsSync(readPath);
|
|
994
984
|
}
|
|
995
985
|
writeFile(filePath, content, { overwrite = true } = {}) {
|
|
996
986
|
const writePath = this.#getPath(filePath);
|
|
997
987
|
const dir = import_path3.default.dirname(writePath);
|
|
998
|
-
if (!
|
|
999
|
-
|
|
988
|
+
if (!import_fs6.default.existsSync(dir))
|
|
989
|
+
import_fs6.default.mkdirSync(dir, { recursive: true });
|
|
1000
990
|
const contentStr = typeof content === "string" ? content : JSON.stringify(content, null, 2);
|
|
1001
|
-
if (
|
|
1002
|
-
const currentContent =
|
|
991
|
+
if (import_fs6.default.existsSync(writePath)) {
|
|
992
|
+
const currentContent = import_fs6.default.readFileSync(writePath, "utf8");
|
|
1003
993
|
if (currentContent === contentStr || !overwrite)
|
|
1004
994
|
this.logger.verbose(`File ${writePath} is unchanged`);
|
|
1005
995
|
else {
|
|
1006
|
-
|
|
996
|
+
import_fs6.default.writeFileSync(writePath, contentStr, "utf8");
|
|
1007
997
|
this.logger.verbose(`File ${writePath} is changed`);
|
|
1008
998
|
}
|
|
1009
999
|
} else {
|
|
1010
|
-
|
|
1000
|
+
import_fs6.default.writeFileSync(writePath, contentStr, "utf8");
|
|
1011
1001
|
this.logger.verbose(`File ${writePath} is created`);
|
|
1012
1002
|
}
|
|
1013
1003
|
return this;
|
|
@@ -1023,11 +1013,11 @@ var Executor = class {
|
|
|
1023
1013
|
}
|
|
1024
1014
|
readFile(filePath) {
|
|
1025
1015
|
const readPath = this.#getPath(filePath);
|
|
1026
|
-
return
|
|
1016
|
+
return import_fs6.default.readFileSync(readPath, "utf8");
|
|
1027
1017
|
}
|
|
1028
1018
|
readJson(filePath) {
|
|
1029
1019
|
const readPath = this.#getPath(filePath);
|
|
1030
|
-
return JSON.parse(
|
|
1020
|
+
return JSON.parse(import_fs6.default.readFileSync(readPath, "utf8"));
|
|
1031
1021
|
}
|
|
1032
1022
|
async cp(srcPath, destPath) {
|
|
1033
1023
|
const src = this.#getPath(srcPath);
|
|
@@ -1096,7 +1086,7 @@ var Executor = class {
|
|
|
1096
1086
|
overwrite = true
|
|
1097
1087
|
}) {
|
|
1098
1088
|
const templatePath = `${__dirname}/src/templates${template ? `/${template}` : ""}`.replace(".ts", ".js");
|
|
1099
|
-
if (
|
|
1089
|
+
if (import_fs6.default.statSync(templatePath).isFile()) {
|
|
1100
1090
|
const filename = import_path3.default.basename(templatePath);
|
|
1101
1091
|
await this.#applyTemplateFile(
|
|
1102
1092
|
{ templatePath, targetPath: import_path3.default.join(basePath2, filename), scanResult, overwrite },
|
|
@@ -1107,7 +1097,7 @@ var Executor = class {
|
|
|
1107
1097
|
await Promise.all(
|
|
1108
1098
|
subdirs.map(async (subdir) => {
|
|
1109
1099
|
const subpath = import_path3.default.join(templatePath, subdir);
|
|
1110
|
-
if (
|
|
1100
|
+
if (import_fs6.default.statSync(subpath).isFile())
|
|
1111
1101
|
await this.#applyTemplateFile(
|
|
1112
1102
|
{ templatePath: subpath, targetPath: import_path3.default.join(basePath2, subdir), scanResult, overwrite },
|
|
1113
1103
|
dict
|
|
@@ -1204,6 +1194,26 @@ var WorkspaceExecutor = class _WorkspaceExecutor extends Executor {
|
|
|
1204
1194
|
this.writeJson("tsconfig.json", rootTsConfig);
|
|
1205
1195
|
return this;
|
|
1206
1196
|
}
|
|
1197
|
+
async getDirInModule(basePath2, name) {
|
|
1198
|
+
const AVOID_DIRS = ["__lib", "__scalar", `_${name}`];
|
|
1199
|
+
const getDirs = async (dirname, maxDepth = 3, results = [], prefix = "") => {
|
|
1200
|
+
const dirs = await import_promises.default.readdir(dirname);
|
|
1201
|
+
await Promise.all(
|
|
1202
|
+
dirs.map(async (dir) => {
|
|
1203
|
+
if (AVOID_DIRS.includes(dir))
|
|
1204
|
+
return;
|
|
1205
|
+
const dirPath = import_path3.default.join(dirname, dir);
|
|
1206
|
+
if (import_fs6.default.lstatSync(dirPath).isDirectory()) {
|
|
1207
|
+
results.push(`${name}/${prefix}${dir}`);
|
|
1208
|
+
if (maxDepth > 0)
|
|
1209
|
+
await getDirs(dirPath, maxDepth - 1, results, `${prefix}${dir}/`);
|
|
1210
|
+
}
|
|
1211
|
+
})
|
|
1212
|
+
);
|
|
1213
|
+
return results;
|
|
1214
|
+
};
|
|
1215
|
+
return await getDirs(basePath2);
|
|
1216
|
+
}
|
|
1207
1217
|
async commit(message, { init = false, add = true } = {}) {
|
|
1208
1218
|
if (init)
|
|
1209
1219
|
await this.exec(`git init --quiet`);
|
|
@@ -1220,8 +1230,8 @@ var WorkspaceExecutor = class _WorkspaceExecutor extends Executor {
|
|
|
1220
1230
|
if (AVOID_DIRS.includes(dir))
|
|
1221
1231
|
return;
|
|
1222
1232
|
const dirPath = import_path3.default.join(dirname, dir);
|
|
1223
|
-
if (
|
|
1224
|
-
const hasTargetFile =
|
|
1233
|
+
if (import_fs6.default.lstatSync(dirPath).isDirectory()) {
|
|
1234
|
+
const hasTargetFile = import_fs6.default.existsSync(import_path3.default.join(dirPath, targetFilename));
|
|
1225
1235
|
if (hasTargetFile)
|
|
1226
1236
|
results.push(`${prefix}${dir}`);
|
|
1227
1237
|
if (maxDepth > 0)
|
|
@@ -1241,6 +1251,14 @@ var WorkspaceExecutor = class _WorkspaceExecutor extends Executor {
|
|
|
1241
1251
|
];
|
|
1242
1252
|
return scalarConstantExampleFiles;
|
|
1243
1253
|
}
|
|
1254
|
+
async getViewFiles() {
|
|
1255
|
+
const [appNames, libNames] = await this.getSyss();
|
|
1256
|
+
const viewExampleFiles = [
|
|
1257
|
+
...(await Promise.all(appNames.map((appName) => AppExecutor.from(this, appName).getViewsSourceCode()))).flat(),
|
|
1258
|
+
...(await Promise.all(libNames.map((libName) => LibExecutor.from(this, libName).getViewsSourceCode()))).flat()
|
|
1259
|
+
];
|
|
1260
|
+
return viewExampleFiles;
|
|
1261
|
+
}
|
|
1244
1262
|
};
|
|
1245
1263
|
var SysExecutor = class extends Executor {
|
|
1246
1264
|
workspace;
|
|
@@ -1255,6 +1273,10 @@ var SysExecutor = class extends Executor {
|
|
|
1255
1273
|
async getConfig(command) {
|
|
1256
1274
|
return this.type === "app" ? await getAppConfig(this.cwdPath, { ...this.workspace.getBaseDevEnv(), type: "app", name: this.name, command }) : await getLibConfig(this.cwdPath, { ...this.workspace.getBaseDevEnv(), type: "lib", name: this.name, command });
|
|
1257
1275
|
}
|
|
1276
|
+
async getModules() {
|
|
1277
|
+
const path7 = this.type === "app" ? `apps/${this.name}/lib` : `libs/${this.name}/lib`;
|
|
1278
|
+
return await this.workspace.getDirInModule(path7, this.name);
|
|
1279
|
+
}
|
|
1258
1280
|
async scan({
|
|
1259
1281
|
tsconfig = this.getTsConfig(`${this.cwdPath}/tsconfig.json`),
|
|
1260
1282
|
akanConfig
|
|
@@ -1279,11 +1301,11 @@ var SysExecutor = class extends Executor {
|
|
|
1279
1301
|
const pathSplitLength = path7.split("/").length;
|
|
1280
1302
|
return tsconfig.compilerOptions.paths[path7][0].split("/").slice(1, 1 + pathSplitLength).join("/");
|
|
1281
1303
|
}).filter((libName) => libName !== this.name);
|
|
1282
|
-
if (!
|
|
1283
|
-
|
|
1304
|
+
if (!import_fs6.default.existsSync(`${this.cwdPath}/lib/__scalar`))
|
|
1305
|
+
import_fs6.default.mkdirSync(`${this.cwdPath}/lib/__scalar`, { recursive: true });
|
|
1284
1306
|
const files = getDefaultFileScan();
|
|
1285
1307
|
const dirnames = (await import_promises.default.readdir(`${this.cwdPath}/lib`)).filter(
|
|
1286
|
-
(name) =>
|
|
1308
|
+
(name) => import_fs6.default.lstatSync(`${this.cwdPath}/lib/${name}`).isDirectory()
|
|
1287
1309
|
);
|
|
1288
1310
|
const databaseDirs = dirnames.filter((name) => !name.startsWith("_"));
|
|
1289
1311
|
const serviceDirs = dirnames.filter((name) => name.startsWith("_") && !name.startsWith("__"));
|
|
@@ -1411,20 +1433,42 @@ var SysExecutor = class extends Executor {
|
|
|
1411
1433
|
return { filepath, content };
|
|
1412
1434
|
}
|
|
1413
1435
|
async getDatabaseModules() {
|
|
1414
|
-
const databaseModules = (await import_promises.default.readdir(`${this.cwdPath}/lib`)).filter((name) => !name.startsWith("_") && !name.startsWith("__") && !name.endsWith(".ts")).filter((name) =>
|
|
1436
|
+
const databaseModules = (await import_promises.default.readdir(`${this.cwdPath}/lib`)).filter((name) => !name.startsWith("_") && !name.startsWith("__") && !name.endsWith(".ts")).filter((name) => import_fs6.default.existsSync(`${this.cwdPath}/lib/${name}/${name}.constant.ts`));
|
|
1415
1437
|
return databaseModules;
|
|
1416
1438
|
}
|
|
1417
1439
|
async getServiceModules() {
|
|
1418
|
-
const serviceModules = (await import_promises.default.readdir(`${this.cwdPath}/lib`)).filter((name) => name.startsWith("_") && !name.startsWith("__")).filter((name) =>
|
|
1440
|
+
const serviceModules = (await import_promises.default.readdir(`${this.cwdPath}/lib`)).filter((name) => name.startsWith("_") && !name.startsWith("__")).filter((name) => import_fs6.default.existsSync(`${this.cwdPath}/lib/${name}/${name}.service.ts`));
|
|
1419
1441
|
return serviceModules;
|
|
1420
1442
|
}
|
|
1421
1443
|
async getScalarModules() {
|
|
1422
|
-
const scalarModules = (await import_promises.default.readdir(`${this.cwdPath}/lib/__scalar`)).filter((name) => !name.startsWith("_")).filter((name) =>
|
|
1444
|
+
const scalarModules = (await import_promises.default.readdir(`${this.cwdPath}/lib/__scalar`)).filter((name) => !name.startsWith("_")).filter((name) => import_fs6.default.existsSync(`${this.cwdPath}/lib/__scalar/${name}/${name}.constant.ts`));
|
|
1423
1445
|
return scalarModules;
|
|
1424
1446
|
}
|
|
1425
|
-
async
|
|
1426
|
-
const
|
|
1427
|
-
return
|
|
1447
|
+
async getViewComponents() {
|
|
1448
|
+
const viewComponents = (await import_promises.default.readdir(`${this.cwdPath}/lib`)).filter((name) => !name.startsWith("_") && !name.startsWith("__") && !name.endsWith(".ts")).filter((name) => import_fs6.default.existsSync(`${this.cwdPath}/lib/${name}/${name}.View.tsx`));
|
|
1449
|
+
return viewComponents;
|
|
1450
|
+
}
|
|
1451
|
+
async getUnitComponents() {
|
|
1452
|
+
const unitComponents = (await import_promises.default.readdir(`${this.cwdPath}/lib`)).filter((name) => name.startsWith("_") && !name.startsWith("__")).filter((name) => import_fs6.default.existsSync(`${this.cwdPath}/lib/${name}/${name}.Unit.tsx`));
|
|
1453
|
+
return unitComponents;
|
|
1454
|
+
}
|
|
1455
|
+
async getTemplateComponents() {
|
|
1456
|
+
const templateComponents = (await import_promises.default.readdir(`${this.cwdPath}/lib`)).filter((name) => name.startsWith("_") && !name.startsWith("__")).filter((name) => import_fs6.default.existsSync(`${this.cwdPath}/lib/${name}/${name}.Template.tsx`));
|
|
1457
|
+
return templateComponents;
|
|
1458
|
+
}
|
|
1459
|
+
async getViewsSourceCode() {
|
|
1460
|
+
const viewComponents = await this.getViewComponents();
|
|
1461
|
+
return viewComponents.map((viewComponent) => this.getLocalFile(`lib/${viewComponent}/${viewComponent}.View.tsx`));
|
|
1462
|
+
}
|
|
1463
|
+
async getUnitsSourceCode() {
|
|
1464
|
+
const unitComponents = await this.getUnitComponents();
|
|
1465
|
+
return unitComponents.map((unitComponent) => this.getLocalFile(`lib/${unitComponent}/${unitComponent}.Unit.tsx`));
|
|
1466
|
+
}
|
|
1467
|
+
async getTemplatesSourceCode() {
|
|
1468
|
+
const templateComponents = await this.getTemplateComponents();
|
|
1469
|
+
return templateComponents.map(
|
|
1470
|
+
(templateComponent) => this.getLocalFile(`lib/${templateComponent}/${templateComponent}.Template.tsx`)
|
|
1471
|
+
);
|
|
1428
1472
|
}
|
|
1429
1473
|
async getScalarConstantFiles() {
|
|
1430
1474
|
const scalarModules = await this.getScalarModules();
|
|
@@ -1464,9 +1508,9 @@ var AppExecutor = class _AppExecutor extends SysExecutor {
|
|
|
1464
1508
|
}
|
|
1465
1509
|
async syncAssets(libDeps) {
|
|
1466
1510
|
const projectPublicLibPath = `${this.cwdPath}/public/libs`;
|
|
1467
|
-
if (
|
|
1511
|
+
if (import_fs6.default.existsSync(projectPublicLibPath))
|
|
1468
1512
|
await import_promises.default.rm(projectPublicLibPath, { recursive: true });
|
|
1469
|
-
const targetDeps = libDeps.filter((dep) =>
|
|
1513
|
+
const targetDeps = libDeps.filter((dep) => import_fs6.default.existsSync(`${this.workspace.workspaceRoot}/libs/${dep}/public`));
|
|
1470
1514
|
await Promise.all(targetDeps.map((dep) => import_promises.default.mkdir(`${projectPublicLibPath}/${dep}`, { recursive: true })));
|
|
1471
1515
|
await Promise.all(
|
|
1472
1516
|
targetDeps.map(
|
|
@@ -1546,21 +1590,21 @@ var akanCloudHost = process.env.NEXT_PUBLIC_OPERATION_MODE === "local" ? "http:/
|
|
|
1546
1590
|
var akanCloudBackendUrl = `${akanCloudHost}${process.env.NEXT_PUBLIC_OPERATION_MODE === "local" ? ":8080" : ""}/backend`;
|
|
1547
1591
|
var akanCloudClientUrl = `${akanCloudHost}${process.env.NEXT_PUBLIC_OPERATION_MODE === "local" ? ":4200" : ""}`;
|
|
1548
1592
|
var defaultHostConfig = {};
|
|
1549
|
-
var defaultAkanGlobalConfig = {};
|
|
1593
|
+
var defaultAkanGlobalConfig = { cloudHost: {}, llm: null };
|
|
1550
1594
|
|
|
1551
1595
|
// pkgs/@akanjs/devkit/src/auth.ts
|
|
1552
|
-
var
|
|
1596
|
+
var import_fs7 = __toESM(require("fs"));
|
|
1553
1597
|
var getAkanGlobalConfig = () => {
|
|
1554
|
-
const akanConfig =
|
|
1598
|
+
const akanConfig = import_fs7.default.existsSync(configPath) ? JSON.parse(import_fs7.default.readFileSync(configPath, "utf8")) : defaultAkanGlobalConfig;
|
|
1555
1599
|
return akanConfig;
|
|
1556
1600
|
};
|
|
1557
1601
|
var setAkanGlobalConfig = (akanConfig) => {
|
|
1558
|
-
|
|
1559
|
-
|
|
1602
|
+
import_fs7.default.mkdirSync(basePath, { recursive: true });
|
|
1603
|
+
import_fs7.default.writeFileSync(configPath, JSON.stringify(akanConfig, null, 2));
|
|
1560
1604
|
};
|
|
1561
1605
|
var getHostConfig = (host = akanCloudHost) => {
|
|
1562
1606
|
const akanConfig = getAkanGlobalConfig();
|
|
1563
|
-
return akanConfig[host] ?? defaultHostConfig;
|
|
1607
|
+
return akanConfig.cloudHost[host] ?? defaultHostConfig;
|
|
1564
1608
|
};
|
|
1565
1609
|
var setHostConfig = (host = akanCloudHost, config = {}) => {
|
|
1566
1610
|
const akanConfig = getAkanGlobalConfig();
|
|
@@ -1579,7 +1623,7 @@ var getSelf = async (token) => {
|
|
|
1579
1623
|
|
|
1580
1624
|
// pkgs/@akanjs/devkit/src/capacitorApp.ts
|
|
1581
1625
|
var import_project = require("@trapezedev/project");
|
|
1582
|
-
var
|
|
1626
|
+
var import_fs8 = __toESM(require("fs"));
|
|
1583
1627
|
var CapacitorApp = class {
|
|
1584
1628
|
constructor(app) {
|
|
1585
1629
|
this.app = app;
|
|
@@ -1605,7 +1649,7 @@ var CapacitorApp = class {
|
|
|
1605
1649
|
await this.project.commit();
|
|
1606
1650
|
}
|
|
1607
1651
|
async releaseIos() {
|
|
1608
|
-
const isAdded =
|
|
1652
|
+
const isAdded = import_fs8.default.existsSync(`${this.app.cwdPath}/ios/App/Podfile`);
|
|
1609
1653
|
if (!isAdded) {
|
|
1610
1654
|
await this.app.spawn("npx cap add ios");
|
|
1611
1655
|
await this.app.spawn("npx @capacitor/assets generate");
|
|
@@ -1614,7 +1658,7 @@ var CapacitorApp = class {
|
|
|
1614
1658
|
await this.app.spawn("cross-env", ["APP_OPERATION_MODE=release", "npx", "cap", "sync", "ios"]);
|
|
1615
1659
|
}
|
|
1616
1660
|
async releaseAndroid() {
|
|
1617
|
-
const isAdded =
|
|
1661
|
+
const isAdded = import_fs8.default.existsSync(`${this.app.cwdPath}/android/app/build.gradle`);
|
|
1618
1662
|
if (!isAdded) {
|
|
1619
1663
|
await this.app.spawn("npx cap add android");
|
|
1620
1664
|
await this.app.spawn("npx @capacitor/assets generate");
|
|
@@ -1855,7 +1899,7 @@ var Target = {
|
|
|
1855
1899
|
// pkgs/@akanjs/devkit/src/commandDecorators/command.ts
|
|
1856
1900
|
var import_prompts3 = require("@inquirer/prompts");
|
|
1857
1901
|
var import_commander = require("commander");
|
|
1858
|
-
var
|
|
1902
|
+
var import_fs9 = __toESM(require("fs"));
|
|
1859
1903
|
var camelToKebabCase = (str) => str.replace(/([A-Z])/g, "-$1").toLowerCase();
|
|
1860
1904
|
var handleOption = (programCommand, argMeta) => {
|
|
1861
1905
|
const {
|
|
@@ -1902,7 +1946,7 @@ var getOptionValue = async (argMeta, opt) => {
|
|
|
1902
1946
|
const message = ask ?? `Do you want to set ${name}? ${desc ? ` (${desc})` : ""}: `;
|
|
1903
1947
|
return await (0, import_prompts3.confirm)({ message });
|
|
1904
1948
|
} else {
|
|
1905
|
-
const message = ask
|
|
1949
|
+
const message = ask ? `${ask}: ` : `Enter the ${name} value${example ? ` (example: ${example})` : ""}: `;
|
|
1906
1950
|
if (argMeta.argsOption.nullable)
|
|
1907
1951
|
return await (0, import_prompts3.input)({ message });
|
|
1908
1952
|
else
|
|
@@ -1951,8 +1995,8 @@ var getArgumentValue = async (argMeta, value, workspace) => {
|
|
|
1951
1995
|
throw new Error(`Invalid system type: ${argMeta.type}`);
|
|
1952
1996
|
};
|
|
1953
1997
|
var runCommands = async (...commands) => {
|
|
1954
|
-
const hasPackageJson =
|
|
1955
|
-
const version = hasPackageJson ? JSON.parse(
|
|
1998
|
+
const hasPackageJson = import_fs9.default.existsSync(`${__dirname}/package.json`);
|
|
1999
|
+
const version = hasPackageJson ? JSON.parse(import_fs9.default.readFileSync(`${__dirname}/package.json`, "utf8")).version : "0.0.1";
|
|
1956
2000
|
import_commander.program.version(version).description("Akan CLI");
|
|
1957
2001
|
for (const command of commands) {
|
|
1958
2002
|
const targetMetas = getTargetMetas(command);
|
|
@@ -2002,15 +2046,64 @@ var runCommands = async (...commands) => {
|
|
|
2002
2046
|
var import_prompts4 = require("@inquirer/prompts");
|
|
2003
2047
|
var import_messages = require("@langchain/core/messages");
|
|
2004
2048
|
var import_openai2 = require("@langchain/openai");
|
|
2049
|
+
var import_chalk = __toESM(require("chalk"));
|
|
2005
2050
|
var MAX_ASK_TRY = 300;
|
|
2051
|
+
var supportedLlmModels = ["deepseek-chat", "deepseek-reasoner"];
|
|
2006
2052
|
var AiSession = class _AiSession {
|
|
2007
|
-
static #chat =
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
|
|
2053
|
+
static #chat = null;
|
|
2054
|
+
static async init({ temperature = 0.7, useExisting = true } = {}) {
|
|
2055
|
+
if (useExisting) {
|
|
2056
|
+
const llmConfig2 = this.getLlmConfig();
|
|
2057
|
+
if (llmConfig2)
|
|
2058
|
+
return this.#setChatModel(llmConfig2.model, llmConfig2.apiKey);
|
|
2059
|
+
}
|
|
2060
|
+
const llmConfig = await this.#requestLlmConfig();
|
|
2061
|
+
const { model, apiKey } = llmConfig;
|
|
2062
|
+
await this.#validateApiKey(model, apiKey);
|
|
2063
|
+
return this.#setChatModel(model, apiKey, { temperature }).setLlmConfig({ model, apiKey });
|
|
2064
|
+
}
|
|
2065
|
+
static #setChatModel(model, apiKey, { temperature = 0.7 } = {}) {
|
|
2066
|
+
this.#chat = new import_openai2.ChatOpenAI({
|
|
2067
|
+
modelName: model,
|
|
2068
|
+
temperature,
|
|
2069
|
+
streaming: true,
|
|
2070
|
+
configuration: { baseURL: "https://api.deepseek.com/v1", apiKey }
|
|
2071
|
+
});
|
|
2072
|
+
return this;
|
|
2073
|
+
}
|
|
2074
|
+
static getLlmConfig() {
|
|
2075
|
+
const akanConfig = getAkanGlobalConfig();
|
|
2076
|
+
return akanConfig.llm ?? null;
|
|
2077
|
+
}
|
|
2078
|
+
static setLlmConfig(llmConfig) {
|
|
2079
|
+
const akanConfig = getAkanGlobalConfig();
|
|
2080
|
+
akanConfig.llm = llmConfig;
|
|
2081
|
+
setAkanGlobalConfig(akanConfig);
|
|
2082
|
+
return this;
|
|
2083
|
+
}
|
|
2084
|
+
static async #requestLlmConfig() {
|
|
2085
|
+
const model = await (0, import_prompts4.select)({ message: "Select a LLM model", choices: supportedLlmModels });
|
|
2086
|
+
const apiKey = await (0, import_prompts4.input)({ message: "Enter your API key" });
|
|
2087
|
+
return { model, apiKey };
|
|
2088
|
+
}
|
|
2089
|
+
static async #validateApiKey(modelName, apiKey) {
|
|
2090
|
+
const chat = new import_openai2.ChatOpenAI({
|
|
2091
|
+
modelName,
|
|
2092
|
+
temperature: 0,
|
|
2093
|
+
configuration: { baseURL: "https://api.deepseek.com/v1", apiKey }
|
|
2094
|
+
});
|
|
2095
|
+
try {
|
|
2096
|
+
await chat.invoke("Hi, and just say 'ok'");
|
|
2097
|
+
return true;
|
|
2098
|
+
} catch (error) {
|
|
2099
|
+
Logger.rawLog(
|
|
2100
|
+
import_chalk.default.red(
|
|
2101
|
+
`LLM API key is invalid. Please check your API key and try again. You can set it again by running "akan set-llm" or reset by running "akan reset-llm"`
|
|
2102
|
+
)
|
|
2103
|
+
);
|
|
2104
|
+
throw error;
|
|
2105
|
+
}
|
|
2106
|
+
}
|
|
2014
2107
|
messageHistory = [];
|
|
2015
2108
|
constructor(messageHistory = []) {
|
|
2016
2109
|
this.messageHistory = messageHistory;
|
|
@@ -2020,6 +2113,8 @@ var AiSession = class _AiSession {
|
|
|
2020
2113
|
Logger.raw(chunk);
|
|
2021
2114
|
}
|
|
2022
2115
|
} = {}) {
|
|
2116
|
+
if (!_AiSession.#chat)
|
|
2117
|
+
throw new Error("Please initialize the AI session first");
|
|
2023
2118
|
try {
|
|
2024
2119
|
const humanMessage = new import_messages.HumanMessage(question);
|
|
2025
2120
|
this.messageHistory.push(humanMessage);
|
|
@@ -2032,6 +2127,8 @@ var AiSession = class _AiSession {
|
|
|
2032
2127
|
onChunk(content);
|
|
2033
2128
|
}
|
|
2034
2129
|
}
|
|
2130
|
+
fullResponse += "\n";
|
|
2131
|
+
onChunk("\n");
|
|
2035
2132
|
this.messageHistory.push(new import_messages.AIMessage(fullResponse));
|
|
2036
2133
|
return { content: fullResponse, messageHistory: this.messageHistory };
|
|
2037
2134
|
} catch (error) {
|
|
@@ -2060,8 +2157,8 @@ var AiSession = class _AiSession {
|
|
|
2060
2157
|
return this.#getTypescriptCode(content);
|
|
2061
2158
|
}
|
|
2062
2159
|
#getTypescriptCode(content) {
|
|
2063
|
-
const code = /```typescript([\s\S]*?)```/.exec(content);
|
|
2064
|
-
return code ? code[
|
|
2160
|
+
const code = /```(typescript|tsx)([\s\S]*?)```/.exec(content);
|
|
2161
|
+
return code ? code[2] : content;
|
|
2065
2162
|
}
|
|
2066
2163
|
};
|
|
2067
2164
|
|
|
@@ -2074,6 +2171,12 @@ var LibraryRunner = class {
|
|
|
2074
2171
|
const scanResult = await lib.scan({ akanConfig });
|
|
2075
2172
|
return scanResult;
|
|
2076
2173
|
}
|
|
2174
|
+
async createLibrary(libName, workspace) {
|
|
2175
|
+
}
|
|
2176
|
+
async removeLibrary(lib) {
|
|
2177
|
+
await lib.workspace.exec(`rm -rf libs/${lib.name}`);
|
|
2178
|
+
lib.log(`Library ${lib.name} removed`);
|
|
2179
|
+
}
|
|
2077
2180
|
async installLibrary(workspace, libName) {
|
|
2078
2181
|
workspace.log(`Installing ${libName} library as git subtree...`);
|
|
2079
2182
|
await workspace.exec(
|
|
@@ -2165,6 +2268,12 @@ var LibraryScript = class {
|
|
|
2165
2268
|
for (const libName of scanResult.akanConfig.libs)
|
|
2166
2269
|
await this.syncLibrary(LibExecutor.from(lib.workspace, libName), { recursive: false });
|
|
2167
2270
|
}
|
|
2271
|
+
async createLibrary(libName, workspace) {
|
|
2272
|
+
await this.#runner.createLibrary(libName, workspace);
|
|
2273
|
+
}
|
|
2274
|
+
async removeLibrary(lib) {
|
|
2275
|
+
await this.#runner.removeLibrary(lib);
|
|
2276
|
+
}
|
|
2168
2277
|
async installLibrary(workspace, libName) {
|
|
2169
2278
|
const lib = await this.#runner.installLibrary(workspace, libName);
|
|
2170
2279
|
workspace.log(`${libName} library installed`);
|
|
@@ -2191,7 +2300,7 @@ var import_openai3 = require("@langchain/openai");
|
|
|
2191
2300
|
var import_plugin_react = __toESM(require("@vitejs/plugin-react"));
|
|
2192
2301
|
var import_dotenv3 = __toESM(require("dotenv"));
|
|
2193
2302
|
var esbuild = __toESM(require("esbuild"));
|
|
2194
|
-
var
|
|
2303
|
+
var import_fs10 = __toESM(require("fs"));
|
|
2195
2304
|
var import_promises2 = __toESM(require("fs/promises"));
|
|
2196
2305
|
var import_js_yaml2 = __toESM(require("js-yaml"));
|
|
2197
2306
|
var import_open = __toESM(require("open"));
|
|
@@ -2202,8 +2311,9 @@ var import_vite_plugin_node_polyfills = require("vite-plugin-node-polyfills");
|
|
|
2202
2311
|
var import_vite_tsconfig_paths = __toESM(require("vite-tsconfig-paths"));
|
|
2203
2312
|
|
|
2204
2313
|
// pkgs/@akanjs/cli/src/module/module.prompt.ts
|
|
2205
|
-
var
|
|
2206
|
-
|
|
2314
|
+
var frameworkDescription = `
|
|
2315
|
+
\uB098\uB294 \uC880 \uB354 \uD6A8\uC728\uC801\uC73C\uB85C \uCF54\uB529\uC744 \uD558\uAE30 \uC704\uD574\uC11C \uC790\uCCB4 \uD504\uB808\uC784\uC6CC\uD06C\uB97C \uC81C\uC791\uD588\uC5B4.
|
|
2316
|
+
\uADF8\uB798\uC11C \uC6B0\uB9AC \uD504\uB808\uC784\uC6CC\uD06C\uC5D0 \uB300\uD55C \uC124\uBA85\uC744 \uD574\uC904\uD14C\uB2C8\uAE4C \uC798 \uC774\uD574\uD558\uB3C4\uB85D \uD574. \uC6B0\uB9AC \uD504\uB808\uC784\uC6CC\uD06C\uB294 next.js 13\uACFC nest.js, capacitor.js, nx, mongoDB \uAE30\uBC18\uC758 \uD504\uB860\uD2B8\uC5D4\uB4DC, \uC571, \uBC31\uC5D4\uB4DC \uD1B5\uD569 \uD504\uB808\uC784\uC6CC\uD06C\uC57C. \uADF8\uB798\uC11C \uBC31\uC5D4\uB4DC, \uD504\uB860\uD2B8\uC5D4\uB4DC, DB Schema\uC5D0 \uB300\uD55C \uCF54\uB4DC\uAC00 \uBAA8\uB450 \uD55C \uD3F4\uB354 \uC548\uC5D0 \uC788\uC5B4. \uADF8\uB798\uC11C \uC790\uBC14\uC2A4\uD06C\uB9BD\uD2B8, \uD0C0\uC785\uC2A4\uD06C\uB9BD\uD2B8, \uADF8\uB9AC\uACE0 \uD504\uB808\uC784\uC6CC\uD06C\uC5D0 \uB300\uD55C \uC774\uD574\uB9CC \uC788\uB2E4\uBA74 \uAD6C\uBD84\uC9D3\uC9C0 \uC54A\uACE0 \uC0AC\uC6A9\uD560 \uC218 \uC788\uB2E4\uB294 \uC7A5\uC810\uC774 \uC788\uC5B4.
|
|
2207
2317
|
|
|
2208
2318
|
\uAC00\uC7A5 \uC678\uBD80\uC758 \uAD6C\uC870\uB294
|
|
2209
2319
|
- app
|
|
@@ -2721,6 +2831,433 @@ export const General = ({ className, \${dict.model}, self }: \${dict.Model}ViewP
|
|
|
2721
2831
|
|
|
2722
2832
|
\uC77C\uB2E8 \uD504\uB808\uC784\uC6CC\uD06C\uC5D0 \uB300\uD55C \uC124\uBA85\uC740 \uC774 \uC815\uB3C4\uB85C \uD558\uACE0 \uC774 \uC815\uBCF4\uB4E4\uC744 \uAE30\uBC18\uC73C\uB85C \uB0B4\uAC00 \uC6D0\uD558\uB294 \uC694\uAD6C\uB97C \uB4E4\uC5B4\uC918.
|
|
2723
2833
|
`;
|
|
2834
|
+
var moduleDesription = `
|
|
2835
|
+
|
|
2836
|
+
The project follows a modular architecture with clear separation of concerns. Each module in lib/<model>/ represents a domain
|
|
2837
|
+
entity with a standardized file structure that promotes consistency and maintainability.
|
|
2838
|
+
|
|
2839
|
+
## Core Components
|
|
2840
|
+
|
|
2841
|
+
### <Model>.View.tsx
|
|
2842
|
+
Presentation-only components that render data without managing state.
|
|
2843
|
+
It works as a server component, They accept model data as props and display it according to specific layouts.
|
|
2844
|
+
These components focus purely on how data looks to the user.
|
|
2845
|
+
only use the full model.
|
|
2846
|
+
This component is only viewing the component. So don't use click event or other interaction events.
|
|
2847
|
+
If you need interaction, possible to wrapping the component with the <Model>.Zone.tsx component.
|
|
2848
|
+
But useable the Link component for navigation.
|
|
2849
|
+
Components created in Model.View.tsx should primarily be made to show the entire detailed data of the model rather than showing only partial data of the model.
|
|
2850
|
+
|
|
2851
|
+
|
|
2852
|
+
### <Model>.Template.tsx
|
|
2853
|
+
Reusable layout patterns with integrated state management. It works as a client component, These components provide consistent UI patterns and handle data
|
|
2854
|
+
binding, often using store hooks to access application state.
|
|
2855
|
+
|
|
2856
|
+
### <Model>.Unit.tsx
|
|
2857
|
+
Small, self-contained UI components representing individual model instances. It works as a server component, They're designed for rendering single items in
|
|
2858
|
+
lists or grids, displaying model data in compact formats. only use the light model.
|
|
2859
|
+
|
|
2860
|
+
### <Model>.Zone.tsx
|
|
2861
|
+
Top-level container components that orchestrate other components. It works as a client component, They compose views, templates, and units into complete UI
|
|
2862
|
+
sections while managing data flow to child components.
|
|
2863
|
+
|
|
2864
|
+
### <Model>.Util.tsx
|
|
2865
|
+
Specialized components and utility functions specific to a model, It works as a client component, providing both UI components and helper functions for
|
|
2866
|
+
model-specific functionality.
|
|
2867
|
+
|
|
2868
|
+
## Data Management
|
|
2869
|
+
|
|
2870
|
+
### <model>.signal.ts
|
|
2871
|
+
Defines API endpoints with type safety using decorators for GraphQL queries and mutations, creating a type-safe bridge between
|
|
2872
|
+
frontend and backend.
|
|
2873
|
+
|
|
2874
|
+
### <model>.store.ts
|
|
2875
|
+
Manages client-side state with typed actions and state, handling UI state, form state, and cached data.
|
|
2876
|
+
|
|
2877
|
+
### <model>.service.ts
|
|
2878
|
+
Implements server-side business logic with dependency injection, handling data processing and complex operations.
|
|
2879
|
+
|
|
2880
|
+
### <model>.constant.ts
|
|
2881
|
+
Defines type definitions and model schemas using decorators to structure model fields, validation, and relationships.
|
|
2882
|
+
|
|
2883
|
+
### <model>.dictionary.ts
|
|
2884
|
+
Provides internationalization and label definitions for model properties and operations.
|
|
2885
|
+
|
|
2886
|
+
### <model>.document.ts
|
|
2887
|
+
Defines database schema and model operations with decorators for database interaction.
|
|
2888
|
+
|
|
2889
|
+
## Data Flow
|
|
2890
|
+
The architecture follows a clear data flow pattern:
|
|
2891
|
+
- Server-side: Document \u2192 Service \u2192 Signal \u2192 API
|
|
2892
|
+
- Client-side: API \u2192 Store \u2192 Components (Zone \u2192 Template/View/Unit)
|
|
2893
|
+
|
|
2894
|
+
This modular structure enables rapid development while maintaining consistency, type safety, and testability throughout the
|
|
2895
|
+
application.
|
|
2896
|
+
`;
|
|
2897
|
+
var utilUiDescription = `
|
|
2898
|
+
This UI kit is an internally developed UI kit within the Akan.js framework.
|
|
2899
|
+
The libs/util/ui directory contains a comprehensive React component library designed for modern web applications.
|
|
2900
|
+
This framework provides a complete set of production-ready, reusable UI components with consistent styling, type safety, and advanced functionality.
|
|
2901
|
+
|
|
2902
|
+
- Every component must be used exactly as described in the documentation.
|
|
2903
|
+
- Do not add any additional props to the components.
|
|
2904
|
+
- Must use the written props exactly.
|
|
2905
|
+
- Only the components explicitly listed in the documentation are available\u2014no additional components exist beyond those specified.
|
|
2906
|
+
|
|
2907
|
+
|
|
2908
|
+
|
|
2909
|
+
Architecture & Foundation
|
|
2910
|
+
|
|
2911
|
+
Core Technologies:
|
|
2912
|
+
- Built on React 18+ with TypeScript for strict type safety
|
|
2913
|
+
- Styled with Tailwind CSS and DaisyUI for consistent design system
|
|
2914
|
+
- Implements modern React patterns including hooks, context providers, and portals
|
|
2915
|
+
- Full internationalization (i18n) support for multilingual applications
|
|
2916
|
+
- Responsive-first design with mobile optimization
|
|
2917
|
+
|
|
2918
|
+
Design Principles:
|
|
2919
|
+
- Composable component architecture with predictable APIs
|
|
2920
|
+
- Accessibility (a11y) compliance throughout
|
|
2921
|
+
- Performance optimization with lazy loading and code splitting
|
|
2922
|
+
- Consistent error handling and validation patterns
|
|
2923
|
+
- Session storage integration for form state persistence
|
|
2924
|
+
|
|
2925
|
+
Component Categories
|
|
2926
|
+
|
|
2927
|
+
Core Input Components
|
|
2928
|
+
|
|
2929
|
+
Essential form controls with advanced validation and user experience features:
|
|
2930
|
+
- Button - Async-aware button with automatic loading/success/error states
|
|
2931
|
+
- Input - Comprehensive input system with real-time validation, multiple variants (Text, Password, Email, Number, Checkbox), and
|
|
2932
|
+
session caching
|
|
2933
|
+
- Select - Advanced dropdown with search, multi-select, and custom rendering
|
|
2934
|
+
- DatePicker - Date/time selection with range support and custom formatting
|
|
2935
|
+
- CodeInput - PIN/verification code input with auto-focus management
|
|
2936
|
+
- Upload - File upload system with drag-drop, progress tracking, image cropping, and multiple file support
|
|
2937
|
+
|
|
2938
|
+
Data Display Components
|
|
2939
|
+
|
|
2940
|
+
Components for presenting and organizing information:
|
|
2941
|
+
- Chart - Visualization suite (Bar, Line, Pie, Doughnut) built on Chart.js
|
|
2942
|
+
- Avatar - User profile images with intelligent fallbacks
|
|
2943
|
+
- ChatBubble - Chat interface with message grouping and timestamps
|
|
2944
|
+
- Empty - Customizable empty state displays
|
|
2945
|
+
- QRCode - QR code generation with click-to-open functionality
|
|
2946
|
+
|
|
2947
|
+
Layout & Navigation System
|
|
2948
|
+
|
|
2949
|
+
Comprehensive layout framework for application structure:
|
|
2950
|
+
- Layout - Complete layout system with Header (auto-hide), Sider (collapsible), Navbar (portal-based), BottomTab (with badges),
|
|
2951
|
+
and container components
|
|
2952
|
+
- Modal/Dialog - Composable dialog system with backdrop, animations, and gesture support
|
|
2953
|
+
- BottomSheet - Mobile-optimized bottom sheet with drag gestures
|
|
2954
|
+
- Menu - Navigation menus with horizontal/vertical modes and submenu support
|
|
2955
|
+
- Tab - Tabbed interfaces with lazy loading and scroll management
|
|
2956
|
+
- ScreenNavigator - Gesture-based screen navigation with spring animations
|
|
2957
|
+
|
|
2958
|
+
Interactive Components
|
|
2959
|
+
|
|
2960
|
+
Advanced user interaction components:
|
|
2961
|
+
- Pagination - Smart page navigation with ellipsis and responsive design
|
|
2962
|
+
- InfiniteScroll - Automatic content loading with intersection observer
|
|
2963
|
+
- DndKit - Drag and drop functionality with provider pattern
|
|
2964
|
+
- Radio - Radio button groups with custom styling
|
|
2965
|
+
- ToggleSelect - Button-based selection with single/multi-select modes
|
|
2966
|
+
- Share - Native share API with copy fallback
|
|
2967
|
+
|
|
2968
|
+
Utility & Feedback Components
|
|
2969
|
+
|
|
2970
|
+
Supporting components for enhanced user experience:
|
|
2971
|
+
- Loading - Comprehensive loading states (Area, Button, Input, Skeleton, Spin, ProgressBar) with animations
|
|
2972
|
+
- Link - Adaptive navigation links with SSR/CSR compatibility
|
|
2973
|
+
- MapView - Map integration supporting both Google Maps and Pigeon Maps with markers and overlays
|
|
2974
|
+
- Image - Optimized image component with blur placeholders and SSR support
|
|
2975
|
+
- Portal - Teleportation component for rendering outside component tree
|
|
2976
|
+
|
|
2977
|
+
Advanced Features
|
|
2978
|
+
|
|
2979
|
+
State Management Integration
|
|
2980
|
+
|
|
2981
|
+
- Context-driven architecture for complex components
|
|
2982
|
+
- Signal-based real-time communication components
|
|
2983
|
+
- Session storage integration for form persistence
|
|
2984
|
+
- Theme-aware styling with automatic adaptation
|
|
2985
|
+
|
|
2986
|
+
Performance Optimizations
|
|
2987
|
+
|
|
2988
|
+
- Lazy loading support for heavy components
|
|
2989
|
+
- Code splitting at component level
|
|
2990
|
+
- Optimized re-rendering with React.memo patterns
|
|
2991
|
+
- Intersection Observer for scroll-based interactions
|
|
2992
|
+
|
|
2993
|
+
Developer Experience
|
|
2994
|
+
|
|
2995
|
+
- Comprehensive TypeScript interfaces for all props
|
|
2996
|
+
- Consistent naming conventions and API patterns
|
|
2997
|
+
- Built-in error boundaries and fallback handling
|
|
2998
|
+
- Extensive JSDoc documentation
|
|
2999
|
+
- Hot reload support for development
|
|
3000
|
+
|
|
3001
|
+
Accessibility & Internationalization
|
|
3002
|
+
|
|
3003
|
+
- ARIA attributes and keyboard navigation support
|
|
3004
|
+
- Screen reader compatibility
|
|
3005
|
+
- RTL (right-to-left) language support
|
|
3006
|
+
- Localized date/time formatting
|
|
3007
|
+
- Color contrast compliance
|
|
3008
|
+
|
|
3009
|
+
Usage Patterns
|
|
3010
|
+
|
|
3011
|
+
The library follows a consistent component composition pattern where complex components are built from smaller, focused
|
|
3012
|
+
subcomponents. For example:
|
|
3013
|
+
|
|
3014
|
+
- Chart.Bar, Chart.Line for different visualization types
|
|
3015
|
+
- Dialog.Modal, Dialog.Title, Dialog.Content for composable modals
|
|
3016
|
+
- Layout.Header, Layout.Sider, Layout.Navbar for layout construction
|
|
3017
|
+
- Upload.File, Upload.Image, Upload.Images for different upload scenarios
|
|
3018
|
+
|
|
3019
|
+
This design enables maximum flexibility while maintaining consistency across the application. Components are designed to work
|
|
3020
|
+
seamlessly together, sharing common styling patterns, validation systems, and state management approaches.
|
|
3021
|
+
|
|
3022
|
+
The library serves as a comprehensive foundation for building modern, accessible, and performant web applications with a focus
|
|
3023
|
+
on developer productivity and end-user experience.
|
|
3024
|
+
|
|
3025
|
+
Avatar
|
|
3026
|
+
- Displays user profile images with automatic fallback to user icon
|
|
3027
|
+
- Props: className?: string, icon?: ReactNode, src?: string
|
|
3028
|
+
|
|
3029
|
+
Button
|
|
3030
|
+
- Enhanced button with automatic loading states and error handling
|
|
3031
|
+
- Props: onClick: (e, {onError}) => Promise<Result>, onSuccess?: (result) => void, className?, children, standard button props
|
|
3032
|
+
|
|
3033
|
+
Input
|
|
3034
|
+
- Comprehensive input system with real-time validation and caching
|
|
3035
|
+
- Props: value: string, validate: (value) => boolean | string, onChange?, nullable?, inputStyleType?: "bordered" | "borderless"
|
|
3036
|
+
| "underline", icon?, cacheKey?
|
|
3037
|
+
- Variants: Input.TextArea, Input.Password, Input.Email, Input.Number, Input.Checkbox
|
|
3038
|
+
|
|
3039
|
+
Select
|
|
3040
|
+
- Advanced dropdown with search and multi-select capabilities
|
|
3041
|
+
- Props: value: T | T[], options: {label, value}[], multiple?, searchable?, onChange, onSearch?, renderOption?, renderSelected?
|
|
3042
|
+
|
|
3043
|
+
DatePicker
|
|
3044
|
+
- Date/time picker with range selection support
|
|
3045
|
+
- Props: value?: Dayjs, onChange, showTime?, format?, disabledDate?
|
|
3046
|
+
- Variants: DatePicker.RangePicker, DatePicker.TimePicker
|
|
3047
|
+
|
|
3048
|
+
CodeInput
|
|
3049
|
+
- PIN/code input with individual character boxes
|
|
3050
|
+
- Props: maxNum: number, value: string, onChange, unitStyle?: "box" | "underline", autoComplete?
|
|
3051
|
+
|
|
3052
|
+
Display Components
|
|
3053
|
+
|
|
3054
|
+
Table
|
|
3055
|
+
- Feature-rich data table with pagination and responsive design
|
|
3056
|
+
- Props: columns: Column[], dataSource: any[], loading?, pagination?, onRow?, rowClassName?
|
|
3057
|
+
|
|
3058
|
+
Modal
|
|
3059
|
+
- Dialog modal with backdrop and action buttons
|
|
3060
|
+
- Props: open: boolean, onCancel, title?, action?, confirmClose?
|
|
3061
|
+
- Variants: Modal.Window
|
|
3062
|
+
|
|
3063
|
+
Image
|
|
3064
|
+
- Optimized image component with blur placeholder and SSR support
|
|
3065
|
+
- Props: src?, file?: ProtoFile, abstractData?, alt?, standard Next.js Image props
|
|
3066
|
+
|
|
3067
|
+
ChatBubble
|
|
3068
|
+
- Chat message bubble with avatar and timestamp
|
|
3069
|
+
- Props: avatar?, hasPrev?, hasNext?, isMe?, name?, at?: Dayjs, children
|
|
3070
|
+
|
|
3071
|
+
Empty
|
|
3072
|
+
- Empty state placeholder with customizable message
|
|
3073
|
+
- Props: description?, minHeight?, children?
|
|
3074
|
+
|
|
3075
|
+
QRCode
|
|
3076
|
+
- QR code generator with click-to-open functionality
|
|
3077
|
+
- Props: href: string, className?
|
|
3078
|
+
|
|
3079
|
+
Layout Components
|
|
3080
|
+
|
|
3081
|
+
BottomSheet
|
|
3082
|
+
- Only mobile bottom sheet with drag gestures
|
|
3083
|
+
- Props: open: boolean, onCancel, type: "full" | "half", children
|
|
3084
|
+
|
|
3085
|
+
Layout
|
|
3086
|
+
Layout - Complete layout framework with responsive design
|
|
3087
|
+
- Layout.Header - Top header with auto-hide functionality
|
|
3088
|
+
- Props: className?: string, type?: "static" | "hide", children?: any, height?: number
|
|
3089
|
+
- Features: Auto-hide on scroll, fixed positioning
|
|
3090
|
+
- Layout.Sider - Collapsible sidebar
|
|
3091
|
+
- Props: className?: string, bgClassName?: string, children?: any
|
|
3092
|
+
- Features: Drawer-based with toggle functionality
|
|
3093
|
+
- Layout.Navbar - Navigation bar with portal content
|
|
3094
|
+
- Props: className?: string, children?: ReactNode, height?:
|
|
3095
|
+
|
|
3096
|
+
Menu
|
|
3097
|
+
- Navigation menu with horizontal/vertical modes and submenu support
|
|
3098
|
+
- Props: items: MenuItem[], mode?: "horizontal" | "inline", selectedKeys?, onClick?, inlineCollapsed?
|
|
3099
|
+
|
|
3100
|
+
|
|
3101
|
+
Tab
|
|
3102
|
+
- Tabbed interface system
|
|
3103
|
+
- Tab.Provider - Tab context provider
|
|
3104
|
+
- Props: className?: string, defaultMenu?: string | null, children?: any
|
|
3105
|
+
- Tab.Menu - Tab menu item
|
|
3106
|
+
- Props: className?: string, activeClassName?: string, disabledClassName?: string, disabled?: boolean, menu: string, children:
|
|
3107
|
+
any, scrollToTop?: boolean, tooltip?: string
|
|
3108
|
+
- Tab.Panel - Tab content panel
|
|
3109
|
+
- Props: className?: string, menu: string, children?: any, loading?: "eager" | "lazy" | "every"
|
|
3110
|
+
- Features: Lazy loading support
|
|
3111
|
+
|
|
3112
|
+
ScreenNavigator
|
|
3113
|
+
- Gesture-based screen navigation
|
|
3114
|
+
- ScreenNavigator.Provider - Navigation context provider
|
|
3115
|
+
- Props: setMenu?: (menu: string) => void, children: ReactNode, menus: string[]
|
|
3116
|
+
- Features: Gesture-based navigation, spring animations
|
|
3117
|
+
- ScreenNavigator.Screen - Individual screen container
|
|
3118
|
+
- Props: children: ReactNode, className?: string
|
|
3119
|
+
- ScreenNavigator.NavbarItem - Navigation bar item
|
|
3120
|
+
- Props: menu: string, children: ReactNode, className?: string
|
|
3121
|
+
|
|
3122
|
+
Upload
|
|
3123
|
+
- File upload system with multiple modes
|
|
3124
|
+
- Upload
|
|
3125
|
+
- Basic file upload with drag & drop
|
|
3126
|
+
- Props: onChange?: (fileList: FileList) => void; multiple?: boolean; accept?: string; className?: string; uploadClassName?: string; children: React.ReactNode; disabled?: boolean;
|
|
3127
|
+
- Upload.File
|
|
3128
|
+
- Single file upload with preview
|
|
3129
|
+
- Props: multiple?: boolean; file: ProtoFile | null; render?: (file: ProtoFile) => React.ReactNode; onChange?: (e: File | FileList) => void | Promise<void>; onRemove?: (e: any) => void; children?: React.ReactNode; disabled?: boolean; maxCount?: number; className?: string; uploadClassName?: string; accept?: string;
|
|
3130
|
+
- Upload.FileList
|
|
3131
|
+
- Multiple files with table view and progress tracking
|
|
3132
|
+
- Props: multiple?: boolean; fileList: ProtoFile[]; render?: (file: ProtoFile) => React.ReactNode; onChange?: (e: File | FileList) => void | Promise<void>; onRemove?: (e: any) => void; children?: React.ReactNode; disabled?: boolean; maxCount?: number; className?: string; uploadClassName?: string; accept?: string;
|
|
3133
|
+
- Upload.Image
|
|
3134
|
+
- Image upload with integrated cropping functionality
|
|
3135
|
+
- Props: multiple?: boolean; file: ProtoFile | null; render?: (file: ProtoFile) => React.ReactNode; onChange?: (e: File | FileList) => void | Promise<void>; onRemove?: (e: any) => void; children?: React.ReactNode; disabled?: boolean; maxCount?: number; className?: string; uploadClassName?: string; accept?: string;
|
|
3136
|
+
- Upload.Images
|
|
3137
|
+
- Multiple image upload with gallery preview
|
|
3138
|
+
- Props: multiple?: boolean; fileList: ProtoFile[]; render?: (file: ProtoFile) => React.ReactNode; onChange?: (e: File | FileList) => void | Promise<void>; onRemove?: (e: any) => void; children?: React.ReactNode; disabled?: boolean; maxCount?: number; className?: string; uploadClassName?: string; accept?: string;
|
|
3139
|
+
|
|
3140
|
+
DndKit
|
|
3141
|
+
- Drag and drop functionality built on @dnd-kit
|
|
3142
|
+
- DndKit.Provider
|
|
3143
|
+
- DnD context provider
|
|
3144
|
+
- Props: className?: string + all DndContextProps
|
|
3145
|
+
- DndKit.DraggableUnit
|
|
3146
|
+
- Draggable item wrapper
|
|
3147
|
+
- Props: id: string, children: ReactNode, className?: string, onClick?: () => void | Promise<void>
|
|
3148
|
+
- DndKit.DroppableColumn
|
|
3149
|
+
- Drop target column
|
|
3150
|
+
- Props: id: string, items: T[], className?: string, children: ReactNode, onOver?: (id, items, event) => void, onEnd?: (id,
|
|
3151
|
+
item, event) => void
|
|
3152
|
+
|
|
3153
|
+
MapView
|
|
3154
|
+
- Map integration with multiple providers
|
|
3155
|
+
- MapView.Map
|
|
3156
|
+
- Main map container with theme awareness
|
|
3157
|
+
- Props: className?: string, onLoad?: () => void, onClick?: (coordinate) => void, onRightClick?: (coordinate) => void,
|
|
3158
|
+
onMouseMove?: (coordinate) => void, children: any
|
|
3159
|
+
- MapView.Marker
|
|
3160
|
+
- Map marker component
|
|
3161
|
+
- Props: coordinate: cnst.Coordinate, zIndex?: number, children?: any
|
|
3162
|
+
- MapView.Google
|
|
3163
|
+
- Google Maps implementation
|
|
3164
|
+
- Props: id?: string, className?: string, mapKey: string, onClick/onRightClick?: (coordinate) => void, center?:
|
|
3165
|
+
cnst.Coordinate, onChangeCenter?: (coordinate) => void, zoom?: number, onChangeZoom?: (zoom) => void, bounds?: {minLat, maxLat,
|
|
3166
|
+
minLng, maxLng}, onLoad?: () => void, onMouseMove?: (coordinate, event) => void, options?: google.maps.MapOptions, children: any
|
|
3167
|
+
- MapView.Pigeon
|
|
3168
|
+
- Pigeon Maps implementation (lightweight alternative)
|
|
3169
|
+
- Props: id?: string, className?: string, onLoad?: () => void, onClick/onRightClick?: (coordinate) => void, center?:
|
|
3170
|
+
cnst.Coordinate, onChangeCenter?: (coordinate) => void, zoom?: number, onChangeZoom?: (zoom) => void, bounds?: {minLat, maxLat,
|
|
3171
|
+
minLng, maxLng}, onChangeBounds?: (bounds) => void, mouseEvents?: boolean, onMouseMove?: (coordinate) => void, mapTiler?: (x, y,
|
|
3172
|
+
z, dpr) => string, children?: any, zoomControlStyle?: CSSProperties
|
|
3173
|
+
|
|
3174
|
+
|
|
3175
|
+
Pagination
|
|
3176
|
+
- Page navigation with smart ellipsis and responsive design
|
|
3177
|
+
- Props: currentPage: number, total: number, onPageSelect, itemsPerPage: number
|
|
3178
|
+
|
|
3179
|
+
Radio
|
|
3180
|
+
- Radio button group with custom styling support
|
|
3181
|
+
- Props: value, children: ReactElement[], onChange, disabled?
|
|
3182
|
+
|
|
3183
|
+
ToggleSelect
|
|
3184
|
+
- Button-based selection with single/multi-select modes
|
|
3185
|
+
- Props: items, value, validate, onChange, nullable
|
|
3186
|
+
- Variants: ToggleSelect.Multi
|
|
3187
|
+
|
|
3188
|
+
Share
|
|
3189
|
+
- Native share API with copy fallback
|
|
3190
|
+
- Props: title: string, url: string, children
|
|
3191
|
+
|
|
3192
|
+
Specialized Component Groups
|
|
3193
|
+
|
|
3194
|
+
Chart
|
|
3195
|
+
- Visualization components built on Chart.js and react-chartjs-2
|
|
3196
|
+
- Chart.Bar - Bar chart component
|
|
3197
|
+
- Props: data: ChartData<"bar">, options?: ChartOptions<"bar">
|
|
3198
|
+
- Features: Responsive layout, legend display, title configuration
|
|
3199
|
+
- Chart.Line - Line chart component
|
|
3200
|
+
- Props: data: ChartData<"line">, options?: ChartOptions<"line">
|
|
3201
|
+
- Features: Line-specific Chart.js configuration with curve interpolation
|
|
3202
|
+
- Chart.Pie - Pie chart component
|
|
3203
|
+
- Props: data: ChartData<"pie">, options?: ChartOptions<"pie">
|
|
3204
|
+
- Features: ArcElement rendering, responsive design
|
|
3205
|
+
- Chart.Doughnut - Doughnut chart component
|
|
3206
|
+
- Props: data: ChartData<"doughnut">, options?: ChartOptions<"doughnut">
|
|
3207
|
+
- Features: Similar to pie but with center cutout
|
|
3208
|
+
|
|
3209
|
+
Dialog
|
|
3210
|
+
- Composable modal dialog system built on Radix UI
|
|
3211
|
+
- Dialog.Provider - Dialog context provider
|
|
3212
|
+
- Props: className?: string, open?: boolean, defaultOpen?: boolean, children?: any
|
|
3213
|
+
- Dialog.Modal - Main modal container
|
|
3214
|
+
- Props: className?: string, bodyClassName?: string, confirmClose?: boolean, children?: any, onCancel?: () => void
|
|
3215
|
+
- Features: Drag gestures, spring animations, responsive design, close confirmation
|
|
3216
|
+
- Dialog.Title - Modal title component
|
|
3217
|
+
- Props: children?: ReactNode
|
|
3218
|
+
- Dialog.Content - Modal content area
|
|
3219
|
+
- Props: className?: string, children?: ReactNode
|
|
3220
|
+
- Dialog.Action - Modal action buttons container
|
|
3221
|
+
- Props: children?: ReactNode
|
|
3222
|
+
- Dialog.Trigger - Modal trigger element
|
|
3223
|
+
- Props: className?: string, children?: any
|
|
3224
|
+
|
|
3225
|
+
Link
|
|
3226
|
+
- Adaptive navigation system
|
|
3227
|
+
- Link
|
|
3228
|
+
- Main adaptive link (auto-switches between CSR/Next.js based on render mode)
|
|
3229
|
+
- Link.Back - Back navigation link
|
|
3230
|
+
- Props: className?: string, children?: any
|
|
3231
|
+
- Features: Browser history integration
|
|
3232
|
+
- Link.Close - Window close link
|
|
3233
|
+
- Props: Similar to Back but closes window
|
|
3234
|
+
- Link.CsrLink & Link.NextLink - Environment-specific implementations with active state support
|
|
3235
|
+
|
|
3236
|
+
|
|
3237
|
+
Loading
|
|
3238
|
+
- Loading states for different UI elements
|
|
3239
|
+
- Loading.Area - Full-screen loading overlay with animated dots
|
|
3240
|
+
- Loading.Button - Button loading skeleton
|
|
3241
|
+
- Props: className?: string, active?: boolean, style?: CSSProperties
|
|
3242
|
+
- Loading.Input - Input loading skeleton
|
|
3243
|
+
- Loading.Skeleton - Multi-line content skeleton with pulse animation
|
|
3244
|
+
- Loading.Spin - Custom loading spinner
|
|
3245
|
+
- Props: indicator?: ReactNode, isCenter?: boolean
|
|
3246
|
+
- Loading.ProgressBar - Animated progress bar
|
|
3247
|
+
- Props: className?: string, value: number, max: number
|
|
3248
|
+
- Features: React Spring animations
|
|
3249
|
+
|
|
3250
|
+
Key Framework Features
|
|
3251
|
+
|
|
3252
|
+
- TypeScript support with strict typing
|
|
3253
|
+
- Responsive design with mobile-first approach
|
|
3254
|
+
- Internationalization (i18n) integration
|
|
3255
|
+
- Session storage caching for form inputs
|
|
3256
|
+
- Accessibility compliance
|
|
3257
|
+
- Consistent DaisyUI/Tailwind CSS styling
|
|
3258
|
+
- Modern React patterns (hooks, context, providers)
|
|
3259
|
+
- Error handling and validation systems
|
|
3260
|
+
`;
|
|
2724
3261
|
var frameworkAbstract = `
|
|
2725
3262
|
Intro
|
|
2726
3263
|
- Build an all-stack application at once.
|
|
@@ -2740,7 +3277,66 @@ Procedure
|
|
|
2740
3277
|
- No Spaghetti Components anymore, build your page with domain-driven components
|
|
2741
3278
|
- write one page, use SSR on Next.js and build Android&iOS CSR app with beautiful page transitions!
|
|
2742
3279
|
- built-in ai code generation, tell about business, the logic is generated.
|
|
3280
|
+
|
|
3281
|
+
|
|
2743
3282
|
`;
|
|
3283
|
+
var eslintDescription = `
|
|
3284
|
+
Core ESLint Extensions
|
|
3285
|
+
|
|
3286
|
+
Base Configurations:
|
|
3287
|
+
- eslint:recommended - Standard ESLint recommended rules
|
|
3288
|
+
- next & next/core-web-vitals - Next.js specific linting rules
|
|
3289
|
+
- @typescript-eslint/recommended-type-checked - TypeScript recommended rules with type checking
|
|
3290
|
+
- @typescript-eslint/strict-type-checked - Strict TypeScript type checking rules
|
|
3291
|
+
- @typescript-eslint/stylistic-type-checked - TypeScript stylistic rules with type checking
|
|
3292
|
+
|
|
3293
|
+
Third-Party Plugins
|
|
3294
|
+
|
|
3295
|
+
1. eslint-plugin-unused-imports
|
|
3296
|
+
- Automatically detects and warns about unused imports
|
|
3297
|
+
- Helps keep code clean by removing unnecessary import statements
|
|
3298
|
+
|
|
3299
|
+
2. eslint-plugin-simple-import-sort
|
|
3300
|
+
- Automatically sorts import statements in a consistent order
|
|
3301
|
+
- Enforces clean import organization throughout the codebase
|
|
3302
|
+
|
|
3303
|
+
Custom Plugin: @akanjs/lint
|
|
3304
|
+
|
|
3305
|
+
1. useClientByFile
|
|
3306
|
+
- Enforces proper "use client" directive usage in Next.js App Router
|
|
3307
|
+
- Server files must NOT have "use client" directive
|
|
3308
|
+
- Client files MUST have "use client" directive at the top
|
|
3309
|
+
|
|
3310
|
+
2. noImportClientFunctions
|
|
3311
|
+
- Prevents server files from importing client-side functions
|
|
3312
|
+
- Ensures proper separation between server and client code
|
|
3313
|
+
|
|
3314
|
+
3. nonScalarPropsRestricted
|
|
3315
|
+
- Prevents non-scalar props (functions) in server components
|
|
3316
|
+
- Specifically targets page.tsx and layout.tsx files
|
|
3317
|
+
- Allows exceptions for specific props like "loader", "render", and "of"
|
|
3318
|
+
|
|
3319
|
+
4. noImportExternalLibrary
|
|
3320
|
+
- Restricts external library imports in pure import/re-export files
|
|
3321
|
+
- Only allows imports from the same app scope (@appName/...)
|
|
3322
|
+
- Promotes clean architecture and prevents dependency leakage
|
|
3323
|
+
|
|
3324
|
+
Key Rule Configurations
|
|
3325
|
+
|
|
3326
|
+
Disabled Rules:
|
|
3327
|
+
- no-console: "error" - Prevents console statements in production code
|
|
3328
|
+
- Various TypeScript strict rules are disabled for flexibility
|
|
3329
|
+
- React and Next.js specific rules are relaxed for development ease
|
|
3330
|
+
|
|
3331
|
+
Import Management:
|
|
3332
|
+
- unused-imports/no-unused-imports: "warn" - Warns about unused imports
|
|
3333
|
+
- simple-import-sort/imports: "warn" - Enforces import sorting
|
|
3334
|
+
- import/first: "warn" - Ensures imports come first
|
|
3335
|
+
- import/newline-after-import: "warn" - Enforces newline after imports
|
|
3336
|
+
|
|
3337
|
+
This configuration creates a robust linting setup that enforces Next.js App Router best practices, maintains clean code
|
|
3338
|
+
organization, and ensures proper server/client code separation.
|
|
3339
|
+
`;
|
|
2744
3340
|
var scalarConstantDescription = `
|
|
2745
3341
|
Purpose and Structure
|
|
2746
3342
|
|
|
@@ -3095,10 +3691,10 @@ ${frameworkAbstract}
|
|
|
3095
3691
|
2. <model>.constant.ts \uD30C\uC77C\uC5D0 \uB300\uD55C \uAC1C\uC694
|
|
3096
3692
|
${scalarConstantDescription}
|
|
3097
3693
|
|
|
3098
|
-
3. <model
|
|
3694
|
+
3. <model>.constant.ts \uD30C\uC77C\uC758 Enum \uC791\uC131\uBC95
|
|
3099
3695
|
${howToSetEnumInModelConstant}
|
|
3100
3696
|
|
|
3101
|
-
4. <model
|
|
3697
|
+
4. <model>.constant.ts \uD30C\uC77C\uC758 Field \uC791\uC131\uBC95
|
|
3102
3698
|
${howToSetFieldInModelConstant}
|
|
3103
3699
|
|
|
3104
3700
|
5. \uD604\uC7AC \uD504\uB85C\uC81D\uD2B8 \uB0B4 \uB2E4\uB978 constant.ts \uD30C\uC77C\uB4E4\uC5D0 \uB300\uD55C \uC608\uC2DC
|
|
@@ -3123,6 +3719,87 @@ Target filename: ${modelName}.constant.ts
|
|
|
3123
3719
|
\`\`\`
|
|
3124
3720
|
${boilerplate}
|
|
3125
3721
|
\`\`\`
|
|
3722
|
+
`;
|
|
3723
|
+
var requestView = ({
|
|
3724
|
+
sysName,
|
|
3725
|
+
modelName,
|
|
3726
|
+
ModelName,
|
|
3727
|
+
boilerplate,
|
|
3728
|
+
constant,
|
|
3729
|
+
properties,
|
|
3730
|
+
exampleFiles
|
|
3731
|
+
}) => `
|
|
3732
|
+
|
|
3733
|
+
|
|
3734
|
+
1. Akan.js \uD504\uB808\uC784\uC6CC\uD06C\uC5D0 \uB300\uD55C \uAC1C\uC694
|
|
3735
|
+
${frameworkAbstract}
|
|
3736
|
+
|
|
3737
|
+
2. Akan.js\uD504\uB808\uC784\uC6CC\uD06C \uB370\uC774\uD130 \uAE30\uBC18 \uBAA8\uB4C8\uC5D0 \uB300\uD55C \uAC1C\uC694
|
|
3738
|
+
${moduleDesription}
|
|
3739
|
+
|
|
3740
|
+
3. Akan.js eslint \uC124\uC815\uC5D0 \uB300\uD55C \uAC1C\uC694
|
|
3741
|
+
${eslintDescription}
|
|
3742
|
+
|
|
3743
|
+
4. util/ui \uB0B4 ui\uD0B7\uC5D0 \uB300\uD55C \uAC1C\uC694
|
|
3744
|
+
${utilUiDescription}
|
|
3745
|
+
|
|
3746
|
+
|
|
3747
|
+
|
|
3748
|
+
5. ${ModelName}.constant.ts \uD30C\uC77C\uC5D0 \uB300\uD55C \uC815\uBCF4
|
|
3749
|
+
${constant}
|
|
3750
|
+
|
|
3751
|
+
6. ${modelName}\uC5D0\uC11C \uC885\uC18D\uB418\uB294 \uB2E4\uB978 \uBAA8\uB378\uB4E4\uC758 \uD0C0\uC785 \uC815\uC758
|
|
3752
|
+
${properties.map(
|
|
3753
|
+
(property) => `
|
|
3754
|
+
\`\`\`
|
|
3755
|
+
${property.key}.constant.ts
|
|
3756
|
+
|
|
3757
|
+
|
|
3758
|
+
${property.source}
|
|
3759
|
+
\`\`\`
|
|
3760
|
+
`
|
|
3761
|
+
).join("\n\n")}
|
|
3762
|
+
|
|
3763
|
+
|
|
3764
|
+
7. \uC608\uC2DC \uD30C\uC77C\uB4E4
|
|
3765
|
+
${exampleFiles.map(
|
|
3766
|
+
(example) => `
|
|
3767
|
+
Example filename: ${example.filepath}
|
|
3768
|
+
\`\`\`
|
|
3769
|
+
${example.content}
|
|
3770
|
+
\`\`\`
|
|
3771
|
+
`
|
|
3772
|
+
).join("\n\n")}
|
|
3773
|
+
|
|
3774
|
+
|
|
3775
|
+
|
|
3776
|
+
Application name: ${sysName}
|
|
3777
|
+
Model name: ${modelName}
|
|
3778
|
+
Target filename: ${ModelName}.View.tsx
|
|
3779
|
+
|
|
3780
|
+
|
|
3781
|
+
\uB108\uB294 Akan.js\uB77C\uB294 \uC0AC\uB0B4 \uD504\uB808\uC784\uC6CC\uD06C\uB85C Typescript \uAE30\uBC18 \uD504\uB85C\uADF8\uB7A8\uC744 \uC791\uC131\uD558\uB294 \uC2DC\uB2C8\uC5B4 \uAC1C\uBC1C\uC790\uC57C.
|
|
3782
|
+
\uADF8 \uC911\uC5D0\uC11C\uB3C4 \uD504\uB860\uD2B8\uC5D4\uB4DC \uAC1C\uBC1C\uC790.
|
|
3783
|
+
\uB9CC\uC57D\uC5D0 \uC544\uC774\uCF58 \uC0AC\uC6A9\uC774 \uD544\uC694\uD558\uBA74 react-icons \uB77C\uC774\uBE0C\uB7EC\uB9AC\uC5D0\uC11C \uC801\uD569\uD55C \uC544\uC774\uCF58\uC744 \uCC3E\uC544\uC11C \uC0AC\uC6A9\uD574\uC918.
|
|
3784
|
+
\uB610, \uC0C9\uC0C1\uC744 \uC0AC\uC6A9\uD558\uB824\uACE0 \uD558\uBA74 \uD558\uB4DC\uCF54\uB529\uB41C \uC0C9\uC0C1(bg-red)\uC774 \uC544\uB2CC \uD14C\uB9C8 \uC0C9\uC0C1(bg-primary)\uC744 \uC0AC\uC6A9\uD574\uC11C \uC791\uC131\uD574\uC918.
|
|
3785
|
+
\uADF8\uB9AC\uACE0 optional\uD55C \uD544\uB4DC\uB294 field && <div>... \uAC00 \uC544\uB2CC, field ? <div>... : null \uD615\uD0DC\uB85C \uC791\uC131\uD574\uC918.
|
|
3786
|
+
css\uB77C\uC774\uBE0C\uB7EC\uB9AC\uB294 DaisyUI\uB97C \uAE30\uBC18\uC73C\uB85C \uC791\uC131\uD574\uC8FC\uB294\uB370, btn, input, badge\uC640 \uAC19\uC740 \uB2E8\uC21C\uD55C \uAE30\uBCF8 css\uB294 \uC0AC\uC6A9\uD574\uB3C4 \uAD1C\uCC2E\uC544. \uADF8\uB7F0\uB370 card, hero\uAC19\uC774 \uBCF5\uC7A1\uD55C \uCEF4\uD3EC\uB10C\uD2B8\uB294 \uC0AC\uC6A9\uD558\uBA74 \uC548\uB3FC.
|
|
3787
|
+
\uBAA8\uB378\uC5D0 \uB300\uD574\uC11C object destructuring\uC740 \uD558\uC9C0\uB9D0\uACE0 ${modelName}.field \uD615\uD0DC\uB85C \uC811\uADFC\uD558\uACE0, \uD0C0\uC785\uC5D0 \uC5D0\uB7EC\uB294 \uC808\uB300\uB85C \uBC1C\uC0DD\uD558\uC9C0 \uC54A\uB3C4\uB85D ${modelName}.constant.ts\uC5D0 \uC791\uC131\uB418\uC788\uB294 \uC2A4\uD0A4\uB9C8\uB97C \uBCF4\uACE0 \uC791\uC131\uD574.
|
|
3788
|
+
\uC870\uAC74\uBD80 className\uC774 \uD544\uC694\uD55C \uACBD\uC6B0\uC5D0\uB294 clsx \uB77C\uC774\uBE0C\uB7EC\uB9AC\uB97C \uC0AC\uC6A9\uD574\uC57C\uB3FC.
|
|
3789
|
+
\uBAA8\uB4E0 \uBAA8\uB378 \uD544\uB4DC\uC5D0 \uC811\uADFC\uD558\uAE30 \uC804\uC5D0, \uAC01 \uC2A4\uD0A4\uB9C8\uC758 \uC2E4\uC81C \uD544\uB4DC \uB9AC\uC2A4\uD2B8\uB97C \uC791\uC131\uD558\uACE0 \uAC80\uD1A0\uD574. \uD2B9\uD788 \uC911\uCCA9\uB41C \uAC1D\uCCB4( ex) XXX.XXX.XXX )\uC5D0 \uC811\uADFC\uD560 \uB54C\uB294 \uB354\uC6B1 \uC8FC\uC758\uD574.
|
|
3790
|
+
\uB610\uD55C ${modelName}\uACFC \uC885\uC18D\uC131\uC774 \uC788\uB294 \uB2E4\uB978 \uBAA8\uB378\uB4E4\uC758 \uD0C0\uC785\uB4E4\uB3C4 \uBAA8\uB450 \uC704\uBC30\uD558\uC9C0\uB9D0\uACE0 \uC798 \uD30C\uC545\uD558\uACE0 \uC791\uC131\uD574.
|
|
3791
|
+
\uC704\uC5D0\uC11C \uC124\uBA85\uD55C \uBAA8\uB4E0 \uB8F0\uACFC \uC124\uBA85, \uD0C0\uC785\uC744 \uC808\uB300\uB85C \uC704\uBC30\uD558\uC9C0\uB9D0\uACE0 \uC798 \uD30C\uC545\uD558\uACE0 \uC791\uC131\uD574.(\uAC01 \uB370\uC774\uD130\uC758 \uD0C0\uC785, \uCEF4\uD3EC\uB10C\uD2B8\uC758 props\uB4F1...)
|
|
3792
|
+
\uC124\uBA85\uD55C \uB0B4\uC6A9 \uC774\uC678\uC5D0 \uB0B4\uC6A9\uC73C\uB85C \uB2C8\uAC00 \uCD94\uC0C1\uD574\uC11C \uC4F0\uC9C0\uB9D0\uACE0 \uC704\uC5D0 \uBA85\uC2DC\uB418\uC788\uB294 \uB8F0 \uC548\uC5D0\uC11C\uB9CC \uC791\uC131\uD574. \uC788\uC9C0\uB3C4 \uC54A\uC740 \uAC83\uB4E4 \uB9CC\uB4E4\uC5B4\uC11C \uCD94\uC0C1\uD654 \uC2DC\uCF1C\uC11C \uC790\uAFB8 \uC4F0\uB294 \uC77C\uC740 \uC808\uB300\uB85C \uD558\uC9C0\uB9C8.
|
|
3793
|
+
\uD2B9\uD788\uB098 \uBC29\uAE08 \uB9D0\uD55C \uC774 \uC704 \uB450 \uBB38\uC7A5\uC740 \uC808\uB300\uC801\uC73C\uB85C \uC9C0\uCF1C\uC57C \uD560 \uB8F0\uC774\uC57C \uC791\uC131\uD560 \uB54C \uD56D\uC0C1 \uC9C0\uD0A4\uACE0 \uB530\uB77C.
|
|
3794
|
+
${ModelName}.View.tsx \uCF54\uB4DC\uB97C \uC791\uC131\uD574\uC918. \uC77C\uBC18\uC801\uC73C\uB85C \uC0AC\uC6A9\uD560 \uC218 \uC788\uB294 \uB514\uC790\uC778\uC758 \uCEF4\uD3EC\uB10C\uD2B8\uB97C 4\uAC1C \uC815\uB3C4 \uB9CC\uB4E4\uC5B4\uC918. (ex card, table...)
|
|
3795
|
+
\uC608\uC2DC \uB4E4\uC5B4\uC92C\uB2E4\uACE0 \uC608\uC2DC\uB9CC \uB9CC\uB4E4\uC9C0 \uB9D0\uACE0 \uB2C8 \uC0DD\uAC01\uC5D0 \uC77C\uBC18\uC801\uC73C\uB85C \uC0AC\uC6A9\uD55C\uB2E4 \uD558\uB294 \uCEF4\uD3EC\uB10C\uD2B8\uB85C \uC0DD\uAC01\uD574\uC11C \uB9CC\uB4E4\uC5B4.
|
|
3796
|
+
|
|
3797
|
+
Target filename: ${ModelName}.View.tsx
|
|
3798
|
+
\`\`\`
|
|
3799
|
+
|
|
3800
|
+
\`\`\`
|
|
3801
|
+
|
|
3802
|
+
|
|
3126
3803
|
`;
|
|
3127
3804
|
|
|
3128
3805
|
// pkgs/@akanjs/cli/src/application/application.prompt.ts
|
|
@@ -3174,6 +3851,10 @@ var ApplicationRunner = class {
|
|
|
3174
3851
|
workspace.setTsPaths("app", appName);
|
|
3175
3852
|
return AppExecutor.from(workspace, appName);
|
|
3176
3853
|
}
|
|
3854
|
+
async removeApplication(app) {
|
|
3855
|
+
await app.workspace.exec(`rm -rf apps/${app.name}`);
|
|
3856
|
+
app.log(`Application ${app.name} removed`);
|
|
3857
|
+
}
|
|
3177
3858
|
async scanSync(app) {
|
|
3178
3859
|
const akanConfig = await getAppConfig(app.cwdPath, {
|
|
3179
3860
|
...app.workspace.getBaseDevEnv(),
|
|
@@ -3281,11 +3962,11 @@ var ApplicationRunner = class {
|
|
|
3281
3962
|
]);
|
|
3282
3963
|
app.dist.writeFile("frontend/Dockerfile", akanConfig.frontend.dockerfile);
|
|
3283
3964
|
}
|
|
3284
|
-
async serveFrontend(app, { open: open2 = false } = {}) {
|
|
3965
|
+
async serveFrontend(app, { open: open2 = false, turbo = true } = {}) {
|
|
3285
3966
|
const { env } = await this.#prepareCommand(app, "serve", "frontend");
|
|
3286
3967
|
if (open2)
|
|
3287
3968
|
setTimeout(() => (0, import_open.default)("http://localhost:4200"), 3e3);
|
|
3288
|
-
await app.spawn("npx", ["next", "dev", "-p", "4200"], { env });
|
|
3969
|
+
await app.spawn("npx", ["next", "dev", "-p", "4200", ...turbo ? ["--turbo"] : []], { env });
|
|
3289
3970
|
}
|
|
3290
3971
|
async #getViteConfig(app) {
|
|
3291
3972
|
const { env } = await this.#prepareCommand(app, "build", "csr");
|
|
@@ -3366,7 +4047,7 @@ var ApplicationRunner = class {
|
|
|
3366
4047
|
setTimeout(() => (0, import_open.default)("http://localhost:4201"), 3e3);
|
|
3367
4048
|
}
|
|
3368
4049
|
async #prepareIos(app) {
|
|
3369
|
-
const isAdded =
|
|
4050
|
+
const isAdded = import_fs10.default.existsSync(`${app.cwdPath}/ios/App/Podfile`);
|
|
3370
4051
|
if (!isAdded) {
|
|
3371
4052
|
await app.spawn("npx", ["cap", "add", "ios"]);
|
|
3372
4053
|
await app.spawn("npx", ["@capacitor/assets", "generate"]);
|
|
@@ -3401,7 +4082,7 @@ var ApplicationRunner = class {
|
|
|
3401
4082
|
await capacitorApp.releaseIos();
|
|
3402
4083
|
}
|
|
3403
4084
|
async #prepareAndroid(app) {
|
|
3404
|
-
const isAdded =
|
|
4085
|
+
const isAdded = import_fs10.default.existsSync(`${app.cwdPath}/android/app/build.gradle`);
|
|
3405
4086
|
if (!isAdded) {
|
|
3406
4087
|
await app.spawn("npx", ["cap", "add", "android"]);
|
|
3407
4088
|
await app.spawn("npx", ["@capacitor/assets", "generate"]);
|
|
@@ -3483,14 +4164,14 @@ var ApplicationRunner = class {
|
|
|
3483
4164
|
const buildRoot = `${app.workspace.workspaceRoot}/releases/builds/${app.name}`;
|
|
3484
4165
|
const appVersionInfo = import_js_yaml2.default.load(app.readFile("config.yaml"));
|
|
3485
4166
|
const platformVersion = appVersionInfo.platforms.android.versionName;
|
|
3486
|
-
if (
|
|
4167
|
+
if (import_fs10.default.existsSync(buildRoot))
|
|
3487
4168
|
await import_promises2.default.rm(buildRoot, { recursive: true, force: true });
|
|
3488
4169
|
await import_promises2.default.mkdir(buildRoot, { recursive: true });
|
|
3489
|
-
if (rebuild || !
|
|
4170
|
+
if (rebuild || !import_fs10.default.existsSync(`${app.dist.cwdPath}/backend`))
|
|
3490
4171
|
await this.buildBackend(app);
|
|
3491
|
-
if (rebuild || !
|
|
4172
|
+
if (rebuild || !import_fs10.default.existsSync(`${app.dist.cwdPath}/frontend`))
|
|
3492
4173
|
await this.buildFrontend(app);
|
|
3493
|
-
if (rebuild || !
|
|
4174
|
+
if (rebuild || !import_fs10.default.existsSync(`${app.dist.cwdPath}/csr`))
|
|
3494
4175
|
await this.buildCsr(app);
|
|
3495
4176
|
const buildVersion = `${platformVersion}-${buildNum}`;
|
|
3496
4177
|
const buildPath = `${buildRoot}/${buildVersion}`;
|
|
@@ -3505,7 +4186,7 @@ var ApplicationRunner = class {
|
|
|
3505
4186
|
buildRoot,
|
|
3506
4187
|
"./"
|
|
3507
4188
|
]);
|
|
3508
|
-
if (
|
|
4189
|
+
if (import_fs10.default.existsSync(`${app.dist.cwdPath}/csr`)) {
|
|
3509
4190
|
await import_promises2.default.cp(`${app.dist.cwdPath}/csr`, "./csr", { recursive: true });
|
|
3510
4191
|
await app.workspace.spawn("zip", [
|
|
3511
4192
|
"-r",
|
|
@@ -3515,7 +4196,7 @@ var ApplicationRunner = class {
|
|
|
3515
4196
|
await import_promises2.default.rm("./csr", { recursive: true, force: true });
|
|
3516
4197
|
}
|
|
3517
4198
|
const sourceRoot = `${app.workspace.workspaceRoot}/releases/sources/${app.name}`;
|
|
3518
|
-
if (
|
|
4199
|
+
if (import_fs10.default.existsSync(sourceRoot)) {
|
|
3519
4200
|
const MAX_RETRY = 3;
|
|
3520
4201
|
for (let i = 0; i < MAX_RETRY; i++) {
|
|
3521
4202
|
try {
|
|
@@ -3535,7 +4216,7 @@ var ApplicationRunner = class {
|
|
|
3535
4216
|
await Promise.all(
|
|
3536
4217
|
[".next", "ios", "android", "public/libs"].map(async (path7) => {
|
|
3537
4218
|
const targetPath = `${sourceRoot}/apps/${app.name}/${path7}`;
|
|
3538
|
-
if (
|
|
4219
|
+
if (import_fs10.default.existsSync(targetPath))
|
|
3539
4220
|
await import_promises2.default.rm(targetPath, { recursive: true, force: true });
|
|
3540
4221
|
})
|
|
3541
4222
|
);
|
|
@@ -3563,8 +4244,8 @@ var ApplicationRunner = class {
|
|
|
3563
4244
|
[]
|
|
3564
4245
|
)
|
|
3565
4246
|
]);
|
|
3566
|
-
|
|
3567
|
-
|
|
4247
|
+
import_fs10.default.writeFileSync(`${sourceRoot}/tsconfig.json`, JSON.stringify(tsconfig, null, 2));
|
|
4248
|
+
import_fs10.default.writeFileSync(
|
|
3568
4249
|
`${sourceRoot}/README.md`,
|
|
3569
4250
|
`# ${app.name}
|
|
3570
4251
|
\uBCF8 \uD504\uB85C\uC81D\uD2B8\uC758 \uC18C\uC2A4\uCF54\uB4DC \uBC0F \uAD00\uB828\uC790\uB8CC\uB294 \uBAA8\uB450 \uBE44\uBC00\uC815\uBCF4\uB85C \uAD00\uB9AC\uB429\uB2C8\uB2E4.
|
|
@@ -3670,6 +4351,9 @@ var ApplicationScript = class {
|
|
|
3670
4351
|
if (serve)
|
|
3671
4352
|
await this.serve(app, { open: true });
|
|
3672
4353
|
}
|
|
4354
|
+
async removeApplication(app) {
|
|
4355
|
+
await this.#runner.removeApplication(app);
|
|
4356
|
+
}
|
|
3673
4357
|
async scanApplication(app, verbose = false) {
|
|
3674
4358
|
const scanResult = await this.#runner.scanSync(app);
|
|
3675
4359
|
if (verbose)
|
|
@@ -3685,7 +4369,7 @@ var ApplicationScript = class {
|
|
|
3685
4369
|
}
|
|
3686
4370
|
async build(app) {
|
|
3687
4371
|
await this.syncApplication(app);
|
|
3688
|
-
await Promise.all([this.buildBackend(app), this.buildFrontend(app)]);
|
|
4372
|
+
await Promise.all([this.buildBackend(app, { sync: false }), this.buildFrontend(app, { sync: false })]);
|
|
3689
4373
|
}
|
|
3690
4374
|
async serve(app, { open: open2 = false } = {}) {
|
|
3691
4375
|
await this.syncApplication(app);
|
|
@@ -3706,10 +4390,10 @@ var ApplicationScript = class {
|
|
|
3706
4390
|
await this.syncApplication(app);
|
|
3707
4391
|
await this.#runner.buildFrontend(app);
|
|
3708
4392
|
}
|
|
3709
|
-
async serveFrontend(app, { open: open2 = false, sync = true } = {}) {
|
|
4393
|
+
async serveFrontend(app, { open: open2 = false, turbo = false, sync = true } = {}) {
|
|
3710
4394
|
if (sync)
|
|
3711
4395
|
await this.syncApplication(app);
|
|
3712
|
-
await this.#runner.serveFrontend(app, { open: open2 });
|
|
4396
|
+
await this.#runner.serveFrontend(app, { open: open2, turbo });
|
|
3713
4397
|
}
|
|
3714
4398
|
async buildCsr(app, { sync = true } = {}) {
|
|
3715
4399
|
if (sync)
|
|
@@ -3800,7 +4484,8 @@ var ApplicationCommand = class {
|
|
|
3800
4484
|
async createApplication(name, serve, workspace) {
|
|
3801
4485
|
await this.applicationScript.createApplication(name, workspace, { serve });
|
|
3802
4486
|
}
|
|
3803
|
-
async removeApplication(app
|
|
4487
|
+
async removeApplication(app) {
|
|
4488
|
+
await this.applicationScript.removeApplication(app);
|
|
3804
4489
|
}
|
|
3805
4490
|
async scanApplication(app) {
|
|
3806
4491
|
await this.applicationScript.scanApplication(app, true);
|
|
@@ -3829,8 +4514,8 @@ var ApplicationCommand = class {
|
|
|
3829
4514
|
async serveBackend(app, open2) {
|
|
3830
4515
|
await this.applicationScript.serveBackend(app, { open: open2 });
|
|
3831
4516
|
}
|
|
3832
|
-
async serveFrontend(app, open2) {
|
|
3833
|
-
await this.applicationScript.serveFrontend(app, { open: open2 });
|
|
4517
|
+
async serveFrontend(app, open2, turbo) {
|
|
4518
|
+
await this.applicationScript.serveFrontend(app, { open: open2, turbo });
|
|
3834
4519
|
}
|
|
3835
4520
|
async serveCsr(app, open2) {
|
|
3836
4521
|
await this.applicationScript.serveCsr(app, { open: open2 });
|
|
@@ -3880,8 +4565,7 @@ __decorateClass([
|
|
|
3880
4565
|
], ApplicationCommand.prototype, "createApplication", 1);
|
|
3881
4566
|
__decorateClass([
|
|
3882
4567
|
Target.Public(),
|
|
3883
|
-
__decorateParam(0, App())
|
|
3884
|
-
__decorateParam(1, Workspace())
|
|
4568
|
+
__decorateParam(0, App())
|
|
3885
4569
|
], ApplicationCommand.prototype, "removeApplication", 1);
|
|
3886
4570
|
__decorateClass([
|
|
3887
4571
|
Target.Public(),
|
|
@@ -3924,7 +4608,8 @@ __decorateClass([
|
|
|
3924
4608
|
__decorateClass([
|
|
3925
4609
|
Target.Public({ short: true }),
|
|
3926
4610
|
__decorateParam(0, App()),
|
|
3927
|
-
__decorateParam(1, Option("open", { type: "boolean", desc: "open web browser", default: false }))
|
|
4611
|
+
__decorateParam(1, Option("open", { type: "boolean", desc: "open web browser", default: false })),
|
|
4612
|
+
__decorateParam(2, Option("turbo", { type: "boolean", desc: "turbo", default: false }))
|
|
3928
4613
|
], ApplicationCommand.prototype, "serveFrontend", 1);
|
|
3929
4614
|
__decorateClass([
|
|
3930
4615
|
Target.Public({ short: true }),
|
|
@@ -4012,7 +4697,7 @@ ApplicationCommand = __decorateClass([
|
|
|
4012
4697
|
// pkgs/@akanjs/cli/src/package/package.runner.ts
|
|
4013
4698
|
var esbuild2 = __toESM(require("esbuild"));
|
|
4014
4699
|
var import_esbuild_plugin_d = require("esbuild-plugin-d.ts");
|
|
4015
|
-
var
|
|
4700
|
+
var import_fs11 = __toESM(require("fs"));
|
|
4016
4701
|
var import_promises3 = __toESM(require("fs/promises"));
|
|
4017
4702
|
var PackageRunner = class {
|
|
4018
4703
|
async version(workspace) {
|
|
@@ -4027,6 +4712,10 @@ var PackageRunner = class {
|
|
|
4027
4712
|
dict: { pkgName, PkgName: capitalize(pkgName) }
|
|
4028
4713
|
});
|
|
4029
4714
|
}
|
|
4715
|
+
async removePackage(pkg) {
|
|
4716
|
+
await pkg.workspace.exec(`rm -rf pkgs/${pkg.name}`);
|
|
4717
|
+
pkg.log(`Package ${pkg.name} removed`);
|
|
4718
|
+
}
|
|
4030
4719
|
async scanSync(pkg) {
|
|
4031
4720
|
const scanResult = await pkg.scan();
|
|
4032
4721
|
return scanResult;
|
|
@@ -4034,7 +4723,7 @@ var PackageRunner = class {
|
|
|
4034
4723
|
async buildPackage(pkg) {
|
|
4035
4724
|
const rootPackageJson = pkg.workspace.readJson("package.json");
|
|
4036
4725
|
const pkgJson = pkg.readJson("package.json");
|
|
4037
|
-
if (
|
|
4726
|
+
if (import_fs11.default.existsSync(pkg.dist.cwdPath))
|
|
4038
4727
|
await pkg.workspace.exec(`rm -rf ${pkg.dist.cwdPath}`);
|
|
4039
4728
|
let buildResult;
|
|
4040
4729
|
if (pkg.name === "@akanjs/config") {
|
|
@@ -4152,6 +4841,9 @@ var PackageScript = class {
|
|
|
4152
4841
|
async createPackage(workspace, pkgName) {
|
|
4153
4842
|
await this.#runner.createPackage(workspace, pkgName);
|
|
4154
4843
|
}
|
|
4844
|
+
async removePackage(pkg) {
|
|
4845
|
+
await this.#runner.removePackage(pkg);
|
|
4846
|
+
}
|
|
4155
4847
|
async scanPackage(pkg) {
|
|
4156
4848
|
const scanResult = await this.#runner.scanSync(pkg);
|
|
4157
4849
|
pkg.logger.rawLog(JSON.stringify(scanResult, null, 2));
|
|
@@ -4163,7 +4855,7 @@ var PackageScript = class {
|
|
|
4163
4855
|
|
|
4164
4856
|
// pkgs/@akanjs/cli/src/cloud/cloud.runner.ts
|
|
4165
4857
|
var import_prompts7 = require("@inquirer/prompts");
|
|
4166
|
-
var
|
|
4858
|
+
var import_chalk2 = __toESM(require("chalk"));
|
|
4167
4859
|
var import_latest_version = __toESM(require("latest-version"));
|
|
4168
4860
|
var import_open2 = __toESM(require("open"));
|
|
4169
4861
|
var QRcode = __toESM(require("qrcode"));
|
|
@@ -4173,17 +4865,17 @@ var CloudRunner = class {
|
|
|
4173
4865
|
const config = getHostConfig();
|
|
4174
4866
|
const self = config.auth ? await getSelf(config.auth.token) : null;
|
|
4175
4867
|
if (self) {
|
|
4176
|
-
Logger.rawLog(
|
|
4868
|
+
Logger.rawLog(import_chalk2.default.green(`
|
|
4177
4869
|
\u2713 Already logged in akan cloud as ${self.nickname}
|
|
4178
4870
|
`));
|
|
4179
4871
|
return true;
|
|
4180
4872
|
}
|
|
4181
4873
|
const remoteId = (0, import_uuid.v4)();
|
|
4182
4874
|
const signinUrl = `${akanCloudClientUrl}/signin?remoteId=${remoteId}`;
|
|
4183
|
-
Logger.rawLog(
|
|
4184
|
-
${
|
|
4185
|
-
Logger.rawLog(
|
|
4186
|
-
Logger.rawLog(
|
|
4875
|
+
Logger.rawLog(import_chalk2.default.bold(`
|
|
4876
|
+
${import_chalk2.default.green("\u27A4")} Authentication Required`));
|
|
4877
|
+
Logger.rawLog(import_chalk2.default.dim("Please visit or click the following URL:"));
|
|
4878
|
+
Logger.rawLog(import_chalk2.default.cyan.underline(signinUrl) + "\n");
|
|
4187
4879
|
try {
|
|
4188
4880
|
const qrcode = await new Promise((resolve, reject) => {
|
|
4189
4881
|
QRcode.toString(signinUrl, { type: "terminal", small: true }, (err, data) => {
|
|
@@ -4194,11 +4886,11 @@ ${import_chalk.default.green("\u27A4")} Authentication Required`));
|
|
|
4194
4886
|
});
|
|
4195
4887
|
Logger.rawLog(qrcode);
|
|
4196
4888
|
await (0, import_open2.default)(signinUrl);
|
|
4197
|
-
Logger.rawLog(
|
|
4889
|
+
Logger.rawLog(import_chalk2.default.dim("Opening browser..."));
|
|
4198
4890
|
} catch {
|
|
4199
|
-
Logger.rawLog(
|
|
4891
|
+
Logger.rawLog(import_chalk2.default.yellow("Could not open browser. Please visit the URL manually."));
|
|
4200
4892
|
}
|
|
4201
|
-
Logger.rawLog(
|
|
4893
|
+
Logger.rawLog(import_chalk2.default.dim("Waiting for authentication..."));
|
|
4202
4894
|
const MAX_RETRY = 300;
|
|
4203
4895
|
for (let i = 0; i < MAX_RETRY; i++) {
|
|
4204
4896
|
const res = await fetch(`${akanCloudBackendUrl}/user/getRemoteAuthToken/${remoteId}`);
|
|
@@ -4206,30 +4898,38 @@ ${import_chalk.default.green("\u27A4")} Authentication Required`));
|
|
|
4206
4898
|
const self2 = jwt ? await getSelf(jwt) : null;
|
|
4207
4899
|
if (jwt && self2) {
|
|
4208
4900
|
setHostConfig(akanCloudHost, { auth: { token: jwt, self: self2 } });
|
|
4209
|
-
Logger.rawLog(
|
|
4210
|
-
Logger.rawLog(
|
|
4901
|
+
Logger.rawLog(import_chalk2.default.green(`\r\u2713 Authentication successful!`));
|
|
4902
|
+
Logger.rawLog(import_chalk2.default.green.bold(`
|
|
4211
4903
|
\u2728 Welcome aboard, ${self2.nickname}!`));
|
|
4212
|
-
Logger.rawLog(
|
|
4904
|
+
Logger.rawLog(import_chalk2.default.dim("You're now ready to use Akan CLI!\n"));
|
|
4213
4905
|
return true;
|
|
4214
4906
|
}
|
|
4215
4907
|
await sleep(2e3);
|
|
4216
4908
|
}
|
|
4217
|
-
throw new Error(
|
|
4909
|
+
throw new Error(import_chalk2.default.red("\u2716 Authentication timed out after 10 minutes. Please try again."));
|
|
4218
4910
|
}
|
|
4219
4911
|
logout() {
|
|
4220
4912
|
const config = getHostConfig();
|
|
4221
4913
|
if (config.auth) {
|
|
4222
4914
|
setHostConfig(akanCloudHost, {});
|
|
4223
|
-
Logger.rawLog(
|
|
4915
|
+
Logger.rawLog(import_chalk2.default.magenta.bold(`
|
|
4224
4916
|
\u{1F44B} Goodbye, ${config.auth.self.nickname}!`));
|
|
4225
|
-
Logger.rawLog(
|
|
4226
|
-
Logger.rawLog(
|
|
4227
|
-
Logger.rawLog(
|
|
4917
|
+
Logger.rawLog(import_chalk2.default.dim("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n"));
|
|
4918
|
+
Logger.rawLog(import_chalk2.default.cyan("You have been successfully logged out."));
|
|
4919
|
+
Logger.rawLog(import_chalk2.default.dim("Thank you for using Akan CLI. Come back soon! \u{1F31F}\n"));
|
|
4228
4920
|
} else {
|
|
4229
|
-
Logger.rawLog(
|
|
4230
|
-
Logger.rawLog(
|
|
4921
|
+
Logger.rawLog(import_chalk2.default.yellow.bold("\n\u26A0\uFE0F No active session found"));
|
|
4922
|
+
Logger.rawLog(import_chalk2.default.dim("You were not logged in to begin with\n"));
|
|
4231
4923
|
}
|
|
4232
4924
|
}
|
|
4925
|
+
async setLlm() {
|
|
4926
|
+
await AiSession.init({ useExisting: true });
|
|
4927
|
+
Logger.rawLog(import_chalk2.default.green("LLM model set successfully"));
|
|
4928
|
+
}
|
|
4929
|
+
resetLlm() {
|
|
4930
|
+
AiSession.setLlmConfig(null);
|
|
4931
|
+
Logger.rawLog(import_chalk2.default.green("LLM model reset successfully"));
|
|
4932
|
+
}
|
|
4233
4933
|
async getAkanPkgs(workspace) {
|
|
4234
4934
|
const pkgs = await workspace.getPkgs();
|
|
4235
4935
|
const akanPkgs = pkgs.filter((pkg) => pkg.startsWith("@akanjs/"));
|
|
@@ -4251,20 +4951,7 @@ ${import_chalk.default.green("\u27A4")} Authentication Required`));
|
|
|
4251
4951
|
const newPackageJsonStr = JSON.stringify({ ...packageJson, version: nextVersion }, null, 2);
|
|
4252
4952
|
workspace.writeFile(`pkgs/${library}/package.json`, newPackageJsonStr);
|
|
4253
4953
|
const distPackageJson = workspace.readJson(`dist/pkgs/${library}/package.json`);
|
|
4254
|
-
const newDistPackageJson = {
|
|
4255
|
-
...distPackageJson,
|
|
4256
|
-
// ...(distPackageJson.dependencies
|
|
4257
|
-
// ? {
|
|
4258
|
-
// dependencies: Object.fromEntries(
|
|
4259
|
-
// Object.entries(distPackageJson.dependencies).map(([key, value]) => [
|
|
4260
|
-
// key,
|
|
4261
|
-
// value.startsWith("^") ? value : `^${value}`,
|
|
4262
|
-
// ])
|
|
4263
|
-
// ),
|
|
4264
|
-
// }
|
|
4265
|
-
// : {}),
|
|
4266
|
-
version: nextVersion
|
|
4267
|
-
};
|
|
4954
|
+
const newDistPackageJson = { ...distPackageJson, version: nextVersion };
|
|
4268
4955
|
workspace.writeJson(`dist/pkgs/${library}/package.json`, newDistPackageJson);
|
|
4269
4956
|
}
|
|
4270
4957
|
const isDeployConfirmed = await (0, import_prompts7.confirm)({
|
|
@@ -4295,6 +4982,17 @@ var CloudScript = class {
|
|
|
4295
4982
|
logout() {
|
|
4296
4983
|
this.#runner.logout();
|
|
4297
4984
|
}
|
|
4985
|
+
async setLlm() {
|
|
4986
|
+
await this.#runner.setLlm();
|
|
4987
|
+
}
|
|
4988
|
+
resetLlm() {
|
|
4989
|
+
this.#runner.resetLlm();
|
|
4990
|
+
}
|
|
4991
|
+
async ask(question) {
|
|
4992
|
+
await AiSession.init();
|
|
4993
|
+
const session = new AiSession();
|
|
4994
|
+
await session.ask(question);
|
|
4995
|
+
}
|
|
4298
4996
|
async deployAkan(workspace) {
|
|
4299
4997
|
const akanPkgs = await this.#runner.getAkanPkgs(workspace);
|
|
4300
4998
|
await Promise.all(
|
|
@@ -4313,6 +5011,15 @@ var CloudCommand = class {
|
|
|
4313
5011
|
logout() {
|
|
4314
5012
|
this.cloudScript.logout();
|
|
4315
5013
|
}
|
|
5014
|
+
async setLlm() {
|
|
5015
|
+
await this.cloudScript.setLlm();
|
|
5016
|
+
}
|
|
5017
|
+
resetLlm() {
|
|
5018
|
+
this.cloudScript.resetLlm();
|
|
5019
|
+
}
|
|
5020
|
+
async ask(question) {
|
|
5021
|
+
await this.cloudScript.ask(question);
|
|
5022
|
+
}
|
|
4316
5023
|
async deployAkan(workspace) {
|
|
4317
5024
|
await this.cloudScript.deployAkan(workspace);
|
|
4318
5025
|
}
|
|
@@ -4323,6 +5030,16 @@ __decorateClass([
|
|
|
4323
5030
|
__decorateClass([
|
|
4324
5031
|
Target.Public()
|
|
4325
5032
|
], CloudCommand.prototype, "logout", 1);
|
|
5033
|
+
__decorateClass([
|
|
5034
|
+
Target.Public()
|
|
5035
|
+
], CloudCommand.prototype, "setLlm", 1);
|
|
5036
|
+
__decorateClass([
|
|
5037
|
+
Target.Public()
|
|
5038
|
+
], CloudCommand.prototype, "resetLlm", 1);
|
|
5039
|
+
__decorateClass([
|
|
5040
|
+
Target.Public(),
|
|
5041
|
+
__decorateParam(0, Option("question", { ask: "question to ask" }))
|
|
5042
|
+
], CloudCommand.prototype, "ask", 1);
|
|
4326
5043
|
__decorateClass([
|
|
4327
5044
|
Target.Public({ devOnly: true }),
|
|
4328
5045
|
__decorateParam(0, Workspace())
|
|
@@ -4335,8 +5052,10 @@ CloudCommand = __decorateClass([
|
|
|
4335
5052
|
var LibraryCommand = class {
|
|
4336
5053
|
libraryScript = new LibraryScript();
|
|
4337
5054
|
async createLibrary(name, workspace) {
|
|
5055
|
+
await this.libraryScript.createLibrary(name, workspace);
|
|
4338
5056
|
}
|
|
4339
|
-
async removeLibrary(lib
|
|
5057
|
+
async removeLibrary(lib) {
|
|
5058
|
+
await this.libraryScript.removeLibrary(lib);
|
|
4340
5059
|
}
|
|
4341
5060
|
async scanLibrary(lib) {
|
|
4342
5061
|
await this.libraryScript.scanLibrary(lib, true);
|
|
@@ -4360,8 +5079,7 @@ __decorateClass([
|
|
|
4360
5079
|
], LibraryCommand.prototype, "createLibrary", 1);
|
|
4361
5080
|
__decorateClass([
|
|
4362
5081
|
Target.Public(),
|
|
4363
|
-
__decorateParam(0, Lib())
|
|
4364
|
-
__decorateParam(1, Workspace())
|
|
5082
|
+
__decorateParam(0, Lib())
|
|
4365
5083
|
], LibraryCommand.prototype, "removeLibrary", 1);
|
|
4366
5084
|
__decorateClass([
|
|
4367
5085
|
Target.Public(),
|
|
@@ -4390,8 +5108,11 @@ LibraryCommand = __decorateClass([
|
|
|
4390
5108
|
Commands()
|
|
4391
5109
|
], LibraryCommand);
|
|
4392
5110
|
|
|
5111
|
+
// pkgs/@akanjs/cli/src/module/module.script.ts
|
|
5112
|
+
var import_prompts8 = require("@inquirer/prompts");
|
|
5113
|
+
var import_fs12 = __toESM(require("fs"));
|
|
5114
|
+
|
|
4393
5115
|
// pkgs/@akanjs/cli/src/module/module.runner.ts
|
|
4394
|
-
var import_fs14 = __toESM(require("fs"));
|
|
4395
5116
|
var ModuleRunner = class {
|
|
4396
5117
|
async createModule(workspace, sysType, sysName, moduleName, description) {
|
|
4397
5118
|
}
|
|
@@ -4469,56 +5190,64 @@ var ModuleRunner = class {
|
|
|
4469
5190
|
}
|
|
4470
5191
|
};
|
|
4471
5192
|
}
|
|
4472
|
-
async createUnit(
|
|
4473
|
-
|
|
4474
|
-
|
|
4475
|
-
|
|
4476
|
-
|
|
4477
|
-
|
|
4478
|
-
|
|
4479
|
-
|
|
4480
|
-
|
|
4481
|
-
\`\`\`
|
|
4482
|
-
${
|
|
4483
|
-
\`\`\`
|
|
4484
|
-
|
|
4485
|
-
|
|
4486
|
-
|
|
4487
|
-
${
|
|
4488
|
-
|
|
4489
|
-
|
|
4490
|
-
|
|
4491
|
-
|
|
4492
|
-
|
|
4493
|
-
|
|
4494
|
-
|
|
4495
|
-
|
|
4496
|
-
|
|
4497
|
-
|
|
4498
|
-
|
|
4499
|
-
|
|
4500
|
-
|
|
4501
|
-
|
|
4502
|
-
|
|
4503
|
-
|
|
4504
|
-
|
|
4505
|
-
|
|
4506
|
-
|
|
4507
|
-
|
|
4508
|
-
|
|
4509
|
-
|
|
4510
|
-
|
|
4511
|
-
|
|
4512
|
-
|
|
4513
|
-
|
|
4514
|
-
|
|
4515
|
-
|
|
4516
|
-
|
|
4517
|
-
|
|
4518
|
-
|
|
4519
|
-
}
|
|
4520
|
-
|
|
4521
|
-
|
|
5193
|
+
// async createUnit(sys: App | Lib, modelName: string) {
|
|
5194
|
+
// const modelFileData = getModelFileData(sys.cwdPath, modelName);
|
|
5195
|
+
// const { paths } = getRelatedCnsts(modelFileData.constantFilePath);
|
|
5196
|
+
// const names = { model: modelName, Model: capitalize(modelName), LightModel: `Light${capitalize(modelName)}` };
|
|
5197
|
+
// const prompt = `
|
|
5198
|
+
// 너는 React, Typescript, TailwindCSS를 기반으로 코딩하는 프론트엔드 개발자야.
|
|
5199
|
+
// ${names.Model}이라는 도메인에 대해서 ${names.LightModel} 스키마를 대상으로 react component를 디자인하려고 해. 아래는 현재 보일러플레이트 형태의 컴포넌트야.
|
|
5200
|
+
// \`\`\`
|
|
5201
|
+
// ${modelFileData.unitFileStr}
|
|
5202
|
+
// \`\`\`
|
|
5203
|
+
// ${names.LightModel}은 다음과 같이 ${names.Model} 스키마에서 일부 필드를 추출해서 lightweight fetch된 형태로 설계되어있어.
|
|
5204
|
+
// \`\`\`
|
|
5205
|
+
// ${modelFileData.constantFileStr}
|
|
5206
|
+
// \`\`\`
|
|
5207
|
+
// 아래는 현재 스키마와 연관된 스키마 파일들이야. 스키마 파일들의 코드들을 보고 서로 어떻게 연계 되어있는지 이해하도록 해.
|
|
5208
|
+
// ${
|
|
5209
|
+
// paths
|
|
5210
|
+
// ? new Array(paths.size).fill(0).map((_, index) => {
|
|
5211
|
+
// //순서대로 paths key 추출
|
|
5212
|
+
// const key = Array.from(paths.keys())[index];
|
|
5213
|
+
// const filePath = paths.get(key)?.filePath;
|
|
5214
|
+
// if (!filePath) throw new Error("filePath is undefined");
|
|
5215
|
+
// return `${key}\n\`\`\`${fs.readFileSync(filePath, "utf8")}\`\`\`\`\n\n`;
|
|
5216
|
+
// })
|
|
5217
|
+
// : ""
|
|
5218
|
+
// }
|
|
5219
|
+
// 추가로, 만약에 아이콘 사용이 필요하면 react-icons/bi 라이브러리에서 사용해줘.
|
|
5220
|
+
// 또, 색상을 사용하려고 하면 하드코딩된 색상(bg-red)이 아닌 테마 색상(bg-primary)을 사용해서 작성해줘.
|
|
5221
|
+
// 그리고 optional한 필드는 field && <div>... 가 아닌, field ? <div>... : null 형태로 작성해줘.
|
|
5222
|
+
// css라이브러리는 DaisyUI를 기반으로 작성해주는데, btn, input, badge와 같은 단순한 기본 css는 사용해도 괜찮아. 그런데 card, hero같이 복잡한 컴포넌트는 사용하면 안돼.
|
|
5223
|
+
// 조건부 className이 필요한 경우에는 clsx 라이브러리를 사용해서 작성해야해.
|
|
5224
|
+
// 모델에 대해서 object destructuring은 하지말고 ${modelName}.field 형태로 접근하게 코드를 작성해야해.
|
|
5225
|
+
// ${names.Model}.Unit.Card의 리액트 컴포넌트를 디자인해서 작성해줘.
|
|
5226
|
+
// `;
|
|
5227
|
+
// try {
|
|
5228
|
+
// fs.writeFileSync("./local/prompt.txt", prompt);
|
|
5229
|
+
// const { content } = await streamAi(prompt, (chunk) => {
|
|
5230
|
+
// process.stdout.write(chunk);
|
|
5231
|
+
// });
|
|
5232
|
+
// fs.writeFileSync("./local/result.txt", content);
|
|
5233
|
+
// } catch (error) {
|
|
5234
|
+
// // console.error("Application error:", error);
|
|
5235
|
+
// }
|
|
5236
|
+
// }
|
|
5237
|
+
// async createView(sys: App | Lib, modelName: string) {
|
|
5238
|
+
// const modelFileData = getModelFileData(sys.cwdPath, modelName);
|
|
5239
|
+
// // const modelFileData = getModelFileData(sys.cwdPath, modelName);
|
|
5240
|
+
// // const { paths } = getRelatedCnsts(modelFileData.constantFilePath);
|
|
5241
|
+
// // const names = { model: modelName, Model: capitalize(modelName), LightModel: `Light${capitalize(modelName)}` };
|
|
5242
|
+
// // const prompt = prompt.requestView({
|
|
5243
|
+
// // sysName: sys.name,
|
|
5244
|
+
// // modelName,
|
|
5245
|
+
// // modelDesc: modelFileData.modelDesc,
|
|
5246
|
+
// // modelSchemaDesign: modelFileData.modelSchemaDesign,
|
|
5247
|
+
// // boilerplate: modelFileData.viewFileStr,
|
|
5248
|
+
// // paths,
|
|
5249
|
+
// // });
|
|
5250
|
+
// }
|
|
4522
5251
|
};
|
|
4523
5252
|
|
|
4524
5253
|
// pkgs/@akanjs/cli/src/module/module.script.ts
|
|
@@ -4563,38 +5292,67 @@ var ModuleScript = class {
|
|
|
4563
5292
|
}
|
|
4564
5293
|
async createTest(workspace, name) {
|
|
4565
5294
|
}
|
|
4566
|
-
async createUnit(
|
|
4567
|
-
const
|
|
4568
|
-
await
|
|
5295
|
+
async createUnit(sys2) {
|
|
5296
|
+
const libs = await sys2.getModules();
|
|
5297
|
+
const unitExampleFiles = await sys2.getUnitsSourceCode();
|
|
5298
|
+
const lib = await (0, import_prompts8.select)({
|
|
5299
|
+
message: "Select the lib",
|
|
5300
|
+
choices: libs
|
|
5301
|
+
}).catch((e) => {
|
|
5302
|
+
Logger.error("canceled");
|
|
5303
|
+
return null;
|
|
5304
|
+
});
|
|
5305
|
+
if (!lib)
|
|
5306
|
+
return;
|
|
5307
|
+
const name = lib.split("/").pop();
|
|
5308
|
+
if (!name)
|
|
5309
|
+
return;
|
|
5310
|
+
const Name = capitalize(name);
|
|
5311
|
+
const relatedCnsts = getRelatedCnsts(`${sys2.cwdPath}/lib/${name}/${name}.constant.ts`);
|
|
5312
|
+
const constant = import_fs12.default.readFileSync(`${sys2.cwdPath}/lib/${name}/${name}.constant.ts`, "utf-8");
|
|
5313
|
+
const session = new AiSession();
|
|
5314
|
+
const promptRst = requestView({
|
|
5315
|
+
sysName: sys2.name,
|
|
5316
|
+
modelName: name,
|
|
5317
|
+
ModelName: Name,
|
|
5318
|
+
constant,
|
|
5319
|
+
properties: relatedCnsts.map((r) => ({ key: r.key, source: r.source })),
|
|
5320
|
+
exampleFiles: randomPicks(unitExampleFiles, Math.min(10, unitExampleFiles.length))
|
|
5321
|
+
});
|
|
5322
|
+
const content = await session.editTypescript(promptRst);
|
|
5323
|
+
import_fs12.default.writeFileSync(`${sys2.cwdPath}/prompt.txt`, promptRst);
|
|
5324
|
+
import_fs12.default.writeFileSync(`${sys2.cwdPath}/result.txt`, content);
|
|
4569
5325
|
}
|
|
4570
5326
|
async createView(sys2) {
|
|
4571
|
-
const
|
|
4572
|
-
const
|
|
4573
|
-
|
|
4574
|
-
|
|
4575
|
-
|
|
4576
|
-
|
|
4577
|
-
|
|
4578
|
-
|
|
4579
|
-
|
|
4580
|
-
|
|
4581
|
-
|
|
4582
|
-
|
|
4583
|
-
|
|
4584
|
-
|
|
4585
|
-
|
|
4586
|
-
|
|
4587
|
-
|
|
4588
|
-
|
|
4589
|
-
|
|
4590
|
-
|
|
4591
|
-
|
|
4592
|
-
|
|
4593
|
-
|
|
4594
|
-
|
|
4595
|
-
|
|
4596
|
-
|
|
4597
|
-
|
|
5327
|
+
const libs = await sys2.getModules();
|
|
5328
|
+
const lib = await (0, import_prompts8.select)({
|
|
5329
|
+
message: "Select the lib",
|
|
5330
|
+
choices: libs
|
|
5331
|
+
}).catch((e) => {
|
|
5332
|
+
Logger.error("canceled");
|
|
5333
|
+
return null;
|
|
5334
|
+
});
|
|
5335
|
+
if (!lib)
|
|
5336
|
+
return;
|
|
5337
|
+
const name = lib.split("/").pop();
|
|
5338
|
+
if (!name)
|
|
5339
|
+
return;
|
|
5340
|
+
const viewExampleFiles = (await sys2.getViewsSourceCode()).filter((f) => f.filepath.includes(`${name}.View.tsx`));
|
|
5341
|
+
const Name = capitalize(name);
|
|
5342
|
+
const relatedCnsts = getRelatedCnsts(`${sys2.cwdPath}/lib/${name}/${name}.constant.ts`);
|
|
5343
|
+
const constant = import_fs12.default.readFileSync(`${sys2.cwdPath}/lib/${name}/${name}.constant.ts`, "utf-8");
|
|
5344
|
+
const session = new AiSession();
|
|
5345
|
+
const promptRst = requestView({
|
|
5346
|
+
sysName: sys2.name,
|
|
5347
|
+
modelName: name,
|
|
5348
|
+
ModelName: Name,
|
|
5349
|
+
constant,
|
|
5350
|
+
properties: relatedCnsts.map((r) => ({ key: r.key, source: r.source })),
|
|
5351
|
+
exampleFiles: randomPicks(viewExampleFiles, Math.min(20, viewExampleFiles.length))
|
|
5352
|
+
});
|
|
5353
|
+
const content = await session.editTypescript(promptRst);
|
|
5354
|
+
import_fs12.default.writeFileSync(`${sys2.cwdPath}/prompt.txt`, promptRst);
|
|
5355
|
+
import_fs12.default.writeFileSync(`${sys2.cwdPath}/result.txt`, content);
|
|
4598
5356
|
}
|
|
4599
5357
|
};
|
|
4600
5358
|
|
|
@@ -4677,7 +5435,8 @@ var PackageCommand = class {
|
|
|
4677
5435
|
async createPackage(name, workspace) {
|
|
4678
5436
|
await this.packageScript.createPackage(workspace, name);
|
|
4679
5437
|
}
|
|
4680
|
-
async removePackage(
|
|
5438
|
+
async removePackage(pkg) {
|
|
5439
|
+
await this.packageScript.removePackage(pkg);
|
|
4681
5440
|
}
|
|
4682
5441
|
async scanPackage(pkg) {
|
|
4683
5442
|
await this.packageScript.scanPackage(pkg);
|
|
@@ -4697,8 +5456,7 @@ __decorateClass([
|
|
|
4697
5456
|
], PackageCommand.prototype, "createPackage", 1);
|
|
4698
5457
|
__decorateClass([
|
|
4699
5458
|
Target.Public(),
|
|
4700
|
-
__decorateParam(0,
|
|
4701
|
-
__decorateParam(1, Workspace())
|
|
5459
|
+
__decorateParam(0, Pkg())
|
|
4702
5460
|
], PackageCommand.prototype, "removePackage", 1);
|
|
4703
5461
|
__decorateClass([
|
|
4704
5462
|
Target.Public(),
|
|
@@ -4712,13 +5470,13 @@ PackageCommand = __decorateClass([
|
|
|
4712
5470
|
Commands()
|
|
4713
5471
|
], PackageCommand);
|
|
4714
5472
|
|
|
4715
|
-
// pkgs/@akanjs/cli/src/
|
|
5473
|
+
// pkgs/@akanjs/cli/src/page/page.runner.ts
|
|
4716
5474
|
var PageRunner = class {
|
|
4717
5475
|
async createPage(app, name) {
|
|
4718
5476
|
}
|
|
4719
5477
|
};
|
|
4720
5478
|
|
|
4721
|
-
// pkgs/@akanjs/cli/src/
|
|
5479
|
+
// pkgs/@akanjs/cli/src/page/page.script.ts
|
|
4722
5480
|
var PageScript = class {
|
|
4723
5481
|
#runner = new PageRunner();
|
|
4724
5482
|
async createPage(app, name) {
|
|
@@ -4726,7 +5484,7 @@ var PageScript = class {
|
|
|
4726
5484
|
}
|
|
4727
5485
|
};
|
|
4728
5486
|
|
|
4729
|
-
// pkgs/@akanjs/cli/src/
|
|
5487
|
+
// pkgs/@akanjs/cli/src/page/page.command.ts
|
|
4730
5488
|
var PageCommand = class {
|
|
4731
5489
|
pageScript = new PageScript();
|
|
4732
5490
|
async createPage(app, name) {
|
|
@@ -4868,8 +5626,8 @@ var WorkspaceCommand = class {
|
|
|
4868
5626
|
};
|
|
4869
5627
|
__decorateClass([
|
|
4870
5628
|
Target.Public(),
|
|
4871
|
-
__decorateParam(0, Option("name", { desc: "name of
|
|
4872
|
-
__decorateParam(1, Option("app", { desc: "application
|
|
5629
|
+
__decorateParam(0, Option("name", { desc: "what is the name of your organization?" })),
|
|
5630
|
+
__decorateParam(1, Option("app", { desc: "describe your first application to create." })),
|
|
4873
5631
|
__decorateParam(2, Option("dir", { desc: "directory of workspace", default: process.env.USE_AKANJS_PKGS === "true" ? "local" : "." }))
|
|
4874
5632
|
], WorkspaceCommand.prototype, "createWorkspace", 1);
|
|
4875
5633
|
__decorateClass([
|
|
@@ -4891,7 +5649,6 @@ void runCommands(
|
|
|
4891
5649
|
PageCommand,
|
|
4892
5650
|
CloudCommand
|
|
4893
5651
|
);
|
|
4894
|
-
//!Field.Prop 거르기가 빡세네.
|
|
4895
5652
|
//! Temp
|
|
4896
5653
|
//! zip 명령어는 압축시 폴더 경로를 무시하는 게 안됨
|
|
4897
5654
|
//! 두 가지 방법이 있음
|
|
@@ -4900,3 +5657,4 @@ void runCommands(
|
|
|
4900
5657
|
//! execSync를 가져오기 싫으니 일단 2번 방법으로 해보자
|
|
4901
5658
|
//! add path in tsconfig.json
|
|
4902
5659
|
//! Temporary fix for barrel library
|
|
5660
|
+
//! 파일을 {name}.View.tsx에 저장.
|