@orkestrel/scaffold 0.0.14 → 0.0.16

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.
@@ -296,6 +296,34 @@ function isMaterializerEventHooks(value) {
296
296
  }
297
297
  //#endregion
298
298
  //#region src/server/parsers.ts
299
+ /**
300
+ * Parse and semantically validate bare registry package names before Sync performs network I/O.
301
+ *
302
+ * @param value - Untrusted package-name collection.
303
+ * @returns A frozen owned snapshot of valid unique npm package names.
304
+ */
305
+ function parseSyncNames(value) {
306
+ const owned = (0, _orkestrel_contract.attempt)(() => {
307
+ if (!(0, _src_core.isDenseDataArray)(value, 1e3, (candidate) => typeof candidate === "string")) throw new Error("package names are malformed");
308
+ const length = Reflect.getOwnPropertyDescriptor(value, "length")?.value;
309
+ if (typeof length !== "number" || !Number.isSafeInteger(length) || length < 0 || length > 1e3) throw new Error("package name length is malformed");
310
+ const names = [];
311
+ for (let index = 0; index < length; index += 1) {
312
+ const descriptor = Reflect.getOwnPropertyDescriptor(value, String(index));
313
+ if (descriptor === void 0 || !Reflect.has(descriptor, "value") || typeof descriptor.value !== "string") throw new Error("package name is malformed");
314
+ names.push(descriptor.value);
315
+ }
316
+ return Object.freeze(names);
317
+ });
318
+ if (!owned.success) throw new _src_core.ScaffoldError("INVALID", "Sync package names are malformed", { error: owned.error });
319
+ const snapshot = owned.value;
320
+ const seen = /* @__PURE__ */ new Set();
321
+ for (const name of snapshot) {
322
+ if (name.length === 0 || name.length > _src_core.MAX_DEPENDENCY_NAME_LENGTH || !_src_core.EXTRA_NAME_PATTERN.test(name) || seen.has(name)) throw new _src_core.ScaffoldError("INVALID", "Sync package names are invalid", { name });
323
+ seen.add(name);
324
+ }
325
+ return snapshot;
326
+ }
299
327
  /** Parse and semantically validate dependency data before Sync performs network I/O. */
300
328
  function parseSyncDependencies(value, external) {
301
329
  const owned = (0, _orkestrel_contract.attempt)(() => {
@@ -3541,6 +3569,10 @@ var Sync = class Sync {
3541
3569
  get emitter() {
3542
3570
  return this.#emitter;
3543
3571
  }
3572
+ async lookup(names) {
3573
+ this.#ensureAlive();
3574
+ return this.#lookup(names, Float64Array.of(this.#budget));
3575
+ }
3544
3576
  async guides(deps, current) {
3545
3577
  this.#ensureAlive();
3546
3578
  return this.#guides(deps, current, Float64Array.of(this.#budget));
@@ -3570,21 +3602,33 @@ var Sync = class Sync {
3570
3602
  return guide;
3571
3603
  });
3572
3604
  }
3573
- #versions(deps, allowance) {
3605
+ async #versions(deps, allowance) {
3574
3606
  const parsed = parseSyncDependencies(deps, true);
3607
+ const lookups = await this.#lookup(parsed.map((dependency) => dependency.name), allowance);
3608
+ const versions = [];
3609
+ for (let index = 0; index < parsed.length; index += 1) {
3610
+ const dep = parsed[index];
3611
+ const lookup = lookups[index];
3612
+ if (dep === void 0 || lookup === void 0) throw new _src_core.ScaffoldError("INVALID", "Sync version lookup result is incomplete");
3613
+ versions.push(Sync.#toVersionSync(dep, lookup));
3614
+ }
3615
+ return Object.freeze(versions);
3616
+ }
3617
+ #lookup(names, allowance) {
3618
+ const parsed = parseSyncNames(names);
3575
3619
  if (parsed.length > this.#items) throw new _src_core.ScaffoldError("INVALID", "Sync dependency count exceeds its item limit", {
3576
3620
  items: parsed.length,
3577
3621
  limit: this.#items
3578
3622
  });
3579
- return Sync.#runPool(parsed, this.#concurrency, async (dep) => {
3580
- const url = this.#registryUrl(dep.name);
3623
+ return Sync.#runPool(parsed, this.#concurrency, async (name) => {
3624
+ const url = this.#registryUrl(name);
3581
3625
  const outcome = await Sync.#fetchText(url, this.#registryTimeout, this.#retries, this.#limit, allowance, this.#controller.signal);
3582
- const version = Sync.#toVersionSync(dep, outcome);
3626
+ const version = Sync.#toVersionLookup(name, outcome);
3583
3627
  if (outcome.kind === "failed") this.#emitter.emit("error", outcome.error);
3584
- this.#emitter.emit("version", dep.name);
3628
+ this.#emitter.emit("version", name);
3585
3629
  if (this.#strict && (version.freshness === "missing" || version.freshness === "failed")) throw new _src_core.ScaffoldError("FETCH", `Failed to fetch registry version at ${url}`, {
3586
3630
  url,
3587
- name: dep.name
3631
+ name
3588
3632
  });
3589
3633
  return version;
3590
3634
  });
