@lark-apaas/fullstack-cli 1.1.22-alpha.24 → 1.1.22-alpha.26
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/dist/gen-dbschema-template/types.ts +0 -96
- package/dist/index.js +191 -28
- package/package.json +1 -1
- package/templates/nest-cli.json +1 -1
- package/templates/scripts/build.sh +25 -6
|
@@ -120,100 +120,4 @@ export const customTimestamptz = customType<{
|
|
|
120
120
|
if(value instanceof Date) return value;
|
|
121
121
|
return new Date(value);
|
|
122
122
|
},
|
|
123
|
-
});
|
|
124
|
-
|
|
125
|
-
/**
|
|
126
|
-
* User type marker for user_profile_domain
|
|
127
|
-
* Simple marker type, no conversion needed - passes through as string
|
|
128
|
-
*/
|
|
129
|
-
export const userType = customType<{
|
|
130
|
-
data: string;
|
|
131
|
-
driverData: string;
|
|
132
|
-
}>({
|
|
133
|
-
dataType() {
|
|
134
|
-
return 'user_profile_domain';
|
|
135
|
-
},
|
|
136
|
-
toDriver(value: string) {
|
|
137
|
-
return value;
|
|
138
|
-
},
|
|
139
|
-
fromDriver(value: string) {
|
|
140
|
-
return value;
|
|
141
|
-
},
|
|
142
|
-
});
|
|
143
|
-
|
|
144
|
-
/**
|
|
145
|
-
* File type marker for file_attachment_domain
|
|
146
|
-
* Simple marker type, no conversion needed - passes through as string
|
|
147
|
-
*/
|
|
148
|
-
export const fileType = customType<{
|
|
149
|
-
data: string;
|
|
150
|
-
driverData: string;
|
|
151
|
-
}>({
|
|
152
|
-
dataType() {
|
|
153
|
-
return 'file_attachment_domain';
|
|
154
|
-
},
|
|
155
|
-
toDriver(value: string) {
|
|
156
|
-
return value;
|
|
157
|
-
},
|
|
158
|
-
fromDriver(value: string) {
|
|
159
|
-
return value;
|
|
160
|
-
},
|
|
161
|
-
});
|
|
162
|
-
|
|
163
|
-
/**
|
|
164
|
-
* User type array for user_profile_domain[]
|
|
165
|
-
*/
|
|
166
|
-
export const userTypeArray = customType<{
|
|
167
|
-
data: string[];
|
|
168
|
-
driverData: string;
|
|
169
|
-
}>({
|
|
170
|
-
dataType() {
|
|
171
|
-
return 'user_profile_domain[]';
|
|
172
|
-
},
|
|
173
|
-
toDriver(value: string[]) {
|
|
174
|
-
return sql`${value}`;
|
|
175
|
-
},
|
|
176
|
-
fromDriver(value: string): string[] {
|
|
177
|
-
if (!value || value === '{}') return [];
|
|
178
|
-
// Parse PostgreSQL array format: {"item1","item2"}
|
|
179
|
-
const inner = value.slice(1, -1);
|
|
180
|
-
if (!inner) return [];
|
|
181
|
-
return inner.split(',').map(item => {
|
|
182
|
-
// Handle quoted strings
|
|
183
|
-
const trimmed = item.trim();
|
|
184
|
-
if (trimmed.startsWith('"') && trimmed.endsWith('"')) {
|
|
185
|
-
return trimmed.slice(1, -1).replace(/\\"/g, '"');
|
|
186
|
-
}
|
|
187
|
-
return trimmed;
|
|
188
|
-
});
|
|
189
|
-
},
|
|
190
|
-
});
|
|
191
|
-
|
|
192
|
-
/**
|
|
193
|
-
* File type array for file_attachment_domain[]
|
|
194
|
-
*/
|
|
195
|
-
export const fileTypeArray = customType<{
|
|
196
|
-
data: string[];
|
|
197
|
-
driverData: string;
|
|
198
|
-
}>({
|
|
199
|
-
dataType() {
|
|
200
|
-
return 'file_attachment_domain[]';
|
|
201
|
-
},
|
|
202
|
-
toDriver(value: string[]) {
|
|
203
|
-
return sql`${value}`;
|
|
204
|
-
},
|
|
205
|
-
fromDriver(value: string): string[] {
|
|
206
|
-
if (!value || value === '{}') return [];
|
|
207
|
-
// Parse PostgreSQL array format: {"item1","item2"}
|
|
208
|
-
const inner = value.slice(1, -1);
|
|
209
|
-
if (!inner) return [];
|
|
210
|
-
return inner.split(',').map(item => {
|
|
211
|
-
// Handle quoted strings
|
|
212
|
-
const trimmed = item.trim();
|
|
213
|
-
if (trimmed.startsWith('"') && trimmed.endsWith('"')) {
|
|
214
|
-
return trimmed.slice(1, -1).replace(/\\"/g, '"');
|
|
215
|
-
}
|
|
216
|
-
return trimmed;
|
|
217
|
-
});
|
|
218
|
-
},
|
|
219
123
|
});
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// src/index.ts
|
|
2
|
-
import
|
|
3
|
-
import
|
|
2
|
+
import fs26 from "fs";
|
|
3
|
+
import path22 from "path";
|
|
4
4
|
import { fileURLToPath as fileURLToPath5 } from "url";
|
|
5
5
|
import { config as dotenvConfig } from "dotenv";
|
|
6
6
|
|
|
@@ -469,18 +469,8 @@ var patchDefectsTransform = {
|
|
|
469
469
|
// src/commands/db/gen-dbschema/transforms/ast/replace-unknown.ts
|
|
470
470
|
import { Node as Node5 } from "ts-morph";
|
|
471
471
|
var KNOWN_TYPE_FACTORIES = {
|
|
472
|
-
// Domain types (new)
|
|
473
|
-
user_profile_domain: "userType",
|
|
474
|
-
file_attachment_domain: "fileType",
|
|
475
|
-
// Domain array types (new)
|
|
476
|
-
"user_profile_domain[]": "userTypeArray",
|
|
477
|
-
"file_attachment_domain[]": "fileTypeArray",
|
|
478
|
-
// Legacy composite types (deprecated but kept for compatibility)
|
|
479
472
|
user_profile: "userProfile",
|
|
480
|
-
file_attachment: "fileAttachment"
|
|
481
|
-
// Legacy array types
|
|
482
|
-
"user_profile[]": "userProfile",
|
|
483
|
-
"file_attachment[]": "fileAttachment"
|
|
473
|
+
file_attachment: "fileAttachment"
|
|
484
474
|
};
|
|
485
475
|
var KNOWN_ARRAY_TYPE_FACTORIES = {
|
|
486
476
|
user_profile: "userProfileArray",
|
|
@@ -510,11 +500,10 @@ var replaceUnknownTransform = {
|
|
|
510
500
|
const line = lines[i];
|
|
511
501
|
const todoMatch = line.match(/\/\/ TODO: failed to parse database type '(?:\w+\.)?([\w_]+)(\[\])?'/);
|
|
512
502
|
if (todoMatch) {
|
|
513
|
-
const
|
|
503
|
+
const typeName = todoMatch[1];
|
|
514
504
|
isArrayType = todoMatch[2] === "[]";
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
factoryName = KNOWN_ARRAY_TYPE_FACTORIES[baseTypeName];
|
|
505
|
+
if (isArrayType && KNOWN_ARRAY_TYPE_FACTORIES[typeName]) {
|
|
506
|
+
factoryName = KNOWN_ARRAY_TYPE_FACTORIES[typeName];
|
|
518
507
|
foundKnownType = true;
|
|
519
508
|
} else if (KNOWN_TYPE_FACTORIES[typeName]) {
|
|
520
509
|
factoryName = KNOWN_TYPE_FACTORIES[typeName];
|
|
@@ -4296,7 +4285,7 @@ var PROMPT_PATTERNS = [
|
|
|
4296
4285
|
{ pattern: /proceed\?/i, answer: "y\n" }
|
|
4297
4286
|
];
|
|
4298
4287
|
async function executeShadcnAdd(registryItemPath) {
|
|
4299
|
-
return new Promise((
|
|
4288
|
+
return new Promise((resolve2) => {
|
|
4300
4289
|
let output = "";
|
|
4301
4290
|
const args = ["--yes", "shadcn@3.8.2", "add", registryItemPath];
|
|
4302
4291
|
const ptyProcess = pty.spawn("npx", args, {
|
|
@@ -4322,7 +4311,7 @@ async function executeShadcnAdd(registryItemPath) {
|
|
|
4322
4311
|
});
|
|
4323
4312
|
const timeoutId = setTimeout(() => {
|
|
4324
4313
|
ptyProcess.kill();
|
|
4325
|
-
|
|
4314
|
+
resolve2({
|
|
4326
4315
|
success: false,
|
|
4327
4316
|
files: [],
|
|
4328
4317
|
error: "\u6267\u884C\u8D85\u65F6"
|
|
@@ -4333,7 +4322,7 @@ async function executeShadcnAdd(registryItemPath) {
|
|
|
4333
4322
|
const success = exitCode === 0;
|
|
4334
4323
|
const filePaths = parseOutput(output);
|
|
4335
4324
|
const files = filePaths.map(toFileInfo);
|
|
4336
|
-
|
|
4325
|
+
resolve2({
|
|
4337
4326
|
success,
|
|
4338
4327
|
files,
|
|
4339
4328
|
error: success ? void 0 : output || `Process exited with code ${exitCode}`
|
|
@@ -4344,12 +4333,12 @@ async function executeShadcnAdd(registryItemPath) {
|
|
|
4344
4333
|
|
|
4345
4334
|
// src/commands/component/add.handler.ts
|
|
4346
4335
|
function runActionPluginInit() {
|
|
4347
|
-
return new Promise((
|
|
4336
|
+
return new Promise((resolve2) => {
|
|
4348
4337
|
execFile("fullstack-cli", ["action-plugin", "init"], { cwd: process.cwd(), stdio: "ignore" }, (error) => {
|
|
4349
4338
|
if (error) {
|
|
4350
4339
|
debug("action-plugin init \u5931\u8D25: %s", error.message);
|
|
4351
4340
|
}
|
|
4352
|
-
|
|
4341
|
+
resolve2();
|
|
4353
4342
|
});
|
|
4354
4343
|
});
|
|
4355
4344
|
}
|
|
@@ -7185,7 +7174,45 @@ async function genArtifactUploadCredential(appId, body) {
|
|
|
7185
7174
|
const response = await client.post(url, body);
|
|
7186
7175
|
if (!response.ok || response.status !== 200) {
|
|
7187
7176
|
throw new Error(
|
|
7188
|
-
`
|
|
7177
|
+
`gen_artifact_upload_credential \u8BF7\u6C42\u5931\u8D25: ${response.status} ${response.statusText}`
|
|
7178
|
+
);
|
|
7179
|
+
}
|
|
7180
|
+
return response.json();
|
|
7181
|
+
}
|
|
7182
|
+
async function getDefaultBucketId(appId) {
|
|
7183
|
+
const client = getHttpClient();
|
|
7184
|
+
const url = `/b/${appId}/get_published_v2`;
|
|
7185
|
+
const response = await client.get(url);
|
|
7186
|
+
if (!response.ok || response.status !== 200) {
|
|
7187
|
+
throw new Error(
|
|
7188
|
+
`get_published_v2 \u8BF7\u6C42\u5931\u8D25: ${response.status} ${response.statusText}`
|
|
7189
|
+
);
|
|
7190
|
+
}
|
|
7191
|
+
const data = await response.json();
|
|
7192
|
+
const bucketId = data?.data?.app_runtime_extra?.bucket?.default_bucket_id;
|
|
7193
|
+
if (!bucketId) {
|
|
7194
|
+
throw new Error(`\u672A\u627E\u5230\u5E94\u7528 ${appId} \u7684\u9ED8\u8BA4\u5B58\u50A8\u6876`);
|
|
7195
|
+
}
|
|
7196
|
+
return bucketId;
|
|
7197
|
+
}
|
|
7198
|
+
async function preUploadStaticAttachment(appId, bucketId) {
|
|
7199
|
+
const client = getHttpClient();
|
|
7200
|
+
const url = `/v1/app/${appId}/storage/bucket/${bucketId}/preUploadStatic`;
|
|
7201
|
+
const response = await client.post(url, {});
|
|
7202
|
+
if (!response.ok || response.status !== 200) {
|
|
7203
|
+
throw new Error(
|
|
7204
|
+
`preUploadStatic \u8BF7\u6C42\u5931\u8D25: ${response.status} ${response.statusText}`
|
|
7205
|
+
);
|
|
7206
|
+
}
|
|
7207
|
+
return response.json();
|
|
7208
|
+
}
|
|
7209
|
+
async function uploadStaticAttachmentCallback(appId, bucketId, body) {
|
|
7210
|
+
const client = getHttpClient();
|
|
7211
|
+
const url = `/v1/app/${appId}/storage/bucket/${bucketId}/object/callbackStatic`;
|
|
7212
|
+
const response = await client.post(url, body);
|
|
7213
|
+
if (!response.ok || response.status !== 200) {
|
|
7214
|
+
throw new Error(
|
|
7215
|
+
`callbackStatic \u8BF7\u6C42\u5931\u8D25: ${response.status} ${response.statusText}`
|
|
7189
7216
|
);
|
|
7190
7217
|
}
|
|
7191
7218
|
return response.json();
|
|
@@ -7223,6 +7250,133 @@ function camelToKebab(str) {
|
|
|
7223
7250
|
return str.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase();
|
|
7224
7251
|
}
|
|
7225
7252
|
|
|
7253
|
+
// src/commands/build/upload-static.handler.ts
|
|
7254
|
+
import * as fs25 from "fs";
|
|
7255
|
+
import * as path21 from "path";
|
|
7256
|
+
import { execSync as execSync3 } from "child_process";
|
|
7257
|
+
var LOG_PREFIX = "[upload-static]";
|
|
7258
|
+
async function uploadStatic(options) {
|
|
7259
|
+
try {
|
|
7260
|
+
const {
|
|
7261
|
+
appId,
|
|
7262
|
+
staticDir = "shared/static",
|
|
7263
|
+
tosutilPath = "/workspace/tosutil",
|
|
7264
|
+
tosutilUrl,
|
|
7265
|
+
endpoint = "tos-cn-beijing.volces.com",
|
|
7266
|
+
region = "cn-beijing"
|
|
7267
|
+
} = options;
|
|
7268
|
+
const resolvedStaticDir = path21.resolve(staticDir);
|
|
7269
|
+
if (!fs25.existsSync(resolvedStaticDir)) {
|
|
7270
|
+
console.error(`${LOG_PREFIX} \u76EE\u5F55\u4E0D\u5B58\u5728: ${resolvedStaticDir}\uFF0C\u8DF3\u8FC7\u4E0A\u4F20`);
|
|
7271
|
+
return;
|
|
7272
|
+
}
|
|
7273
|
+
if (isDirEmpty(resolvedStaticDir)) {
|
|
7274
|
+
console.error(`${LOG_PREFIX} \u76EE\u5F55\u4E3A\u7A7A: ${resolvedStaticDir}\uFF0C\u8DF3\u8FC7\u4E0A\u4F20`);
|
|
7275
|
+
return;
|
|
7276
|
+
}
|
|
7277
|
+
const resolvedTosutilPath = ensureTosutil(tosutilPath, tosutilUrl);
|
|
7278
|
+
const bucketId = await resolveBucketId(appId);
|
|
7279
|
+
console.error(`${LOG_PREFIX} \u8C03\u7528 preUploadStatic...`);
|
|
7280
|
+
const preUploadResp = await fetchPreUpload(appId, bucketId);
|
|
7281
|
+
const { uploadPrefix, uploadID, uploadCredential } = preUploadResp.data;
|
|
7282
|
+
console.error(`${LOG_PREFIX} \u4E0A\u4F20\u76EE\u6807: ${uploadPrefix}`);
|
|
7283
|
+
console.error(`${LOG_PREFIX} \u914D\u7F6E tosutil...`);
|
|
7284
|
+
configureTosutil(resolvedTosutilPath, {
|
|
7285
|
+
endpoint,
|
|
7286
|
+
region,
|
|
7287
|
+
accessKeyID: uploadCredential.accessKeyID,
|
|
7288
|
+
secretAccessKey: uploadCredential.secretAccessKey,
|
|
7289
|
+
sessionToken: uploadCredential.sessionToken
|
|
7290
|
+
});
|
|
7291
|
+
console.error(`${LOG_PREFIX} \u4E0A\u4F20 ${resolvedStaticDir} -> ${uploadPrefix}`);
|
|
7292
|
+
uploadToTos(resolvedTosutilPath, resolvedStaticDir, uploadPrefix);
|
|
7293
|
+
console.error(`${LOG_PREFIX} tosutil \u4E0A\u4F20\u5B8C\u6210`);
|
|
7294
|
+
console.error(`${LOG_PREFIX} \u8C03\u7528 callbackStatic (uploadID: ${uploadID})...`);
|
|
7295
|
+
const callbackResp = await uploadStaticAttachmentCallback(appId, bucketId, { uploadID });
|
|
7296
|
+
if (callbackResp.status_code !== "0") {
|
|
7297
|
+
throw new Error(`callbackStatic \u8FD4\u56DE\u5F02\u5E38, status_code: ${callbackResp.status_code}`);
|
|
7298
|
+
}
|
|
7299
|
+
const attachments = callbackResp.data?.attachments || [];
|
|
7300
|
+
console.error(`${LOG_PREFIX} \u4E0A\u4F20\u5B8C\u6210\uFF0C\u5171 ${attachments.length} \u4E2A\u6587\u4EF6`);
|
|
7301
|
+
console.log(JSON.stringify(callbackResp));
|
|
7302
|
+
} catch (error) {
|
|
7303
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
7304
|
+
console.error(`${LOG_PREFIX} Error: ${message}`);
|
|
7305
|
+
process.exit(1);
|
|
7306
|
+
}
|
|
7307
|
+
}
|
|
7308
|
+
async function fetchPreUpload(appId, bucketId) {
|
|
7309
|
+
const response = await preUploadStaticAttachment(appId, bucketId);
|
|
7310
|
+
if (response.status_code !== "0") {
|
|
7311
|
+
throw new Error(`preUploadStatic \u8FD4\u56DE\u5F02\u5E38, status_code: ${response.status_code}`);
|
|
7312
|
+
}
|
|
7313
|
+
const { uploadPrefix, uploadID, uploadCredential } = response.data || {};
|
|
7314
|
+
if (!uploadPrefix || !uploadID) {
|
|
7315
|
+
throw new Error("preUploadStatic \u8FD4\u56DE\u6570\u636E\u4E0D\u5B8C\u6574\uFF0C\u7F3A\u5C11 uploadPrefix \u6216 uploadID");
|
|
7316
|
+
}
|
|
7317
|
+
if (!uploadCredential?.accessKeyID || !uploadCredential?.secretAccessKey || !uploadCredential?.sessionToken) {
|
|
7318
|
+
throw new Error("preUploadStatic \u8FD4\u56DE\u7684\u51ED\u8BC1\u5B57\u6BB5\u4E0D\u5B8C\u6574");
|
|
7319
|
+
}
|
|
7320
|
+
return response;
|
|
7321
|
+
}
|
|
7322
|
+
function ensureTosutil(tosutilPath, tosutilUrl) {
|
|
7323
|
+
if (isTosutilAvailable(tosutilPath)) {
|
|
7324
|
+
console.error(`${LOG_PREFIX} tosutil \u5DF2\u5C31\u7EEA: ${tosutilPath}`);
|
|
7325
|
+
return tosutilPath;
|
|
7326
|
+
}
|
|
7327
|
+
if (!tosutilUrl) {
|
|
7328
|
+
throw new Error(
|
|
7329
|
+
`tosutil \u4E0D\u53EF\u7528 (\u8DEF\u5F84: ${tosutilPath})\uFF0C\u4E14\u672A\u63D0\u4F9B --tosutil-url \u4E0B\u8F7D\u5730\u5740\u3002\u8BF7\u786E\u4FDD tosutil \u5DF2\u5B58\u5728\uFF0C\u6216\u901A\u8FC7 --tosutil-url \u6307\u5B9A\u4E0B\u8F7D\u5730\u5740\u3002`
|
|
7330
|
+
);
|
|
7331
|
+
}
|
|
7332
|
+
console.error(`${LOG_PREFIX} tosutil \u4E0D\u5B58\u5728\uFF0C\u4ECE ${tosutilUrl} \u4E0B\u8F7D...`);
|
|
7333
|
+
downloadTosutil(tosutilUrl, tosutilPath);
|
|
7334
|
+
if (!isTosutilAvailable(tosutilPath)) {
|
|
7335
|
+
throw new Error(`tosutil \u4E0B\u8F7D\u540E\u4ECD\u4E0D\u53EF\u7528 (\u8DEF\u5F84: ${tosutilPath})`);
|
|
7336
|
+
}
|
|
7337
|
+
console.error(`${LOG_PREFIX} tosutil \u4E0B\u8F7D\u5B8C\u6210: ${tosutilPath}`);
|
|
7338
|
+
return tosutilPath;
|
|
7339
|
+
}
|
|
7340
|
+
function isTosutilAvailable(tosutilPath) {
|
|
7341
|
+
try {
|
|
7342
|
+
execSync3(`${tosutilPath} --version`, { stdio: "pipe" });
|
|
7343
|
+
return true;
|
|
7344
|
+
} catch {
|
|
7345
|
+
return false;
|
|
7346
|
+
}
|
|
7347
|
+
}
|
|
7348
|
+
function downloadTosutil(url, destPath) {
|
|
7349
|
+
const destDir = path21.dirname(destPath);
|
|
7350
|
+
if (!fs25.existsSync(destDir)) {
|
|
7351
|
+
fs25.mkdirSync(destDir, { recursive: true });
|
|
7352
|
+
}
|
|
7353
|
+
execSync3(`curl -L --fail -o "${destPath}" "${url}"`, { stdio: "pipe" });
|
|
7354
|
+
execSync3(`chmod +x "${destPath}"`, { stdio: "pipe" });
|
|
7355
|
+
}
|
|
7356
|
+
function configureTosutil(tosutilPath, config) {
|
|
7357
|
+
const { endpoint, region, accessKeyID, secretAccessKey, sessionToken } = config;
|
|
7358
|
+
execSync3(
|
|
7359
|
+
`${tosutilPath} config -e ${endpoint} -i ${accessKeyID} -k ${secretAccessKey} -t ${sessionToken} -re ${region}`,
|
|
7360
|
+
{ stdio: "pipe" }
|
|
7361
|
+
);
|
|
7362
|
+
}
|
|
7363
|
+
function uploadToTos(tosutilPath, sourceDir, destUrl) {
|
|
7364
|
+
execSync3(
|
|
7365
|
+
`${tosutilPath} cp "${sourceDir}" "${destUrl}" -r -flat -j 5 -p 3 -ps 10485760 -f`,
|
|
7366
|
+
{ stdio: "inherit" }
|
|
7367
|
+
);
|
|
7368
|
+
}
|
|
7369
|
+
async function resolveBucketId(appId) {
|
|
7370
|
+
console.error(`${LOG_PREFIX} \u83B7\u53D6\u9ED8\u8BA4\u5B58\u50A8\u6876...`);
|
|
7371
|
+
const bucketId = await getDefaultBucketId(appId);
|
|
7372
|
+
console.error(`${LOG_PREFIX} \u9ED8\u8BA4\u5B58\u50A8\u6876: ${bucketId}`);
|
|
7373
|
+
return bucketId;
|
|
7374
|
+
}
|
|
7375
|
+
function isDirEmpty(dirPath) {
|
|
7376
|
+
const entries = fs25.readdirSync(dirPath);
|
|
7377
|
+
return entries.length === 0;
|
|
7378
|
+
}
|
|
7379
|
+
|
|
7226
7380
|
// src/commands/build/index.ts
|
|
7227
7381
|
var getTokenCommand = {
|
|
7228
7382
|
name: "get-token",
|
|
@@ -7233,10 +7387,19 @@ var getTokenCommand = {
|
|
|
7233
7387
|
});
|
|
7234
7388
|
}
|
|
7235
7389
|
};
|
|
7390
|
+
var uploadStaticCommand = {
|
|
7391
|
+
name: "upload-static",
|
|
7392
|
+
description: "Upload shared/static files to TOS",
|
|
7393
|
+
register(program) {
|
|
7394
|
+
program.command(this.name).description(this.description).requiredOption("--app-id <id>", "Application ID").option("--static-dir <dir>", "Static files directory", "shared/static").option("--tosutil-path <path>", "Path to tosutil binary", "/workspace/tosutil").option("--tosutil-url <url>", "URL to download tosutil if not present").option("--endpoint <endpoint>", "TOS endpoint", "tos-cn-beijing.volces.com").option("--region <region>", "TOS region", "cn-beijing").action(async (options) => {
|
|
7395
|
+
await uploadStatic(options);
|
|
7396
|
+
});
|
|
7397
|
+
}
|
|
7398
|
+
};
|
|
7236
7399
|
var buildCommandGroup = {
|
|
7237
7400
|
name: "build",
|
|
7238
7401
|
description: "Build related commands",
|
|
7239
|
-
commands: [getTokenCommand]
|
|
7402
|
+
commands: [getTokenCommand, uploadStaticCommand]
|
|
7240
7403
|
};
|
|
7241
7404
|
|
|
7242
7405
|
// src/commands/index.ts
|
|
@@ -7253,12 +7416,12 @@ var commands = [
|
|
|
7253
7416
|
];
|
|
7254
7417
|
|
|
7255
7418
|
// src/index.ts
|
|
7256
|
-
var envPath =
|
|
7257
|
-
if (
|
|
7419
|
+
var envPath = path22.join(process.cwd(), ".env");
|
|
7420
|
+
if (fs26.existsSync(envPath)) {
|
|
7258
7421
|
dotenvConfig({ path: envPath });
|
|
7259
7422
|
}
|
|
7260
|
-
var __dirname =
|
|
7261
|
-
var pkg = JSON.parse(
|
|
7423
|
+
var __dirname = path22.dirname(fileURLToPath5(import.meta.url));
|
|
7424
|
+
var pkg = JSON.parse(fs26.readFileSync(path22.join(__dirname, "../package.json"), "utf-8"));
|
|
7262
7425
|
var cli = new FullstackCLI(pkg.version);
|
|
7263
7426
|
cli.useAll(commands);
|
|
7264
7427
|
cli.run();
|
package/package.json
CHANGED
package/templates/nest-cli.json
CHANGED
|
@@ -19,28 +19,28 @@ print_time() {
|
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
# ==================== 步骤 0 ====================
|
|
22
|
-
echo "🗑️ [0/
|
|
22
|
+
echo "🗑️ [0/6] 安装插件"
|
|
23
23
|
STEP_START=$(node -e "console.log(Date.now())")
|
|
24
24
|
npx fullstack-cli action-plugin init
|
|
25
25
|
print_time $STEP_START
|
|
26
26
|
echo ""
|
|
27
27
|
|
|
28
28
|
# ==================== 步骤 1 ====================
|
|
29
|
-
echo "📝 [1/
|
|
29
|
+
echo "📝 [1/6] 更新 openapi 代码"
|
|
30
30
|
STEP_START=$(node -e "console.log(Date.now())")
|
|
31
31
|
npm run gen:openapi
|
|
32
32
|
print_time $STEP_START
|
|
33
33
|
echo ""
|
|
34
34
|
|
|
35
35
|
# ==================== 步骤 2 ====================
|
|
36
|
-
echo "🗑️ [2/
|
|
36
|
+
echo "🗑️ [2/6] 清理 dist 目录"
|
|
37
37
|
STEP_START=$(node -e "console.log(Date.now())")
|
|
38
38
|
rm -rf "$ROOT_DIR/dist"
|
|
39
39
|
print_time $STEP_START
|
|
40
40
|
echo ""
|
|
41
41
|
|
|
42
42
|
# ==================== 步骤 3 ====================
|
|
43
|
-
echo "🔨 [3/
|
|
43
|
+
echo "🔨 [3/6] 并行构建 server 和 client"
|
|
44
44
|
STEP_START=$(node -e "console.log(Date.now())")
|
|
45
45
|
|
|
46
46
|
# 并行构建
|
|
@@ -78,7 +78,7 @@ print_time $STEP_START
|
|
|
78
78
|
echo ""
|
|
79
79
|
|
|
80
80
|
# ==================== 步骤 4 ====================
|
|
81
|
-
echo "📦 [4/
|
|
81
|
+
echo "📦 [4/6] 准备 server 依赖产物"
|
|
82
82
|
STEP_START=$(node -e "console.log(Date.now())")
|
|
83
83
|
|
|
84
84
|
mkdir -p "$OUT_DIR/dist/client"
|
|
@@ -97,7 +97,7 @@ print_time $STEP_START
|
|
|
97
97
|
echo ""
|
|
98
98
|
|
|
99
99
|
# ==================== 步骤 5 ====================
|
|
100
|
-
echo "✂️ [5/
|
|
100
|
+
echo "✂️ [5/6] 智能依赖裁剪"
|
|
101
101
|
STEP_START=$(node -e "console.log(Date.now())")
|
|
102
102
|
|
|
103
103
|
# 分析实际依赖、复制并裁剪 node_modules、生成精简的 package.json
|
|
@@ -106,6 +106,25 @@ node "$ROOT_DIR/scripts/prune-smart.js"
|
|
|
106
106
|
print_time $STEP_START
|
|
107
107
|
echo ""
|
|
108
108
|
|
|
109
|
+
# ==================== 步骤 6 ====================
|
|
110
|
+
echo "☁️ [6/6] 上传静态资源到 TOS"
|
|
111
|
+
STEP_START=$(node -e "console.log(Date.now())")
|
|
112
|
+
|
|
113
|
+
# 环境变量(与产物上传脚本共享同一 CI 环境):
|
|
114
|
+
# app_id - 应用 ID
|
|
115
|
+
# tosutil_url - tosutil 下载地址
|
|
116
|
+
# bucket_id 由 CLI 自动通过 get_published_v2 获取,也可通过 --bucket-id 显式指定
|
|
117
|
+
if [ -d "$ROOT_DIR/shared/static" ] && [ "$(ls -A "$ROOT_DIR/shared/static" 2>/dev/null)" ]; then
|
|
118
|
+
npx fullstack-cli build upload-static \
|
|
119
|
+
--app-id "${app_id}" \
|
|
120
|
+
--tosutil-url "${tosutil_url}"
|
|
121
|
+
else
|
|
122
|
+
echo " ⏭️ shared/static 目录为空或不存在,跳过上传"
|
|
123
|
+
fi
|
|
124
|
+
|
|
125
|
+
print_time $STEP_START
|
|
126
|
+
echo ""
|
|
127
|
+
|
|
109
128
|
# 总耗时
|
|
110
129
|
echo "构建完成"
|
|
111
130
|
print_time $TOTAL_START
|