@spotpatch/dev-server 0.7.0 → 0.8.0

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/index.cjs CHANGED
@@ -2472,6 +2472,7 @@ function createSourceRegistry(options = {}) {
2472
2472
  );
2473
2473
  }
2474
2474
  componentIdsByPath.set(normalizedPath, currentIds);
2475
+ return fileId;
2475
2476
  },
2476
2477
  resolve(fileId) {
2477
2478
  return idToPath.get(fileId);
@@ -4095,14 +4096,26 @@ var import_node_crypto11 = require("crypto");
4095
4096
  var import_promises7 = require("fs/promises");
4096
4097
  var import_node_path8 = __toESM(require("path"), 1);
4097
4098
  var import_compiler = require("@spotpatch/compiler");
4099
+ var import_shared21 = require("@spotpatch/shared");
4098
4100
  var import_zod2 = require("zod");
4099
- var REGISTRATION_BODY_LIMIT_BYTES = 4096;
4101
+ var REGISTRATION_BODY_LIMIT_BYTES = import_shared21.DEFAULT_DATA_FLOW_LIMITS.protocolRequestMaxBytes;
4100
4102
  var REGISTRATION_IDENTITY_PATTERN = /^[A-Za-z0-9_-]{16,128}$/u;
4103
+ var DATA_FLOW_IDENTITY_PATTERN = /^[A-Za-z0-9_-]{1,128}$/u;
4101
4104
  var INTERNAL_SECRET_HEADER = "x-spotpatch-internal";
4102
4105
  var FORBIDDEN_SOURCE_SEGMENTS = /* @__PURE__ */ new Set([".next", "node_modules"]);
4103
4106
  var registrationRequestSchema = import_zod2.z.strictObject({
4104
4107
  epoch: import_zod2.z.string().regex(REGISTRATION_IDENTITY_PATTERN),
4105
- resourcePath: import_zod2.z.string().min(1).max(3072)
4108
+ resourcePath: import_zod2.z.string().min(1).max(3072),
4109
+ dataFlow: import_zod2.z.strictObject({
4110
+ sourceVersion: import_zod2.z.string().regex(DATA_FLOW_IDENTITY_PATTERN),
4111
+ components: import_zod2.z.array(
4112
+ import_zod2.z.strictObject({
4113
+ componentSourceId: import_zod2.z.string().regex(DATA_FLOW_IDENTITY_PATTERN),
4114
+ line: import_zod2.z.number().int().positive().max(1e7),
4115
+ column: import_zod2.z.number().int().positive().max(1e7)
4116
+ })
4117
+ ).max(import_shared21.DEFAULT_DATA_FLOW_LIMITS.sourceMaxComponents)
4118
+ }).optional()
4106
4119
  });
4107
4120
  function getSingleHeader3(request, name) {
4108
4121
  const value = request.headers[name.toLowerCase()];
@@ -4166,6 +4179,33 @@ async function createSourceRegistrationService(input) {
4166
4179
  }
4167
4180
  const root = await (0, import_promises7.realpath)(input.root);
4168
4181
  const sourceFilter = (0, import_compiler.createSourceFilter)(root, input.options);
4182
+ const dataFlowFilter = (0, import_compiler.createDataFlowSourceFilter)(root, input.options);
4183
+ const registrationQueues = /* @__PURE__ */ new Map();
4184
+ async function registerCurrentSource(sourcePath, dataFlow) {
4185
+ if (dataFlow === void 0) {
4186
+ return input.registry.register(sourcePath);
4187
+ }
4188
+ let fileId;
4189
+ const previous = registrationQueues.get(sourcePath) ?? Promise.resolve();
4190
+ const current = previous.catch(() => void 0).then(async () => {
4191
+ const currentSource = await (0, import_promises7.readFile)(sourcePath, "utf8");
4192
+ if ((0, import_compiler.createDataFlowSourceVersion)(currentSource) !== dataFlow.sourceVersion) {
4193
+ return;
4194
+ }
4195
+ fileId = input.registry.registerDataFlowComponents(
4196
+ sourcePath,
4197
+ dataFlow.sourceVersion,
4198
+ dataFlow.components
4199
+ );
4200
+ });
4201
+ registrationQueues.set(sourcePath, current);
4202
+ await current.finally(() => {
4203
+ if (registrationQueues.get(sourcePath) === current) {
4204
+ registrationQueues.delete(sourcePath);
4205
+ }
4206
+ });
4207
+ return fileId;
4208
+ }
4169
4209
  const handler = (request, response) => {
4170
4210
  const handle = async () => {
4171
4211
  const contentType = getSingleHeader3(request, "content-type")?.split(";", 1)[0]?.trim().toLowerCase();
@@ -4186,16 +4226,18 @@ async function createSourceRegistrationService(input) {
4186
4226
  const sourcePath = await resolveAuthorizedSource(
4187
4227
  root,
4188
4228
  parsed.data.resourcePath,
4189
- (absolutePath) => sourceFilter.shouldTransform(absolutePath, "<")
4229
+ (absolutePath) => parsed.data.dataFlow === void 0 ? sourceFilter.shouldTransform(absolutePath, "<") : dataFlowFilter.shouldTransform(absolutePath, "")
4190
4230
  );
4191
4231
  if (sourcePath === void 0) {
4192
4232
  writeJson3(response, 403, { ok: false });
4193
4233
  return;
4194
4234
  }
4195
- writeJson3(response, 200, {
4196
- epoch: input.registryEpoch,
4197
- fileId: input.registry.register(sourcePath)
4198
- });
4235
+ const fileId = await registerCurrentSource(sourcePath, parsed.data.dataFlow);
4236
+ if (fileId === void 0) {
4237
+ writeJson3(response, 409, { ok: false });
4238
+ return;
4239
+ }
4240
+ writeJson3(response, 200, { epoch: input.registryEpoch, fileId });
4199
4241
  };
4200
4242
  void handle().catch(() => {
4201
4243
  if (!response.headersSent) {