@workglow/storage 0.0.126 → 0.1.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.
Files changed (36) hide show
  1. package/dist/browser.js +58 -23
  2. package/dist/browser.js.map +18 -18
  3. package/dist/bun.js +104 -42
  4. package/dist/bun.js.map +24 -24
  5. package/dist/node.js +104 -42
  6. package/dist/node.js.map +24 -24
  7. package/dist/queue/InMemoryQueueStorage.d.ts.map +1 -1
  8. package/dist/queue/IndexedDbQueueStorage.d.ts.map +1 -1
  9. package/dist/queue/SupabaseQueueStorage.d.ts +11 -0
  10. package/dist/queue/SupabaseQueueStorage.d.ts.map +1 -1
  11. package/dist/queue-limiter/IndexedDbRateLimiterStorage.d.ts.map +1 -1
  12. package/dist/sqlite/browser.d.ts.map +1 -1
  13. package/dist/sqlite/browser.js.map +2 -2
  14. package/dist/sqlite/bun.d.ts.map +1 -1
  15. package/dist/sqlite/bun.js.map +2 -2
  16. package/dist/tabular/BaseSqlTabularStorage.d.ts.map +1 -1
  17. package/dist/tabular/CachedTabularStorage.d.ts +1 -0
  18. package/dist/tabular/CachedTabularStorage.d.ts.map +1 -1
  19. package/dist/tabular/FsFolderTabularStorage.d.ts.map +1 -1
  20. package/dist/tabular/HuggingFaceTabularStorage.d.ts.map +1 -1
  21. package/dist/tabular/InMemoryTabularStorage.d.ts +2 -0
  22. package/dist/tabular/InMemoryTabularStorage.d.ts.map +1 -1
  23. package/dist/tabular/IndexedDbTabularStorage.d.ts.map +1 -1
  24. package/dist/tabular/PostgresTabularStorage.d.ts.map +1 -1
  25. package/dist/tabular/SharedInMemoryTabularStorage.d.ts.map +1 -1
  26. package/dist/tabular/SqliteTabularStorage.d.ts.map +1 -1
  27. package/dist/tabular/StorageError.d.ts.map +1 -1
  28. package/dist/tabular/SupabaseTabularStorage.d.ts.map +1 -1
  29. package/dist/tabular/TelemetryTabularStorage.d.ts.map +1 -1
  30. package/dist/util/HybridSubscriptionManager.d.ts.map +1 -1
  31. package/dist/util/PollingSubscriptionManager.d.ts +2 -0
  32. package/dist/util/PollingSubscriptionManager.d.ts.map +1 -1
  33. package/dist/vector/PostgresVectorStorage.d.ts +0 -12
  34. package/dist/vector/PostgresVectorStorage.d.ts.map +1 -1
  35. package/dist/vector/SqliteAiVectorStorage.d.ts.map +1 -1
  36. package/package.json +7 -7
