@emulates/acm 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 +12 -2
- package/DISCOVERY.md +1 -1
- package/README.md +1 -1
- package/dist/{chunk-H5GNI4YR.js → chunk-E5LEFT72.js} +53 -33
- package/dist/chunk-E5LEFT72.js.map +7 -0
- package/dist/{chunk-BFYCSZFV.js → chunk-JQ7NVTLE.js} +3 -3
- package/dist/{chunk-BFYCSZFV.js.map → chunk-JQ7NVTLE.js.map} +1 -1
- package/dist/cli.js +2 -2
- package/dist/index.js +1 -1
- package/dist/server.js +2 -2
- package/package.json +5 -5
- package/dist/chunk-H5GNI4YR.js.map +0 -7
package/CHANGELOG.md
CHANGED
|
@@ -1,9 +1,19 @@
|
|
|
1
1
|
# Changelog — @emulates/acm
|
|
2
2
|
|
|
3
|
-
## 0.
|
|
3
|
+
## 1.0.0 (2026-10-07)
|
|
4
4
|
|
|
5
|
-
|
|
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/
|
|
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/acm
|
|
2
2
|
|
|
3
|
-
> Part of [Emulates](https://github.com/crvouga/
|
|
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 Certificate Manager. ESM; Node 22+ or Bun 1.2+.
|
|
6
6
|
|
|
@@ -83,7 +83,7 @@ var CORE_MIGRATIONS = [
|
|
|
83
83
|
{
|
|
84
84
|
id: "20260322_core_records_sequences",
|
|
85
85
|
sql: `
|
|
86
|
-
CREATE TABLE IF NOT EXISTS
|
|
86
|
+
CREATE TABLE IF NOT EXISTS emulates_records (
|
|
87
87
|
namespace TEXT NOT NULL,
|
|
88
88
|
collection TEXT NOT NULL,
|
|
89
89
|
id TEXT NOT NULL,
|
|
@@ -91,9 +91,9 @@ var CORE_MIGRATIONS = [
|
|
|
91
91
|
value TEXT NOT NULL,
|
|
92
92
|
PRIMARY KEY (namespace, collection, id)
|
|
93
93
|
);
|
|
94
|
-
CREATE INDEX IF NOT EXISTS
|
|
95
|
-
ON
|
|
96
|
-
CREATE TABLE IF NOT EXISTS
|
|
94
|
+
CREATE INDEX IF NOT EXISTS emulates_records_seq
|
|
95
|
+
ON emulates_records (namespace, collection, seq);
|
|
96
|
+
CREATE TABLE IF NOT EXISTS emulates_sequences (
|
|
97
97
|
namespace TEXT NOT NULL,
|
|
98
98
|
name TEXT NOT NULL,
|
|
99
99
|
kind TEXT NOT NULL,
|
|
@@ -103,13 +103,33 @@ var CORE_MIGRATIONS = [
|
|
|
103
103
|
`
|
|
104
104
|
}
|
|
105
105
|
];
|
|
106
|
+
var LEGACY_TABLES = [
|
|
107
|
+
["emulators_records", "emulates_records"],
|
|
108
|
+
["emulators_sequences", "emulates_sequences"]
|
|
109
|
+
];
|
|
110
|
+
var LEGACY_INDEXES = [["emulators_records_seq", "emulates_records_seq"]];
|
|
111
|
+
var namesOf = (sqlite, type) => new Set(sqlite.prepare("SELECT name FROM sqlite_master WHERE type = ?").all(type).map((row) => row.name));
|
|
106
112
|
var migrateCore = (sqlite) => {
|
|
107
113
|
migrate(sqlite, CORE_MIGRATIONS);
|
|
114
|
+
const tables = namesOf(sqlite, "table");
|
|
115
|
+
const indexes = namesOf(sqlite, "index");
|
|
116
|
+
sqlite.transaction(() => {
|
|
117
|
+
for (const [from, to] of LEGACY_TABLES) {
|
|
118
|
+
if (tables.has(from) && !tables.has(to))
|
|
119
|
+
sqlite.exec(`ALTER TABLE ${from} RENAME TO ${to}`);
|
|
120
|
+
}
|
|
121
|
+
for (const [from, to] of LEGACY_INDEXES) {
|
|
122
|
+
if (!indexes.has(from) || indexes.has(to))
|
|
123
|
+
continue;
|
|
124
|
+
sqlite.exec(`DROP INDEX ${from}`);
|
|
125
|
+
sqlite.exec(`CREATE INDEX ${to} ON emulates_records (namespace, collection, seq)`);
|
|
126
|
+
}
|
|
127
|
+
});
|
|
108
128
|
};
|
|
109
129
|
var clearNamespace = (sqlite, namespace) => {
|
|
110
130
|
sqlite.transaction(() => {
|
|
111
|
-
sqlite.prepare("DELETE FROM
|
|
112
|
-
sqlite.prepare("DELETE FROM
|
|
131
|
+
sqlite.prepare("DELETE FROM emulates_records WHERE namespace = ?").run(namespace);
|
|
132
|
+
sqlite.prepare("DELETE FROM emulates_sequences WHERE namespace = ?").run(namespace);
|
|
113
133
|
});
|
|
114
134
|
};
|
|
115
135
|
|
|
@@ -4270,9 +4290,9 @@ var Collection = class {
|
|
|
4270
4290
|
this.collectionName = collectionName;
|
|
4271
4291
|
}
|
|
4272
4292
|
bumpCollectionSeq() {
|
|
4273
|
-
const row = this.sqlite.prepare("SELECT value FROM
|
|
4293
|
+
const row = this.sqlite.prepare("SELECT value FROM emulates_sequences WHERE namespace = ? AND name = ? AND kind = 'collection'").get(this.namespace, this.collectionName);
|
|
4274
4294
|
const next = (row?.value ?? 0) + 1;
|
|
4275
|
-
this.sqlite.prepare(`INSERT INTO
|
|
4295
|
+
this.sqlite.prepare(`INSERT INTO emulates_sequences (namespace, name, kind, value) VALUES (?, ?, 'collection', ?)
|
|
4276
4296
|
ON CONFLICT(namespace, name, kind) DO UPDATE SET value = excluded.value`).run(this.namespace, this.collectionName, next);
|
|
4277
4297
|
return next;
|
|
4278
4298
|
}
|
|
@@ -4280,13 +4300,13 @@ var Collection = class {
|
|
|
4280
4300
|
return this.sqlite.transaction(() => this.bumpCollectionSeq());
|
|
4281
4301
|
}
|
|
4282
4302
|
get(id) {
|
|
4283
|
-
const row = this.sqlite.prepare("SELECT value FROM
|
|
4303
|
+
const row = this.sqlite.prepare("SELECT value FROM emulates_records WHERE namespace = ? AND collection = ? AND id = ?").get(this.namespace, this.collectionName, id);
|
|
4284
4304
|
if (!row)
|
|
4285
4305
|
return void 0;
|
|
4286
4306
|
return JSON.parse(row.value).value;
|
|
4287
4307
|
}
|
|
4288
4308
|
has(id) {
|
|
4289
|
-
const row = this.sqlite.prepare("SELECT 1 AS ok FROM
|
|
4309
|
+
const row = this.sqlite.prepare("SELECT 1 AS ok FROM emulates_records WHERE namespace = ? AND collection = ? AND id = ?").get(this.namespace, this.collectionName, id);
|
|
4290
4310
|
return row !== void 0;
|
|
4291
4311
|
}
|
|
4292
4312
|
/** Insert a new record, assigning it the next sequence number. */
|
|
@@ -4294,7 +4314,7 @@ var Collection = class {
|
|
|
4294
4314
|
return this.sqlite.transaction(() => {
|
|
4295
4315
|
const seq = this.bumpCollectionSeq();
|
|
4296
4316
|
const stored = { seq, value };
|
|
4297
|
-
this.sqlite.prepare(`INSERT INTO
|
|
4317
|
+
this.sqlite.prepare(`INSERT INTO emulates_records (namespace, collection, id, seq, value)
|
|
4298
4318
|
VALUES (?, ?, ?, ?, ?)
|
|
4299
4319
|
ON CONFLICT(namespace, collection, id) DO UPDATE SET seq = excluded.seq, value = excluded.value`).run(this.namespace, this.collectionName, id, seq, JSON.stringify(stored));
|
|
4300
4320
|
return stored;
|
|
@@ -4303,25 +4323,25 @@ var Collection = class {
|
|
|
4303
4323
|
/** Replace an existing record's value, keeping its position. */
|
|
4304
4324
|
update(id, value) {
|
|
4305
4325
|
return this.sqlite.transaction(() => {
|
|
4306
|
-
const row = this.sqlite.prepare("SELECT seq, value FROM
|
|
4326
|
+
const row = this.sqlite.prepare("SELECT seq, value FROM emulates_records WHERE namespace = ? AND collection = ? AND id = ?").get(this.namespace, this.collectionName, id);
|
|
4307
4327
|
if (!row)
|
|
4308
4328
|
return void 0;
|
|
4309
4329
|
const stored = { seq: row.seq, value };
|
|
4310
|
-
this.sqlite.prepare("UPDATE
|
|
4330
|
+
this.sqlite.prepare("UPDATE emulates_records SET value = ? WHERE namespace = ? AND collection = ? AND id = ?").run(JSON.stringify(stored), this.namespace, this.collectionName, id);
|
|
4311
4331
|
return stored;
|
|
4312
4332
|
});
|
|
4313
4333
|
}
|
|
4314
4334
|
delete(id) {
|
|
4315
|
-
const result = this.sqlite.prepare("DELETE FROM
|
|
4335
|
+
const result = this.sqlite.prepare("DELETE FROM emulates_records WHERE namespace = ? AND collection = ? AND id = ?").run(this.namespace, this.collectionName, id);
|
|
4316
4336
|
return result.changes > 0;
|
|
4317
4337
|
}
|
|
4318
4338
|
/** How many records the collection holds, without reading them. */
|
|
4319
4339
|
count() {
|
|
4320
|
-
const row = this.sqlite.prepare("SELECT COUNT(*) AS n FROM
|
|
4340
|
+
const row = this.sqlite.prepare("SELECT COUNT(*) AS n FROM emulates_records WHERE namespace = ? AND collection = ?").get(this.namespace, this.collectionName);
|
|
4321
4341
|
return Number(row?.n ?? 0);
|
|
4322
4342
|
}
|
|
4323
4343
|
list(options = {}) {
|
|
4324
|
-
const rows = this.sqlite.prepare("SELECT id, seq, value FROM
|
|
4344
|
+
const rows = this.sqlite.prepare("SELECT id, seq, value FROM emulates_records WHERE namespace = ? AND collection = ?").all(this.namespace, this.collectionName);
|
|
4325
4345
|
const out = [];
|
|
4326
4346
|
for (const row of rows) {
|
|
4327
4347
|
const stored = JSON.parse(row.value);
|
|
@@ -4370,9 +4390,9 @@ var IdSequence = class {
|
|
|
4370
4390
|
}
|
|
4371
4391
|
next(prefix, length = 14) {
|
|
4372
4392
|
return this.sqlite.transaction(() => {
|
|
4373
|
-
const row = this.sqlite.prepare("SELECT value FROM
|
|
4393
|
+
const row = this.sqlite.prepare("SELECT value FROM emulates_sequences WHERE namespace = ? AND name = ? AND kind = 'id'").get(this.namespace, prefix);
|
|
4374
4394
|
const value = (row?.value ?? 0) + 1;
|
|
4375
|
-
this.sqlite.prepare(`INSERT INTO
|
|
4395
|
+
this.sqlite.prepare(`INSERT INTO emulates_sequences (namespace, name, kind, value) VALUES (?, ?, 'id', ?)
|
|
4376
4396
|
ON CONFLICT(namespace, name, kind) DO UPDATE SET value = excluded.value`).run(this.namespace, prefix, value);
|
|
4377
4397
|
return `${prefix}${opaqueToken(`${this.salt}:${prefix}:${value}`, length)}`;
|
|
4378
4398
|
});
|
|
@@ -5215,7 +5235,7 @@ var json = (status, body) => new Response(JSON.stringify(body), {
|
|
|
5215
5235
|
status,
|
|
5216
5236
|
headers: { "content-type": "application/json; charset=utf-8" }
|
|
5217
5237
|
});
|
|
5218
|
-
var adminError = (status, message) => json(status, { error: { type: "
|
|
5238
|
+
var adminError = (status, message) => json(status, { error: { type: "emulates_admin", message } });
|
|
5219
5239
|
var UNITS = {
|
|
5220
5240
|
ms: 1,
|
|
5221
5241
|
s: 1e3,
|
|
@@ -6087,18 +6107,18 @@ var adminUiRoutes = (service, ui, adminPrefix = ADMIN_PREFIX) => {
|
|
|
6087
6107
|
// ../core/dist/snapshot.js
|
|
6088
6108
|
var snapshotNamespace = (sqlite, namespace) => ({
|
|
6089
6109
|
namespace,
|
|
6090
|
-
records: sqlite.prepare("SELECT collection, id, seq, value FROM
|
|
6091
|
-
sequences: sqlite.prepare("SELECT name, kind, value FROM
|
|
6110
|
+
records: sqlite.prepare("SELECT collection, id, seq, value FROM emulates_records WHERE namespace = ? ORDER BY collection, seq").all(namespace),
|
|
6111
|
+
sequences: sqlite.prepare("SELECT name, kind, value FROM emulates_sequences WHERE namespace = ? ORDER BY name, kind").all(namespace)
|
|
6092
6112
|
});
|
|
6093
6113
|
var restoreNamespace = (sqlite, namespace, snapshot) => {
|
|
6094
6114
|
sqlite.transaction(() => {
|
|
6095
|
-
sqlite.prepare("DELETE FROM
|
|
6096
|
-
sqlite.prepare("DELETE FROM
|
|
6097
|
-
const record = sqlite.prepare("INSERT INTO
|
|
6115
|
+
sqlite.prepare("DELETE FROM emulates_records WHERE namespace = ?").run(namespace);
|
|
6116
|
+
sqlite.prepare("DELETE FROM emulates_sequences WHERE namespace = ?").run(namespace);
|
|
6117
|
+
const record = sqlite.prepare("INSERT INTO emulates_records (namespace, collection, id, seq, value) VALUES (?, ?, ?, ?, ?)");
|
|
6098
6118
|
for (const row of snapshot.records) {
|
|
6099
6119
|
record.run(namespace, row.collection, row.id, row.seq, row.value);
|
|
6100
6120
|
}
|
|
6101
|
-
const sequence = sqlite.prepare("INSERT INTO
|
|
6121
|
+
const sequence = sqlite.prepare("INSERT INTO emulates_sequences (namespace, name, kind, value) VALUES (?, ?, ?, ?)");
|
|
6102
6122
|
for (const row of snapshot.sequences) {
|
|
6103
6123
|
sequence.run(namespace, row.name, row.kind, row.value);
|
|
6104
6124
|
}
|
|
@@ -6197,8 +6217,8 @@ var discoverCollections = (root) => {
|
|
|
6197
6217
|
return found;
|
|
6198
6218
|
};
|
|
6199
6219
|
var storedNames = (sqlite, namespace) => {
|
|
6200
|
-
const records = sqlite.prepare("SELECT DISTINCT collection AS name FROM
|
|
6201
|
-
const sequences = sqlite.prepare("SELECT DISTINCT name FROM
|
|
6220
|
+
const records = sqlite.prepare("SELECT DISTINCT collection AS name FROM emulates_records WHERE namespace = ?").all(namespace);
|
|
6221
|
+
const sequences = sqlite.prepare("SELECT DISTINCT name FROM emulates_sequences WHERE namespace = ? AND kind = 'collection'").all(namespace);
|
|
6202
6222
|
return [...records, ...sequences].map((row) => row.name);
|
|
6203
6223
|
};
|
|
6204
6224
|
var blankAccum = (name) => ({
|
|
@@ -6439,7 +6459,7 @@ var json3 = (status, body) => new Response(JSON.stringify(body), {
|
|
|
6439
6459
|
status,
|
|
6440
6460
|
headers: { "content-type": "application/json; charset=utf-8" }
|
|
6441
6461
|
});
|
|
6442
|
-
var adminError2 = (status, message) => json3(status, { error: { type: "
|
|
6462
|
+
var adminError2 = (status, message) => json3(status, { error: { type: "emulates_admin", message } });
|
|
6443
6463
|
var fromResult = (result, status) => result.ok ? json3(status, result.value) : adminError2(result.status, result.message);
|
|
6444
6464
|
var integerParam = (value) => {
|
|
6445
6465
|
if (value === null)
|
|
@@ -6540,14 +6560,14 @@ var stateAdminRoutes = (routes) => {
|
|
|
6540
6560
|
};
|
|
6541
6561
|
|
|
6542
6562
|
// ../core/dist/version.js
|
|
6543
|
-
var PACKAGE_VERSION = true ? "0.
|
|
6563
|
+
var PACKAGE_VERSION = true ? "1.0.0" : UNRELEASED_VERSION;
|
|
6544
6564
|
|
|
6545
6565
|
// ../core/dist/webhooks.js
|
|
6546
6566
|
var json4 = (status, body) => new Response(JSON.stringify(body), {
|
|
6547
6567
|
status,
|
|
6548
6568
|
headers: { "content-type": "application/json; charset=utf-8" }
|
|
6549
6569
|
});
|
|
6550
|
-
var adminError3 = (status, message) => json4(status, { error: { type: "
|
|
6570
|
+
var adminError3 = (status, message) => json4(status, { error: { type: "emulates_admin", message } });
|
|
6551
6571
|
var isRecord4 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
6552
6572
|
var parseEndpoint = (value) => {
|
|
6553
6573
|
if (!isRecord4(value) || typeof value.url !== "string")
|
|
@@ -7149,7 +7169,7 @@ var createRuntime = (options) => {
|
|
|
7149
7169
|
log(400);
|
|
7150
7170
|
return stamp(new Response(JSON.stringify({
|
|
7151
7171
|
error: {
|
|
7152
|
-
type: "
|
|
7172
|
+
type: "emulates_admin",
|
|
7153
7173
|
message: `${NAMESPACE_HEADER} must match ${NAMESPACE_PATTERN}`
|
|
7154
7174
|
}
|
|
7155
7175
|
}), { status: 400, headers: { "content-type": "application/json; charset=utf-8" } }));
|
|
@@ -7315,7 +7335,7 @@ var adminJson = (status, body) => new Response(JSON.stringify(body), {
|
|
|
7315
7335
|
status,
|
|
7316
7336
|
headers: { "content-type": "application/json; charset=utf-8" }
|
|
7317
7337
|
});
|
|
7318
|
-
var adminFail = (status, message) => adminJson(status, { error: { type: "
|
|
7338
|
+
var adminFail = (status, message) => adminJson(status, { error: { type: "emulates_admin", message } });
|
|
7319
7339
|
var isObject = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
7320
7340
|
var credentialRoutes = (registry) => ({
|
|
7321
7341
|
"GET /credentials": () => adminJson(200, {
|
|
@@ -7517,4 +7537,4 @@ export {
|
|
|
7517
7537
|
createRuntime2 as createRuntime,
|
|
7518
7538
|
AcmAPI
|
|
7519
7539
|
};
|
|
7520
|
-
//# sourceMappingURL=chunk-
|
|
7540
|
+
//# sourceMappingURL=chunk-E5LEFT72.js.map
|