@hot-updater/azure 1.1.4 → 1.2.0-rc.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/functions/index.mjs +894 -418
- package/dist/index.cjs +73 -28
- package/dist/index.mjs +73 -28
- package/dist/init/index.cjs +40 -15
- package/dist/init/index.mjs +40 -15
- package/package.json +6 -6
package/dist/init/index.mjs
CHANGED
|
@@ -261,7 +261,15 @@ const emulatorAborted = (error) => statusOf(error) === 500 && /PostgresError\(Sq
|
|
|
261
261
|
* replaces the row it read.
|
|
262
262
|
*/
|
|
263
263
|
const createCosmosStore = ({ client, databaseId, containerId, engine, nativePageSize }) => {
|
|
264
|
-
|
|
264
|
+
let opened;
|
|
265
|
+
const open = () => opened ??= (() => {
|
|
266
|
+
const account = typeof client === "function" ? client() : client;
|
|
267
|
+
return {
|
|
268
|
+
client: account,
|
|
269
|
+
container: account.database(databaseId).container(containerId)
|
|
270
|
+
};
|
|
271
|
+
})();
|
|
272
|
+
const container = () => open().container;
|
|
265
273
|
/**
|
|
266
274
|
* The state of the items `ids` names, by id, with the rows of `rowIds`;
|
|
267
275
|
* a missing item has none.
|
|
@@ -269,7 +277,7 @@ const createCosmosStore = ({ client, databaseId, containerId, engine, nativePage
|
|
|
269
277
|
const readStates = async (ids, rowIds) => {
|
|
270
278
|
const states = /* @__PURE__ */ new Map();
|
|
271
279
|
for (const [group, projection] of [[ids.filter((id) => !rowIds.has(id)), ""], [ids.filter((id) => rowIds.has(id)), ", c.row"]]) for (let at = 0; at < group.length; at += GET_BATCH) {
|
|
272
|
-
const { resources } = await container.items.query(`SELECT c.id, c._etag AS etag, c.row._v AS v, c.expireAt${projection} FROM c WHERE c.id IN (${idList(group.slice(at, at + GET_BATCH))})`, { partitionKey: COSMOS_PARTITION }).fetchAll().catch(missingContainer);
|
|
280
|
+
const { resources } = await container().items.query(`SELECT c.id, c._etag AS etag, c.row._v AS v, c.expireAt${projection} FROM c WHERE c.id IN (${idList(group.slice(at, at + GET_BATCH))})`, { partitionKey: COSMOS_PARTITION }).fetchAll().catch(missingContainer);
|
|
273
281
|
for (const { id, etag, v, expireAt, row } of resources) states.set(id, {
|
|
274
282
|
etag,
|
|
275
283
|
v,
|
|
@@ -407,7 +415,7 @@ const createCosmosStore = ({ client, databaseId, containerId, engine, nativePage
|
|
|
407
415
|
const found = /* @__PURE__ */ new Map();
|
|
408
416
|
const ids = [...new Set(keys.map(cosmosItemId))];
|
|
409
417
|
for (let at = 0; at < ids.length; at += GET_BATCH) {
|
|
410
|
-
const { resources } = await container.items.query(`SELECT c.id, c.row FROM c WHERE c.id IN (${idList(ids.slice(at, at + GET_BATCH))})`, { partitionKey: COSMOS_PARTITION }).fetchAll().catch(missingContainer);
|
|
418
|
+
const { resources } = await container().items.query(`SELECT c.id, c.row FROM c WHERE c.id IN (${idList(ids.slice(at, at + GET_BATCH))})`, { partitionKey: COSMOS_PARTITION }).fetchAll().catch(missingContainer);
|
|
411
419
|
for (const resource of resources) found.set(resource.id, toRow(resource.row));
|
|
412
420
|
}
|
|
413
421
|
return keys.map((key) => found.get(cosmosItemId(key)) ?? null);
|
|
@@ -443,7 +451,7 @@ const createCosmosStore = ({ client, databaseId, containerId, engine, nativePage
|
|
|
443
451
|
value: after
|
|
444
452
|
});
|
|
445
453
|
}
|
|
446
|
-
const { resources } = await container.items.query({
|
|
454
|
+
const { resources } = await container().items.query({
|
|
447
455
|
query: `SELECT TOP @size c.sk, c.row FROM c WHERE ${filters.join(" AND ")} ORDER BY c.pk ${order === "asc" ? "ASC" : "DESC"}, c.sk ${order === "asc" ? "ASC" : "DESC"}`,
|
|
448
456
|
parameters
|
|
449
457
|
}, {
|
|
@@ -493,7 +501,7 @@ const createCosmosStore = ({ client, databaseId, containerId, engine, nativePage
|
|
|
493
501
|
if (planned.length > BATCH_OPERATIONS) throw new Error(`A Cosmos DB batch takes ${BATCH_OPERATIONS} operations; this write needs ${planned.length}.`);
|
|
494
502
|
let results;
|
|
495
503
|
try {
|
|
496
|
-
const response = await container.items.batch(planned.map(({ operation }) => operation), COSMOS_PARTITION);
|
|
504
|
+
const response = await container().items.batch(planned.map(({ operation }) => operation), COSMOS_PARTITION);
|
|
497
505
|
if (response.result === void 0) throw Object.assign(/* @__PURE__ */ new Error(`Cosmos DB refused the batch with status ${response.code}`), { code: response.code });
|
|
498
506
|
results = response.result;
|
|
499
507
|
} catch (error) {
|
|
@@ -527,7 +535,7 @@ const createCosmosStore = ({ client, databaseId, containerId, engine, nativePage
|
|
|
527
535
|
async deleteConsumed(keys) {
|
|
528
536
|
let remaining = [...new Set(keys.map(cosmosItemId))];
|
|
529
537
|
for (let attempt = 0; remaining.length > 0; attempt += 1) {
|
|
530
|
-
const failed = (await container.items.executeBulkOperations(remaining.map((id) => ({
|
|
538
|
+
const failed = (await container().items.executeBulkOperations(remaining.map((id) => ({
|
|
531
539
|
operationType: "Delete",
|
|
532
540
|
id,
|
|
533
541
|
partitionKey: COSMOS_PARTITION
|
|
@@ -548,8 +556,8 @@ const createCosmosStore = ({ client, databaseId, containerId, engine, nativePage
|
|
|
548
556
|
migrations: {
|
|
549
557
|
/** Creates the database and the container when they are missing. */
|
|
550
558
|
async apply() {
|
|
551
|
-
if (engine !== void 0) await assertCosmosContainerReusable(container, engine);
|
|
552
|
-
const { database } = await client.databases.createIfNotExists({ id: databaseId });
|
|
559
|
+
if (engine !== void 0) await assertCosmosContainerReusable(container(), engine);
|
|
560
|
+
const { database } = await open().client.databases.createIfNotExists({ id: databaseId });
|
|
553
561
|
const { resource } = await database.containers.createIfNotExists({
|
|
554
562
|
id: containerId,
|
|
555
563
|
partitionKey: { paths: [COSMOS_PARTITION_KEY_PATH] },
|
|
@@ -585,15 +593,15 @@ async apply() {
|
|
|
585
593
|
const adapterOf = (config) => {
|
|
586
594
|
const { databaseId = AZURE_COSMOS_V1_DATABASE, containerId = AZURE_COSMOS_V1_CONTAINER, aggregateBatching: _, ...connection } = config;
|
|
587
595
|
if (connection.consistencyLevel !== void 0 && connection.consistencyLevel !== "Strong") throw new Error(`cosmosDatabase reads with strong consistency; consistencyLevel "${String(connection.consistencyLevel)}" is weaker.`);
|
|
588
|
-
|
|
596
|
+
let client;
|
|
589
597
|
const store = createCosmosStore({
|
|
590
|
-
client,
|
|
598
|
+
client: () => client ??= new CosmosClient(connection),
|
|
591
599
|
databaseId,
|
|
592
600
|
containerId,
|
|
593
601
|
engine: currentCosmosEngine()
|
|
594
602
|
});
|
|
595
603
|
return {
|
|
596
|
-
client,
|
|
604
|
+
dispose: () => client?.dispose(),
|
|
597
605
|
adapter: createKvAdapter({ store })
|
|
598
606
|
};
|
|
599
607
|
};
|
|
@@ -605,8 +613,23 @@ const adapterOf = (config) => {
|
|
|
605
613
|
* it with the managed server's plugins.
|
|
606
614
|
*/
|
|
607
615
|
const migrateCosmosDatabase = (config, plugins = []) => {
|
|
608
|
-
const {
|
|
609
|
-
return migrateCoreSchema(adapter, "cosmosDatabase", plugins).finally(
|
|
616
|
+
const { dispose, adapter } = adapterOf(config);
|
|
617
|
+
return migrateCoreSchema(adapter, "cosmosDatabase", plugins).finally(dispose);
|
|
618
|
+
};
|
|
619
|
+
/**
|
|
620
|
+
* The resource this database reaches, without credentials, under the key
|
|
621
|
+
* `hot-updater doctor` reads to tell the database `hot-updater init` saved
|
|
622
|
+
* from another (a convention CLAUDE.md documents).
|
|
623
|
+
*/
|
|
624
|
+
const DATABASE_TARGET = Symbol.for("@hot-updater/database-target");
|
|
625
|
+
/** The account host a client reaches: its endpoint, or the connection string's. */
|
|
626
|
+
const accountHostOf = ({ endpoint, connectionString }) => {
|
|
627
|
+
const url = endpoint ?? connectionString?.match(/AccountEndpoint=([^;]+)/iu)?.[1];
|
|
628
|
+
try {
|
|
629
|
+
return url === void 0 ? void 0 : new URL(url).hostname;
|
|
630
|
+
} catch {
|
|
631
|
+
return;
|
|
632
|
+
}
|
|
610
633
|
};
|
|
611
634
|
/**
|
|
612
635
|
* Hot Updater's database in one Azure Cosmos DB for NoSQL container,
|
|
@@ -615,16 +638,18 @@ const migrateCosmosDatabase = (config, plugins = []) => {
|
|
|
615
638
|
* 20 GB.
|
|
616
639
|
*/
|
|
617
640
|
const cosmosDatabase = (config) => {
|
|
618
|
-
const {
|
|
641
|
+
const { dispose, adapter } = adapterOf(config);
|
|
642
|
+
const host = accountHostOf(config);
|
|
619
643
|
return {
|
|
620
644
|
...createEngineDatabase({
|
|
621
645
|
name: "cosmosDatabase",
|
|
622
646
|
adapter,
|
|
623
647
|
aggregateBatching: config.aggregateBatching ?? {}
|
|
624
648
|
}),
|
|
649
|
+
...host === void 0 ? {} : { [DATABASE_TARGET]: `cosmos/${host}` },
|
|
625
650
|
async dispose() {
|
|
626
651
|
await adapter.dispose?.();
|
|
627
|
-
|
|
652
|
+
dispose();
|
|
628
653
|
}
|
|
629
654
|
};
|
|
630
655
|
};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hot-updater/azure",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.2.0-rc.0",
|
|
5
5
|
"description": "React Native OTA solution for self-hosted",
|
|
6
6
|
"engines": {
|
|
7
7
|
"node": "^22.23.4 || ^24.22.1 || >=26.12.1"
|
|
@@ -42,10 +42,10 @@
|
|
|
42
42
|
"@azure/core-auth": "1.11.0",
|
|
43
43
|
"@azure/cosmos": "4.10.1",
|
|
44
44
|
"@azure/storage-blob": "12.34.0",
|
|
45
|
-
"@hot-updater/
|
|
46
|
-
"@hot-updater/
|
|
47
|
-
"@hot-updater/
|
|
48
|
-
"@hot-updater/
|
|
45
|
+
"@hot-updater/cli-tools": "1.2.0-rc.0",
|
|
46
|
+
"@hot-updater/plugin-core": "1.2.0-rc.0",
|
|
47
|
+
"@hot-updater/protocol": "1.2.0-rc.0",
|
|
48
|
+
"@hot-updater/server": "1.2.0-rc.0"
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|
|
51
51
|
"@azure/functions": "4.16.5",
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
"execa": "9.5.2",
|
|
54
54
|
"jszip": "^3.10.1",
|
|
55
55
|
"vitest": "4.1.4",
|
|
56
|
-
"@hot-updater/test-utils": "1.
|
|
56
|
+
"@hot-updater/test-utils": "1.2.0-rc.0"
|
|
57
57
|
},
|
|
58
58
|
"scripts": {
|
|
59
59
|
"build": "tsdown",
|