deepspace 0.4.1 → 0.4.2
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/cli.js +145 -20
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +38 -1
- package/dist/index.js +171 -69
- package/dist/index.js.map +1 -1
- package/dist/testing.d.ts +115 -0
- package/features/file-attachments/feature.json +1 -0
- package/features/file-attachments/src/useFilePreview.ts +1 -1
- package/features/integration-test/src/IntegrationTestPage.tsx +1 -0
- package/features/integration-test/src/integration.spec.ts +14 -5
- package/features/messaging/src/components/chat/MessageList.tsx +1 -1
- package/features/presence-test/src/PresenceTestPage.tsx +1 -1
- package/features/search-bar/feature.json +34 -0
- package/features/search-bar/src/SearchOverlay.tsx +710 -0
- package/features/testing/src/subrequest-burn-action.ts +6 -3
- package/package.json +1 -1
- package/scripts/add-feature.cjs +5 -4
package/dist/cli.js
CHANGED
|
@@ -187,10 +187,12 @@ var DEV_VARS_DIVIDER = "# --- not managed by the SDK; preserved across dev/test
|
|
|
187
187
|
function extractCustomDevVars(content) {
|
|
188
188
|
const lines = content.split("\n");
|
|
189
189
|
const out = [];
|
|
190
|
+
let belowDivider = false;
|
|
190
191
|
let i = 0;
|
|
191
192
|
while (i < lines.length) {
|
|
192
193
|
const line = lines[i];
|
|
193
194
|
if (line.trim() === DEV_VARS_DIVIDER.trim()) {
|
|
195
|
+
belowDivider = true;
|
|
194
196
|
i++;
|
|
195
197
|
continue;
|
|
196
198
|
}
|
|
@@ -215,7 +217,7 @@ function extractCustomDevVars(content) {
|
|
|
215
217
|
} else {
|
|
216
218
|
i++;
|
|
217
219
|
}
|
|
218
|
-
if (!SDK_MANAGED_KEYS.has(key)) {
|
|
220
|
+
if (belowDivider || !SDK_MANAGED_KEYS.has(key)) {
|
|
219
221
|
out.push(...block);
|
|
220
222
|
}
|
|
221
223
|
}
|
|
@@ -1346,6 +1348,7 @@ var test_accounts_default = defineCommand7({
|
|
|
1346
1348
|
// src/cli/commands/deploy.ts
|
|
1347
1349
|
import { defineCommand as defineCommand8 } from "citty";
|
|
1348
1350
|
import { execSync as execSync2 } from "child_process";
|
|
1351
|
+
import { randomUUID } from "crypto";
|
|
1349
1352
|
import { readFileSync as readFileSync6, readdirSync, existsSync as existsSync9 } from "fs";
|
|
1350
1353
|
import { parse as parseToml2 } from "smol-toml";
|
|
1351
1354
|
import { join as join9, resolve as resolve5, dirname } from "path";
|
|
@@ -1599,6 +1602,59 @@ function formatDeployWorkerError(status2, error) {
|
|
|
1599
1602
|
|
|
1600
1603
|
Underlying error: ${detail}`;
|
|
1601
1604
|
}
|
|
1605
|
+
var MAX_GROUP_BYTES = 40 * 1024 * 1024;
|
|
1606
|
+
var GROUP_BYTES = (() => {
|
|
1607
|
+
const raw = Number(process.env.DEEPSPACE_DEPLOY_GROUP_BYTES);
|
|
1608
|
+
const v = Number.isInteger(raw) && raw > 0 ? raw : 3 * 1024 * 1024;
|
|
1609
|
+
return Math.min(v, MAX_GROUP_BYTES);
|
|
1610
|
+
})();
|
|
1611
|
+
function packAssetGroups(assets, maxBytes) {
|
|
1612
|
+
const groups = [];
|
|
1613
|
+
let current = [];
|
|
1614
|
+
let currentBytes = 2;
|
|
1615
|
+
for (const a of assets) {
|
|
1616
|
+
const entryBytes = Buffer.byteLength(JSON.stringify(a), "utf-8") + 1;
|
|
1617
|
+
if (current.length > 0 && currentBytes + entryBytes > maxBytes) {
|
|
1618
|
+
groups.push(current);
|
|
1619
|
+
current = [];
|
|
1620
|
+
currentBytes = 2;
|
|
1621
|
+
}
|
|
1622
|
+
current.push(a);
|
|
1623
|
+
currentBytes += entryBytes;
|
|
1624
|
+
}
|
|
1625
|
+
if (current.length > 0) groups.push(current);
|
|
1626
|
+
return groups;
|
|
1627
|
+
}
|
|
1628
|
+
async function postWithRetry(url, makeInit, { attempts = 4, retryServerErrors = true } = {}) {
|
|
1629
|
+
let lastRes;
|
|
1630
|
+
let lastErr;
|
|
1631
|
+
for (let attempt = 1; attempt <= attempts; attempt++) {
|
|
1632
|
+
try {
|
|
1633
|
+
const res = await fetch(url, makeInit());
|
|
1634
|
+
const isTransient = retryServerErrors && (res.status >= 500 || res.status === 408 || res.status === 429);
|
|
1635
|
+
if (!isTransient) {
|
|
1636
|
+
return res;
|
|
1637
|
+
}
|
|
1638
|
+
lastRes = res;
|
|
1639
|
+
} catch (err) {
|
|
1640
|
+
lastErr = err;
|
|
1641
|
+
}
|
|
1642
|
+
if (attempt < attempts) {
|
|
1643
|
+
await new Promise((r) => setTimeout(r, Math.min(8e3, 500 * 2 ** (attempt - 1))));
|
|
1644
|
+
}
|
|
1645
|
+
}
|
|
1646
|
+
if (lastRes) return lastRes;
|
|
1647
|
+
throw lastErr instanceof Error ? lastErr : new Error(String(lastErr));
|
|
1648
|
+
}
|
|
1649
|
+
async function abortStagedUpload(appName, uploadId, totalGroups, token2) {
|
|
1650
|
+
try {
|
|
1651
|
+
await fetch(
|
|
1652
|
+
`${DEPLOY_URL}/api/deploy/${appName}/assets?uploadId=${uploadId}&totalGroups=${totalGroups}`,
|
|
1653
|
+
{ method: "DELETE", headers: { Authorization: `Bearer ${token2}` } }
|
|
1654
|
+
);
|
|
1655
|
+
} catch {
|
|
1656
|
+
}
|
|
1657
|
+
}
|
|
1602
1658
|
var deploy_default = defineCommand8({
|
|
1603
1659
|
meta: {
|
|
1604
1660
|
name: "deploy",
|
|
@@ -1647,7 +1703,8 @@ var deploy_default = defineCommand8({
|
|
|
1647
1703
|
execSync2("npx vite build", { cwd: appDir, stdio: "pipe" });
|
|
1648
1704
|
} catch (err) {
|
|
1649
1705
|
s.stop("Build failed");
|
|
1650
|
-
|
|
1706
|
+
const detail = [err.stdout?.toString(), err.stderr?.toString()].filter(Boolean).join("\n").trim();
|
|
1707
|
+
console.error(detail || err.message);
|
|
1651
1708
|
process.exit(1);
|
|
1652
1709
|
}
|
|
1653
1710
|
s.stop("Built");
|
|
@@ -1740,30 +1797,98 @@ var deploy_default = defineCommand8({
|
|
|
1740
1797
|
p4.log.info(`App secrets (from .dev.vars): ${userSecretNames.join(", ")}`);
|
|
1741
1798
|
}
|
|
1742
1799
|
s.start(`Deploying to ${appName}.app.space...`);
|
|
1743
|
-
const form = new FormData();
|
|
1744
|
-
form.append("worker", new Blob([workerJs], { type: "application/javascript" }), "worker.js");
|
|
1745
|
-
form.append("assets", JSON.stringify(assets));
|
|
1746
|
-
if (doManifest) {
|
|
1747
|
-
form.append("doManifest", JSON.stringify(doManifest));
|
|
1748
|
-
}
|
|
1749
|
-
if (customBindings.length) {
|
|
1750
|
-
form.append("bindingManifest", JSON.stringify(customBindings));
|
|
1751
|
-
}
|
|
1752
|
-
if (userSecretNames.length) {
|
|
1753
|
-
form.append("userSecrets", JSON.stringify(userSecrets));
|
|
1754
|
-
}
|
|
1755
1800
|
const extraRoutes = extractRunWorkerFirst(wranglerConfig);
|
|
1756
1801
|
if (extraRoutes.length) {
|
|
1757
|
-
form.append("extraRunWorkerFirst", JSON.stringify(extraRoutes));
|
|
1758
1802
|
p4.log.info(`Custom worker-first routes: ${extraRoutes.join(", ")}`);
|
|
1759
1803
|
}
|
|
1760
|
-
const
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1804
|
+
const assetGroups = packAssetGroups(assets, GROUP_BYTES);
|
|
1805
|
+
let inlineAssets = null;
|
|
1806
|
+
let uploadId = null;
|
|
1807
|
+
let totalGroups = 0;
|
|
1808
|
+
if (assetGroups.length <= 1) {
|
|
1809
|
+
inlineAssets = JSON.stringify(assets);
|
|
1810
|
+
} else {
|
|
1811
|
+
uploadId = randomUUID();
|
|
1812
|
+
totalGroups = assetGroups.length;
|
|
1813
|
+
try {
|
|
1814
|
+
for (let i = 0; i < totalGroups; i++) {
|
|
1815
|
+
const groupJson = JSON.stringify(assetGroups[i]);
|
|
1816
|
+
s.message(`Uploading assets \u2014 group ${i + 1}/${totalGroups}...`);
|
|
1817
|
+
const groupRes = await postWithRetry(
|
|
1818
|
+
`${DEPLOY_URL}/api/deploy/${appName}/assets?uploadId=${uploadId}&groupIndex=${i}&totalGroups=${totalGroups}`,
|
|
1819
|
+
() => ({
|
|
1820
|
+
method: "POST",
|
|
1821
|
+
headers: {
|
|
1822
|
+
Authorization: `Bearer ${token2}`,
|
|
1823
|
+
"Content-Type": "application/json"
|
|
1824
|
+
},
|
|
1825
|
+
body: groupJson
|
|
1826
|
+
})
|
|
1827
|
+
);
|
|
1828
|
+
if (!groupRes.ok) {
|
|
1829
|
+
const errBody = await groupRes.json().catch(() => ({}));
|
|
1830
|
+
await abortStagedUpload(appName, uploadId, totalGroups, token2);
|
|
1831
|
+
s.stop("Deploy failed");
|
|
1832
|
+
p4.cancel(
|
|
1833
|
+
`Asset upload failed on group ${i + 1}/${totalGroups}: ${errBody.error ?? `HTTP ${groupRes.status}`}`
|
|
1834
|
+
);
|
|
1835
|
+
process.exit(1);
|
|
1836
|
+
}
|
|
1837
|
+
}
|
|
1838
|
+
} catch (err) {
|
|
1839
|
+
await abortStagedUpload(appName, uploadId, totalGroups, token2);
|
|
1840
|
+
s.stop("Deploy failed");
|
|
1841
|
+
p4.cancel(`Asset upload failed (network): ${err?.message ?? err}`);
|
|
1842
|
+
process.exit(1);
|
|
1843
|
+
}
|
|
1844
|
+
s.message(`Deploying to ${appName}.app.space...`);
|
|
1845
|
+
}
|
|
1846
|
+
const makeForm = () => {
|
|
1847
|
+
const form = new FormData();
|
|
1848
|
+
form.append("worker", new Blob([workerJs], { type: "application/javascript" }), "worker.js");
|
|
1849
|
+
if (inlineAssets !== null) {
|
|
1850
|
+
form.append("assets", inlineAssets);
|
|
1851
|
+
} else {
|
|
1852
|
+
form.append("uploadId", uploadId);
|
|
1853
|
+
form.append("totalGroups", String(totalGroups));
|
|
1854
|
+
}
|
|
1855
|
+
if (doManifest) {
|
|
1856
|
+
form.append("doManifest", JSON.stringify(doManifest));
|
|
1857
|
+
}
|
|
1858
|
+
if (customBindings.length) {
|
|
1859
|
+
form.append("bindingManifest", JSON.stringify(customBindings));
|
|
1860
|
+
}
|
|
1861
|
+
if (userSecretNames.length) {
|
|
1862
|
+
form.append("userSecrets", JSON.stringify(userSecrets));
|
|
1863
|
+
}
|
|
1864
|
+
if (extraRoutes.length) {
|
|
1865
|
+
form.append("extraRunWorkerFirst", JSON.stringify(extraRoutes));
|
|
1866
|
+
}
|
|
1867
|
+
return form;
|
|
1868
|
+
};
|
|
1869
|
+
let res;
|
|
1870
|
+
try {
|
|
1871
|
+
res = await postWithRetry(
|
|
1872
|
+
`${DEPLOY_URL}/api/deploy/${appName}`,
|
|
1873
|
+
() => ({
|
|
1874
|
+
method: "POST",
|
|
1875
|
+
headers: { Authorization: `Bearer ${token2}` },
|
|
1876
|
+
body: makeForm()
|
|
1877
|
+
}),
|
|
1878
|
+
// Commit runs a real deploy — don't retry its 5xx (could double-deploy);
|
|
1879
|
+
// only a thrown fetch (dropped connection) is retried, and the staged
|
|
1880
|
+
// groups survive on the worker until this request succeeds.
|
|
1881
|
+
{ retryServerErrors: false }
|
|
1882
|
+
);
|
|
1883
|
+
} catch (err) {
|
|
1884
|
+
if (uploadId) await abortStagedUpload(appName, uploadId, totalGroups, token2);
|
|
1885
|
+
s.stop("Deploy failed");
|
|
1886
|
+
p4.cancel(`Deploy request failed: ${err?.message ?? err}`);
|
|
1887
|
+
process.exit(1);
|
|
1888
|
+
}
|
|
1765
1889
|
const body = await res.json().catch(() => ({}));
|
|
1766
1890
|
if (!res.ok || !body.success) {
|
|
1891
|
+
if (uploadId) await abortStagedUpload(appName, uploadId, totalGroups, token2);
|
|
1767
1892
|
s.stop("Deploy failed");
|
|
1768
1893
|
p4.cancel(formatDeployWorkerError(res.status, body.error));
|
|
1769
1894
|
process.exit(1);
|