@concavejs/cli 0.0.1-alpha.6 → 0.0.1-alpha.8
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/assets/dashboard/dashboard.js +1 -1
- package/dist/assets/manifest.json +14 -14
- package/dist/assets/runtime-bun/server/index.js +4167 -2989
- package/dist/assets/runtime-cf/runtime.bundle.js +35932 -20254
- package/dist/assets/runtime-node/server/index.js +4110 -2903
- package/dist/cli.js +489 -63
- package/package.json +4 -4
package/dist/cli.js
CHANGED
|
@@ -4757,7 +4757,7 @@ async function loadAppDefinition(configPath, parentComponentPath, entries, visit
|
|
|
4757
4757
|
for (const child of childComponents) {
|
|
4758
4758
|
const componentPath = joinComponentPath(parentComponentPath, child.name);
|
|
4759
4759
|
const definitionPath = resolveChildDefinitionPath(configPath, child.path);
|
|
4760
|
-
const modulesDir =
|
|
4760
|
+
const modulesDir = await resolveComponentModulesDir(definitionPath);
|
|
4761
4761
|
entries.push({
|
|
4762
4762
|
componentPath,
|
|
4763
4763
|
modulesDir,
|
|
@@ -4780,7 +4780,7 @@ async function loadComponentDefinition(configPath, componentPath, entries, visit
|
|
|
4780
4780
|
for (const child of childComponents) {
|
|
4781
4781
|
const nestedComponentPath = joinComponentPath(componentPath, child.name);
|
|
4782
4782
|
const definitionPath = resolveChildDefinitionPath(configPath, child.path);
|
|
4783
|
-
const modulesDir =
|
|
4783
|
+
const modulesDir = await resolveComponentModulesDir(definitionPath);
|
|
4784
4784
|
entries.push({
|
|
4785
4785
|
componentPath: nestedComponentPath,
|
|
4786
4786
|
modulesDir,
|
|
@@ -4806,6 +4806,17 @@ function resolveChildDefinitionPath(parentConfigPath, childPath) {
|
|
|
4806
4806
|
const parentDir = path.dirname(parentConfigPath);
|
|
4807
4807
|
return path.resolve(parentDir, childPath);
|
|
4808
4808
|
}
|
|
4809
|
+
async function resolveComponentModulesDir(definitionPath) {
|
|
4810
|
+
const definitionDir = path.dirname(definitionPath);
|
|
4811
|
+
const nestedConvexDir = path.join(definitionDir, "convex");
|
|
4812
|
+
try {
|
|
4813
|
+
const stats = await fs.stat(nestedConvexDir);
|
|
4814
|
+
if (stats.isDirectory()) {
|
|
4815
|
+
return nestedConvexDir;
|
|
4816
|
+
}
|
|
4817
|
+
} catch {}
|
|
4818
|
+
return definitionDir;
|
|
4819
|
+
}
|
|
4809
4820
|
function joinComponentPath(parent, child) {
|
|
4810
4821
|
if (!parent) {
|
|
4811
4822
|
return child;
|
|
@@ -5146,6 +5157,7 @@ async function generateUserEntry(projectRoot, outDir) {
|
|
|
5146
5157
|
const componentManifest = await scanComponents(projectRoot);
|
|
5147
5158
|
await writeComponentManifest(targetDir, componentManifest.entries);
|
|
5148
5159
|
await copyComponentModules(targetDir, componentManifest.entries);
|
|
5160
|
+
const componentLoaderBlocks = await buildComponentLoaderBlocks(targetDir, componentManifest.entries);
|
|
5149
5161
|
const fallbackEntries = files.map((filePath) => {
|
|
5150
5162
|
const importPath = formatImportPath(targetDir, filePath);
|
|
5151
5163
|
return ` '${importPath}': () => import('${importPath}'),`;
|
|
@@ -5154,10 +5166,20 @@ async function generateUserEntry(projectRoot, outDir) {
|
|
|
5154
5166
|
const content = `// Generated by concave CLI
|
|
5155
5167
|
// Do not edit this file manually
|
|
5156
5168
|
|
|
5169
|
+
import { createModuleLoaderFromGlob, setConcaveModuleLoader } from "@concavejs/core/udf";
|
|
5170
|
+
|
|
5157
5171
|
const modules = import.meta?.glob?.(["../convex/**/*.*s", "!../**/*.*.*s"]) ?? {
|
|
5158
5172
|
${fallbackEntries}
|
|
5159
5173
|
};
|
|
5160
5174
|
|
|
5175
|
+
const componentLoaders = [];
|
|
5176
|
+
${componentLoaderBlocks.join(`
|
|
5177
|
+
|
|
5178
|
+
`)}
|
|
5179
|
+
for (const { componentPath, loader } of componentLoaders) {
|
|
5180
|
+
setConcaveModuleLoader(loader, { componentPath });
|
|
5181
|
+
}
|
|
5182
|
+
|
|
5161
5183
|
export { modules };
|
|
5162
5184
|
`;
|
|
5163
5185
|
const contentWithFunctionsPath = content.replace('const modules = import.meta?.glob?.(["../convex/**/*.*s", "!../**/*.*.*s"]) ?? {', `const modules = import.meta?.glob?.([${JSON.stringify(functionsGlobPattern)}, "!../**/*.*.*s"]) ?? {`);
|
|
@@ -6611,6 +6633,7 @@ async function bundleProject(projectRoot, _verbose) {
|
|
|
6611
6633
|
sourcemap: false,
|
|
6612
6634
|
logLevel: "silent",
|
|
6613
6635
|
absWorkingDir: buildDir,
|
|
6636
|
+
external: ["node:*"],
|
|
6614
6637
|
plugins: [componentDefinitionPlugin()]
|
|
6615
6638
|
});
|
|
6616
6639
|
if (buildResult.errors.length > 0) {
|
|
@@ -7386,6 +7409,8 @@ import {
|
|
|
7386
7409
|
} from "convex/server";
|
|
7387
7410
|
import type { DataModel } from "./dataModel.js";
|
|
7388
7411
|
|
|
7412
|
+
export { defineSchema, defineTable } from "convex/server";
|
|
7413
|
+
|
|
7389
7414
|
/**
|
|
7390
7415
|
* Define a query in this Convex app's public API.
|
|
7391
7416
|
*
|
|
@@ -7527,6 +7552,8 @@ import {
|
|
|
7527
7552
|
internalActionGeneric,
|
|
7528
7553
|
internalMutationGeneric,
|
|
7529
7554
|
internalQueryGeneric,
|
|
7555
|
+
defineSchema,
|
|
7556
|
+
defineTable,
|
|
7530
7557
|
} from "convex/server";
|
|
7531
7558
|
|
|
7532
7559
|
/**
|
|
@@ -7598,6 +7625,11 @@ export const internalAction = internalActionGeneric;
|
|
|
7598
7625
|
* @returns The wrapped endpoint function. Route a URL path to this function in \`convex/http.js\`.
|
|
7599
7626
|
*/
|
|
7600
7627
|
export const httpAction = httpActionGeneric;
|
|
7628
|
+
|
|
7629
|
+
/**
|
|
7630
|
+
* Define a table in this Convex app's schema.
|
|
7631
|
+
*/
|
|
7632
|
+
export { defineTable, defineSchema };
|
|
7601
7633
|
`;
|
|
7602
7634
|
await fs9.writeFile(path12.join(generatedDir, "server.js"), content, "utf8");
|
|
7603
7635
|
}
|
|
@@ -7734,8 +7766,59 @@ async function generateApiJs(generatedDir) {
|
|
|
7734
7766
|
* @module
|
|
7735
7767
|
*/
|
|
7736
7768
|
|
|
7737
|
-
|
|
7738
|
-
|
|
7769
|
+
const functionName = Symbol.for("functionName");
|
|
7770
|
+
const toReferencePath = Symbol.for("toReferencePath");
|
|
7771
|
+
|
|
7772
|
+
function createApi(pathParts = []) {
|
|
7773
|
+
return new Proxy(
|
|
7774
|
+
{},
|
|
7775
|
+
{
|
|
7776
|
+
get(_target, prop) {
|
|
7777
|
+
if (typeof prop === "string") {
|
|
7778
|
+
return createApi([...pathParts, prop]);
|
|
7779
|
+
}
|
|
7780
|
+
if (prop === functionName) {
|
|
7781
|
+
if (pathParts.length < 2) {
|
|
7782
|
+
const found = ["api", ...pathParts].join(".");
|
|
7783
|
+
throw new Error(
|
|
7784
|
+
"API path is expected to be of the form \`api.moduleName.functionName\`. Found: \`" + found + "\`",
|
|
7785
|
+
);
|
|
7786
|
+
}
|
|
7787
|
+
const modulePath = pathParts.slice(0, -1).join("/");
|
|
7788
|
+
const exportName = pathParts[pathParts.length - 1];
|
|
7789
|
+
return exportName === "default" ? modulePath : modulePath + ":" + exportName;
|
|
7790
|
+
}
|
|
7791
|
+
if (prop === Symbol.toStringTag) {
|
|
7792
|
+
return "FunctionReference";
|
|
7793
|
+
}
|
|
7794
|
+
return undefined;
|
|
7795
|
+
},
|
|
7796
|
+
},
|
|
7797
|
+
);
|
|
7798
|
+
}
|
|
7799
|
+
|
|
7800
|
+
function createComponents(pathParts = []) {
|
|
7801
|
+
return new Proxy(
|
|
7802
|
+
{},
|
|
7803
|
+
{
|
|
7804
|
+
get(_target, prop) {
|
|
7805
|
+
if (typeof prop === "string") {
|
|
7806
|
+
return createComponents([...pathParts, prop]);
|
|
7807
|
+
}
|
|
7808
|
+
if (prop === toReferencePath) {
|
|
7809
|
+
if (pathParts.length < 1) {
|
|
7810
|
+
const found = ["components", ...pathParts].join(".");
|
|
7811
|
+
throw new Error(
|
|
7812
|
+
"API path is expected to be of the form \`components.childComponent.functionName\`. Found: \`" + found + "\`",
|
|
7813
|
+
);
|
|
7814
|
+
}
|
|
7815
|
+
return "_reference/childComponent/" + pathParts.join("/");
|
|
7816
|
+
}
|
|
7817
|
+
return undefined;
|
|
7818
|
+
},
|
|
7819
|
+
},
|
|
7820
|
+
);
|
|
7821
|
+
}
|
|
7739
7822
|
|
|
7740
7823
|
/**
|
|
7741
7824
|
* A utility for referencing Convex functions in your app's API.
|
|
@@ -7745,9 +7828,9 @@ import { componentsGeneric } from "convex/server";
|
|
|
7745
7828
|
* const myFunctionReference = api.myModule.myFunction;
|
|
7746
7829
|
* \`\`\`
|
|
7747
7830
|
*/
|
|
7748
|
-
export const api =
|
|
7749
|
-
export const internal =
|
|
7750
|
-
export const components =
|
|
7831
|
+
export const api = createApi();
|
|
7832
|
+
export const internal = createApi();
|
|
7833
|
+
export const components = createComponents();
|
|
7751
7834
|
`;
|
|
7752
7835
|
await fs9.writeFile(path12.join(generatedDir, "api.js"), content, "utf8");
|
|
7753
7836
|
}
|
|
@@ -8296,6 +8379,8 @@ import {
|
|
|
8296
8379
|
} from "convex/server";
|
|
8297
8380
|
import type { DataModel } from "./dataModel.js";
|
|
8298
8381
|
|
|
8382
|
+
export { defineSchema, defineTable } from "convex/server";
|
|
8383
|
+
|
|
8299
8384
|
export declare const query: QueryBuilder<DataModel, "public">;
|
|
8300
8385
|
export declare const internalQuery: QueryBuilder<DataModel, "internal">;
|
|
8301
8386
|
export declare const mutation: MutationBuilder<DataModel, "public">;
|
|
@@ -8331,15 +8416,84 @@ import {
|
|
|
8331
8416
|
internalActionGeneric,
|
|
8332
8417
|
internalMutationGeneric,
|
|
8333
8418
|
internalQueryGeneric,
|
|
8419
|
+
defineSchema,
|
|
8420
|
+
defineTable,
|
|
8334
8421
|
} from "convex/server";
|
|
8335
8422
|
|
|
8423
|
+
/**
|
|
8424
|
+
* Define a query in this Convex app's public API.
|
|
8425
|
+
*
|
|
8426
|
+
* This function will be allowed to read your Convex database and will be accessible from the client.
|
|
8427
|
+
*
|
|
8428
|
+
* @param func - The query function. It receives a {@link QueryCtx} as its first argument.
|
|
8429
|
+
* @returns The wrapped query. Include this as an \`export\` to name it and make it accessible.
|
|
8430
|
+
*/
|
|
8336
8431
|
export const query = queryGeneric;
|
|
8432
|
+
|
|
8433
|
+
/**
|
|
8434
|
+
* Define a query that is only accessible from other Convex functions (but not from the client).
|
|
8435
|
+
*
|
|
8436
|
+
* This function will be allowed to read from your Convex database. It will not be accessible from the client.
|
|
8437
|
+
*
|
|
8438
|
+
* @param func - The query function. It receives a {@link QueryCtx} as its first argument.
|
|
8439
|
+
* @returns The wrapped query. Include this as an \`export\` to name it and make it accessible.
|
|
8440
|
+
*/
|
|
8337
8441
|
export const internalQuery = internalQueryGeneric;
|
|
8442
|
+
|
|
8443
|
+
/**
|
|
8444
|
+
* Define a mutation in this Convex app's public API.
|
|
8445
|
+
*
|
|
8446
|
+
* This function will be allowed to modify your Convex database and will be accessible from the client.
|
|
8447
|
+
*
|
|
8448
|
+
* @param func - The mutation function. It receives a {@link MutationCtx} as its first argument.
|
|
8449
|
+
* @returns The wrapped mutation. Include this as an \`export\` to name it and make it accessible.
|
|
8450
|
+
*/
|
|
8338
8451
|
export const mutation = mutationGeneric;
|
|
8452
|
+
|
|
8453
|
+
/**
|
|
8454
|
+
* Define a mutation that is only accessible from other Convex functions (but not from the client).
|
|
8455
|
+
*
|
|
8456
|
+
* This function will be allowed to modify your Convex database. It will not be accessible from the client.
|
|
8457
|
+
*
|
|
8458
|
+
* @param func - The mutation function. It receives a {@link MutationCtx} as its first argument.
|
|
8459
|
+
* @returns The wrapped mutation. Include this as an \`export\` to name it and make it accessible.
|
|
8460
|
+
*/
|
|
8339
8461
|
export const internalMutation = internalMutationGeneric;
|
|
8462
|
+
|
|
8463
|
+
/**
|
|
8464
|
+
* Define an action in this Convex app's public API.
|
|
8465
|
+
*
|
|
8466
|
+
* An action is a function which can execute any JavaScript code, including non-deterministic
|
|
8467
|
+
* code and code with side-effects, like calling third-party services.
|
|
8468
|
+
* They can be run in Convex's JavaScript environment or in Node.js using the "use node" directive.
|
|
8469
|
+
* They can interact with the database indirectly by calling queries and mutations using the {@link ActionCtx}.
|
|
8470
|
+
*
|
|
8471
|
+
* @param func - The action. It receives an {@link ActionCtx} as its first argument.
|
|
8472
|
+
* @returns The wrapped action. Include this as an \`export\` to name it and make it accessible.
|
|
8473
|
+
*/
|
|
8340
8474
|
export const action = actionGeneric;
|
|
8475
|
+
|
|
8476
|
+
/**
|
|
8477
|
+
* Define an action that is only accessible from other Convex functions (but not from the client).
|
|
8478
|
+
*
|
|
8479
|
+
* @param func - The function. It receives an {@link ActionCtx} as its first argument.
|
|
8480
|
+
* @returns The wrapped function. Include this as an \`export\` to name it and make it accessible.
|
|
8481
|
+
*/
|
|
8341
8482
|
export const internalAction = internalActionGeneric;
|
|
8483
|
+
|
|
8484
|
+
/**
|
|
8485
|
+
* Define a Convex HTTP action.
|
|
8486
|
+
*
|
|
8487
|
+
* @param func - The function. It receives an {@link ActionCtx} as its first argument, and a \`Request\` object
|
|
8488
|
+
* as its second.
|
|
8489
|
+
* @returns The wrapped endpoint function. Route a URL path to this function in \`convex/http.js\`.
|
|
8490
|
+
*/
|
|
8342
8491
|
export const httpAction = httpActionGeneric;
|
|
8492
|
+
|
|
8493
|
+
/**
|
|
8494
|
+
* Define a table in this Convex app's schema.
|
|
8495
|
+
*/
|
|
8496
|
+
export { defineTable, defineSchema };
|
|
8343
8497
|
`;
|
|
8344
8498
|
await fs10.writeFile(path13.join(generatedDir, "server.js"), content, "utf8");
|
|
8345
8499
|
}
|
|
@@ -8382,7 +8536,59 @@ async function generateApiJs2(generatedDir) {
|
|
|
8382
8536
|
* @module
|
|
8383
8537
|
*/
|
|
8384
8538
|
|
|
8385
|
-
|
|
8539
|
+
const functionName = Symbol.for("functionName");
|
|
8540
|
+
const toReferencePath = Symbol.for("toReferencePath");
|
|
8541
|
+
|
|
8542
|
+
function createApi(pathParts = []) {
|
|
8543
|
+
return new Proxy(
|
|
8544
|
+
{},
|
|
8545
|
+
{
|
|
8546
|
+
get(_target, prop) {
|
|
8547
|
+
if (typeof prop === "string") {
|
|
8548
|
+
return createApi([...pathParts, prop]);
|
|
8549
|
+
}
|
|
8550
|
+
if (prop === functionName) {
|
|
8551
|
+
if (pathParts.length < 2) {
|
|
8552
|
+
const found = ["api", ...pathParts].join(".");
|
|
8553
|
+
throw new Error(
|
|
8554
|
+
"API path is expected to be of the form \`api.moduleName.functionName\`. Found: \`" + found + "\`",
|
|
8555
|
+
);
|
|
8556
|
+
}
|
|
8557
|
+
const modulePath = pathParts.slice(0, -1).join("/");
|
|
8558
|
+
const exportName = pathParts[pathParts.length - 1];
|
|
8559
|
+
return exportName === "default" ? modulePath : modulePath + ":" + exportName;
|
|
8560
|
+
}
|
|
8561
|
+
if (prop === Symbol.toStringTag) {
|
|
8562
|
+
return "FunctionReference";
|
|
8563
|
+
}
|
|
8564
|
+
return undefined;
|
|
8565
|
+
},
|
|
8566
|
+
},
|
|
8567
|
+
);
|
|
8568
|
+
}
|
|
8569
|
+
|
|
8570
|
+
function createComponents(pathParts = []) {
|
|
8571
|
+
return new Proxy(
|
|
8572
|
+
{},
|
|
8573
|
+
{
|
|
8574
|
+
get(_target, prop) {
|
|
8575
|
+
if (typeof prop === "string") {
|
|
8576
|
+
return createComponents([...pathParts, prop]);
|
|
8577
|
+
}
|
|
8578
|
+
if (prop === toReferencePath) {
|
|
8579
|
+
if (pathParts.length < 1) {
|
|
8580
|
+
const found = ["components", ...pathParts].join(".");
|
|
8581
|
+
throw new Error(
|
|
8582
|
+
"API path is expected to be of the form \`components.childComponent.functionName\`. Found: \`" + found + "\`",
|
|
8583
|
+
);
|
|
8584
|
+
}
|
|
8585
|
+
return "_reference/childComponent/" + pathParts.join("/");
|
|
8586
|
+
}
|
|
8587
|
+
return undefined;
|
|
8588
|
+
},
|
|
8589
|
+
},
|
|
8590
|
+
);
|
|
8591
|
+
}
|
|
8386
8592
|
|
|
8387
8593
|
/**
|
|
8388
8594
|
* A utility for referencing Convex functions in your app's API.
|
|
@@ -8392,9 +8598,9 @@ import { anyApi, componentsGeneric } from "convex/server";
|
|
|
8392
8598
|
* const myFunctionReference = api.myModule.myFunction;
|
|
8393
8599
|
* \`\`\`
|
|
8394
8600
|
*/
|
|
8395
|
-
export const api =
|
|
8396
|
-
export const internal =
|
|
8397
|
-
export const components =
|
|
8601
|
+
export const api = createApi();
|
|
8602
|
+
export const internal = createApi();
|
|
8603
|
+
export const components = createComponents();
|
|
8398
8604
|
`;
|
|
8399
8605
|
await fs10.writeFile(path13.join(generatedDir, "api.js"), content, "utf8");
|
|
8400
8606
|
}
|
|
@@ -10097,7 +10303,7 @@ function setupAuthEnvironment(keys, siteUrl, options = {}) {
|
|
|
10097
10303
|
setEnv("AUTH_SKIP_VERIFICATION", "true");
|
|
10098
10304
|
}
|
|
10099
10305
|
// package.json
|
|
10100
|
-
var version = "0.0.1-alpha.
|
|
10306
|
+
var version = "0.0.1-alpha.8";
|
|
10101
10307
|
|
|
10102
10308
|
// src/cli/cli.ts
|
|
10103
10309
|
var WATCH_IGNORE_PATTERNS = [
|
|
@@ -10248,14 +10454,6 @@ async function ensurePackageJsonWithConvexDependency(projectRoot) {
|
|
|
10248
10454
|
};
|
|
10249
10455
|
}
|
|
10250
10456
|
async function canResolveConvexRuntime(projectRoot) {
|
|
10251
|
-
const nodeModulesConvex = path15.join(projectRoot, "node_modules", "convex", "package.json");
|
|
10252
|
-
if (existsSync2(nodeModulesConvex)) {
|
|
10253
|
-
return true;
|
|
10254
|
-
}
|
|
10255
|
-
const hasYarnPnp = existsSync2(path15.join(projectRoot, ".pnp.cjs")) || existsSync2(path15.join(projectRoot, ".pnp.js"));
|
|
10256
|
-
if (!hasYarnPnp) {
|
|
10257
|
-
return false;
|
|
10258
|
-
}
|
|
10259
10457
|
const requireFromProject = createRequire3(path15.join(projectRoot, "__concave__.js"));
|
|
10260
10458
|
try {
|
|
10261
10459
|
requireFromProject.resolve("convex/values");
|
|
@@ -10291,7 +10489,7 @@ async function ensureConvexDependencyReady(projectRoot, commandName) {
|
|
|
10291
10489
|
}
|
|
10292
10490
|
if (!hasConvexDependency(packageJson)) {
|
|
10293
10491
|
console.error(import_picocolors9.default.red("✗ Missing dependency: convex"));
|
|
10294
|
-
console.error(import_picocolors9.default.dim(" Concave function files import `convex/values` and generated
|
|
10492
|
+
console.error(import_picocolors9.default.dim(" Concave function files import `convex/values` and generated types depend on `convex/server`."));
|
|
10295
10493
|
console.error(import_picocolors9.default.dim(` Run: ${addCommand.display}`));
|
|
10296
10494
|
process.exit(1);
|
|
10297
10495
|
}
|
|
@@ -10954,17 +11152,15 @@ async function runBunDevServer(cwd, opts, artifacts, layout) {
|
|
|
10954
11152
|
throw error;
|
|
10955
11153
|
}
|
|
10956
11154
|
};
|
|
10957
|
-
const
|
|
11155
|
+
const reloadServer = async (reason) => {
|
|
10958
11156
|
if (isRestarting)
|
|
10959
11157
|
return;
|
|
10960
11158
|
isRestarting = true;
|
|
10961
11159
|
try {
|
|
10962
|
-
console.log(import_picocolors9.default.
|
|
10963
|
-
⟳ ${reason}`));
|
|
10964
|
-
|
|
10965
|
-
|
|
10966
|
-
}
|
|
10967
|
-
await startServer();
|
|
11160
|
+
console.log(import_picocolors9.default.dim(`
|
|
11161
|
+
⟳ ${reason}`));
|
|
11162
|
+
await server.reload();
|
|
11163
|
+
console.log(import_picocolors9.default.dim(` ✓ Reloaded`));
|
|
10968
11164
|
} catch (error) {
|
|
10969
11165
|
console.error(import_picocolors9.default.red("✗ Failed to reload server:"), error.message);
|
|
10970
11166
|
} finally {
|
|
@@ -10988,7 +11184,7 @@ async function runBunDevServer(cwd, opts, artifacts, layout) {
|
|
|
10988
11184
|
try {
|
|
10989
11185
|
await generateTypes(cwd, { silent: true });
|
|
10990
11186
|
} catch {}
|
|
10991
|
-
|
|
11187
|
+
reloadServer(`File changed: ${relPath}`);
|
|
10992
11188
|
}, 300);
|
|
10993
11189
|
};
|
|
10994
11190
|
watcher.on("add", (filePath) => scheduleReload("added", filePath)).on("change", (filePath) => scheduleReload("changed", filePath)).on("unlink", (filePath) => scheduleReload("deleted", filePath));
|
|
@@ -11095,20 +11291,136 @@ process.on("SIGTERM", async () => {
|
|
|
11095
11291
|
`;
|
|
11096
11292
|
await fs12.writeFile(tempScriptPath, scriptContent, "utf8");
|
|
11097
11293
|
const bunArgs = [tempScriptPath];
|
|
11098
|
-
|
|
11099
|
-
|
|
11100
|
-
|
|
11101
|
-
|
|
11102
|
-
|
|
11103
|
-
|
|
11104
|
-
|
|
11105
|
-
|
|
11106
|
-
|
|
11107
|
-
|
|
11108
|
-
|
|
11109
|
-
|
|
11110
|
-
|
|
11294
|
+
let watcher;
|
|
11295
|
+
let bunProcess;
|
|
11296
|
+
let reloadTimer;
|
|
11297
|
+
let isRestarting = false;
|
|
11298
|
+
let isShuttingDown = false;
|
|
11299
|
+
const stopBunProcess = async () => {
|
|
11300
|
+
const activeProcess = bunProcess;
|
|
11301
|
+
if (!activeProcess || activeProcess.exitCode !== null) {
|
|
11302
|
+
return;
|
|
11303
|
+
}
|
|
11304
|
+
await new Promise((resolve3) => {
|
|
11305
|
+
let settled = false;
|
|
11306
|
+
let forceKillTimer;
|
|
11307
|
+
const finish = () => {
|
|
11308
|
+
if (settled) {
|
|
11309
|
+
return;
|
|
11310
|
+
}
|
|
11311
|
+
settled = true;
|
|
11312
|
+
if (forceKillTimer) {
|
|
11313
|
+
clearTimeout(forceKillTimer);
|
|
11314
|
+
forceKillTimer = undefined;
|
|
11315
|
+
}
|
|
11316
|
+
activeProcess.off("exit", onExit);
|
|
11317
|
+
resolve3();
|
|
11318
|
+
};
|
|
11319
|
+
const onExit = () => finish();
|
|
11320
|
+
activeProcess.once("exit", onExit);
|
|
11321
|
+
try {
|
|
11322
|
+
activeProcess.kill("SIGTERM");
|
|
11323
|
+
} catch {
|
|
11324
|
+
finish();
|
|
11325
|
+
return;
|
|
11326
|
+
}
|
|
11327
|
+
forceKillTimer = setTimeout(() => {
|
|
11328
|
+
if (settled) {
|
|
11329
|
+
return;
|
|
11330
|
+
}
|
|
11331
|
+
try {
|
|
11332
|
+
activeProcess.kill("SIGKILL");
|
|
11333
|
+
} catch {
|
|
11334
|
+
finish();
|
|
11335
|
+
}
|
|
11336
|
+
}, 2000);
|
|
11337
|
+
});
|
|
11338
|
+
};
|
|
11339
|
+
const cleanup = async () => {
|
|
11340
|
+
if (reloadTimer) {
|
|
11341
|
+
clearTimeout(reloadTimer);
|
|
11342
|
+
reloadTimer = undefined;
|
|
11343
|
+
}
|
|
11344
|
+
if (watcher) {
|
|
11345
|
+
await watcher.close();
|
|
11346
|
+
watcher = undefined;
|
|
11347
|
+
}
|
|
11348
|
+
await stopBunProcess();
|
|
11349
|
+
await fs12.unlink(tempScriptPath).catch(() => {});
|
|
11350
|
+
};
|
|
11351
|
+
const spawnBunProcess = () => {
|
|
11352
|
+
const child = spawn2("bun", bunArgs, {
|
|
11353
|
+
cwd,
|
|
11354
|
+
stdio: "inherit"
|
|
11355
|
+
});
|
|
11356
|
+
child.on("exit", (code) => {
|
|
11357
|
+
if (isRestarting || isShuttingDown) {
|
|
11358
|
+
return;
|
|
11359
|
+
}
|
|
11360
|
+
cleanup().catch(() => {}).finally(() => {
|
|
11361
|
+
process.exit(code ?? 0);
|
|
11362
|
+
});
|
|
11363
|
+
});
|
|
11364
|
+
return child;
|
|
11365
|
+
};
|
|
11366
|
+
const reloadServerViaHttp = async (reason) => {
|
|
11367
|
+
if (isRestarting || isShuttingDown) {
|
|
11368
|
+
return;
|
|
11369
|
+
}
|
|
11370
|
+
isRestarting = true;
|
|
11371
|
+
try {
|
|
11372
|
+
console.log(import_picocolors9.default.dim(`
|
|
11373
|
+
⟳ ${reason}`));
|
|
11374
|
+
const response = await fetch(`http://127.0.0.1:${port}/_dev/reload`, {
|
|
11375
|
+
method: "POST",
|
|
11376
|
+
signal: AbortSignal.timeout(5000)
|
|
11377
|
+
});
|
|
11378
|
+
if (response.ok) {
|
|
11379
|
+
console.log(import_picocolors9.default.dim(` ✓ Reloaded`));
|
|
11380
|
+
} else {
|
|
11381
|
+
throw new Error(`HTTP ${response.status}`);
|
|
11382
|
+
}
|
|
11383
|
+
} catch (error) {
|
|
11384
|
+
console.warn(import_picocolors9.default.dim(` HTTP reload failed (${error.message}), restarting process...`));
|
|
11385
|
+
await stopBunProcess();
|
|
11386
|
+
bunProcess = spawnBunProcess();
|
|
11387
|
+
} finally {
|
|
11388
|
+
isRestarting = false;
|
|
11389
|
+
}
|
|
11390
|
+
};
|
|
11391
|
+
bunProcess = spawnBunProcess();
|
|
11392
|
+
watcher = esm_default.watch(convexDir, {
|
|
11393
|
+
ignoreInitial: true,
|
|
11394
|
+
ignored: WATCH_IGNORE_PATTERNS,
|
|
11395
|
+
persistent: true
|
|
11111
11396
|
});
|
|
11397
|
+
const scheduleReload = (_event, filePath) => {
|
|
11398
|
+
if (reloadTimer) {
|
|
11399
|
+
clearTimeout(reloadTimer);
|
|
11400
|
+
}
|
|
11401
|
+
reloadTimer = setTimeout(async () => {
|
|
11402
|
+
reloadTimer = undefined;
|
|
11403
|
+
const relPath = path15.relative(cwd, filePath);
|
|
11404
|
+
try {
|
|
11405
|
+
await generateTypes(cwd, { silent: true });
|
|
11406
|
+
} catch {}
|
|
11407
|
+
await reloadServerViaHttp(`File changed: ${relPath}`);
|
|
11408
|
+
}, 300);
|
|
11409
|
+
};
|
|
11410
|
+
watcher.on("add", (filePath) => scheduleReload("added", filePath)).on("change", (filePath) => scheduleReload("changed", filePath)).on("unlink", (filePath) => scheduleReload("deleted", filePath));
|
|
11411
|
+
const shutdown = async () => {
|
|
11412
|
+
if (isShuttingDown) {
|
|
11413
|
+
return;
|
|
11414
|
+
}
|
|
11415
|
+
isShuttingDown = true;
|
|
11416
|
+
console.log(import_picocolors9.default.cyan(`
|
|
11417
|
+
|
|
11418
|
+
\uD83C\uDF0A Shutting down Concave dev server...`));
|
|
11419
|
+
await cleanup();
|
|
11420
|
+
process.exit(0);
|
|
11421
|
+
};
|
|
11422
|
+
process.on("SIGINT", shutdown);
|
|
11423
|
+
process.on("SIGTERM", shutdown);
|
|
11112
11424
|
}
|
|
11113
11425
|
async function ensureNodeSqliteReady() {
|
|
11114
11426
|
const hasFlag = process.execArgv.includes("--experimental-sqlite");
|
|
@@ -11261,17 +11573,15 @@ async function runNodeDevServer(cwd, opts, artifacts, layout) {
|
|
|
11261
11573
|
throw error;
|
|
11262
11574
|
}
|
|
11263
11575
|
};
|
|
11264
|
-
const
|
|
11576
|
+
const reloadServer = async (reason) => {
|
|
11265
11577
|
if (isRestarting)
|
|
11266
11578
|
return;
|
|
11267
11579
|
isRestarting = true;
|
|
11268
11580
|
try {
|
|
11269
|
-
console.log(import_picocolors9.default.
|
|
11270
|
-
⟳ ${reason}`));
|
|
11271
|
-
|
|
11272
|
-
|
|
11273
|
-
}
|
|
11274
|
-
await startServer();
|
|
11581
|
+
console.log(import_picocolors9.default.dim(`
|
|
11582
|
+
⟳ ${reason}`));
|
|
11583
|
+
await server.reload();
|
|
11584
|
+
console.log(import_picocolors9.default.dim(` ✓ Reloaded`));
|
|
11275
11585
|
} catch (error) {
|
|
11276
11586
|
console.error(import_picocolors9.default.red("✗ Failed to reload server:"), error.message);
|
|
11277
11587
|
} finally {
|
|
@@ -11295,7 +11605,7 @@ async function runNodeDevServer(cwd, opts, artifacts, layout) {
|
|
|
11295
11605
|
try {
|
|
11296
11606
|
await generateTypes(cwd, { silent: true });
|
|
11297
11607
|
} catch {}
|
|
11298
|
-
|
|
11608
|
+
reloadServer(`File changed: ${relPath}`);
|
|
11299
11609
|
}, 300);
|
|
11300
11610
|
};
|
|
11301
11611
|
watcher.on("add", (filePath) => scheduleReload("added", filePath)).on("change", (filePath) => scheduleReload("changed", filePath)).on("unlink", (filePath) => scheduleReload("deleted", filePath));
|
|
@@ -11411,20 +11721,136 @@ process.on("SIGTERM", async () => {
|
|
|
11411
11721
|
await fs12.writeFile(tempScriptPath, scriptContent, "utf8");
|
|
11412
11722
|
const nodeArgs = ["--experimental-sqlite", "--import", tsxLoaderPath, tempScriptPath];
|
|
11413
11723
|
const executable = detectHostRuntime() === "node" ? process.execPath : "node";
|
|
11414
|
-
|
|
11415
|
-
|
|
11416
|
-
|
|
11417
|
-
|
|
11418
|
-
|
|
11419
|
-
|
|
11420
|
-
|
|
11421
|
-
|
|
11422
|
-
|
|
11423
|
-
|
|
11424
|
-
|
|
11425
|
-
|
|
11426
|
-
|
|
11724
|
+
let watcher;
|
|
11725
|
+
let nodeProcess;
|
|
11726
|
+
let reloadTimer;
|
|
11727
|
+
let isRestarting = false;
|
|
11728
|
+
let isShuttingDown = false;
|
|
11729
|
+
const stopNodeProcess = async () => {
|
|
11730
|
+
const activeProcess = nodeProcess;
|
|
11731
|
+
if (!activeProcess || activeProcess.exitCode !== null) {
|
|
11732
|
+
return;
|
|
11733
|
+
}
|
|
11734
|
+
await new Promise((resolve3) => {
|
|
11735
|
+
let settled = false;
|
|
11736
|
+
let forceKillTimer;
|
|
11737
|
+
const finish = () => {
|
|
11738
|
+
if (settled) {
|
|
11739
|
+
return;
|
|
11740
|
+
}
|
|
11741
|
+
settled = true;
|
|
11742
|
+
if (forceKillTimer) {
|
|
11743
|
+
clearTimeout(forceKillTimer);
|
|
11744
|
+
forceKillTimer = undefined;
|
|
11745
|
+
}
|
|
11746
|
+
activeProcess.off("exit", onExit);
|
|
11747
|
+
resolve3();
|
|
11748
|
+
};
|
|
11749
|
+
const onExit = () => finish();
|
|
11750
|
+
activeProcess.once("exit", onExit);
|
|
11751
|
+
try {
|
|
11752
|
+
activeProcess.kill("SIGTERM");
|
|
11753
|
+
} catch {
|
|
11754
|
+
finish();
|
|
11755
|
+
return;
|
|
11756
|
+
}
|
|
11757
|
+
forceKillTimer = setTimeout(() => {
|
|
11758
|
+
if (settled) {
|
|
11759
|
+
return;
|
|
11760
|
+
}
|
|
11761
|
+
try {
|
|
11762
|
+
activeProcess.kill("SIGKILL");
|
|
11763
|
+
} catch {
|
|
11764
|
+
finish();
|
|
11765
|
+
}
|
|
11766
|
+
}, 2000);
|
|
11767
|
+
});
|
|
11768
|
+
};
|
|
11769
|
+
const cleanup = async () => {
|
|
11770
|
+
if (reloadTimer) {
|
|
11771
|
+
clearTimeout(reloadTimer);
|
|
11772
|
+
reloadTimer = undefined;
|
|
11773
|
+
}
|
|
11774
|
+
if (watcher) {
|
|
11775
|
+
await watcher.close();
|
|
11776
|
+
watcher = undefined;
|
|
11777
|
+
}
|
|
11778
|
+
await stopNodeProcess();
|
|
11779
|
+
await fs12.unlink(tempScriptPath).catch(() => {});
|
|
11780
|
+
};
|
|
11781
|
+
const spawnNodeProcess = () => {
|
|
11782
|
+
const child = spawn2(executable, nodeArgs, {
|
|
11783
|
+
cwd,
|
|
11784
|
+
stdio: "inherit"
|
|
11785
|
+
});
|
|
11786
|
+
child.on("exit", (code) => {
|
|
11787
|
+
if (isRestarting || isShuttingDown) {
|
|
11788
|
+
return;
|
|
11789
|
+
}
|
|
11790
|
+
cleanup().catch(() => {}).finally(() => {
|
|
11791
|
+
process.exit(code ?? 0);
|
|
11792
|
+
});
|
|
11793
|
+
});
|
|
11794
|
+
return child;
|
|
11795
|
+
};
|
|
11796
|
+
const reloadServerViaHttp = async (reason) => {
|
|
11797
|
+
if (isRestarting || isShuttingDown) {
|
|
11798
|
+
return;
|
|
11799
|
+
}
|
|
11800
|
+
isRestarting = true;
|
|
11801
|
+
try {
|
|
11802
|
+
console.log(import_picocolors9.default.dim(`
|
|
11803
|
+
⟳ ${reason}`));
|
|
11804
|
+
const response = await fetch(`http://127.0.0.1:${port}/_dev/reload`, {
|
|
11805
|
+
method: "POST",
|
|
11806
|
+
signal: AbortSignal.timeout(5000)
|
|
11807
|
+
});
|
|
11808
|
+
if (response.ok) {
|
|
11809
|
+
console.log(import_picocolors9.default.dim(` ✓ Reloaded`));
|
|
11810
|
+
} else {
|
|
11811
|
+
throw new Error(`HTTP ${response.status}`);
|
|
11812
|
+
}
|
|
11813
|
+
} catch (error) {
|
|
11814
|
+
console.warn(import_picocolors9.default.dim(` HTTP reload failed (${error.message}), restarting process...`));
|
|
11815
|
+
await stopNodeProcess();
|
|
11816
|
+
nodeProcess = spawnNodeProcess();
|
|
11817
|
+
} finally {
|
|
11818
|
+
isRestarting = false;
|
|
11819
|
+
}
|
|
11820
|
+
};
|
|
11821
|
+
nodeProcess = spawnNodeProcess();
|
|
11822
|
+
watcher = esm_default.watch(convexDir, {
|
|
11823
|
+
ignoreInitial: true,
|
|
11824
|
+
ignored: WATCH_IGNORE_PATTERNS,
|
|
11825
|
+
persistent: true
|
|
11427
11826
|
});
|
|
11827
|
+
const scheduleReload = (_event, filePath) => {
|
|
11828
|
+
if (reloadTimer) {
|
|
11829
|
+
clearTimeout(reloadTimer);
|
|
11830
|
+
}
|
|
11831
|
+
reloadTimer = setTimeout(async () => {
|
|
11832
|
+
reloadTimer = undefined;
|
|
11833
|
+
const relPath = path15.relative(cwd, filePath);
|
|
11834
|
+
try {
|
|
11835
|
+
await generateTypes(cwd, { silent: true });
|
|
11836
|
+
} catch {}
|
|
11837
|
+
await reloadServerViaHttp(`File changed: ${relPath}`);
|
|
11838
|
+
}, 300);
|
|
11839
|
+
};
|
|
11840
|
+
watcher.on("add", (filePath) => scheduleReload("added", filePath)).on("change", (filePath) => scheduleReload("changed", filePath)).on("unlink", (filePath) => scheduleReload("deleted", filePath));
|
|
11841
|
+
const shutdown = async () => {
|
|
11842
|
+
if (isShuttingDown) {
|
|
11843
|
+
return;
|
|
11844
|
+
}
|
|
11845
|
+
isShuttingDown = true;
|
|
11846
|
+
console.log(import_picocolors9.default.cyan(`
|
|
11847
|
+
|
|
11848
|
+
\uD83C\uDF0A Shutting down Concave dev server...`));
|
|
11849
|
+
await cleanup();
|
|
11850
|
+
process.exit(0);
|
|
11851
|
+
};
|
|
11852
|
+
process.on("SIGINT", shutdown);
|
|
11853
|
+
process.on("SIGTERM", shutdown);
|
|
11428
11854
|
}
|
|
11429
11855
|
async function ensureWranglerConfig(cwd) {
|
|
11430
11856
|
const userConfigs = [
|