@burdenoff/be-sdk 2026.825.7 → 2026.825.9
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/EventQueueFactory-J2XXPYXH.js +7 -0
- package/dist/{EventQueueFactory-ELT7NDXK.js.map → EventQueueFactory-J2XXPYXH.js.map} +1 -1
- package/dist/auth/index.js +2 -2
- package/dist/cache/index.js +3 -3
- package/dist/{chunk-AW6JUXCU.js → chunk-3UQMAUX4.js} +4 -4
- package/dist/{chunk-AW6JUXCU.js.map → chunk-3UQMAUX4.js.map} +1 -1
- package/dist/{chunk-N3YN6ZII.js → chunk-5JNHVKHG.js} +3 -3
- package/dist/{chunk-N3YN6ZII.js.map → chunk-5JNHVKHG.js.map} +1 -1
- package/dist/{chunk-7UJXIX4I.js → chunk-5NT2OEDQ.js} +3 -3
- package/dist/{chunk-7UJXIX4I.js.map → chunk-5NT2OEDQ.js.map} +1 -1
- package/dist/{chunk-OQLDXOZ3.js → chunk-6GL4SLU7.js} +3 -3
- package/dist/{chunk-OQLDXOZ3.js.map → chunk-6GL4SLU7.js.map} +1 -1
- package/dist/{chunk-L3QCRJOA.js → chunk-74Y5YD3U.js} +7 -7
- package/dist/{chunk-L3QCRJOA.js.map → chunk-74Y5YD3U.js.map} +1 -1
- package/dist/{chunk-NVVWSOY7.js → chunk-AX3UF33H.js} +3 -3
- package/dist/{chunk-NVVWSOY7.js.map → chunk-AX3UF33H.js.map} +1 -1
- package/dist/{chunk-Z3O32BW6.js → chunk-CPLFP5JK.js} +3 -3
- package/dist/{chunk-Z3O32BW6.js.map → chunk-CPLFP5JK.js.map} +1 -1
- package/dist/{chunk-XD5ZK727.js → chunk-DS3YMJ4X.js} +3 -3
- package/dist/{chunk-XD5ZK727.js.map → chunk-DS3YMJ4X.js.map} +1 -1
- package/dist/{chunk-2HANKZZM.js → chunk-ELU7VL3E.js} +3 -3
- package/dist/{chunk-2HANKZZM.js.map → chunk-ELU7VL3E.js.map} +1 -1
- package/dist/{chunk-KESVEZB2.js → chunk-FA5ROGTS.js} +3 -3
- package/dist/{chunk-KESVEZB2.js.map → chunk-FA5ROGTS.js.map} +1 -1
- package/dist/{chunk-WFVLQELZ.js → chunk-FYH5IAPR.js} +6 -6
- package/dist/{chunk-WFVLQELZ.js.map → chunk-FYH5IAPR.js.map} +1 -1
- package/dist/{chunk-RXMOV3YE.js → chunk-GJWQK3IU.js} +3 -3
- package/dist/{chunk-RXMOV3YE.js.map → chunk-GJWQK3IU.js.map} +1 -1
- package/dist/{chunk-TORD32GS.js → chunk-INAZ3PKF.js} +3 -3
- package/dist/{chunk-TORD32GS.js.map → chunk-INAZ3PKF.js.map} +1 -1
- package/dist/{chunk-UJG32VIP.js → chunk-IUJSIXMM.js} +3 -3
- package/dist/{chunk-UJG32VIP.js.map → chunk-IUJSIXMM.js.map} +1 -1
- package/dist/{chunk-VI4VSNTI.js → chunk-KJOSPVB2.js} +3 -3
- package/dist/{chunk-VI4VSNTI.js.map → chunk-KJOSPVB2.js.map} +1 -1
- package/dist/{chunk-UM32ZA3G.js → chunk-KMNSVLDS.js} +5 -5
- package/dist/{chunk-UM32ZA3G.js.map → chunk-KMNSVLDS.js.map} +1 -1
- package/dist/{chunk-VBXPFYZ5.js → chunk-KO2ZXZ7W.js} +3 -3
- package/dist/{chunk-VBXPFYZ5.js.map → chunk-KO2ZXZ7W.js.map} +1 -1
- package/dist/{chunk-VDYBUTFI.js → chunk-KW55Q6TA.js} +5 -5
- package/dist/{chunk-VDYBUTFI.js.map → chunk-KW55Q6TA.js.map} +1 -1
- package/dist/{chunk-OCYZEBOL.js → chunk-L5TDUAFN.js} +3 -3
- package/dist/{chunk-OCYZEBOL.js.map → chunk-L5TDUAFN.js.map} +1 -1
- package/dist/{chunk-S7LWYERE.js → chunk-LKCBI6B2.js} +3 -3
- package/dist/{chunk-S7LWYERE.js.map → chunk-LKCBI6B2.js.map} +1 -1
- package/dist/{chunk-LGTQ26Z2.js → chunk-MEA4BQNA.js} +3 -3
- package/dist/{chunk-LGTQ26Z2.js.map → chunk-MEA4BQNA.js.map} +1 -1
- package/dist/{chunk-QLVKMWFA.js → chunk-MWPYA2HD.js} +3 -3
- package/dist/{chunk-QLVKMWFA.js.map → chunk-MWPYA2HD.js.map} +1 -1
- package/dist/{chunk-XWVP4MC6.js → chunk-MZCBEJ67.js} +3 -3
- package/dist/{chunk-XWVP4MC6.js.map → chunk-MZCBEJ67.js.map} +1 -1
- package/dist/{chunk-URDYOM2L.js → chunk-QJN4K7LD.js} +4 -4
- package/dist/{chunk-URDYOM2L.js.map → chunk-QJN4K7LD.js.map} +1 -1
- package/dist/{chunk-CBZNP6RF.js → chunk-RU266375.js} +48 -7
- package/dist/chunk-RU266375.js.map +1 -0
- package/dist/{chunk-A6DGEZJ4.js → chunk-UD5PPGVU.js} +3 -3
- package/dist/{chunk-A6DGEZJ4.js.map → chunk-UD5PPGVU.js.map} +1 -1
- package/dist/{chunk-JNJSSBKO.js → chunk-UFXHLQ2T.js} +5 -5
- package/dist/{chunk-JNJSSBKO.js.map → chunk-UFXHLQ2T.js.map} +1 -1
- package/dist/{chunk-F5SGJ6VS.js → chunk-UNASM5VJ.js} +3 -3
- package/dist/{chunk-F5SGJ6VS.js.map → chunk-UNASM5VJ.js.map} +1 -1
- package/dist/{chunk-5LXDPGDH.js → chunk-VAT66FJA.js} +3 -3
- package/dist/{chunk-5LXDPGDH.js.map → chunk-VAT66FJA.js.map} +1 -1
- package/dist/{chunk-7E76FL2C.js → chunk-XCQN6GH7.js} +18 -10
- package/dist/chunk-XCQN6GH7.js.map +1 -0
- package/dist/{chunk-4X5WL6I3.js → chunk-XYWLCNJH.js} +5 -5
- package/dist/{chunk-4X5WL6I3.js.map → chunk-XYWLCNJH.js.map} +1 -1
- package/dist/{chunk-MX4AHK3E.js → chunk-YAQ7GNAC.js} +6 -6
- package/dist/{chunk-MX4AHK3E.js.map → chunk-YAQ7GNAC.js.map} +1 -1
- package/dist/{chunk-RNR45JQH.js → chunk-YK7C5DU6.js} +3 -3
- package/dist/{chunk-RNR45JQH.js.map → chunk-YK7C5DU6.js.map} +1 -1
- package/dist/{chunk-IC7YDBGE.js → chunk-YNDJQRI3.js} +3 -3
- package/dist/{chunk-IC7YDBGE.js.map → chunk-YNDJQRI3.js.map} +1 -1
- package/dist/{chunk-WCJIZR5Q.js → chunk-Z5BURBFZ.js} +3 -3
- package/dist/{chunk-WCJIZR5Q.js.map → chunk-Z5BURBFZ.js.map} +1 -1
- package/dist/client/internal-client.js +2 -2
- package/dist/database/index.js +2 -2
- package/dist/event-queue/index.js +6 -6
- package/dist/export/index.js +5 -5
- package/dist/feature-flags/index.js +2 -2
- package/dist/gateway/index.js +4 -4
- package/dist/gateway/security/index.js +2 -2
- package/dist/graph/index.js +8 -8
- package/dist/graphql/index.js +4 -4
- package/dist/graphql/services/index.js +2 -2
- package/dist/i18n/index.js +2 -2
- package/dist/{index-BtpoFSLa.d.ts → index-BLWIKXin.d.ts} +1 -1
- package/dist/{index-C0qWSC_Q.d.ts → index-hWpL68Vx.d.ts} +4 -2
- package/dist/index.d.ts +3 -3
- package/dist/index.js +44 -44
- package/dist/init/index.js +6 -6
- package/dist/instrumentation/index.d.ts +2 -2
- package/dist/instrumentation/index.js +2 -2
- package/dist/layer/index.js +2 -2
- package/dist/lifecycle/index.js +2 -2
- package/dist/logger/index.d.ts +1 -1
- package/dist/logger/index.js +1 -1
- package/dist/middleware/index.js +2 -2
- package/dist/notifications/index.js +2 -2
- package/dist/observability/index.js +2 -2
- package/dist/pino-logger-GJ2CYLD5.js +5 -0
- package/dist/{pino-logger-XF275Y5C.js.map → pino-logger-GJ2CYLD5.js.map} +1 -1
- package/dist/platform/index.js +2 -2
- package/dist/prisma/index.js +8 -8
- package/dist/rbac/index.js +2 -2
- package/dist/resource-caps/index.js +2 -2
- package/dist/server/index.js +6 -6
- package/dist/sharding/index.js +1 -1
- package/dist/sharing/index.js +2 -2
- package/dist/telemetry/index.d.ts +3 -3
- package/dist/telemetry/index.js +5 -5
- package/dist/temporal/index.js +2 -2
- package/dist/tracker/index.js +4 -4
- package/dist/workspace-guard-7PEZT3ZJ.js +5 -0
- package/dist/{workspace-guard-4BUG4ZP2.js.map → workspace-guard-7PEZT3ZJ.js.map} +1 -1
- package/package.json +1 -1
- package/dist/EventQueueFactory-ELT7NDXK.js +0 -7
- package/dist/chunk-7E76FL2C.js.map +0 -1
- package/dist/chunk-CBZNP6RF.js.map +0 -1
- package/dist/pino-logger-XF275Y5C.js +0 -5
- package/dist/workspace-guard-4BUG4ZP2.js +0 -5
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/export/index.ts","../src/export/base-exporter.ts","../src/export/pagination.ts","../src/export/csv.ts","../src/export/gateway-client.ts"],"names":["BaseModuleExporter","moduleKey","displayName","description","defaultExcludeFields","supportedProducts","modelName","filterFields","entity","excludeFields","fieldsToExclude","length","filtered","record","key","value","Object","entries","includes","filterFieldsMany","entities","map","paginate","queryFn","page","pageSize","skip","take","items","total","data","hasMore","nextCursor","String","undefined","fetchAll","fetchBatch","batchSize","allItems","cursor","batch","push","lastItem","id","transformForExport","validateOptions","options","validFormats","format","Error","join","getSupportedFormats","getMetadata","supportedFormats","PaginationService","params","start","end","paginatedItems","slice","totalCount","pageInfo","hasNextPage","hasPreviousPage","startCursor","endCursor","Math","min","calculatePagination","totalPages","ceil","startIndex","endIndex","currentPage","paginatedQuery","fetchFn","limit","initialCursor","totalYielded","item","collectPaginatedQuery","createPrismaFetchFn","_batchSize","calculateOffset","max","parseCursor","decoded","Buffer","from","toString","JSON","parse","createCursor","stringify","FORMULA_PREFIX_RE","sanitizeCSVCell","test","convertToCSV","delimiter","includeHeaders","flattenFields","maxFlattenDepth","flattenObject","obj","prefix","depth","result","newKey","Date","toISOString","Array","isArray","assign","flattenedRecords","allKeys","Set","keys","add","headers","sort","a","b","localeCompare","escapeCSV","sanitizedValue","replace","lines","row","header","parseCSV","csv","hasHeaders","split","filter","line","trim","parseLine","values","current","inQuotes","i","char","nextChar","dataLines","firstLine","firstRow","_","forEach","csvToJSON","pretty","parseOptions","getCSVHeaders","collectKeys","fullKey","estimateCSVSize","sampleSize","sample","sampleCSV","averageRowSize","headerSize","CREATE_EXPORT_JOB_MUTATION","triggerExportJob","serviceName","layer","actorId","actorType","workspaceId","name","entityTypes","includeMetadata","dateRangeStart","dateRangeEnd","client","GatewayClient","input","response","internalQuery","query","variables","job","createExportJob"],"mappings":"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","file":"chunk-LGTQ26Z2.js","sourcesContent":["/**\n * Export Module\n *\n * Provides common utilities for data export operations across all Burdenoff microservices.\n * Includes pagination services, base exporter classes, CSV utilities, and type definitions.\n *\n * @module export\n *\n * @example\n * ```typescript\n * // Import from the export module\n * import {\n * BaseModuleExporter,\n * PaginationService,\n * convertToCSV,\n * } from '@burdenoff/be-sdk/export';\n *\n * // Create a custom exporter\n * class UserExporter extends BaseModuleExporter<User> {\n * moduleKey = 'users';\n * displayName = 'Users';\n *\n * async export(options: ExportOptions): Promise<ExportResult> {\n * const data = await this.fetchAll(\n * (cursor) => db.user.findMany({\n * where: cursor ? { id: { gt: cursor } } : {},\n * take: 100,\n * })\n * );\n *\n * const csv = convertToCSV(data);\n * return { data, format: 'csv' };\n * }\n * }\n *\n * // Use pagination utilities\n * const result = PaginationService.paginate(items, { page: 1, pageSize: 20 });\n * ```\n */\n\n// ============================================================================\n// Type Exports\n// ============================================================================\n\nexport type {\n // Export format types\n ExportFormat,\n ExportFormatEnum,\n\n // Configuration types\n ExportConfig,\n ExportOptions,\n\n // Job types\n ExportJobStatus,\n ExportJob,\n ExportProgress,\n ExportResult,\n\n // Fetch types\n ExportFetchOptions,\n ExportFetchResult,\n\n // Pagination types\n PaginationParams,\n PaginatedResult,\n PaginatedQueryOptions,\n PaginateResult,\n PaginateQueryFn,\n\n // Module interface\n ExportableModule,\n\n // CSV types\n CSVConversionOptions,\n} from './types.js';\n\n// ============================================================================\n// Class Exports\n// ============================================================================\n\nexport { BaseModuleExporter } from './base-exporter.js';\nexport { PaginationService } from './pagination.js';\n\n// ============================================================================\n// Function Exports\n// ============================================================================\n\nexport { convertToCSV, parseCSV, csvToJSON, getCSVHeaders, estimateCSVSize } from './csv.js';\n\n// ============================================================================\n// Gateway Helper Exports\n// ============================================================================\n\nexport { triggerExportJob } from './gateway-client.js';\nexport type { TriggerExportJobParams, ExportJobResult, ExportActorType, ExportFormatGql } from './gateway-client.js';\n","/**\n * Base Module Exporter\n *\n * Abstract base class for module exporters across all Burdenoff microservices.\n * Provides common functionality for exporting data from different modules.\n *\n * @module export/base-exporter\n *\n * @example\n * ```typescript\n * import { BaseModuleExporter } from '@burdenoff/be-sdk/export';\n *\n * class UserExporter extends BaseModuleExporter<User> {\n * moduleKey = 'users';\n * displayName = 'Users';\n * description = 'Export user data';\n *\n * async export(options: ExportOptions): Promise<ExportResult> {\n * // Implementation\n * }\n * }\n * ```\n */\n\nimport type { ExportOptions, ExportResult, PaginateQueryFn, PaginateResult } from './types.js';\n\n/**\n * Abstract base class for module exporters\n *\n * Provides common functionality that all module exporters can inherit:\n * - Field filtering\n * - Pagination helpers\n * - Module metadata\n *\n * @typeParam T - The type of entity this exporter handles\n */\nexport abstract class BaseModuleExporter<T = unknown> {\n /** Unique key identifying this module (e.g., 'users', 'tags', 'orders') */\n moduleKey?: string;\n\n /** Human-readable display name for the module */\n displayName?: string;\n\n /** Description of what this module exports */\n description?: string;\n\n /** Default fields to exclude from export (e.g., sensitive data) */\n defaultExcludeFields?: string[];\n\n /** List of product IDs this exporter supports */\n supportedProducts?: string[];\n\n /** Model name for database operations */\n protected modelName?: string;\n\n /**\n * Export data from this module\n *\n * Subclasses should implement this method to perform the actual export.\n * The method is optional to allow for gradual implementation.\n *\n * @param options - Export options including format, filters, and pagination\n * @returns Export result with data or download URL\n */\n export?(options: ExportOptions): Promise<ExportResult>;\n\n /**\n * Filter fields from an entity based on exclude list\n *\n * Use this to remove sensitive or unnecessary fields from exported data.\n *\n * @param entity - Entity to filter\n * @param excludeFields - Fields to exclude (uses defaultExcludeFields if not provided)\n * @returns Filtered entity as a plain object\n *\n * @example\n * ```typescript\n * const user = { id: '1', name: 'John', password: 'secret', ssn: '123' };\n * const filtered = this.filterFields(user, ['password', 'ssn']);\n * // Result: { id: '1', name: 'John' }\n * ```\n */\n protected filterFields(entity: T | Record<string, unknown>, excludeFields?: string[]): Record<string, unknown> {\n const fieldsToExclude = excludeFields || this.defaultExcludeFields || [];\n\n if (fieldsToExclude.length === 0) {\n return entity as Record<string, unknown>;\n }\n\n const filtered: Record<string, unknown> = {};\n const record = entity as Record<string, unknown>;\n\n for (const [key, value] of Object.entries(record)) {\n if (!fieldsToExclude.includes(key)) {\n filtered[key] = value;\n }\n }\n\n return filtered;\n }\n\n /**\n * Filter multiple entities\n *\n * @param entities - Array of entities to filter\n * @param excludeFields - Fields to exclude\n * @returns Array of filtered entities\n */\n protected filterFieldsMany(\n entities: (T | Record<string, unknown>)[],\n excludeFields?: string[]\n ): Record<string, unknown>[] {\n return entities.map((entity) => this.filterFields(entity, excludeFields));\n }\n\n /**\n * Paginate helper for database queries\n *\n * Use this to implement paginated data fetching in your export method.\n *\n * @param queryFn - Function that executes the paginated query\n * @param page - Page number (1-indexed)\n * @param pageSize - Number of items per page\n * @returns Paginated result with data and metadata\n *\n * @example\n * ```typescript\n * const result = await this.paginate(\n * async ({ skip, take }) => {\n * const items = await db.user.findMany({ skip, take });\n * const total = await db.user.count();\n * return { items, total };\n * },\n * 1,\n * 100\n * );\n * ```\n */\n protected async paginate(\n queryFn: PaginateQueryFn<T>,\n page: number = 1,\n pageSize: number = 100\n ): Promise<PaginateResult<T>> {\n const skip = (page - 1) * pageSize;\n const take = pageSize;\n\n const { items, total } = await queryFn({ skip, take });\n\n return {\n data: items,\n total,\n hasMore: skip + items.length < total,\n nextCursor: items.length > 0 && skip + items.length < total ? String(page + 1) : undefined,\n };\n }\n\n /**\n * Fetch all data using cursor-based pagination\n *\n * Use this for exporting large datasets efficiently.\n *\n * @param fetchBatch - Function to fetch a batch of data\n * @param batchSize - Number of items per batch\n * @returns All fetched items\n *\n * @example\n * ```typescript\n * const allUsers = await this.fetchAll(\n * async (cursor) => db.user.findMany({\n * where: cursor ? { id: { gt: cursor } } : undefined,\n * orderBy: { id: 'asc' },\n * take: 100,\n * }),\n * 100\n * );\n * ```\n */\n protected async fetchAll(\n fetchBatch: (cursor?: string) => Promise<(T & { id: string })[]>,\n batchSize: number = 100\n ): Promise<T[]> {\n const allItems: T[] = [];\n let cursor: string | undefined;\n\n while (true) {\n const batch = await fetchBatch(cursor);\n\n if (batch.length === 0) {\n break;\n }\n\n allItems.push(...batch);\n\n // Get cursor from last item\n const lastItem = batch[batch.length - 1];\n if (lastItem) {\n cursor = lastItem.id;\n }\n\n // If we got fewer items than batch size, we're done\n if (batch.length < batchSize) {\n break;\n }\n }\n\n return allItems;\n }\n\n /**\n * Transform entity for export\n *\n * Override this method to customize how entities are transformed before export.\n * Default implementation returns the entity as-is after field filtering.\n *\n * @param entity - Entity to transform\n * @param excludeFields - Fields to exclude\n * @returns Transformed entity\n */\n protected transformForExport(entity: T, excludeFields?: string[]): Record<string, unknown> {\n return this.filterFields(entity, excludeFields);\n }\n\n /**\n * Validate export options\n *\n * Override this to add custom validation for export options.\n *\n * @param options - Export options to validate\n * @throws Error if options are invalid\n */\n protected validateOptions(options: ExportOptions): void {\n const validFormats = ['csv', 'json', 'xlsx'];\n if (!validFormats.includes(options.format)) {\n throw new Error(`Invalid export format: ${options.format}. Valid formats: ${validFormats.join(', ')}`);\n }\n }\n\n /**\n * Get supported export formats\n *\n * @returns Array of supported format strings\n */\n getSupportedFormats(): string[] {\n return ['csv', 'json', 'xlsx'];\n }\n\n /**\n * Get module metadata\n *\n * @returns Module metadata object\n */\n getMetadata(): {\n moduleKey?: string;\n displayName?: string;\n description?: string;\n supportedProducts?: string[];\n supportedFormats: string[];\n } {\n return {\n moduleKey: this.moduleKey,\n displayName: this.displayName,\n description: this.description,\n supportedProducts: this.supportedProducts,\n supportedFormats: this.getSupportedFormats(),\n };\n }\n}\n","/**\n * Pagination Service\n *\n * Provides pagination utilities for export operations across all Burdenoff microservices.\n * Supports both offset-based and cursor-based pagination strategies.\n *\n * @module export/pagination\n *\n * @example\n * ```typescript\n * import { PaginationService } from '@burdenoff/be-sdk/export';\n *\n * // Offset-based pagination\n * const result = PaginationService.paginate(items, { page: 2, pageSize: 20 });\n *\n * // Cursor-based pagination with async generator\n * for await (const item of PaginationService.paginatedQuery(fetchFn, { limit: 100 })) {\n * console.log(item);\n * }\n * ```\n */\n\nimport type { PaginatedQueryOptions, PaginatedResult, PaginationParams } from './types.js';\n\n/**\n * Service providing pagination utilities for export and data fetching operations\n */\nexport class PaginationService {\n /**\n * Paginate an array of items using offset-based pagination\n *\n * @param items - Array of items to paginate\n * @param params - Pagination parameters\n * @returns Paginated result with items and metadata\n *\n * @example\n * ```typescript\n * const allUsers = await db.user.findMany();\n * const page = PaginationService.paginate(allUsers, { page: 1, pageSize: 10 });\n * console.log(page.items); // First 10 users\n * console.log(page.pageInfo.hasNextPage); // true if more pages exist\n * ```\n */\n static paginate<T>(items: T[], params: PaginationParams): PaginatedResult<T> {\n const page = params.page ?? 1;\n const pageSize = params.pageSize ?? 20;\n const start = (page - 1) * pageSize;\n const end = start + pageSize;\n\n const paginatedItems = items.slice(start, end);\n\n return {\n items: paginatedItems,\n totalCount: items.length,\n pageInfo: {\n hasNextPage: end < items.length,\n hasPreviousPage: page > 1,\n startCursor: paginatedItems.length > 0 ? String(start) : undefined,\n endCursor: paginatedItems.length > 0 ? String(Math.min(end, items.length) - 1) : undefined,\n },\n };\n }\n\n /**\n * Calculate pagination metadata without slicing data\n *\n * @param totalCount - Total number of items\n * @param page - Current page number (1-indexed)\n * @param pageSize - Items per page\n * @returns Pagination metadata\n *\n * @example\n * ```typescript\n * const meta = PaginationService.calculatePagination(150, 3, 20);\n * // meta.hasNextPage = true (page 4 exists)\n * // meta.hasPreviousPage = true (page 2 exists)\n * // meta.totalPages = 8\n * ```\n */\n static calculatePagination(\n totalCount: number,\n page: number,\n pageSize: number\n ): {\n hasNextPage: boolean;\n hasPreviousPage: boolean;\n totalPages: number;\n currentPage: number;\n pageSize: number;\n startIndex: number;\n endIndex: number;\n } {\n const totalPages = Math.ceil(totalCount / pageSize);\n const startIndex = (page - 1) * pageSize;\n const endIndex = Math.min(startIndex + pageSize - 1, totalCount - 1);\n\n return {\n hasNextPage: page < totalPages,\n hasPreviousPage: page > 1,\n totalPages,\n currentPage: page,\n pageSize,\n startIndex,\n endIndex,\n };\n }\n\n /**\n * Async generator for paginated database queries using cursor-based pagination\n *\n * This is ideal for processing large datasets without loading everything into memory.\n * The generator yields items one at a time, fetching new batches as needed.\n *\n * @param fetchFn - Function to fetch data given a cursor\n * @param options - Pagination options\n * @returns Async generator of items\n *\n * @example\n * ```typescript\n * // Define fetch function that queries the database\n * const fetchUsers = async (cursor?: string) => {\n * return db.user.findMany({\n * where: cursor ? { id: { gt: cursor } } : undefined,\n * orderBy: { id: 'asc' },\n * take: 100,\n * });\n * };\n *\n * // Process all users without loading all into memory\n * for await (const user of PaginationService.paginatedQuery(fetchUsers)) {\n * await processUser(user);\n * }\n * ```\n */\n static async *paginatedQuery<T extends { id: string }>(\n fetchFn: (cursor?: string) => Promise<T[]>,\n options: PaginatedQueryOptions = {}\n ): AsyncGenerator<T, void, unknown> {\n const { limit, initialCursor } = options;\n let cursor = initialCursor;\n let hasMore = true;\n let totalYielded = 0;\n\n while (hasMore) {\n const items = await fetchFn(cursor);\n\n if (items.length === 0) {\n break;\n }\n\n for (const item of items) {\n yield item;\n totalYielded++;\n\n if (limit && totalYielded >= limit) {\n return;\n }\n }\n\n // Get next cursor from last item\n const lastItem = items[items.length - 1];\n if (lastItem) {\n cursor = lastItem.id;\n }\n\n // If we got fewer items than expected batch size, we're done\n // Note: This assumes fetchFn respects a consistent batch size internally\n hasMore = items.length > 0;\n }\n }\n\n /**\n * Collect all items from a paginated query into an array\n *\n * @param fetchFn - Function to fetch data given a cursor\n * @param options - Pagination options\n * @returns Array of all items\n *\n * @example\n * ```typescript\n * const allUsers = await PaginationService.collectPaginatedQuery(fetchUsers, { limit: 1000 });\n * ```\n */\n static async collectPaginatedQuery<T extends { id: string }>(\n fetchFn: (cursor?: string) => Promise<T[]>,\n options: PaginatedQueryOptions = {}\n ): Promise<T[]> {\n const items: T[] = [];\n\n for await (const item of PaginationService.paginatedQuery(fetchFn, options)) {\n items.push(item);\n }\n\n return items;\n }\n\n /**\n * Create a cursor-based paginated fetch function from a Prisma-style query\n *\n * @param queryFn - Prisma-style query function\n * @param batchSize - Number of items to fetch per batch\n * @returns Fetch function compatible with paginatedQuery\n *\n * @example\n * ```typescript\n * const fetchFn = PaginationService.createPrismaFetchFn(\n * (cursor) => db.user.findMany({\n * where: { isActive: true, ...(cursor ? { id: { gt: cursor } } : {}) },\n * orderBy: { id: 'asc' },\n * take: 100,\n * }),\n * 100\n * );\n *\n * for await (const user of PaginationService.paginatedQuery(fetchFn)) {\n * console.log(user);\n * }\n * ```\n */\n static createPrismaFetchFn<T extends { id: string }>(\n queryFn: (cursor?: string) => Promise<T[]>,\n _batchSize: number = 100\n ): (cursor?: string) => Promise<T[]> {\n return queryFn;\n }\n\n /**\n * Calculate offset for skip-based pagination\n *\n * @param page - Page number (1-indexed)\n * @param pageSize - Items per page\n * @returns Offset value for skip\n */\n static calculateOffset(page: number, pageSize: number): number {\n return (Math.max(1, page) - 1) * pageSize;\n }\n\n /**\n * Parse cursor string to extract pagination state\n *\n * @param cursor - Base64-encoded cursor string\n * @returns Decoded cursor data or null if invalid\n */\n static parseCursor<T = Record<string, unknown>>(cursor: string): T | null {\n try {\n const decoded = Buffer.from(cursor, 'base64').toString('utf-8');\n return JSON.parse(decoded) as T;\n } catch {\n return null;\n }\n }\n\n /**\n * Create cursor string from pagination state\n *\n * @param data - Data to encode in cursor\n * @returns Base64-encoded cursor string\n */\n static createCursor(data: Record<string, unknown>): string {\n return Buffer.from(JSON.stringify(data)).toString('base64');\n }\n}\n","/**\n * CSV Utilities\n *\n * Utilities for converting data to CSV format for export operations.\n *\n * @module export/csv\n *\n * @example\n * ```typescript\n * import { convertToCSV, parseCSV } from '@burdenoff/be-sdk/export';\n *\n * const csv = convertToCSV(users, { includeHeaders: true });\n * console.log(csv);\n * ```\n */\n\nimport type { CSVConversionOptions } from './types.js';\n\nconst FORMULA_PREFIX_RE = /^[=+\\-@]/;\n\nexport function sanitizeCSVCell(value: string): string {\n return FORMULA_PREFIX_RE.test(value) ? `'${value}` : value;\n}\n\n/**\n * Convert an array of objects to CSV format\n *\n * Handles nested objects by flattening them with dot notation.\n * Arrays are JSON stringified.\n * Dates are converted to ISO strings.\n *\n * @param data - Array of objects to convert\n * @param options - CSV conversion options\n * @returns CSV string\n *\n * @example\n * ```typescript\n * const users = [\n * { id: 1, name: 'John', address: { city: 'NYC' } },\n * { id: 2, name: 'Jane', address: { city: 'LA' } },\n * ];\n *\n * const csv = convertToCSV(users);\n * // Output:\n * // id,name,address.city\n * // 1,John,NYC\n * // 2,Jane,LA\n * ```\n */\nexport function convertToCSV(data: unknown[], options: CSVConversionOptions = {}): string {\n const { delimiter = ',', includeHeaders = true, flattenFields = true, maxFlattenDepth = 3 } = options;\n\n if (data.length === 0) {\n return '';\n }\n\n // Flatten objects and get all keys\n const flattenObject = (obj: unknown, prefix = '', depth = 0): Record<string, string> => {\n const result: Record<string, string> = {};\n\n if (obj === null || obj === undefined) {\n return result;\n }\n\n if (typeof obj !== 'object') {\n return { [prefix || 'value']: String(obj) };\n }\n\n for (const [key, value] of Object.entries(obj as Record<string, unknown>)) {\n const newKey = prefix ? `${prefix}.${key}` : key;\n\n if (value === null || value === undefined) {\n result[newKey] = '';\n } else if (value instanceof Date) {\n result[newKey] = value.toISOString();\n } else if (Array.isArray(value)) {\n result[newKey] = JSON.stringify(value);\n } else if (typeof value === 'object' && flattenFields && depth < maxFlattenDepth) {\n Object.assign(result, flattenObject(value, newKey, depth + 1));\n } else if (typeof value === 'object') {\n result[newKey] = JSON.stringify(value);\n } else {\n result[newKey] = String(value);\n }\n }\n\n return result;\n };\n\n // Flatten all records and collect all keys\n const flattenedRecords = data.map((item) => flattenObject(item));\n const allKeys = new Set<string>();\n for (const record of flattenedRecords) {\n for (const key of Object.keys(record)) {\n allKeys.add(key);\n }\n }\n\n const headers = Array.from(allKeys).sort((a, b) => a.localeCompare(b));\n\n // Escape CSV values\n const escapeCSV = (value: string): string => {\n const sanitizedValue = sanitizeCSVCell(value);\n\n if (\n sanitizedValue.includes(delimiter) ||\n sanitizedValue.includes('\"') ||\n sanitizedValue.includes('\\n') ||\n sanitizedValue.includes('\\r')\n ) {\n return `\"${sanitizedValue.replace(/\"/g, '\"\"')}\"`;\n }\n return sanitizedValue;\n };\n\n // Build CSV\n const lines: string[] = [];\n\n if (includeHeaders) {\n lines.push(headers.map(escapeCSV).join(delimiter));\n }\n\n for (const record of flattenedRecords) {\n const row = headers.map((header) => escapeCSV(record[header] || ''));\n lines.push(row.join(delimiter));\n }\n\n return lines.join('\\n');\n}\n\n/**\n * Parse a CSV string into an array of objects\n *\n * @param csv - CSV string to parse\n * @param options - Parse options\n * @returns Array of parsed objects\n *\n * @example\n * ```typescript\n * const csv = 'id,name\\n1,John\\n2,Jane';\n * const data = parseCSV(csv);\n * // [{ id: '1', name: 'John' }, { id: '2', name: 'Jane' }]\n * ```\n */\nexport function parseCSV(\n csv: string,\n options: { delimiter?: string; hasHeaders?: boolean } = {}\n): Record<string, string>[] {\n const { delimiter = ',', hasHeaders = true } = options;\n\n const lines = csv.split(/\\r?\\n/).filter((line) => line.trim());\n\n if (lines.length === 0) {\n return [];\n }\n\n // Parse a single CSV line, handling quoted values\n const parseLine = (line: string): string[] => {\n const values: string[] = [];\n let current = '';\n let inQuotes = false;\n\n let i = 0;\n while (i < line.length) {\n const char = line[i];\n const nextChar = line[i + 1];\n\n if (char === '\"' && inQuotes && nextChar === '\"') {\n current += '\"';\n i += 2; // Skip next quote\n } else if (char === '\"') {\n inQuotes = !inQuotes;\n i++;\n } else if (char === delimiter && !inQuotes) {\n values.push(current);\n current = '';\n i++;\n } else {\n current += char;\n i++;\n }\n }\n\n values.push(current);\n return values;\n };\n\n let headers: string[];\n let dataLines: string[];\n\n // We've already checked that lines.length > 0, so lines[0] is guaranteed to exist\n const firstLine = lines[0] as string;\n\n if (hasHeaders) {\n headers = parseLine(firstLine);\n dataLines = lines.slice(1);\n } else {\n // Generate numeric headers if no header row\n const firstRow = parseLine(firstLine);\n headers = firstRow.map((_, i) => `col${i}`);\n dataLines = lines;\n }\n\n return dataLines.map((line) => {\n const values = parseLine(line);\n const obj: Record<string, string> = {};\n\n headers.forEach((header, i) => {\n obj[header] = values[i] || '';\n });\n\n return obj;\n });\n}\n\n/**\n * Convert CSV to JSON string\n *\n * @param csv - CSV string\n * @param options - Parse options\n * @returns JSON string\n */\nexport function csvToJSON(\n csv: string,\n options: { delimiter?: string; hasHeaders?: boolean; pretty?: boolean } = {}\n): string {\n const { pretty = false, ...parseOptions } = options;\n const data = parseCSV(csv, parseOptions);\n return pretty ? JSON.stringify(data, null, 2) : JSON.stringify(data);\n}\n\n/**\n * Get CSV headers from data\n *\n * @param data - Array of objects\n * @param flattenFields - Whether to flatten nested objects\n * @returns Array of header strings\n */\nexport function getCSVHeaders(data: unknown[], flattenFields: boolean = true): string[] {\n if (data.length === 0) {\n return [];\n }\n\n const collectKeys = (obj: unknown, prefix = '', depth = 0): string[] => {\n const keys: string[] = [];\n\n if (obj === null || obj === undefined || typeof obj !== 'object') {\n return prefix ? [prefix] : [];\n }\n\n for (const [key, value] of Object.entries(obj as Record<string, unknown>)) {\n const fullKey = prefix ? `${prefix}.${key}` : key;\n\n if (\n value !== null &&\n typeof value === 'object' &&\n !Array.isArray(value) &&\n !(value instanceof Date) &&\n flattenFields &&\n depth < 3\n ) {\n keys.push(...collectKeys(value, fullKey, depth + 1));\n } else {\n keys.push(fullKey);\n }\n }\n\n return keys;\n };\n\n const allKeys = new Set<string>();\n for (const item of data) {\n for (const key of collectKeys(item)) {\n allKeys.add(key);\n }\n }\n\n return Array.from(allKeys).sort((a, b) => a.localeCompare(b));\n}\n\n/**\n * Estimate CSV file size for a dataset\n *\n * @param data - Array of objects\n * @param sampleSize - Number of records to sample for estimation\n * @returns Estimated size in bytes\n */\nexport function estimateCSVSize(data: unknown[], sampleSize: number = 100): number {\n if (data.length === 0) {\n return 0;\n }\n\n // Take a sample to estimate average row size\n const sample = data.slice(0, Math.min(sampleSize, data.length));\n const sampleCSV = convertToCSV(sample);\n const averageRowSize = sampleCSV.length / sample.length;\n\n // Estimate total size (headers + data rows)\n const headers = getCSVHeaders(data);\n const headerSize = headers.join(',').length + 1; // +1 for newline\n\n return Math.ceil(headerSize + averageRowSize * data.length);\n}\n","/**\n * Export Gateway Helper\n *\n * Centralised wrapper around the workspace internal gateway's\n * `createExportJob` mutation, used by per-svc convenience resolvers\n * (e.g. `createTagsExportJob`, `createGroupsExportJob`).\n *\n * Replaces the duplicated `src/clients/export-gateway.ts` files that\n * existed in 19+ workspace svcs.\n *\n * @module export/gateway-client\n *\n * @example\n * ```typescript\n * import { triggerExportJob } from '@burdenoff/be-sdk/export';\n *\n * const result = await triggerExportJob({\n * serviceName: 'wspace-tags-svc',\n * workspaceId: ctx.workspaceId,\n * name: input.name,\n * entityTypes: ['tags', 'vocabularies'],\n * format: input.format,\n * actorId: ctx.actorId,\n * actorType: ctx.actorType,\n * });\n * ```\n */\n\nimport { GatewayClient } from '../gateway/index.js';\nimport type { ServiceLayer } from '../types/layer.js';\n\nconst CREATE_EXPORT_JOB_MUTATION = `mutation CreateExportJob($input: CreateExportJobInput!) {\n createExportJob(input: $input) {\n id\n status\n workspaceId\n entityTypes\n format\n createdAt\n }\n}`;\n\nexport type ExportActorType = 'user' | 'app' | 'service' | 'super_admin';\nexport type ExportFormatGql = 'JSON' | 'CSV';\n\nexport interface TriggerExportJobParams {\n /** Caller service name, used by gateway client telemetry/auth */\n serviceName: string;\n /** Layer for the gateway. Defaults to `wspace`. */\n layer?: ServiceLayer;\n /** Workspace context (required for wspace exports). */\n workspaceId: string;\n /** Human-readable name for the export job. */\n name: string;\n /** Entity types registered in `wspace-export-svc` to include. */\n entityTypes: string[];\n /** Output format. */\n format: ExportFormatGql;\n /** Actor making the request (forwarded to RBAC). */\n actorId: string;\n actorType: ExportActorType;\n /** Whether to include extended metadata in the export ZIP. */\n includeMetadata?: boolean;\n /** Optional ISO date-range bounds. */\n dateRangeStart?: string;\n dateRangeEnd?: string;\n}\n\nexport interface ExportJobResult {\n id: string;\n status: string;\n workspaceId: string;\n entityTypes: string[];\n format: string;\n createdAt: string;\n}\n\ninterface CreateExportJobResponse {\n createExportJob?: ExportJobResult;\n}\n\n/**\n * Submit a `createExportJob` mutation to the workspace internal gateway.\n *\n * The caller is expected to map the returned `ExportJobResult` to its\n * own GraphQL output type (the per-svc `ExportJobResponse`).\n */\nexport async function triggerExportJob(params: TriggerExportJobParams): Promise<ExportJobResult> {\n const {\n serviceName,\n layer = 'wspace',\n actorId,\n actorType,\n workspaceId,\n name,\n entityTypes,\n format,\n includeMetadata,\n dateRangeStart,\n dateRangeEnd,\n } = params;\n\n const client = new GatewayClient({ layer, serviceName });\n\n const input = {\n workspaceId,\n name,\n entityTypes,\n format,\n ...(includeMetadata !== undefined ? { includeMetadata } : {}),\n ...(dateRangeStart !== undefined ? { dateRangeStart } : {}),\n ...(dateRangeEnd !== undefined ? { dateRangeEnd } : {}),\n };\n\n const response = await client.internalQuery<CreateExportJobResponse>({\n query: CREATE_EXPORT_JOB_MUTATION,\n variables: { input },\n headers: {\n 'x-actor-id': actorId,\n 'x-actor-type': actorType,\n 'x-workspace-id': workspaceId,\n },\n });\n\n const job = response.data?.createExportJob;\n if (!job) {\n throw new Error('Export service did not return a job');\n }\n return job;\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/export/index.ts","../src/export/base-exporter.ts","../src/export/pagination.ts","../src/export/csv.ts","../src/export/gateway-client.ts"],"names":["BaseModuleExporter","moduleKey","displayName","description","defaultExcludeFields","supportedProducts","modelName","filterFields","entity","excludeFields","fieldsToExclude","length","filtered","record","key","value","Object","entries","includes","filterFieldsMany","entities","map","paginate","queryFn","page","pageSize","skip","take","items","total","data","hasMore","nextCursor","String","undefined","fetchAll","fetchBatch","batchSize","allItems","cursor","batch","push","lastItem","id","transformForExport","validateOptions","options","validFormats","format","Error","join","getSupportedFormats","getMetadata","supportedFormats","PaginationService","params","start","end","paginatedItems","slice","totalCount","pageInfo","hasNextPage","hasPreviousPage","startCursor","endCursor","Math","min","calculatePagination","totalPages","ceil","startIndex","endIndex","currentPage","paginatedQuery","fetchFn","limit","initialCursor","totalYielded","item","collectPaginatedQuery","createPrismaFetchFn","_batchSize","calculateOffset","max","parseCursor","decoded","Buffer","from","toString","JSON","parse","createCursor","stringify","FORMULA_PREFIX_RE","sanitizeCSVCell","test","convertToCSV","delimiter","includeHeaders","flattenFields","maxFlattenDepth","flattenObject","obj","prefix","depth","result","newKey","Date","toISOString","Array","isArray","assign","flattenedRecords","allKeys","Set","keys","add","headers","sort","a","b","localeCompare","escapeCSV","sanitizedValue","replace","lines","row","header","parseCSV","csv","hasHeaders","split","filter","line","trim","parseLine","values","current","inQuotes","i","char","nextChar","dataLines","firstLine","firstRow","_","forEach","csvToJSON","pretty","parseOptions","getCSVHeaders","collectKeys","fullKey","estimateCSVSize","sampleSize","sample","sampleCSV","averageRowSize","headerSize","CREATE_EXPORT_JOB_MUTATION","triggerExportJob","serviceName","layer","actorId","actorType","workspaceId","name","entityTypes","includeMetadata","dateRangeStart","dateRangeEnd","client","GatewayClient","input","response","internalQuery","query","variables","job","createExportJob"],"mappings":"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","file":"chunk-MEA4BQNA.js","sourcesContent":["/**\n * Export Module\n *\n * Provides common utilities for data export operations across all Burdenoff microservices.\n * Includes pagination services, base exporter classes, CSV utilities, and type definitions.\n *\n * @module export\n *\n * @example\n * ```typescript\n * // Import from the export module\n * import {\n * BaseModuleExporter,\n * PaginationService,\n * convertToCSV,\n * } from '@burdenoff/be-sdk/export';\n *\n * // Create a custom exporter\n * class UserExporter extends BaseModuleExporter<User> {\n * moduleKey = 'users';\n * displayName = 'Users';\n *\n * async export(options: ExportOptions): Promise<ExportResult> {\n * const data = await this.fetchAll(\n * (cursor) => db.user.findMany({\n * where: cursor ? { id: { gt: cursor } } : {},\n * take: 100,\n * })\n * );\n *\n * const csv = convertToCSV(data);\n * return { data, format: 'csv' };\n * }\n * }\n *\n * // Use pagination utilities\n * const result = PaginationService.paginate(items, { page: 1, pageSize: 20 });\n * ```\n */\n\n// ============================================================================\n// Type Exports\n// ============================================================================\n\nexport type {\n // Export format types\n ExportFormat,\n ExportFormatEnum,\n\n // Configuration types\n ExportConfig,\n ExportOptions,\n\n // Job types\n ExportJobStatus,\n ExportJob,\n ExportProgress,\n ExportResult,\n\n // Fetch types\n ExportFetchOptions,\n ExportFetchResult,\n\n // Pagination types\n PaginationParams,\n PaginatedResult,\n PaginatedQueryOptions,\n PaginateResult,\n PaginateQueryFn,\n\n // Module interface\n ExportableModule,\n\n // CSV types\n CSVConversionOptions,\n} from './types.js';\n\n// ============================================================================\n// Class Exports\n// ============================================================================\n\nexport { BaseModuleExporter } from './base-exporter.js';\nexport { PaginationService } from './pagination.js';\n\n// ============================================================================\n// Function Exports\n// ============================================================================\n\nexport { convertToCSV, parseCSV, csvToJSON, getCSVHeaders, estimateCSVSize } from './csv.js';\n\n// ============================================================================\n// Gateway Helper Exports\n// ============================================================================\n\nexport { triggerExportJob } from './gateway-client.js';\nexport type { TriggerExportJobParams, ExportJobResult, ExportActorType, ExportFormatGql } from './gateway-client.js';\n","/**\n * Base Module Exporter\n *\n * Abstract base class for module exporters across all Burdenoff microservices.\n * Provides common functionality for exporting data from different modules.\n *\n * @module export/base-exporter\n *\n * @example\n * ```typescript\n * import { BaseModuleExporter } from '@burdenoff/be-sdk/export';\n *\n * class UserExporter extends BaseModuleExporter<User> {\n * moduleKey = 'users';\n * displayName = 'Users';\n * description = 'Export user data';\n *\n * async export(options: ExportOptions): Promise<ExportResult> {\n * // Implementation\n * }\n * }\n * ```\n */\n\nimport type { ExportOptions, ExportResult, PaginateQueryFn, PaginateResult } from './types.js';\n\n/**\n * Abstract base class for module exporters\n *\n * Provides common functionality that all module exporters can inherit:\n * - Field filtering\n * - Pagination helpers\n * - Module metadata\n *\n * @typeParam T - The type of entity this exporter handles\n */\nexport abstract class BaseModuleExporter<T = unknown> {\n /** Unique key identifying this module (e.g., 'users', 'tags', 'orders') */\n moduleKey?: string;\n\n /** Human-readable display name for the module */\n displayName?: string;\n\n /** Description of what this module exports */\n description?: string;\n\n /** Default fields to exclude from export (e.g., sensitive data) */\n defaultExcludeFields?: string[];\n\n /** List of product IDs this exporter supports */\n supportedProducts?: string[];\n\n /** Model name for database operations */\n protected modelName?: string;\n\n /**\n * Export data from this module\n *\n * Subclasses should implement this method to perform the actual export.\n * The method is optional to allow for gradual implementation.\n *\n * @param options - Export options including format, filters, and pagination\n * @returns Export result with data or download URL\n */\n export?(options: ExportOptions): Promise<ExportResult>;\n\n /**\n * Filter fields from an entity based on exclude list\n *\n * Use this to remove sensitive or unnecessary fields from exported data.\n *\n * @param entity - Entity to filter\n * @param excludeFields - Fields to exclude (uses defaultExcludeFields if not provided)\n * @returns Filtered entity as a plain object\n *\n * @example\n * ```typescript\n * const user = { id: '1', name: 'John', password: 'secret', ssn: '123' };\n * const filtered = this.filterFields(user, ['password', 'ssn']);\n * // Result: { id: '1', name: 'John' }\n * ```\n */\n protected filterFields(entity: T | Record<string, unknown>, excludeFields?: string[]): Record<string, unknown> {\n const fieldsToExclude = excludeFields || this.defaultExcludeFields || [];\n\n if (fieldsToExclude.length === 0) {\n return entity as Record<string, unknown>;\n }\n\n const filtered: Record<string, unknown> = {};\n const record = entity as Record<string, unknown>;\n\n for (const [key, value] of Object.entries(record)) {\n if (!fieldsToExclude.includes(key)) {\n filtered[key] = value;\n }\n }\n\n return filtered;\n }\n\n /**\n * Filter multiple entities\n *\n * @param entities - Array of entities to filter\n * @param excludeFields - Fields to exclude\n * @returns Array of filtered entities\n */\n protected filterFieldsMany(\n entities: (T | Record<string, unknown>)[],\n excludeFields?: string[]\n ): Record<string, unknown>[] {\n return entities.map((entity) => this.filterFields(entity, excludeFields));\n }\n\n /**\n * Paginate helper for database queries\n *\n * Use this to implement paginated data fetching in your export method.\n *\n * @param queryFn - Function that executes the paginated query\n * @param page - Page number (1-indexed)\n * @param pageSize - Number of items per page\n * @returns Paginated result with data and metadata\n *\n * @example\n * ```typescript\n * const result = await this.paginate(\n * async ({ skip, take }) => {\n * const items = await db.user.findMany({ skip, take });\n * const total = await db.user.count();\n * return { items, total };\n * },\n * 1,\n * 100\n * );\n * ```\n */\n protected async paginate(\n queryFn: PaginateQueryFn<T>,\n page: number = 1,\n pageSize: number = 100\n ): Promise<PaginateResult<T>> {\n const skip = (page - 1) * pageSize;\n const take = pageSize;\n\n const { items, total } = await queryFn({ skip, take });\n\n return {\n data: items,\n total,\n hasMore: skip + items.length < total,\n nextCursor: items.length > 0 && skip + items.length < total ? String(page + 1) : undefined,\n };\n }\n\n /**\n * Fetch all data using cursor-based pagination\n *\n * Use this for exporting large datasets efficiently.\n *\n * @param fetchBatch - Function to fetch a batch of data\n * @param batchSize - Number of items per batch\n * @returns All fetched items\n *\n * @example\n * ```typescript\n * const allUsers = await this.fetchAll(\n * async (cursor) => db.user.findMany({\n * where: cursor ? { id: { gt: cursor } } : undefined,\n * orderBy: { id: 'asc' },\n * take: 100,\n * }),\n * 100\n * );\n * ```\n */\n protected async fetchAll(\n fetchBatch: (cursor?: string) => Promise<(T & { id: string })[]>,\n batchSize: number = 100\n ): Promise<T[]> {\n const allItems: T[] = [];\n let cursor: string | undefined;\n\n while (true) {\n const batch = await fetchBatch(cursor);\n\n if (batch.length === 0) {\n break;\n }\n\n allItems.push(...batch);\n\n // Get cursor from last item\n const lastItem = batch[batch.length - 1];\n if (lastItem) {\n cursor = lastItem.id;\n }\n\n // If we got fewer items than batch size, we're done\n if (batch.length < batchSize) {\n break;\n }\n }\n\n return allItems;\n }\n\n /**\n * Transform entity for export\n *\n * Override this method to customize how entities are transformed before export.\n * Default implementation returns the entity as-is after field filtering.\n *\n * @param entity - Entity to transform\n * @param excludeFields - Fields to exclude\n * @returns Transformed entity\n */\n protected transformForExport(entity: T, excludeFields?: string[]): Record<string, unknown> {\n return this.filterFields(entity, excludeFields);\n }\n\n /**\n * Validate export options\n *\n * Override this to add custom validation for export options.\n *\n * @param options - Export options to validate\n * @throws Error if options are invalid\n */\n protected validateOptions(options: ExportOptions): void {\n const validFormats = ['csv', 'json', 'xlsx'];\n if (!validFormats.includes(options.format)) {\n throw new Error(`Invalid export format: ${options.format}. Valid formats: ${validFormats.join(', ')}`);\n }\n }\n\n /**\n * Get supported export formats\n *\n * @returns Array of supported format strings\n */\n getSupportedFormats(): string[] {\n return ['csv', 'json', 'xlsx'];\n }\n\n /**\n * Get module metadata\n *\n * @returns Module metadata object\n */\n getMetadata(): {\n moduleKey?: string;\n displayName?: string;\n description?: string;\n supportedProducts?: string[];\n supportedFormats: string[];\n } {\n return {\n moduleKey: this.moduleKey,\n displayName: this.displayName,\n description: this.description,\n supportedProducts: this.supportedProducts,\n supportedFormats: this.getSupportedFormats(),\n };\n }\n}\n","/**\n * Pagination Service\n *\n * Provides pagination utilities for export operations across all Burdenoff microservices.\n * Supports both offset-based and cursor-based pagination strategies.\n *\n * @module export/pagination\n *\n * @example\n * ```typescript\n * import { PaginationService } from '@burdenoff/be-sdk/export';\n *\n * // Offset-based pagination\n * const result = PaginationService.paginate(items, { page: 2, pageSize: 20 });\n *\n * // Cursor-based pagination with async generator\n * for await (const item of PaginationService.paginatedQuery(fetchFn, { limit: 100 })) {\n * console.log(item);\n * }\n * ```\n */\n\nimport type { PaginatedQueryOptions, PaginatedResult, PaginationParams } from './types.js';\n\n/**\n * Service providing pagination utilities for export and data fetching operations\n */\nexport class PaginationService {\n /**\n * Paginate an array of items using offset-based pagination\n *\n * @param items - Array of items to paginate\n * @param params - Pagination parameters\n * @returns Paginated result with items and metadata\n *\n * @example\n * ```typescript\n * const allUsers = await db.user.findMany();\n * const page = PaginationService.paginate(allUsers, { page: 1, pageSize: 10 });\n * console.log(page.items); // First 10 users\n * console.log(page.pageInfo.hasNextPage); // true if more pages exist\n * ```\n */\n static paginate<T>(items: T[], params: PaginationParams): PaginatedResult<T> {\n const page = params.page ?? 1;\n const pageSize = params.pageSize ?? 20;\n const start = (page - 1) * pageSize;\n const end = start + pageSize;\n\n const paginatedItems = items.slice(start, end);\n\n return {\n items: paginatedItems,\n totalCount: items.length,\n pageInfo: {\n hasNextPage: end < items.length,\n hasPreviousPage: page > 1,\n startCursor: paginatedItems.length > 0 ? String(start) : undefined,\n endCursor: paginatedItems.length > 0 ? String(Math.min(end, items.length) - 1) : undefined,\n },\n };\n }\n\n /**\n * Calculate pagination metadata without slicing data\n *\n * @param totalCount - Total number of items\n * @param page - Current page number (1-indexed)\n * @param pageSize - Items per page\n * @returns Pagination metadata\n *\n * @example\n * ```typescript\n * const meta = PaginationService.calculatePagination(150, 3, 20);\n * // meta.hasNextPage = true (page 4 exists)\n * // meta.hasPreviousPage = true (page 2 exists)\n * // meta.totalPages = 8\n * ```\n */\n static calculatePagination(\n totalCount: number,\n page: number,\n pageSize: number\n ): {\n hasNextPage: boolean;\n hasPreviousPage: boolean;\n totalPages: number;\n currentPage: number;\n pageSize: number;\n startIndex: number;\n endIndex: number;\n } {\n const totalPages = Math.ceil(totalCount / pageSize);\n const startIndex = (page - 1) * pageSize;\n const endIndex = Math.min(startIndex + pageSize - 1, totalCount - 1);\n\n return {\n hasNextPage: page < totalPages,\n hasPreviousPage: page > 1,\n totalPages,\n currentPage: page,\n pageSize,\n startIndex,\n endIndex,\n };\n }\n\n /**\n * Async generator for paginated database queries using cursor-based pagination\n *\n * This is ideal for processing large datasets without loading everything into memory.\n * The generator yields items one at a time, fetching new batches as needed.\n *\n * @param fetchFn - Function to fetch data given a cursor\n * @param options - Pagination options\n * @returns Async generator of items\n *\n * @example\n * ```typescript\n * // Define fetch function that queries the database\n * const fetchUsers = async (cursor?: string) => {\n * return db.user.findMany({\n * where: cursor ? { id: { gt: cursor } } : undefined,\n * orderBy: { id: 'asc' },\n * take: 100,\n * });\n * };\n *\n * // Process all users without loading all into memory\n * for await (const user of PaginationService.paginatedQuery(fetchUsers)) {\n * await processUser(user);\n * }\n * ```\n */\n static async *paginatedQuery<T extends { id: string }>(\n fetchFn: (cursor?: string) => Promise<T[]>,\n options: PaginatedQueryOptions = {}\n ): AsyncGenerator<T, void, unknown> {\n const { limit, initialCursor } = options;\n let cursor = initialCursor;\n let hasMore = true;\n let totalYielded = 0;\n\n while (hasMore) {\n const items = await fetchFn(cursor);\n\n if (items.length === 0) {\n break;\n }\n\n for (const item of items) {\n yield item;\n totalYielded++;\n\n if (limit && totalYielded >= limit) {\n return;\n }\n }\n\n // Get next cursor from last item\n const lastItem = items[items.length - 1];\n if (lastItem) {\n cursor = lastItem.id;\n }\n\n // If we got fewer items than expected batch size, we're done\n // Note: This assumes fetchFn respects a consistent batch size internally\n hasMore = items.length > 0;\n }\n }\n\n /**\n * Collect all items from a paginated query into an array\n *\n * @param fetchFn - Function to fetch data given a cursor\n * @param options - Pagination options\n * @returns Array of all items\n *\n * @example\n * ```typescript\n * const allUsers = await PaginationService.collectPaginatedQuery(fetchUsers, { limit: 1000 });\n * ```\n */\n static async collectPaginatedQuery<T extends { id: string }>(\n fetchFn: (cursor?: string) => Promise<T[]>,\n options: PaginatedQueryOptions = {}\n ): Promise<T[]> {\n const items: T[] = [];\n\n for await (const item of PaginationService.paginatedQuery(fetchFn, options)) {\n items.push(item);\n }\n\n return items;\n }\n\n /**\n * Create a cursor-based paginated fetch function from a Prisma-style query\n *\n * @param queryFn - Prisma-style query function\n * @param batchSize - Number of items to fetch per batch\n * @returns Fetch function compatible with paginatedQuery\n *\n * @example\n * ```typescript\n * const fetchFn = PaginationService.createPrismaFetchFn(\n * (cursor) => db.user.findMany({\n * where: { isActive: true, ...(cursor ? { id: { gt: cursor } } : {}) },\n * orderBy: { id: 'asc' },\n * take: 100,\n * }),\n * 100\n * );\n *\n * for await (const user of PaginationService.paginatedQuery(fetchFn)) {\n * console.log(user);\n * }\n * ```\n */\n static createPrismaFetchFn<T extends { id: string }>(\n queryFn: (cursor?: string) => Promise<T[]>,\n _batchSize: number = 100\n ): (cursor?: string) => Promise<T[]> {\n return queryFn;\n }\n\n /**\n * Calculate offset for skip-based pagination\n *\n * @param page - Page number (1-indexed)\n * @param pageSize - Items per page\n * @returns Offset value for skip\n */\n static calculateOffset(page: number, pageSize: number): number {\n return (Math.max(1, page) - 1) * pageSize;\n }\n\n /**\n * Parse cursor string to extract pagination state\n *\n * @param cursor - Base64-encoded cursor string\n * @returns Decoded cursor data or null if invalid\n */\n static parseCursor<T = Record<string, unknown>>(cursor: string): T | null {\n try {\n const decoded = Buffer.from(cursor, 'base64').toString('utf-8');\n return JSON.parse(decoded) as T;\n } catch {\n return null;\n }\n }\n\n /**\n * Create cursor string from pagination state\n *\n * @param data - Data to encode in cursor\n * @returns Base64-encoded cursor string\n */\n static createCursor(data: Record<string, unknown>): string {\n return Buffer.from(JSON.stringify(data)).toString('base64');\n }\n}\n","/**\n * CSV Utilities\n *\n * Utilities for converting data to CSV format for export operations.\n *\n * @module export/csv\n *\n * @example\n * ```typescript\n * import { convertToCSV, parseCSV } from '@burdenoff/be-sdk/export';\n *\n * const csv = convertToCSV(users, { includeHeaders: true });\n * console.log(csv);\n * ```\n */\n\nimport type { CSVConversionOptions } from './types.js';\n\nconst FORMULA_PREFIX_RE = /^[=+\\-@]/;\n\nexport function sanitizeCSVCell(value: string): string {\n return FORMULA_PREFIX_RE.test(value) ? `'${value}` : value;\n}\n\n/**\n * Convert an array of objects to CSV format\n *\n * Handles nested objects by flattening them with dot notation.\n * Arrays are JSON stringified.\n * Dates are converted to ISO strings.\n *\n * @param data - Array of objects to convert\n * @param options - CSV conversion options\n * @returns CSV string\n *\n * @example\n * ```typescript\n * const users = [\n * { id: 1, name: 'John', address: { city: 'NYC' } },\n * { id: 2, name: 'Jane', address: { city: 'LA' } },\n * ];\n *\n * const csv = convertToCSV(users);\n * // Output:\n * // id,name,address.city\n * // 1,John,NYC\n * // 2,Jane,LA\n * ```\n */\nexport function convertToCSV(data: unknown[], options: CSVConversionOptions = {}): string {\n const { delimiter = ',', includeHeaders = true, flattenFields = true, maxFlattenDepth = 3 } = options;\n\n if (data.length === 0) {\n return '';\n }\n\n // Flatten objects and get all keys\n const flattenObject = (obj: unknown, prefix = '', depth = 0): Record<string, string> => {\n const result: Record<string, string> = {};\n\n if (obj === null || obj === undefined) {\n return result;\n }\n\n if (typeof obj !== 'object') {\n return { [prefix || 'value']: String(obj) };\n }\n\n for (const [key, value] of Object.entries(obj as Record<string, unknown>)) {\n const newKey = prefix ? `${prefix}.${key}` : key;\n\n if (value === null || value === undefined) {\n result[newKey] = '';\n } else if (value instanceof Date) {\n result[newKey] = value.toISOString();\n } else if (Array.isArray(value)) {\n result[newKey] = JSON.stringify(value);\n } else if (typeof value === 'object' && flattenFields && depth < maxFlattenDepth) {\n Object.assign(result, flattenObject(value, newKey, depth + 1));\n } else if (typeof value === 'object') {\n result[newKey] = JSON.stringify(value);\n } else {\n result[newKey] = String(value);\n }\n }\n\n return result;\n };\n\n // Flatten all records and collect all keys\n const flattenedRecords = data.map((item) => flattenObject(item));\n const allKeys = new Set<string>();\n for (const record of flattenedRecords) {\n for (const key of Object.keys(record)) {\n allKeys.add(key);\n }\n }\n\n const headers = Array.from(allKeys).sort((a, b) => a.localeCompare(b));\n\n // Escape CSV values\n const escapeCSV = (value: string): string => {\n const sanitizedValue = sanitizeCSVCell(value);\n\n if (\n sanitizedValue.includes(delimiter) ||\n sanitizedValue.includes('\"') ||\n sanitizedValue.includes('\\n') ||\n sanitizedValue.includes('\\r')\n ) {\n return `\"${sanitizedValue.replace(/\"/g, '\"\"')}\"`;\n }\n return sanitizedValue;\n };\n\n // Build CSV\n const lines: string[] = [];\n\n if (includeHeaders) {\n lines.push(headers.map(escapeCSV).join(delimiter));\n }\n\n for (const record of flattenedRecords) {\n const row = headers.map((header) => escapeCSV(record[header] || ''));\n lines.push(row.join(delimiter));\n }\n\n return lines.join('\\n');\n}\n\n/**\n * Parse a CSV string into an array of objects\n *\n * @param csv - CSV string to parse\n * @param options - Parse options\n * @returns Array of parsed objects\n *\n * @example\n * ```typescript\n * const csv = 'id,name\\n1,John\\n2,Jane';\n * const data = parseCSV(csv);\n * // [{ id: '1', name: 'John' }, { id: '2', name: 'Jane' }]\n * ```\n */\nexport function parseCSV(\n csv: string,\n options: { delimiter?: string; hasHeaders?: boolean } = {}\n): Record<string, string>[] {\n const { delimiter = ',', hasHeaders = true } = options;\n\n const lines = csv.split(/\\r?\\n/).filter((line) => line.trim());\n\n if (lines.length === 0) {\n return [];\n }\n\n // Parse a single CSV line, handling quoted values\n const parseLine = (line: string): string[] => {\n const values: string[] = [];\n let current = '';\n let inQuotes = false;\n\n let i = 0;\n while (i < line.length) {\n const char = line[i];\n const nextChar = line[i + 1];\n\n if (char === '\"' && inQuotes && nextChar === '\"') {\n current += '\"';\n i += 2; // Skip next quote\n } else if (char === '\"') {\n inQuotes = !inQuotes;\n i++;\n } else if (char === delimiter && !inQuotes) {\n values.push(current);\n current = '';\n i++;\n } else {\n current += char;\n i++;\n }\n }\n\n values.push(current);\n return values;\n };\n\n let headers: string[];\n let dataLines: string[];\n\n // We've already checked that lines.length > 0, so lines[0] is guaranteed to exist\n const firstLine = lines[0] as string;\n\n if (hasHeaders) {\n headers = parseLine(firstLine);\n dataLines = lines.slice(1);\n } else {\n // Generate numeric headers if no header row\n const firstRow = parseLine(firstLine);\n headers = firstRow.map((_, i) => `col${i}`);\n dataLines = lines;\n }\n\n return dataLines.map((line) => {\n const values = parseLine(line);\n const obj: Record<string, string> = {};\n\n headers.forEach((header, i) => {\n obj[header] = values[i] || '';\n });\n\n return obj;\n });\n}\n\n/**\n * Convert CSV to JSON string\n *\n * @param csv - CSV string\n * @param options - Parse options\n * @returns JSON string\n */\nexport function csvToJSON(\n csv: string,\n options: { delimiter?: string; hasHeaders?: boolean; pretty?: boolean } = {}\n): string {\n const { pretty = false, ...parseOptions } = options;\n const data = parseCSV(csv, parseOptions);\n return pretty ? JSON.stringify(data, null, 2) : JSON.stringify(data);\n}\n\n/**\n * Get CSV headers from data\n *\n * @param data - Array of objects\n * @param flattenFields - Whether to flatten nested objects\n * @returns Array of header strings\n */\nexport function getCSVHeaders(data: unknown[], flattenFields: boolean = true): string[] {\n if (data.length === 0) {\n return [];\n }\n\n const collectKeys = (obj: unknown, prefix = '', depth = 0): string[] => {\n const keys: string[] = [];\n\n if (obj === null || obj === undefined || typeof obj !== 'object') {\n return prefix ? [prefix] : [];\n }\n\n for (const [key, value] of Object.entries(obj as Record<string, unknown>)) {\n const fullKey = prefix ? `${prefix}.${key}` : key;\n\n if (\n value !== null &&\n typeof value === 'object' &&\n !Array.isArray(value) &&\n !(value instanceof Date) &&\n flattenFields &&\n depth < 3\n ) {\n keys.push(...collectKeys(value, fullKey, depth + 1));\n } else {\n keys.push(fullKey);\n }\n }\n\n return keys;\n };\n\n const allKeys = new Set<string>();\n for (const item of data) {\n for (const key of collectKeys(item)) {\n allKeys.add(key);\n }\n }\n\n return Array.from(allKeys).sort((a, b) => a.localeCompare(b));\n}\n\n/**\n * Estimate CSV file size for a dataset\n *\n * @param data - Array of objects\n * @param sampleSize - Number of records to sample for estimation\n * @returns Estimated size in bytes\n */\nexport function estimateCSVSize(data: unknown[], sampleSize: number = 100): number {\n if (data.length === 0) {\n return 0;\n }\n\n // Take a sample to estimate average row size\n const sample = data.slice(0, Math.min(sampleSize, data.length));\n const sampleCSV = convertToCSV(sample);\n const averageRowSize = sampleCSV.length / sample.length;\n\n // Estimate total size (headers + data rows)\n const headers = getCSVHeaders(data);\n const headerSize = headers.join(',').length + 1; // +1 for newline\n\n return Math.ceil(headerSize + averageRowSize * data.length);\n}\n","/**\n * Export Gateway Helper\n *\n * Centralised wrapper around the workspace internal gateway's\n * `createExportJob` mutation, used by per-svc convenience resolvers\n * (e.g. `createTagsExportJob`, `createGroupsExportJob`).\n *\n * Replaces the duplicated `src/clients/export-gateway.ts` files that\n * existed in 19+ workspace svcs.\n *\n * @module export/gateway-client\n *\n * @example\n * ```typescript\n * import { triggerExportJob } from '@burdenoff/be-sdk/export';\n *\n * const result = await triggerExportJob({\n * serviceName: 'wspace-tags-svc',\n * workspaceId: ctx.workspaceId,\n * name: input.name,\n * entityTypes: ['tags', 'vocabularies'],\n * format: input.format,\n * actorId: ctx.actorId,\n * actorType: ctx.actorType,\n * });\n * ```\n */\n\nimport { GatewayClient } from '../gateway/index.js';\nimport type { ServiceLayer } from '../types/layer.js';\n\nconst CREATE_EXPORT_JOB_MUTATION = `mutation CreateExportJob($input: CreateExportJobInput!) {\n createExportJob(input: $input) {\n id\n status\n workspaceId\n entityTypes\n format\n createdAt\n }\n}`;\n\nexport type ExportActorType = 'user' | 'app' | 'service' | 'super_admin';\nexport type ExportFormatGql = 'JSON' | 'CSV';\n\nexport interface TriggerExportJobParams {\n /** Caller service name, used by gateway client telemetry/auth */\n serviceName: string;\n /** Layer for the gateway. Defaults to `wspace`. */\n layer?: ServiceLayer;\n /** Workspace context (required for wspace exports). */\n workspaceId: string;\n /** Human-readable name for the export job. */\n name: string;\n /** Entity types registered in `wspace-export-svc` to include. */\n entityTypes: string[];\n /** Output format. */\n format: ExportFormatGql;\n /** Actor making the request (forwarded to RBAC). */\n actorId: string;\n actorType: ExportActorType;\n /** Whether to include extended metadata in the export ZIP. */\n includeMetadata?: boolean;\n /** Optional ISO date-range bounds. */\n dateRangeStart?: string;\n dateRangeEnd?: string;\n}\n\nexport interface ExportJobResult {\n id: string;\n status: string;\n workspaceId: string;\n entityTypes: string[];\n format: string;\n createdAt: string;\n}\n\ninterface CreateExportJobResponse {\n createExportJob?: ExportJobResult;\n}\n\n/**\n * Submit a `createExportJob` mutation to the workspace internal gateway.\n *\n * The caller is expected to map the returned `ExportJobResult` to its\n * own GraphQL output type (the per-svc `ExportJobResponse`).\n */\nexport async function triggerExportJob(params: TriggerExportJobParams): Promise<ExportJobResult> {\n const {\n serviceName,\n layer = 'wspace',\n actorId,\n actorType,\n workspaceId,\n name,\n entityTypes,\n format,\n includeMetadata,\n dateRangeStart,\n dateRangeEnd,\n } = params;\n\n const client = new GatewayClient({ layer, serviceName });\n\n const input = {\n workspaceId,\n name,\n entityTypes,\n format,\n ...(includeMetadata !== undefined ? { includeMetadata } : {}),\n ...(dateRangeStart !== undefined ? { dateRangeStart } : {}),\n ...(dateRangeEnd !== undefined ? { dateRangeEnd } : {}),\n };\n\n const response = await client.internalQuery<CreateExportJobResponse>({\n query: CREATE_EXPORT_JOB_MUTATION,\n variables: { input },\n headers: {\n 'x-actor-id': actorId,\n 'x-actor-type': actorType,\n 'x-workspace-id': workspaceId,\n },\n });\n\n const job = response.data?.createExportJob;\n if (!job) {\n throw new Error('Export service did not return a job');\n }\n return job;\n}\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { logger } from './chunk-
|
|
1
|
+
import { logger } from './chunk-RU266375.js';
|
|
2
2
|
import { __name } from './chunk-XE4OXN2W.js';
|
|
3
3
|
|
|
4
4
|
// src/graphql/services/Logger.ts
|
|
@@ -90,5 +90,5 @@ function createDatabaseService(prismaClient) {
|
|
|
90
90
|
__name(createDatabaseService, "createDatabaseService");
|
|
91
91
|
|
|
92
92
|
export { Logger, createDatabaseService };
|
|
93
|
-
//# sourceMappingURL=chunk-
|
|
94
|
-
//# sourceMappingURL=chunk-
|
|
93
|
+
//# sourceMappingURL=chunk-MWPYA2HD.js.map
|
|
94
|
+
//# sourceMappingURL=chunk-MWPYA2HD.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/graphql/services/Logger.ts","../src/graphql/services/Database.ts"],"names":["Logger","log","message","args","sdkLogger","info","warn","error","debug","trace","createDatabaseService","prismaClient","Database","client","transaction","fn","$transaction","isConnected","$queryRaw"],"mappings":";;;;AAmBO,IAAMA,SAAN,MAAMA;EAnBb;;;;;;AAuBEC,EAAAA,GAAAA,CAAIC,YAAoBC,IAAAA,EAAuB;AAC7CC,IAAAA,MAAAA,CAAUC,IAAAA,CAAKH,OAAAA,EAAAA,GAAYC,IAAAA,CAAAA;AAC7B,EAAA;;;;AAKAE,EAAAA,IAAAA,CAAKH,YAAoBC,IAAAA,EAAuB;AAC9CC,IAAAA,MAAAA,CAAUC,IAAAA,CAAKH,OAAAA,EAAAA,GAAYC,IAAAA,CAAAA;AAC7B,EAAA;;;;AAKAG,EAAAA,IAAAA,CAAKJ,YAAoBC,IAAAA,EAAuB;AAC9CC,IAAAA,MAAAA,CAAUE,IAAAA,CAAKJ,OAAAA,EAAAA,GAAYC,IAAAA,CAAAA;AAC7B,EAAA;;;;EAKAI,KAAAA,CAAML,OAAAA,EAAiBK,UAA4BJ,IAAAA,EAAuB;AACxEC,IAAAA,MAAAA,CAAUG,KAAAA,CAAML,OAAAA,EAASK,KAAAA,EAAAA,GAAUJ,IAAAA,CAAAA;AACrC,EAAA;;;;AAKAK,EAAAA,KAAAA,CAAMN,YAAoBC,IAAAA,EAAuB;AAC/CC,IAAAA,MAAAA,CAAUI,KAAAA,CAAMN,OAAAA,EAAAA,GAAYC,IAAAA,CAAAA;AAC9B,EAAA;;;;AAKAM,EAAAA,KAAAA,CAAMP,YAAoBC,IAAAA,EAAuB;AAC/C,IAAA,IAAI,OAAA,IAAWC,MAAAA,IAAa,OAAOA,MAAAA,CAAUK,UAAU,UAAA,EAAY;AACjEL,MAAAA,MAAAA,CAAUK,KAAAA,CAAMP,OAAAA,EAAAA,GAAYC,IAAAA,CAAAA;IAC9B,CAAA,MAAO;AACLC,MAAAA,MAAAA,CAAUI,KAAAA,CAAMN,OAAAA,EAAAA,GAAYC,IAAAA,CAAAA;AAC9B,IAAA;AACF,EAAA;AACF;;;ACzBO,SAASO,sBACdC,YAAAA,EAA2B;AAQ3B,EAAA,IAAMC,QAAAA,GAAN,MAAMA,QAAAA,CAAAA;IAjDR;;;;;;AAqDI,IAAA,IAAIC,MAAAA,GAAwB;AAC1B,MAAA,OAAOF,YAAAA;AACT,IAAA;;;;;;;AAQA,IAAA,MAAMG,YAAeC,EAAAA,EAA4E;AAC/F,MAAA,OAAOJ,YAAAA,CAAaK,aAAaD,EAAAA,CAAAA;AACnC,IAAA;;;;;;AAOA,IAAA,MAAME,WAAAA,GAAgC;AACpC,MAAA,IAAI;AAEF,QAAA,IAAI,WAAA,IAAeN,YAAAA,IAAgB,OAAOA,YAAAA,CAAaO,cAAc,UAAA,EAAY;AAC/E,UAAA,MAAOP,YAAAA,CAAaO,SAAAA,CAAAA,QAAAA,CAAAA;AACtB,QAAA;AACA,QAAA,OAAO,IAAA;MACT,CAAA,CAAA,MAAQ;AACN,QAAA,OAAO,KAAA;AACT,MAAA;AACF,IAAA;AACF,GAAA;AAEA,EAAA,OAAON,QAAAA;AACT;AA9CgBF,MAAAA,CAAAA,qBAAAA,EAAAA,uBAAAA,CAAAA","file":"chunk-
|
|
1
|
+
{"version":3,"sources":["../src/graphql/services/Logger.ts","../src/graphql/services/Database.ts"],"names":["Logger","log","message","args","sdkLogger","info","warn","error","debug","trace","createDatabaseService","prismaClient","Database","client","transaction","fn","$transaction","isConnected","$queryRaw"],"mappings":";;;;AAmBO,IAAMA,SAAN,MAAMA;EAnBb;;;;;;AAuBEC,EAAAA,GAAAA,CAAIC,YAAoBC,IAAAA,EAAuB;AAC7CC,IAAAA,MAAAA,CAAUC,IAAAA,CAAKH,OAAAA,EAAAA,GAAYC,IAAAA,CAAAA;AAC7B,EAAA;;;;AAKAE,EAAAA,IAAAA,CAAKH,YAAoBC,IAAAA,EAAuB;AAC9CC,IAAAA,MAAAA,CAAUC,IAAAA,CAAKH,OAAAA,EAAAA,GAAYC,IAAAA,CAAAA;AAC7B,EAAA;;;;AAKAG,EAAAA,IAAAA,CAAKJ,YAAoBC,IAAAA,EAAuB;AAC9CC,IAAAA,MAAAA,CAAUE,IAAAA,CAAKJ,OAAAA,EAAAA,GAAYC,IAAAA,CAAAA;AAC7B,EAAA;;;;EAKAI,KAAAA,CAAML,OAAAA,EAAiBK,UAA4BJ,IAAAA,EAAuB;AACxEC,IAAAA,MAAAA,CAAUG,KAAAA,CAAML,OAAAA,EAASK,KAAAA,EAAAA,GAAUJ,IAAAA,CAAAA;AACrC,EAAA;;;;AAKAK,EAAAA,KAAAA,CAAMN,YAAoBC,IAAAA,EAAuB;AAC/CC,IAAAA,MAAAA,CAAUI,KAAAA,CAAMN,OAAAA,EAAAA,GAAYC,IAAAA,CAAAA;AAC9B,EAAA;;;;AAKAM,EAAAA,KAAAA,CAAMP,YAAoBC,IAAAA,EAAuB;AAC/C,IAAA,IAAI,OAAA,IAAWC,MAAAA,IAAa,OAAOA,MAAAA,CAAUK,UAAU,UAAA,EAAY;AACjEL,MAAAA,MAAAA,CAAUK,KAAAA,CAAMP,OAAAA,EAAAA,GAAYC,IAAAA,CAAAA;IAC9B,CAAA,MAAO;AACLC,MAAAA,MAAAA,CAAUI,KAAAA,CAAMN,OAAAA,EAAAA,GAAYC,IAAAA,CAAAA;AAC9B,IAAA;AACF,EAAA;AACF;;;ACzBO,SAASO,sBACdC,YAAAA,EAA2B;AAQ3B,EAAA,IAAMC,QAAAA,GAAN,MAAMA,QAAAA,CAAAA;IAjDR;;;;;;AAqDI,IAAA,IAAIC,MAAAA,GAAwB;AAC1B,MAAA,OAAOF,YAAAA;AACT,IAAA;;;;;;;AAQA,IAAA,MAAMG,YAAeC,EAAAA,EAA4E;AAC/F,MAAA,OAAOJ,YAAAA,CAAaK,aAAaD,EAAAA,CAAAA;AACnC,IAAA;;;;;;AAOA,IAAA,MAAME,WAAAA,GAAgC;AACpC,MAAA,IAAI;AAEF,QAAA,IAAI,WAAA,IAAeN,YAAAA,IAAgB,OAAOA,YAAAA,CAAaO,cAAc,UAAA,EAAY;AAC/E,UAAA,MAAOP,YAAAA,CAAaO,SAAAA,CAAAA,QAAAA,CAAAA;AACtB,QAAA;AACA,QAAA,OAAO,IAAA;MACT,CAAA,CAAA,MAAQ;AACN,QAAA,OAAO,KAAA;AACT,MAAA;AACF,IAAA;AACF,GAAA;AAEA,EAAA,OAAON,QAAAA;AACT;AA9CgBF,MAAAA,CAAAA,qBAAAA,EAAAA,uBAAAA,CAAAA","file":"chunk-MWPYA2HD.js","sourcesContent":["/**\n * Logger Service - Utility class for logging\n *\n * Provides structured logging functionality.\n * Wrap this class with decorators in your microservice for DI.\n *\n * @example\n * ```typescript\n * import { Logger } from '@burdenoff/be-sdk/graphql/services';\n * import { Injectable, Scope } from 'graphql-modules';\n *\n * // In your microservice\n * @Injectable({ scope: Scope.Singleton, global: true })\n * export class LoggerProvider extends Logger {}\n * ```\n */\n\nimport { logger as sdkLogger } from '../../logger/index.js';\n\nexport class Logger {\n /**\n * Log a message at INFO level\n */\n log(message: string, ...args: unknown[]): void {\n sdkLogger.info(message, ...args);\n }\n\n /**\n * Log a message at INFO level\n */\n info(message: string, ...args: unknown[]): void {\n sdkLogger.info(message, ...args);\n }\n\n /**\n * Log a message at WARN level\n */\n warn(message: string, ...args: unknown[]): void {\n sdkLogger.warn(message, ...args);\n }\n\n /**\n * Log a message at ERROR level\n */\n error(message: string, error?: Error | unknown, ...args: unknown[]): void {\n sdkLogger.error(message, error, ...args);\n }\n\n /**\n * Log a message at DEBUG level\n */\n debug(message: string, ...args: unknown[]): void {\n sdkLogger.debug(message, ...args);\n }\n\n /**\n * Log a message at TRACE level\n */\n trace(message: string, ...args: unknown[]): void {\n if ('trace' in sdkLogger && typeof sdkLogger.trace === 'function') {\n sdkLogger.trace(message, ...args);\n } else {\n sdkLogger.debug(message, ...args);\n }\n }\n}\n","/**\n * Database Service - Utility class for database operations\n *\n * Provides access to Prisma client for database operations.\n * Each microservice creates its own Database instance with its Prisma client.\n * Wrap the returned class with decorators in your microservice for DI.\n *\n * @example\n * ```typescript\n * // In your module definition:\n * import { createDatabaseService } from '@burdenoff/be-sdk/graphql/services';\n * import { prisma } from './utils/prisma.js';\n *\n * // Create base Database class from SDK\n * const BaseDatabaseService = createDatabaseService(prisma);\n *\n * // Wrap with decorators in your microservice\n * @Injectable({ scope: Scope.Singleton, global: true })\n * class DatabaseProvider extends BaseDatabaseService {}\n *\n * export const myModule = createModule({\n * providers: [DatabaseProvider, MyProvider, ...],\n * });\n * ```\n */\n\n/**\n * Type for Prisma client transaction\n */\nexport type PrismaTransactionClient<TPrismaClient> = Omit<\n TPrismaClient,\n '$connect' | '$disconnect' | '$on' | '$transaction' | '$use' | '$extends'\n>;\n\n/**\n * Create a Database service class with the provided Prisma client\n *\n * @param prismaClient - The Prisma client instance for this microservice\n * @returns Database service class (without decorators - add them in your microservice)\n */\nexport function createDatabaseService<TPrismaClient extends { $transaction: (...args: unknown[]) => Promise<unknown> }>(\n prismaClient: TPrismaClient\n): {\n new (): {\n readonly client: TPrismaClient;\n transaction<T>(fn: (tx: PrismaTransactionClient<TPrismaClient>) => Promise<T>): Promise<T>;\n isConnected(): Promise<boolean>;\n };\n} {\n class Database {\n /**\n * Get the Prisma client instance\n */\n get client(): TPrismaClient {\n return prismaClient;\n }\n\n /**\n * Execute a transaction\n *\n * @param fn - Transaction callback function\n * @returns Promise resolving to transaction result\n */\n async transaction<T>(fn: (tx: PrismaTransactionClient<TPrismaClient>) => Promise<T>): Promise<T> {\n return prismaClient.$transaction(fn) as Promise<T>;\n }\n\n /**\n * Check if database is connected\n *\n * @returns Promise resolving to true if connected, false otherwise\n */\n async isConnected(): Promise<boolean> {\n try {\n // Use $queryRaw if available, otherwise assume connected\n if ('$queryRaw' in prismaClient && typeof prismaClient.$queryRaw === 'function') {\n await (prismaClient.$queryRaw as (query: TemplateStringsArray) => Promise<unknown>)`SELECT 1`;\n }\n return true;\n } catch {\n return false;\n }\n }\n }\n\n return Database;\n}\n\n/**\n * Type helper to extract Database service type\n */\nexport type DatabaseService<TPrismaClient extends { $transaction: (...args: unknown[]) => Promise<unknown> }> =\n InstanceType<ReturnType<typeof createDatabaseService<TPrismaClient>>>;\n"]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createCounter } from './chunk-AWPNRV3L.js';
|
|
2
|
-
import { logger } from './chunk-
|
|
2
|
+
import { logger } from './chunk-RU266375.js';
|
|
3
3
|
import { __name } from './chunk-XE4OXN2W.js';
|
|
4
4
|
import { GraphQLError } from 'graphql';
|
|
5
5
|
|
|
@@ -447,5 +447,5 @@ function __resetResourceCapsForTests() {
|
|
|
447
447
|
__name(__resetResourceCapsForTests, "__resetResourceCapsForTests");
|
|
448
448
|
|
|
449
449
|
export { RESOURCE_CAP_DEFAULTS, ResourceCapExceededError, ResourceCapsModule, __resetResourceCapsForTests, configureResourceCaps, getResourceCaps };
|
|
450
|
-
//# sourceMappingURL=chunk-
|
|
451
|
-
//# sourceMappingURL=chunk-
|
|
450
|
+
//# sourceMappingURL=chunk-MZCBEJ67.js.map
|
|
451
|
+
//# sourceMappingURL=chunk-MZCBEJ67.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/resource-caps/index.ts"],"names":["RESOURCE_CAP_DEFAULTS","workspace","free","paidDefault","scope","workspaceMember","sandbox","vibe","agent","conversation","message","tag","file","group","calendar","scheduledTask","form","apiKey","webhook","ResourceCapExceededError","GraphQLError","detail","resource","currentCount","limit","planName","extensions","code","userMessage","technicalMessage","name","PLAN_QUERY","ResourceCapsModule","client","transport","cacheTtlMs","clientlessTier","billingFailureTier","onFallback","onBillingFailure","warnedClientless","planCache","Map","planResolutionCounter","enforcementCounter","config","createCounter","configure","undefined","hasBillingSource","clear","Boolean","getResourceCap","userId","Error","defaults","plan","resolvePlan","override","overrides","planTier","isFallback","fallbackReason","enforceResourceCap","cap","inc","plan_tier","result","getWorkspaceResourceCap","workspaceId","organizationId","workspaceCacheKey","enforceWorkspaceResourceCap","invalidate","delete","invalidateWorkspace","invalidateAll","cacheKey","key","cached","get","Date","now","fetchedAt","fetchPlan","set","warnClientlessOnce","reason","fallbackPlan","planNode","fetchPlanNode","logger","warn","tier","normaliseTier","sanitizeOverrides","resourceCaps","err","data","userBillingPlan","res","query","raw","fallback","lc","toLowerCase","out","value","Object","entries","Number","isFinite","Math","max","floor","defaultInstance","getResourceCaps","configureResourceCaps","instance","__resetResourceCapsForTests"],"mappings":"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","file":"chunk-XWVP4MC6.js","sourcesContent":["/**\n * Resource Caps Module\n *\n * Enforces per-user / per-workspace resource ceilings to prevent unbounded\n * resource use on a multi-tenant SaaS. Caps come from the user's billing plan\n * (resolved via global-billing-svc) and fall back to static defaults defined\n * here when the plan lookup fails or the resource isn't overridden.\n *\n * Two plan tiers exist by default:\n * - free: tight per-user / per-workspace ceilings\n * - paid (default): ~100x looser; individual paid plans can override via the\n * `Plan.resourceCaps` JSON column in global-billing-svc.\n *\n * @example\n * ```ts\n * import { resourceCaps } from '@burdenoff/be-sdk/resource-caps';\n *\n * const { limit } = await resourceCaps.getResourceCap(userId, 'tag');\n * await resourceCaps.enforceResourceCap(userId, 'tag', currentCount);\n * ```\n */\n\nimport { GraphQLError } from 'graphql';\n\nimport type { BurdenoffGraphQLClient } from '../client/graphql.js';\nimport { createCounter } from '../instrumentation/metrics-collector.js';\nimport { logger } from '../logger/index.js';\n\n// ---------------------------------------------------------------------------\n// Resource registry\n// ---------------------------------------------------------------------------\n\n/**\n * Canonical resource names. Adding a new capped resource? Append it here,\n * extend RESOURCE_CAP_DEFAULTS, and reference it from the relevant svc.\n */\nexport type ResourceName =\n | 'workspace' // per user\n | 'workspaceMember' // per workspace\n | 'sandbox' // per user\n | 'vibe' // per user\n | 'agent' // per workspace\n | 'conversation' // per user/day\n | 'message' // per user/day\n | 'tag' // per workspace\n | 'file' // per user (count only)\n | 'group' // per workspace\n | 'calendar' // per user\n | 'scheduledTask' // per user\n | 'form' // per user\n | 'apiKey' // per user\n | 'webhook'; // per workspace\n\nexport type PlanTier = 'free' | 'paid';\n\nexport interface ResourceCapDefaults {\n free: number;\n paidDefault: number;\n /** Optional scope hint used by callers when wiring guards */\n scope: 'user' | 'workspace' | 'user/day';\n}\n\n/**\n * Static fallback caps. Real values may be overridden per plan in\n * global-billing-svc Plan.resourceCaps JSON.\n */\nexport const RESOURCE_CAP_DEFAULTS: Record<ResourceName, ResourceCapDefaults> = {\n workspace: { free: 3, paidDefault: 50, scope: 'user' },\n workspaceMember: { free: 500, paidDefault: 500, scope: 'workspace' },\n sandbox: { free: 2, paidDefault: 50, scope: 'user' },\n vibe: { free: 10, paidDefault: 500, scope: 'user' },\n agent: { free: 2, paidDefault: 20, scope: 'workspace' },\n conversation: { free: 20, paidDefault: 2000, scope: 'user/day' },\n message: { free: 200, paidDefault: 20000, scope: 'user/day' },\n tag: { free: 50, paidDefault: 5000, scope: 'workspace' },\n file: { free: 100, paidDefault: 10000, scope: 'user' },\n group: { free: 5, paidDefault: 500, scope: 'workspace' },\n calendar: { free: 3, paidDefault: 100, scope: 'user' },\n scheduledTask: { free: 5, paidDefault: 500, scope: 'user' },\n form: { free: 5, paidDefault: 500, scope: 'user' },\n apiKey: { free: 2, paidDefault: 50, scope: 'user' },\n webhook: { free: 2, paidDefault: 100, scope: 'workspace' },\n};\n\n// ---------------------------------------------------------------------------\n// Types & errors\n// ---------------------------------------------------------------------------\n\nexport interface ResourceCap {\n resource: ResourceName;\n limit: number;\n planName: string;\n planTier: PlanTier;\n /** True when the cap came from defaults, not from the billing service */\n isFallback: boolean;\n /** Why the fallback was used, when isFallback is true */\n fallbackReason?: 'clientless' | 'billing_error';\n}\n\n/**\n * Scope for workspace-scoped resource caps. The cap is derived from the plan of\n * the workspace's owning organization, not from whichever actor happens to be\n * making the request, so two members of the same workspace always see the same\n * limit (BOFF-4808).\n */\nexport interface WorkspaceResourceCapScope {\n /** Stable workspace identifier; used as the cache key. */\n workspaceId: string;\n /**\n * Organization that owns the workspace and whose billing plan determines the\n * cap. This is the `organizationId` from global-tenant-svc's Workspace type\n * (or `orgId` from wspace-workspace-svc's Workspace type).\n */\n organizationId: string;\n}\n\n/**\n * Layer-aware transport for the `userBillingPlan` lookup. Given the GraphQL\n * document + variables, returns the response `data` object (or null). Preferred\n * over `client`: the SDK bootstrap wires this to a same-layer (global) or\n * cross-layer (wspace→global) gateway call so billing is reachable from every\n * service without any per-call-site wiring (BOFF-4805).\n */\nexport type BillingPlanTransport = (query: string, variables: Record<string, unknown>) => Promise<unknown>;\n\nexport interface ResourceCapsConfig {\n client?: BurdenoffGraphQLClient;\n /** Preferred billing lookup path; see {@link BillingPlanTransport}. */\n transport?: BillingPlanTransport;\n /** Optional in-memory TTL for plan lookups; defaults to 60s */\n cacheTtlMs?: number;\n /**\n * Plan tier used when the module has no billing source (clientless). This is\n * the misconfiguration path: services should always bootstrap with a billing\n * transport. Defaults to `free` so a clientless service is visibly broken in\n * tests, while still not hard-blocking local unit tests.\n */\n clientlessTier?: PlanTier;\n /**\n * Plan tier used when a billing source is configured but the lookup fails\n * (network error, billing service down, etc.). Defaults to `paid` so a\n * transient billing outage does not silently downgrade paid customers to the\n * tightest free-tier caps (fail-open with alerting; BOFF-4805/4809).\n */\n billingFailureTier?: PlanTier;\n /**\n * Telemetry hook invoked when the module cannot reach billing (no transport /\n * client) and collapses to the clientless fallback. Wired to a metric counter\n * by observability so an unwired/broken integration is visible (BOFF-4809).\n */\n onFallback?: () => void;\n /**\n * Telemetry hook invoked when a billing source is configured but the lookup\n * fails (billing error fallback to the paid default).\n */\n onBillingFailure?: () => void;\n}\n\ninterface CachedPlan {\n planName: string;\n planTier: PlanTier;\n overrides: Partial<Record<ResourceName, number>>;\n fetchedAt: number;\n isFallback: boolean;\n fallbackReason?: 'clientless' | 'billing_error';\n}\n\n/**\n * Thrown when an entity create operation would push the user past the cap.\n * The matching GraphQL error has extensions.code = RESOURCE_CAP_EXCEEDED\n * so clients can detect and route to an upgrade flow.\n */\nexport class ResourceCapExceededError extends GraphQLError {\n constructor(detail: { resource: ResourceName; currentCount: number; limit: number; planName: string }) {\n super(\n `Resource cap exceeded for ${detail.resource}: ${detail.currentCount}/${detail.limit} on plan '${detail.planName}'.`,\n {\n extensions: {\n code: 'RESOURCE_CAP_EXCEEDED',\n userMessage: \"You've reached your plan limit. Upgrade your plan to continue.\",\n technicalMessage: `Resource cap exceeded for ${detail.resource}: ${detail.currentCount}/${detail.limit} on plan '${detail.planName}'.`,\n resource: detail.resource,\n currentCount: detail.currentCount,\n limit: detail.limit,\n planName: detail.planName,\n },\n }\n );\n this.name = 'ResourceCapExceededError';\n }\n}\n\n// ---------------------------------------------------------------------------\n// Module\n// ---------------------------------------------------------------------------\n\nconst PLAN_QUERY = /* GraphQL */ `\n query GetUserPlanForCaps($userId: ID!) {\n userBillingPlan(userId: $userId) {\n planName\n tier\n resourceCaps\n }\n }\n`;\n\ninterface PlanQueryResponse {\n userBillingPlan?: {\n planName?: string | null;\n tier?: string | null;\n resourceCaps?: Record<string, number> | null;\n } | null;\n}\n\ntype PlanNode = NonNullable<PlanQueryResponse['userBillingPlan']>;\n\nexport class ResourceCapsModule {\n private client?: BurdenoffGraphQLClient;\n private transport?: BillingPlanTransport;\n private cacheTtlMs: number;\n private clientlessTier: PlanTier;\n private billingFailureTier: PlanTier;\n private onFallback?: () => void;\n private onBillingFailure?: () => void;\n private warnedClientless = false;\n private readonly planCache = new Map<string, CachedPlan>();\n private readonly planResolutionCounter;\n private readonly enforcementCounter;\n\n constructor(config: ResourceCapsConfig = {}) {\n this.client = config.client;\n this.transport = config.transport;\n this.cacheTtlMs = config.cacheTtlMs ?? 60_000;\n this.clientlessTier = config.clientlessTier ?? 'free';\n this.billingFailureTier = config.billingFailureTier ?? 'paid';\n this.onFallback = config.onFallback;\n this.onBillingFailure = config.onBillingFailure;\n this.planResolutionCounter = createCounter(\n 'resource_caps.plan_resolution_total',\n 'Total number of billing plan resolutions for resource caps'\n );\n this.enforcementCounter = createCounter(\n 'resource_caps.enforcement_total',\n 'Total number of resource cap enforcement checks'\n );\n }\n\n /**\n * (Re)bind runtime dependencies on an already-constructed module. The SDK\n * bootstrap uses this to prime the process-wide singleton with a billing\n * transport even if an early caller already lazily created it clientless\n * (a bare `getResourceCaps(config)` ignores config once the instance exists).\n * Clears the plan cache so stale fallback entries don't linger.\n */\n configure(config: ResourceCapsConfig): void {\n if (config.client !== undefined) this.client = config.client;\n if (config.transport !== undefined) this.transport = config.transport;\n if (config.onFallback !== undefined) this.onFallback = config.onFallback;\n if (config.onBillingFailure !== undefined) this.onBillingFailure = config.onBillingFailure;\n if (typeof config.cacheTtlMs === 'number') this.cacheTtlMs = config.cacheTtlMs;\n if (config.clientlessTier) this.clientlessTier = config.clientlessTier;\n if (config.billingFailureTier) this.billingFailureTier = config.billingFailureTier;\n if (this.hasBillingSource()) this.warnedClientless = false;\n this.planCache.clear();\n }\n\n /** True when the module can actually reach billing (has a transport or client). */\n hasBillingSource(): boolean {\n return Boolean(this.transport || this.client);\n }\n\n /**\n * Resolve the cap for a given resource for the supplied user.\n * Order: plan-override → plan-tier-default → static free default.\n */\n async getResourceCap(userId: string, resource: ResourceName): Promise<ResourceCap> {\n if (!userId) {\n throw new Error('getResourceCap: userId is required');\n }\n const defaults = RESOURCE_CAP_DEFAULTS[resource];\n if (!defaults) {\n throw new Error(`getResourceCap: unknown resource '${resource}'`);\n }\n\n const plan = await this.resolvePlan(userId);\n const override = plan.overrides[resource];\n if (typeof override === 'number' && override >= 0) {\n return {\n resource,\n limit: override,\n planName: plan.planName,\n planTier: plan.planTier,\n isFallback: plan.isFallback,\n fallbackReason: plan.fallbackReason,\n };\n }\n\n const limit = plan.planTier === 'paid' ? defaults.paidDefault : defaults.free;\n return {\n resource,\n limit,\n planName: plan.planName,\n planTier: plan.planTier,\n isFallback: plan.isFallback,\n fallbackReason: plan.fallbackReason,\n };\n }\n\n /**\n * Throws ResourceCapExceededError when currentCount >= limit.\n * Use BEFORE the create transaction to avoid orphan rows.\n */\n async enforceResourceCap(userId: string, resource: ResourceName, currentCount: number): Promise<ResourceCap> {\n const cap = await this.getResourceCap(userId, resource);\n if (currentCount >= cap.limit) {\n this.enforcementCounter.inc({\n resource,\n plan_tier: cap.planTier,\n result: 'denied',\n });\n throw new ResourceCapExceededError({\n resource,\n currentCount,\n limit: cap.limit,\n planName: cap.planName,\n });\n }\n this.enforcementCounter.inc({\n resource,\n plan_tier: cap.planTier,\n result: 'allowed',\n });\n return cap;\n }\n\n /**\n * Resolve a workspace-scoped resource cap from the workspace's owner\n * organization plan, regardless of which actor triggered the action.\n *\n * @example\n * ```ts\n * const { limit } = await caps.getWorkspaceResourceCap(\n * { workspaceId: 'ws-1', organizationId: 'org-1' },\n * 'group'\n * );\n * ```\n */\n async getWorkspaceResourceCap(scope: WorkspaceResourceCapScope, resource: ResourceName): Promise<ResourceCap> {\n const { workspaceId, organizationId } = scope;\n if (!workspaceId) {\n throw new Error('getWorkspaceResourceCap: workspaceId is required');\n }\n if (!organizationId) {\n throw new Error('getWorkspaceResourceCap: organizationId is required');\n }\n const defaults = RESOURCE_CAP_DEFAULTS[resource];\n if (!defaults) {\n throw new Error(`getWorkspaceResourceCap: unknown resource '${resource}'`);\n }\n\n const plan = await this.resolvePlan(organizationId, this.workspaceCacheKey(workspaceId));\n const override = plan.overrides[resource];\n if (typeof override === 'number' && override >= 0) {\n return {\n resource,\n limit: override,\n planName: plan.planName,\n planTier: plan.planTier,\n isFallback: plan.isFallback,\n fallbackReason: plan.fallbackReason,\n };\n }\n\n const limit = plan.planTier === 'paid' ? defaults.paidDefault : defaults.free;\n return {\n resource,\n limit,\n planName: plan.planName,\n planTier: plan.planTier,\n isFallback: plan.isFallback,\n fallbackReason: plan.fallbackReason,\n };\n }\n\n /**\n * Throws ResourceCapExceededError when currentCount >= limit for a\n * workspace-scoped resource. The cap is resolved from the workspace owner's\n * organization plan, so the answer is stable across members.\n */\n async enforceWorkspaceResourceCap(\n scope: WorkspaceResourceCapScope,\n resource: ResourceName,\n currentCount: number\n ): Promise<ResourceCap> {\n const cap = await this.getWorkspaceResourceCap(scope, resource);\n if (currentCount >= cap.limit) {\n this.enforcementCounter.inc({\n resource,\n plan_tier: cap.planTier,\n result: 'denied',\n });\n throw new ResourceCapExceededError({\n resource,\n currentCount,\n limit: cap.limit,\n planName: cap.planName,\n });\n }\n this.enforcementCounter.inc({\n resource,\n plan_tier: cap.planTier,\n result: 'allowed',\n });\n return cap;\n }\n\n /** Invalidate cache for a user (e.g. after plan upgrade) */\n invalidate(userId: string): void {\n this.planCache.delete(userId);\n }\n\n /** Invalidate cache for a workspace (e.g. after workspace plan change) */\n invalidateWorkspace(workspaceId: string): void {\n this.planCache.delete(this.workspaceCacheKey(workspaceId));\n }\n\n /** Clear entire plan cache */\n invalidateAll(): void {\n this.planCache.clear();\n }\n\n // -------------------------------------------------------------------------\n // Internals\n // -------------------------------------------------------------------------\n\n private workspaceCacheKey(workspaceId: string): string {\n return `workspace:${workspaceId}`;\n }\n\n private async resolvePlan(userId: string, cacheKey?: string): Promise<CachedPlan> {\n const key = cacheKey ?? userId;\n const cached = this.planCache.get(key);\n if (cached && Date.now() - cached.fetchedAt < this.cacheTtlMs) {\n return cached;\n }\n\n const plan = await this.fetchPlan(userId);\n this.planCache.set(key, plan);\n return plan;\n }\n\n private async fetchPlan(userId: string): Promise<CachedPlan> {\n // No billing source wired → every cap silently collapses to the configured\n // clientless tier. Warn loudly (once) so an unwired/broken integration\n // can't hide in prod (BOFF-4805/4809).\n if (!this.hasBillingSource()) {\n this.warnClientlessOnce();\n this.planResolutionCounter.inc({ result: 'fallback', reason: 'clientless' });\n return this.fallbackPlan(this.clientlessTier, 'clientless');\n }\n try {\n const planNode = await this.fetchPlanNode(userId);\n if (!planNode) {\n logger.warn('resource-caps: plan lookup returned null; falling back to paid defaults', {\n userId,\n });\n this.onBillingFailure?.();\n this.planResolutionCounter.inc({ result: 'fallback', reason: 'billing_error' });\n return this.fallbackPlan(this.billingFailureTier, 'billing_error');\n }\n const tier = normaliseTier(planNode.tier, this.billingFailureTier);\n const overrides = sanitizeOverrides(planNode.resourceCaps);\n this.planResolutionCounter.inc({ result: 'billing' });\n return {\n planName: planNode.planName ?? (tier === 'paid' ? 'paid' : 'free'),\n planTier: tier,\n overrides,\n fetchedAt: Date.now(),\n isFallback: false,\n };\n } catch (err) {\n logger.warn('resource-caps: plan lookup failed; falling back to paid defaults', {\n err,\n userId,\n });\n this.onBillingFailure?.();\n this.planResolutionCounter.inc({ result: 'fallback', reason: 'billing_error' });\n return this.fallbackPlan(this.billingFailureTier, 'billing_error');\n }\n }\n\n /**\n * Resolve the raw `userBillingPlan` node via the injected transport (preferred)\n * or the legacy direct client. Guarded by {@link hasBillingSource} in the\n * caller, so at least one path is present here.\n */\n private async fetchPlanNode(userId: string): Promise<PlanNode | null> {\n if (this.transport) {\n const data = (await this.transport(PLAN_QUERY, { userId })) as PlanQueryResponse | null | undefined;\n return data?.userBillingPlan ?? null;\n }\n if (this.client) {\n const res = await this.client.query<PlanQueryResponse>(PLAN_QUERY, { userId });\n return res?.userBillingPlan ?? null;\n }\n return null;\n }\n\n private warnClientlessOnce(): void {\n if (this.warnedClientless) return;\n this.warnedClientless = true;\n logger.warn(\n 'resource-caps: running WITHOUT a billing transport/client — every resource cap will use the ' +\n 'free-tier fallback regardless of the customer plan. Ensure initializeBurdenoffSDK() ran with a ' +\n 'layer/gateway configured (BOFF-4805).'\n );\n this.onFallback?.();\n }\n\n private fallbackPlan(tier: PlanTier, reason: 'clientless' | 'billing_error'): CachedPlan {\n return {\n planName: tier === 'paid' ? 'fallback-paid' : 'fallback-free',\n planTier: tier,\n overrides: {},\n fetchedAt: Date.now(),\n isFallback: true,\n fallbackReason: reason,\n };\n }\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction normaliseTier(raw: string | null | undefined, fallback: PlanTier): PlanTier {\n if (!raw) return fallback;\n const lc = raw.toLowerCase();\n if (lc === 'free' || lc === 'paid') return lc;\n // Treat anything non-free as paid (enterprise, business, pro, etc.)\n if (lc === 'enterprise' || lc === 'business' || lc === 'pro' || lc === 'team') {\n return 'paid';\n }\n return fallback;\n}\n\nfunction sanitizeOverrides(raw: Record<string, number> | null | undefined): Partial<Record<ResourceName, number>> {\n if (!raw || typeof raw !== 'object') return {};\n const out: Partial<Record<ResourceName, number>> = {};\n for (const [key, value] of Object.entries(raw)) {\n if (key in RESOURCE_CAP_DEFAULTS && typeof value === 'number' && Number.isFinite(value)) {\n out[key as ResourceName] = Math.max(0, Math.floor(value));\n }\n }\n return out;\n}\n\n// ---------------------------------------------------------------------------\n// Convenience singleton\n// ---------------------------------------------------------------------------\n\nlet defaultInstance: ResourceCapsModule | null = null;\n\n/**\n * Obtain a process-wide singleton. The first call binds the GraphQL client\n * (typically the SDK's internal client). Later calls return the same instance.\n */\nexport function getResourceCaps(config?: ResourceCapsConfig): ResourceCapsModule {\n if (!defaultInstance) {\n defaultInstance = new ResourceCapsModule(config);\n } else if (config) {\n // Previously the config was silently dropped once the singleton existed —\n // the root cause of BOFF-4805 where the billing client could never be bound\n // after a lazy first construction. Apply it instead.\n defaultInstance.configure(config);\n }\n return defaultInstance;\n}\n\n/**\n * Prime/rebind the process-wide singleton with billing connectivity. Call once\n * during SDK bootstrap. Unlike a bare `getResourceCaps(config)` on a fresh\n * process, this is explicit about the intent to (re)wire and is safe to call\n * after the singleton was already lazily created clientless.\n */\nexport function configureResourceCaps(config: ResourceCapsConfig): ResourceCapsModule {\n const instance = getResourceCaps();\n instance.configure(config);\n return instance;\n}\n\n/** Reset the singleton (for tests) */\nexport function __resetResourceCapsForTests(): void {\n defaultInstance = null;\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/resource-caps/index.ts"],"names":["RESOURCE_CAP_DEFAULTS","workspace","free","paidDefault","scope","workspaceMember","sandbox","vibe","agent","conversation","message","tag","file","group","calendar","scheduledTask","form","apiKey","webhook","ResourceCapExceededError","GraphQLError","detail","resource","currentCount","limit","planName","extensions","code","userMessage","technicalMessage","name","PLAN_QUERY","ResourceCapsModule","client","transport","cacheTtlMs","clientlessTier","billingFailureTier","onFallback","onBillingFailure","warnedClientless","planCache","Map","planResolutionCounter","enforcementCounter","config","createCounter","configure","undefined","hasBillingSource","clear","Boolean","getResourceCap","userId","Error","defaults","plan","resolvePlan","override","overrides","planTier","isFallback","fallbackReason","enforceResourceCap","cap","inc","plan_tier","result","getWorkspaceResourceCap","workspaceId","organizationId","workspaceCacheKey","enforceWorkspaceResourceCap","invalidate","delete","invalidateWorkspace","invalidateAll","cacheKey","key","cached","get","Date","now","fetchedAt","fetchPlan","set","warnClientlessOnce","reason","fallbackPlan","planNode","fetchPlanNode","logger","warn","tier","normaliseTier","sanitizeOverrides","resourceCaps","err","data","userBillingPlan","res","query","raw","fallback","lc","toLowerCase","out","value","Object","entries","Number","isFinite","Math","max","floor","defaultInstance","getResourceCaps","configureResourceCaps","instance","__resetResourceCapsForTests"],"mappings":";;;;;AAkEO,IAAMA,qBAAAA,GAAmE;EAC9EC,SAAAA,EAAW;IAAEC,IAAAA,EAAM,CAAA;IAAGC,WAAAA,EAAa,EAAA;IAAIC,KAAAA,EAAO;AAAO,GAAA;EACrDC,eAAAA,EAAiB;IAAEH,IAAAA,EAAM,GAAA;IAAKC,WAAAA,EAAa,GAAA;IAAKC,KAAAA,EAAO;AAAY,GAAA;EACnEE,OAAAA,EAAS;IAAEJ,IAAAA,EAAM,CAAA;IAAGC,WAAAA,EAAa,EAAA;IAAIC,KAAAA,EAAO;AAAO,GAAA;EACnDG,IAAAA,EAAM;IAAEL,IAAAA,EAAM,EAAA;IAAIC,WAAAA,EAAa,GAAA;IAAKC,KAAAA,EAAO;AAAO,GAAA;EAClDI,KAAAA,EAAO;IAAEN,IAAAA,EAAM,CAAA;IAAGC,WAAAA,EAAa,EAAA;IAAIC,KAAAA,EAAO;AAAY,GAAA;EACtDK,YAAAA,EAAc;IAAEP,IAAAA,EAAM,EAAA;IAAIC,WAAAA,EAAa,GAAA;IAAMC,KAAAA,EAAO;AAAW,GAAA;EAC/DM,OAAAA,EAAS;IAAER,IAAAA,EAAM,GAAA;IAAKC,WAAAA,EAAa,GAAA;IAAOC,KAAAA,EAAO;AAAW,GAAA;EAC5DO,GAAAA,EAAK;IAAET,IAAAA,EAAM,EAAA;IAAIC,WAAAA,EAAa,GAAA;IAAMC,KAAAA,EAAO;AAAY,GAAA;EACvDQ,IAAAA,EAAM;IAAEV,IAAAA,EAAM,GAAA;IAAKC,WAAAA,EAAa,GAAA;IAAOC,KAAAA,EAAO;AAAO,GAAA;EACrDS,KAAAA,EAAO;IAAEX,IAAAA,EAAM,CAAA;IAAGC,WAAAA,EAAa,GAAA;IAAKC,KAAAA,EAAO;AAAY,GAAA;EACvDU,QAAAA,EAAU;IAAEZ,IAAAA,EAAM,CAAA;IAAGC,WAAAA,EAAa,GAAA;IAAKC,KAAAA,EAAO;AAAO,GAAA;EACrDW,aAAAA,EAAe;IAAEb,IAAAA,EAAM,CAAA;IAAGC,WAAAA,EAAa,GAAA;IAAKC,KAAAA,EAAO;AAAO,GAAA;EAC1DY,IAAAA,EAAM;IAAEd,IAAAA,EAAM,CAAA;IAAGC,WAAAA,EAAa,GAAA;IAAKC,KAAAA,EAAO;AAAO,GAAA;EACjDa,MAAAA,EAAQ;IAAEf,IAAAA,EAAM,CAAA;IAAGC,WAAAA,EAAa,EAAA;IAAIC,KAAAA,EAAO;AAAO,GAAA;EAClDc,OAAAA,EAAS;IAAEhB,IAAAA,EAAM,CAAA;IAAGC,WAAAA,EAAa,GAAA;IAAKC,KAAAA,EAAO;AAAY;AAC3D;AA0FO,IAAMe,wBAAAA,GAAN,cAAuCC,YAAAA,CAAAA;EA5K9C;;;AA6KE,EAAA,WAAA,CAAYC,MAAAA,EAA2F;AACrG,IAAA,KAAA,CACE,CAAA,0BAAA,EAA6BA,MAAAA,CAAOC,QAAQ,CAAA,EAAA,EAAKD,MAAAA,CAAOE,YAAY,CAAA,CAAA,EAAIF,MAAAA,CAAOG,KAAK,CAAA,UAAA,EAAaH,MAAAA,CAAOI,QAAQ,CAAA,EAAA,CAAA,EAChH;MACEC,UAAAA,EAAY;QACVC,IAAAA,EAAM,uBAAA;QACNC,WAAAA,EAAa,gEAAA;QACbC,gBAAAA,EAAkB,CAAA,0BAAA,EAA6BR,MAAAA,CAAOC,QAAQ,CAAA,EAAA,EAAKD,MAAAA,CAAOE,YAAY,CAAA,CAAA,EAAIF,MAAAA,CAAOG,KAAK,CAAA,UAAA,EAAaH,MAAAA,CAAOI,QAAQ,CAAA,EAAA,CAAA;AAClIH,QAAAA,QAAAA,EAAUD,MAAAA,CAAOC,QAAAA;AACjBC,QAAAA,YAAAA,EAAcF,MAAAA,CAAOE,YAAAA;AACrBC,QAAAA,KAAAA,EAAOH,MAAAA,CAAOG,KAAAA;AACdC,QAAAA,QAAAA,EAAUJ,MAAAA,CAAOI;AACnB;KACF,CAAA;AAEF,IAAA,IAAA,CAAKK,IAAAA,GAAO,0BAAA;AACd,EAAA;AACF;AAMA,IAAMC,UAAAA;;AAA2B,EAAA;;;;;;;;;;AAoB1B,IAAMC,qBAAN,MAAMA;EAxNb;;;AAyNUC,EAAAA,MAAAA;AACAC,EAAAA,SAAAA;AACAC,EAAAA,UAAAA;AACAC,EAAAA,cAAAA;AACAC,EAAAA,kBAAAA;AACAC,EAAAA,UAAAA;AACAC,EAAAA,gBAAAA;EACAC,gBAAAA,GAAmB,KAAA;AACVC,EAAAA,SAAAA,uBAAgBC,GAAAA,EAAAA;AAChBC,EAAAA,qBAAAA;AACAC,EAAAA,kBAAAA;EAEjB,WAAA,CAAYC,MAAAA,GAA6B,EAAC,EAAG;AAC3C,IAAA,IAAA,CAAKZ,SAASY,MAAAA,CAAOZ,MAAAA;AACrB,IAAA,IAAA,CAAKC,YAAYW,MAAAA,CAAOX,SAAAA;AACxB,IAAA,IAAA,CAAKC,UAAAA,GAAaU,OAAOV,UAAAA,IAAc,GAAA;AACvC,IAAA,IAAA,CAAKC,cAAAA,GAAiBS,OAAOT,cAAAA,IAAkB,MAAA;AAC/C,IAAA,IAAA,CAAKC,kBAAAA,GAAqBQ,OAAOR,kBAAAA,IAAsB,MAAA;AACvD,IAAA,IAAA,CAAKC,aAAaO,MAAAA,CAAOP,UAAAA;AACzB,IAAA,IAAA,CAAKC,mBAAmBM,MAAAA,CAAON,gBAAAA;AAC/B,IAAA,IAAA,CAAKI,qBAAAA,GAAwBG,aAAAA,CAC3B,qCAAA,EACA,4DAAA,CAAA;AAEF,IAAA,IAAA,CAAKF,kBAAAA,GAAqBE,aAAAA,CACxB,iCAAA,EACA,iDAAA,CAAA;AAEJ,EAAA;;;;;;;;AASAC,EAAAA,SAAAA,CAAUF,MAAAA,EAAkC;AAC1C,IAAA,IAAIA,MAAAA,CAAOZ,MAAAA,KAAWe,MAAAA,EAAW,IAAA,CAAKf,SAASY,MAAAA,CAAOZ,MAAAA;AACtD,IAAA,IAAIY,MAAAA,CAAOX,SAAAA,KAAcc,MAAAA,EAAW,IAAA,CAAKd,YAAYW,MAAAA,CAAOX,SAAAA;AAC5D,IAAA,IAAIW,MAAAA,CAAOP,UAAAA,KAAeU,MAAAA,EAAW,IAAA,CAAKV,aAAaO,MAAAA,CAAOP,UAAAA;AAC9D,IAAA,IAAIO,MAAAA,CAAON,gBAAAA,KAAqBS,MAAAA,EAAW,IAAA,CAAKT,mBAAmBM,MAAAA,CAAON,gBAAAA;AAC1E,IAAA,IAAI,OAAOM,MAAAA,CAAOV,UAAAA,KAAe,QAAA,EAAU,IAAA,CAAKA,aAAaU,MAAAA,CAAOV,UAAAA;AACpE,IAAA,IAAIU,MAAAA,CAAOT,cAAAA,EAAgB,IAAA,CAAKA,cAAAA,GAAiBS,MAAAA,CAAOT,cAAAA;AACxD,IAAA,IAAIS,MAAAA,CAAOR,kBAAAA,EAAoB,IAAA,CAAKA,kBAAAA,GAAqBQ,MAAAA,CAAOR,kBAAAA;AAChE,IAAA,IAAI,IAAA,CAAKY,gBAAAA,EAAgB,EAAI,IAAA,CAAKT,gBAAAA,GAAmB,KAAA;AACrD,IAAA,IAAA,CAAKC,UAAUS,KAAAA,EAAK;AACtB,EAAA;;EAGAD,gBAAAA,GAA4B;AAC1B,IAAA,OAAOE,OAAAA,CAAQ,IAAA,CAAKjB,SAAAA,IAAa,IAAA,CAAKD,MAAM,CAAA;AAC9C,EAAA;;;;;EAMA,MAAMmB,cAAAA,CAAeC,QAAgB/B,QAAAA,EAA8C;AACjF,IAAA,IAAI,CAAC+B,MAAAA,EAAQ;AACX,MAAA,MAAM,IAAIC,MAAM,oCAAA,CAAA;AAClB,IAAA;AACA,IAAA,MAAMC,QAAAA,GAAWvD,sBAAsBsB,QAAAA,CAAAA;AACvC,IAAA,IAAI,CAACiC,QAAAA,EAAU;AACb,MAAA,MAAM,IAAID,KAAAA,CAAM,CAAA,kCAAA,EAAqChC,QAAAA,CAAAA,CAAAA,CAAW,CAAA;AAClE,IAAA;AAEA,IAAA,MAAMkC,IAAAA,GAAO,MAAM,IAAA,CAAKC,WAAAA,CAAYJ,MAAAA,CAAAA;AACpC,IAAA,MAAMK,QAAAA,GAAWF,IAAAA,CAAKG,SAAAA,CAAUrC,QAAAA,CAAAA;AAChC,IAAA,IAAI,OAAOoC,QAAAA,KAAa,QAAA,IAAYA,QAAAA,IAAY,CAAA,EAAG;AACjD,MAAA,OAAO;AACLpC,QAAAA,QAAAA;QACAE,KAAAA,EAAOkC,QAAAA;AACPjC,QAAAA,QAAAA,EAAU+B,IAAAA,CAAK/B,QAAAA;AACfmC,QAAAA,QAAAA,EAAUJ,IAAAA,CAAKI,QAAAA;AACfC,QAAAA,UAAAA,EAAYL,IAAAA,CAAKK,UAAAA;AACjBC,QAAAA,cAAAA,EAAgBN,IAAAA,CAAKM;AACvB,OAAA;AACF,IAAA;AAEA,IAAA,MAAMtC,QAAQgC,IAAAA,CAAKI,QAAAA,KAAa,MAAA,GAASL,QAAAA,CAASpD,cAAcoD,QAAAA,CAASrD,IAAAA;AACzE,IAAA,OAAO;AACLoB,MAAAA,QAAAA;AACAE,MAAAA,KAAAA;AACAC,MAAAA,QAAAA,EAAU+B,IAAAA,CAAK/B,QAAAA;AACfmC,MAAAA,QAAAA,EAAUJ,IAAAA,CAAKI,QAAAA;AACfC,MAAAA,UAAAA,EAAYL,IAAAA,CAAKK,UAAAA;AACjBC,MAAAA,cAAAA,EAAgBN,IAAAA,CAAKM;AACvB,KAAA;AACF,EAAA;;;;;EAMA,MAAMC,kBAAAA,CAAmBV,MAAAA,EAAgB/B,QAAAA,EAAwBC,YAAAA,EAA4C;AAC3G,IAAA,MAAMyC,GAAAA,GAAM,MAAM,IAAA,CAAKZ,cAAAA,CAAeC,QAAQ/B,QAAAA,CAAAA;AAC9C,IAAA,IAAIC,YAAAA,IAAgByC,IAAIxC,KAAAA,EAAO;AAC7B,MAAA,IAAA,CAAKoB,mBAAmBqB,GAAAA,CAAI;AAC1B3C,QAAAA,QAAAA;AACA4C,QAAAA,SAAAA,EAAWF,GAAAA,CAAIJ,QAAAA;QACfO,MAAAA,EAAQ;OACV,CAAA;AACA,MAAA,MAAM,IAAIhD,wBAAAA,CAAyB;AACjCG,QAAAA,QAAAA;AACAC,QAAAA,YAAAA;AACAC,QAAAA,KAAAA,EAAOwC,GAAAA,CAAIxC,KAAAA;AACXC,QAAAA,QAAAA,EAAUuC,GAAAA,CAAIvC;OAChB,CAAA;AACF,IAAA;AACA,IAAA,IAAA,CAAKmB,mBAAmBqB,GAAAA,CAAI;AAC1B3C,MAAAA,QAAAA;AACA4C,MAAAA,SAAAA,EAAWF,GAAAA,CAAIJ,QAAAA;MACfO,MAAAA,EAAQ;KACV,CAAA;AACA,IAAA,OAAOH,GAAAA;AACT,EAAA;;;;;;;;;;;;;EAcA,MAAMI,uBAAAA,CAAwBhE,OAAkCkB,QAAAA,EAA8C;AAC5G,IAAA,MAAM,EAAE+C,WAAAA,EAAaC,cAAAA,EAAc,GAAKlE,KAAAA;AACxC,IAAA,IAAI,CAACiE,WAAAA,EAAa;AAChB,MAAA,MAAM,IAAIf,MAAM,kDAAA,CAAA;AAClB,IAAA;AACA,IAAA,IAAI,CAACgB,cAAAA,EAAgB;AACnB,MAAA,MAAM,IAAIhB,MAAM,qDAAA,CAAA;AAClB,IAAA;AACA,IAAA,MAAMC,QAAAA,GAAWvD,sBAAsBsB,QAAAA,CAAAA;AACvC,IAAA,IAAI,CAACiC,QAAAA,EAAU;AACb,MAAA,MAAM,IAAID,KAAAA,CAAM,CAAA,2CAAA,EAA8ChC,QAAAA,CAAAA,CAAAA,CAAW,CAAA;AAC3E,IAAA;AAEA,IAAA,MAAMkC,IAAAA,GAAO,MAAM,IAAA,CAAKC,WAAAA,CAAYa,gBAAgB,IAAA,CAAKC,iBAAAA,CAAkBF,WAAAA,CAAAA,CAAAA;AAC3E,IAAA,MAAMX,QAAAA,GAAWF,IAAAA,CAAKG,SAAAA,CAAUrC,QAAAA,CAAAA;AAChC,IAAA,IAAI,OAAOoC,QAAAA,KAAa,QAAA,IAAYA,QAAAA,IAAY,CAAA,EAAG;AACjD,MAAA,OAAO;AACLpC,QAAAA,QAAAA;QACAE,KAAAA,EAAOkC,QAAAA;AACPjC,QAAAA,QAAAA,EAAU+B,IAAAA,CAAK/B,QAAAA;AACfmC,QAAAA,QAAAA,EAAUJ,IAAAA,CAAKI,QAAAA;AACfC,QAAAA,UAAAA,EAAYL,IAAAA,CAAKK,UAAAA;AACjBC,QAAAA,cAAAA,EAAgBN,IAAAA,CAAKM;AACvB,OAAA;AACF,IAAA;AAEA,IAAA,MAAMtC,QAAQgC,IAAAA,CAAKI,QAAAA,KAAa,MAAA,GAASL,QAAAA,CAASpD,cAAcoD,QAAAA,CAASrD,IAAAA;AACzE,IAAA,OAAO;AACLoB,MAAAA,QAAAA;AACAE,MAAAA,KAAAA;AACAC,MAAAA,QAAAA,EAAU+B,IAAAA,CAAK/B,QAAAA;AACfmC,MAAAA,QAAAA,EAAUJ,IAAAA,CAAKI,QAAAA;AACfC,MAAAA,UAAAA,EAAYL,IAAAA,CAAKK,UAAAA;AACjBC,MAAAA,cAAAA,EAAgBN,IAAAA,CAAKM;AACvB,KAAA;AACF,EAAA;;;;;;EAOA,MAAMU,2BAAAA,CACJpE,KAAAA,EACAkB,QAAAA,EACAC,YAAAA,EACsB;AACtB,IAAA,MAAMyC,GAAAA,GAAM,MAAM,IAAA,CAAKI,uBAAAA,CAAwBhE,OAAOkB,QAAAA,CAAAA;AACtD,IAAA,IAAIC,YAAAA,IAAgByC,IAAIxC,KAAAA,EAAO;AAC7B,MAAA,IAAA,CAAKoB,mBAAmBqB,GAAAA,CAAI;AAC1B3C,QAAAA,QAAAA;AACA4C,QAAAA,SAAAA,EAAWF,GAAAA,CAAIJ,QAAAA;QACfO,MAAAA,EAAQ;OACV,CAAA;AACA,MAAA,MAAM,IAAIhD,wBAAAA,CAAyB;AACjCG,QAAAA,QAAAA;AACAC,QAAAA,YAAAA;AACAC,QAAAA,KAAAA,EAAOwC,GAAAA,CAAIxC,KAAAA;AACXC,QAAAA,QAAAA,EAAUuC,GAAAA,CAAIvC;OAChB,CAAA;AACF,IAAA;AACA,IAAA,IAAA,CAAKmB,mBAAmBqB,GAAAA,CAAI;AAC1B3C,MAAAA,QAAAA;AACA4C,MAAAA,SAAAA,EAAWF,GAAAA,CAAIJ,QAAAA;MACfO,MAAAA,EAAQ;KACV,CAAA;AACA,IAAA,OAAOH,GAAAA;AACT,EAAA;;AAGAS,EAAAA,UAAAA,CAAWpB,MAAAA,EAAsB;AAC/B,IAAA,IAAA,CAAKZ,SAAAA,CAAUiC,OAAOrB,MAAAA,CAAAA;AACxB,EAAA;;AAGAsB,EAAAA,mBAAAA,CAAoBN,WAAAA,EAA2B;AAC7C,IAAA,IAAA,CAAK5B,SAAAA,CAAUiC,MAAAA,CAAO,IAAA,CAAKH,iBAAAA,CAAkBF,WAAAA,CAAAA,CAAAA;AAC/C,EAAA;;EAGAO,aAAAA,GAAsB;AACpB,IAAA,IAAA,CAAKnC,UAAUS,KAAAA,EAAK;AACtB,EAAA;;;;AAMQqB,EAAAA,iBAAAA,CAAkBF,WAAAA,EAA6B;AACrD,IAAA,OAAO,aAAaA,WAAAA,CAAAA,CAAAA;AACtB,EAAA;EAEA,MAAcZ,WAAAA,CAAYJ,QAAgBwB,QAAAA,EAAwC;AAChF,IAAA,MAAMC,MAAMD,QAAAA,IAAYxB,MAAAA;AACxB,IAAA,MAAM0B,MAAAA,GAAS,IAAA,CAAKtC,SAAAA,CAAUuC,GAAAA,CAAIF,GAAAA,CAAAA;AAClC,IAAA,IAAIC,UAAUE,IAAAA,CAAKC,GAAAA,KAAQH,MAAAA,CAAOI,SAAAA,GAAY,KAAKhD,UAAAA,EAAY;AAC7D,MAAA,OAAO4C,MAAAA;AACT,IAAA;AAEA,IAAA,MAAMvB,IAAAA,GAAO,MAAM,IAAA,CAAK4B,SAAAA,CAAU/B,MAAAA,CAAAA;AAClC,IAAA,IAAA,CAAKZ,SAAAA,CAAU4C,GAAAA,CAAIP,GAAAA,EAAKtB,IAAAA,CAAAA;AACxB,IAAA,OAAOA,IAAAA;AACT,EAAA;AAEA,EAAA,MAAc4B,UAAU/B,MAAAA,EAAqC;AAI3D,IAAA,IAAI,CAAC,IAAA,CAAKJ,gBAAAA,EAAgB,EAAI;AAC5B,MAAA,IAAA,CAAKqC,kBAAAA,EAAkB;AACvB,MAAA,IAAA,CAAK3C,sBAAsBsB,GAAAA,CAAI;QAAEE,MAAAA,EAAQ,UAAA;QAAYoB,MAAAA,EAAQ;OAAa,CAAA;AAC1E,MAAA,OAAO,IAAA,CAAKC,YAAAA,CAAa,IAAA,CAAKpD,cAAAA,EAAgB,YAAA,CAAA;AAChD,IAAA;AACA,IAAA,IAAI;AACF,MAAA,MAAMqD,QAAAA,GAAW,MAAM,IAAA,CAAKC,aAAAA,CAAcrC,MAAAA,CAAAA;AAC1C,MAAA,IAAI,CAACoC,QAAAA,EAAU;AACbE,QAAAA,MAAAA,CAAOC,KAAK,yEAAA,EAA2E;AACrFvC,UAAAA;SACF,CAAA;AACA,QAAA,IAAA,CAAKd,gBAAAA,IAAgB;AACrB,QAAA,IAAA,CAAKI,sBAAsBsB,GAAAA,CAAI;UAAEE,MAAAA,EAAQ,UAAA;UAAYoB,MAAAA,EAAQ;SAAgB,CAAA;AAC7E,QAAA,OAAO,IAAA,CAAKC,YAAAA,CAAa,IAAA,CAAKnD,kBAAAA,EAAoB,eAAA,CAAA;AACpD,MAAA;AACA,MAAA,MAAMwD,IAAAA,GAAOC,aAAAA,CAAcL,QAAAA,CAASI,IAAAA,EAAM,KAAKxD,kBAAkB,CAAA;AACjE,MAAA,MAAMsB,SAAAA,GAAYoC,iBAAAA,CAAkBN,QAAAA,CAASO,YAAY,CAAA;AACzD,MAAA,IAAA,CAAKrD,sBAAsBsB,GAAAA,CAAI;QAAEE,MAAAA,EAAQ;OAAU,CAAA;AACnD,MAAA,OAAO;AACL1C,QAAAA,QAAAA,EAAUgE,QAAAA,CAAShE,QAAAA,KAAaoE,IAAAA,KAAS,MAAA,GAAS,MAAA,GAAS,MAAA,CAAA;QAC3DjC,QAAAA,EAAUiC,IAAAA;AACVlC,QAAAA,SAAAA;AACAwB,QAAAA,SAAAA,EAAWF,KAAKC,GAAAA,EAAG;QACnBrB,UAAAA,EAAY;AACd,OAAA;AACF,IAAA,CAAA,CAAA,OAASoC,GAAAA,EAAK;AACZN,MAAAA,MAAAA,CAAOC,KAAK,kEAAA,EAAoE;AAC9EK,QAAAA,GAAAA;AACA5C,QAAAA;OACF,CAAA;AACA,MAAA,IAAA,CAAKd,gBAAAA,IAAgB;AACrB,MAAA,IAAA,CAAKI,sBAAsBsB,GAAAA,CAAI;QAAEE,MAAAA,EAAQ,UAAA;QAAYoB,MAAAA,EAAQ;OAAgB,CAAA;AAC7E,MAAA,OAAO,IAAA,CAAKC,YAAAA,CAAa,IAAA,CAAKnD,kBAAAA,EAAoB,eAAA,CAAA;AACpD,IAAA;AACF,EAAA;;;;;;AAOA,EAAA,MAAcqD,cAAcrC,MAAAA,EAA0C;AACpE,IAAA,IAAI,KAAKnB,SAAAA,EAAW;AAClB,MAAA,MAAMgE,IAAAA,GAAQ,MAAM,IAAA,CAAKhE,SAAAA,CAAUH,UAAAA,EAAY;AAAEsB,QAAAA;OAAO,CAAA;AACxD,MAAA,OAAO6C,MAAMC,eAAAA,IAAmB,IAAA;AAClC,IAAA;AACA,IAAA,IAAI,KAAKlE,MAAAA,EAAQ;AACf,MAAA,MAAMmE,GAAAA,GAAM,MAAM,IAAA,CAAKnE,MAAAA,CAAOoE,MAAyBtE,UAAAA,EAAY;AAAEsB,QAAAA;OAAO,CAAA;AAC5E,MAAA,OAAO+C,KAAKD,eAAAA,IAAmB,IAAA;AACjC,IAAA;AACA,IAAA,OAAO,IAAA;AACT,EAAA;EAEQb,kBAAAA,GAA2B;AACjC,IAAA,IAAI,KAAK9C,gBAAAA,EAAkB;AAC3B,IAAA,IAAA,CAAKA,gBAAAA,GAAmB,IAAA;AACxBmD,IAAAA,MAAAA,CAAOC,KACL,uOAEE,CAAA;AAEJ,IAAA,IAAA,CAAKtD,UAAAA,IAAU;AACjB,EAAA;AAEQkD,EAAAA,YAAAA,CAAaK,MAAgBN,MAAAA,EAAoD;AACvF,IAAA,OAAO;MACL9D,QAAAA,EAAUoE,IAAAA,KAAS,SAAS,eAAA,GAAkB,eAAA;MAC9CjC,QAAAA,EAAUiC,IAAAA;AACVlC,MAAAA,SAAAA,EAAW,EAAC;AACZwB,MAAAA,SAAAA,EAAWF,KAAKC,GAAAA,EAAG;MACnBrB,UAAAA,EAAY,IAAA;MACZC,cAAAA,EAAgByB;AAClB,KAAA;AACF,EAAA;AACF;AAMA,SAASO,aAAAA,CAAcQ,KAAgCC,QAAAA,EAAkB;AACvE,EAAA,IAAI,CAACD,KAAK,OAAOC,QAAAA;AACjB,EAAA,MAAMC,EAAAA,GAAKF,IAAIG,WAAAA,EAAW;AAC1B,EAAA,IAAID,EAAAA,KAAO,MAAA,IAAUA,EAAAA,KAAO,MAAA,EAAQ,OAAOA,EAAAA;AAE3C,EAAA,IAAIA,OAAO,YAAA,IAAgBA,EAAAA,KAAO,cAAcA,EAAAA,KAAO,KAAA,IAASA,OAAO,MAAA,EAAQ;AAC7E,IAAA,OAAO,MAAA;AACT,EAAA;AACA,EAAA,OAAOD,QAAAA;AACT;AATST,MAAAA,CAAAA,aAAAA,EAAAA,eAAAA,CAAAA;AAWT,SAASC,kBAAkBO,GAAAA,EAA8C;AACvE,EAAA,IAAI,CAACA,GAAAA,IAAO,OAAOA,GAAAA,KAAQ,QAAA,SAAiB,EAAC;AAC7C,EAAA,MAAMI,MAA6C,EAAC;AACpD,EAAA,KAAA,MAAW,CAAC5B,GAAAA,EAAK6B,KAAAA,KAAUC,MAAAA,CAAOC,OAAAA,CAAQP,GAAAA,CAAAA,EAAM;AAC9C,IAAA,IAAIxB,GAAAA,IAAO9E,yBAAyB,OAAO2G,KAAAA,KAAU,YAAYG,MAAAA,CAAOC,QAAAA,CAASJ,KAAAA,CAAAA,EAAQ;AACvFD,MAAAA,GAAAA,CAAI5B,GAAAA,IAAuBkC,IAAAA,CAAKC,GAAAA,CAAI,GAAGD,IAAAA,CAAKE,KAAAA,CAAMP,KAAAA,CAAAA,CAAAA;AACpD,IAAA;AACF,EAAA;AACA,EAAA,OAAOD,GAAAA;AACT;AATSX,MAAAA,CAAAA,iBAAAA,EAAAA,mBAAAA,CAAAA;AAeT,IAAIoB,eAAAA,GAA6C,IAAA;AAM1C,SAASC,gBAAgBvE,MAAAA,EAA2B;AACzD,EAAA,IAAI,CAACsE,eAAAA,EAAiB;AACpBA,IAAAA,eAAAA,GAAkB,IAAInF,mBAAmBa,MAAAA,CAAAA;AAC3C,EAAA,CAAA,MAAA,IAAWA,MAAAA,EAAQ;AAIjBsE,IAAAA,eAAAA,CAAgBpE,UAAUF,MAAAA,CAAAA;AAC5B,EAAA;AACA,EAAA,OAAOsE,eAAAA;AACT;AAVgBC,MAAAA,CAAAA,eAAAA,EAAAA,iBAAAA,CAAAA;AAkBT,SAASC,sBAAsBxE,MAAAA,EAA0B;AAC9D,EAAA,MAAMyE,WAAWF,eAAAA,EAAAA;AACjBE,EAAAA,QAAAA,CAASvE,UAAUF,MAAAA,CAAAA;AACnB,EAAA,OAAOyE,QAAAA;AACT;AAJgBD,MAAAA,CAAAA,qBAAAA,EAAAA,uBAAAA,CAAAA;AAOT,SAASE,2BAAAA,GAAAA;AACdJ,EAAAA,eAAAA,GAAkB,IAAA;AACpB;AAFgBI,MAAAA,CAAAA,2BAAAA,EAAAA,6BAAAA,CAAAA","file":"chunk-MZCBEJ67.js","sourcesContent":["/**\n * Resource Caps Module\n *\n * Enforces per-user / per-workspace resource ceilings to prevent unbounded\n * resource use on a multi-tenant SaaS. Caps come from the user's billing plan\n * (resolved via global-billing-svc) and fall back to static defaults defined\n * here when the plan lookup fails or the resource isn't overridden.\n *\n * Two plan tiers exist by default:\n * - free: tight per-user / per-workspace ceilings\n * - paid (default): ~100x looser; individual paid plans can override via the\n * `Plan.resourceCaps` JSON column in global-billing-svc.\n *\n * @example\n * ```ts\n * import { resourceCaps } from '@burdenoff/be-sdk/resource-caps';\n *\n * const { limit } = await resourceCaps.getResourceCap(userId, 'tag');\n * await resourceCaps.enforceResourceCap(userId, 'tag', currentCount);\n * ```\n */\n\nimport { GraphQLError } from 'graphql';\n\nimport type { BurdenoffGraphQLClient } from '../client/graphql.js';\nimport { createCounter } from '../instrumentation/metrics-collector.js';\nimport { logger } from '../logger/index.js';\n\n// ---------------------------------------------------------------------------\n// Resource registry\n// ---------------------------------------------------------------------------\n\n/**\n * Canonical resource names. Adding a new capped resource? Append it here,\n * extend RESOURCE_CAP_DEFAULTS, and reference it from the relevant svc.\n */\nexport type ResourceName =\n | 'workspace' // per user\n | 'workspaceMember' // per workspace\n | 'sandbox' // per user\n | 'vibe' // per user\n | 'agent' // per workspace\n | 'conversation' // per user/day\n | 'message' // per user/day\n | 'tag' // per workspace\n | 'file' // per user (count only)\n | 'group' // per workspace\n | 'calendar' // per user\n | 'scheduledTask' // per user\n | 'form' // per user\n | 'apiKey' // per user\n | 'webhook'; // per workspace\n\nexport type PlanTier = 'free' | 'paid';\n\nexport interface ResourceCapDefaults {\n free: number;\n paidDefault: number;\n /** Optional scope hint used by callers when wiring guards */\n scope: 'user' | 'workspace' | 'user/day';\n}\n\n/**\n * Static fallback caps. Real values may be overridden per plan in\n * global-billing-svc Plan.resourceCaps JSON.\n */\nexport const RESOURCE_CAP_DEFAULTS: Record<ResourceName, ResourceCapDefaults> = {\n workspace: { free: 3, paidDefault: 50, scope: 'user' },\n workspaceMember: { free: 500, paidDefault: 500, scope: 'workspace' },\n sandbox: { free: 2, paidDefault: 50, scope: 'user' },\n vibe: { free: 10, paidDefault: 500, scope: 'user' },\n agent: { free: 2, paidDefault: 20, scope: 'workspace' },\n conversation: { free: 20, paidDefault: 2000, scope: 'user/day' },\n message: { free: 200, paidDefault: 20000, scope: 'user/day' },\n tag: { free: 50, paidDefault: 5000, scope: 'workspace' },\n file: { free: 100, paidDefault: 10000, scope: 'user' },\n group: { free: 5, paidDefault: 500, scope: 'workspace' },\n calendar: { free: 3, paidDefault: 100, scope: 'user' },\n scheduledTask: { free: 5, paidDefault: 500, scope: 'user' },\n form: { free: 5, paidDefault: 500, scope: 'user' },\n apiKey: { free: 2, paidDefault: 50, scope: 'user' },\n webhook: { free: 2, paidDefault: 100, scope: 'workspace' },\n};\n\n// ---------------------------------------------------------------------------\n// Types & errors\n// ---------------------------------------------------------------------------\n\nexport interface ResourceCap {\n resource: ResourceName;\n limit: number;\n planName: string;\n planTier: PlanTier;\n /** True when the cap came from defaults, not from the billing service */\n isFallback: boolean;\n /** Why the fallback was used, when isFallback is true */\n fallbackReason?: 'clientless' | 'billing_error';\n}\n\n/**\n * Scope for workspace-scoped resource caps. The cap is derived from the plan of\n * the workspace's owning organization, not from whichever actor happens to be\n * making the request, so two members of the same workspace always see the same\n * limit (BOFF-4808).\n */\nexport interface WorkspaceResourceCapScope {\n /** Stable workspace identifier; used as the cache key. */\n workspaceId: string;\n /**\n * Organization that owns the workspace and whose billing plan determines the\n * cap. This is the `organizationId` from global-tenant-svc's Workspace type\n * (or `orgId` from wspace-workspace-svc's Workspace type).\n */\n organizationId: string;\n}\n\n/**\n * Layer-aware transport for the `userBillingPlan` lookup. Given the GraphQL\n * document + variables, returns the response `data` object (or null). Preferred\n * over `client`: the SDK bootstrap wires this to a same-layer (global) or\n * cross-layer (wspace→global) gateway call so billing is reachable from every\n * service without any per-call-site wiring (BOFF-4805).\n */\nexport type BillingPlanTransport = (query: string, variables: Record<string, unknown>) => Promise<unknown>;\n\nexport interface ResourceCapsConfig {\n client?: BurdenoffGraphQLClient;\n /** Preferred billing lookup path; see {@link BillingPlanTransport}. */\n transport?: BillingPlanTransport;\n /** Optional in-memory TTL for plan lookups; defaults to 60s */\n cacheTtlMs?: number;\n /**\n * Plan tier used when the module has no billing source (clientless). This is\n * the misconfiguration path: services should always bootstrap with a billing\n * transport. Defaults to `free` so a clientless service is visibly broken in\n * tests, while still not hard-blocking local unit tests.\n */\n clientlessTier?: PlanTier;\n /**\n * Plan tier used when a billing source is configured but the lookup fails\n * (network error, billing service down, etc.). Defaults to `paid` so a\n * transient billing outage does not silently downgrade paid customers to the\n * tightest free-tier caps (fail-open with alerting; BOFF-4805/4809).\n */\n billingFailureTier?: PlanTier;\n /**\n * Telemetry hook invoked when the module cannot reach billing (no transport /\n * client) and collapses to the clientless fallback. Wired to a metric counter\n * by observability so an unwired/broken integration is visible (BOFF-4809).\n */\n onFallback?: () => void;\n /**\n * Telemetry hook invoked when a billing source is configured but the lookup\n * fails (billing error fallback to the paid default).\n */\n onBillingFailure?: () => void;\n}\n\ninterface CachedPlan {\n planName: string;\n planTier: PlanTier;\n overrides: Partial<Record<ResourceName, number>>;\n fetchedAt: number;\n isFallback: boolean;\n fallbackReason?: 'clientless' | 'billing_error';\n}\n\n/**\n * Thrown when an entity create operation would push the user past the cap.\n * The matching GraphQL error has extensions.code = RESOURCE_CAP_EXCEEDED\n * so clients can detect and route to an upgrade flow.\n */\nexport class ResourceCapExceededError extends GraphQLError {\n constructor(detail: { resource: ResourceName; currentCount: number; limit: number; planName: string }) {\n super(\n `Resource cap exceeded for ${detail.resource}: ${detail.currentCount}/${detail.limit} on plan '${detail.planName}'.`,\n {\n extensions: {\n code: 'RESOURCE_CAP_EXCEEDED',\n userMessage: \"You've reached your plan limit. Upgrade your plan to continue.\",\n technicalMessage: `Resource cap exceeded for ${detail.resource}: ${detail.currentCount}/${detail.limit} on plan '${detail.planName}'.`,\n resource: detail.resource,\n currentCount: detail.currentCount,\n limit: detail.limit,\n planName: detail.planName,\n },\n }\n );\n this.name = 'ResourceCapExceededError';\n }\n}\n\n// ---------------------------------------------------------------------------\n// Module\n// ---------------------------------------------------------------------------\n\nconst PLAN_QUERY = /* GraphQL */ `\n query GetUserPlanForCaps($userId: ID!) {\n userBillingPlan(userId: $userId) {\n planName\n tier\n resourceCaps\n }\n }\n`;\n\ninterface PlanQueryResponse {\n userBillingPlan?: {\n planName?: string | null;\n tier?: string | null;\n resourceCaps?: Record<string, number> | null;\n } | null;\n}\n\ntype PlanNode = NonNullable<PlanQueryResponse['userBillingPlan']>;\n\nexport class ResourceCapsModule {\n private client?: BurdenoffGraphQLClient;\n private transport?: BillingPlanTransport;\n private cacheTtlMs: number;\n private clientlessTier: PlanTier;\n private billingFailureTier: PlanTier;\n private onFallback?: () => void;\n private onBillingFailure?: () => void;\n private warnedClientless = false;\n private readonly planCache = new Map<string, CachedPlan>();\n private readonly planResolutionCounter;\n private readonly enforcementCounter;\n\n constructor(config: ResourceCapsConfig = {}) {\n this.client = config.client;\n this.transport = config.transport;\n this.cacheTtlMs = config.cacheTtlMs ?? 60_000;\n this.clientlessTier = config.clientlessTier ?? 'free';\n this.billingFailureTier = config.billingFailureTier ?? 'paid';\n this.onFallback = config.onFallback;\n this.onBillingFailure = config.onBillingFailure;\n this.planResolutionCounter = createCounter(\n 'resource_caps.plan_resolution_total',\n 'Total number of billing plan resolutions for resource caps'\n );\n this.enforcementCounter = createCounter(\n 'resource_caps.enforcement_total',\n 'Total number of resource cap enforcement checks'\n );\n }\n\n /**\n * (Re)bind runtime dependencies on an already-constructed module. The SDK\n * bootstrap uses this to prime the process-wide singleton with a billing\n * transport even if an early caller already lazily created it clientless\n * (a bare `getResourceCaps(config)` ignores config once the instance exists).\n * Clears the plan cache so stale fallback entries don't linger.\n */\n configure(config: ResourceCapsConfig): void {\n if (config.client !== undefined) this.client = config.client;\n if (config.transport !== undefined) this.transport = config.transport;\n if (config.onFallback !== undefined) this.onFallback = config.onFallback;\n if (config.onBillingFailure !== undefined) this.onBillingFailure = config.onBillingFailure;\n if (typeof config.cacheTtlMs === 'number') this.cacheTtlMs = config.cacheTtlMs;\n if (config.clientlessTier) this.clientlessTier = config.clientlessTier;\n if (config.billingFailureTier) this.billingFailureTier = config.billingFailureTier;\n if (this.hasBillingSource()) this.warnedClientless = false;\n this.planCache.clear();\n }\n\n /** True when the module can actually reach billing (has a transport or client). */\n hasBillingSource(): boolean {\n return Boolean(this.transport || this.client);\n }\n\n /**\n * Resolve the cap for a given resource for the supplied user.\n * Order: plan-override → plan-tier-default → static free default.\n */\n async getResourceCap(userId: string, resource: ResourceName): Promise<ResourceCap> {\n if (!userId) {\n throw new Error('getResourceCap: userId is required');\n }\n const defaults = RESOURCE_CAP_DEFAULTS[resource];\n if (!defaults) {\n throw new Error(`getResourceCap: unknown resource '${resource}'`);\n }\n\n const plan = await this.resolvePlan(userId);\n const override = plan.overrides[resource];\n if (typeof override === 'number' && override >= 0) {\n return {\n resource,\n limit: override,\n planName: plan.planName,\n planTier: plan.planTier,\n isFallback: plan.isFallback,\n fallbackReason: plan.fallbackReason,\n };\n }\n\n const limit = plan.planTier === 'paid' ? defaults.paidDefault : defaults.free;\n return {\n resource,\n limit,\n planName: plan.planName,\n planTier: plan.planTier,\n isFallback: plan.isFallback,\n fallbackReason: plan.fallbackReason,\n };\n }\n\n /**\n * Throws ResourceCapExceededError when currentCount >= limit.\n * Use BEFORE the create transaction to avoid orphan rows.\n */\n async enforceResourceCap(userId: string, resource: ResourceName, currentCount: number): Promise<ResourceCap> {\n const cap = await this.getResourceCap(userId, resource);\n if (currentCount >= cap.limit) {\n this.enforcementCounter.inc({\n resource,\n plan_tier: cap.planTier,\n result: 'denied',\n });\n throw new ResourceCapExceededError({\n resource,\n currentCount,\n limit: cap.limit,\n planName: cap.planName,\n });\n }\n this.enforcementCounter.inc({\n resource,\n plan_tier: cap.planTier,\n result: 'allowed',\n });\n return cap;\n }\n\n /**\n * Resolve a workspace-scoped resource cap from the workspace's owner\n * organization plan, regardless of which actor triggered the action.\n *\n * @example\n * ```ts\n * const { limit } = await caps.getWorkspaceResourceCap(\n * { workspaceId: 'ws-1', organizationId: 'org-1' },\n * 'group'\n * );\n * ```\n */\n async getWorkspaceResourceCap(scope: WorkspaceResourceCapScope, resource: ResourceName): Promise<ResourceCap> {\n const { workspaceId, organizationId } = scope;\n if (!workspaceId) {\n throw new Error('getWorkspaceResourceCap: workspaceId is required');\n }\n if (!organizationId) {\n throw new Error('getWorkspaceResourceCap: organizationId is required');\n }\n const defaults = RESOURCE_CAP_DEFAULTS[resource];\n if (!defaults) {\n throw new Error(`getWorkspaceResourceCap: unknown resource '${resource}'`);\n }\n\n const plan = await this.resolvePlan(organizationId, this.workspaceCacheKey(workspaceId));\n const override = plan.overrides[resource];\n if (typeof override === 'number' && override >= 0) {\n return {\n resource,\n limit: override,\n planName: plan.planName,\n planTier: plan.planTier,\n isFallback: plan.isFallback,\n fallbackReason: plan.fallbackReason,\n };\n }\n\n const limit = plan.planTier === 'paid' ? defaults.paidDefault : defaults.free;\n return {\n resource,\n limit,\n planName: plan.planName,\n planTier: plan.planTier,\n isFallback: plan.isFallback,\n fallbackReason: plan.fallbackReason,\n };\n }\n\n /**\n * Throws ResourceCapExceededError when currentCount >= limit for a\n * workspace-scoped resource. The cap is resolved from the workspace owner's\n * organization plan, so the answer is stable across members.\n */\n async enforceWorkspaceResourceCap(\n scope: WorkspaceResourceCapScope,\n resource: ResourceName,\n currentCount: number\n ): Promise<ResourceCap> {\n const cap = await this.getWorkspaceResourceCap(scope, resource);\n if (currentCount >= cap.limit) {\n this.enforcementCounter.inc({\n resource,\n plan_tier: cap.planTier,\n result: 'denied',\n });\n throw new ResourceCapExceededError({\n resource,\n currentCount,\n limit: cap.limit,\n planName: cap.planName,\n });\n }\n this.enforcementCounter.inc({\n resource,\n plan_tier: cap.planTier,\n result: 'allowed',\n });\n return cap;\n }\n\n /** Invalidate cache for a user (e.g. after plan upgrade) */\n invalidate(userId: string): void {\n this.planCache.delete(userId);\n }\n\n /** Invalidate cache for a workspace (e.g. after workspace plan change) */\n invalidateWorkspace(workspaceId: string): void {\n this.planCache.delete(this.workspaceCacheKey(workspaceId));\n }\n\n /** Clear entire plan cache */\n invalidateAll(): void {\n this.planCache.clear();\n }\n\n // -------------------------------------------------------------------------\n // Internals\n // -------------------------------------------------------------------------\n\n private workspaceCacheKey(workspaceId: string): string {\n return `workspace:${workspaceId}`;\n }\n\n private async resolvePlan(userId: string, cacheKey?: string): Promise<CachedPlan> {\n const key = cacheKey ?? userId;\n const cached = this.planCache.get(key);\n if (cached && Date.now() - cached.fetchedAt < this.cacheTtlMs) {\n return cached;\n }\n\n const plan = await this.fetchPlan(userId);\n this.planCache.set(key, plan);\n return plan;\n }\n\n private async fetchPlan(userId: string): Promise<CachedPlan> {\n // No billing source wired → every cap silently collapses to the configured\n // clientless tier. Warn loudly (once) so an unwired/broken integration\n // can't hide in prod (BOFF-4805/4809).\n if (!this.hasBillingSource()) {\n this.warnClientlessOnce();\n this.planResolutionCounter.inc({ result: 'fallback', reason: 'clientless' });\n return this.fallbackPlan(this.clientlessTier, 'clientless');\n }\n try {\n const planNode = await this.fetchPlanNode(userId);\n if (!planNode) {\n logger.warn('resource-caps: plan lookup returned null; falling back to paid defaults', {\n userId,\n });\n this.onBillingFailure?.();\n this.planResolutionCounter.inc({ result: 'fallback', reason: 'billing_error' });\n return this.fallbackPlan(this.billingFailureTier, 'billing_error');\n }\n const tier = normaliseTier(planNode.tier, this.billingFailureTier);\n const overrides = sanitizeOverrides(planNode.resourceCaps);\n this.planResolutionCounter.inc({ result: 'billing' });\n return {\n planName: planNode.planName ?? (tier === 'paid' ? 'paid' : 'free'),\n planTier: tier,\n overrides,\n fetchedAt: Date.now(),\n isFallback: false,\n };\n } catch (err) {\n logger.warn('resource-caps: plan lookup failed; falling back to paid defaults', {\n err,\n userId,\n });\n this.onBillingFailure?.();\n this.planResolutionCounter.inc({ result: 'fallback', reason: 'billing_error' });\n return this.fallbackPlan(this.billingFailureTier, 'billing_error');\n }\n }\n\n /**\n * Resolve the raw `userBillingPlan` node via the injected transport (preferred)\n * or the legacy direct client. Guarded by {@link hasBillingSource} in the\n * caller, so at least one path is present here.\n */\n private async fetchPlanNode(userId: string): Promise<PlanNode | null> {\n if (this.transport) {\n const data = (await this.transport(PLAN_QUERY, { userId })) as PlanQueryResponse | null | undefined;\n return data?.userBillingPlan ?? null;\n }\n if (this.client) {\n const res = await this.client.query<PlanQueryResponse>(PLAN_QUERY, { userId });\n return res?.userBillingPlan ?? null;\n }\n return null;\n }\n\n private warnClientlessOnce(): void {\n if (this.warnedClientless) return;\n this.warnedClientless = true;\n logger.warn(\n 'resource-caps: running WITHOUT a billing transport/client — every resource cap will use the ' +\n 'free-tier fallback regardless of the customer plan. Ensure initializeBurdenoffSDK() ran with a ' +\n 'layer/gateway configured (BOFF-4805).'\n );\n this.onFallback?.();\n }\n\n private fallbackPlan(tier: PlanTier, reason: 'clientless' | 'billing_error'): CachedPlan {\n return {\n planName: tier === 'paid' ? 'fallback-paid' : 'fallback-free',\n planTier: tier,\n overrides: {},\n fetchedAt: Date.now(),\n isFallback: true,\n fallbackReason: reason,\n };\n }\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction normaliseTier(raw: string | null | undefined, fallback: PlanTier): PlanTier {\n if (!raw) return fallback;\n const lc = raw.toLowerCase();\n if (lc === 'free' || lc === 'paid') return lc;\n // Treat anything non-free as paid (enterprise, business, pro, etc.)\n if (lc === 'enterprise' || lc === 'business' || lc === 'pro' || lc === 'team') {\n return 'paid';\n }\n return fallback;\n}\n\nfunction sanitizeOverrides(raw: Record<string, number> | null | undefined): Partial<Record<ResourceName, number>> {\n if (!raw || typeof raw !== 'object') return {};\n const out: Partial<Record<ResourceName, number>> = {};\n for (const [key, value] of Object.entries(raw)) {\n if (key in RESOURCE_CAP_DEFAULTS && typeof value === 'number' && Number.isFinite(value)) {\n out[key as ResourceName] = Math.max(0, Math.floor(value));\n }\n }\n return out;\n}\n\n// ---------------------------------------------------------------------------\n// Convenience singleton\n// ---------------------------------------------------------------------------\n\nlet defaultInstance: ResourceCapsModule | null = null;\n\n/**\n * Obtain a process-wide singleton. The first call binds the GraphQL client\n * (typically the SDK's internal client). Later calls return the same instance.\n */\nexport function getResourceCaps(config?: ResourceCapsConfig): ResourceCapsModule {\n if (!defaultInstance) {\n defaultInstance = new ResourceCapsModule(config);\n } else if (config) {\n // Previously the config was silently dropped once the singleton existed —\n // the root cause of BOFF-4805 where the billing client could never be bound\n // after a lazy first construction. Apply it instead.\n defaultInstance.configure(config);\n }\n return defaultInstance;\n}\n\n/**\n * Prime/rebind the process-wide singleton with billing connectivity. Call once\n * during SDK bootstrap. Unlike a bare `getResourceCaps(config)` on a fresh\n * process, this is explicit about the intent to (re)wire and is safe to call\n * after the singleton was already lazily created clientless.\n */\nexport function configureResourceCaps(config: ResourceCapsConfig): ResourceCapsModule {\n const instance = getResourceCaps();\n instance.configure(config);\n return instance;\n}\n\n/** Reset the singleton (for tests) */\nexport function __resetResourceCapsForTests(): void {\n defaultInstance = null;\n}\n"]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { EventQueueFactory, QueueType } from './chunk-
|
|
2
|
-
import { logger } from './chunk-
|
|
1
|
+
import { EventQueueFactory, QueueType } from './chunk-UFXHLQ2T.js';
|
|
2
|
+
import { logger } from './chunk-RU266375.js';
|
|
3
3
|
import { __name } from './chunk-XE4OXN2W.js';
|
|
4
4
|
import { randomUUID } from 'crypto';
|
|
5
5
|
|
|
@@ -599,5 +599,5 @@ async function resetGraphEventEmitter() {
|
|
|
599
599
|
__name(resetGraphEventEmitter, "resetGraphEventEmitter");
|
|
600
600
|
|
|
601
601
|
export { GraphEventEmitterImpl, MemoryEventBus, MemoryEventConsumer, MemoryEventPublisher, MemoryEventQueue, createGraphEventEmitter, createGraphEventEmitter2, createMemoryConsumer, createMemoryPublisher, getGraphEventEmitter, resetGraphEventEmitter };
|
|
602
|
-
//# sourceMappingURL=chunk-
|
|
603
|
-
//# sourceMappingURL=chunk-
|
|
602
|
+
//# sourceMappingURL=chunk-QJN4K7LD.js.map
|
|
603
|
+
//# sourceMappingURL=chunk-QJN4K7LD.js.map
|