@samebase/convex-hosting 0.3.2 → 0.4.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/CHANGELOG.md +17 -132
- package/README.md +188 -406
- package/dist/cli/convex.d.ts +63 -0
- package/dist/cli/convex.js +108 -0
- package/dist/cli/convex.js.map +1 -0
- package/dist/cli/files.d.ts +18 -0
- package/dist/cli/files.js +106 -0
- package/dist/cli/files.js.map +1 -0
- package/dist/cli/index.d.ts +1 -11
- package/dist/cli/index.js +3 -58
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/main.d.ts +5 -0
- package/dist/cli/main.js +377 -0
- package/dist/cli/main.js.map +1 -0
- package/dist/client/index.d.ts +8 -115
- package/dist/client/index.js +65 -242
- package/dist/client/index.js.map +1 -1
- package/dist/client/types.d.ts +5 -0
- package/dist/client/version-module.d.ts +6 -0
- package/dist/component/_generated/api.d.ts +0 -5
- package/dist/component/_generated/api.js.map +1 -1
- package/dist/component/_generated/component.d.ts +20 -18
- package/dist/component/_generated/dataModel.d.ts +0 -1
- package/dist/component/_generated/server.d.ts +12 -1
- package/dist/component/_generated/server.js +2 -0
- package/dist/component/_generated/server.js.map +1 -1
- package/dist/component/convex.config.d.ts +0 -1
- package/dist/component/lib.d.ts +175 -156
- package/dist/component/lib.js +396 -710
- package/dist/component/lib.js.map +1 -1
- package/dist/component/schema.d.ts +76 -72
- package/dist/component/schema.js +35 -59
- package/dist/component/schema.js.map +1 -1
- package/dist/workers-shared/asset-worker/src/analytics.d.ts +39 -0
- package/dist/workers-shared/asset-worker/src/analytics.js +86 -0
- package/dist/workers-shared/asset-worker/src/analytics.js.map +1 -0
- package/dist/workers-shared/asset-worker/src/compatibility-flags.d.ts +19 -0
- package/dist/workers-shared/asset-worker/src/compatibility-flags.js +29 -0
- package/dist/workers-shared/asset-worker/src/compatibility-flags.js.map +1 -0
- package/dist/workers-shared/asset-worker/src/configuration.d.ts +3 -0
- package/dist/workers-shared/asset-worker/src/configuration.js +30 -0
- package/dist/workers-shared/asset-worker/src/configuration.js.map +1 -0
- package/dist/workers-shared/asset-worker/src/constants.d.ts +1 -0
- package/dist/workers-shared/asset-worker/src/constants.js +3 -0
- package/dist/workers-shared/asset-worker/src/constants.js.map +1 -0
- package/dist/workers-shared/asset-worker/src/handler.d.ts +28 -0
- package/dist/workers-shared/asset-worker/src/handler.js +717 -0
- package/dist/workers-shared/asset-worker/src/handler.js.map +1 -0
- package/dist/workers-shared/asset-worker/src/types.d.ts +13 -0
- package/dist/workers-shared/asset-worker/src/types.js +2 -0
- package/dist/workers-shared/asset-worker/src/types.js.map +1 -0
- package/dist/workers-shared/asset-worker/src/utils/base-path.d.ts +29 -0
- package/dist/workers-shared/asset-worker/src/utils/base-path.js +56 -0
- package/dist/workers-shared/asset-worker/src/utils/base-path.js.map +1 -0
- package/dist/workers-shared/asset-worker/src/utils/headers.d.ts +11 -0
- package/dist/workers-shared/asset-worker/src/utils/headers.js +77 -0
- package/dist/workers-shared/asset-worker/src/utils/headers.js.map +1 -0
- package/dist/workers-shared/asset-worker/src/utils/rules-engine.d.ts +23 -0
- package/dist/workers-shared/asset-worker/src/utils/rules-engine.js +133 -0
- package/dist/workers-shared/asset-worker/src/utils/rules-engine.js.map +1 -0
- package/dist/workers-shared/asset-worker/src/worker.d.ts +14 -0
- package/dist/workers-shared/asset-worker/src/worker.js +12 -0
- package/dist/workers-shared/asset-worker/src/worker.js.map +1 -0
- package/dist/workers-shared/utils/base-path.d.ts +32 -0
- package/dist/workers-shared/utils/base-path.js +94 -0
- package/dist/workers-shared/utils/base-path.js.map +1 -0
- package/dist/workers-shared/utils/configuration/constants.d.ts +15 -0
- package/dist/workers-shared/utils/configuration/constants.js +16 -0
- package/dist/workers-shared/utils/configuration/constants.js.map +1 -0
- package/dist/workers-shared/utils/configuration/constructConfiguration.d.ts +12 -0
- package/dist/workers-shared/utils/configuration/constructConfiguration.js +103 -0
- package/dist/workers-shared/utils/configuration/constructConfiguration.js.map +1 -0
- package/dist/workers-shared/utils/configuration/parseHeaders.d.ts +5 -0
- package/dist/workers-shared/utils/configuration/parseHeaders.js +181 -0
- package/dist/workers-shared/utils/configuration/parseHeaders.js.map +1 -0
- package/dist/workers-shared/utils/configuration/parseRedirects.d.ts +8 -0
- package/dist/workers-shared/utils/configuration/parseRedirects.js +129 -0
- package/dist/workers-shared/utils/configuration/parseRedirects.js.map +1 -0
- package/dist/workers-shared/utils/configuration/parseStaticRouting.d.ts +2 -0
- package/dist/workers-shared/utils/configuration/parseStaticRouting.js +94 -0
- package/dist/workers-shared/utils/configuration/parseStaticRouting.js.map +1 -0
- package/dist/workers-shared/utils/configuration/types.d.ts +38 -0
- package/dist/workers-shared/utils/configuration/types.js +2 -0
- package/dist/workers-shared/utils/configuration/types.js.map +1 -0
- package/dist/workers-shared/utils/configuration/validateURL.d.ts +3 -0
- package/dist/workers-shared/utils/configuration/validateURL.js +56 -0
- package/dist/workers-shared/utils/configuration/validateURL.js.map +1 -0
- package/dist/workers-shared/utils/constants.d.ts +28 -0
- package/dist/workers-shared/utils/constants.js +34 -0
- package/dist/workers-shared/utils/constants.js.map +1 -0
- package/dist/workers-shared/utils/helpers.d.ts +22 -0
- package/dist/workers-shared/utils/helpers.js +73 -0
- package/dist/workers-shared/utils/helpers.js.map +1 -0
- package/dist/workers-shared/utils/responses.d.ts +43 -0
- package/dist/workers-shared/utils/responses.js +125 -0
- package/dist/workers-shared/utils/responses.js.map +1 -0
- package/dist/workers-shared/utils/tracing.d.ts +3 -0
- package/dist/workers-shared/utils/tracing.js +29 -0
- package/dist/workers-shared/utils/tracing.js.map +1 -0
- package/dist/workers-shared/utils/types.d.ts +131 -0
- package/dist/workers-shared/utils/types.js +72 -0
- package/dist/workers-shared/utils/types.js.map +1 -0
- package/package.json +21 -37
- package/INTEGRATION.md +0 -399
- package/dist/cli/args.d.ts +0 -28
- package/dist/cli/args.d.ts.map +0 -1
- package/dist/cli/args.js +0 -148
- package/dist/cli/args.js.map +0 -1
- package/dist/cli/argumentChunks.d.ts +0 -3
- package/dist/cli/argumentChunks.d.ts.map +0 -1
- package/dist/cli/argumentChunks.js +0 -29
- package/dist/cli/argumentChunks.js.map +0 -1
- package/dist/cli/collectFiles.d.ts +0 -10
- package/dist/cli/collectFiles.d.ts.map +0 -1
- package/dist/cli/collectFiles.js +0 -53
- package/dist/cli/collectFiles.js.map +0 -1
- package/dist/cli/commands.d.ts +0 -8
- package/dist/cli/commands.d.ts.map +0 -1
- package/dist/cli/commands.js +0 -56
- package/dist/cli/commands.js.map +0 -1
- package/dist/cli/componentName.d.ts +0 -32
- package/dist/cli/componentName.d.ts.map +0 -1
- package/dist/cli/componentName.js +0 -43
- package/dist/cli/componentName.js.map +0 -1
- package/dist/cli/deploy.d.ts +0 -16
- package/dist/cli/deploy.d.ts.map +0 -1
- package/dist/cli/deploy.js +0 -283
- package/dist/cli/deploy.js.map +0 -1
- package/dist/cli/deployEnvironment.d.ts +0 -10
- package/dist/cli/deployEnvironment.d.ts.map +0 -1
- package/dist/cli/deployEnvironment.js +0 -12
- package/dist/cli/deployEnvironment.js.map +0 -1
- package/dist/cli/index.d.ts.map +0 -1
- package/dist/cli/upload.d.ts +0 -22
- package/dist/cli/upload.d.ts.map +0 -1
- package/dist/cli/upload.js +0 -630
- package/dist/cli/upload.js.map +0 -1
- package/dist/client/_generated/_ignore.d.ts +0 -1
- package/dist/client/_generated/_ignore.d.ts.map +0 -1
- package/dist/client/_generated/_ignore.js +0 -3
- package/dist/client/_generated/_ignore.js.map +0 -1
- package/dist/client/index.d.ts.map +0 -1
- package/dist/component/_generated/api.d.ts.map +0 -1
- package/dist/component/_generated/component.d.ts.map +0 -1
- package/dist/component/_generated/dataModel.d.ts.map +0 -1
- package/dist/component/_generated/server.d.ts.map +0 -1
- package/dist/component/convex.config.d.ts.map +0 -1
- package/dist/component/http.d.ts +0 -4
- package/dist/component/http.d.ts.map +0 -1
- package/dist/component/http.js +0 -113
- package/dist/component/http.js.map +0 -1
- package/dist/component/lib.d.ts.map +0 -1
- package/dist/component/schema.d.ts.map +0 -1
- package/dist/component/serving.d.ts +0 -23
- package/dist/component/serving.d.ts.map +0 -1
- package/dist/component/serving.js +0 -161
- package/dist/component/serving.js.map +0 -1
- package/dist/react/index.d.ts +0 -59
- package/dist/react/index.d.ts.map +0 -1
- package/dist/react/index.js +0 -137
- package/dist/react/index.js.map +0 -1
- package/src/cli/args.test.ts +0 -79
- package/src/cli/args.ts +0 -153
- package/src/cli/argumentChunks.test.ts +0 -27
- package/src/cli/argumentChunks.ts +0 -40
- package/src/cli/collectFiles.test.ts +0 -26
- package/src/cli/collectFiles.ts +0 -59
- package/src/cli/commands.ts +0 -68
- package/src/cli/componentName.test.ts +0 -41
- package/src/cli/componentName.ts +0 -46
- package/src/cli/deploy.ts +0 -336
- package/src/cli/deployEnvironment.test.ts +0 -27
- package/src/cli/deployEnvironment.ts +0 -17
- package/src/cli/index.ts +0 -65
- package/src/cli/upload.ts +0 -837
- package/src/client/_generated/_ignore.ts +0 -1
- package/src/client/index.test.ts +0 -549
- package/src/client/index.ts +0 -344
- package/src/client/setup.test.ts +0 -22
- package/src/component/_generated/api.ts +0 -54
- package/src/component/_generated/component.ts +0 -55
- package/src/component/_generated/dataModel.ts +0 -60
- package/src/component/_generated/server.ts +0 -156
- package/src/component/convex.config.ts +0 -3
- package/src/component/http.test.ts +0 -254
- package/src/component/http.ts +0 -133
- package/src/component/lib.test.ts +0 -1007
- package/src/component/lib.ts +0 -862
- package/src/component/schema.ts +0 -75
- package/src/component/serving.ts +0 -170
- package/src/component/setup.test.ts +0 -11
- package/src/react/index.tsx +0 -197
- package/src/test.ts +0 -23
package/src/cli/args.test.ts
DELETED
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
import { describe, expect, test } from "vite-plus/test";
|
|
2
|
-
import { buildDeployUploadArgs, parseDeployArgs, parseUploadArgs } from "./args.js";
|
|
3
|
-
|
|
4
|
-
describe("CLI argument parsing", () => {
|
|
5
|
-
test("targets named preview uploads without selecting production", () => {
|
|
6
|
-
expect(parseUploadArgs([])).toMatchObject({
|
|
7
|
-
prod: false,
|
|
8
|
-
previewName: null,
|
|
9
|
-
});
|
|
10
|
-
expect(parseUploadArgs(["--preview-name", "feature-routing"])).toMatchObject({
|
|
11
|
-
prod: false,
|
|
12
|
-
previewName: "feature-routing",
|
|
13
|
-
});
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
test.each([
|
|
17
|
-
["--prod", "--preview-name", "feature-routing"],
|
|
18
|
-
["--preview-name", "feature-routing", "--prod"],
|
|
19
|
-
])("rejects conflicting upload destinations: %s", (...args) => {
|
|
20
|
-
expect(() => parseUploadArgs(args)).toThrow("--prod and --preview-name cannot be combined");
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
test("parses and forwards deploy upload options exactly", () => {
|
|
24
|
-
const parsed = parseDeployArgs([
|
|
25
|
-
"--dist",
|
|
26
|
-
"web-dist",
|
|
27
|
-
"--component",
|
|
28
|
-
"site",
|
|
29
|
-
"--cdn",
|
|
30
|
-
"--cdn-delete-function",
|
|
31
|
-
"hosting:deleteCdnBlobs",
|
|
32
|
-
"--no-spa",
|
|
33
|
-
]);
|
|
34
|
-
|
|
35
|
-
expect(buildDeployUploadArgs(parsed)).toEqual([
|
|
36
|
-
"upload",
|
|
37
|
-
"--dist",
|
|
38
|
-
"web-dist",
|
|
39
|
-
"--component",
|
|
40
|
-
"site",
|
|
41
|
-
"--prod",
|
|
42
|
-
"--cdn",
|
|
43
|
-
"--cdn-delete-function",
|
|
44
|
-
"hosting:deleteCdnBlobs",
|
|
45
|
-
"--no-spa",
|
|
46
|
-
]);
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
test("parses upload environment and concurrency options", () => {
|
|
50
|
-
expect(
|
|
51
|
-
parseUploadArgs([
|
|
52
|
-
"--prod",
|
|
53
|
-
"--component",
|
|
54
|
-
"site",
|
|
55
|
-
"--concurrency",
|
|
56
|
-
"8",
|
|
57
|
-
"--build-command",
|
|
58
|
-
"npm run build:web",
|
|
59
|
-
]),
|
|
60
|
-
).toMatchObject({
|
|
61
|
-
prod: true,
|
|
62
|
-
component: "site",
|
|
63
|
-
concurrency: 8,
|
|
64
|
-
build: true,
|
|
65
|
-
buildCommand: "npm run build:web",
|
|
66
|
-
});
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
test.each([
|
|
70
|
-
["missing preview name", () => parseUploadArgs(["--preview-name"])],
|
|
71
|
-
["invalid preview name", () => parseUploadArgs(["--preview-name", "--prod"])],
|
|
72
|
-
["upload", () => parseUploadArgs(["--dist", "--prod"])],
|
|
73
|
-
["deploy", () => parseDeployArgs(["--cdn-delete-function", "--no-spa"])],
|
|
74
|
-
["unknown upload", () => parseUploadArgs(["--wat"])],
|
|
75
|
-
["unknown deploy", () => parseDeployArgs(["--wat"])],
|
|
76
|
-
])("rejects malformed %s arguments", (_name, parse) => {
|
|
77
|
-
expect(parse).toThrow();
|
|
78
|
-
});
|
|
79
|
-
});
|
package/src/cli/args.ts
DELETED
|
@@ -1,153 +0,0 @@
|
|
|
1
|
-
export interface UploadArgs {
|
|
2
|
-
dist: string;
|
|
3
|
-
component: string;
|
|
4
|
-
prod: boolean;
|
|
5
|
-
previewName: string | null;
|
|
6
|
-
build: boolean;
|
|
7
|
-
buildCommand: string;
|
|
8
|
-
cdn: boolean;
|
|
9
|
-
cdnDeleteFunction: string;
|
|
10
|
-
concurrency: number;
|
|
11
|
-
spaFallback: boolean;
|
|
12
|
-
help: boolean;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export interface DeployArgs {
|
|
16
|
-
dist: string;
|
|
17
|
-
component: string;
|
|
18
|
-
help: boolean;
|
|
19
|
-
skipBuild: boolean;
|
|
20
|
-
skipConvex: boolean;
|
|
21
|
-
cdn: boolean;
|
|
22
|
-
cdnDeleteFunction: string;
|
|
23
|
-
spaFallback: boolean;
|
|
24
|
-
buildCommand: string;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
function optionValue(args: string[], index: number, option: string): string {
|
|
28
|
-
const value = args[index + 1];
|
|
29
|
-
if (!value || value.startsWith("-")) {
|
|
30
|
-
throw new Error(`${option} requires a value`);
|
|
31
|
-
}
|
|
32
|
-
return value;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
export function parseUploadArgs(args: string[]): UploadArgs {
|
|
36
|
-
const result: UploadArgs = {
|
|
37
|
-
dist: "./dist",
|
|
38
|
-
component: "hosting",
|
|
39
|
-
prod: false,
|
|
40
|
-
previewName: null,
|
|
41
|
-
build: false,
|
|
42
|
-
buildCommand: "npm run build",
|
|
43
|
-
cdn: false,
|
|
44
|
-
cdnDeleteFunction: "",
|
|
45
|
-
concurrency: 5,
|
|
46
|
-
spaFallback: true,
|
|
47
|
-
help: false,
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
for (let i = 0; i < args.length; i++) {
|
|
51
|
-
const arg = args[i];
|
|
52
|
-
if (arg === "--help" || arg === "-h") {
|
|
53
|
-
result.help = true;
|
|
54
|
-
} else if (arg === "--dist" || arg === "-d") {
|
|
55
|
-
result.dist = optionValue(args, i, arg);
|
|
56
|
-
i++;
|
|
57
|
-
} else if (arg === "--component" || arg === "-c") {
|
|
58
|
-
result.component = optionValue(args, i, arg);
|
|
59
|
-
i++;
|
|
60
|
-
} else if (arg === "--preview-name") {
|
|
61
|
-
result.previewName = optionValue(args, i, arg);
|
|
62
|
-
i++;
|
|
63
|
-
} else if (arg === "--prod") {
|
|
64
|
-
result.prod = true;
|
|
65
|
-
} else if (arg === "--no-prod" || arg === "--dev") {
|
|
66
|
-
result.prod = false;
|
|
67
|
-
} else if (arg === "--build" || arg === "-b") {
|
|
68
|
-
result.build = true;
|
|
69
|
-
} else if (arg === "--build-command") {
|
|
70
|
-
result.buildCommand = optionValue(args, i, arg);
|
|
71
|
-
result.build = true;
|
|
72
|
-
i++;
|
|
73
|
-
} else if (arg === "--no-spa") {
|
|
74
|
-
result.spaFallback = false;
|
|
75
|
-
} else if (arg === "--spa") {
|
|
76
|
-
result.spaFallback = true;
|
|
77
|
-
} else if (arg === "--cdn") {
|
|
78
|
-
result.cdn = true;
|
|
79
|
-
} else if (arg === "--cdn-delete-function") {
|
|
80
|
-
result.cdnDeleteFunction = optionValue(args, i, arg);
|
|
81
|
-
i++;
|
|
82
|
-
} else if (arg === "--concurrency" || arg === "-j") {
|
|
83
|
-
const value = optionValue(args, i, arg);
|
|
84
|
-
const concurrency = Number(value);
|
|
85
|
-
if (!Number.isInteger(concurrency) || concurrency <= 0) {
|
|
86
|
-
throw new Error(`${arg} must be a positive integer`);
|
|
87
|
-
}
|
|
88
|
-
result.concurrency = concurrency;
|
|
89
|
-
i++;
|
|
90
|
-
} else {
|
|
91
|
-
throw new Error(`Unknown upload option: ${arg}`);
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
if (result.prod && result.previewName !== null)
|
|
95
|
-
throw new Error("--prod and --preview-name cannot be combined");
|
|
96
|
-
return result;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
export function parseDeployArgs(args: string[]): DeployArgs {
|
|
100
|
-
const result: DeployArgs = {
|
|
101
|
-
dist: "./dist",
|
|
102
|
-
component: "hosting",
|
|
103
|
-
help: false,
|
|
104
|
-
skipBuild: false,
|
|
105
|
-
skipConvex: false,
|
|
106
|
-
cdn: false,
|
|
107
|
-
cdnDeleteFunction: "",
|
|
108
|
-
spaFallback: true,
|
|
109
|
-
buildCommand: "npm run build",
|
|
110
|
-
};
|
|
111
|
-
|
|
112
|
-
for (let i = 0; i < args.length; i++) {
|
|
113
|
-
const arg = args[i];
|
|
114
|
-
if (arg === "--help" || arg === "-h") {
|
|
115
|
-
result.help = true;
|
|
116
|
-
} else if (arg === "--dist" || arg === "-d") {
|
|
117
|
-
result.dist = optionValue(args, i, arg);
|
|
118
|
-
i++;
|
|
119
|
-
} else if (arg === "--component" || arg === "-c") {
|
|
120
|
-
result.component = optionValue(args, i, arg);
|
|
121
|
-
i++;
|
|
122
|
-
} else if (arg === "--skip-build") {
|
|
123
|
-
result.skipBuild = true;
|
|
124
|
-
} else if (arg === "--skip-convex") {
|
|
125
|
-
result.skipConvex = true;
|
|
126
|
-
} else if (arg === "--cdn") {
|
|
127
|
-
result.cdn = true;
|
|
128
|
-
} else if (arg === "--cdn-delete-function") {
|
|
129
|
-
result.cdnDeleteFunction = optionValue(args, i, arg);
|
|
130
|
-
i++;
|
|
131
|
-
} else if (arg === "--no-spa") {
|
|
132
|
-
result.spaFallback = false;
|
|
133
|
-
} else if (arg === "--spa") {
|
|
134
|
-
result.spaFallback = true;
|
|
135
|
-
} else if (arg === "--build-command") {
|
|
136
|
-
result.buildCommand = optionValue(args, i, arg);
|
|
137
|
-
i++;
|
|
138
|
-
} else {
|
|
139
|
-
throw new Error(`Unknown deploy option: ${arg}`);
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
return result;
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
export function buildDeployUploadArgs(args: DeployArgs): string[] {
|
|
146
|
-
const uploadArgs = ["upload", "--dist", args.dist, "--component", args.component, "--prod"];
|
|
147
|
-
if (args.cdn) uploadArgs.push("--cdn");
|
|
148
|
-
if (args.cdnDeleteFunction) {
|
|
149
|
-
uploadArgs.push("--cdn-delete-function", args.cdnDeleteFunction);
|
|
150
|
-
}
|
|
151
|
-
if (!args.spaFallback) uploadArgs.push("--no-spa");
|
|
152
|
-
return uploadArgs;
|
|
153
|
-
}
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import { describe, expect, test } from "vite-plus/test";
|
|
2
|
-
import { chunkBySerializedArgument, MAX_CONVEX_ARGUMENT_BYTES } from "./argumentChunks.js";
|
|
3
|
-
|
|
4
|
-
describe("chunkBySerializedArgument", () => {
|
|
5
|
-
test("keeps every serialized command argument within the portable limit", () => {
|
|
6
|
-
const records = Array.from({ length: 200 }, (_, index) => ({
|
|
7
|
-
path: `/assets/${index}-${"x".repeat(180)}.js`,
|
|
8
|
-
deploymentId: "deployment",
|
|
9
|
-
}));
|
|
10
|
-
|
|
11
|
-
const chunks = chunkBySerializedArgument(records, (assets) => ({ assets }));
|
|
12
|
-
|
|
13
|
-
expect(chunks.length).toBeGreaterThan(1);
|
|
14
|
-
expect(chunks.flat()).toEqual(records);
|
|
15
|
-
for (const assets of chunks) {
|
|
16
|
-
expect(Buffer.byteLength(JSON.stringify({ assets }))).toBeLessThanOrEqual(
|
|
17
|
-
MAX_CONVEX_ARGUMENT_BYTES,
|
|
18
|
-
);
|
|
19
|
-
}
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
test("rejects one record that cannot fit safely", () => {
|
|
23
|
-
expect(() =>
|
|
24
|
-
chunkBySerializedArgument(["x".repeat(200)], (values) => ({ values }), 100),
|
|
25
|
-
).toThrow("Shorten the asset path");
|
|
26
|
-
});
|
|
27
|
-
});
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
// Windows limits the complete command line to roughly 32 KiB. Keep each JSON
|
|
2
|
-
// argument below 20 KiB so the Node executable, Convex flags, and paths still
|
|
3
|
-
// have comfortable headroom on every supported platform.
|
|
4
|
-
export const MAX_CONVEX_ARGUMENT_BYTES = 20 * 1024;
|
|
5
|
-
|
|
6
|
-
export function chunkBySerializedArgument<T>(
|
|
7
|
-
items: T[],
|
|
8
|
-
makeArgs: (chunk: T[]) => Record<string, unknown>,
|
|
9
|
-
maxBytes = MAX_CONVEX_ARGUMENT_BYTES,
|
|
10
|
-
): T[][] {
|
|
11
|
-
const chunks: T[][] = [];
|
|
12
|
-
let current: T[] = [];
|
|
13
|
-
|
|
14
|
-
for (const item of items) {
|
|
15
|
-
const candidate = [...current, item];
|
|
16
|
-
const candidateBytes = Buffer.byteLength(JSON.stringify(makeArgs(candidate)));
|
|
17
|
-
if (candidateBytes <= maxBytes) {
|
|
18
|
-
current = candidate;
|
|
19
|
-
continue;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
if (current.length === 0) {
|
|
23
|
-
throw new Error(
|
|
24
|
-
`One upload record needs ${candidateBytes} bytes, which exceeds the safe Convex CLI argument limit of ${maxBytes} bytes. Shorten the asset path.`,
|
|
25
|
-
);
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
chunks.push(current);
|
|
29
|
-
current = [item];
|
|
30
|
-
const singleBytes = Buffer.byteLength(JSON.stringify(makeArgs(current)));
|
|
31
|
-
if (singleBytes > maxBytes) {
|
|
32
|
-
throw new Error(
|
|
33
|
-
`One upload record needs ${singleBytes} bytes, which exceeds the safe Convex CLI argument limit of ${maxBytes} bytes. Shorten the asset path.`,
|
|
34
|
-
);
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
if (current.length > 0) chunks.push(current);
|
|
39
|
-
return chunks;
|
|
40
|
-
}
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "fs";
|
|
2
|
-
import { tmpdir } from "os";
|
|
3
|
-
import { join } from "path";
|
|
4
|
-
import { afterEach, describe, expect, test } from "vite-plus/test";
|
|
5
|
-
import { collectFiles } from "./collectFiles.js";
|
|
6
|
-
|
|
7
|
-
describe("collectFiles", () => {
|
|
8
|
-
let distDir: string;
|
|
9
|
-
|
|
10
|
-
afterEach(() => {
|
|
11
|
-
rmSync(distDir, { recursive: true, force: true });
|
|
12
|
-
});
|
|
13
|
-
|
|
14
|
-
test("skips hosting rule files at the root of the build output", () => {
|
|
15
|
-
distDir = mkdtempSync(join(tmpdir(), "convex-hosting-dist-"));
|
|
16
|
-
mkdirSync(join(distDir, "docs"));
|
|
17
|
-
for (const path of ["index.html", "_headers", "_redirects", "docs/_headers"]) {
|
|
18
|
-
writeFileSync(join(distDir, path), "");
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
const { files, skipped } = collectFiles(distDir);
|
|
22
|
-
|
|
23
|
-
expect(files.map((file) => file.path).sort()).toEqual(["/docs/_headers", "/index.html"]);
|
|
24
|
-
expect(skipped.sort()).toEqual(["/_headers", "/_redirects"]);
|
|
25
|
-
});
|
|
26
|
-
});
|
package/src/cli/collectFiles.ts
DELETED
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
import { readdirSync } from "fs";
|
|
2
|
-
import { extname, join, relative } from "path";
|
|
3
|
-
|
|
4
|
-
const MIME_TYPES: Record<string, string> = {
|
|
5
|
-
".html": "text/html; charset=utf-8",
|
|
6
|
-
".js": "application/javascript; charset=utf-8",
|
|
7
|
-
".mjs": "application/javascript; charset=utf-8",
|
|
8
|
-
".css": "text/css; charset=utf-8",
|
|
9
|
-
".json": "application/json; charset=utf-8",
|
|
10
|
-
".png": "image/png",
|
|
11
|
-
".jpg": "image/jpeg",
|
|
12
|
-
".jpeg": "image/jpeg",
|
|
13
|
-
".gif": "image/gif",
|
|
14
|
-
".svg": "image/svg+xml",
|
|
15
|
-
".ico": "image/x-icon",
|
|
16
|
-
".webp": "image/webp",
|
|
17
|
-
".woff": "font/woff",
|
|
18
|
-
".woff2": "font/woff2",
|
|
19
|
-
".ttf": "font/ttf",
|
|
20
|
-
".txt": "text/plain; charset=utf-8",
|
|
21
|
-
".map": "application/json",
|
|
22
|
-
".webmanifest": "application/manifest+json",
|
|
23
|
-
".xml": "application/xml",
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
// Cloudflare and Netlify read these files at the root of the build output as hosting rules and
|
|
27
|
-
// never serve them. This package does not apply them, so it does not upload them either.
|
|
28
|
-
const HOSTING_RULE_FILES = new Set(["/_headers", "/_redirects"]);
|
|
29
|
-
|
|
30
|
-
export type CollectedFile = { path: string; localPath: string; contentType: string };
|
|
31
|
-
|
|
32
|
-
export function collectFiles(distDir: string): {
|
|
33
|
-
files: CollectedFile[];
|
|
34
|
-
skipped: string[];
|
|
35
|
-
} {
|
|
36
|
-
const files: CollectedFile[] = [];
|
|
37
|
-
const skipped: string[] = [];
|
|
38
|
-
const visit = (dir: string) => {
|
|
39
|
-
for (const entry of readdirSync(dir, { withFileTypes: true })) {
|
|
40
|
-
const localPath = join(dir, entry.name);
|
|
41
|
-
if (entry.isDirectory()) {
|
|
42
|
-
visit(localPath);
|
|
43
|
-
} else if (entry.isFile()) {
|
|
44
|
-
const path = "/" + relative(distDir, localPath).replace(/\\/g, "/");
|
|
45
|
-
if (HOSTING_RULE_FILES.has(path)) {
|
|
46
|
-
skipped.push(path);
|
|
47
|
-
continue;
|
|
48
|
-
}
|
|
49
|
-
files.push({
|
|
50
|
-
path,
|
|
51
|
-
localPath,
|
|
52
|
-
contentType: MIME_TYPES[extname(localPath).toLowerCase()] || "application/octet-stream",
|
|
53
|
-
});
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
};
|
|
57
|
-
visit(distDir);
|
|
58
|
-
return { files, skipped };
|
|
59
|
-
}
|
package/src/cli/commands.ts
DELETED
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
import { execFile, execFileSync, spawnSync } from "child_process";
|
|
2
|
-
import { createRequire } from "module";
|
|
3
|
-
import { dirname, join, resolve } from "path";
|
|
4
|
-
import { fileURLToPath } from "url";
|
|
5
|
-
|
|
6
|
-
const requireFromCwd = createRequire(join(process.cwd(), "package.json"));
|
|
7
|
-
|
|
8
|
-
function convexBinPath(): string {
|
|
9
|
-
const packageJsonPath = requireFromCwd.resolve("convex/package.json");
|
|
10
|
-
return join(dirname(packageJsonPath), "bin", "main.js");
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
function shellCommand(command: string): { command: string; args: string[] } {
|
|
14
|
-
return process.platform === "win32"
|
|
15
|
-
? { command: "cmd.exe", args: ["/d", "/s", "/c", command] }
|
|
16
|
-
: { command: "sh", args: ["-c", command] };
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export function runConvex(args: string[]): string {
|
|
20
|
-
return execFileSync(process.execPath, [convexBinPath(), ...args], {
|
|
21
|
-
encoding: "utf-8",
|
|
22
|
-
stdio: ["pipe", "pipe", "pipe"],
|
|
23
|
-
}).trim();
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
export function runConvexAsync(args: string[], options: { quiet?: boolean } = {}): Promise<string> {
|
|
27
|
-
return new Promise((resolve, reject) => {
|
|
28
|
-
execFile(
|
|
29
|
-
process.execPath,
|
|
30
|
-
[convexBinPath(), ...args],
|
|
31
|
-
{ encoding: "utf-8" },
|
|
32
|
-
(error, stdout, stderr) => {
|
|
33
|
-
if (error) {
|
|
34
|
-
// Callers that probe optional components (e.g. resolving a legacy
|
|
35
|
-
// instance name) pass quiet so an expected miss isn't logged as a
|
|
36
|
-
// failure.
|
|
37
|
-
if (!options.quiet) {
|
|
38
|
-
console.error("Convex run failed:", stderr || stdout);
|
|
39
|
-
}
|
|
40
|
-
reject(error);
|
|
41
|
-
return;
|
|
42
|
-
}
|
|
43
|
-
resolve(stdout.trim());
|
|
44
|
-
},
|
|
45
|
-
);
|
|
46
|
-
});
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
export function spawnConvex(args: string[]): number | null {
|
|
50
|
-
return spawnSync(process.execPath, [convexBinPath(), ...args], {
|
|
51
|
-
stdio: "inherit",
|
|
52
|
-
}).status;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
export function spawnShell(command: string, env: NodeJS.ProcessEnv = process.env): number | null {
|
|
56
|
-
const cmd = shellCommand(command);
|
|
57
|
-
return spawnSync(cmd.command, cmd.args, {
|
|
58
|
-
env,
|
|
59
|
-
stdio: "inherit",
|
|
60
|
-
}).status;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
export function spawnStaticHostingCli(args: string[]): number | null {
|
|
64
|
-
const cliPath = resolve(dirname(fileURLToPath(import.meta.url)), "index.js");
|
|
65
|
-
return spawnSync(process.execPath, [cliPath, ...args], {
|
|
66
|
-
stdio: "inherit",
|
|
67
|
-
}).status;
|
|
68
|
-
}
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import { describe, expect, test } from "vite-plus/test";
|
|
2
|
-
import {
|
|
3
|
-
componentNameCandidates,
|
|
4
|
-
DEFAULT_COMPONENT_NAME,
|
|
5
|
-
isLegacyAutoDetected,
|
|
6
|
-
LEGACY_COMPONENT_NAME,
|
|
7
|
-
legacyComponentNameWarning,
|
|
8
|
-
} from "./componentName.js";
|
|
9
|
-
|
|
10
|
-
describe("component name resolution", () => {
|
|
11
|
-
test("default name also probes the legacy name", () => {
|
|
12
|
-
expect(componentNameCandidates(DEFAULT_COMPONENT_NAME)).toEqual([
|
|
13
|
-
DEFAULT_COMPONENT_NAME,
|
|
14
|
-
LEGACY_COMPONENT_NAME,
|
|
15
|
-
]);
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
test("legacy name is used verbatim without expanding", () => {
|
|
19
|
-
expect(componentNameCandidates(LEGACY_COMPONENT_NAME)).toEqual([LEGACY_COMPONENT_NAME]);
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
test("a custom name is never redirected to another instance", () => {
|
|
23
|
-
expect(componentNameCandidates("hostingV2")).toEqual(["hostingV2"]);
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
test("only an auto-detected legacy fallback warrants a warning", () => {
|
|
27
|
-
// Relied on the default, fell back to legacy: warn.
|
|
28
|
-
expect(isLegacyAutoDetected(DEFAULT_COMPONENT_NAME, LEGACY_COMPONENT_NAME)).toBe(true);
|
|
29
|
-
// Explicitly requested the legacy name (e.g. deploy forwarding it to the
|
|
30
|
-
// upload subprocess): stay silent so a single command warns at most once.
|
|
31
|
-
expect(isLegacyAutoDetected(LEGACY_COMPONENT_NAME, LEGACY_COMPONENT_NAME)).toBe(false);
|
|
32
|
-
// Resolved the default: nothing to warn about.
|
|
33
|
-
expect(isLegacyAutoDetected(DEFAULT_COMPONENT_NAME, DEFAULT_COMPONENT_NAME)).toBe(false);
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
test("the legacy warning names the instance and the current default", () => {
|
|
37
|
-
const warning = legacyComponentNameWarning(LEGACY_COMPONENT_NAME);
|
|
38
|
-
expect(warning).toContain(LEGACY_COMPONENT_NAME);
|
|
39
|
-
expect(warning).toContain(DEFAULT_COMPONENT_NAME);
|
|
40
|
-
});
|
|
41
|
-
});
|
package/src/cli/componentName.ts
DELETED
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Component instance name resolution shared by the deploy and upload commands.
|
|
3
|
-
*
|
|
4
|
-
* `@convex-dev/static-hosting` mounted the component as `staticHosting`; this
|
|
5
|
-
* package defaults to `hosting`. An app that switches packages but keeps
|
|
6
|
-
* its existing instance (`app.use(hosting, { name: "staticHosting" })`)
|
|
7
|
-
* keeps its uploaded files and URLs. Without the probe it would have to pass
|
|
8
|
-
* `--component staticHosting` on every command. Instead the CLI probes both
|
|
9
|
-
* names when the caller relied on the default, and warns when it lands on the
|
|
10
|
-
* legacy one.
|
|
11
|
-
*/
|
|
12
|
-
export const DEFAULT_COMPONENT_NAME = "hosting";
|
|
13
|
-
export const LEGACY_COMPONENT_NAME = "staticHosting";
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Instance names to probe, in order, for a requested name.
|
|
17
|
-
*
|
|
18
|
-
* Only the default request expands to include the legacy name. Any other
|
|
19
|
-
* requested name is used verbatim: an explicit custom name must never be
|
|
20
|
-
* silently redirected to a different instance.
|
|
21
|
-
*/
|
|
22
|
-
export function componentNameCandidates(requested: string): string[] {
|
|
23
|
-
if (requested !== DEFAULT_COMPONENT_NAME) return [requested];
|
|
24
|
-
return [DEFAULT_COMPONENT_NAME, LEGACY_COMPONENT_NAME];
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Whether resolving `requested` to `resolved` was a legacy-name auto-detection
|
|
29
|
-
* worth warning about. Only true when the caller relied on the default and we
|
|
30
|
-
* fell back to the legacy name — an explicitly requested name (including a
|
|
31
|
-
* command forwarding the resolved name to a subprocess) is left silent so a
|
|
32
|
-
* single `deploy` warns at most once.
|
|
33
|
-
*/
|
|
34
|
-
export function isLegacyAutoDetected(requested: string, resolved: string): boolean {
|
|
35
|
-
return requested === DEFAULT_COMPONENT_NAME && resolved === LEGACY_COMPONENT_NAME;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
/** Warning shown once when a command resolves to the legacy instance name. */
|
|
39
|
-
export function legacyComponentNameWarning(name: string): string {
|
|
40
|
-
return (
|
|
41
|
-
`⚠️ Using the component instance "${name}" (the @convex-dev/static-hosting ` +
|
|
42
|
-
`default; this package's default is "${DEFAULT_COMPONENT_NAME}").\n` +
|
|
43
|
-
` It keeps working without flags. To use the default, rename the instance ` +
|
|
44
|
-
`to "${DEFAULT_COMPONENT_NAME}" and upload your files again.`
|
|
45
|
-
);
|
|
46
|
-
}
|