create-asaje-go-vue 0.3.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +17 -0
- package/bin/create-asaje-go-vue.js +291 -0
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -8,6 +8,7 @@ CLI package for scaffolding and running the Asaje Go + Vue boilerplate.
|
|
|
8
8
|
|
|
9
9
|
| Command | Purpose |
|
|
10
10
|
| --- | --- |
|
|
11
|
+
| `asaje sync-project-config [directory]` | Scan the project, detect managed services, and rewrite `asaje.config.json` / `asaje.railway.json` |
|
|
11
12
|
| `asaje setup-railway [directory]` | Provision infrastructure, create missing Railway services, wire variables, and deploy |
|
|
12
13
|
| `asaje update-railway [directory]` | Reconcile an existing Railway project after changing `asaje.config.json` |
|
|
13
14
|
| `asaje sync-railway-env [directory]` | Reapply Railway variables without reprovisioning infra |
|
|
@@ -66,6 +67,13 @@ npx -p create-asaje-go-vue@latest asaje update ./my-app --yes
|
|
|
66
67
|
npx -p create-asaje-go-vue@latest asaje update ./my-app --include admin/src/stores/session.ts,admin/src/services/http/session.ts
|
|
67
68
|
```
|
|
68
69
|
|
|
70
|
+
### Scan the project and regenerate local config manifests
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
npx -p create-asaje-go-vue@latest asaje sync-project-config ./my-app --dry-run
|
|
74
|
+
npx -p create-asaje-go-vue@latest asaje sync-project-config ./my-app --yes
|
|
75
|
+
```
|
|
76
|
+
|
|
69
77
|
### Provision Railway resources
|
|
70
78
|
|
|
71
79
|
```bash
|
|
@@ -171,6 +179,15 @@ npx -p create-asaje-go-vue@latest asaje destroy-railway ./my-app --scope project
|
|
|
171
179
|
- supports `--dry-run` to preview which files would be updated
|
|
172
180
|
- updates `asaje.config.json` with the template repository and branch used for the update
|
|
173
181
|
|
|
182
|
+
## What `asaje sync-project-config` does
|
|
183
|
+
|
|
184
|
+
- scans the project tree for service-local `Dockerfile` files
|
|
185
|
+
- infers Railway managed services from the detected directories
|
|
186
|
+
- preserves existing service metadata when possible, while updating directories and Dockerfile paths from the scan
|
|
187
|
+
- rewrites `asaje.config.json` with the merged `railway.services` list
|
|
188
|
+
- rewrites `asaje.railway.json` so local service names line up with the current managed service list
|
|
189
|
+
- supports `--dry-run` to preview the rewrite without changing local files
|
|
190
|
+
|
|
174
191
|
## What `asaje setup-railway` does
|
|
175
192
|
|
|
176
193
|
- validates the target project structure
|
|
@@ -104,6 +104,12 @@ async function main() {
|
|
|
104
104
|
return;
|
|
105
105
|
}
|
|
106
106
|
|
|
107
|
+
if (invocation.command === "sync-project-config") {
|
|
108
|
+
await runSyncProjectConfig(invocation.argv);
|
|
109
|
+
outro(pc.green("Project config sync complete."));
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
|
|
107
113
|
if (invocation.command === "setup-railway") {
|
|
108
114
|
await runSetupRailway(invocation.argv);
|
|
109
115
|
outro(pc.green("Railway setup complete."));
|
|
@@ -202,6 +208,10 @@ function resolveInvocation(argv) {
|
|
|
202
208
|
return { argv: rawArgs.slice(1), command: "update", title: "asaje update" };
|
|
203
209
|
}
|
|
204
210
|
|
|
211
|
+
if (firstArg === "sync-project-config") {
|
|
212
|
+
return { argv: rawArgs.slice(1), command: "sync-project-config", title: "asaje sync-project-config" };
|
|
213
|
+
}
|
|
214
|
+
|
|
205
215
|
if (firstArg === "setup-railway") {
|
|
206
216
|
return { argv: rawArgs.slice(1), command: "setup-railway", title: "asaje setup-railway" };
|
|
207
217
|
}
|
|
@@ -261,6 +271,10 @@ function resolveInvocation(argv) {
|
|
|
261
271
|
return { argv: rawArgs.slice(1), command: "update", title: "create-asaje-go-vue" };
|
|
262
272
|
}
|
|
263
273
|
|
|
274
|
+
if (firstArg === "sync-project-config") {
|
|
275
|
+
return { argv: rawArgs.slice(1), command: "sync-project-config", title: "create-asaje-go-vue" };
|
|
276
|
+
}
|
|
277
|
+
|
|
264
278
|
if (firstArg === "setup-railway") {
|
|
265
279
|
return { argv: rawArgs.slice(1), command: "setup-railway", title: "create-asaje-go-vue" };
|
|
266
280
|
}
|
|
@@ -308,6 +322,7 @@ function printHelp() {
|
|
|
308
322
|
console.log(`- ${pc.bold("asaje doctor [directory]")} check environment and project readiness`);
|
|
309
323
|
console.log(`- ${pc.bold("asaje publish")} run npm publish checklist for the CLI package`);
|
|
310
324
|
console.log(`- ${pc.bold("asaje update [directory]")} update managed boilerplate files from the template`);
|
|
325
|
+
console.log(`- ${pc.bold("asaje sync-project-config [directory]")} scan the project and rewrite Asaje config manifests`);
|
|
311
326
|
console.log(`- ${pc.bold("asaje setup-railway [directory]")} provision Railway infrastructure for a project`);
|
|
312
327
|
console.log(`- ${pc.bold("asaje update-railway [directory]")} reconcile Railway resources/services/vars from current config`);
|
|
313
328
|
console.log(`- ${pc.bold("asaje sync-railway-env [directory]")} sync Railway app variables without provisioning`);
|
|
@@ -324,6 +339,7 @@ function printHelp() {
|
|
|
324
339
|
console.log(`- ${pc.bold("asaje doctor ..")}`);
|
|
325
340
|
console.log(`- ${pc.bold("asaje publish")}`);
|
|
326
341
|
console.log(`- ${pc.bold("asaje update .. --dry-run")}`);
|
|
342
|
+
console.log(`- ${pc.bold("asaje sync-project-config .. --dry-run")}`);
|
|
327
343
|
console.log(`- ${pc.bold("asaje setup-railway ..")}`);
|
|
328
344
|
console.log(`- ${pc.bold("asaje update-railway ..")}`);
|
|
329
345
|
console.log(`- ${pc.bold("asaje sync-railway-env ..")}`);
|
|
@@ -1207,6 +1223,34 @@ async function runUpdate(argv) {
|
|
|
1207
1223
|
}
|
|
1208
1224
|
}
|
|
1209
1225
|
|
|
1226
|
+
async function runSyncProjectConfig(argv) {
|
|
1227
|
+
const args = await collectSyncProjectConfigAnswers(parseSyncProjectConfigArgs(argv));
|
|
1228
|
+
const projectDir = path.resolve(process.cwd(), args.directory);
|
|
1229
|
+
|
|
1230
|
+
await ensureProjectStructure(projectDir);
|
|
1231
|
+
|
|
1232
|
+
const projectConfig = await loadProjectConfig(projectDir);
|
|
1233
|
+
const manifest = await readRailwayManifest(projectDir);
|
|
1234
|
+
const scanSummary = await scanProjectForManagedRailwayServices(projectDir);
|
|
1235
|
+
const nextProjectConfig = buildSyncedProjectConfig(projectDir, projectConfig, scanSummary.serviceSpecs);
|
|
1236
|
+
const nextManifest = buildSyncedRailwayManifest(manifest, nextProjectConfig, scanSummary.serviceSpecs);
|
|
1237
|
+
|
|
1238
|
+
if (!args.dryRun) {
|
|
1239
|
+
await writeProjectConfigFile(projectDir, nextProjectConfig);
|
|
1240
|
+
await writeRailwayManifest(projectDir, nextManifest);
|
|
1241
|
+
}
|
|
1242
|
+
|
|
1243
|
+
printSyncProjectConfigSummary({
|
|
1244
|
+
dryRun: args.dryRun,
|
|
1245
|
+
manifest,
|
|
1246
|
+
nextManifest,
|
|
1247
|
+
nextProjectConfig,
|
|
1248
|
+
previousProjectConfig: projectConfig,
|
|
1249
|
+
projectDir,
|
|
1250
|
+
scanSummary,
|
|
1251
|
+
});
|
|
1252
|
+
}
|
|
1253
|
+
|
|
1210
1254
|
async function runSetupRailway(argv) {
|
|
1211
1255
|
const args = parseSetupRailwayArgs(argv);
|
|
1212
1256
|
const answers = await collectSetupRailwayAnswers(args);
|
|
@@ -1910,6 +1954,34 @@ function parseImportRailwayConfigArgs(argv) {
|
|
|
1910
1954
|
return options;
|
|
1911
1955
|
}
|
|
1912
1956
|
|
|
1957
|
+
function parseSyncProjectConfigArgs(argv) {
|
|
1958
|
+
const options = {
|
|
1959
|
+
directory: ".",
|
|
1960
|
+
dryRun: false,
|
|
1961
|
+
yes: false,
|
|
1962
|
+
};
|
|
1963
|
+
const positionals = [];
|
|
1964
|
+
|
|
1965
|
+
for (let index = 0; index < argv.length; index += 1) {
|
|
1966
|
+
const arg = argv[index];
|
|
1967
|
+
|
|
1968
|
+
if (arg === "--yes" || arg === "-y") {
|
|
1969
|
+
options.yes = true;
|
|
1970
|
+
continue;
|
|
1971
|
+
}
|
|
1972
|
+
|
|
1973
|
+
if (arg === "--dry-run") {
|
|
1974
|
+
options.dryRun = true;
|
|
1975
|
+
continue;
|
|
1976
|
+
}
|
|
1977
|
+
|
|
1978
|
+
positionals.push(arg);
|
|
1979
|
+
}
|
|
1980
|
+
|
|
1981
|
+
options.directory = positionals[0] || options.directory;
|
|
1982
|
+
return options;
|
|
1983
|
+
}
|
|
1984
|
+
|
|
1913
1985
|
function parseDiffRailwayConfigArgs(argv) {
|
|
1914
1986
|
const options = {
|
|
1915
1987
|
compareEnvironment: undefined,
|
|
@@ -2235,6 +2307,25 @@ async function collectImportRailwayConfigAnswers(args) {
|
|
|
2235
2307
|
return args;
|
|
2236
2308
|
}
|
|
2237
2309
|
|
|
2310
|
+
async function collectSyncProjectConfigAnswers(args) {
|
|
2311
|
+
if (args.yes || args.dryRun) {
|
|
2312
|
+
return args;
|
|
2313
|
+
}
|
|
2314
|
+
|
|
2315
|
+
const confirmed = await prompt(
|
|
2316
|
+
confirm({
|
|
2317
|
+
initialValue: true,
|
|
2318
|
+
message: `Scan ${args.directory} and rewrite asaje.config.json / ${RAILWAY_MANIFEST_FILENAME}?`,
|
|
2319
|
+
}),
|
|
2320
|
+
);
|
|
2321
|
+
|
|
2322
|
+
if (!confirmed) {
|
|
2323
|
+
throw new Error("Project config sync cancelled.");
|
|
2324
|
+
}
|
|
2325
|
+
|
|
2326
|
+
return args;
|
|
2327
|
+
}
|
|
2328
|
+
|
|
2238
2329
|
async function collectDestroyRailwayAnswers(args) {
|
|
2239
2330
|
if (args.yes) {
|
|
2240
2331
|
return args;
|
|
@@ -4149,6 +4240,206 @@ async function ensureRailwayAppServiceTargets(projectDir, appServiceSpecs) {
|
|
|
4149
4240
|
}
|
|
4150
4241
|
}
|
|
4151
4242
|
|
|
4243
|
+
async function scanProjectForManagedRailwayServices(projectDir) {
|
|
4244
|
+
const dockerfiles = [];
|
|
4245
|
+
await collectDockerfiles(projectDir, "", dockerfiles);
|
|
4246
|
+
|
|
4247
|
+
const serviceSpecs = dockerfiles
|
|
4248
|
+
.map((dockerfilePath) => buildScannedRailwayServiceSpec(projectDir, dockerfilePath))
|
|
4249
|
+
.filter(Boolean)
|
|
4250
|
+
.sort((left, right) => left.directory.localeCompare(right.directory));
|
|
4251
|
+
|
|
4252
|
+
return {
|
|
4253
|
+
dockerfiles,
|
|
4254
|
+
serviceSpecs,
|
|
4255
|
+
};
|
|
4256
|
+
}
|
|
4257
|
+
|
|
4258
|
+
async function collectDockerfiles(projectDir, relativeDir, results) {
|
|
4259
|
+
const absoluteDir = path.join(projectDir, relativeDir);
|
|
4260
|
+
const entries = await fs.readdir(absoluteDir, { withFileTypes: true });
|
|
4261
|
+
|
|
4262
|
+
for (const entry of entries) {
|
|
4263
|
+
const nextRelativePath = relativeDir ? path.posix.join(relativeDir, entry.name) : entry.name;
|
|
4264
|
+
if (entry.isDirectory()) {
|
|
4265
|
+
if (shouldSkipProjectScanDirectory(entry.name, nextRelativePath)) {
|
|
4266
|
+
continue;
|
|
4267
|
+
}
|
|
4268
|
+
|
|
4269
|
+
await collectDockerfiles(projectDir, nextRelativePath, results);
|
|
4270
|
+
continue;
|
|
4271
|
+
}
|
|
4272
|
+
|
|
4273
|
+
if (entry.isFile() && entry.name === "Dockerfile") {
|
|
4274
|
+
results.push(nextRelativePath);
|
|
4275
|
+
}
|
|
4276
|
+
}
|
|
4277
|
+
}
|
|
4278
|
+
|
|
4279
|
+
function shouldSkipProjectScanDirectory(name, relativePath) {
|
|
4280
|
+
const normalized = String(name || "").trim();
|
|
4281
|
+
if (!normalized) {
|
|
4282
|
+
return false;
|
|
4283
|
+
}
|
|
4284
|
+
|
|
4285
|
+
if ([".git", ".turbo", ".next", ".nuxt", "node_modules", "dist", "build", "coverage", "tmp", "vendor"].includes(normalized)) {
|
|
4286
|
+
return true;
|
|
4287
|
+
}
|
|
4288
|
+
|
|
4289
|
+
if (relativePath === "cli") {
|
|
4290
|
+
return true;
|
|
4291
|
+
}
|
|
4292
|
+
|
|
4293
|
+
return normalized.startsWith(".") && normalized !== ".well-known";
|
|
4294
|
+
}
|
|
4295
|
+
|
|
4296
|
+
function buildScannedRailwayServiceSpec(projectDir, dockerfilePath) {
|
|
4297
|
+
const directory = path.posix.dirname(dockerfilePath);
|
|
4298
|
+
if (!directory || directory === ".") {
|
|
4299
|
+
return null;
|
|
4300
|
+
}
|
|
4301
|
+
|
|
4302
|
+
const inferred = inferRailwayServiceIdentity(directory);
|
|
4303
|
+
return {
|
|
4304
|
+
aliases: inferred.aliases,
|
|
4305
|
+
baseName: inferred.baseName,
|
|
4306
|
+
directory,
|
|
4307
|
+
dockerfile: dockerfilePath,
|
|
4308
|
+
key: inferred.key,
|
|
4309
|
+
seedImage: inferred.key === "admin" ? "nginx:1.29-alpine" : "alpine:3.22",
|
|
4310
|
+
serviceName: null,
|
|
4311
|
+
};
|
|
4312
|
+
}
|
|
4313
|
+
|
|
4314
|
+
function inferRailwayServiceIdentity(directory) {
|
|
4315
|
+
const normalizedDirectory = directory.replace(/\/+$/g, "");
|
|
4316
|
+
const directoryName = path.posix.basename(normalizedDirectory);
|
|
4317
|
+
const normalizedName = normalizeRailwayServiceName(directoryName);
|
|
4318
|
+
|
|
4319
|
+
if (["api", "backend", "server"].includes(normalizedName)) {
|
|
4320
|
+
return { aliases: ["api", "backend", "server"], baseName: "api", key: "api" };
|
|
4321
|
+
}
|
|
4322
|
+
if (["admin", "frontend", "web"].includes(normalizedName)) {
|
|
4323
|
+
return { aliases: ["admin", "frontend", "web"], baseName: "admin", key: "admin" };
|
|
4324
|
+
}
|
|
4325
|
+
if (["realtime", "realtime-gateway"].includes(normalizedName)) {
|
|
4326
|
+
return { aliases: ["realtime-gateway", "realtime"], baseName: "realtime-gateway", key: "realtime" };
|
|
4327
|
+
}
|
|
4328
|
+
|
|
4329
|
+
const slug = slugify(directoryName);
|
|
4330
|
+
return { aliases: [slug], baseName: slug, key: slug };
|
|
4331
|
+
}
|
|
4332
|
+
|
|
4333
|
+
function buildSyncedProjectConfig(projectDir, projectConfig, scannedServiceSpecs) {
|
|
4334
|
+
const nextConfig = {
|
|
4335
|
+
...(projectConfig || {}),
|
|
4336
|
+
projectName: projectConfig?.projectName || path.basename(projectDir),
|
|
4337
|
+
projectSlug: projectConfig?.projectSlug || slugify(path.basename(projectDir)),
|
|
4338
|
+
};
|
|
4339
|
+
|
|
4340
|
+
const previousServices = resolveRailwayAppServiceSpecs(projectConfig);
|
|
4341
|
+
const mergedServices = mergeScannedRailwayServices(previousServices, scannedServiceSpecs);
|
|
4342
|
+
|
|
4343
|
+
nextConfig.railway = {
|
|
4344
|
+
...(getRailwayConfig(projectConfig) || {}),
|
|
4345
|
+
services: mergedServices.map((service) => ({
|
|
4346
|
+
baseName: service.baseName,
|
|
4347
|
+
directory: service.directory,
|
|
4348
|
+
...(service.dockerfile ? { dockerfile: service.dockerfile } : {}),
|
|
4349
|
+
key: service.key,
|
|
4350
|
+
...(service.aliases?.length > 0 ? { aliases: service.aliases } : {}),
|
|
4351
|
+
...(service.serviceName ? { serviceName: service.serviceName } : {}),
|
|
4352
|
+
...(service.seedImage ? { seedImage: service.seedImage } : {}),
|
|
4353
|
+
})),
|
|
4354
|
+
};
|
|
4355
|
+
|
|
4356
|
+
return nextConfig;
|
|
4357
|
+
}
|
|
4358
|
+
|
|
4359
|
+
function mergeScannedRailwayServices(previousServices, scannedServiceSpecs) {
|
|
4360
|
+
const previousByKey = new Map(previousServices.map((service) => [service.key, service]));
|
|
4361
|
+
const previousByDirectory = new Map(previousServices.map((service) => [service.directory, service]));
|
|
4362
|
+
|
|
4363
|
+
return scannedServiceSpecs.map((scanned) => {
|
|
4364
|
+
const previous = previousByKey.get(scanned.key) || previousByDirectory.get(scanned.directory);
|
|
4365
|
+
return {
|
|
4366
|
+
aliases: uniqueStrings([...(previous?.aliases || []), ...scanned.aliases]),
|
|
4367
|
+
baseName: previous?.baseName || scanned.baseName,
|
|
4368
|
+
directory: scanned.directory,
|
|
4369
|
+
dockerfile: scanned.dockerfile,
|
|
4370
|
+
key: previous?.key || scanned.key,
|
|
4371
|
+
seedImage: previous?.seedImage || scanned.seedImage,
|
|
4372
|
+
serviceName: previous?.serviceName || null,
|
|
4373
|
+
};
|
|
4374
|
+
});
|
|
4375
|
+
}
|
|
4376
|
+
|
|
4377
|
+
function buildSyncedRailwayManifest(manifest, nextProjectConfig, scannedServiceSpecs) {
|
|
4378
|
+
const nextManifest = {
|
|
4379
|
+
...(manifest || {}),
|
|
4380
|
+
appServices: {},
|
|
4381
|
+
projectSlug: nextProjectConfig.projectSlug || manifest?.projectSlug || null,
|
|
4382
|
+
updatedAt: new Date().toISOString(),
|
|
4383
|
+
};
|
|
4384
|
+
|
|
4385
|
+
const previousAppServices = manifest?.appServices || {};
|
|
4386
|
+
const existingSpecs = resolveRailwayAppServiceSpecs(nextProjectConfig);
|
|
4387
|
+
for (const spec of existingSpecs) {
|
|
4388
|
+
const previousEntry =
|
|
4389
|
+
previousAppServices[spec.key] ||
|
|
4390
|
+
findRailwayManifestAppServiceByName(previousAppServices, resolveRailwayServiceName(spec, nextManifest.projectSlug));
|
|
4391
|
+
|
|
4392
|
+
nextManifest.appServices[spec.key] = {
|
|
4393
|
+
serviceId: previousEntry?.serviceId || null,
|
|
4394
|
+
serviceName: previousEntry?.serviceName || resolveRailwayServiceName(spec, nextManifest.projectSlug),
|
|
4395
|
+
};
|
|
4396
|
+
}
|
|
4397
|
+
|
|
4398
|
+
return nextManifest;
|
|
4399
|
+
}
|
|
4400
|
+
|
|
4401
|
+
function findRailwayManifestAppServiceByName(appServices, serviceName) {
|
|
4402
|
+
return Object.values(appServices || {}).find(
|
|
4403
|
+
(entry) => normalizeRailwayServiceName(entry?.serviceName) === normalizeRailwayServiceName(serviceName),
|
|
4404
|
+
) || null;
|
|
4405
|
+
}
|
|
4406
|
+
|
|
4407
|
+
async function writeProjectConfigFile(projectDir, projectConfig) {
|
|
4408
|
+
const configPath = path.join(projectDir, "asaje.config.json");
|
|
4409
|
+
await fs.writeJson(configPath, projectConfig, { spaces: 2 });
|
|
4410
|
+
}
|
|
4411
|
+
|
|
4412
|
+
function printSyncProjectConfigSummary(config) {
|
|
4413
|
+
const previousServices = new Map(resolveRailwayAppServiceSpecs(config.previousProjectConfig).map((service) => [service.key, service]));
|
|
4414
|
+
const nextServices = config.nextProjectConfig.railway?.services || [];
|
|
4415
|
+
|
|
4416
|
+
console.log(pc.bold("\nProject config sync"));
|
|
4417
|
+
console.log(`- Directory: ${pc.bold(config.projectDir)}`);
|
|
4418
|
+
console.log(`- Dockerfiles found: ${pc.bold(String(config.scanSummary.dockerfiles.length))}`);
|
|
4419
|
+
|
|
4420
|
+
console.log(pc.bold("\nRailway services"));
|
|
4421
|
+
if (nextServices.length === 0) {
|
|
4422
|
+
console.log("- No managed Railway services detected");
|
|
4423
|
+
} else {
|
|
4424
|
+
for (const service of nextServices) {
|
|
4425
|
+
const previous = previousServices.get(service.key);
|
|
4426
|
+
const status = !previous ? "new" : previous.directory !== service.directory || previous.dockerfile !== service.dockerfile ? "updated" : "unchanged";
|
|
4427
|
+
console.log(`- ${pc.bold(service.key)}: ${status} (${service.directory})`);
|
|
4428
|
+
}
|
|
4429
|
+
}
|
|
4430
|
+
|
|
4431
|
+
console.log(pc.bold("\nFiles"));
|
|
4432
|
+
console.log(`- ${config.dryRun ? "would write" : "wrote"} ${pc.bold("asaje.config.json")}`);
|
|
4433
|
+
console.log(`- ${config.dryRun ? "would write" : "wrote"} ${pc.bold(RAILWAY_MANIFEST_FILENAME)}`);
|
|
4434
|
+
if (config.dryRun) {
|
|
4435
|
+
console.log("- Dry run only, local files were not modified");
|
|
4436
|
+
}
|
|
4437
|
+
}
|
|
4438
|
+
|
|
4439
|
+
function uniqueStrings(values) {
|
|
4440
|
+
return [...new Set((values || []).map((value) => String(value || "").trim()).filter(Boolean))];
|
|
4441
|
+
}
|
|
4442
|
+
|
|
4152
4443
|
function resolveProjectSlug(projectDir, projectConfig) {
|
|
4153
4444
|
return slugify(projectConfig?.projectSlug || projectConfig?.projectName || path.basename(projectDir) || "asaje-app");
|
|
4154
4445
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-asaje-go-vue",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"description": "CLI to scaffold, configure, and run the Asaje Go + Vue boilerplate",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
"create": "node ./bin/create-asaje-go-vue.js",
|
|
12
12
|
"start": "node ./bin/asaje.js start .",
|
|
13
13
|
"doctor": "node ./bin/asaje.js doctor ..",
|
|
14
|
+
"sync-project-config": "node ./bin/asaje.js sync-project-config .. --dry-run",
|
|
14
15
|
"setup-railway": "node ./bin/asaje.js setup-railway .. --yes",
|
|
15
16
|
"update-railway": "node ./bin/asaje.js update-railway .. --yes",
|
|
16
17
|
"sync-railway-env": "node ./bin/asaje.js sync-railway-env .. --yes",
|