Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 | 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 18x 18x 18x 1x 1x 1x 1x 17x 17x 1x 1x 198x 198x 18x 18x 18x 18x 18x 18x 18x 197x 197x 1x 1x 192x 192x 192x 192x 13x 13x 13x 13x 192x 192x 192x 1x 1x 1x 13x 13x 13x 1x 1x 1x 32x 32x 1x 1x 1x 25x 24x 24x 25x 1x 1x 25x 1x 1x 38x 38x | import { TableClient } from "@azure/data-tables";
/**
* Single access point for Azure Table Storage (research.md R2).
*
* Clients are created lazily per table and cached for the process lifetime;
* the first `ensureTable` call auto-creates the table (createTable swallows
* TableAlreadyExists). Connection string resolution: TABLES_CONNECTION_STRING
* (tests/local Azurite override) then AzureWebJobsStorage (the Function App's
* existing storage account). `UseDevelopmentStorage=true` is translated by
* the SDK itself, including allowInsecureConnection for Azurite's http
* endpoint.
*/
const clients = new Map<string, TableClient>();
const creations = new Map<string, Promise<void>>();
export function resolveTablesConnectionString(): string {
const connectionString =
process.env.TABLES_CONNECTION_STRING || process.env.AzureWebJobsStorage;
if (!connectionString) {
throw new Error(
"Table Storage is not configured: set TABLES_CONNECTION_STRING or AzureWebJobsStorage."
);
}
return connectionString;
}
export function getTableClient(tableName: string): TableClient {
let client = clients.get(tableName);
if (!client) {
client = TableClient.fromConnectionString(
resolveTablesConnectionString(),
tableName,
{ allowInsecureConnection: true }
);
clients.set(tableName, client);
}
return client;
}
/** Returns the table's client, creating the table on first use. */
export async function ensureTable(tableName: string): Promise<TableClient> {
const client = getTableClient(tableName);
let creation = creations.get(tableName);
if (!creation) {
creation = client.createTable().catch((err) => {
// Let the next caller retry instead of caching the failure forever.
creations.delete(tableName);
throw err;
});
creations.set(tableName, creation);
}
await creation;
return client;
}
/** Drops cached clients/creation state so tests can re-resolve env config. */
export function resetTablesServiceForTests(): void {
clients.clear();
creations.clear();
}
/** Encodes a structured value into a Table string property. */
export function encodeJsonProperty(value: unknown): string {
return JSON.stringify(value);
}
/** Decodes a JSON-string property; corrupt or absent values yield the fallback. */
export function decodeJsonProperty<T>(raw: string | undefined | null, fallback: T): T {
if (typeof raw !== "string" || raw.length === 0) return fallback;
try {
return JSON.parse(raw) as T;
} catch {
return fallback;
}
}
export function nowIso(): string {
return new Date().toISOString();
}
|