@@ -3925,34 +3969,42 @@ var Sync = class Sync {
3925
3969
  ...baseline === void 0 ? {} : { baseline }
3926
3970
  };
3927
3971
  }
3928
- static #toVersionSync(dep, outcome) {
3972
+ static #toVersionLookup(name, outcome) {
3929
3973
  if (outcome.kind === "missing") return {
3930
- name: dep.name,
3931
- range: dep.range,
3932
- latest: "",
3974
+ name,
3933
3975
  freshness: "missing",
3934
3976
  note: "HTTP 404"
3935
3977
  };
3936
3978
  if (outcome.kind === "failed") return {
3937
- name: dep.name,
3938
- range: dep.range,
3939
- latest: "",
3979
+ name,
3940
3980
  freshness: "failed",
3941
3981
  note: outcome.note
3942
3982
  };
3943
3983
  const latest = Sync.#parseLatest(outcome.text);
3944
3984
  if (latest === void 0) return {
3985
+ name,
3986
+ freshness: "failed",
3987
+ note: "malformed registry response (missing dist-tags.latest)"
3988
+ };
3989
+ return {
3990
+ name,
3991
+ latest,
3992
+ freshness: "behind"
3993
+ };
3994
+ }
3995
+ static #toVersionSync(dep, lookup) {
3996
+ if (lookup.freshness !== "behind") return {
3945
3997
  name: dep.name,
3946
3998
  range: dep.range,
3947
3999
  latest: "",
3948
- freshness: "failed",
3949
- note: "malformed registry response (missing dist-tags.latest)"
4000
+ freshness: lookup.freshness,
4001
+ note: lookup.note
3950
4002
  };
3951
4003
  return {
3952
4004
  name: dep.name,
3953
4005
  range: dep.range,
3954
- latest,
3955
- freshness: (0, _src_core.rangeToFreshness)(dep.range, latest)
4006
+ latest: lookup.latest,
4007
+ freshness: (0, _src_core.rangeToFreshness)(dep.range, lookup.latest)
3956
4008
  };
3957
4009
  }
3958
4010
  static #toOrgPackages(outcome, url) {
@@ -4151,6 +4203,7 @@ exports.parseSyncBase = parseSyncBase;
4151
4203
  exports.parseSyncBranch = parseSyncBranch;
4152
4204
  exports.parseSyncCurrent = parseSyncCurrent;
4153
4205
  exports.parseSyncDependencies = parseSyncDependencies;
4206
+ exports.parseSyncNames = parseSyncNames;
4154
4207
  exports.parseSyncOptions = parseSyncOptions;
4155
4208
  exports.parseWritePreconditions = parseWritePreconditions;
4156
4209
  exports.pruneTargets = pruneTargets;