@emulates/firehose 0.1.1 → 1.0.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/CHANGELOG.md CHANGED
@@ -1,9 +1,19 @@
1
1
  # Changelog — @emulates/firehose
2
2
 
3
- ## 0.1.1 (2026-10-06)
3
+ ## 1.0.0 (2026-10-07)
4
4
 
5
- Initial release.
5
+ ### ⚠️ Breaking changes
6
+
7
+ - point the repo at crvouga/emulates ([cdb5e53](https://github.com/crvouga/emulates/commit/cdb5e536ed8c1f52345e3984f089001c25fdb08a))
8
+
9
+ ### Fixes and improvements
10
+
11
+ - format the emulates records query ([8698872](https://github.com/crvouga/emulates/commit/8698872509d06002be5a8fcdc85d79f8462320c3))
6
12
 
7
13
  ### Dependencies
8
14
 
9
15
  - `@emulates/sqlite`
16
+
17
+ ## 0.1.1 (2026-10-06)
18
+
19
+ Initial release.
package/DISCOVERY.md CHANGED
@@ -47,7 +47,7 @@ designed for assertions and diagnosis by consuming test suites.
47
47
 
48
48
  ## Report a mismatch or missing capability
49
49
 
50
- Follow the [agent reporting contract](https://github.com/crvouga/emulators/blob/main/docs/REPORTING_ISSUES.md). Include package version,
50
+ Follow the [agent reporting contract](https://github.com/crvouga/emulates/blob/main/docs/REPORTING_ISSUES.md). Include package version,
51
51
  operation/command, a minimal redacted request, actual emulator result, expected oracle result or vendor
52
52
  documentation, and whether the mismatch appears in the matrix. Never include keys, tokens,
53
53
  customer data, prompts, PHI, card data, or unredacted recordings.
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @emulates/firehose
2
2
 
3
- > Part of [Emulates](https://github.com/crvouga/emulators): high-fidelity, in-process emulators for APIs and databases.
3
+ > Part of [Emulates](https://github.com/crvouga/emulates): high-fidelity, in-process emulators for APIs and databases.
4
4
 
5
5
  Stateful local emulator of Amazon Data Firehose. ESM; Node 22+ or Bun 1.2+.
6
6
 
@@ -33,7 +33,7 @@ var CORE_MIGRATIONS = [
33
33
  {
34
34
  id: "20260322_core_records_sequences",
35
35
  sql: `
36
- CREATE TABLE IF NOT EXISTS emulators_records (
36
+ CREATE TABLE IF NOT EXISTS emulates_records (
37
37
  namespace TEXT NOT NULL,
38
38
  collection TEXT NOT NULL,
39
39
  id TEXT NOT NULL,
@@ -41,9 +41,9 @@ var CORE_MIGRATIONS = [
41
41
  value TEXT NOT NULL,
42
42
  PRIMARY KEY (namespace, collection, id)
43
43
  );
44
- CREATE INDEX IF NOT EXISTS emulators_records_seq
45
- ON emulators_records (namespace, collection, seq);
46
- CREATE TABLE IF NOT EXISTS emulators_sequences (
44
+ CREATE INDEX IF NOT EXISTS emulates_records_seq
45
+ ON emulates_records (namespace, collection, seq);
46
+ CREATE TABLE IF NOT EXISTS emulates_sequences (
47
47
  namespace TEXT NOT NULL,
48
48
  name TEXT NOT NULL,
49
49
  kind TEXT NOT NULL,
@@ -53,13 +53,33 @@ var CORE_MIGRATIONS = [
53
53
  `
54
54
  }
55
55
  ];
56
+ var LEGACY_TABLES = [
57
+ ["emulators_records", "emulates_records"],
58
+ ["emulators_sequences", "emulates_sequences"]
59
+ ];
60
+ var LEGACY_INDEXES = [["emulators_records_seq", "emulates_records_seq"]];
61
+ var namesOf = (sqlite, type) => new Set(sqlite.prepare("SELECT name FROM sqlite_master WHERE type = ?").all(type).map((row) => row.name));
56
62
  var migrateCore = (sqlite) => {
57
63
  migrate(sqlite, CORE_MIGRATIONS);
64
+ const tables = namesOf(sqlite, "table");
65
+ const indexes = namesOf(sqlite, "index");
66
+ sqlite.transaction(() => {
67
+ for (const [from, to] of LEGACY_TABLES) {
68
+ if (tables.has(from) && !tables.has(to))
69
+ sqlite.exec(`ALTER TABLE ${from} RENAME TO ${to}`);
70
+ }
71
+ for (const [from, to] of LEGACY_INDEXES) {
72
+ if (!indexes.has(from) || indexes.has(to))
73
+ continue;
74
+ sqlite.exec(`DROP INDEX ${from}`);
75
+ sqlite.exec(`CREATE INDEX ${to} ON emulates_records (namespace, collection, seq)`);
76
+ }
77
+ });
58
78
  };
59
79
  var clearNamespace = (sqlite, namespace) => {
60
80
  sqlite.transaction(() => {
61
- sqlite.prepare("DELETE FROM emulators_records WHERE namespace = ?").run(namespace);
62
- sqlite.prepare("DELETE FROM emulators_sequences WHERE namespace = ?").run(namespace);
81
+ sqlite.prepare("DELETE FROM emulates_records WHERE namespace = ?").run(namespace);
82
+ sqlite.prepare("DELETE FROM emulates_sequences WHERE namespace = ?").run(namespace);
63
83
  });
64
84
  };
65
85
 
@@ -4220,9 +4240,9 @@ var Collection = class {
4220
4240
  this.collectionName = collectionName;
4221
4241
  }
4222
4242
  bumpCollectionSeq() {
4223
- const row = this.sqlite.prepare("SELECT value FROM emulators_sequences WHERE namespace = ? AND name = ? AND kind = 'collection'").get(this.namespace, this.collectionName);
4243
+ const row = this.sqlite.prepare("SELECT value FROM emulates_sequences WHERE namespace = ? AND name = ? AND kind = 'collection'").get(this.namespace, this.collectionName);
4224
4244
  const next = (row?.value ?? 0) + 1;
4225
- this.sqlite.prepare(`INSERT INTO emulators_sequences (namespace, name, kind, value) VALUES (?, ?, 'collection', ?)
4245
+ this.sqlite.prepare(`INSERT INTO emulates_sequences (namespace, name, kind, value) VALUES (?, ?, 'collection', ?)
4226
4246
  ON CONFLICT(namespace, name, kind) DO UPDATE SET value = excluded.value`).run(this.namespace, this.collectionName, next);
4227
4247
  return next;
4228
4248
  }
@@ -4230,13 +4250,13 @@ var Collection = class {
4230
4250
  return this.sqlite.transaction(() => this.bumpCollectionSeq());
4231
4251
  }
4232
4252
  get(id) {
4233
- const row = this.sqlite.prepare("SELECT value FROM emulators_records WHERE namespace = ? AND collection = ? AND id = ?").get(this.namespace, this.collectionName, id);
4253
+ const row = this.sqlite.prepare("SELECT value FROM emulates_records WHERE namespace = ? AND collection = ? AND id = ?").get(this.namespace, this.collectionName, id);
4234
4254
  if (!row)
4235
4255
  return void 0;
4236
4256
  return JSON.parse(row.value).value;
4237
4257
  }
4238
4258
  has(id) {
4239
- const row = this.sqlite.prepare("SELECT 1 AS ok FROM emulators_records WHERE namespace = ? AND collection = ? AND id = ?").get(this.namespace, this.collectionName, id);
4259
+ const row = this.sqlite.prepare("SELECT 1 AS ok FROM emulates_records WHERE namespace = ? AND collection = ? AND id = ?").get(this.namespace, this.collectionName, id);
4240
4260
  return row !== void 0;
4241
4261
  }
4242
4262
  /** Insert a new record, assigning it the next sequence number. */
@@ -4244,7 +4264,7 @@ var Collection = class {
4244
4264
  return this.sqlite.transaction(() => {
4245
4265
  const seq = this.bumpCollectionSeq();
4246
4266
  const stored = { seq, value };
4247
- this.sqlite.prepare(`INSERT INTO emulators_records (namespace, collection, id, seq, value)
4267
+ this.sqlite.prepare(`INSERT INTO emulates_records (namespace, collection, id, seq, value)
4248
4268
  VALUES (?, ?, ?, ?, ?)
4249
4269
  ON CONFLICT(namespace, collection, id) DO UPDATE SET seq = excluded.seq, value = excluded.value`).run(this.namespace, this.collectionName, id, seq, JSON.stringify(stored));
4250
4270
  return stored;
@@ -4253,25 +4273,25 @@ var Collection = class {
4253
4273
  /** Replace an existing record's value, keeping its position. */
4254
4274
  update(id, value) {
4255
4275
  return this.sqlite.transaction(() => {
4256
- const row = this.sqlite.prepare("SELECT seq, value FROM emulators_records WHERE namespace = ? AND collection = ? AND id = ?").get(this.namespace, this.collectionName, id);
4276
+ const row = this.sqlite.prepare("SELECT seq, value FROM emulates_records WHERE namespace = ? AND collection = ? AND id = ?").get(this.namespace, this.collectionName, id);
4257
4277
  if (!row)
4258
4278
  return void 0;
4259
4279
  const stored = { seq: row.seq, value };
4260
- this.sqlite.prepare("UPDATE emulators_records SET value = ? WHERE namespace = ? AND collection = ? AND id = ?").run(JSON.stringify(stored), this.namespace, this.collectionName, id);
4280
+ this.sqlite.prepare("UPDATE emulates_records SET value = ? WHERE namespace = ? AND collection = ? AND id = ?").run(JSON.stringify(stored), this.namespace, this.collectionName, id);
4261
4281
  return stored;
4262
4282
  });
4263
4283
  }
4264
4284
  delete(id) {
4265
- const result = this.sqlite.prepare("DELETE FROM emulators_records WHERE namespace = ? AND collection = ? AND id = ?").run(this.namespace, this.collectionName, id);
4285
+ const result = this.sqlite.prepare("DELETE FROM emulates_records WHERE namespace = ? AND collection = ? AND id = ?").run(this.namespace, this.collectionName, id);
4266
4286
  return result.changes > 0;
4267
4287
  }
4268
4288
  /** How many records the collection holds, without reading them. */
4269
4289
  count() {
4270
- const row = this.sqlite.prepare("SELECT COUNT(*) AS n FROM emulators_records WHERE namespace = ? AND collection = ?").get(this.namespace, this.collectionName);
4290
+ const row = this.sqlite.prepare("SELECT COUNT(*) AS n FROM emulates_records WHERE namespace = ? AND collection = ?").get(this.namespace, this.collectionName);
4271
4291
  return Number(row?.n ?? 0);
4272
4292
  }
4273
4293
  list(options = {}) {
4274
- const rows = this.sqlite.prepare("SELECT id, seq, value FROM emulators_records WHERE namespace = ? AND collection = ?").all(this.namespace, this.collectionName);
4294
+ const rows = this.sqlite.prepare("SELECT id, seq, value FROM emulates_records WHERE namespace = ? AND collection = ?").all(this.namespace, this.collectionName);
4275
4295
  const out = [];
4276
4296
  for (const row of rows) {
4277
4297
  const stored = JSON.parse(row.value);
@@ -4320,9 +4340,9 @@ var IdSequence = class {
4320
4340
  }
4321
4341
  next(prefix, length = 14) {
4322
4342
  return this.sqlite.transaction(() => {
4323
- const row = this.sqlite.prepare("SELECT value FROM emulators_sequences WHERE namespace = ? AND name = ? AND kind = 'id'").get(this.namespace, prefix);
4343
+ const row = this.sqlite.prepare("SELECT value FROM emulates_sequences WHERE namespace = ? AND name = ? AND kind = 'id'").get(this.namespace, prefix);
4324
4344
  const value = (row?.value ?? 0) + 1;
4325
- this.sqlite.prepare(`INSERT INTO emulators_sequences (namespace, name, kind, value) VALUES (?, ?, 'id', ?)
4345
+ this.sqlite.prepare(`INSERT INTO emulates_sequences (namespace, name, kind, value) VALUES (?, ?, 'id', ?)
4326
4346
  ON CONFLICT(namespace, name, kind) DO UPDATE SET value = excluded.value`).run(this.namespace, prefix, value);
4327
4347
  return `${prefix}${opaqueToken(`${this.salt}:${prefix}:${value}`, length)}`;
4328
4348
  });
@@ -5165,7 +5185,7 @@ var json = (status, body) => new Response(JSON.stringify(body), {
5165
5185
  status,
5166
5186
  headers: { "content-type": "application/json; charset=utf-8" }
5167
5187
  });
5168
- var adminError = (status, message) => json(status, { error: { type: "emulators_admin", message } });
5188
+ var adminError = (status, message) => json(status, { error: { type: "emulates_admin", message } });
5169
5189
  var UNITS = {
5170
5190
  ms: 1,
5171
5191
  s: 1e3,
@@ -6037,18 +6057,18 @@ var adminUiRoutes = (service, ui, adminPrefix = ADMIN_PREFIX) => {
6037
6057
  // ../core/dist/snapshot.js
6038
6058
  var snapshotNamespace = (sqlite, namespace) => ({
6039
6059
  namespace,
6040
- records: sqlite.prepare("SELECT collection, id, seq, value FROM emulators_records WHERE namespace = ? ORDER BY collection, seq").all(namespace),
6041
- sequences: sqlite.prepare("SELECT name, kind, value FROM emulators_sequences WHERE namespace = ? ORDER BY name, kind").all(namespace)
6060
+ records: sqlite.prepare("SELECT collection, id, seq, value FROM emulates_records WHERE namespace = ? ORDER BY collection, seq").all(namespace),
6061
+ sequences: sqlite.prepare("SELECT name, kind, value FROM emulates_sequences WHERE namespace = ? ORDER BY name, kind").all(namespace)
6042
6062
  });
6043
6063
  var restoreNamespace = (sqlite, namespace, snapshot) => {
6044
6064
  sqlite.transaction(() => {
6045
- sqlite.prepare("DELETE FROM emulators_records WHERE namespace = ?").run(namespace);
6046
- sqlite.prepare("DELETE FROM emulators_sequences WHERE namespace = ?").run(namespace);
6047
- const record = sqlite.prepare("INSERT INTO emulators_records (namespace, collection, id, seq, value) VALUES (?, ?, ?, ?, ?)");
6065
+ sqlite.prepare("DELETE FROM emulates_records WHERE namespace = ?").run(namespace);
6066
+ sqlite.prepare("DELETE FROM emulates_sequences WHERE namespace = ?").run(namespace);
6067
+ const record = sqlite.prepare("INSERT INTO emulates_records (namespace, collection, id, seq, value) VALUES (?, ?, ?, ?, ?)");
6048
6068
  for (const row of snapshot.records) {
6049
6069
  record.run(namespace, row.collection, row.id, row.seq, row.value);
6050
6070
  }
6051
- const sequence = sqlite.prepare("INSERT INTO emulators_sequences (namespace, name, kind, value) VALUES (?, ?, ?, ?)");
6071
+ const sequence = sqlite.prepare("INSERT INTO emulates_sequences (namespace, name, kind, value) VALUES (?, ?, ?, ?)");
6052
6072
  for (const row of snapshot.sequences) {
6053
6073
  sequence.run(namespace, row.name, row.kind, row.value);
6054
6074
  }
@@ -6147,8 +6167,8 @@ var discoverCollections = (root) => {
6147
6167
  return found;
6148
6168
  };
6149
6169
  var storedNames = (sqlite, namespace) => {
6150
- const records = sqlite.prepare("SELECT DISTINCT collection AS name FROM emulators_records WHERE namespace = ?").all(namespace);
6151
- const sequences = sqlite.prepare("SELECT DISTINCT name FROM emulators_sequences WHERE namespace = ? AND kind = 'collection'").all(namespace);
6170
+ const records = sqlite.prepare("SELECT DISTINCT collection AS name FROM emulates_records WHERE namespace = ?").all(namespace);
6171
+ const sequences = sqlite.prepare("SELECT DISTINCT name FROM emulates_sequences WHERE namespace = ? AND kind = 'collection'").all(namespace);
6152
6172
  return [...records, ...sequences].map((row) => row.name);
6153
6173
  };
6154
6174
  var blankAccum = (name) => ({
@@ -6389,7 +6409,7 @@ var json3 = (status, body) => new Response(JSON.stringify(body), {
6389
6409
  status,
6390
6410
  headers: { "content-type": "application/json; charset=utf-8" }
6391
6411
  });
6392
- var adminError2 = (status, message) => json3(status, { error: { type: "emulators_admin", message } });
6412
+ var adminError2 = (status, message) => json3(status, { error: { type: "emulates_admin", message } });
6393
6413
  var fromResult = (result, status) => result.ok ? json3(status, result.value) : adminError2(result.status, result.message);
6394
6414
  var integerParam = (value) => {
6395
6415
  if (value === null)
@@ -6490,14 +6510,14 @@ var stateAdminRoutes = (routes) => {
6490
6510
  };
6491
6511
 
6492
6512
  // ../core/dist/version.js
6493
- var PACKAGE_VERSION = true ? "0.1.1" : UNRELEASED_VERSION;
6513
+ var PACKAGE_VERSION = true ? "1.0.0" : UNRELEASED_VERSION;
6494
6514
 
6495
6515
  // ../core/dist/webhooks.js
6496
6516
  var json4 = (status, body) => new Response(JSON.stringify(body), {
6497
6517
  status,
6498
6518
  headers: { "content-type": "application/json; charset=utf-8" }
6499
6519
  });
6500
- var adminError3 = (status, message) => json4(status, { error: { type: "emulators_admin", message } });
6520
+ var adminError3 = (status, message) => json4(status, { error: { type: "emulates_admin", message } });
6501
6521
  var isRecord4 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
6502
6522
  var parseEndpoint = (value) => {
6503
6523
  if (!isRecord4(value) || typeof value.url !== "string")
@@ -7099,7 +7119,7 @@ var createRuntime = (options) => {
7099
7119
  log(400);
7100
7120
  return stamp(new Response(JSON.stringify({
7101
7121
  error: {
7102
- type: "emulators_admin",
7122
+ type: "emulates_admin",
7103
7123
  message: `${NAMESPACE_HEADER} must match ${NAMESPACE_PATTERN}`
7104
7124
  }
7105
7125
  }), { status: 400, headers: { "content-type": "application/json; charset=utf-8" } }));
@@ -7265,7 +7285,7 @@ var adminJson = (status, body) => new Response(JSON.stringify(body), {
7265
7285
  status,
7266
7286
  headers: { "content-type": "application/json; charset=utf-8" }
7267
7287
  });
7268
- var adminFail = (status, message) => adminJson(status, { error: { type: "emulators_admin", message } });
7288
+ var adminFail = (status, message) => adminJson(status, { error: { type: "emulates_admin", message } });
7269
7289
  var isObject = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
7270
7290
  var credentialRoutes = (registry) => ({
7271
7291
  "GET /credentials": () => adminJson(200, {
@@ -7468,4 +7488,4 @@ export {
7468
7488
  createRuntime2 as createRuntime,
7469
7489
  FirehoseAPI
7470
7490
  };
7471
- //# sourceMappingURL=chunk-TTCJP75R.js.map
7491
+ //# sourceMappingURL=chunk-77CSI3VM.js.map