sculpted 0.3.1 → 0.3.3
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 +4 -2
- package/dist/index.d.mts +3 -3
- package/dist/index.mjs +1 -1
- package/dist/{patcher-DQgKdozw.mjs → patcher-nj9VhRT-.mjs} +131 -11
- package/dist/{runtime-C911j-aR.d.mts → runtime-Cpxddehp.d.mts} +3 -2
- package/dist/runtime.d.mts +1 -1
- package/dist/runtime.mjs +530 -18
- package/dist/{sourceSyntax-U2iybN9L.d.mts → sourceSyntax-DKIh-VKA.d.mts} +1 -1
- package/dist/tsrx.d.mts +1 -1
- package/dist/{types-CdByW0ji.d.mts → types-0a4hNfAF.d.mts} +11 -1
- package/dist/ui.d.mts +7 -2
- package/dist/ui.mjs +430 -72
- package/dist/vite.d.mts +1 -1
- package/dist/vite.mjs +493 -185
- package/docs/source-writeback.md +4 -2
- package/examples/vite-preact-pandacss/src/BatchFixtures.tsx +77 -0
- package/examples/vite-preact-pandacss/src/main.tsx +2 -0
- package/examples/vite-react-pandacss/src/BatchFixtures.tsx +77 -0
- package/examples/vite-react-pandacss/src/main.tsx +2 -0
- package/package.json +3 -2
package/dist/vite.mjs
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { _ as markerClassForEditId, a as DEFAULT_JSX_SOURCE_ATTRIBUTE, c as DEFAULT_OPEN_SOURCE_ENDPOINT, d as DEFAULT_TOKEN_WRITEBACK_ENDPOINT, f as DEFAULT_WRITEBACK_ENDPOINT, l as DEFAULT_SOURCE_ATTRIBUTE, p as SCULPTED_EVENTS, r as DEFAULT_EDIT_ID_ATTRIBUTE, t as DEFAULT_COMPONENT_ATTRIBUTE, u as DEFAULT_STYLE_MODULE_ENDPOINT } from "./protocol-D5heR2QM.mjs";
|
|
2
|
-
import { S as
|
|
2
|
+
import { S as parsePandaSource, _ as createStaticCssPatch, a as createStyleModuleSourcePatch, b as hashSource, c as resolveProjectPath, d as toRelativeProjectPath$1, f as trustedManifestFilePath, g as createStaticCssBatchPatch, h as verifyProjectWritePath, i as createStyleModuleDetachPatch, l as safeProjectSourcePath, m as verifyProjectExistingPath, n as componentStyleModulePaths, o as readComponentStyleModule, p as trustedTokenSourceFilePath, r as createStyleModuleAttachPatch, s as normalizePath$1, t as createTokenConfigPatch, u as stripViteQuery, v as createInlineCssSourcePatch, w as resolveSourceParserAdapter, y as analyzePandaCssSource } from "./patcher-nj9VhRT-.mjs";
|
|
3
3
|
import ts from "typescript";
|
|
4
4
|
import { access, mkdir, readFile, writeFile } from "node:fs/promises";
|
|
5
|
-
import { loadConfigAndCreateContext } from "@pandacss/node";
|
|
6
5
|
import { dirname } from "node:path";
|
|
6
|
+
import { loadConfigAndCreateContext } from "@pandacss/node";
|
|
7
7
|
//#region src/vite/constants.ts
|
|
8
8
|
const DEFAULT_EXCLUDE = ["node_modules/**", "styled-system/**"];
|
|
9
9
|
const DEFAULT_RUNTIME_BOOTSTRAP_ENDPOINT = "/@sculpted/runtime";
|
|
@@ -281,22 +281,43 @@ async function createEditorMetadata(options) {
|
|
|
281
281
|
properties
|
|
282
282
|
};
|
|
283
283
|
}
|
|
284
|
+
function tokenSourceIdsForPandaConfigSource(options) {
|
|
285
|
+
return parsePandaConfigEditorMetadata(options).tokenSources.map((item) => item.id);
|
|
286
|
+
}
|
|
284
287
|
async function readPandaConfigSource(projectRoot, pandaConfigPath) {
|
|
285
288
|
const root = normalizePath(projectRoot).replace(/\/$/, "");
|
|
286
289
|
const candidates = pandaConfigPath ? [absoluteProjectPath(root, pandaConfigPath)] : DEFAULT_PANDA_CONFIG_FILES.map((fileName) => `${root}/${fileName}`);
|
|
287
|
-
for (const filePath of candidates)
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
290
|
+
for (const filePath of candidates) {
|
|
291
|
+
try {
|
|
292
|
+
await access(filePath);
|
|
293
|
+
} catch (error) {
|
|
294
|
+
if (isMissingFileError$2(error)) continue;
|
|
295
|
+
return {
|
|
296
|
+
ok: false,
|
|
297
|
+
reason: "panda-config-unreadable",
|
|
298
|
+
message: `Failed to access Panda config ${filePath}: ${errorMessage$1(error)}`
|
|
299
|
+
};
|
|
300
|
+
}
|
|
301
|
+
const safePath = await verifyProjectExistingPath(root, filePath);
|
|
302
|
+
if (!safePath.ok) return {
|
|
296
303
|
ok: false,
|
|
297
304
|
reason: "panda-config-unreadable",
|
|
298
|
-
message:
|
|
305
|
+
message: safePath.message
|
|
299
306
|
};
|
|
307
|
+
try {
|
|
308
|
+
return {
|
|
309
|
+
ok: true,
|
|
310
|
+
filePath,
|
|
311
|
+
sourceText: await readFile(filePath, "utf8")
|
|
312
|
+
};
|
|
313
|
+
} catch (error) {
|
|
314
|
+
if (isMissingFileError$2(error)) continue;
|
|
315
|
+
return {
|
|
316
|
+
ok: false,
|
|
317
|
+
reason: "panda-config-unreadable",
|
|
318
|
+
message: `Failed to read Panda config ${filePath}: ${errorMessage$1(error)}`
|
|
319
|
+
};
|
|
320
|
+
}
|
|
300
321
|
}
|
|
301
322
|
return {
|
|
302
323
|
ok: false,
|
|
@@ -446,7 +467,7 @@ async function resolvePandaConfigEditorMetadata(options) {
|
|
|
446
467
|
} catch (error) {
|
|
447
468
|
return {
|
|
448
469
|
ok: false,
|
|
449
|
-
message: `Failed to resolve Panda token metadata: ${errorMessage(error)}`
|
|
470
|
+
message: `Failed to resolve Panda token metadata: ${errorMessage$1(error)}`
|
|
450
471
|
};
|
|
451
472
|
}
|
|
452
473
|
}
|
|
@@ -697,7 +718,7 @@ function collectColorTokenMetadata(object, options, path = []) {
|
|
|
697
718
|
sourcePath: nextPath,
|
|
698
719
|
writable: options.writable,
|
|
699
720
|
readonlyReason: options.writable ? void 0 : "Token source target is read-only.",
|
|
700
|
-
conditions: options.kind === "semantic-token" && isJsonObject(value) ? Object.entries(value).map(([condition, conditionValue]) => ({
|
|
721
|
+
conditions: options.kind === "semantic-token" && isJsonObject$1(value) ? Object.entries(value).map(([condition, conditionValue]) => ({
|
|
701
722
|
condition,
|
|
702
723
|
value: conditionValue,
|
|
703
724
|
swatch: swatchFromJsonValue(conditionValue)
|
|
@@ -822,7 +843,7 @@ function unavailableMetadataSection(reason, message) {
|
|
|
822
843
|
message
|
|
823
844
|
};
|
|
824
845
|
}
|
|
825
|
-
function isJsonObject(value) {
|
|
846
|
+
function isJsonObject$1(value) {
|
|
826
847
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
827
848
|
}
|
|
828
849
|
function swatchFromJsonValue(value) {
|
|
@@ -848,7 +869,7 @@ function normalizePath(path) {
|
|
|
848
869
|
function isMissingFileError$2(error) {
|
|
849
870
|
return isRecord$3(error) && error.code === "ENOENT";
|
|
850
871
|
}
|
|
851
|
-
function errorMessage(error) {
|
|
872
|
+
function errorMessage$1(error) {
|
|
852
873
|
return error instanceof Error ? error.message : String(error);
|
|
853
874
|
}
|
|
854
875
|
function isRecord$3(value) {
|
|
@@ -866,10 +887,33 @@ function isJsonValue$1(value) {
|
|
|
866
887
|
return Object.values(value).every(isJsonValue$1);
|
|
867
888
|
}
|
|
868
889
|
//#endregion
|
|
890
|
+
//#region src/vite/logging.ts
|
|
891
|
+
function logUnexpectedDevServerError(message, error) {
|
|
892
|
+
console.error(`[sculpted] ${message}`, error);
|
|
893
|
+
}
|
|
894
|
+
function errorMessage(error) {
|
|
895
|
+
return error instanceof Error ? error.message : String(error);
|
|
896
|
+
}
|
|
897
|
+
//#endregion
|
|
898
|
+
//#region src/vite/requestBody.ts
|
|
899
|
+
const MAX_DEV_SERVER_JSON_BODY_BYTES = 1024 * 1024;
|
|
900
|
+
async function readRequestBody(request, maxBytes = MAX_DEV_SERVER_JSON_BODY_BYTES) {
|
|
901
|
+
if (!request[Symbol.asyncIterator]) return "";
|
|
902
|
+
let bytes = 0;
|
|
903
|
+
let body = "";
|
|
904
|
+
for await (const chunk of request) {
|
|
905
|
+
const text = typeof chunk === "string" ? chunk : Buffer.from(chunk).toString("utf8");
|
|
906
|
+
bytes += Buffer.byteLength(text);
|
|
907
|
+
if (bytes > maxBytes) throw new Error(`Request body exceeds ${maxBytes} bytes.`);
|
|
908
|
+
body += text;
|
|
909
|
+
}
|
|
910
|
+
return body;
|
|
911
|
+
}
|
|
912
|
+
//#endregion
|
|
869
913
|
//#region src/vite/sourceLocation.ts
|
|
870
914
|
async function readOpenSourceLocationRequest(request) {
|
|
871
915
|
try {
|
|
872
|
-
const body = await readRequestBody
|
|
916
|
+
const body = await readRequestBody(request);
|
|
873
917
|
const parsed = JSON.parse(body);
|
|
874
918
|
if (!isOpenSourceLocationRequest(parsed)) return {
|
|
875
919
|
ok: false,
|
|
@@ -900,6 +944,8 @@ async function resolveOpenSourceLocation(options) {
|
|
|
900
944
|
} catch {
|
|
901
945
|
return openSourceLocationFailure("file-not-found", "Component source file does not exist.", { file: toRelativeProjectPath$1(trustedPath.file, options.projectRoot) });
|
|
902
946
|
}
|
|
947
|
+
const resolvedPath = await verifyProjectExistingPath(options.projectRoot, trustedPath.file);
|
|
948
|
+
if (!resolvedPath.ok) return openSourceLocationFailure("path-outside-project", resolvedPath.message, resolvedPath.details);
|
|
903
949
|
return openSourceLocationSuccess({
|
|
904
950
|
file: trustedPath.file,
|
|
905
951
|
line,
|
|
@@ -916,6 +962,8 @@ async function resolveOpenSourceLocation(options) {
|
|
|
916
962
|
} catch {
|
|
917
963
|
return openSourceLocationFailure("file-not-found", "Source file does not exist.", { file: toRelativeProjectPath$1(safePath.file, options.projectRoot) });
|
|
918
964
|
}
|
|
965
|
+
const resolvedPath = await verifyProjectExistingPath(options.projectRoot, safePath.file);
|
|
966
|
+
if (!resolvedPath.ok) return openSourceLocationFailure("path-outside-project", resolvedPath.message, resolvedPath.details);
|
|
919
967
|
return openSourceLocationSuccess({
|
|
920
968
|
file: safePath.file,
|
|
921
969
|
line: parsed.line,
|
|
@@ -935,9 +983,9 @@ function parseSourceLocationText(source) {
|
|
|
935
983
|
ok: false,
|
|
936
984
|
response: openSourceLocationFailure("invalid-request", "Source location must include a file path.")
|
|
937
985
|
};
|
|
938
|
-
const line =
|
|
939
|
-
const column =
|
|
940
|
-
if (
|
|
986
|
+
const line = parseOptionalPositiveInteger(match[2]);
|
|
987
|
+
const column = parseOptionalPositiveInteger(match[3]);
|
|
988
|
+
if (match[2] !== void 0 && line === void 0 || match[3] !== void 0 && column === void 0) return {
|
|
941
989
|
ok: false,
|
|
942
990
|
response: openSourceLocationFailure("invalid-request", "Line and column numbers must be positive integers.")
|
|
943
991
|
};
|
|
@@ -948,6 +996,11 @@ function parseSourceLocationText(source) {
|
|
|
948
996
|
column
|
|
949
997
|
};
|
|
950
998
|
}
|
|
999
|
+
function parseOptionalPositiveInteger(value) {
|
|
1000
|
+
if (value === void 0) return void 0;
|
|
1001
|
+
const parsed = Number(value);
|
|
1002
|
+
return Number.isSafeInteger(parsed) && parsed >= 1 ? parsed : void 0;
|
|
1003
|
+
}
|
|
951
1004
|
function openSourceLocationSuccess(options) {
|
|
952
1005
|
const file = toRelativeProjectPath$1(options.file, options.projectRoot);
|
|
953
1006
|
const location = [
|
|
@@ -975,15 +1028,12 @@ function openSourceLocationFailure(code, message, details) {
|
|
|
975
1028
|
}
|
|
976
1029
|
function isOpenSourceLocationRequest(value) {
|
|
977
1030
|
if (!isRecord$2(value)) return false;
|
|
978
|
-
if (value.kind === "source") return typeof value.source === "string" && value.source.length > 0;
|
|
979
|
-
if (value.kind === "component") return typeof value.editId === "string" && value.editId.length > 0;
|
|
1031
|
+
if (value.kind === "source") return hasOnlyKeys$2(value, ["kind", "source"]) && typeof value.source === "string" && value.source.length > 0;
|
|
1032
|
+
if (value.kind === "component") return hasOnlyKeys$2(value, ["kind", "editId"]) && typeof value.editId === "string" && value.editId.length > 0;
|
|
980
1033
|
return false;
|
|
981
1034
|
}
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
let body = "";
|
|
985
|
-
for await (const chunk of request) body += typeof chunk === "string" ? chunk : Buffer.from(chunk).toString("utf8");
|
|
986
|
-
return body;
|
|
1035
|
+
function hasOnlyKeys$2(value, allowedKeys) {
|
|
1036
|
+
return Object.keys(value).every((key) => allowedKeys.includes(key));
|
|
987
1037
|
}
|
|
988
1038
|
function isRecord$2(value) {
|
|
989
1039
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
@@ -1010,10 +1060,11 @@ function registerRuntimeModuleRoutes(server, options) {
|
|
|
1010
1060
|
response.setHeader("cache-control", "no-store");
|
|
1011
1061
|
response.end(runtimeModuleSourceMap);
|
|
1012
1062
|
} catch (error) {
|
|
1063
|
+
logUnexpectedDevServerError("Failed to load Sculpted runtime module source map.", error);
|
|
1013
1064
|
response.statusCode = 404;
|
|
1014
1065
|
response.setHeader("content-type", "text/plain");
|
|
1015
1066
|
response.setHeader("cache-control", "no-store");
|
|
1016
|
-
response.end(`Failed to load Sculpted runtime module source map: ${
|
|
1067
|
+
response.end(`Failed to load Sculpted runtime module source map: ${errorMessage(error)}`);
|
|
1017
1068
|
}
|
|
1018
1069
|
});
|
|
1019
1070
|
server.middlewares.use(options.runtimeModuleEndpoint, async (_request, response) => {
|
|
@@ -1024,10 +1075,11 @@ function registerRuntimeModuleRoutes(server, options) {
|
|
|
1024
1075
|
response.setHeader("cache-control", "no-store");
|
|
1025
1076
|
response.end(runtimeModuleSource);
|
|
1026
1077
|
} catch (error) {
|
|
1078
|
+
logUnexpectedDevServerError("Failed to load Sculpted runtime module.", error);
|
|
1027
1079
|
response.statusCode = 500;
|
|
1028
1080
|
response.setHeader("content-type", "text/plain");
|
|
1029
1081
|
response.setHeader("cache-control", "no-store");
|
|
1030
|
-
response.end(`Failed to load Sculpted runtime module: ${
|
|
1082
|
+
response.end(`Failed to load Sculpted runtime module: ${errorMessage(error)}`);
|
|
1031
1083
|
}
|
|
1032
1084
|
});
|
|
1033
1085
|
server.middlewares.use(options.runtimeChunkEndpoint, async (request, response) => {
|
|
@@ -1040,16 +1092,24 @@ function registerRuntimeModuleRoutes(server, options) {
|
|
|
1040
1092
|
return;
|
|
1041
1093
|
}
|
|
1042
1094
|
try {
|
|
1095
|
+
if (!(await runtimeChunkFileNames()).has(fileName)) {
|
|
1096
|
+
response.statusCode = 404;
|
|
1097
|
+
response.setHeader("content-type", "text/plain");
|
|
1098
|
+
response.setHeader("cache-control", "no-store");
|
|
1099
|
+
response.end("Unknown Sculpted runtime chunk.");
|
|
1100
|
+
return;
|
|
1101
|
+
}
|
|
1043
1102
|
const runtimeChunkSource = await readFile(new URL(`./${fileName}`, import.meta.url), "utf8");
|
|
1044
1103
|
response.statusCode = 200;
|
|
1045
1104
|
response.setHeader("content-type", fileName.endsWith(".map") ? "application/json" : "application/javascript");
|
|
1046
1105
|
response.setHeader("cache-control", "no-store");
|
|
1047
1106
|
response.end(runtimeChunkSource);
|
|
1048
1107
|
} catch (error) {
|
|
1108
|
+
logUnexpectedDevServerError("Failed to load Sculpted runtime chunk.", error);
|
|
1049
1109
|
response.statusCode = 404;
|
|
1050
1110
|
response.setHeader("content-type", "text/plain");
|
|
1051
1111
|
response.setHeader("cache-control", "no-store");
|
|
1052
|
-
response.end(`Failed to load Sculpted runtime chunk: ${
|
|
1112
|
+
response.end(`Failed to load Sculpted runtime chunk: ${errorMessage(error)}`);
|
|
1053
1113
|
}
|
|
1054
1114
|
});
|
|
1055
1115
|
server.middlewares.use(DEFAULT_UI_MODULE_SOURCE_MAP_ENDPOINT, async (_request, response) => {
|
|
@@ -1060,10 +1120,11 @@ function registerRuntimeModuleRoutes(server, options) {
|
|
|
1060
1120
|
response.setHeader("cache-control", "no-store");
|
|
1061
1121
|
response.end(uiModuleSourceMap);
|
|
1062
1122
|
} catch (error) {
|
|
1123
|
+
logUnexpectedDevServerError("Failed to load Sculpted UI module source map.", error);
|
|
1063
1124
|
response.statusCode = 404;
|
|
1064
1125
|
response.setHeader("content-type", "text/plain");
|
|
1065
1126
|
response.setHeader("cache-control", "no-store");
|
|
1066
|
-
response.end(`Failed to load Sculpted UI module source map: ${
|
|
1127
|
+
response.end(`Failed to load Sculpted UI module source map: ${errorMessage(error)}`);
|
|
1067
1128
|
}
|
|
1068
1129
|
});
|
|
1069
1130
|
server.middlewares.use(options.uiModuleEndpoint, async (_request, response) => {
|
|
@@ -1074,10 +1135,11 @@ function registerRuntimeModuleRoutes(server, options) {
|
|
|
1074
1135
|
response.setHeader("cache-control", "no-store");
|
|
1075
1136
|
response.end(uiModuleSource);
|
|
1076
1137
|
} catch (error) {
|
|
1138
|
+
logUnexpectedDevServerError("Failed to load Sculpted UI module.", error);
|
|
1077
1139
|
response.statusCode = 500;
|
|
1078
1140
|
response.setHeader("content-type", "text/plain");
|
|
1079
1141
|
response.setHeader("cache-control", "no-store");
|
|
1080
|
-
response.end(`Failed to load Sculpted UI module: ${
|
|
1142
|
+
response.end(`Failed to load Sculpted UI module: ${errorMessage(error)}`);
|
|
1081
1143
|
}
|
|
1082
1144
|
});
|
|
1083
1145
|
}
|
|
@@ -1096,6 +1158,22 @@ function runtimeBootstrapSource(options) {
|
|
|
1096
1158
|
function rewriteInspectorModuleSource(source, runtimeChunkEndpoint, sourceMapEndpoint) {
|
|
1097
1159
|
return source.replaceAll("from \"./", `from "${runtimeChunkEndpoint}`).replace(/\/\/# sourceMappingURL=[^\r\n]+/g, `//# sourceMappingURL=${sourceMapEndpoint}`);
|
|
1098
1160
|
}
|
|
1161
|
+
async function runtimeChunkFileNames() {
|
|
1162
|
+
const [runtimeSource, uiSource] = await Promise.all([readFile(new URL("./runtime.mjs", import.meta.url), "utf8"), readFile(new URL("./ui.mjs", import.meta.url), "utf8")]);
|
|
1163
|
+
return runtimeChunkFileNamesFromSources([runtimeSource, uiSource]);
|
|
1164
|
+
}
|
|
1165
|
+
function runtimeChunkFileNamesFromSources(sources) {
|
|
1166
|
+
const fileNames = /* @__PURE__ */ new Set();
|
|
1167
|
+
for (const source of sources) for (const match of source.matchAll(/(?:from\s+|import\s*\()\s*["']\.\/([^"']+)["']/g)) {
|
|
1168
|
+
const specifier = match[1] ?? "";
|
|
1169
|
+
if (specifier.includes("/") || specifier.includes("\\") || /[?#]/.test(specifier)) continue;
|
|
1170
|
+
const fileName = runtimeChunkFileName(specifier);
|
|
1171
|
+
if (!fileName) continue;
|
|
1172
|
+
fileNames.add(fileName);
|
|
1173
|
+
if (fileName.endsWith(".mjs")) fileNames.add(`${fileName}.map`);
|
|
1174
|
+
}
|
|
1175
|
+
return fileNames;
|
|
1176
|
+
}
|
|
1099
1177
|
function runtimeChunkFileName(url) {
|
|
1100
1178
|
const fileName = (url ?? "").replace(/[?#].*$/, "").split("/").filter(Boolean).at(-1);
|
|
1101
1179
|
if (!fileName || !/^[A-Za-z0-9._-]+\.mjs(?:\.map)?$/.test(fileName)) return void 0;
|
|
@@ -1132,23 +1210,52 @@ function registerStyleModuleRoute(server, options) {
|
|
|
1132
1210
|
return;
|
|
1133
1211
|
}
|
|
1134
1212
|
let sourceText;
|
|
1213
|
+
let styleFileExists = true;
|
|
1135
1214
|
try {
|
|
1136
|
-
|
|
1215
|
+
await access(paths.paths.styleFile);
|
|
1137
1216
|
} catch (error) {
|
|
1138
|
-
if (
|
|
1217
|
+
if (isMissingFileError$1(error)) styleFileExists = false;
|
|
1218
|
+
else {
|
|
1219
|
+
logUnexpectedDevServerError("Failed to read Sculpted style module.", error);
|
|
1139
1220
|
response.statusCode = 400;
|
|
1140
1221
|
response.setHeader("content-type", "application/json");
|
|
1141
1222
|
response.setHeader("cache-control", "no-store");
|
|
1142
|
-
response.end(JSON.stringify(styleModuleFailure("write-failed", `Failed to read style module: ${
|
|
1223
|
+
response.end(JSON.stringify(styleModuleFailure("write-failed", `Failed to read style module: ${errorMessage(error)}`)));
|
|
1143
1224
|
return;
|
|
1144
1225
|
}
|
|
1145
1226
|
}
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1227
|
+
if (styleFileExists) {
|
|
1228
|
+
const safePath = await verifyProjectExistingPath(options.projectRoot, paths.paths.styleFile);
|
|
1229
|
+
if (!safePath.ok) {
|
|
1230
|
+
response.statusCode = 400;
|
|
1231
|
+
response.setHeader("content-type", "application/json");
|
|
1232
|
+
response.setHeader("cache-control", "no-store");
|
|
1233
|
+
response.end(JSON.stringify(styleModuleFailure(safePath.code, safePath.message, safePath.details)));
|
|
1234
|
+
return;
|
|
1235
|
+
}
|
|
1236
|
+
try {
|
|
1237
|
+
sourceText = await readFile(paths.paths.styleFile, "utf8");
|
|
1238
|
+
} catch (error) {
|
|
1239
|
+
logUnexpectedDevServerError("Failed to read Sculpted style module.", error);
|
|
1240
|
+
response.statusCode = 400;
|
|
1241
|
+
response.setHeader("content-type", "application/json");
|
|
1242
|
+
response.setHeader("cache-control", "no-store");
|
|
1243
|
+
response.end(JSON.stringify(styleModuleFailure("write-failed", `Failed to read style module: ${errorMessage(error)}`)));
|
|
1244
|
+
return;
|
|
1245
|
+
}
|
|
1246
|
+
}
|
|
1247
|
+
let result;
|
|
1248
|
+
try {
|
|
1249
|
+
result = readComponentStyleModule({
|
|
1250
|
+
projectRoot: options.projectRoot,
|
|
1251
|
+
componentSource: requestResult.componentSource,
|
|
1252
|
+
sourceText,
|
|
1253
|
+
cssImportSources: options.cssImportSources
|
|
1254
|
+
});
|
|
1255
|
+
} catch (error) {
|
|
1256
|
+
logUnexpectedDevServerError("Failed to inspect Sculpted style module.", error);
|
|
1257
|
+
result = styleModuleFailure("write-failed", `Failed to inspect style module: ${errorMessage(error)}`);
|
|
1258
|
+
}
|
|
1152
1259
|
response.statusCode = result.ok ? 200 : 400;
|
|
1153
1260
|
response.setHeader("content-type", "application/json");
|
|
1154
1261
|
response.setHeader("cache-control", "no-store");
|
|
@@ -1157,9 +1264,9 @@ function registerStyleModuleRoute(server, options) {
|
|
|
1157
1264
|
}
|
|
1158
1265
|
async function readStyleModuleRequest(request) {
|
|
1159
1266
|
try {
|
|
1160
|
-
const body = await readRequestBody
|
|
1267
|
+
const body = await readRequestBody(request);
|
|
1161
1268
|
const parsed = JSON.parse(body);
|
|
1162
|
-
if (!isRecord$1(parsed) || typeof parsed.componentSource !== "string") return {
|
|
1269
|
+
if (!isRecord$1(parsed) || !hasOnlyKeys$1(parsed, ["componentSource"]) || typeof parsed.componentSource !== "string" || parsed.componentSource.length === 0) return {
|
|
1163
1270
|
ok: false,
|
|
1164
1271
|
response: styleModuleFailure("invalid-edit", "Request body is not a valid style-module request.")
|
|
1165
1272
|
};
|
|
@@ -1174,12 +1281,6 @@ async function readStyleModuleRequest(request) {
|
|
|
1174
1281
|
};
|
|
1175
1282
|
}
|
|
1176
1283
|
}
|
|
1177
|
-
async function readRequestBody$1(request) {
|
|
1178
|
-
if (!request[Symbol.asyncIterator]) return "";
|
|
1179
|
-
let body = "";
|
|
1180
|
-
for await (const chunk of request) body += typeof chunk === "string" ? chunk : Buffer.from(chunk).toString("utf8");
|
|
1181
|
-
return body;
|
|
1182
|
-
}
|
|
1183
1284
|
function styleModuleFailure(code, message, details) {
|
|
1184
1285
|
return {
|
|
1185
1286
|
ok: false,
|
|
@@ -1193,6 +1294,9 @@ function styleModuleFailure(code, message, details) {
|
|
|
1193
1294
|
function isMissingFileError$1(error) {
|
|
1194
1295
|
return isRecord$1(error) && error.code === "ENOENT";
|
|
1195
1296
|
}
|
|
1297
|
+
function hasOnlyKeys$1(value, allowedKeys) {
|
|
1298
|
+
return Object.keys(value).every((key) => allowedKeys.includes(key));
|
|
1299
|
+
}
|
|
1196
1300
|
function isRecord$1(value) {
|
|
1197
1301
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1198
1302
|
}
|
|
@@ -1509,42 +1613,49 @@ function registerWritebackRoutes(server, options) {
|
|
|
1509
1613
|
response.end(JSON.stringify(requestResult.response));
|
|
1510
1614
|
return;
|
|
1511
1615
|
}
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1616
|
+
let result;
|
|
1617
|
+
try {
|
|
1618
|
+
result = requestResult.request.kind === "panda-css-inline-source" ? await writeInlineCssSourcePatch({
|
|
1619
|
+
request: requestResult.request,
|
|
1620
|
+
projectRoot: options.projectRoot,
|
|
1621
|
+
cssImportSources: options.cssImportSources,
|
|
1622
|
+
sourceSyntax: options.sourceSyntax,
|
|
1623
|
+
attributes: options.attributes,
|
|
1624
|
+
onManifestEntries: options.onManifestEntries
|
|
1625
|
+
}) : requestResult.request.kind === "panda-css-style-module-source" || requestResult.request.kind === "panda-css-style-module-attach" || requestResult.request.kind === "panda-css-style-module-detach" ? await writeStyleModulePatch({
|
|
1626
|
+
request: requestResult.request,
|
|
1627
|
+
projectRoot: options.projectRoot,
|
|
1628
|
+
cssImportSources: options.cssImportSources,
|
|
1629
|
+
styledSystemPackageName: await inferStyledSystemPackageName(options.projectRoot),
|
|
1630
|
+
attributes: options.attributes,
|
|
1631
|
+
onManifestEntries: options.onManifestEntries
|
|
1632
|
+
}) : requestResult.request.kind === "panda-css-batch" ? await writeStaticCssBatchPatch({
|
|
1633
|
+
manifest: options.manifest(),
|
|
1634
|
+
request: requestResult.request,
|
|
1635
|
+
projectRoot: options.projectRoot,
|
|
1636
|
+
cssImportSources: options.cssImportSources,
|
|
1637
|
+
sourceSyntax: options.sourceSyntax,
|
|
1638
|
+
onManifestEntries: options.onManifestEntries
|
|
1639
|
+
}) : await writeStaticCssPatch({
|
|
1640
|
+
manifest: options.manifest(),
|
|
1641
|
+
request: requestResult.request,
|
|
1642
|
+
projectRoot: options.projectRoot,
|
|
1643
|
+
cssImportSources: options.cssImportSources,
|
|
1644
|
+
sourceSyntax: options.sourceSyntax,
|
|
1645
|
+
onManifestEntries: options.onManifestEntries
|
|
1646
|
+
});
|
|
1647
|
+
} catch (error) {
|
|
1648
|
+
logUnexpectedDevServerError("Unhandled Sculpted writeback failure.", error);
|
|
1649
|
+
const failure = styleEditFailure(requestResult.request.kind === "panda-css-batch" ? requestResult.request.requests.map((item) => item.editId).join(" ") : requestResult.request.editId, "write-failed", `Unhandled Sculpted writeback failure: ${errorMessage(error)}`);
|
|
1650
|
+
result = requestResult.request.kind === "panda-css-batch" ? styleEditBatchFailure(failure) : failure;
|
|
1651
|
+
}
|
|
1541
1652
|
response.statusCode = result.ok ? 200 : 400;
|
|
1542
1653
|
response.setHeader("content-type", "application/json");
|
|
1543
1654
|
response.setHeader("cache-control", "no-store");
|
|
1544
1655
|
response.end(JSON.stringify(result));
|
|
1545
1656
|
if (result.ok && result.written && result.manifestUpdate) {
|
|
1546
1657
|
notifyViteAboutWrittenFiles(server, options.projectRoot, result.manifestUpdate.changedFiles);
|
|
1547
|
-
server
|
|
1658
|
+
sendViteEvent$1(server, SCULPTED_EVENTS.manifestUpdate, result.manifestUpdate);
|
|
1548
1659
|
}
|
|
1549
1660
|
});
|
|
1550
1661
|
server.middlewares.use(DEFAULT_TOKEN_WRITEBACK_ENDPOINT, async (request, response) => {
|
|
@@ -1563,27 +1674,42 @@ function registerWritebackRoutes(server, options) {
|
|
|
1563
1674
|
response.end(JSON.stringify(requestResult.response));
|
|
1564
1675
|
return;
|
|
1565
1676
|
}
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1677
|
+
let result;
|
|
1678
|
+
try {
|
|
1679
|
+
result = await writeTokenConfigPatch({
|
|
1680
|
+
request: requestResult.request,
|
|
1681
|
+
projectRoot: options.projectRoot,
|
|
1682
|
+
pandaConfigPath: options.pandaConfigPath
|
|
1683
|
+
});
|
|
1684
|
+
} catch (error) {
|
|
1685
|
+
logUnexpectedDevServerError("Unhandled Sculpted token writeback failure.", error);
|
|
1686
|
+
result = tokenConfigEditFailure(requestResult.request.editId, "write-failed", `Unhandled Sculpted token writeback failure: ${errorMessage(error)}`);
|
|
1687
|
+
}
|
|
1571
1688
|
response.statusCode = result.ok ? 200 : 400;
|
|
1572
1689
|
response.setHeader("content-type", "application/json");
|
|
1573
1690
|
response.setHeader("cache-control", "no-store");
|
|
1574
1691
|
response.end(JSON.stringify(result));
|
|
1575
1692
|
if (result.ok && result.written && result.metadataUpdate) {
|
|
1576
1693
|
notifyViteAboutWrittenFiles(server, options.projectRoot, result.metadataUpdate.changedFiles);
|
|
1577
|
-
server
|
|
1694
|
+
sendViteEvent$1(server, SCULPTED_EVENTS.metadataUpdate, result.metadataUpdate);
|
|
1578
1695
|
}
|
|
1579
1696
|
});
|
|
1580
1697
|
}
|
|
1698
|
+
function sendViteEvent$1(server, event, payload) {
|
|
1699
|
+
try {
|
|
1700
|
+
server.ws?.send(event, payload);
|
|
1701
|
+
} catch {}
|
|
1702
|
+
}
|
|
1581
1703
|
function notifyViteAboutWrittenFiles(server, projectRoot, changedFiles) {
|
|
1582
1704
|
for (const changedFile of changedFiles) {
|
|
1583
1705
|
const absoluteFile = normalizePath$1(`${projectRoot.replace(/\/$/, "")}/${changedFile}`);
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1706
|
+
try {
|
|
1707
|
+
const modules = server.moduleGraph?.getModulesByFile?.(absoluteFile);
|
|
1708
|
+
if (modules) for (const module of modules) server.moduleGraph?.invalidateModule?.(module);
|
|
1709
|
+
} catch {}
|
|
1710
|
+
try {
|
|
1711
|
+
server.watcher?.emit?.("change", absoluteFile);
|
|
1712
|
+
} catch {}
|
|
1587
1713
|
}
|
|
1588
1714
|
}
|
|
1589
1715
|
async function readStyleEditRequest(request) {
|
|
@@ -1624,44 +1750,87 @@ async function readTokenConfigEditRequest(request) {
|
|
|
1624
1750
|
};
|
|
1625
1751
|
}
|
|
1626
1752
|
}
|
|
1627
|
-
async function readRequestBody(request) {
|
|
1628
|
-
if (!request[Symbol.asyncIterator]) return "";
|
|
1629
|
-
let body = "";
|
|
1630
|
-
for await (const chunk of request) body += typeof chunk === "string" ? chunk : Buffer.from(chunk).toString("utf8");
|
|
1631
|
-
return body;
|
|
1632
|
-
}
|
|
1633
1753
|
function isStyleEditRequest(value) {
|
|
1634
1754
|
if (!isRecord(value)) return false;
|
|
1755
|
+
if (!hasOnlyKeys(value, [
|
|
1756
|
+
"editId",
|
|
1757
|
+
"kind",
|
|
1758
|
+
"edits",
|
|
1759
|
+
"options"
|
|
1760
|
+
])) return false;
|
|
1635
1761
|
if (typeof value.editId !== "string" || value.editId.length === 0) return false;
|
|
1636
1762
|
if (value.kind !== "panda-css") return false;
|
|
1637
1763
|
if (!Array.isArray(value.edits) || value.edits.length === 0) return false;
|
|
1764
|
+
if (!isStyleEditOptions(value.options, true)) return false;
|
|
1638
1765
|
return value.edits.every((edit) => {
|
|
1639
1766
|
if (!isRecord(edit)) return false;
|
|
1640
|
-
if (edit.op === "set") return
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1767
|
+
if (edit.op === "set") return hasOnlyKeys(edit, [
|
|
1768
|
+
"op",
|
|
1769
|
+
"path",
|
|
1770
|
+
"value"
|
|
1771
|
+
]) && isPath(edit.path) && isJsonValue(edit.value);
|
|
1772
|
+
if (edit.op === "delete") return hasOnlyKeys(edit, ["op", "path"]) && isPath(edit.path);
|
|
1773
|
+
if (edit.op === "rename") return hasOnlyKeys(edit, [
|
|
1774
|
+
"op",
|
|
1775
|
+
"from",
|
|
1776
|
+
"to"
|
|
1777
|
+
]) && isPath(edit.from) && isPath(edit.to);
|
|
1778
|
+
if (edit.op === "replace-object") return hasOnlyKeys(edit, ["op", "value"]) && isJsonObject(edit.value);
|
|
1644
1779
|
return false;
|
|
1645
1780
|
});
|
|
1646
1781
|
}
|
|
1647
1782
|
function isStyleEditBatchRequest(value) {
|
|
1648
1783
|
if (!isRecord(value)) return false;
|
|
1784
|
+
if (!hasOnlyKeys(value, [
|
|
1785
|
+
"kind",
|
|
1786
|
+
"requests",
|
|
1787
|
+
"options"
|
|
1788
|
+
])) return false;
|
|
1649
1789
|
if (value.kind !== "panda-css-batch") return false;
|
|
1650
1790
|
if (!Array.isArray(value.requests) || value.requests.length === 0) return false;
|
|
1791
|
+
if (!isStyleEditOptions(value.options, false)) return false;
|
|
1651
1792
|
return value.requests.every(isStyleEditRequest);
|
|
1652
1793
|
}
|
|
1653
1794
|
function isInlineCssSourceCreateRequest(value) {
|
|
1654
1795
|
if (!isRecord(value)) return false;
|
|
1796
|
+
if (!hasOnlyKeys(value, [
|
|
1797
|
+
"editId",
|
|
1798
|
+
"kind",
|
|
1799
|
+
"jsxSource",
|
|
1800
|
+
"edits",
|
|
1801
|
+
"options"
|
|
1802
|
+
])) return false;
|
|
1655
1803
|
if (typeof value.editId !== "string" || value.editId.length === 0) return false;
|
|
1656
1804
|
if (value.kind !== "panda-css-inline-source") return false;
|
|
1657
1805
|
if (typeof value.jsxSource !== "string" || value.jsxSource.length === 0) return false;
|
|
1658
|
-
|
|
1806
|
+
if (value.edits !== void 0) {
|
|
1807
|
+
if (!Array.isArray(value.edits)) return false;
|
|
1808
|
+
if (!value.edits.every((edit) => {
|
|
1809
|
+
if (!isRecord(edit)) return false;
|
|
1810
|
+
if (edit.op === "set") return hasOnlyKeys(edit, [
|
|
1811
|
+
"op",
|
|
1812
|
+
"path",
|
|
1813
|
+
"value"
|
|
1814
|
+
]) && isPath(edit.path) && isJsonValue(edit.value);
|
|
1815
|
+
if (edit.op === "delete") return hasOnlyKeys(edit, ["op", "path"]) && isPath(edit.path);
|
|
1816
|
+
return false;
|
|
1817
|
+
})) return false;
|
|
1818
|
+
}
|
|
1819
|
+
return isStyleEditOptions(value.options, false);
|
|
1659
1820
|
}
|
|
1660
1821
|
function isStyleModuleEditRequest(value) {
|
|
1661
1822
|
return isStyleModuleSourceCreateRequest(value) || isStyleModuleSourceAttachRequest(value) || isStyleModuleSourceDetachRequest(value);
|
|
1662
1823
|
}
|
|
1663
1824
|
function isStyleModuleSourceCreateRequest(value) {
|
|
1664
1825
|
if (!isRecord(value)) return false;
|
|
1826
|
+
if (!hasOnlyKeys(value, [
|
|
1827
|
+
"editId",
|
|
1828
|
+
"kind",
|
|
1829
|
+
"componentSource",
|
|
1830
|
+
"name",
|
|
1831
|
+
"edits",
|
|
1832
|
+
"options"
|
|
1833
|
+
])) return false;
|
|
1665
1834
|
if (typeof value.editId !== "string" || value.editId.length === 0) return false;
|
|
1666
1835
|
if (value.kind !== "panda-css-style-module-source") return false;
|
|
1667
1836
|
if (typeof value.componentSource !== "string" || value.componentSource.length === 0) return false;
|
|
@@ -1670,40 +1839,82 @@ function isStyleModuleSourceCreateRequest(value) {
|
|
|
1670
1839
|
if (!Array.isArray(value.edits)) return false;
|
|
1671
1840
|
if (!value.edits.every((edit) => {
|
|
1672
1841
|
if (!isRecord(edit)) return false;
|
|
1673
|
-
if (edit.op === "set") return
|
|
1674
|
-
|
|
1842
|
+
if (edit.op === "set") return hasOnlyKeys(edit, [
|
|
1843
|
+
"op",
|
|
1844
|
+
"path",
|
|
1845
|
+
"value"
|
|
1846
|
+
]) && isPath(edit.path) && isJsonValue(edit.value);
|
|
1847
|
+
if (edit.op === "delete") return hasOnlyKeys(edit, ["op", "path"]) && isPath(edit.path);
|
|
1675
1848
|
return false;
|
|
1676
1849
|
})) return false;
|
|
1677
1850
|
}
|
|
1678
|
-
return value.options
|
|
1851
|
+
return isStyleEditOptions(value.options, false);
|
|
1679
1852
|
}
|
|
1680
1853
|
function isStyleModuleSourceAttachRequest(value) {
|
|
1681
1854
|
if (!isRecord(value)) return false;
|
|
1855
|
+
if (!hasOnlyKeys(value, [
|
|
1856
|
+
"editId",
|
|
1857
|
+
"kind",
|
|
1858
|
+
"jsxSource",
|
|
1859
|
+
"componentSource",
|
|
1860
|
+
"name",
|
|
1861
|
+
"options"
|
|
1862
|
+
])) return false;
|
|
1682
1863
|
if (typeof value.editId !== "string" || value.editId.length === 0) return false;
|
|
1683
1864
|
if (value.kind !== "panda-css-style-module-attach") return false;
|
|
1684
1865
|
if (typeof value.jsxSource !== "string" || value.jsxSource.length === 0) return false;
|
|
1685
1866
|
if (typeof value.componentSource !== "string" || value.componentSource.length === 0) return false;
|
|
1686
1867
|
if (typeof value.name !== "string" || value.name.length === 0) return false;
|
|
1687
|
-
return value.options
|
|
1868
|
+
return isStyleEditOptions(value.options, false);
|
|
1688
1869
|
}
|
|
1689
1870
|
function isStyleModuleSourceDetachRequest(value) {
|
|
1690
1871
|
if (!isRecord(value)) return false;
|
|
1872
|
+
if (!hasOnlyKeys(value, [
|
|
1873
|
+
"editId",
|
|
1874
|
+
"kind",
|
|
1875
|
+
"jsxSource",
|
|
1876
|
+
"componentSource",
|
|
1877
|
+
"name",
|
|
1878
|
+
"options"
|
|
1879
|
+
])) return false;
|
|
1691
1880
|
if (typeof value.editId !== "string" || value.editId.length === 0) return false;
|
|
1692
1881
|
if (value.kind !== "panda-css-style-module-detach") return false;
|
|
1693
1882
|
if (typeof value.jsxSource !== "string" || value.jsxSource.length === 0) return false;
|
|
1694
1883
|
if (typeof value.componentSource !== "string" || value.componentSource.length === 0) return false;
|
|
1695
1884
|
if (typeof value.name !== "string" || value.name.length === 0) return false;
|
|
1696
|
-
return value.options
|
|
1885
|
+
return isStyleEditOptions(value.options, false);
|
|
1697
1886
|
}
|
|
1698
1887
|
function isTokenConfigEditRequest(value) {
|
|
1699
1888
|
if (!isRecord(value)) return false;
|
|
1889
|
+
if (!hasOnlyKeys(value, [
|
|
1890
|
+
"editId",
|
|
1891
|
+
"kind",
|
|
1892
|
+
"sourceTargetId",
|
|
1893
|
+
"section",
|
|
1894
|
+
"path",
|
|
1895
|
+
"value",
|
|
1896
|
+
"options"
|
|
1897
|
+
])) return false;
|
|
1700
1898
|
if (typeof value.editId !== "string" || value.editId.length === 0) return false;
|
|
1701
1899
|
if (value.kind !== "panda-token-config") return false;
|
|
1702
1900
|
if (typeof value.sourceTargetId !== "string" || value.sourceTargetId.length === 0) return false;
|
|
1703
1901
|
if (value.section !== "tokens.colors" && value.section !== "semanticTokens.colors") return false;
|
|
1704
1902
|
if (!isPath(value.path)) return false;
|
|
1705
1903
|
if (!isJsonPrimitive(value.value)) return false;
|
|
1706
|
-
return value.options
|
|
1904
|
+
return isStyleEditOptions(value.options, true);
|
|
1905
|
+
}
|
|
1906
|
+
function isStyleEditOptions(value, allowExpectedSourceHash) {
|
|
1907
|
+
if (value === void 0) return true;
|
|
1908
|
+
if (!isRecord(value)) return false;
|
|
1909
|
+
for (const key of Object.keys(value)) {
|
|
1910
|
+
if (key === "write" || key === "format") continue;
|
|
1911
|
+
if (key === "expectedSourceHash" && allowExpectedSourceHash) continue;
|
|
1912
|
+
return false;
|
|
1913
|
+
}
|
|
1914
|
+
return (!("write" in value) || typeof value.write === "boolean") && (!("format" in value) || typeof value.format === "boolean") && (!allowExpectedSourceHash || !("expectedSourceHash" in value) || typeof value.expectedSourceHash === "string");
|
|
1915
|
+
}
|
|
1916
|
+
function hasOnlyKeys(value, allowedKeys) {
|
|
1917
|
+
return Object.keys(value).every((key) => allowedKeys.includes(key));
|
|
1707
1918
|
}
|
|
1708
1919
|
function styleEditBatchFailure(response) {
|
|
1709
1920
|
return {
|
|
@@ -1714,14 +1925,17 @@ function styleEditBatchFailure(response) {
|
|
|
1714
1925
|
error: response.error
|
|
1715
1926
|
};
|
|
1716
1927
|
}
|
|
1717
|
-
function
|
|
1718
|
-
|
|
1928
|
+
function isNewInlineSourceEntry(entry, request) {
|
|
1929
|
+
const initialSetPaths = request.edits?.flatMap((edit) => edit.op === "set" && edit.path.length === 1 ? edit.path : []) ?? [];
|
|
1930
|
+
return entry.kind === "panda-css" && (entry.attribute === "class" || entry.attribute === "className") && (initialSetPaths.length === 0 ? Object.keys(entry.styleObject).length === 0 : initialSetPaths.every((path) => path in entry.styleObject));
|
|
1719
1931
|
}
|
|
1720
1932
|
async function writeInlineCssSourcePatch(options) {
|
|
1721
1933
|
const parsed = parseJsxSourceFile(options.request.jsxSource);
|
|
1722
1934
|
if (!parsed.ok) return styleEditFailure(options.request.editId, parsed.code, parsed.message, parsed.details);
|
|
1723
1935
|
const filePath = safeProjectSourcePath(options.projectRoot, parsed.file);
|
|
1724
1936
|
if (!filePath.ok) return styleEditFailure(options.request.editId, filePath.code, filePath.message, filePath.details);
|
|
1937
|
+
const readPath = await verifyWriteTarget(options.projectRoot, filePath.file, options.request.editId);
|
|
1938
|
+
if (readPath) return readPath;
|
|
1725
1939
|
let sourceText;
|
|
1726
1940
|
try {
|
|
1727
1941
|
sourceText = await readFile(filePath.file, "utf8");
|
|
@@ -1744,22 +1958,30 @@ async function writeInlineCssSourcePatch(options) {
|
|
|
1744
1958
|
});
|
|
1745
1959
|
if (!patch.ok || !patch.nextSource) return patch;
|
|
1746
1960
|
if (options.request.options?.write !== true) return patch;
|
|
1961
|
+
let transformedEntries;
|
|
1747
1962
|
try {
|
|
1748
|
-
|
|
1963
|
+
transformedEntries = transformTsxSource({
|
|
1964
|
+
sourceText: patch.nextSource,
|
|
1965
|
+
filePath: filePath.file,
|
|
1966
|
+
projectRoot: options.projectRoot,
|
|
1967
|
+
attributes: options.attributes,
|
|
1968
|
+
cssImportSources: options.cssImportSources,
|
|
1969
|
+
sourceSyntax: options.sourceSyntax
|
|
1970
|
+
}).entries;
|
|
1749
1971
|
} catch (error) {
|
|
1750
|
-
return styleEditFailure(options.request.editId, "write-failed", `Failed to
|
|
1972
|
+
return styleEditFailure(options.request.editId, "write-failed", `Failed to analyze source after inline source creation: ${error instanceof Error ? error.message : String(error)}`);
|
|
1751
1973
|
}
|
|
1752
|
-
const nextEntries =
|
|
1753
|
-
sourceText: patch.nextSource,
|
|
1754
|
-
filePath: filePath.file,
|
|
1755
|
-
projectRoot: options.projectRoot,
|
|
1756
|
-
attributes: options.attributes,
|
|
1757
|
-
cssImportSources: options.cssImportSources,
|
|
1758
|
-
sourceSyntax: options.sourceSyntax
|
|
1759
|
-
}).entries.map((entry) => isNewEmptyInlineSourceEntry(entry) ? {
|
|
1974
|
+
const nextEntries = transformedEntries.map((entry) => isNewInlineSourceEntry(entry, options.request) ? {
|
|
1760
1975
|
...entry,
|
|
1761
1976
|
jsxSourceAliases: Array.from(new Set([...entry.jsxSourceAliases ?? [], options.request.jsxSource]))
|
|
1762
1977
|
} : entry);
|
|
1978
|
+
const writePath = await verifyWriteTarget(options.projectRoot, filePath.file, options.request.editId);
|
|
1979
|
+
if (writePath) return writePath;
|
|
1980
|
+
try {
|
|
1981
|
+
await writeFile(filePath.file, patch.nextSource, "utf8");
|
|
1982
|
+
} catch (error) {
|
|
1983
|
+
return styleEditFailure(options.request.editId, "write-failed", `Failed to write source file: ${error instanceof Error ? error.message : String(error)}`);
|
|
1984
|
+
}
|
|
1763
1985
|
options.onManifestEntries(filePath.file, nextEntries);
|
|
1764
1986
|
const manifestUpdate = {
|
|
1765
1987
|
version: 1,
|
|
@@ -1780,6 +2002,8 @@ async function writeStyleModulePatch(options) {
|
|
|
1780
2002
|
if (!paths.ok) return styleEditFailure(options.request.editId, paths.code, paths.message, paths.details);
|
|
1781
2003
|
const write = options.request.options?.write === true;
|
|
1782
2004
|
if (options.request.kind === "panda-css-style-module-source") {
|
|
2005
|
+
const readPath = await verifyWriteTarget(options.projectRoot, paths.paths.styleFile, options.request.editId);
|
|
2006
|
+
if (readPath) return readPath;
|
|
1783
2007
|
let sourceText;
|
|
1784
2008
|
try {
|
|
1785
2009
|
sourceText = await readFile(paths.paths.styleFile, "utf8");
|
|
@@ -1801,18 +2025,25 @@ async function writeStyleModulePatch(options) {
|
|
|
1801
2025
|
});
|
|
1802
2026
|
if (!patch.ok || !patch.nextSource) return patch;
|
|
1803
2027
|
if (!write) return patch;
|
|
2028
|
+
let nextEntries;
|
|
2029
|
+
try {
|
|
2030
|
+
nextEntries = analyzePandaCssSource({
|
|
2031
|
+
sourceText: patch.nextSource,
|
|
2032
|
+
filePath: paths.paths.styleFile,
|
|
2033
|
+
projectRoot: options.projectRoot,
|
|
2034
|
+
cssImportSources: options.cssImportSources
|
|
2035
|
+
}).entries;
|
|
2036
|
+
} catch (error) {
|
|
2037
|
+
return styleEditFailure(options.request.editId, "write-failed", `Failed to analyze style module after writeback: ${error instanceof Error ? error.message : String(error)}`);
|
|
2038
|
+
}
|
|
2039
|
+
const writePath = await verifyWriteTarget(options.projectRoot, paths.paths.styleFile, options.request.editId);
|
|
2040
|
+
if (writePath) return writePath;
|
|
1804
2041
|
try {
|
|
1805
2042
|
await mkdir(dirname(paths.paths.styleFile), { recursive: true });
|
|
1806
2043
|
await writeFile(paths.paths.styleFile, patch.nextSource, "utf8");
|
|
1807
2044
|
} catch (error) {
|
|
1808
2045
|
return styleEditFailure(options.request.editId, "write-failed", `Failed to write style module: ${error instanceof Error ? error.message : String(error)}`);
|
|
1809
2046
|
}
|
|
1810
|
-
const nextEntries = analyzePandaCssSource({
|
|
1811
|
-
sourceText: patch.nextSource,
|
|
1812
|
-
filePath: paths.paths.styleFile,
|
|
1813
|
-
projectRoot: options.projectRoot,
|
|
1814
|
-
cssImportSources: options.cssImportSources
|
|
1815
|
-
}).entries;
|
|
1816
2047
|
options.onManifestEntries(paths.paths.styleFile, nextEntries);
|
|
1817
2048
|
const manifestUpdate = {
|
|
1818
2049
|
version: 1,
|
|
@@ -1826,12 +2057,16 @@ async function writeStyleModulePatch(options) {
|
|
|
1826
2057
|
};
|
|
1827
2058
|
}
|
|
1828
2059
|
let componentSourceText;
|
|
2060
|
+
const componentReadPath = await verifyWriteTarget(options.projectRoot, paths.paths.componentFile, options.request.editId);
|
|
2061
|
+
if (componentReadPath) return componentReadPath;
|
|
1829
2062
|
try {
|
|
1830
2063
|
componentSourceText = await readFile(paths.paths.componentFile, "utf8");
|
|
1831
2064
|
} catch (error) {
|
|
1832
2065
|
return styleEditFailure(options.request.editId, "write-failed", `Failed to read component module before style attachment: ${error instanceof Error ? error.message : String(error)}`);
|
|
1833
2066
|
}
|
|
1834
2067
|
let styleSourceText;
|
|
2068
|
+
const styleReadPath = await verifyWriteTarget(options.projectRoot, paths.paths.styleFile, options.request.editId);
|
|
2069
|
+
if (styleReadPath) return styleReadPath;
|
|
1835
2070
|
try {
|
|
1836
2071
|
styleSourceText = await readFile(paths.paths.styleFile, "utf8");
|
|
1837
2072
|
} catch (error) {
|
|
@@ -1863,28 +2098,36 @@ async function writeStyleModulePatch(options) {
|
|
|
1863
2098
|
});
|
|
1864
2099
|
if (!patch.ok || !patch.nextSource) return patch;
|
|
1865
2100
|
if (!write) return patch;
|
|
2101
|
+
let componentEntries;
|
|
2102
|
+
let analyzedStyleEntries;
|
|
1866
2103
|
try {
|
|
1867
|
-
|
|
2104
|
+
componentEntries = transformTsxSource({
|
|
2105
|
+
sourceText: patch.nextSource,
|
|
2106
|
+
filePath: paths.paths.componentFile,
|
|
2107
|
+
projectRoot: options.projectRoot,
|
|
2108
|
+
attributes: options.attributes,
|
|
2109
|
+
cssImportSources: options.cssImportSources
|
|
2110
|
+
}).entries;
|
|
2111
|
+
analyzedStyleEntries = analyzePandaCssSource({
|
|
2112
|
+
sourceText: styleSourceText,
|
|
2113
|
+
filePath: paths.paths.styleFile,
|
|
2114
|
+
projectRoot: options.projectRoot,
|
|
2115
|
+
cssImportSources: options.cssImportSources
|
|
2116
|
+
}).entries;
|
|
1868
2117
|
} catch (error) {
|
|
1869
|
-
return styleEditFailure(options.request.editId, "write-failed", `Failed to
|
|
2118
|
+
return styleEditFailure(options.request.editId, "write-failed", `Failed to analyze style-module attachment after writeback: ${error instanceof Error ? error.message : String(error)}`);
|
|
1870
2119
|
}
|
|
1871
|
-
const componentEntries = transformTsxSource({
|
|
1872
|
-
sourceText: patch.nextSource,
|
|
1873
|
-
filePath: paths.paths.componentFile,
|
|
1874
|
-
projectRoot: options.projectRoot,
|
|
1875
|
-
attributes: options.attributes,
|
|
1876
|
-
cssImportSources: options.cssImportSources
|
|
1877
|
-
}).entries;
|
|
1878
|
-
const analyzedStyleEntries = analyzePandaCssSource({
|
|
1879
|
-
sourceText: styleSourceText,
|
|
1880
|
-
filePath: paths.paths.styleFile,
|
|
1881
|
-
projectRoot: options.projectRoot,
|
|
1882
|
-
cssImportSources: options.cssImportSources
|
|
1883
|
-
}).entries;
|
|
1884
2120
|
const styleEntries = styleModuleEntriesWithJsxAlias({
|
|
1885
2121
|
entries: analyzedStyleEntries,
|
|
1886
2122
|
request: options.request
|
|
1887
2123
|
});
|
|
2124
|
+
const writePath = await verifyWriteTarget(options.projectRoot, paths.paths.componentFile, options.request.editId);
|
|
2125
|
+
if (writePath) return writePath;
|
|
2126
|
+
try {
|
|
2127
|
+
await writeFile(paths.paths.componentFile, patch.nextSource, "utf8");
|
|
2128
|
+
} catch (error) {
|
|
2129
|
+
return styleEditFailure(options.request.editId, "write-failed", `Failed to write component module: ${error instanceof Error ? error.message : String(error)}`);
|
|
2130
|
+
}
|
|
1888
2131
|
options.onManifestEntries(paths.paths.componentFile, componentEntries);
|
|
1889
2132
|
options.onManifestEntries(paths.paths.styleFile, styleEntries);
|
|
1890
2133
|
const manifestUpdate = {
|
|
@@ -1918,6 +2161,8 @@ async function writeStaticCssPatch(options) {
|
|
|
1918
2161
|
if (!entry) return styleEditFailure(options.request.editId, "manifest-entry-not-found", "No manifest entry exists for edit id.");
|
|
1919
2162
|
const filePath = trustedManifestFilePath(options.manifest, entry);
|
|
1920
2163
|
if (!filePath.ok) return styleEditFailure(options.request.editId, filePath.code, filePath.message, filePath.details);
|
|
2164
|
+
const readPath = await verifyWriteTarget(options.projectRoot, filePath.file, options.request.editId);
|
|
2165
|
+
if (readPath) return readPath;
|
|
1921
2166
|
let sourceText;
|
|
1922
2167
|
try {
|
|
1923
2168
|
sourceText = await readFile(filePath.file, "utf8");
|
|
@@ -1940,18 +2185,25 @@ async function writeStaticCssPatch(options) {
|
|
|
1940
2185
|
});
|
|
1941
2186
|
if (!patch.ok || !patch.nextSource) return patch;
|
|
1942
2187
|
if (options.request.options?.write !== true) return patch;
|
|
2188
|
+
let nextEntries;
|
|
2189
|
+
try {
|
|
2190
|
+
nextEntries = analyzePandaCssSource({
|
|
2191
|
+
sourceText: patch.nextSource,
|
|
2192
|
+
filePath: filePath.file,
|
|
2193
|
+
projectRoot: options.projectRoot,
|
|
2194
|
+
cssImportSources: options.cssImportSources,
|
|
2195
|
+
sourceSyntax: options.sourceSyntax
|
|
2196
|
+
}).entries;
|
|
2197
|
+
} catch (error) {
|
|
2198
|
+
return styleEditFailure(options.request.editId, "write-failed", `Failed to analyze source after writeback: ${error instanceof Error ? error.message : String(error)}`);
|
|
2199
|
+
}
|
|
2200
|
+
const writePath = await verifyWriteTarget(options.projectRoot, filePath.file, options.request.editId);
|
|
2201
|
+
if (writePath) return writePath;
|
|
1943
2202
|
try {
|
|
1944
2203
|
await writeFile(filePath.file, patch.nextSource, "utf8");
|
|
1945
2204
|
} catch (error) {
|
|
1946
2205
|
return styleEditFailure(options.request.editId, "write-failed", `Failed to write source file: ${error instanceof Error ? error.message : String(error)}`);
|
|
1947
2206
|
}
|
|
1948
|
-
const nextEntries = analyzePandaCssSource({
|
|
1949
|
-
sourceText: patch.nextSource,
|
|
1950
|
-
filePath: filePath.file,
|
|
1951
|
-
projectRoot: options.projectRoot,
|
|
1952
|
-
cssImportSources: options.cssImportSources,
|
|
1953
|
-
sourceSyntax: options.sourceSyntax
|
|
1954
|
-
}).entries;
|
|
1955
2207
|
options.onManifestEntries(filePath.file, nextEntries);
|
|
1956
2208
|
const manifestUpdate = {
|
|
1957
2209
|
version: 1,
|
|
@@ -1983,6 +2235,8 @@ async function writeStaticCssBatchPatch(options) {
|
|
|
1983
2235
|
}
|
|
1984
2236
|
const prepared = [];
|
|
1985
2237
|
for (const group of groups.values()) {
|
|
2238
|
+
const readPath = await verifyWriteTarget(options.projectRoot, group.file, group.requests.map((request) => request.editId).join(" "));
|
|
2239
|
+
if (readPath) return styleEditBatchFailure(readPath);
|
|
1986
2240
|
let sourceText;
|
|
1987
2241
|
try {
|
|
1988
2242
|
sourceText = await readFile(group.file, "utf8");
|
|
@@ -2004,30 +2258,52 @@ async function writeStaticCssBatchPatch(options) {
|
|
|
2004
2258
|
sourceSyntax: options.sourceSyntax
|
|
2005
2259
|
});
|
|
2006
2260
|
if (!patch.ok || !patch.nextSource) return styleEditBatchFailure(patch);
|
|
2261
|
+
let nextEntries;
|
|
2262
|
+
if (write) try {
|
|
2263
|
+
nextEntries = analyzePandaCssSource({
|
|
2264
|
+
sourceText: patch.nextSource,
|
|
2265
|
+
filePath: group.file,
|
|
2266
|
+
projectRoot: options.projectRoot,
|
|
2267
|
+
cssImportSources: options.cssImportSources,
|
|
2268
|
+
sourceSyntax: options.sourceSyntax
|
|
2269
|
+
}).entries;
|
|
2270
|
+
} catch (error) {
|
|
2271
|
+
return styleEditBatchFailure(styleEditFailure(group.requests[0]?.editId ?? "", "write-failed", `Failed to analyze source after batch writeback: ${error instanceof Error ? error.message : String(error)}`));
|
|
2272
|
+
}
|
|
2007
2273
|
prepared.push({
|
|
2008
2274
|
file: group.file,
|
|
2009
2275
|
changedFile: group.changedFile,
|
|
2010
2276
|
requests: group.requests,
|
|
2011
|
-
|
|
2277
|
+
previousSource: sourceText,
|
|
2278
|
+
nextSource: patch.nextSource,
|
|
2279
|
+
nextEntries
|
|
2012
2280
|
});
|
|
2013
2281
|
}
|
|
2014
2282
|
const changedFiles = prepared.map((item) => item.changedFile);
|
|
2015
2283
|
const entryIds = [];
|
|
2016
|
-
if (write)
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2284
|
+
if (write) {
|
|
2285
|
+
const written = [];
|
|
2286
|
+
for (const item of prepared) {
|
|
2287
|
+
const writePath = await verifyWriteTarget(options.projectRoot, item.file, item.requests.map((request) => request.editId).join(" "));
|
|
2288
|
+
if (writePath) return styleEditBatchFailure(writePath);
|
|
2289
|
+
try {
|
|
2290
|
+
await writeFile(item.file, item.nextSource, "utf8");
|
|
2291
|
+
written.push(item);
|
|
2292
|
+
} catch (error) {
|
|
2293
|
+
const rollbackFailures = [];
|
|
2294
|
+
for (const writtenItem of [...written].reverse()) try {
|
|
2295
|
+
await writeFile(writtenItem.file, writtenItem.previousSource, "utf8");
|
|
2296
|
+
} catch (rollbackError) {
|
|
2297
|
+
rollbackFailures.push(`${writtenItem.changedFile}: ${rollbackError instanceof Error ? rollbackError.message : String(rollbackError)}`);
|
|
2298
|
+
}
|
|
2299
|
+
return styleEditBatchFailure(styleEditFailure(item.requests[0]?.editId ?? "", "write-failed", `Failed to write source file: ${error instanceof Error ? error.message : String(error)}`, rollbackFailures.length > 0 ? { rollbackFailures } : void 0));
|
|
2300
|
+
}
|
|
2301
|
+
}
|
|
2302
|
+
for (const item of prepared) {
|
|
2303
|
+
if (!item.nextEntries) continue;
|
|
2304
|
+
options.onManifestEntries(item.file, item.nextEntries);
|
|
2305
|
+
entryIds.push(...item.nextEntries.map((nextEntry) => nextEntry.id));
|
|
2021
2306
|
}
|
|
2022
|
-
const nextEntries = analyzePandaCssSource({
|
|
2023
|
-
sourceText: item.nextSource,
|
|
2024
|
-
filePath: item.file,
|
|
2025
|
-
projectRoot: options.projectRoot,
|
|
2026
|
-
cssImportSources: options.cssImportSources,
|
|
2027
|
-
sourceSyntax: options.sourceSyntax
|
|
2028
|
-
}).entries;
|
|
2029
|
-
options.onManifestEntries(item.file, nextEntries);
|
|
2030
|
-
entryIds.push(...nextEntries.map((nextEntry) => nextEntry.id));
|
|
2031
2307
|
}
|
|
2032
2308
|
const manifestUpdate = write ? {
|
|
2033
2309
|
version: 1,
|
|
@@ -2060,6 +2336,8 @@ async function writeTokenConfigPatch(options) {
|
|
|
2060
2336
|
if (!tokenSource) return tokenConfigEditFailure(options.request.editId, "manifest-entry-not-found", "No token source exists for source target id.", { sourceTargetId: options.request.sourceTargetId });
|
|
2061
2337
|
const filePath = trustedTokenSourceFilePath(options.projectRoot, tokenSource);
|
|
2062
2338
|
if (!filePath.ok) return tokenConfigEditFailure(options.request.editId, filePath.code, filePath.message, filePath.details);
|
|
2339
|
+
const readPath = await verifyWriteTarget(options.projectRoot, filePath.file, options.request.editId);
|
|
2340
|
+
if (readPath) return tokenConfigEditFailure(options.request.editId, readPath.error?.code ?? "path-outside-project", readPath.error?.message ?? "Token source path resolves outside the project root.");
|
|
2063
2341
|
let sourceText;
|
|
2064
2342
|
try {
|
|
2065
2343
|
sourceText = await readFile(filePath.file, "utf8");
|
|
@@ -2082,19 +2360,27 @@ async function writeTokenConfigPatch(options) {
|
|
|
2082
2360
|
});
|
|
2083
2361
|
if (!patch.ok || !patch.nextSource) return patch;
|
|
2084
2362
|
if (!write) return patch;
|
|
2363
|
+
let nextTokenSourceIds;
|
|
2364
|
+
try {
|
|
2365
|
+
nextTokenSourceIds = tokenSourceIdsForPandaConfigSource({
|
|
2366
|
+
projectRoot: options.projectRoot,
|
|
2367
|
+
filePath: filePath.file,
|
|
2368
|
+
sourceText: patch.nextSource
|
|
2369
|
+
});
|
|
2370
|
+
} catch (error) {
|
|
2371
|
+
return tokenConfigEditFailure(options.request.editId, "write-failed", `Failed to prepare editor metadata for token writeback: ${error instanceof Error ? error.message : String(error)}`);
|
|
2372
|
+
}
|
|
2373
|
+
const writePath = await verifyWriteTarget(options.projectRoot, filePath.file, options.request.editId);
|
|
2374
|
+
if (writePath) return writePath;
|
|
2085
2375
|
try {
|
|
2086
2376
|
await writeFile(filePath.file, patch.nextSource, "utf8");
|
|
2087
2377
|
} catch (error) {
|
|
2088
2378
|
return tokenConfigEditFailure(options.request.editId, "write-failed", `Failed to write Panda config: ${error instanceof Error ? error.message : String(error)}`);
|
|
2089
2379
|
}
|
|
2090
|
-
const nextMetadata = await createEditorMetadata({
|
|
2091
|
-
projectRoot: options.projectRoot,
|
|
2092
|
-
pandaConfigPath: options.pandaConfigPath
|
|
2093
|
-
});
|
|
2094
2380
|
const metadataUpdate = {
|
|
2095
2381
|
version: 1,
|
|
2096
2382
|
changedFiles: [toRelativeProjectPath$1(filePath.file, options.projectRoot)],
|
|
2097
|
-
tokenSourceIds:
|
|
2383
|
+
tokenSourceIds: nextTokenSourceIds
|
|
2098
2384
|
};
|
|
2099
2385
|
return {
|
|
2100
2386
|
...patch,
|
|
@@ -2111,6 +2397,11 @@ async function inferStyledSystemPackageName(projectRoot) {
|
|
|
2111
2397
|
return;
|
|
2112
2398
|
}
|
|
2113
2399
|
}
|
|
2400
|
+
async function verifyWriteTarget(projectRoot, filePath, editId) {
|
|
2401
|
+
const verified = await verifyProjectWritePath(projectRoot, filePath);
|
|
2402
|
+
if (verified.ok) return void 0;
|
|
2403
|
+
return styleEditFailure(editId, verified.code, verified.message, verified.details);
|
|
2404
|
+
}
|
|
2114
2405
|
function styleEditFailure(editId, code, message, details) {
|
|
2115
2406
|
return {
|
|
2116
2407
|
ok: false,
|
|
@@ -2160,21 +2451,17 @@ function isPath(value) {
|
|
|
2160
2451
|
}
|
|
2161
2452
|
function isJsonValue(value) {
|
|
2162
2453
|
if (value === null) return true;
|
|
2163
|
-
if (
|
|
2164
|
-
|
|
2165
|
-
"number",
|
|
2166
|
-
"boolean"
|
|
2167
|
-
].includes(typeof value)) return true;
|
|
2454
|
+
if (typeof value === "string" || typeof value === "boolean") return true;
|
|
2455
|
+
if (typeof value === "number") return Number.isFinite(value);
|
|
2168
2456
|
if (Array.isArray(value)) return value.every(isJsonValue);
|
|
2169
2457
|
if (!isRecord(value)) return false;
|
|
2170
2458
|
return Object.values(value).every(isJsonValue);
|
|
2171
2459
|
}
|
|
2172
2460
|
function isJsonPrimitive(value) {
|
|
2173
|
-
return value === null ||
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
].includes(typeof value);
|
|
2461
|
+
return value === null || typeof value === "string" || typeof value === "boolean" || typeof value === "number" && Number.isFinite(value);
|
|
2462
|
+
}
|
|
2463
|
+
function isJsonObject(value) {
|
|
2464
|
+
return isRecord(value) && Object.values(value).every(isJsonValue);
|
|
2178
2465
|
}
|
|
2179
2466
|
//#endregion
|
|
2180
2467
|
//#region src/vite.ts
|
|
@@ -2217,10 +2504,20 @@ function sculpted(options = {}) {
|
|
|
2217
2504
|
response.end(JSON.stringify(manifest()));
|
|
2218
2505
|
});
|
|
2219
2506
|
nextServer.middlewares.use(editorMetadataEndpoint, async (_request, response) => {
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2507
|
+
let metadata;
|
|
2508
|
+
try {
|
|
2509
|
+
metadata = await createEditorMetadata({
|
|
2510
|
+
projectRoot,
|
|
2511
|
+
pandaConfigPath: options.panda?.configPath
|
|
2512
|
+
});
|
|
2513
|
+
} catch (error) {
|
|
2514
|
+
logUnexpectedDevServerError("Failed to create Sculpted editor metadata.", error);
|
|
2515
|
+
response.statusCode = 500;
|
|
2516
|
+
response.setHeader("content-type", "text/plain");
|
|
2517
|
+
response.setHeader("cache-control", "no-store");
|
|
2518
|
+
response.end(`Failed to create Sculpted editor metadata: ${errorMessage(error)}`);
|
|
2519
|
+
return;
|
|
2520
|
+
}
|
|
2224
2521
|
response.statusCode = 200;
|
|
2225
2522
|
response.setHeader("content-type", "application/json");
|
|
2226
2523
|
response.setHeader("cache-control", "no-store");
|
|
@@ -2242,11 +2539,17 @@ function sculpted(options = {}) {
|
|
|
2242
2539
|
response.end(JSON.stringify(requestResult.response));
|
|
2243
2540
|
return;
|
|
2244
2541
|
}
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2542
|
+
let result;
|
|
2543
|
+
try {
|
|
2544
|
+
result = await resolveOpenSourceLocation({
|
|
2545
|
+
request: requestResult.request,
|
|
2546
|
+
manifest: manifest(),
|
|
2547
|
+
projectRoot
|
|
2548
|
+
});
|
|
2549
|
+
} catch (error) {
|
|
2550
|
+
logUnexpectedDevServerError("Unhandled Sculpted source-open failure.", error);
|
|
2551
|
+
result = openSourceLocationFailure("open-failed", `Unhandled Sculpted source-open failure: ${errorMessage(error)}`);
|
|
2552
|
+
}
|
|
2250
2553
|
response.statusCode = result.ok ? 200 : 400;
|
|
2251
2554
|
response.setHeader("content-type", "application/json");
|
|
2252
2555
|
response.setHeader("cache-control", "no-store");
|
|
@@ -2303,7 +2606,7 @@ function sculpted(options = {}) {
|
|
|
2303
2606
|
sourceSyntax: options.sourceSyntax
|
|
2304
2607
|
});
|
|
2305
2608
|
manifestByFile.set(filePath, result.entries);
|
|
2306
|
-
if (result.entries.length > 0) server
|
|
2609
|
+
if (result.entries.length > 0) sendViteEvent(server, SCULPTED_EVENTS.manifestUpdate, {
|
|
2307
2610
|
version: 1,
|
|
2308
2611
|
changedFiles: [toRelativeProjectPath$1(filePath, projectRoot)],
|
|
2309
2612
|
entryIds: result.entries.map((entry) => entry.id)
|
|
@@ -2316,5 +2619,10 @@ function sculpted(options = {}) {
|
|
|
2316
2619
|
}
|
|
2317
2620
|
};
|
|
2318
2621
|
}
|
|
2622
|
+
function sendViteEvent(server, event, payload) {
|
|
2623
|
+
try {
|
|
2624
|
+
server?.ws?.send(event, payload);
|
|
2625
|
+
} catch {}
|
|
2626
|
+
}
|
|
2319
2627
|
//#endregion
|
|
2320
2628
|
export { sculpted };
|