package/dist/browser.js CHANGED
@@ -391,6 +391,7 @@ var MEMORY_TABULAR_REPOSITORY = createServiceToken2("storage.tabularRepository.i
391
391
  class InMemoryTabularStorage extends BaseTabularStorage {
392
392
  values = new Map;
393
393
  autoIncrementCounter = 0;
394
+ _lastPutWasInsert = false;
394
395
  constructor(schema, primaryKeyNames, indexes = [], clientProvidedKeys = "if-missing") {
395
396
  super(schema, primaryKeyNames, indexes, clientProvidedKeys);
396
397
  }
@@ -426,6 +427,7 @@ class InMemoryTabularStorage extends BaseTabularStorage {
426
427
  }
427
428
  const { key } = this.separateKeyValueFromCombined(entityToStore);
428
429
  const id = await makeFingerprint2(key);
430
+ this._lastPutWasInsert = !this.values.has(id);
429
431
  this.values.set(id, entityToStore);
430
432
  this.events.emit("put", entityToStore);
431
433
  return entityToStore;
@@ -622,7 +624,7 @@ class InMemoryTabularStorage extends BaseTabularStorage {
622
624
  }
623
625
  subscribeToChanges(callback, options) {
624
626
  const handlePut = (entity) => {
625
- callback({ type: "UPDATE", new: entity });
627
+ callback({ type: this._lastPutWasInsert ? "INSERT" : "UPDATE", new: entity });
626
628
  };
627
629
  const handleDelete = (_key) => {
628
630
  callback({ type: "DELETE" });
@@ -651,6 +653,7 @@ class CachedTabularStorage extends BaseTabularStorage {
651
653
  cache;
652
654
  durable;
653
655
  cacheInitialized = false;
656
+ cacheInitPromise = null;
654
657
  constructor(durable, cache, schema, primaryKeyNames, indexes, clientProvidedKeys = "if-missing") {
655
658
  if (!schema || !primaryKeyNames) {
656
659
  throw new Error("Schema and primaryKeyNames must be provided when creating CachedTabularStorage");
@@ -684,16 +687,23 @@ class CachedTabularStorage extends BaseTabularStorage {
684
687
  async initializeCache() {
685
688
  if (this.cacheInitialized)
686
689
  return;
687
- try {
688
- const all = await this.durable.getAll();
689
- if (all && all.length > 0) {
690
- await this.cache.putBulk(all);
691
- }
692
- this.cacheInitialized = true;
693
- } catch (error) {
694
- getLogger().warn("Failed to initialize cache from durable repository:", { error });
695
- this.cacheInitialized = true;
690
+ if (this.cacheInitPromise) {
691
+ return this.cacheInitPromise;
696
692
  }
693
+ this.cacheInitPromise = (async () => {
694
+ try {
695
+ const all = await this.durable.getAll();
696
+ if (all && all.length > 0) {
697
+ await this.cache.putBulk(all);
698
+ }
699
+ this.cacheInitialized = true;
700
+ } catch (error) {
701
+ getLogger().warn("Failed to initialize cache from durable repository:", { error });
702
+ } finally {
703
+ this.cacheInitPromise = null;
704
+ }
705
+ })();
706
+ return this.cacheInitPromise;
697
707
  }
698
708
  async put(value) {
699
709
  await this.initializeCache();
@@ -1529,13 +1539,17 @@ class InMemoryQueueStorage {
1529
1539
  }
1530
1540
  async complete(job) {
1531
1541
  await sleep(0);
1532
- const index = this.jobQueue.findIndex((j) => j.id === job.id);
1542
+ const jobWithPrefixes = job;
1543
+ const index = this.jobQueue.findIndex((j) => j.id === job.id && this.matchesPrefixes(j));
1533
1544
  if (index !== -1) {
1534
1545
  const existing = this.jobQueue[index];
1535
1546
  const currentAttempts = existing?.run_attempts ?? 0;
1536
- job.run_attempts = currentAttempts + 1;
1537
- this.jobQueue[index] = job;
1538
- this.events.emit("change", { type: "UPDATE", old: existing, new: job });
1547
+ jobWithPrefixes.run_attempts = currentAttempts + 1;
1548
+ for (const [key, value] of Object.entries(this.prefixValues)) {
1549
+ jobWithPrefixes[key] = value;
1550
+ }
1551
+ this.jobQueue[index] = jobWithPrefixes;
1552
+ this.events.emit("change", { type: "UPDATE", old: existing, new: jobWithPrefixes });
1539
1553
  }
1540
1554
  }
1541
1555
  async abort(id) {
@@ -1890,6 +1904,7 @@ class PollingSubscriptionManager {
1890
1904
  intervals = new Map;
1891
1905
  lastKnownState = new Map;
1892
1906
  initialized = false;
1907
+ initializing = false;
1893
1908
  fetchState;
1894
1909
  compareItems;
1895
1910
  payloadFactory;
@@ -1914,7 +1929,8 @@ class PollingSubscriptionManager {
1914
1929
  this.intervals.set(interval, intervalGroup);
1915
1930
  if (!this.initialized) {
1916
1931
  this.initialized = true;
1917
- this.initAndPoll(subscribers, subscription);
1932
+ this.initializing = true;
1933
+ this.initAndPoll(subscription);
1918
1934
  } else {
1919
1935
  this.pollForNewSubscriber(subscription);
1920
1936
  }
@@ -1933,7 +1949,7 @@ class PollingSubscriptionManager {
1933
1949
  }
1934
1950
  };
1935
1951
  }
1936
- async initAndPoll(subscribers, newSubscription) {
1952
+ async initAndPoll(newSubscription) {
1937
1953
  try {
1938
1954
  this.lastKnownState = await this.fetchState();
1939
1955
  for (const [, item] of this.lastKnownState) {
@@ -1942,7 +1958,9 @@ class PollingSubscriptionManager {
1942
1958
  newSubscription.callback(payload);
1943
1959
  } catch {}
1944
1960
  }
1945
- } catch {}
1961
+ } catch {} finally {
1962
+ this.initializing = false;
1963
+ }
1946
1964
  }
1947
1965
  pollForNewSubscriber(subscription) {
1948
1966
  for (const [, item] of this.lastKnownState) {
@@ -1955,6 +1973,8 @@ class PollingSubscriptionManager {
1955
1973
  async poll(subscribers) {
1956
1974
  if (subscribers.size === 0)
1957
1975
  return;
1976
+ if (this.initializing)
1977
+ return;
1958
1978
  try {
1959
1979
  const currentState = await this.fetchState();
1960
1980
  const changes = [];
@@ -1998,6 +2018,7 @@ class PollingSubscriptionManager {
1998
2018
  this.intervals.clear();
1999
2019
  this.lastKnownState.clear();
2000
2020
  this.initialized = false;
2021
+ this.initializing = false;
2001
2022
  }
2002
2023
  }
2003
2024
  // src/vector/InMemoryVectorStorage.ts
@@ -2102,7 +2123,7 @@ class InMemoryVectorStorage extends InMemoryTabularStorage {
2102
2123
  continue;
2103
2124
  }
2104
2125
  const vectorScore = cosineSimilarity(query, vector);
2105
- const metadataText = Object.values(metadata).join(" ").toLowerCase();
2126
+ const metadataText = Object.values(metadata ?? {}).join(" ").toLowerCase();
2106
2127
  const textScore = textRelevance(metadataText, textQuery);
2107
2128
  const combinedScore = vectorWeight * vectorScore + (1 - vectorWeight) * textScore;
2108
2129
  if (combinedScore < scoreThreshold) {
@@ -4484,12 +4505,24 @@ class SupabaseQueueStorage {
4484
4505
  const conditions = this.prefixes.map((p) => {
4485
4506
  const value = this.prefixValues[p.name];
4486
4507
  if (p.type === "uuid") {
4487
- return `${p.name} = '${this.escapeSqlString(String(value))}'`;
4508
+ const validated = this.validateSqlValue(String(value), `prefix "${p.name}"`);
4509
+ return `${p.name} = '${this.escapeSqlString(validated)}'`;
4510
+ }
4511
+ const numValue = Number(value ?? 0);
4512
+ if (!Number.isFinite(numValue)) {
4513
+ throw new Error(`Invalid numeric prefix value for "${p.name}": ${value}`);
4488
4514
  }
4489
- return `${p.name} = ${Number(value ?? 0)}`;
4515
+ return `${p.name} = ${numValue}`;
4490
4516
  }).join(" AND ");
4491
4517
  return " AND " + conditions;
4492
4518
  }
4519
+ static SAFE_SQL_VALUE_RE = /^[a-zA-Z0-9_\-.:]+$/;
4520
+ validateSqlValue(value, context) {
4521
+ if (!SupabaseQueueStorage.SAFE_SQL_VALUE_RE.test(value)) {
4522
+ throw new Error(`Unsafe value for ${context}: "${value}". Values must match /^[a-zA-Z0-9_\\-.:]+$/.`);
4523
+ }
4524
+ return value;
4525
+ }
4493
4526
  escapeSqlString(value) {
4494
4527
  return value.replace(/'/g, "''");
4495
4528
  }
@@ -4596,8 +4629,10 @@ class SupabaseQueueStorage {
4596
4629
  }
4597
4630
  async next(workerId) {
4598
4631
  const prefixConditions = this.buildPrefixWhereSql();
4599
- const escapedQueueName = this.escapeSqlString(this.queueName);
4600
- const escapedWorkerId = this.escapeSqlString(workerId);
4632
+ const validatedQueueName = this.validateSqlValue(this.queueName, "queueName");
4633
+ const validatedWorkerId = this.validateSqlValue(workerId, "workerId");
4634
+ const escapedQueueName = this.escapeSqlString(validatedQueueName);
4635
+ const escapedWorkerId = this.escapeSqlString(validatedWorkerId);
4601
4636
  const sql = `
4602
4637
  UPDATE ${this.tableName}
4603
4638
  SET status = '${JobStatus.PROCESSING}', last_ran_at = NOW() AT TIME ZONE 'UTC', worker_id = '${escapedWorkerId}'
@@ -5469,4 +5504,4 @@ export {
5469
5504
  BaseTabularStorage
5470
5505
  };
5471
5506
 
5472
- //# debugId=D02D6875010DA7A164756E2164756E21
5507
+ //# debugId=09B8497E3C06E04164756E2164756E21