UNPKG

@storybooker/azure

Version:

StoryBooker Adapter for interacting with Azure services.

1 lines 8.63 kB
{"version":3,"file":"data-tables.cjs","names":["collections: string[]","#serviceClient","#tableClientGenerator","items: Document[]"],"sources":["../src/data-tables.ts"],"sourcesContent":["import type {\n TableClient,\n TableEntityResult,\n TableServiceClient,\n} from \"@azure/data-tables\";\nimport type {\n DatabaseDocumentListOptions,\n DatabaseService,\n DatabaseServiceOptions,\n StoryBookerDatabaseDocument,\n} from \"@storybooker/core/types\";\n\nexport type TableClientGenerator = (tableName: string) => TableClient;\n\nexport class AzureDataTablesDatabaseService implements DatabaseService {\n #serviceClient: TableServiceClient;\n #tableClientGenerator: TableClientGenerator;\n constructor(\n serviceClient: TableServiceClient,\n tableClientGenerator: TableClientGenerator,\n ) {\n this.#serviceClient = serviceClient;\n this.#tableClientGenerator = tableClientGenerator;\n }\n\n listCollections: DatabaseService[\"listCollections\"] = async (options) => {\n const collections: string[] = [];\n for await (const table of this.#serviceClient.listTables({\n abortSignal: options.abortSignal,\n })) {\n if (table.name) {\n collections.push(table.name);\n }\n }\n\n return collections;\n };\n\n createCollection: DatabaseService[\"createCollection\"] = async (\n collectionId,\n options,\n ) => {\n const tableName = genTableNameFromCollectionId(collectionId);\n await this.#serviceClient.createTable(tableName, {\n abortSignal: options.abortSignal,\n });\n return;\n };\n\n hasCollection: DatabaseService[\"hasCollection\"] = async (\n collectionId,\n options,\n ) => {\n try {\n const tableName = genTableNameFromCollectionId(collectionId);\n const iterator = this.#serviceClient.listTables({\n abortSignal: options.abortSignal,\n queryOptions: { filter: `TableName eq '${tableName}'` },\n });\n for await (const table of iterator) {\n if (table.name === collectionId) {\n return true;\n }\n }\n\n return false;\n } catch {\n return false;\n }\n };\n\n deleteCollection: DatabaseService[\"deleteCollection\"] = async (\n collectionId,\n options,\n ) => {\n const tableName = genTableNameFromCollectionId(collectionId);\n await this.#serviceClient.deleteTable(tableName, {\n abortSignal: options.abortSignal,\n });\n return;\n };\n\n listDocuments: DatabaseService[\"listDocuments\"] = async <\n Document extends StoryBookerDatabaseDocument,\n >(\n collectionId: string,\n listOptions: DatabaseDocumentListOptions<Document>,\n options: DatabaseServiceOptions,\n ): Promise<Document[]> => {\n const { filter, limit, select, sort } = listOptions || {};\n\n const tableName = genTableNameFromCollectionId(collectionId);\n const tableClient = this.#tableClientGenerator(tableName);\n const pageIterator = tableClient\n .listEntities({\n abortSignal: options.abortSignal,\n queryOptions: {\n filter: typeof filter === \"string\" ? filter : undefined,\n select,\n },\n })\n .byPage({ maxPageSize: limit });\n\n const items: Document[] = [];\n for await (const page of pageIterator) {\n for (const entity of page) {\n const item = entityToItem<Document>(entity);\n if (filter && typeof filter === \"function\") {\n if (filter(item)) {\n items.push(item);\n } else {\n continue;\n }\n } else {\n items.push(item);\n }\n }\n }\n\n if (sort && typeof sort === \"function\") {\n items.sort(sort);\n }\n\n return items;\n };\n\n getDocument: DatabaseService[\"getDocument\"] = async <\n Document extends StoryBookerDatabaseDocument,\n >(\n collectionId: string,\n documentId: string,\n options: DatabaseServiceOptions,\n ): Promise<Document> => {\n const tableName = genTableNameFromCollectionId(collectionId);\n const tableClient = this.#tableClientGenerator(tableName);\n const entity = await tableClient.getEntity(collectionId, documentId, {\n abortSignal: options.abortSignal,\n });\n\n return entityToItem<Document>(entity);\n };\n\n hasDocument: DatabaseService[\"hasDocument\"] = async (\n collectionId,\n documentId,\n options,\n ) => {\n try {\n return Boolean(await this.getDocument(collectionId, documentId, options));\n } catch {\n return false;\n }\n };\n\n createDocument: DatabaseService[\"createDocument\"] = async (\n collectionId,\n documentData,\n options,\n ) => {\n const tableName = genTableNameFromCollectionId(collectionId);\n const tableClient = this.#tableClientGenerator(tableName);\n await tableClient.createEntity(\n {\n ...documentData,\n partitionKey: collectionId,\n rowKey: documentData.id,\n },\n { abortSignal: options.abortSignal },\n );\n\n return;\n };\n\n deleteDocument: DatabaseService[\"deleteDocument\"] = async (\n collectionId,\n documentId,\n options,\n ) => {\n const tableName = genTableNameFromCollectionId(collectionId);\n const tableClient = this.#tableClientGenerator(tableName);\n await tableClient.deleteEntity(collectionId, documentId, {\n abortSignal: options.abortSignal,\n });\n\n return;\n };\n\n // oxlint-disable-next-line max-params\n updateDocument: DatabaseService[\"updateDocument\"] = async (\n collectionId,\n documentId,\n documentData,\n options,\n ) => {\n const tableName = genTableNameFromCollectionId(collectionId);\n const tableClient = this.#tableClientGenerator(tableName);\n await tableClient.updateEntity(\n { ...documentData, partitionKey: collectionId, rowKey: documentId },\n \"Merge\",\n { abortSignal: options.abortSignal },\n );\n\n return;\n };\n}\n\nfunction genTableNameFromCollectionId(collectionId: string): string {\n if (/^[A-Za-z][A-Za-z0-9]{2,62}$/.test(collectionId)) {\n return collectionId;\n }\n\n return collectionId.replaceAll(/\\W/g, \"\").slice(0, 63).padEnd(3, \"X\");\n}\n\nfunction entityToItem<Item extends { id: string }>(\n entity: TableEntityResult<Record<string, unknown>>,\n): Item {\n return {\n ...entity,\n id: entity.rowKey || entity.partitionKey || entity.etag,\n } as unknown as Item;\n}\n"],"mappings":"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"}