@lpdjs/firestore-repo-service 2.2.6 → 2.2.8
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/{create-servers-DmggzSb3.d.cts → create-servers-BGtAS0oG.d.cts} +3 -3
- package/dist/{create-servers-D4-NGpKm.d.ts → create-servers-DMszgNtg.d.ts} +3 -3
- package/dist/history/index.cjs +2 -0
- package/dist/history/index.cjs.map +1 -0
- package/dist/history/index.d.cts +126 -0
- package/dist/history/index.d.ts +126 -0
- package/dist/history/index.js +2 -0
- package/dist/history/index.js.map +1 -0
- package/dist/{index-Cvip2Sgt.d.ts → index-BSZP0Gz9.d.ts} +3 -3
- package/dist/{index-DpD4DEqH.d.cts → index-D7oj3Pft.d.cts} +3 -3
- package/dist/index.cjs +120 -102
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +21 -12
- package/dist/index.d.ts +21 -12
- package/dist/index.js +120 -102
- package/dist/index.js.map +1 -1
- package/dist/{openapi-B3P2F8op.d.ts → openapi-BdqIkSjO.d.ts} +1 -1
- package/dist/{openapi-UJJ1aCFk.d.cts → openapi-lY43PZXy.d.cts} +1 -1
- package/dist/read-DfXXxhO4.d.cts +230 -0
- package/dist/read-DfXXxhO4.d.ts +230 -0
- package/dist/servers/admin/index.cjs +31 -13
- package/dist/servers/admin/index.cjs.map +1 -1
- package/dist/servers/admin/index.d.cts +4 -2
- package/dist/servers/admin/index.d.ts +4 -2
- package/dist/servers/admin/index.js +31 -13
- package/dist/servers/admin/index.js.map +1 -1
- package/dist/servers/crud/index.d.cts +6 -4
- package/dist/servers/crud/index.d.ts +6 -4
- package/dist/servers/index.cjs +33 -15
- package/dist/servers/index.cjs.map +1 -1
- package/dist/servers/index.d.cts +6 -5
- package/dist/servers/index.d.ts +6 -5
- package/dist/servers/index.js +33 -15
- package/dist/servers/index.js.map +1 -1
- package/dist/{types-Z9Qy8Xmx.d.ts → types-BESS89Fu.d.cts} +30 -12
- package/dist/{types-Z9Qy8Xmx.d.cts → types-BVUFVcpl.d.ts} +30 -12
- package/package.json +17 -1
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/shared/zod-compat.ts","../src/servers/admin/components/cell-value.tsx","../src/servers/admin/components/type-check.ts","../src/servers/admin/components/right-panel.tsx","../src/query-builder.ts","../src/shared/date-config.ts","../src/shared/utils.ts","../src/pagination.ts","../src/methods/aggregate.ts","../src/methods/batch.ts","../src/methods/bulk.ts","../src/methods/crud.ts","../src/methods/get.ts","../src/methods/query.ts","../src/methods/relations.ts","../src/methods/transaction.ts","../src/repositories/factory.ts","../src/servers/admin/router.ts","../src/sync/schema-mapper.ts","../src/sync/constants.ts","../src/sync/serializer.ts","../src/sync/admin.ts","../src/sync/triggers.ts","../src/sync/queue.ts","../src/sync/worker.ts","../src/sync/create-sync.ts","../src/servers/admin/handlers.ts","../src/servers/admin/form-gen.ts","../src/servers/admin/components/index.ts","../src/servers/admin/components/client-script.raw.js","../src/servers/admin/components/client-script.tsx","../src/servers/admin/components/shell.tsx","../src/servers/admin/components/dashboard.tsx","../src/servers/admin/components/filter-bar.tsx","../src/servers/admin/components/form.tsx","../src/servers/admin/components/list.tsx","../src/servers/admin/renderer.ts","../src/servers/admin/index-url.ts","../src/servers/admin/index.ts","../src/servers/crud/handlers.ts","../src/servers/crud/openapi.ts","../src/servers/crud/index.ts","../src/servers/create-servers.ts","../src/index.ts"],"names":["getTypeName","schema","s","v4Type","TYPE_MAP","v3Type","getInnerType","getArrayElementType","getDefaultValue","v","getShape","getEnumValues","getNativeEnumValues","getLiteralValue","getStringChecks","kinds","v4Checks","c","v3Checks","init_zod_compat","__esmMin","CellDate","val","jsx","TypeMismatchBadge","message","CellValue","mismatch","inner","renderInner","jsxs","item","i","entries","k","Fragment","str","init_cell_value","expectedTypeOf","unwrap","tn","resolveAtPath","path","segments","cur","seg","actualTypeOf","mismatchMessage","expected","actual","init_type_check","right_panel_exports","__export","PanelMany","PanelOne","RightPanel","doc","repoName","basePath","columns","id","editUrl","expectedTypes","buildExpectedMap","docs","fk","fv","pagination","fullViewUrl","d","ri","ci","out","init_right_panel","chunkArray","array","size","chunks","applyBasicQueryOptions","q","options","o","f","needsSplitting","clause","operator","value","splitWhereClause","field","chunk","applyWhereClausesToQuery","baseQuery","whereClauses","executeAndMergeQueries","queries","snapshots","docsMap","snapshot","firstSnapshot","buildAndExecuteQuery","hasOrWhere","hasOrWhereGroups","splitClauses","cartesianProduct","combination","baseClauses","rawGroups","allQueries","orGroup","fullGroup","groupQueries","arrays","first","rest","restProduct","result","combo","currentMode","setDateHandling","mode","getDateHandling","isTimestampLike","coerceToDate","Timestamp","isPlainObject","proto","normalizeTimestamps","maybeNormalize","capitalize","applyQueryOptions","executePaginatedQuery","queryOptions","hasMore","actualDocs","data","isPrev","createPaginationIterator","cursor","createAggregateMethods","collectionRef","total","count","createBatchMethods","db","documentRef","documentKey","pathKey","createdKey","updatedKey","now","batch","args","lastArg","hasOptions","pathArgs","mergeOption","docRef","enrichedData","docIdValue","createBulkMethods","items","bulkWriter","pendingOps","merge","docRefs","createCrudMethods","actualCollection","docId","dataWithPath","updates","createdDoc","setDocument","updatedDoc","createGetMethods","foreignKeys","getMethods","key","values","results","foreignKey","methodName","opts","createQueryMethods","queryKeys","relationalKeys","allRepositories","queryMethods","populateDocuments","documents","includeConfigs","normalizedConfigs","cfg","select","relation","targetRepo","fieldValue","method","err","populated","queryKey","mergedOptions","onNext","onError","include","paginationOptions","populatedData","page","createPopulateMethods","config","document","relationKeyOrOptions","keys","selectMap","selectFields","createTransactionMethods","updateFunction","rawTransaction","docSnap","extractParentKeys","refCb","match","params","p","createRepository","aggregateMethods","crudMethods","batchMethods","transactionMethods","bulkMethods","populateMethods","compilePath","paramNames","src","_match","name","extractPath","req","raw","idx","MiniRouter","_req","res","middleware","handler","pattern","matchedRoute","route","m","enrichedReq","finalHandler","index","next","mw","SYNC_VERSION_COLUMN","WRAPPER_TYPES","current","nullable","LOGICAL_MAP","flattenSchema","shape","dialect","prefix","parentNullable","excludeSet","columnMap","primaryKey","fieldSchema","fullKey","typeName","isNullable","nestedShape","logical","isPK","colName","zodSchemaToColumns","exclude","serializeValue","geo","flattenObject","obj","flatKey","serializeDocument","flat","topLevel","column","getLinkBase","base","project","region","target","service","host","title","linkBase","body","sendHtml","html","status","sendJson","isJsonRequest","createadminsyncServer","repoMapping","adapter","queues","handleMessage","repoConfigs","pubsub","topicPrefix","features","repoInfos","repo","repoCfg","router","realm","lb","rows","r","links","queueLink","configCheckLink","info","expectedCols","actualCols","tableExists","error","e","actualSet","expectedSet","missing","extra","matched","isHealthy","statusBadge","colRows","extraRows","collRef","synced","errors","errorSamples","batchSize","query","lastDoc","serialized","msg","queue","errorBlock","queueData","consoleBase","tPrefix","checks","msgLower","isApiDisabled","isPermission","isProjectNotFound","isNotFound","exists","topicName","topic","allOk","statusIcon","grouped","renderSection","fixHtml","parts","overallBadge","DEFAULT_TOPIC_PREFIX","buildDocumentPath","collectionPath","createSyncTriggers","onDocumentCreated","onDocumentUpdated","onDocumentDeleted","triggers","topicCache","getTopic","t","publish","syncEvent","documentPath","event","snap","SyncQueue","interval","events","upsertsById","deleteIds","evt","existing","a","upserts","handlerErr","migratedRepos","ensureMigrated","tableName","newCols","createSyncWorker","deps","flushIntervalMs","autoMigrate","workerOptions","getQueue","onFlushError","dlTopicName","dlTopic","dlErr","createHandler","handlerFn","promises","lazyProxy","factory","instance","_","prop","createFirestoreSync","rawAdapter","adminConfig","worker","handlers","adminHandler","toLabel","required","defaultValue","zodToFields","namePrefix","fieldName","zodFieldToDescriptor","rawName","label","isEmail","isUrl","enumObj","nested","elSchema","elInner","elTn","arrayElementType","arrayElementOptions","arrayElementFields","renderField","depth","indent","nameAttr","requiredAttr","isNullValue","defaultStr","nullToggle","input","sel3","renderArrayField","subFields","isObject","itemsHtml","renderObjectItem","renderPrimitiveItem","templateHtml","strVal","inputHtml","renderForm","fields","action","submitLabel","fieldsHtml","client_script_raw_default","ClientScript","renderHtml","element","renderToString","THEMES","ThemeSwitcher","PageShell","children","breadcrumb","flash","renderPageJsx","content","renderDashboardJsx","repos","OPS_TEXT","OPS_NUMERIC","OPS_ARRAY","opsForType","zodType","NULL_SENTINEL","nullToggleScript","inputId","enumChecklistScript","hiddenId","group","NullToggle","active","FilterValueInput","col","isNull","op","isMultiOp","selected","isAny","FilterBar","columnMeta","activeFilters","isGroup","activeMap","hasActive","needsIndexHint","filterable","ops","currentOp","renderFormPageJsx","formHtml","crumbs","baseParams","filters","sort","pageSize","paginationHref","dir","sortHref","pageSizeHref","newPs","renderListJsx","allowDelete","relationalMeta","sortState","currentPageSize","queryError","totalCount","mutableFields","listUrl","createUrl","scalarMutable","canBulkUpdate","canBulkDelete","showSelection","bulkFieldsMeta","sub","meta","ps","isSorted","arrow","rowIdx","deleteUrl","mi","rawVal","fallbackHref","renderPage","renderDashboard","renderList","renderFormPage","RANGE_OPS","ARRAY_OPS","toIndexOrder","collectionIdFromPath","buildIndexUrl","projectId","collectionId","seen","buildExemptionUrl","lastDir","buildCompositeUrl","databaseId","resource","payload","pbString","pbInt","pbMessage","encodeIndexField","urlDbId","encoded","toBase64","extractIndexUrl","pbVarint","n","pbTag","fieldNumber","wireType","bytes","bin","b64","extractProjectId","ref","candidates","isMissingIndexError","fe","toQueryError","ctx","isIndex","indexUrl","colId","_idChars","generateFirestoreId","extractPathArgs","fullPath","fetchDocById","entry","docKey","getMethod","flashFromDocFetchError","qe","redirect","to","parseFormBody","zodField","resolveTypeName","subRaw","hasDotKeys","innerSchema","itn","toDatetimeLocal","date","pad","resolveInnerSchema","isFieldNullable","extractEnumValues","vals","prefillFromDoc","innerTn","dtLocal","applyPrefill","prefilled","parseFilters","validFields","validOps","opRaw","filtersToWhere","coerce","arr","buildColumnMeta","fullName","subShape","resolveZodAtPath","part","getMutableSchema","dotGroups","dot","parent","child","picked","z","staticBasePath","createAdminHandlers","registry","handleDashboard","handleList","cursorStr","sortField","sortDir","psRaw","allColumns","filterableColumns","resolved","whereFilters","cursorSnapshot","colRef","isError","nextCursorId","prevCursorId","handleCreateForm","createSchema","actionUrl","handleCreateSubmit","rawBody","parsed","validation","errorMsg","missingKeys","parentIds","createSchema2","handleEditForm","mutableSchema","handleEditSubmit","mutableSchema2","handleDelete","handlePanel","type","coerceFilterValue","resolveRefs","ids","refs","resolveAllIds","where","handleBulkDelete","collectTargetIds","handleBulkUpdate","parsedValue","sanitizeFilters","x","readRawBody","parseUrlEncoded","pair","createAdminServer","parseBody","auth","extraMiddleware","httpsOptions","resolvedSchema","filterableFields","createFields","fc","roles","role","parentKeys","pk","repoRelKeys","rel","_res","contentType","sendSuccess","sendError","sendQueryError","fallbackMessage","verbose","wrapDateSchemas","def","wrapped","dflt","pickSchemaFields","systemKeys","source","validateData","partial","targetSchema","partialSchema","allowedFields","opMap","opKey","parsedVal","parseValue","num","serializeCursor","deserializeCursor","createCrudHandlers","getRepoEntry","getterName","getter","ctxFilters","ctxSort","direction","orderBy","orderDir","selectStr","includes","inc","cursorObj","responseData","handleQuery","validIncludes","allowed","invalid","w","handleGet","handleCreate","customError","created","handleUpdate","existingDoc","updated","handleOptions","zodToJsonSchema","schemaRef","errorResponse","description","successResponse","dataSchema","listResponse","itemSchema","paginationParams","filterParams","queryBodySchema","buildPathsForEntry","modelSchemaName","createSchemaName","updateSchemaName","paths","tag","idParam","singularize","docOps","generateOpenAPISpec","version","servers","schemas","allPaths","tags","modelName","createName","updateName","buildShape","fieldList","top","createShape","updateShape","entryPaths","securitySchemes","security","scalarDocsHtml","specUrl","createCrudServer","openapi","openapiOpts","_specCache","getSpec","authType","specPath","docsPath","spec","maybeWrap","injectRepos","bound","serverName","createServers","fullRepos","merged","createRepositoryConfig","buildRepositoryRelations","mapping","relations","repoKey","RepositoryMapping","createRepositoryMapping","mappingKeys","_target"],"mappings":"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A;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA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","file":"index.js","sourcesContent":["/**\n * Zod introspection utilities — compatible with Zod 4.\n *\n * Centralizes all internal `_zod.def` accesses so the rest of the codebase\n * never touches Zod internals directly. If a future Zod version changes\n * the internal layout, only this file needs updating.\n */\n\nimport type { z } from \"zod\";\n\n// ---------------------------------------------------------------------------\n// Type-name resolution\n// ---------------------------------------------------------------------------\n\n/**\n * Canonical Zod type names used in the codebase.\n * These match the **Zod 3** naming convention (e.g. \"ZodString\") that the\n * form-gen / admin handlers already rely on, so we don't need to rewrite\n * every `case \"ZodString\":` branch.\n */\ntype ZodTypeName =\n | \"ZodString\"\n | \"ZodNumber\"\n | \"ZodBigInt\"\n | \"ZodBoolean\"\n | \"ZodDate\"\n | \"ZodEnum\"\n | \"ZodNativeEnum\"\n | \"ZodLiteral\"\n | \"ZodObject\"\n | \"ZodArray\"\n | \"ZodOptional\"\n | \"ZodNullable\"\n | \"ZodDefault\"\n | \"ZodCoerce\"\n | \"ZodUnion\"\n | \"ZodUndefined\"\n | \"ZodUnknown\"\n | \"ZodAny\"\n | \"ZodRecord\"\n | string;\n\n/**\n * Map from Zod 4 `_zod.def.type` (lowercase) → Zod 3 `_def.typeName` format.\n * Any key not in this map is capitalised as `Zod${Capitalised}`.\n */\nconst TYPE_MAP: Record<string, ZodTypeName> = {\n string: \"ZodString\",\n number: \"ZodNumber\",\n bigint: \"ZodBigInt\",\n boolean: \"ZodBoolean\",\n date: \"ZodDate\",\n enum: \"ZodEnum\",\n nativeEnum: \"ZodNativeEnum\",\n literal: \"ZodLiteral\",\n object: \"ZodObject\",\n array: \"ZodArray\",\n optional: \"ZodOptional\",\n nullable: \"ZodNullable\",\n default: \"ZodDefault\",\n coerce: \"ZodCoerce\",\n union: \"ZodUnion\",\n undefined: \"ZodUndefined\",\n unknown: \"ZodUnknown\",\n any: \"ZodAny\",\n record: \"ZodRecord\",\n};\n\n/**\n * Get the canonical type name of a Zod schema.\n *\n * Works with both Zod 3 (`_def.typeName`) and Zod 4 (`_zod.def.type`).\n * Returns names in Zod-3 style (\"ZodString\", \"ZodObject\" …) for\n * backward-compatible switch/case usage.\n */\nexport function getTypeName(schema: z.ZodType): ZodTypeName {\n const s = schema as any;\n\n // Zod 4 path\n const v4Type: string | undefined = s._zod?.def?.type;\n if (v4Type)\n return (\n TYPE_MAP[v4Type] ??\n `Zod${v4Type.charAt(0).toUpperCase()}${v4Type.slice(1)}`\n );\n\n // Zod 3 fallback\n const v3Type: string | undefined = s._def?.typeName;\n if (v3Type) return v3Type;\n\n return \"\";\n}\n\n// ---------------------------------------------------------------------------\n// Unwrapping wrappers (Optional / Nullable / Default)\n// ---------------------------------------------------------------------------\n\n/**\n * Get the inner schema from a wrapper type (Optional / Nullable / Default).\n */\nexport function getInnerType(schema: z.ZodType): z.ZodType | undefined {\n const s = schema as any;\n\n // Zod 4: _zod.def.innerType\n if (s._zod?.def?.innerType) return s._zod.def.innerType;\n\n // Zod 3 compat: _def.innerType\n if (s._def?.innerType) return s._def.innerType;\n\n return undefined;\n}\n\n/**\n * Get the **element schema** from a `ZodArray`.\n * Returns `undefined` for non-array schemas.\n */\nexport function getArrayElementType(\n schema: z.ZodType,\n): z.ZodType | undefined {\n const s = schema as any;\n\n // Zod 4: _zod.def.element\n if (s._zod?.def?.element) return s._zod.def.element;\n\n // Zod 3: _def.type (ZodArray stores element schema in _def.type)\n if (s._def?.type) return s._def.type;\n\n return undefined;\n}\n\n/**\n * Returns the list of **required** (non-optional) top-level keys of a ZodObject.\n * A key is required when its schema is NOT wrapped in ZodOptional.\n * ZodNullable / ZodDefault fields are still considered required — they must be present.\n */\nexport function getRequiredSchemaKeys(schema: z.ZodObject<any>): string[] {\n const required: string[] = [];\n for (const [key, fieldSchema] of Object.entries(schema.shape)) {\n const typeName = getTypeName(fieldSchema as z.ZodType);\n if (typeName !== \"ZodOptional\") {\n required.push(key);\n }\n }\n return required;\n}\n\n/**\n * Get the default value for a ZodDefault schema.\n * In Zod 3 this was `_def.defaultValue()` (function). In Zod 4 it's a direct value.\n */\nexport function getDefaultValue(schema: z.ZodType): unknown {\n const s = schema as any;\n\n // Zod 4\n if (s._zod?.def?.defaultValue !== undefined) return s._zod.def.defaultValue;\n\n // Zod 3 compat\n const v = s._def?.defaultValue;\n if (typeof v === \"function\") return v();\n return v;\n}\n\n// ---------------------------------------------------------------------------\n// Object shape\n// ---------------------------------------------------------------------------\n\n/**\n * Get the shape of a ZodObject schema (Record<string, ZodType>).\n * Handles both Zod 3 (`_def.shape()` function) and Zod 4 (`.shape` property).\n */\nexport function getShape(schema: z.ZodType): Record<string, z.ZodType> {\n const s = schema as any;\n\n // Direct `.shape` property (Zod 3 & 4 for ZodObject instances)\n if (s.shape && typeof s.shape === \"object\") return s.shape;\n\n // Zod 4: _zod.def.shape\n if (s._zod?.def?.shape && typeof s._zod.def.shape === \"object\")\n return s._zod.def.shape;\n\n // Zod 3 fallback: _def.shape() or _def.shape\n if (s._def?.shape) {\n return typeof s._def.shape === \"function\" ? s._def.shape() : s._def.shape;\n }\n\n return {};\n}\n\n// ---------------------------------------------------------------------------\n// Enum / Literal values\n// ---------------------------------------------------------------------------\n\n/**\n * Get the values of a ZodEnum schema as a string[].\n */\nexport function getEnumValues(schema: z.ZodType): string[] {\n const s = schema as any;\n\n // Zod 4: `.options` or `_zod.def.entries`\n if (Array.isArray(s.options)) return s.options;\n if (s._zod?.def?.entries)\n return Object.values(s._zod.def.entries) as string[];\n\n // Zod 3: `_def.values`\n if (Array.isArray(s._def?.values)) return s._def.values;\n\n return [];\n}\n\n/**\n * Get the value object of a ZodNativeEnum schema.\n */\nexport function getNativeEnumValues(\n schema: z.ZodType,\n): Record<string, unknown> {\n const s = schema as any;\n\n // Zod 4: `_zod.def.entries` or `.enum`\n if (s._zod?.def?.entries) return s._zod.def.entries;\n if (s.enum && typeof s.enum === \"object\") return s.enum;\n\n // Zod 3: `_def.values`\n if (s._def?.values && typeof s._def.values === \"object\") return s._def.values;\n\n return {};\n}\n\n/**\n * Get the value of a ZodLiteral schema.\n */\nexport function getLiteralValue(schema: z.ZodType): unknown {\n const s = schema as any;\n\n // Zod 4: `_zod.def.values[0]`\n if (Array.isArray(s._zod?.def?.values)) return s._zod.def.values[0];\n\n // Zod 3: `_def.value`\n return s._def?.value;\n}\n\n// ---------------------------------------------------------------------------\n// String checks\n// ---------------------------------------------------------------------------\n\n/**\n * Get relevant \"check kinds\" from a ZodString schema.\n * Returns an array of kind strings: \"email\", \"url\", etc.\n */\nexport function getStringChecks(schema: z.ZodType): string[] {\n const s = schema as any;\n const kinds: string[] = [];\n\n // Zod 4: checks with `.format` field\n const v4Checks: any[] | undefined = s._zod?.def?.checks;\n if (Array.isArray(v4Checks)) {\n for (const c of v4Checks) {\n if (c.format) kinds.push(c.format);\n }\n if (kinds.length > 0) return kinds;\n }\n\n // Zod 3: _def.checks with `.kind` field\n const v3Checks: any[] | undefined = s._def?.checks;\n if (Array.isArray(v3Checks)) {\n for (const c of v3Checks) {\n if (c.kind) kinds.push(c.kind);\n }\n }\n\n return kinds;\n}\n","function CellDate({ val }: { val: Date }) {\n return (\n <span class=\"text-sm text-base-content/80 font-mono tabular-nums whitespace-nowrap\">\n {val.toLocaleString()}\n </span>\n );\n}\n\n/** Small warning icon with tooltip — rendered next to a cell when its value's runtime type doesn't match the schema. */\nfunction TypeMismatchBadge({ message }: { message: string }) {\n return (\n <span\n class=\"tooltip tooltip-warning tooltip-right inline-flex align-middle ml-1 text-warning\"\n data-tip={message}\n role=\"img\"\n aria-label={message}\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"currentColor\"\n class=\"size-3.5\"\n >\n <path d=\"M12 2 1 22h22L12 2zm0 6 7.5 13h-15L12 8zm-1 4v4h2v-4h-2zm0 5v2h2v-2h-2z\" />\n </svg>\n </span>\n );\n}\n\nexport function CellValue({\n val,\n mismatch,\n}: {\n val: unknown;\n mismatch?: string | null;\n}) {\n const inner = renderInner(val);\n if (!mismatch) return inner;\n return (\n <span class=\"inline-flex items-start gap-0.5\">\n {inner}\n <TypeMismatchBadge message={mismatch} />\n </span>\n );\n}\n\nfunction renderInner(val: unknown) {\n if (val === null || val === undefined) {\n return <span class=\"opacity-30 italic text-xs\">—</span>;\n }\n\n if (typeof val === \"boolean\") {\n return val ? (\n <span class=\"badge badge-success badge-sm\">true</span>\n ) : (\n <span class=\"badge badge-error badge-sm\">false</span>\n );\n }\n\n if (val instanceof Date) {\n return <CellDate val={val} />;\n }\n\n // Firestore Timestamp (.toDate())\n if (\n typeof val === \"object\" &&\n val !== null &&\n typeof (val as any).toDate === \"function\"\n ) {\n return <CellDate val={(val as any).toDate() as Date} />;\n }\n\n if (typeof val === \"number\") {\n return <span class=\"text-sm font-mono tabular-nums\">{String(val)}</span>;\n }\n\n if (Array.isArray(val)) {\n if (val.length === 0)\n return <span class=\"text-xs text-base-content/30\">{\"[]\"}</span>;\n return (\n <ul class=\"list-none p-0 m-0 space-y-0.5 text-xs\">\n {val.slice(0, 8).map((item, i) => (\n <li key={i} class=\"break-all\">\n {typeof item === \"object\" ? JSON.stringify(item) : String(item)}\n </li>\n ))}\n {val.length > 8 && (\n <li class=\"text-base-content/40 italic\">\n +{val.length - 8} more…\n </li>\n )}\n </ul>\n );\n }\n\n if (typeof val === \"object\" && val !== null) {\n const entries = Object.entries(val as Record<string, unknown>);\n if (entries.length === 0)\n return <span class=\"text-xs text-base-content/30\">{\"{}\"}</span>;\n return (\n <dl class=\"grid grid-cols-[auto_1fr] gap-x-2 gap-y-0.5 text-xs m-0\">\n {entries.slice(0, 8).map(([k, v]) => (\n <>\n <dt class=\"text-base-content/50 font-semibold whitespace-nowrap\">\n {k}\n </dt>\n <dd class=\"break-all\">{String(v ?? \"\")}</dd>\n </>\n ))}\n {entries.length > 8 && (\n <dt class=\"col-span-2 text-base-content/40 italic\">\n +{entries.length - 8} more…\n </dt>\n )}\n </dl>\n );\n }\n\n const str = String(val);\n return <span class=\"text-sm break-all\">{str}</span>;\n}\n","/**\n * Runtime type-mismatch detection between a column's declared Zod schema\n * and the actual value returned by Firestore.\n *\n * Used by the list view to surface a small warning indicator + tooltip\n * when the stored data drifts from the model (e.g. the schema declares a\n * `string` but Firestore returns a `number`).\n */\n\nimport type { z } from \"zod\";\nimport {\n getInnerType,\n getShape,\n getTypeName,\n} from \"../../../shared/zod-compat\";\n\nexport type ExpectedType =\n | \"string\"\n | \"number\"\n | \"bigint\"\n | \"boolean\"\n | \"date\"\n | \"array\"\n | \"object\"\n | \"enum\"\n | \"literal\"\n | \"unknown\";\n\n/** Resolve the expected runtime type name from a Zod schema (after unwrapping optional/nullable/default). */\nexport function expectedTypeOf(schema: z.ZodType | undefined): ExpectedType {\n if (!schema) return \"unknown\";\n const inner = unwrap(schema);\n const tn = getTypeName(inner);\n switch (tn) {\n case \"ZodString\":\n return \"string\";\n case \"ZodNumber\":\n return \"number\";\n case \"ZodBigInt\":\n return \"bigint\";\n case \"ZodBoolean\":\n return \"boolean\";\n case \"ZodDate\":\n return \"date\";\n case \"ZodArray\":\n return \"array\";\n case \"ZodObject\":\n case \"ZodRecord\":\n return \"object\";\n case \"ZodEnum\":\n case \"ZodNativeEnum\":\n return \"enum\";\n case \"ZodLiteral\":\n return \"literal\";\n default:\n return \"unknown\";\n }\n}\n\n/** Recursively unwrap Optional/Nullable/Default wrappers. */\nfunction unwrap(schema: z.ZodType): z.ZodType {\n const tn = getTypeName(schema);\n if (\n tn === \"ZodOptional\" ||\n tn === \"ZodNullable\" ||\n tn === \"ZodDefault\"\n ) {\n const inner = getInnerType(schema);\n return inner ? unwrap(inner) : schema;\n }\n return schema;\n}\n\n/** Resolve a Zod schema for a possibly dot-noted column path, returning undefined if unresolvable. */\nexport function resolveAtPath(\n schema: z.ZodType | undefined,\n path: string,\n): z.ZodType | undefined {\n if (!schema) return undefined;\n const segments = path.split(\".\");\n let cur: z.ZodType | undefined = schema;\n for (const seg of segments) {\n if (!cur) return undefined;\n const inner = unwrap(cur);\n const tn = getTypeName(inner);\n if (tn !== \"ZodObject\") return undefined;\n const shape = getShape(inner);\n cur = shape[seg];\n }\n return cur;\n}\n\n/** Best-effort runtime type label of a value, mirroring ExpectedType vocabulary. */\nexport function actualTypeOf(val: unknown): ExpectedType | \"null\" {\n if (val === null || val === undefined) return \"null\";\n if (val instanceof Date) return \"date\";\n if (Array.isArray(val)) return \"array\";\n if (typeof val === \"string\") return \"string\";\n if (typeof val === \"boolean\") return \"boolean\";\n if (typeof val === \"bigint\") return \"bigint\";\n if (typeof val === \"number\") return \"number\";\n if (typeof val === \"object\") {\n // Firestore Timestamp duck-typing\n if (typeof (val as any).toDate === \"function\") return \"date\";\n return \"object\";\n }\n return \"unknown\";\n}\n\n/** Return null if compatible; otherwise a tooltip message describing the mismatch. */\nexport function mismatchMessage(\n expected: ExpectedType,\n val: unknown,\n): string | null {\n if (expected === \"unknown\") return null;\n const actual = actualTypeOf(val);\n // Null is acceptable here — nullability is a separate concern handled by the schema (optional/nullable).\n if (actual === \"null\") return null;\n // enum/literal compatibility — both stored as primitives; we don't validate the value set here.\n if (expected === \"enum\" || expected === \"literal\") {\n if (actual === \"string\" || actual === \"number\") return null;\n return `Expected ${expected} (string/number), got ${actual}`;\n }\n if (expected === actual) return null;\n // Cross-compatible numerics: bigint vs number\n if (\n (expected === \"number\" && actual === \"bigint\") ||\n (expected === \"bigint\" && actual === \"number\")\n ) {\n return null;\n }\n return `Expected ${expected}, got ${actual}`;\n}\n","import type { FC } from \"hono/jsx\";\nimport { CellValue } from \"./cell-value\";\nimport type { ExpectedType } from \"./type-check\";\nimport { expectedTypeOf, mismatchMessage, resolveAtPath } from \"./type-check\";\n\n/** Slide-in right panel container — rendered once in the page shell, populated client-side. */\nexport const RightPanel: FC = () => (\n <div\n class=\"fixed inset-0 z-[100] hidden pointer-events-none\"\n data-frs-panel-root\n aria-hidden=\"true\"\n >\n {/* Backdrop */}\n <div\n class=\"absolute inset-0 bg-black/30 opacity-0 transition-opacity duration-200 pointer-events-auto\"\n data-frs-panel-backdrop\n />\n {/* Panel — 50% on md+, full-width on mobile */}\n <aside\n class=\"absolute top-0 right-0 h-full w-full md:w-1/2 bg-base-100 shadow-2xl border-l border-base-300 translate-x-full transition-transform duration-200 pointer-events-auto flex flex-col\"\n data-frs-panel\n role=\"dialog\"\n aria-label=\"Relation preview\"\n >\n <header class=\"flex items-center justify-between px-5 py-3 border-b border-base-300 bg-base-200/40 shrink-0\">\n <h2\n class=\"font-semibold text-base truncate\"\n data-frs-panel-title\n >\n Relation\n </h2>\n <button\n type=\"button\"\n class=\"btn btn-sm btn-ghost btn-circle\"\n data-frs-panel-close\n aria-label=\"Close panel\"\n >\n ✕\n </button>\n </header>\n <div\n class=\"flex-1 overflow-auto p-5 text-sm\"\n data-frs-panel-body\n >\n <div class=\"flex items-center justify-center py-12 text-base-content/40\">\n <span class=\"loading loading-spinner loading-md\" />\n </div>\n </div>\n </aside>\n </div>\n);\n\n// ---------------------------------------------------------------------------\n// Server-rendered HTML fragments served at GET /:repoName/_panel\n// (no <html>/<body> wrapper — they're injected into the panel body by JS)\n// ---------------------------------------------------------------------------\n\n/** Render the \"one\" relation preview: read-only field list + Edit/Open button. */\nexport function PanelOne({\n doc,\n repoName,\n basePath,\n schema,\n columns,\n}: {\n doc: Record<string, unknown> | null;\n repoName: string;\n basePath: string;\n schema?: import(\"zod\").ZodObject<any>;\n columns: string[];\n}) {\n if (!doc) {\n return (\n <div class=\"text-center py-12 text-base-content/50\">\n Document not found.\n </div>\n );\n }\n const id = String(doc[\"docId\"] ?? doc[\"id\"] ?? \"\");\n const editUrl = `${basePath}/${repoName}/${encodeURIComponent(id)}/edit`;\n const expectedTypes = buildExpectedMap(schema, columns);\n return (\n <div class=\"space-y-4\">\n <div class=\"flex items-center justify-between gap-2\">\n <div class=\"text-xs text-base-content/60\">\n <span class=\"font-mono\">{repoName}</span>\n <span class=\"opacity-50\"> · </span>\n <span class=\"font-mono break-all\">{id}</span>\n </div>\n <a href={editUrl} class=\"btn btn-sm btn-primary\">\n Edit →\n </a>\n </div>\n <dl class=\"grid grid-cols-[max-content_1fr] gap-x-4 gap-y-2 border border-base-300 rounded-box p-4 bg-base-100\">\n {columns.map((c) => {\n const val = doc[c];\n const expected = expectedTypes[c];\n const mismatch = expected ? mismatchMessage(expected, val) : null;\n return (\n <>\n <dt class=\"text-xs font-semibold text-base-content/60 uppercase tracking-wide pt-0.5\">\n {c}\n </dt>\n <dd class=\"min-w-0\">\n <CellValue val={val} mismatch={mismatch} />\n </dd>\n </>\n );\n })}\n </dl>\n </div>\n );\n}\n\n/** Render the \"many\" relation preview: full filtered list (compact table). */\nexport function PanelMany({\n docs,\n repoName,\n basePath,\n fk,\n fv,\n columns,\n schema,\n pagination,\n}: {\n docs: Record<string, unknown>[];\n repoName: string;\n basePath: string;\n fk: string;\n fv: string;\n columns: string[];\n schema?: import(\"zod\").ZodObject<any>;\n pagination: {\n hasPrev: boolean;\n hasNext: boolean;\n prevCursor: string;\n nextCursor: string;\n pageSize: number;\n };\n}) {\n const fullViewUrl = `${basePath}/${repoName}?fv_${fk}=${encodeURIComponent(fv)}`;\n const expectedTypes = buildExpectedMap(schema, columns);\n return (\n <div class=\"space-y-4\">\n <div class=\"flex items-center justify-between gap-2\">\n <div class=\"text-xs text-base-content/60\">\n <span class=\"font-mono\">{repoName}</span>\n <span class=\"opacity-50\"> where </span>\n <span class=\"font-mono\">{fk}</span>\n <span class=\"opacity-50\"> = </span>\n <span class=\"font-mono break-all\">{fv}</span>\n <span class=\"opacity-50\"> · </span>\n <span>\n {docs.length} doc{docs.length !== 1 ? \"s\" : \"\"}\n </span>\n </div>\n <a href={fullViewUrl} class=\"btn btn-sm btn-outline\">\n Full view →\n </a>\n </div>\n <div class=\"overflow-x-auto rounded-box border border-base-300 bg-base-100\">\n <table class=\"table table-xs w-full\">\n <thead>\n <tr class=\"bg-base-200/50\">\n {columns.map((c, i) => (\n <th\n key={i}\n class=\"text-xs font-semibold text-base-content/60 uppercase tracking-wide\"\n >\n {c}\n </th>\n ))}\n <th />\n </tr>\n </thead>\n <tbody>\n {docs.length === 0 ? (\n <tr>\n <td\n colspan={columns.length + 1}\n class=\"text-center py-10 text-base-content/40\"\n >\n No related documents\n </td>\n </tr>\n ) : (\n docs.map((d, ri) => {\n const id = String(d[\"docId\"] ?? d[\"id\"] ?? \"\");\n const editUrl = `${basePath}/${repoName}/${encodeURIComponent(id)}/edit`;\n return (\n <tr key={ri} class=\"hover\">\n {columns.map((c, ci) => {\n const val = d[c];\n const expected = expectedTypes[c];\n const mismatch = expected\n ? mismatchMessage(expected, val)\n : null;\n return (\n <td key={ci} class=\"align-top py-1.5\">\n <CellValue val={val} mismatch={mismatch} />\n </td>\n );\n })}\n <td class=\"text-right py-1.5\">\n <a href={editUrl} class=\"btn btn-xs btn-ghost\">\n Edit\n </a>\n </td>\n </tr>\n );\n })\n )}\n </tbody>\n </table>\n </div>\n {(pagination.hasPrev || pagination.hasNext) && (\n <div class=\"flex justify-center items-center gap-2\">\n {pagination.hasPrev ? (\n <button\n type=\"button\"\n class=\"btn btn-xs btn-outline\"\n data-frs-panel-page=\"prev\"\n data-cursor={pagination.prevCursor}\n >\n ← Previous\n </button>\n ) : (\n <button class=\"btn btn-xs btn-outline\" disabled>\n ← Previous\n </button>\n )}\n {pagination.hasNext ? (\n <button\n type=\"button\"\n class=\"btn btn-xs btn-outline\"\n data-frs-panel-page=\"next\"\n data-cursor={pagination.nextCursor}\n >\n Next →\n </button>\n ) : (\n <button class=\"btn btn-xs btn-outline\" disabled>\n Next →\n </button>\n )}\n </div>\n )}\n </div>\n );\n}\n\nfunction buildExpectedMap(\n schema: import(\"zod\").ZodObject<any> | undefined,\n columns: string[],\n): Record<string, ExpectedType> {\n if (!schema) return {};\n const out: Record<string, ExpectedType> = {};\n for (const c of columns) {\n out[c] = expectedTypeOf(resolveAtPath(schema, c));\n }\n return out;\n}\n","import type { Query, QuerySnapshot } from \"firebase-admin/firestore\";\nimport type { QueryOptions, WhereClause } from \"./shared/types\";\n\n/**\n * Chunk array into smaller arrays\n */\nfunction chunkArray<T>(array: T[], size: number): T[][] {\n const chunks: T[][] = [];\n for (let i = 0; i < array.length; i += size) {\n chunks.push(array.slice(i, i + size));\n }\n return chunks;\n}\n\n/**\n * Apply basic query options (orderBy, limit, offset, select, cursors)\n */\nfunction applyBasicQueryOptions<T>(q: Query, options: QueryOptions<T>): Query {\n if (options.orderBy) {\n options.orderBy.forEach((o) => {\n q = q.orderBy(String(o.field), o.direction ?? \"asc\");\n });\n }\n\n if (options.limit) {\n q = q.limit(options.limit);\n }\n\n if (options.offset) {\n q = q.offset(options.offset);\n }\n\n if (options.select && options.select.length > 0) {\n q = q.select(...options.select.map((f) => String(f)));\n }\n\n // Cursor-based pagination\n if (options.startAt) {\n q = Array.isArray(options.startAt)\n ? q.startAt(...options.startAt)\n : q.startAt(options.startAt);\n }\n\n if (options.startAfter) {\n q = Array.isArray(options.startAfter)\n ? q.startAfter(...options.startAfter)\n : q.startAfter(options.startAfter);\n }\n\n if (options.endAt) {\n q = Array.isArray(options.endAt)\n ? q.endAt(...options.endAt)\n : q.endAt(options.endAt);\n }\n\n if (options.endBefore) {\n q = Array.isArray(options.endBefore)\n ? q.endBefore(...options.endBefore)\n : q.endBefore(options.endBefore);\n }\n\n return q;\n}\n\n/**\n * Check if a where clause needs splitting (in or array-contains-any with > 30 values)\n */\nfunction needsSplitting<T>(clause: WhereClause<T>): boolean {\n const [, operator, value] = clause;\n return (\n (operator === \"in\" || operator === \"array-contains-any\") &&\n Array.isArray(value) &&\n value.length > 30\n );\n}\n\n/**\n * Split a where clause into multiple clauses (for in/array-contains-any)\n */\nfunction splitWhereClause<T>(clause: WhereClause<T>): WhereClause<T>[] {\n const [field, operator, value] = clause;\n\n if (!needsSplitting(clause)) {\n return [clause];\n }\n\n // Split array into chunks of 30\n const chunks = chunkArray(value as any[], 30);\n return chunks.map((chunk) => [field, operator, chunk] as WhereClause<T>);\n}\n\n/**\n * Apply where clauses to a query, handling splits for in/array-contains-any\n */\nfunction applyWhereClausesToQuery<T>(\n baseQuery: Query,\n whereClauses: WhereClause<T>[],\n): Query {\n let q = baseQuery;\n\n for (const [field, operator, value] of whereClauses) {\n q = q.where(String(field), operator, value);\n }\n\n return q;\n}\n\n/**\n * Execute multiple queries in parallel and merge results\n */\nasync function executeAndMergeQueries(\n queries: Query[],\n): Promise<QuerySnapshot> {\n const snapshots = await Promise.all(queries.map((q) => q.get()));\n\n // Merge all documents, removing duplicates by ID\n const docsMap = new Map();\n snapshots.forEach((snapshot) => {\n snapshot.docs.forEach((doc) => {\n if (!docsMap.has(doc.id)) {\n docsMap.set(doc.id, doc);\n }\n });\n });\n\n // Return first snapshot with merged docs\n const firstSnapshot = snapshots[0];\n if (!firstSnapshot) {\n throw new Error(\"No snapshots returned\");\n }\n\n // Create a merged snapshot-like object\n return {\n ...firstSnapshot,\n docs: Array.from(docsMap.values()),\n size: docsMap.size,\n empty: docsMap.size === 0,\n } as QuerySnapshot;\n}\n\n/**\n * Build and execute query with automatic splitting for in/array-contains-any\n * Handles both simple AND conditions and complex OR conditions\n */\nexport async function buildAndExecuteQuery<T>(\n baseQuery: Query,\n options: QueryOptions<T>,\n): Promise<QuerySnapshot> {\n const hasOrWhere = options.orWhere && options.orWhere.length > 0;\n const hasOrWhereGroups =\n options.orWhereGroups && options.orWhereGroups.length > 0;\n\n // Case 1: Pure AND query\n if (!hasOrWhere && !hasOrWhereGroups) {\n if (!options.where || options.where.length === 0) {\n const q = applyBasicQueryOptions(baseQuery, options);\n return q.get();\n }\n const needsSplit = options.where.some(needsSplitting);\n if (!needsSplit) {\n let q = applyWhereClausesToQuery(baseQuery, options.where);\n q = applyBasicQueryOptions(q, options);\n return q.get();\n }\n const splitClauses: WhereClause<T>[][] =\n options.where.map(splitWhereClause);\n const combinations = cartesianProduct(splitClauses);\n const queries = combinations.map((combination) => {\n let q = applyWhereClausesToQuery(baseQuery, combination);\n q = applyBasicQueryOptions(q, options);\n return q;\n });\n return executeAndMergeQueries(queries);\n }\n\n // Case 2: OR query — convert orWhere/orWhereGroups into OR groups,\n // then prepend base where conditions to every group.\n const baseClauses: WhereClause<T>[] = options.where ?? [];\n\n // Normalise: orWhere entries are single-clause groups;\n // orWhereGroups entries are multi-clause groups.\n const rawGroups: WhereClause<T>[][] = [\n ...(options.orWhere?.map((clause) => [clause]) ?? []),\n ...(options.orWhereGroups ?? []),\n ];\n\n const allQueries: Query[] = [];\n\n for (const orGroup of rawGroups) {\n // Merge base AND conditions into each OR group\n const fullGroup: WhereClause<T>[] = [...baseClauses, ...orGroup];\n const needsSplit = fullGroup.some(needsSplitting);\n\n if (!needsSplit) {\n let q = applyWhereClausesToQuery(baseQuery, fullGroup);\n q = applyBasicQueryOptions(q, options);\n allQueries.push(q);\n } else {\n const splitClauses = fullGroup.map(splitWhereClause);\n const combinations = cartesianProduct(splitClauses);\n const groupQueries = combinations.map((combination) => {\n let q = applyWhereClausesToQuery(baseQuery, combination);\n q = applyBasicQueryOptions(q, options);\n return q;\n });\n allQueries.push(...groupQueries);\n }\n }\n\n return executeAndMergeQueries(allQueries);\n}\n\n/**\n * Generate Cartesian product of arrays\n * Example: [[a,b], [1,2]] => [[a,1], [a,2], [b,1], [b,2]]\n */\nfunction cartesianProduct<T>(arrays: T[][]): T[][] {\n if (arrays.length === 0) return [[]];\n\n const first = arrays[0];\n if (arrays.length === 1 && first) {\n return first.map((item) => [item]);\n }\n\n if (!first) return [[]];\n\n const rest = arrays.slice(1);\n const restProduct = cartesianProduct(rest);\n\n const result: T[][] = [];\n for (const item of first) {\n for (const combo of restProduct) {\n result.push([item, ...combo]);\n }\n }\n\n return result;\n}\n","import { Timestamp } from \"firebase-admin/firestore\";\n\nexport type DateHandlingMode = \"preserve\" | \"normalize\";\n\nlet currentMode: DateHandlingMode = \"preserve\";\n\nexport function setDateHandling(mode: DateHandlingMode): void {\n currentMode = mode;\n}\n\nexport function getDateHandling(): DateHandlingMode {\n return currentMode;\n}\n\nfunction isTimestampLike(\n v: unknown,\n): v is { _seconds: number; _nanoseconds: number } {\n return (\n typeof v === \"object\" &&\n v !== null &&\n typeof (v as { _seconds?: unknown })._seconds === \"number\" &&\n typeof (v as { _nanoseconds?: unknown })._nanoseconds === \"number\"\n );\n}\n\nexport function coerceToDate(value: unknown): Date | null {\n if (value === null || value === undefined) return null;\n if (value instanceof Date) return Number.isNaN(value.getTime()) ? null : value;\n if (value instanceof Timestamp) return value.toDate();\n if (isTimestampLike(value)) {\n return new Date(\n value._seconds * 1000 + Math.floor(value._nanoseconds / 1e6),\n );\n }\n if (typeof value === \"string\") {\n const d = new Date(value);\n return Number.isNaN(d.getTime()) ? null : d;\n }\n if (typeof value === \"number\") {\n const d = new Date(value);\n return Number.isNaN(d.getTime()) ? null : d;\n }\n return null;\n}\n\nfunction isPlainObject(v: unknown): v is Record<string, unknown> {\n if (typeof v !== \"object\" || v === null) return false;\n const proto = Object.getPrototypeOf(v);\n return proto === Object.prototype || proto === null;\n}\n\nexport function normalizeTimestamps<T>(value: T): T {\n if (value instanceof Timestamp) return value.toDate() as unknown as T;\n if (Array.isArray(value)) {\n return value.map((v) => normalizeTimestamps(v)) as unknown as T;\n }\n if (isPlainObject(value)) {\n const out: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(value)) {\n out[k] = normalizeTimestamps(v);\n }\n return out as unknown as T;\n }\n return value;\n}\n\nexport function maybeNormalize<T>(value: T): T {\n return currentMode === \"normalize\" ? normalizeTimestamps(value) : value;\n}\n","import type { Query } from \"firebase-admin/firestore\";\nimport type { QueryOptions } from \"./types\";\n\n/**\n * Split an array into chunks of specified size\n */\nexport function chunkArray<T>(array: T[], size: number): T[][] {\n const chunks: T[][] = [];\n for (let i = 0; i < array.length; i += size) {\n chunks.push(array.slice(i, i + size));\n }\n return chunks;\n}\n\n/**\n * Capitalize first letter of a string\n */\nexport function capitalize(str: string): string {\n return str.charAt(0).toUpperCase() + str.slice(1);\n}\n\n/**\n * Apply QueryOptions to a Firestore query.\n * Handles where, orderBy, limit, offset, select and cursor-based pagination.\n * Does NOT handle orWhere — use buildAndExecuteQuery for that.\n */\nexport function applyQueryOptions<T>(\n q: Query,\n options: QueryOptions<T>,\n): Query {\n if (options.where) {\n options.where.forEach(([field, operator, value]) => {\n q = q.where(String(field), operator, value);\n });\n }\n\n if (options.orderBy) {\n options.orderBy.forEach((o) => {\n q = q.orderBy(String(o.field), o.direction ?? \"asc\");\n });\n }\n\n if (options.limit) {\n q = q.limit(options.limit);\n }\n\n if (options.offset) {\n q = q.offset(options.offset);\n }\n\n if (options.select && options.select.length > 0) {\n q = q.select(...options.select.map((f) => String(f)));\n }\n\n if (options.startAt) {\n q = Array.isArray(options.startAt)\n ? q.startAt(...options.startAt)\n : q.startAt(options.startAt);\n }\n\n if (options.startAfter) {\n q = Array.isArray(options.startAfter)\n ? q.startAfter(...options.startAfter)\n : q.startAfter(options.startAfter);\n }\n\n if (options.endAt) {\n q = Array.isArray(options.endAt)\n ? q.endAt(...options.endAt)\n : q.endAt(options.endAt);\n }\n\n if (options.endBefore) {\n q = Array.isArray(options.endBefore)\n ? q.endBefore(...options.endBefore)\n : q.endBefore(options.endBefore);\n }\n\n return q;\n}\n","import type { DocumentSnapshot, Query } from \"firebase-admin/firestore\";\nimport { buildAndExecuteQuery } from \"./query-builder\";\nimport { maybeNormalize } from \"./shared/date-config\";\nimport type { QueryOptions } from \"./shared/types\";\nimport { applyQueryOptions } from \"./shared/utils\";\n\nexport { applyQueryOptions };\n\n/**\n * Pagination result with data and cursor information\n * @template T - Data model type\n */\nexport interface PaginationResult<T> {\n /** Array of documents for the current page */\n data: T[];\n /** Cursor to the next page (undefined if no more pages) */\n nextCursor?: DocumentSnapshot;\n /** Cursor to the previous page (undefined if on first page) */\n prevCursor?: DocumentSnapshot;\n /** Whether there are more pages after this one */\n hasNextPage: boolean;\n /** Whether there are pages before this one */\n hasPrevPage: boolean;\n /** Total number of items in current page */\n pageSize: number;\n}\n\n/**\n * Pagination options for cursor-based pagination\n * @template T - Data model type\n */\nexport interface PaginationOptions<T> extends Omit<QueryOptions<T>, \"limit\"> {\n /** Number of items per page */\n pageSize: number;\n /** Cursor to start after (for next page) */\n cursor?: DocumentSnapshot;\n /** Direction of pagination */\n direction?: \"next\" | \"prev\";\n}\n\n/**\n * Executes a paginated query and returns results with pagination info.\n * Uses the advanced query builder that handles OR conditions and automatic splitting.\n *\n * @template T - Data model type\n * @param baseQuery - Base Firestore query\n * @param options - Pagination options\n * @returns Pagination result with data and cursor information\n *\n * @example\n * ```typescript\n * // Basic pagination\n * const firstPage = await executePaginatedQuery(collectionRef, {\n * pageSize: 10\n * });\n * console.log(firstPage.data); // Array of 10 items\n * console.log(firstPage.hasNextPage); // true if more pages exist\n *\n * // Get next page using cursor\n * if (firstPage.hasNextPage) {\n * const secondPage = await executePaginatedQuery(collectionRef, {\n * pageSize: 10,\n * cursor: firstPage.nextCursor,\n * direction: \"next\"\n * });\n * }\n *\n * // Pagination with filters and sorting\n * const filteredPage = await executePaginatedQuery(collectionRef, {\n * pageSize: 20,\n * where: [[\"status\", \"==\", \"active\"]],\n * orderBy: [[\"createdAt\", \"desc\"]],\n * select: [\"title\", \"status\", \"createdAt\"]\n * });\n *\n * // Pagination with OR conditions\n * const orPage = await executePaginatedQuery(collectionRef, {\n * pageSize: 10,\n * orWhere: [\n * [\"status\", \"==\", \"published\"],\n * [\"status\", \"==\", \"featured\"]\n * ]\n * });\n *\n * // Go to previous page\n * const prevPage = await executePaginatedQuery(collectionRef, {\n * pageSize: 10,\n * cursor: currentPage.prevCursor,\n * direction: \"prev\"\n * });\n * ```\n */\nexport async function executePaginatedQuery<T>(\n baseQuery: Query,\n options: PaginationOptions<T>,\n): Promise<PaginationResult<T>> {\n // Prepare options with cursor-based pagination\n const queryOptions: QueryOptions<T> = {\n ...options,\n limit: options.pageSize + 1, // Fetch one extra to check if there's a next page\n };\n\n // Apply cursor\n if (options.cursor) {\n if (options.direction === \"prev\") {\n queryOptions.endBefore = options.cursor;\n } else {\n queryOptions.startAfter = options.cursor;\n }\n }\n\n // Use the advanced query builder (handles OR and auto-splitting)\n const snapshot = await buildAndExecuteQuery(baseQuery, queryOptions);\n const docs = snapshot.docs;\n\n // Check if there are more pages\n const hasMore = docs.length > options.pageSize;\n const actualDocs = hasMore ? docs.slice(0, options.pageSize) : docs;\n\n const data = actualDocs.map((doc) =>\n maybeNormalize({\n ...doc.data(),\n docId: doc.id,\n }),\n ) as T[];\n\n const isPrev = options.direction === \"prev\";\n\n return {\n data,\n // When going \"prev\": nextCursor always points to last doc of the page (to go forward\n // again), prevCursor only set when there are even earlier docs (hasMore).\n // When going \"next\" (default): same logic as before.\n nextCursor: isPrev\n ? actualDocs.length > 0\n ? actualDocs[actualDocs.length - 1]\n : undefined\n : hasMore\n ? actualDocs[actualDocs.length - 1]\n : undefined,\n prevCursor: isPrev ? (hasMore ? actualDocs[0] : undefined) : actualDocs[0],\n hasNextPage: isPrev ? !!options.cursor : hasMore,\n hasPrevPage: isPrev ? hasMore : !!options.cursor,\n pageSize: data.length,\n };\n}\n\n/**\n * Creates an async generator for iterating through all pages.\n * Useful for processing large datasets without loading everything into memory.\n *\n * @template T - Data model type\n * @param baseQuery - Base Firestore query\n * @param options - Pagination options (without cursor)\n * @yields Pagination results for each page\n *\n * @example\n * ```typescript\n * // Basic iteration through all pages\n * const pageIterator = createPaginationIterator(query, { pageSize: 100 });\n * for await (const page of pageIterator) {\n * console.log(`Processing ${page.data.length} items`);\n * for (const item of page.data) {\n * await processItem(item);\n * }\n * }\n *\n * // With filters and sorting\n * const filteredIterator = createPaginationIterator(query, {\n * pageSize: 50,\n * where: [[\"status\", \"==\", \"pending\"]],\n * orderBy: [[\"createdAt\", \"asc\"]]\n * });\n *\n * let totalProcessed = 0;\n * for await (const page of filteredIterator) {\n * totalProcessed += page.data.length;\n * console.log(`Processed ${totalProcessed} items so far`);\n * }\n *\n * // Export all data to CSV\n * const allData: User[] = [];\n * for await (const page of createPaginationIterator(usersQuery, { pageSize: 500 })) {\n * allData.push(...page.data);\n * }\n * exportToCsv(allData);\n *\n * // Early exit if condition met\n * for await (const page of createPaginationIterator(query, { pageSize: 100 })) {\n * const found = page.data.find(item => item.id === targetId);\n * if (found) {\n * console.log(\"Found target item!\");\n * break; // Stop iteration early\n * }\n * }\n * ```\n */\nexport async function* createPaginationIterator<T>(\n baseQuery: Query,\n options: Omit<PaginationOptions<T>, \"cursor\" | \"direction\">,\n): AsyncGenerator<PaginationResult<T>, void, unknown> {\n let cursor: DocumentSnapshot | undefined;\n let hasMore = true;\n\n while (hasMore) {\n const result = await executePaginatedQuery<T>(baseQuery, {\n ...options,\n cursor,\n direction: \"next\",\n });\n\n yield result;\n\n hasMore = result.hasNextPage;\n cursor = result.nextCursor;\n }\n}\n","import type { Query } from \"firebase-admin/firestore\";\nimport type { QueryOptions } from \"../shared/types\";\nimport { applyQueryOptions } from \"../shared/utils\";\n\n/**\n * Creates aggregate methods for server-side computations.\n * These operations are executed on the Firestore server for optimal performance.\n *\n * @param collectionRef - Firestore query reference\n * @returns Object containing aggregate methods (count, sum, average)\n *\n * @example\n * ```typescript\n * // COUNT - Count all documents\n * const totalUsers = await repos.users.aggregate.count();\n *\n * // Count with filter\n * const activeUsers = await repos.users.aggregate.count({\n * where: [[\"isActive\", \"==\", true]]\n * });\n *\n * // Count with complex filters\n * const premiumActiveUsers = await repos.users.aggregate.count({\n * where: [\n * [\"isActive\", \"==\", true],\n * [\"subscription\", \"==\", \"premium\"]\n * ]\n * });\n *\n * // SUM - Sum of a numeric field\n * const totalRevenue = await repos.orders.aggregate.sum(\"amount\");\n *\n * // Sum with filter\n * const monthlyRevenue = await repos.orders.aggregate.sum(\"amount\", {\n * where: [\n * [\"createdAt\", \">=\", startOfMonth],\n * [\"createdAt\", \"<=\", endOfMonth]\n * ]\n * });\n *\n * // AVERAGE - Average of a numeric field\n * const avgOrderValue = await repos.orders.aggregate.average(\"amount\");\n *\n * // Average with filter\n * const avgPremiumOrder = await repos.orders.aggregate.average(\"amount\", {\n * where: [[\"customerType\", \"==\", \"premium\"]]\n * });\n *\n * // Returns null if no matching documents\n * const avgEmpty = await repos.orders.aggregate.average(\"amount\", {\n * where: [[\"status\", \"==\", \"nonexistent\"]]\n * }); // null\n *\n * // Combine multiple aggregations\n * const [total, sum, avg] = await Promise.all([\n * repos.orders.aggregate.count(),\n * repos.orders.aggregate.sum(\"amount\"),\n * repos.orders.aggregate.average(\"amount\")\n * ]);\n * console.log(`${total} orders, $${sum} total, $${avg} average`);\n * ```\n */\nexport function createAggregateMethods(collectionRef: Query) {\n return {\n // Count documents matching query options\n count: async (options: QueryOptions = {}): Promise<number> => {\n let q: Query = collectionRef as any;\n q = applyQueryOptions(q, options);\n const snapshot = await q.count().get();\n return snapshot.data().count;\n },\n\n // Sum of a numeric field\n sum: async (field: string, options: QueryOptions = {}): Promise<number> => {\n let q: Query = collectionRef as any;\n q = applyQueryOptions(q, options);\n const snapshot = await q.get();\n\n let total = 0;\n snapshot.forEach((doc) => {\n const value = doc.data()[field];\n if (typeof value === \"number\") {\n total += value;\n }\n });\n\n return total;\n },\n\n // Average of a numeric field\n average: async (\n field: string,\n options: QueryOptions = {},\n ): Promise<number | null> => {\n let q: Query = collectionRef as any;\n q = applyQueryOptions(q, options);\n const snapshot = await q.get();\n\n if (snapshot.empty) return null;\n\n let total = 0;\n let count = 0;\n\n snapshot.forEach((doc) => {\n const value = doc.data()[field];\n if (typeof value === \"number\") {\n total += value;\n count++;\n }\n });\n\n return count > 0 ? total / count : null;\n },\n };\n}\n","import type { Firestore, WriteBatch } from \"firebase-admin/firestore\";\n\n/**\n * Creates batch operation methods for atomic writes (max 500 operations).\n * All operations in a batch either succeed or fail together.\n *\n * @param db - Firestore database instance\n * @param documentRef - Function to create document references\n * @param documentKey - The field name used as document ID\n * @param pathKey - Optional field name to store the document path\n * @param createdKey - Optional field name for creation timestamp\n * @param updatedKey - Optional field name for update timestamp\n * @returns Object containing batch creation method\n *\n * @example\n * ```typescript\n * // Create a batch for atomic operations\n * const batch = repos.users.batch.create();\n *\n * // SET - Add multiple documents\n * batch.set(\"user-1\", { name: \"Alice\", email: \"alice@example.com\" });\n * batch.set(\"user-2\", { name: \"Bob\", email: \"bob@example.com\" });\n * batch.set(\"user-3\", { name: \"Charlie\", email: \"charlie@example.com\" });\n *\n * // For subcollections (e.g., posts/{postId}/comments/{commentId}):\n * const commentBatch = repos.comments.batch.create();\n * commentBatch.set(\"post-1\", \"comment-1\", { content: \"First comment\" });\n * commentBatch.set(\"post-1\", \"comment-2\", { content: \"Second comment\" });\n *\n * // UPDATE - Update existing documents in batch\n * batch.update(\"user-1\", { name: \"Alice Updated\" });\n * batch.update(\"user-2\", { age: 30 });\n *\n * // DELETE - Delete documents in batch\n * batch.delete(\"user-3\");\n *\n * // COMMIT - Execute all operations atomically\n * await batch.commit();\n *\n * // With merge option (default: true)\n * batch.set(\"user-4\", { name: \"David\" }, { merge: false }); // Overwrites entirely\n *\n * // Full example with mixed operations\n * const orderBatch = repos.orders.batch.create();\n * orderBatch.set(\"order-new\", { status: \"pending\", total: 99.99 });\n * orderBatch.update(\"order-old\", { status: \"completed\" });\n * orderBatch.delete(\"order-cancelled\");\n * await orderBatch.commit(); // All or nothing\n * ```\n */\nexport function createBatchMethods(\n db: Firestore,\n documentRef: (...args: any[]) => any,\n documentKey: string,\n pathKey?: string,\n createdKey?: string,\n updatedKey?: string,\n) {\n const now = () => new Date();\n\n return {\n create: () => {\n const batch: WriteBatch = db.batch();\n return {\n batch,\n set: (...args: any[]) => {\n const lastArg = args[args.length - 1];\n const hasOptions =\n typeof lastArg === \"object\" &&\n lastArg !== null &&\n \"merge\" in lastArg;\n\n const data = hasOptions\n ? args[args.length - 2]\n : args[args.length - 1];\n const pathArgs = hasOptions ? args.slice(0, -2) : args.slice(0, -1);\n const mergeOption = hasOptions ? lastArg : { merge: true };\n\n const docRef = documentRef(...pathArgs);\n\n // Auto-populate documentKey, pathKey, createdKey and updatedKey\n const enrichedData = { ...data };\n // Use the last pathArg as documentKey (for subcollections, first args are parent IDs)\n const docIdValue = pathArgs[pathArgs.length - 1];\n if (documentKey && docIdValue) {\n enrichedData[documentKey] = docIdValue;\n }\n if (pathKey) {\n enrichedData[pathKey] = docRef.path;\n }\n if (createdKey) {\n enrichedData[createdKey] = now();\n }\n if (updatedKey) {\n enrichedData[updatedKey] = now();\n }\n\n batch.set(docRef, enrichedData, mergeOption);\n },\n update: (...args: any[]) => {\n const data = args.pop();\n const pathArgs = args;\n const docRef = documentRef(...pathArgs);\n\n // Auto-set updatedKey\n const enrichedData = { ...data };\n if (updatedKey) {\n enrichedData[updatedKey] = now();\n }\n\n batch.update(docRef, enrichedData);\n },\n delete: (...args: any[]) => {\n const docRef = documentRef(...args);\n batch.delete(docRef);\n },\n commit: async () => {\n await batch.commit();\n },\n };\n },\n };\n}\n","import type { DocumentReference, Firestore } from \"firebase-admin/firestore\";\n\n/**\n * Creates bulk operation methods using BulkWriter for large-scale operations.\n * Automatically handles batching (flushes every 500 operations) and provides\n * better performance for large datasets than regular batches.\n *\n * @param db - Firestore database instance\n * @param createdKey - Optional field name for creation timestamp\n * @param updatedKey - Optional field name for update timestamp\n * @returns Object containing bulk write methods\n *\n * @example\n * ```typescript\n * // BULK SET - Create/update thousands of documents efficiently\n * // Prepare items with document references\n * const items = users.map(user => ({\n * docRef: db.collection(\"users\").doc(user.id),\n * data: { name: user.name, email: user.email },\n * merge: true // Optional, defaults to true\n * }));\n *\n * await repos.users.bulk.set(items);\n *\n * // BULK UPDATE - Update many documents\n * const updates = [\n * { docRef: db.collection(\"users\").doc(\"user-1\"), data: { status: \"active\" } },\n * { docRef: db.collection(\"users\").doc(\"user-2\"), data: { status: \"active\" } },\n * // ... thousands more\n * ];\n *\n * await repos.users.bulk.update(updates);\n *\n * // BULK DELETE - Delete many documents\n * const docsToDelete = [\n * db.collection(\"users\").doc(\"user-1\"),\n * db.collection(\"users\").doc(\"user-2\"),\n * // ... thousands more\n * ];\n *\n * await repos.users.bulk.delete(docsToDelete);\n *\n * // Practical example: Migrate data\n * const allUsers = await repos.users.query.getAll();\n * const bulkItems = allUsers.map(user => ({\n * docRef: db.collection(\"users\").doc(user.docId),\n * data: { ...user, migrated: true, version: 2 }\n * }));\n * await repos.users.bulk.set(bulkItems);\n *\n * // Note: Unlike batch, bulk operations are NOT atomic.\n * // Each write is independent - some may succeed while others fail.\n * // Use batch for atomic operations (max 500), bulk for large datasets.\n * ```\n */\nexport function createBulkMethods(\n db: Firestore,\n createdKey?: string,\n updatedKey?: string,\n) {\n const now = () => new Date();\n\n return {\n // Set multiple documents with automatic batching (500 ops per flush)\n set: async (\n items: Array<{\n docRef: DocumentReference;\n data: any;\n merge?: boolean;\n }>,\n ) => {\n const bulkWriter = db.bulkWriter();\n let pendingOps = 0;\n\n for (const item of items) {\n if (!item) continue;\n const { docRef, data, merge = true } = item;\n\n // Auto-set createdKey and updatedKey\n const enrichedData = { ...data };\n if (createdKey) {\n enrichedData[createdKey] = now();\n }\n if (updatedKey) {\n enrichedData[updatedKey] = now();\n }\n\n bulkWriter.set(docRef, enrichedData, { merge });\n pendingOps++;\n\n if (pendingOps >= 500) {\n await bulkWriter.flush();\n pendingOps = 0;\n }\n }\n\n await bulkWriter.close();\n },\n\n // Update multiple documents with automatic batching\n update: async (items: Array<{ docRef: DocumentReference; data: any }>) => {\n const bulkWriter = db.bulkWriter();\n let pendingOps = 0;\n\n for (const item of items) {\n if (!item) continue;\n const { docRef, data } = item;\n\n // Auto-set updatedKey\n const enrichedData = { ...data };\n if (updatedKey) {\n enrichedData[updatedKey] = now();\n }\n\n bulkWriter.update(docRef, enrichedData);\n pendingOps++;\n\n if (pendingOps >= 500) {\n await bulkWriter.flush();\n pendingOps = 0;\n }\n }\n\n await bulkWriter.close();\n },\n\n // Delete multiple documents with automatic batching\n delete: async (docRefs: DocumentReference[]) => {\n const bulkWriter = db.bulkWriter();\n let pendingOps = 0;\n\n for (const docRef of docRefs) {\n if (!docRef) continue;\n bulkWriter.delete(docRef);\n pendingOps++;\n\n if (pendingOps >= 500) {\n await bulkWriter.flush();\n pendingOps = 0;\n }\n }\n\n await bulkWriter.close();\n },\n };\n}\n","import type { CollectionReference } from \"firebase-admin/firestore\";\nimport { maybeNormalize } from \"../shared/date-config\";\n\n/**\n * Creates CRUD methods (create, set, update, delete).\n *\n * @template T - The document type\n * @param actualCollection - The collection reference (null for collection groups)\n * @param documentRef - Function to create document references\n * @param documentKey - The field name used as document ID\n * @param pathKey - Optional field name to store the document path\n * @param createdKey - Optional field name for creation timestamp\n * @param updatedKey - Optional field name for update timestamp\n * @returns Object containing CRUD methods\n *\n * @example\n * ```typescript\n * // CREATE - Add a new document\n * // Auto-generates docId if not provided, sets createdAt/updatedAt\n * const newUser = await repos.users.create({\n * name: \"John Doe\",\n * email: \"john@example.com\",\n * age: 28\n * });\n * console.log(newUser.docId); // Auto-generated ID\n *\n * // Create with custom docId\n * const customUser = await repos.users.create({\n * docId: \"custom-id-123\",\n * name: \"Jane Doe\",\n * email: \"jane@example.com\"\n * });\n *\n * // SET - Create or replace a document by ID\n * // For regular collections:\n * const user = await repos.users.set(\"user-123\", {\n * name: \"Updated Name\",\n * email: \"new@example.com\"\n * });\n *\n * // For subcollections (e.g., posts/{postId}/comments/{commentId}):\n * const comment = await repos.comments.set(\"post-123\", \"comment-456\", {\n * content: \"Great post!\",\n * likes: 0\n * });\n *\n * // Set with merge option (default: true)\n * await repos.users.set(\"user-123\", { name: \"Only Name\" }, { merge: true });\n *\n * // UPDATE - Partially update an existing document\n * const updatedUser = await repos.users.update(\"user-123\", {\n * name: \"New Name\"\n * });\n *\n * // Update subcollection document:\n * await repos.comments.update(\"post-123\", \"comment-456\", {\n * likes: 10\n * });\n *\n * // DELETE - Remove a document\n * await repos.users.delete(\"user-123\");\n *\n * // Delete subcollection document:\n * await repos.comments.delete(\"post-123\", \"comment-456\");\n * ```\n */\nexport function createCrudMethods<T>(\n actualCollection: CollectionReference | null,\n documentRef: (...args: any[]) => any,\n documentKey: string,\n pathKey?: string,\n createdKey?: string,\n updatedKey?: string,\n) {\n const now = () => new Date();\n\n // Create - adds a new document, optionally with a provided document key\n const create = async (data: any): Promise<T> => {\n if (!actualCollection) {\n throw new Error(\n \"Cannot use create() on collection groups. Use set() with a specific document ID instead.\",\n );\n }\n\n let docRef;\n let docId: string;\n\n // Auto-set createdKey and updatedKey\n const enrichedData = { ...data };\n if (createdKey) {\n enrichedData[createdKey] = now();\n }\n if (updatedKey) {\n enrichedData[updatedKey] = now();\n }\n\n // If documentKey is provided in data, use set() with that ID\n if (data[documentKey]) {\n docId = data[documentKey];\n docRef = actualCollection.doc(docId);\n // Also set pathKey if defined\n const dataWithPath = pathKey\n ? { ...enrichedData, [pathKey]: docRef.path }\n : enrichedData;\n await docRef.set(dataWithPath);\n } else {\n // Otherwise, use add() to auto-generate ID\n docRef = await actualCollection.add(enrichedData);\n docId = docRef.id;\n // Update the document to include the documentKey and optionally pathKey\n const updates: Record<string, string> = { [documentKey]: docId };\n if (pathKey) {\n updates[pathKey] = docRef.path;\n }\n await docRef.update(updates);\n }\n\n const createdDoc = await docRef.get();\n return maybeNormalize(createdDoc.data()) as T;\n };\n\n // Set - creates or replaces a document\n const set = async (...args: any[]): Promise<T> => {\n const lastArg = args[args.length - 1];\n const hasOptions =\n typeof lastArg === \"object\" && lastArg !== null && \"merge\" in lastArg;\n\n const data = hasOptions ? args[args.length - 2] : args[args.length - 1];\n const pathArgs = hasOptions ? args.slice(0, -2) : args.slice(0, -1);\n const mergeOption = hasOptions ? lastArg : { merge: true };\n\n const enrichedData = { ...data };\n\n // Auto-set updatedKey\n if (updatedKey) {\n enrichedData[updatedKey] = now();\n }\n\n const docRef = documentRef(...pathArgs);\n\n // Inject documentKey (last segment of the path args) and pathKey — same\n // behaviour as create() and batch.set() so the fields are always present.\n const docIdValue = pathArgs[pathArgs.length - 1];\n if (documentKey && docIdValue != null) {\n enrichedData[documentKey] = docIdValue;\n }\n if (pathKey) {\n enrichedData[pathKey] = docRef.path;\n }\n\n await docRef.set(enrichedData, mergeOption);\n\n const setDocument = await docRef.get();\n return maybeNormalize(setDocument.data()) as T;\n };\n\n // Update - updates a document and returns the merged object\n const update = async (...args: any[]): Promise<T> => {\n const data = args.pop();\n const pathArgs = args;\n\n // Auto-set updatedKey\n const enrichedData = { ...data };\n if (updatedKey) {\n enrichedData[updatedKey] = now();\n }\n\n const docRef = documentRef(...pathArgs);\n await docRef.update(enrichedData);\n\n const updatedDoc = await docRef.get();\n return maybeNormalize(updatedDoc.data()) as T;\n };\n\n // Delete - removes a document\n const deleteMethod = async (...args: any[]): Promise<void> => {\n const docRef = documentRef(...args);\n await docRef.delete();\n };\n\n return {\n create,\n set,\n update,\n delete: deleteMethod,\n };\n}\n","import type {\n CollectionReference,\n DocumentReference,\n DocumentSnapshot,\n Query,\n QuerySnapshot,\n} from \"firebase-admin/firestore\";\nimport { maybeNormalize } from \"../shared/date-config\";\nimport type { GetOptions } from \"../shared/types\";\nimport { capitalize, chunkArray } from \"../shared/utils\";\n\n/**\n * Creates get.by* methods for foreign keys.\n * These methods return a single document or null.\n *\n * @template T - The document type\n * @param collectionRef - Firestore query reference\n * @param foreignKeys - Array of field names to generate get methods for\n * @param actualCollection - The actual collection reference (null for collection groups)\n * @param documentRef - Function to create document references\n * @param documentKey - The field name used as document ID\n * @returns Object containing generated get methods\n *\n * @example\n * ```typescript\n * // Generated methods based on foreignKeys: [\"docId\", \"email\", \"slug\"]\n *\n * // Basic usage - get user by docId\n * const user = await repos.users.get.byDocId(\"user-123\");\n *\n * // Get user by email\n * const userByEmail = await repos.users.get.byEmail(\"john@example.com\");\n *\n * // With select - only return specific fields\n * const partialUser = await repos.users.get.byDocId(\"user-123\", {\n * select: [\"name\", \"email\"]\n * });\n *\n * // With returnDoc - get both data and Firestore DocumentSnapshot\n * const { data, doc } = await repos.users.get.byDocId(\"user-123\", {\n * returnDoc: true\n * });\n * console.log(\"Document path:\", doc.ref.path);\n *\n * // Get multiple documents by list of values\n * const users = await repos.users.get.byList(\"docId\", [\"user-1\", \"user-2\", \"user-3\"]);\n *\n * // Get by list with array-contains-any operator\n * const usersWithTags = await repos.users.get.byList(\n * \"tags\",\n * [\"admin\", \"moderator\"],\n * \"array-contains-any\"\n * );\n * ```\n */\nexport function createGetMethods<T>(\n collectionRef: Query,\n foreignKeys: readonly string[],\n actualCollection: CollectionReference | null,\n documentRef: (...args: any[]) => DocumentReference,\n documentKey: string,\n) {\n const getMethods: any = {};\n\n // get.byList - retrieve multiple documents by list of values\n getMethods.byList = async (\n key: string,\n values: any[],\n operator: \"in\" | \"array-contains-any\" = \"in\",\n options: GetOptions = {},\n ): Promise<T[] | { data: T; doc: DocumentSnapshot }[]> => {\n if (values.length === 0) return [];\n\n const results: (T | { data: T; doc: DocumentSnapshot })[] = [];\n const chunks = chunkArray(values, 30); // Firestore limits 'in' to 30 elements\n\n for (const chunk of chunks) {\n let q: Query = collectionRef as any;\n q = q.where(key, operator, chunk);\n\n // Apply select if specified\n if (options.select && options.select.length > 0) {\n q = q.select(...options.select.map((f) => String(f)));\n }\n\n const snapshot: QuerySnapshot = await q.get();\n\n snapshot.forEach((doc) => {\n const data = maybeNormalize(doc.data()) as T;\n results.push(options.returnDoc ? { data, doc } : data);\n });\n }\n\n return results as T[] | { data: T; doc: DocumentSnapshot }[];\n };\n\n // Generate get.by* methods for each foreign key\n foreignKeys.forEach((foreignKey: string) => {\n const methodName = `by${capitalize(String(foreignKey))}`;\n getMethods[methodName] = async (\n value: string,\n options: GetOptions | boolean = {},\n ): Promise<T | { data: T; doc: DocumentSnapshot } | null> => {\n // Handle legacy boolean returnDoc parameter\n const opts: GetOptions =\n typeof options === \"boolean\" ? { returnDoc: options } : options;\n\n // Special case: if foreignKey is the documentKey, use direct document reference\n if (String(foreignKey) === documentKey) {\n const docRef = documentRef(value);\n const doc = await docRef.get();\n if (!doc.exists) return null;\n const data = maybeNormalize(doc.data()) as T;\n return opts.returnDoc ? { data, doc } : data;\n }\n\n // For other keys, query by field value\n let q: Query = collectionRef as any;\n q = q.where(String(foreignKey), \"==\", value).limit(1);\n\n // Apply select if specified\n if (opts.select && opts.select.length > 0) {\n q = q.select(...opts.select.map((f) => String(f)));\n }\n\n const snapshot: QuerySnapshot = await q.get();\n if (snapshot.empty) return null;\n const doc = snapshot.docs[0];\n if (!doc) return null;\n const data = maybeNormalize(doc.data()) as T;\n return opts.returnDoc ? { data, doc } : data;\n };\n });\n\n return getMethods;\n}\n","import type { Query } from \"firebase-admin/firestore\";\nimport {\n createPaginationIterator,\n executePaginatedQuery,\n type PaginationOptions,\n type PaginationResult,\n} from \"../pagination\";\nimport { buildAndExecuteQuery } from \"../query-builder\";\nimport { maybeNormalize } from \"../shared/date-config\";\nimport type {\n QueryOptions,\n RelationConfig,\n WhereClause,\n} from \"../shared/types\";\nimport { applyQueryOptions, capitalize } from \"../shared/utils\";\n\n/**\n * Include configuration for a relation with optional select\n */\nexport interface IncludeConfig {\n /** The relation key to include */\n relation: string;\n /** Fields to select from the related documents (Firestore select) */\n select?: string[];\n}\n\n/**\n * Options for pagination with include support\n */\nexport interface PaginationWithIncludeOptions<\n T,\n TRelationKeys = string,\n> extends PaginationOptions<T> {\n /** Relations to include in results - can be relation keys or IncludeConfig objects */\n include?: (TRelationKeys | IncludeConfig)[];\n}\n\n/**\n * Creates query.by* methods for query keys.\n * These methods return arrays of documents matching a query condition.\n *\n * @template T - The document type\n * @param collectionRef - Firestore query reference\n * @param queryKeys - Array of field names to generate query methods for\n * @param relationalKeys - Optional relation configuration for includes\n * @param allRepositories - Optional map of all repositories for relation resolution\n * @returns Object containing generated query methods\n *\n * @example\n * ```typescript\n * // Generated methods based on queryKeys: [\"status\", \"categoryId\"]\n * // Basic usage - get all posts with status \"published\"\n * const publishedPosts = await repos.posts.query.byStatus(\"published\");\n *\n * // With options - filter, sort, limit and select\n * const recentPosts = await repos.posts.query.byStatus(\"published\", {\n * orderBy: [[\"createdAt\", \"desc\"]],\n * limit: 10,\n * select: [\"title\", \"createdAt\"]\n * });\n *\n * // Generic query.by with full options\n * const filteredPosts = await repos.posts.query.by({\n * where: [[\"views\", \">=\", 1000]],\n * orWhere: [\n * [\"status\", \"==\", \"published\"],\n * [\"status\", \"==\", \"featured\"]\n * ],\n * orderBy: [[\"views\", \"desc\"]],\n * limit: 20\n * });\n *\n * // Pagination with include (relation population)\n * const paginatedPosts = await repos.posts.query.paginate({\n * pageSize: 10,\n * orderBy: [[\"createdAt\", \"desc\"]],\n * include: [\"userId\", { relation: \"categoryId\", select: [\"name\"] }]\n * });\n *\n * // Iterate through all pages\n * for await (const page of repos.posts.query.paginateAll({ pageSize: 50 })) {\n * console.log(`Processing ${page.data.length} posts`);\n * }\n * ```\n */\nexport function createQueryMethods<T>(\n collectionRef: Query,\n queryKeys: readonly string[],\n relationalKeys?: Record<string, RelationConfig>,\n allRepositories?: Record<string, any>,\n) {\n const queryMethods: any = {};\n\n /**\n * Resolve included relations for a list of documents (parallel per document,\n * parallel per relation). Stores results by field key to avoid repo-name collisions.\n */\n const populateDocuments = async (\n documents: T[],\n includeConfigs: (string | IncludeConfig)[],\n ): Promise<(T & { populated: Record<string, any> })[]> => {\n if (!relationalKeys || !allRepositories || includeConfigs.length === 0) {\n return documents as any;\n }\n\n const normalizedConfigs: { key: string; select?: string[] }[] =\n includeConfigs.map((cfg) =>\n typeof cfg === \"string\"\n ? { key: cfg }\n : { key: cfg.relation, select: cfg.select },\n );\n\n return Promise.all(\n documents.map(async (doc) => {\n const entries = await Promise.all(\n normalizedConfigs.map(async ({ key, select }) => {\n const relation = relationalKeys[key];\n if (!relation) return [key, undefined] as const;\n\n const targetRepo = allRepositories[relation.repo];\n if (!targetRepo) return [key, undefined] as const;\n\n const fieldValue = (doc as any)[key];\n if (fieldValue === undefined || fieldValue === null) {\n return [key, relation.type === \"one\" ? null : []] as const;\n }\n\n const opts = select ? { select } : undefined;\n\n try {\n if (relation.type === \"one\") {\n const method = `by${capitalize(relation.key)}`;\n const result =\n typeof targetRepo.get?.[method] === \"function\"\n ? await targetRepo.get[method](fieldValue, opts)\n : null;\n return [key, result] as const;\n } else {\n const method = `by${capitalize(relation.key)}`;\n const result =\n typeof targetRepo.query?.[method] === \"function\"\n ? await targetRepo.query[method](fieldValue, opts)\n : [];\n return [key, result] as const;\n }\n } catch (err) {\n console.error(`[include] Error populating \"${key}\":`, err);\n return [key, relation.type === \"one\" ? null : []] as const;\n }\n }),\n );\n\n const populated: Record<string, any> = {};\n for (const [k, v] of entries) {\n if (k !== undefined) populated[k] = v;\n }\n return { ...doc, populated };\n }),\n );\n };\n\n // Generate query.by* methods — inject queryKey condition into options so\n // orWhere and other advanced options are all handled by buildAndExecuteQuery.\n queryKeys.forEach((queryKey: string) => {\n const methodName = `by${capitalize(queryKey)}`;\n queryMethods[methodName] = async (\n value: any,\n options: QueryOptions<T> = {},\n ): Promise<T[]> => {\n const mergedOptions: QueryOptions<T> = {\n ...options,\n where: [\n [queryKey, \"==\", value] as unknown as WhereClause<T>,\n ...(options.where ?? []),\n ],\n };\n const snapshot = await buildAndExecuteQuery<T>(\n collectionRef,\n mergedOptions,\n );\n return snapshot.docs.map((doc) => maybeNormalize(doc.data()) as T);\n };\n });\n\n // Generic query.by — full orWhere support via buildAndExecuteQuery\n queryMethods.by = async (options: QueryOptions<T>): Promise<T[]> => {\n const snapshot = await buildAndExecuteQuery<T>(collectionRef, options);\n return snapshot.docs.map((doc) => maybeNormalize(doc.data()) as T);\n };\n\n // getAll — full orWhere support via buildAndExecuteQuery\n queryMethods.getAll = async (options: QueryOptions<T> = {}): Promise<T[]> => {\n const snapshot = await buildAndExecuteQuery<T>(collectionRef, options);\n return snapshot.docs.map((doc) => maybeNormalize(doc.data()) as T);\n };\n\n // onSnapshot — real-time listener (orWhere not supported by Firestore SDK real-time)\n queryMethods.onSnapshot = (\n options: QueryOptions<T>,\n onNext: (data: T[]) => void,\n onError?: (error: Error) => void,\n ): (() => void) => {\n const q = applyQueryOptions(collectionRef, options);\n return q.onSnapshot((snapshot) => {\n onNext(snapshot.docs.map((doc) => maybeNormalize(doc.data()) as T));\n }, onError);\n };\n\n // Paginate — includes relation resolution after each page\n queryMethods.paginate = async (\n options: PaginationWithIncludeOptions<T, string>,\n ): Promise<\n | PaginationResult<T>\n | PaginationResult<T & { populated: Record<string, any> }>\n > => {\n const { include, ...paginationOptions } = options;\n const result = await executePaginatedQuery<T>(\n collectionRef,\n paginationOptions,\n );\n\n if (include && include.length > 0) {\n const populatedData = await populateDocuments(result.data, include);\n return { ...result, data: populatedData };\n }\n\n return result;\n };\n\n queryMethods.paginateAll = async function* (\n options: Omit<\n PaginationWithIncludeOptions<T, string>,\n \"cursor\" | \"direction\"\n >,\n ): AsyncGenerator<\n | PaginationResult<T>\n | PaginationResult<T & { populated: Record<string, any> }>,\n void,\n unknown\n > {\n const { include, ...paginationOptions } = options;\n for await (const page of createPaginationIterator<T>(\n collectionRef,\n paginationOptions,\n )) {\n if (include && include.length > 0) {\n const populatedData = await populateDocuments(page.data, include);\n yield { ...page, data: populatedData };\n } else {\n yield page;\n }\n }\n };\n\n return queryMethods;\n}\n","import type { RelationConfig, RepositoryConfig } from \"../shared/types\";\nimport { capitalize } from \"../shared/utils\";\n\n/**\n * Options for populate with select support.\n * Two formats:\n * - Single relation: { relation: \"userId\", select: [\"name\", \"email\"] }\n * - Multiple relations: { relations: [\"userId\", \"editorId\"], select: { userId: [\"name\"] } }\n */\nexport type PopulateOptions<TRelationKey = string> =\n | {\n relation: TRelationKey;\n select?: string[];\n }\n | {\n relations: TRelationKey | TRelationKey[];\n select?: Partial<Record<string, string[]>>;\n };\n\n/**\n * Creates populate methods for resolving relations between repositories.\n * Results are keyed by the **field name** (relation key) — not the repo name —\n * to avoid collisions when two fields point to the same repository.\n *\n * @template TConfig - Repository configuration type\n * @param config - Repository configuration with relational keys\n * @param allRepositories - Map of all repositories for relation resolution\n * @returns Object containing the populate method\n *\n * @example\n * ```typescript\n * // Assume relations configured as:\n * // posts.userId -> users.docId (one-to-one)\n * // posts.categoryId -> categories.docId (one-to-one)\n * // users.docId -> posts.userId (one-to-many)\n *\n * // POPULATE SINGLE RELATION - Get post with its author\n * const post = await repos.posts.get.byDocId(\"post-123\");\n * const postWithAuthor = await repos.posts.populate(post, \"userId\");\n * console.log(postWithAuthor.populated.userId); // User object\n *\n * // POPULATE WITH SELECT - Only fetch specific fields\n * const postWithPartialAuthor = await repos.posts.populate(post, {\n * relation: \"userId\",\n * select: [\"name\", \"email\", \"avatar\"]\n * });\n * console.log(postWithPartialAuthor.populated.userId.name);\n *\n * // POPULATE MULTIPLE RELATIONS - Get post with author and category\n * const postWithRelations = await repos.posts.populate(post, [\"userId\", \"categoryId\"]);\n * console.log(postWithRelations.populated.userId); // User object\n * console.log(postWithRelations.populated.categoryId); // Category object\n *\n * // POPULATE MULTIPLE WITH DIFFERENT SELECTS\n * const postWithCustomSelects = await repos.posts.populate(post, {\n * relations: [\"userId\", \"categoryId\"],\n * select: {\n * userId: [\"name\", \"avatar\"],\n * categoryId: [\"name\", \"slug\"]\n * }\n * });\n *\n * // POPULATE ONE-TO-MANY - Get user with all their posts\n * const user = await repos.users.get.byDocId(\"user-123\");\n * const userWithPosts = await repos.users.populate(user, \"docId\");\n * console.log(userWithPosts.populated.docId); // Array of Post objects\n *\n * // With select on one-to-many\n * const userWithPartialPosts = await repos.users.populate(user, {\n * relation: \"docId\",\n * select: [\"title\", \"status\", \"createdAt\"]\n * });\n *\n * // Chained population (nested relations)\n * const post = await repos.posts.get.byDocId(\"post-123\");\n * const postWithAuthor = await repos.posts.populate(post, \"userId\");\n * // If you need author's posts too:\n * const authorWithPosts = await repos.users.populate(\n * postWithAuthor.populated.userId,\n * \"docId\"\n * );\n * ```\n *\n * @internal\n */\nexport function createPopulateMethods<\n TConfig extends RepositoryConfig<\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any\n >,\n>(\n config: TConfig,\n allRepositories: Record<string, any>,\n): {\n populate: <\n K extends keyof NonNullable<TConfig[\"relationalKeys\"]>,\n TDoc extends Pick<TConfig[\"type\"], K>,\n >(\n document: TDoc,\n relationKeyOrOptions: K | K[] | PopulateOptions<K>,\n ) => Promise<TDoc & { populated: Record<string, any> }>;\n} {\n return {\n populate: async (document: any, relationKeyOrOptions: any) => {\n if (!config.relationalKeys) {\n return { ...document, populated: {} };\n }\n\n // Parse options into a list of keys + per-key select map\n let keys: string[];\n let selectMap: Record<string, string[]> = {};\n\n if (\n typeof relationKeyOrOptions === \"object\" &&\n !Array.isArray(relationKeyOrOptions)\n ) {\n if (\"relation\" in relationKeyOrOptions) {\n const opts = relationKeyOrOptions as {\n relation: string;\n select?: string[];\n };\n keys = [opts.relation];\n if (opts.select) selectMap[opts.relation] = opts.select;\n } else if (\"relations\" in relationKeyOrOptions) {\n const opts = relationKeyOrOptions as {\n relations: string | string[];\n select?: Record<string, string[]>;\n };\n keys = Array.isArray(opts.relations)\n ? opts.relations\n : [opts.relations];\n selectMap = opts.select ?? {};\n } else {\n keys = [];\n }\n } else {\n keys = Array.isArray(relationKeyOrOptions)\n ? relationKeyOrOptions\n : [relationKeyOrOptions];\n }\n\n // Resolve all relations in parallel\n const entries = await Promise.all(\n keys.map(async (key) => {\n const relation: RelationConfig | undefined =\n config.relationalKeys?.[key as string];\n if (!relation) {\n console.warn(`[populate] Relation \"${key}\" not found in config`);\n return [key, undefined] as const;\n }\n\n const targetRepo = allRepositories[relation.repo];\n if (!targetRepo) {\n console.warn(\n `[populate] Repository \"${relation.repo}\" not found in mapping`,\n );\n return [key, undefined] as const;\n }\n\n const fieldValue = document[key];\n if (fieldValue === undefined || fieldValue === null) {\n return [key, relation.type === \"one\" ? null : []] as const;\n }\n\n const selectFields = selectMap[key];\n const opts = selectFields ? { select: selectFields } : undefined;\n\n try {\n if (relation.type === \"one\") {\n const method = `by${capitalize(relation.key)}`;\n const result =\n typeof targetRepo.get?.[method] === \"function\"\n ? await targetRepo.get[method](fieldValue, opts)\n : null;\n return [key, result] as const;\n } else {\n const method = `by${capitalize(relation.key)}`;\n const result =\n typeof targetRepo.query?.[method] === \"function\"\n ? await targetRepo.query[method](fieldValue, opts)\n : [];\n return [key, result] as const;\n }\n } catch (err) {\n console.error(`[populate] Error populating \"${key}\":`, err);\n return [key, relation.type === \"one\" ? null : []] as const;\n }\n }),\n );\n\n const populated: Record<string, any> = {};\n for (const [k, v] of entries) {\n if (v !== undefined) populated[k] = v;\n }\n\n return { ...document, populated };\n },\n };\n}\n","import type { Firestore } from \"firebase-admin/firestore\";\nimport { maybeNormalize } from \"../shared/date-config\";\n\n/**\n * Creates transaction operation methods for atomic read-write operations.\n * Transactions ensure consistency when reading and writing data atomically.\n *\n * @param db - Firestore database instance\n * @param documentRef - Function to create document references\n * @returns Object containing the transaction run method\n *\n * @example\n * ```typescript\n * // Basic transaction - transfer points between users\n * const result = await repos.users.transaction.run(async (tx) => {\n * // Read both users\n * const sender = await tx.get(\"sender-id\");\n * const receiver = await tx.get(\"receiver-id\");\n *\n * if (!sender || sender.points < 100) {\n * throw new Error(\"Insufficient points\");\n * }\n *\n * // Update both atomically\n * tx.update(\"sender-id\", { points: sender.points - 100 });\n * tx.update(\"receiver-id\", { points: (receiver?.points || 0) + 100 });\n *\n * return { transferred: 100 };\n * });\n *\n * // Transaction with subcollections\n * await repos.comments.transaction.run(async (tx) => {\n * // Get comment from subcollection (postId, commentId)\n * const comment = await tx.get(\"post-123\", \"comment-456\");\n *\n * // Update the comment\n * tx.update(\"post-123\", \"comment-456\", {\n * likes: (comment?.likes || 0) + 1\n * });\n * });\n *\n * // Transaction with set and delete\n * await repos.orders.transaction.run(async (tx) => {\n * const order = await tx.get(\"order-id\");\n *\n * // Create archive entry\n * tx.set(\"archived-order-id\", {\n * ...order,\n * archivedAt: new Date()\n * });\n *\n * // Delete original\n * tx.delete(\"order-id\");\n * });\n *\n * // Access raw Firestore transaction for advanced use\n * await repos.users.transaction.run(async (tx) => {\n * // Use raw transaction for cross-collection operations\n * const rawTx = tx.raw;\n * const otherDoc = await rawTx.get(db.collection(\"other\").doc(\"id\"));\n * // ...\n * });\n *\n * // Transaction with merge option\n * await repos.users.transaction.run(async (tx) => {\n * tx.set(\"user-id\", { lastLogin: new Date() }, { merge: true });\n * });\n * ```\n */\nexport function createTransactionMethods(\n db: Firestore,\n documentRef: (...args: any[]) => any,\n) {\n return {\n run: async <R>(\n updateFunction: (transaction: any) => Promise<R>,\n ): Promise<R> => {\n return db.runTransaction(async (rawTransaction) => {\n const typedTransaction = {\n // Type-safe get method\n get: async (...args: any[]) => {\n const docRef = documentRef(...args);\n const docSnap = (await rawTransaction.get(docRef)) as any;\n if (!docSnap.exists) return null;\n return maybeNormalize({ ...docSnap.data(), docId: docSnap.id }) as any;\n },\n\n // Type-safe set method\n set: (...args: any[]) => {\n const options = args[args.length - 1];\n const hasOptions =\n typeof options === \"object\" &&\n options !== null &&\n \"merge\" in options;\n\n const data = hasOptions\n ? args[args.length - 2]\n : args[args.length - 1];\n const pathArgs = hasOptions ? args.slice(0, -2) : args.slice(0, -1);\n const mergeOption = hasOptions ? options : { merge: true };\n\n const docRef = documentRef(...pathArgs);\n rawTransaction.set(docRef, data, mergeOption);\n },\n\n // Type-safe update method\n update: (...args: any[]) => {\n const data = args[args.length - 1];\n const pathArgs = args.slice(0, -1);\n const docRef = documentRef(...pathArgs);\n rawTransaction.update(docRef, data);\n },\n\n // Delete method\n delete: (...args: any[]) => {\n const docRef = documentRef(...args);\n rawTransaction.delete(docRef);\n },\n\n // Access to raw transaction\n raw: rawTransaction,\n };\n\n return updateFunction(typedTransaction);\n });\n },\n };\n}\n","import type {\n CollectionReference,\n Firestore,\n Query,\n} from \"firebase-admin/firestore\";\nimport { createAggregateMethods } from \"../methods/aggregate\";\nimport { createBatchMethods } from \"../methods/batch\";\nimport { createBulkMethods } from \"../methods/bulk\";\nimport { createCrudMethods } from \"../methods/crud\";\nimport { createGetMethods } from \"../methods/get\";\nimport { createQueryMethods } from \"../methods/query\";\nimport { createPopulateMethods } from \"../methods/relations\";\nimport { createTransactionMethods } from \"../methods/transaction\";\nimport type { RepositoryConfig } from \"../shared/types\";\nimport type { ConfiguredRepository } from \"./types\";\n\n/**\n * Extract parent-key parameter names from a refCb function.\n * For `(db, postId, docId) => …` this returns `[\"postId\"]` (everything\n * between the first param – the Firestore `db` – and the last param – the\n * document's own ID).\n * Returns an empty array when the function has ≤ 2 params (db + docId).\n * @internal\n */\nfunction extractParentKeys(refCb: unknown): string[] {\n if (typeof refCb !== \"function\") return [];\n const src = refCb.toString();\n const match = src.match(/^\\s*(?:function\\s*\\w*\\s*)?\\(([^)]*)\\)/);\n if (!match?.[1]) return [];\n const params = match[1]\n .split(\",\")\n .map((p) => p.trim().replace(/\\s*[:=].*$/, \"\").trim())\n .filter(Boolean);\n // (db, docId) → 0 parents; (db, parentId, docId) → 1 parent; etc.\n if (params.length <= 2) return [];\n return params.slice(1, -1);\n}\n\n/**\n * Creates a configured repository instance with all methods\n */\nexport function createRepository<\n T extends RepositoryConfig<any, any, any, any, any, any, any, any, any, any>,\n>(\n db: Firestore,\n config: T,\n allRepositories: Record<string, any> = {},\n): ConfiguredRepository<T> {\n // Create collection reference\n const collectionRef: CollectionReference | Query = config.isGroup\n ? db.collectionGroup(config.path)\n : db.collection(config.path);\n\n // Keep actual collection for create operations\n const actualCollection = config.isGroup ? null : db.collection(config.path);\n\n // Create document reference function\n const documentRef = (...args: any[]) => (config.refCb as any)(db, ...args);\n\n // Create all method groups\n const getMethods = createGetMethods(\n collectionRef as Query,\n config.foreignKeys,\n actualCollection,\n documentRef,\n config.documentKey as string,\n );\n const queryMethods = createQueryMethods(\n collectionRef as Query,\n config.queryKeys,\n config.relationalKeys as Record<string, any> | undefined,\n allRepositories,\n );\n const aggregateMethods = createAggregateMethods(collectionRef as Query);\n const crudMethods = createCrudMethods(\n actualCollection,\n documentRef,\n config.documentKey as string,\n config.pathKey as string | undefined,\n config.createdKey as string | undefined,\n config.updatedKey as string | undefined,\n );\n const batchMethods = createBatchMethods(\n db,\n documentRef,\n config.documentKey as string,\n config.pathKey as string | undefined,\n config.createdKey as string | undefined,\n config.updatedKey as string | undefined,\n );\n const transactionMethods = createTransactionMethods(db, documentRef);\n const bulkMethods = createBulkMethods(\n db,\n config.createdKey as string | undefined,\n config.updatedKey as string | undefined,\n );\n const populateMethods = createPopulateMethods(config, allRepositories);\n\n return {\n ref: collectionRef,\n documentRef,\n get: getMethods,\n query: queryMethods,\n aggregate: aggregateMethods,\n ...crudMethods,\n batch: batchMethods,\n transaction: transactionMethods,\n bulk: bulkMethods,\n ...populateMethods,\n // Pass through the Zod schema if one was attached via createRepositoryConfig(schema)\n schema: (config as any).schema,\n // Pass through relational keys built by buildRepositoryRelations\n relationalKeys: (config as any).relationalKeys,\n // Auto-managed keys that should never be accepted in user-provided payloads\n _systemKeys: [\n config.documentKey as string,\n config.pathKey as string | undefined,\n config.createdKey as string | undefined,\n config.updatedKey as string | undefined,\n ].filter((k): k is string => typeof k === \"string\"),\n // Expose pathKey name so server handlers can extract path args from documents\n _pathKey: (config.pathKey as string | undefined) ?? null,\n // Whether this is a collectionGroup repository\n _isGroup: !!config.isGroup,\n // Parent key field names auto-detected from refCb signature\n _parentKeys: config.isGroup\n ? extractParentKeys(config.refCb)\n : [],\n // Expose createdKey so server handlers can inject it when using set() for creates\n _createdKey: (config.createdKey as string | undefined) ?? null,\n } as unknown as ConfiguredRepository<T>;\n}\n","/**\n * Minimal zero-dependency HTTP router for Firebase Functions.\n * Compatible with any Express-like (req, res) handler.\n *\n * Supports:\n * - Named path parameters (e.g. \"/repos/:name/:id\")\n * - GET, POST, DELETE methods\n * - Global middleware (before each route)\n * - 404 / error fallbacks\n *\n * @example\n * ```typescript\n * import { MiniRouter } from \"@lpdjs/firestore-repo-service/servers/admin\";\n *\n * // Create router\n * const router = new MiniRouter();\n *\n * // Add global middleware (executed before every route)\n * router.use(async (req, res, next) => {\n * console.log(`${req.method} ${req.url}`);\n * await next();\n * });\n *\n * // Auth middleware\n * router.use((req, res, next) => {\n * if (!req.headers?.authorization) {\n * res.status(401).send(\"Unauthorized\");\n * return;\n * }\n * next();\n * });\n *\n * // Define routes with path parameters\n * router.get(\"/users\", async (req, res) => {\n * res.json({ users: await getAllUsers() });\n * });\n *\n * router.get(\"/users/:id\", async (req, res) => {\n * const user = await getUser(req.params.id); // Access path params\n * if (!user) {\n * res.status(404).send(\"User not found\");\n * return;\n * }\n * res.json(user);\n * });\n *\n * router.post(\"/users\", async (req, res) => {\n * const user = await createUser(req.body);\n * res.status(201).json(user);\n * });\n *\n * router.delete(\"/users/:id\", async (req, res) => {\n * await deleteUser(req.params.id);\n * res.status(204).end();\n * });\n *\n * // Custom 404 handler\n * router.onNotFound((req, res) => {\n * res.status(404).json({ error: \"Route not found\", path: req.url });\n * });\n *\n * // Custom error handler\n * router.onError((err, req, res) => {\n * console.error(\"Error:\", err);\n * res.status(500).json({ error: \"Internal server error\" });\n * });\n *\n * // Use with Firebase Functions\n * export const api = onRequest(async (req, res) => {\n * await router.handle(req, res);\n * });\n * ```\n */\n\nexport type AnyReq = {\n method?: string;\n url?: string;\n /** Express originalUrl — preserved before any router stripping, contains the full path including the Firebase Functions prefix */\n originalUrl?: string;\n path?: string;\n headers?: Record<string, string | string[] | undefined>;\n body?: unknown;\n query?: Record<string, string | string[] | undefined>;\n};\n\nexport type AnyRes = {\n status: (code: number) => AnyRes;\n set: (key: string, value: string) => AnyRes;\n send: (body: string) => void;\n json: (body: unknown) => void;\n end: () => void;\n};\n\nexport type RouteParams = Record<string, string>;\n\nexport type RouteHandler = (\n req: AnyReq & { params: RouteParams },\n res: AnyRes,\n) => void | Promise<void>;\n\nexport type Middleware = (\n req: AnyReq & { params: RouteParams },\n res: AnyRes,\n next: () => void | Promise<void>,\n) => void | Promise<void>;\n\n// ---------------------------------------------------------------------------\n// Route matching\n// ---------------------------------------------------------------------------\n\ninterface CompiledRoute {\n method: string;\n pattern: RegExp;\n paramNames: string[];\n handler: RouteHandler;\n}\n\nfunction compilePath(path: string): { pattern: RegExp; paramNames: string[] } {\n const paramNames: string[] = [];\n const src = path\n .replace(/[.*+?^${}()|[\\]\\\\]/g, (c) => (c === \":\" ? c : `\\\\${c}`))\n .replace(/:([a-zA-Z_][a-zA-Z0-9_]*)/g, (_match, name: string) => {\n paramNames.push(name);\n return \"([^/]+)\";\n });\n\n return { pattern: new RegExp(`^${src}$`), paramNames };\n}\n\nfunction extractPath(req: AnyReq): string {\n const raw = req.path ?? req.url ?? \"/\";\n const idx = raw.indexOf(\"?\");\n return idx === -1 ? raw : raw.slice(0, idx);\n}\n\n// ---------------------------------------------------------------------------\n// Router class\n// ---------------------------------------------------------------------------\n\nexport class MiniRouter {\n private routes: CompiledRoute[] = [];\n private middlewares: Middleware[] = [];\n private notFoundHandler: RouteHandler = (_req, res) => {\n res.status(404).send(\"Not Found\");\n };\n private errorHandler: (err: unknown, req: AnyReq, res: AnyRes) => void = (\n err,\n _req,\n res,\n ) => {\n console.error(\"[MiniRouter]\", err);\n res.status(500).send(\"Internal Server Error\");\n };\n\n // ── Route registration ────────────────────────────────────────────────────\n\n use(middleware: Middleware): this {\n this.middlewares.push(middleware);\n return this;\n }\n\n get(path: string, handler: RouteHandler): this {\n return this.addRoute(\"GET\", path, handler);\n }\n\n post(path: string, handler: RouteHandler): this {\n return this.addRoute(\"POST\", path, handler);\n }\n\n put(path: string, handler: RouteHandler): this {\n return this.addRoute(\"PUT\", path, handler);\n }\n\n patch(path: string, handler: RouteHandler): this {\n return this.addRoute(\"PATCH\", path, handler);\n }\n\n delete(path: string, handler: RouteHandler): this {\n return this.addRoute(\"DELETE\", path, handler);\n }\n\n onNotFound(handler: RouteHandler): this {\n this.notFoundHandler = handler;\n return this;\n }\n\n onError(handler: (err: unknown, req: AnyReq, res: AnyRes) => void): this {\n this.errorHandler = handler;\n return this;\n }\n\n private addRoute(method: string, path: string, handler: RouteHandler): this {\n const { pattern, paramNames } = compilePath(path);\n this.routes.push({\n method: method.toUpperCase(),\n pattern,\n paramNames,\n handler,\n });\n return this;\n }\n\n // ── Dispatch ──────────────────────────────────────────────────────────────\n\n async handle(req: AnyReq, res: AnyRes): Promise<void> {\n const method = (req.method ?? \"GET\").toUpperCase();\n const path = extractPath(req);\n\n // Find matching route\n let matchedRoute: CompiledRoute | null = null;\n let params: RouteParams = {};\n\n for (const route of this.routes) {\n if (route.method !== method) continue;\n const m = path.match(route.pattern);\n if (m) {\n matchedRoute = route;\n params = {};\n route.paramNames.forEach((name, i) => {\n params[name] = decodeURIComponent(m[i + 1] ?? \"\");\n });\n break;\n }\n }\n\n const enrichedReq = Object.assign(req, { params });\n\n // Run middleware chain → then handler\n const handler = matchedRoute ? matchedRoute.handler : this.notFoundHandler;\n\n try {\n await this.runMiddlewareChain(enrichedReq, res, handler);\n } catch (err) {\n this.errorHandler(err, req, res);\n }\n }\n\n private async runMiddlewareChain(\n req: AnyReq & { params: RouteParams },\n res: AnyRes,\n finalHandler: RouteHandler,\n ): Promise<void> {\n let index = 0;\n\n const next = async (): Promise<void> => {\n if (index < this.middlewares.length) {\n const mw = this.middlewares[index++]!;\n await mw(req, res, next);\n } else {\n await finalHandler(req, res);\n }\n };\n\n await next();\n }\n}\n","import { z } from \"zod\";\nimport {\n getTypeName,\n getInnerType,\n getShape,\n} from \"../shared/zod-compat\";\nimport { SYNC_VERSION_COLUMN } from \"./constants\";\nimport type { SqlColumn, SqlDialect, LogicalType } from \"./types\";\n\nconst WRAPPER_TYPES = new Set([\"ZodOptional\", \"ZodNullable\", \"ZodDefault\"]);\n\nfunction unwrap(schema: z.ZodType): { inner: z.ZodType; nullable: boolean } {\n let current = schema;\n let nullable = false;\n\n for (;;) {\n const name = getTypeName(current);\n if (!WRAPPER_TYPES.has(name)) break;\n if (name === \"ZodOptional\" || name === \"ZodNullable\") nullable = true;\n const inner = getInnerType(current);\n if (!inner) break;\n current = inner;\n }\n\n return { inner: current, nullable };\n}\n\nconst LOGICAL_MAP: Record<string, LogicalType> = {\n ZodString: \"string\",\n ZodNumber: \"number\",\n ZodBigInt: \"bigint\",\n ZodBoolean: \"boolean\",\n ZodDate: \"timestamp\",\n ZodEnum: \"string\",\n ZodNativeEnum: \"string\",\n ZodLiteral: \"string\",\n};\n\nexport function zodTypeToLogical(schema: z.ZodType): LogicalType {\n const { inner } = unwrap(schema);\n return LOGICAL_MAP[getTypeName(inner)] ?? \"json\";\n}\n\nexport interface ZodSchemaToColumnsOptions {\n primaryKey?: string;\n exclude?: string[];\n columnMap?: Record<string, string>;\n}\n\n/**\n * Recursively flatten a Zod object schema into flat SQL columns.\n * Nested objects produce `parent_child` column names.\n * Arrays and non-object complex types become JSON columns.\n */\nfunction flattenSchema(\n shape: Record<string, z.ZodType>,\n dialect: SqlDialect,\n prefix: string,\n parentNullable: boolean,\n excludeSet: Set<string>,\n columnMap: Record<string, string>,\n primaryKey: string | undefined,\n columns: SqlColumn[],\n): void {\n for (const [field, fieldSchema] of Object.entries(shape)) {\n const fullKey = prefix ? `${prefix}__${field}` : field;\n\n // Exclude check on the original (dotless) path and the flattened key\n if (excludeSet.has(field) || excludeSet.has(fullKey)) continue;\n\n const { inner, nullable } = unwrap(fieldSchema);\n const typeName = getTypeName(inner);\n const isNullable = parentNullable || nullable;\n\n // Nested object → recurse to flatten\n if (typeName === \"ZodObject\") {\n const nestedShape = getShape(inner as z.ZodObject<any>);\n flattenSchema(\n nestedShape,\n dialect,\n fullKey,\n isNullable,\n excludeSet,\n columnMap,\n primaryKey,\n columns,\n );\n continue;\n }\n\n // Arrays and other complex types → JSON\n const logical = LOGICAL_MAP[typeName] ?? \"json\";\n const isPK = fullKey === primaryKey || field === primaryKey;\n const colName = columnMap[fullKey] ?? columnMap[field] ?? fullKey;\n\n columns.push({\n name: colName,\n sqlType: dialect.mapType(logical),\n nullable: isPK ? false : isNullable,\n isPrimaryKey: isPK,\n });\n }\n}\n\n/**\n * Convert a Zod object schema into an array of {@link SqlColumn} definitions\n * suitable for SQL table creation.\n *\n * Nested ZodObject fields are recursively flattened into separate columns\n * with underscore-separated names (e.g. `address.street` → `address_street`).\n * Arrays become JSON columns.\n */\nexport function zodSchemaToColumns(\n schema: z.ZodObject<any>,\n dialect: SqlDialect,\n options: ZodSchemaToColumnsOptions = {},\n): SqlColumn[] {\n const { primaryKey, exclude = [], columnMap = {} } = options;\n const excludeSet = new Set(exclude);\n const shape = getShape(schema);\n const columns: SqlColumn[] = [];\n\n flattenSchema(shape, dialect, \"\", false, excludeSet, columnMap, primaryKey, columns);\n\n // Internal version column used by the worker to discard out-of-order\n // PubSub deliveries (added unconditionally — never excluded).\n if (!columns.some((c) => c.name === SYNC_VERSION_COLUMN)) {\n columns.push({\n name: SYNC_VERSION_COLUMN,\n sqlType: dialect.mapType(\"bigint\"),\n nullable: true,\n isPrimaryKey: false,\n description: \"Monotonic publish version (Date.now() ms). Internal.\",\n });\n }\n\n return columns;\n}\n","/**\n * Internal constants shared between the worker, queue, schema mapper and\n * SQL adapters.\n */\n\n/**\n * Name of the SQL column that stores the publish-time `version` of each\n * sync event. Used by the worker to discard out-of-order PubSub deliveries\n * (the MERGE only updates rows when the incoming version is strictly\n * greater than the stored one).\n *\n * Two underscores prefix avoids collisions with user-defined fields.\n */\nexport const SYNC_VERSION_COLUMN = \"__sync_version\";\n","import type { RepoSyncConfig } from \"./types\";\n\n/**\n * Convert a single Firestore value into a SQL-safe primitive.\n *\n * Complex types (arrays, GeoPoints, binary) become JSON strings.\n * Primitives pass through unchanged.\n * Objects are NOT stringified here — they are flattened by serializeDocument.\n */\nexport function serializeValue(value: unknown): unknown {\n if (value === null || value === undefined) return null;\n\n // Firestore Timestamp (duck-typed: has .toDate())\n if (\n typeof value === \"object\" &&\n typeof (value as Record<string, unknown>).toDate === \"function\"\n ) {\n return ((value as { toDate(): Date }).toDate()).toISOString();\n }\n\n if (value instanceof Date) return value.toISOString();\n\n if (Buffer.isBuffer(value)) return value.toString(\"base64\");\n\n if (value instanceof Uint8Array) {\n return Buffer.from(value).toString(\"base64\");\n }\n\n // Firestore GeoPoint (duck-typed: has latitude & longitude)\n if (\n typeof value === \"object\" &&\n \"latitude\" in (value as object) &&\n \"longitude\" in (value as object)\n ) {\n const geo = value as { latitude: number; longitude: number };\n return JSON.stringify({ lat: geo.latitude, lng: geo.longitude });\n }\n\n // Arrays → JSON (native JSON column in BigQuery)\n if (Array.isArray(value)) {\n return JSON.stringify(value.map(serializeValue));\n }\n\n // string | number | boolean — pass through\n // Plain objects are handled by flattenObject in serializeDocument\n return value;\n}\n\n/**\n * Recursively flatten a nested object into a flat key-value map\n * using underscore-separated keys: `{ address: { street: \"x\" } }` → `{ address_street: \"x\" }`.\n * Arrays and non-plain-object values are serialized as leaves.\n */\nfunction flattenObject(\n obj: Record<string, unknown>,\n prefix: string,\n result: Record<string, unknown>,\n): void {\n for (const [key, value] of Object.entries(obj)) {\n const flatKey = prefix ? `${prefix}__${key}` : key;\n\n if (\n value !== null &&\n value !== undefined &&\n typeof value === \"object\" &&\n !Array.isArray(value) &&\n !(value instanceof Date) &&\n !Buffer.isBuffer(value) &&\n !(value instanceof Uint8Array) &&\n // Not a Firestore Timestamp\n typeof (value as Record<string, unknown>).toDate !== \"function\" &&\n // Not a GeoPoint\n !(\"latitude\" in (value as object) && \"longitude\" in (value as object))\n ) {\n // Plain object → recurse\n flattenObject(value as Record<string, unknown>, flatKey, result);\n } else {\n result[flatKey] = serializeValue(value);\n }\n }\n}\n\n/**\n * Serialize a full Firestore document into a flat object of SQL-safe values.\n *\n * Nested objects are flattened into underscore-separated column names\n * (e.g. `address.street` → `address_street`). Arrays become JSON strings.\n * Applies optional field exclusions and column renames from `options`.\n */\nexport function serializeDocument(\n doc: Record<string, unknown>,\n options?: Pick<RepoSyncConfig, \"exclude\" | \"columnMap\">,\n): Record<string, unknown> {\n const exclude = new Set(options?.exclude);\n const columnMap = options?.columnMap ?? {};\n\n // First flatten the document\n const flat: Record<string, unknown> = {};\n flattenObject(doc, \"\", flat);\n\n // Then apply excludes and column renames\n const result: Record<string, unknown> = {};\n for (const [flatKey, value] of Object.entries(flat)) {\n if (exclude.has(flatKey)) continue;\n // Also check top-level prefix for excludes (e.g. exclude \"address\" removes all address_* cols)\n const topLevel = flatKey.split(\"__\")[0]!;\n if (topLevel !== flatKey && exclude.has(topLevel)) continue;\n const column =\n columnMap[flatKey] ??\n (flatKey.includes(\"__\")\n ? columnMap[flatKey.split(\"__\").pop()!]\n : undefined) ??\n flatKey;\n result[column] = value;\n }\n\n return result;\n}\n","/**\n * Sync Admin — optional HTTP endpoint for inspecting and managing the\n * Firestore → SQL sync pipeline.\n *\n * Features (gated by `featuresFlag`):\n * - **healthCheck** — compare expected Zod-derived columns vs actual SQL columns\n * - **manualSync** — force re-sync all documents in a Firestore collection\n * - **viewQueue** — inspect pending items in the per-repo SyncQueue\n *\n * @example\n * ```typescript\n * const sync = createFirestoreSync(repos, {\n * // …deps, adapter, etc.\n * admin: {\n * auth: { type: \"basic\", username: \"admin\", password: \"secret\" },\n * featuresFlag: { healthCheck: true, manualSync: true, viewQueue: true },\n * },\n * });\n *\n * export const adminsync = onRequest(sync.adminHandler!);\n * ```\n */\n\nimport { z } from \"zod\";\nimport type { AnyReq, AnyRes, RouteParams } from \"../servers/admin/router\";\nimport { MiniRouter } from \"../servers/admin/router\";\nimport type { SyncQueue } from \"./queue\";\nimport { zodSchemaToColumns } from \"./schema-mapper\";\nimport { serializeDocument } from \"./serializer\";\nimport type {\n adminsyncConfig,\n PubSubClientDep,\n RepoSyncConfig,\n SqlAdapter,\n SyncEvent,\n} from \"./types\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\ntype Req = AnyReq & { params: RouteParams };\n\ninterface RepoInfo {\n name: string;\n schema: z.ZodObject<any> | null;\n documentKey: string;\n tableName: string;\n isGroup: boolean;\n repoCfg: RepoSyncConfig<string> | undefined;\n repo: any;\n}\n\n// ---------------------------------------------------------------------------\n// Link-base resolution (emulator vs production)\n// ---------------------------------------------------------------------------\n\n/**\n * Compute the link base for all HTML links.\n *\n * In the Firebase emulator `FUNCTIONS_EMULATOR=true`, functions are served at\n * `http://localhost:5001/{project}/{region}/{functionTarget}/…`\n * and the browser needs the full prefix for navigation to work.\n *\n * In production, the Firebase proxy strips the prefix so `basePath` is enough.\n */\nfunction getLinkBase(req: any, base: string): string {\n if (process.env[\"FUNCTIONS_EMULATOR\"] === \"true\") {\n const project =\n process.env[\"GCLOUD_PROJECT\"] ??\n process.env[\"GOOGLE_CLOUD_PROJECT\"] ??\n \"demo-project\";\n const region = process.env[\"FUNCTION_REGION\"] ?? \"us-central1\";\n // FUNCTION_TARGET uses dots (e.g. \"sync.functions.adminsync\") but the\n // emulator URL uses hyphens (\"sync-functions-adminsync\").\n const target = (process.env[\"FUNCTION_TARGET\"] ?? \"\").replace(/\\./g, \"-\");\n return `/${project}/${region}/${target}${base}`;\n }\n\n // Cloud Functions v2: K_SERVICE = function name = URL path prefix.\n // Only add it when accessed via cloudfunctions.net (not custom domains).\n // Cloud Run (Gen 2) lowercases service names, but K_SERVICE may still\n // carry the original mixed-case export name — normalise to lowercase\n // so that generated links match the canonical URL.\n const service = process.env[\"K_SERVICE\"];\n const host: string = req.hostname ?? req.headers?.[\"host\"] ?? \"\";\n if (service && host.includes(\"cloudfunctions.net\")) {\n return `/${service.toLowerCase()}${base}`;\n }\n\n return base;\n}\n\n// ---------------------------------------------------------------------------\n// HTML helpers\n// ---------------------------------------------------------------------------\n\nfunction page(title: string, linkBase: string, body: string): string {\n return `<!DOCTYPE html>\n<html lang=\"en\"><head>\n<meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width,initial-scale=1\">\n<title>${title} — Sync Admin</title>\n<style>\n *{box-sizing:border-box;margin:0;padding:0}\n body{font-family:system-ui,-apple-system,sans-serif;background:#f5f5f5;color:#1a1a1a;padding:2rem}\n a{color:#0969da;text-decoration:none}a:hover{text-decoration:underline}\n h1{margin-bottom:1rem}h2{margin:1.5rem 0 .75rem}\n table{border-collapse:collapse;width:100%;margin-bottom:1rem}\n th,td{text-align:left;padding:.5rem .75rem;border:1px solid #d0d7de}\n th{background:#f6f8fa;font-weight:600}\n tr:nth-child(even){background:#fafbfc}\n .badge{display:inline-block;padding:.15rem .5rem;border-radius:1rem;font-size:.8rem;font-weight:600}\n .badge-ok{background:#dafbe1;color:#1a7f37}\n .badge-warn{background:#fff8c5;color:#9a6700}\n .badge-err{background:#ffebe9;color:#cf222e}\n .btn{display:inline-block;padding:.4rem 1rem;border:1px solid #d0d7de;border-radius:.375rem;\n background:#fff;cursor:pointer;font-size:.85rem;text-decoration:none;color:#1a1a1a}\n .btn:hover{background:#f3f4f6}.btn-primary{background:#0969da;color:#fff;border-color:#0969da}\n .btn-primary:hover{background:#0860ca}\n nav{margin-bottom:1.5rem}nav a{margin-right:1rem}\n .card{background:#fff;border:1px solid #d0d7de;border-radius:.5rem;padding:1.25rem;margin-bottom:1rem}\n pre{background:#f6f8fa;padding:1rem;border-radius:.375rem;overflow-x:auto;font-size:.85rem}\n .muted{color:#656d76;font-size:.85rem}\n</style>\n</head><body>\n<nav><a href=\"${linkBase}/\">← Dashboard</a></nav>\n<h1>${title}</h1>\n${body}\n</body></html>`;\n}\n\nfunction sendHtml(res: AnyRes, html: string, status = 200): void {\n res.status(status).set(\"Content-Type\", \"text/html; charset=utf-8\").send(html);\n}\n\nfunction sendJson(res: AnyRes, data: unknown, status = 200): void {\n res\n .status(status)\n .set(\"Content-Type\", \"application/json\")\n .send(JSON.stringify(data, null, 2));\n}\n\nfunction isJsonRequest(req: AnyReq): boolean {\n const accept = (req.headers?.[\"accept\"] ?? \"\") as string;\n return accept.includes(\"application/json\");\n}\n\n// ---------------------------------------------------------------------------\n// Factory\n// ---------------------------------------------------------------------------\n\n/**\n * Create the sync admin HTTP handler.\n *\n * @param repoMapping - The configured repository mapping\n * @param adapter - The SQL adapter (e.g. BigQueryAdapter)\n * @param queues - Live queue map from the worker\n * @param handleMessage - Direct SyncEvent processor from the worker\n * @param config - Admin-specific config (auth, basePath, features)\n * @param repoConfigs - Per-repo sync config (tableName, exclude, columnMap…)\n * @param pubsub - PubSub client (needed for configCheck)\n * @param topicPrefix - PubSub topic prefix (needed for configCheck)\n */\nexport function createadminsyncServer(\n repoMapping: Record<string, any>,\n adapter: SqlAdapter,\n queues: Map<string, SyncQueue>,\n handleMessage: (event: SyncEvent) => Promise<void>,\n config: adminsyncConfig,\n repoConfigs: Record<string, RepoSyncConfig<string> | undefined>,\n pubsub?: PubSubClientDep,\n topicPrefix?: string,\n): (req: any, res: any) => Promise<void> {\n const basePath = (config.basePath ?? \"/\").replace(/\\/$/, \"\") || \"\";\n const features = config.featuresFlag ?? {};\n\n // Pre-compute repo info\n const repoInfos: RepoInfo[] = [];\n for (const [name, repo] of Object.entries(repoMapping)) {\n const repoCfg = repoConfigs[name];\n repoInfos.push({\n name,\n schema: (repo as any).schema ?? null,\n documentKey:\n (repo as any)._systemKeys?.[0] ?? (repo as any).documentKey ?? \"docId\",\n tableName: repoCfg?.tableName ?? name,\n isGroup: !!(repo as any)._isGroup,\n repoCfg,\n repo,\n });\n }\n\n const router = new MiniRouter();\n\n // -- Auth middleware -----------------------------------------------------\n if (config.auth) {\n if (typeof config.auth === \"function\") {\n router.use(config.auth as any);\n } else {\n const realm = config.auth.realm ?? \"Sync Admin\";\n const expected =\n \"Basic \" +\n Buffer.from(`${config.auth.username}:${config.auth.password}`).toString(\n \"base64\",\n );\n router.use((req, res, next) => {\n const authorization = (req as any).headers?.[\"authorization\"] ?? \"\";\n if (authorization !== expected) {\n res\n .status(401)\n .set(\"WWW-Authenticate\", `Basic realm=\"${realm}\"`)\n .set(\"Content-Type\", \"text/plain\")\n .send(\"Unauthorized\");\n return;\n }\n next();\n });\n }\n }\n\n // -- Dashboard ----------------------------------------------------------\n router.get(`${basePath}/`, (req, res) => {\n const lb = getLinkBase(req, basePath);\n const rows = repoInfos\n .map((r) => {\n const links: string[] = [];\n if (features.healthCheck)\n links.push(`<a class=\"btn\" href=\"${lb}/${r.name}/health\">Health</a>`);\n if (features.manualSync)\n links.push(\n `<a class=\"btn btn-primary\" href=\"${lb}/${r.name}/force-sync\">Force Sync</a>`,\n );\n return `<tr>\n <td><strong>${r.name}</strong></td>\n <td>${r.tableName}</td>\n <td>${r.isGroup ? '<span class=\"badge badge-warn\">group</span>' : '<span class=\"badge badge-ok\">collection</span>'}</td>\n <td>${r.schema ? \"✓\" : \"✗\"}</td>\n <td>${links.join(\" \")}</td>\n </tr>`;\n })\n .join(\"\\n\");\n\n const queueLink = features.viewQueue\n ? `<p><a class=\"btn\" href=\"${lb}/queues\">View Queues</a></p>`\n : \"\";\n\n const configCheckLink = features.configCheck\n ? `<p style=\"margin-top:.5rem\"><a class=\"btn\" href=\"${lb}/config-check\">⚙ Config Check</a></p>`\n : \"\";\n\n const html = page(\n \"Sync Dashboard\",\n lb,\n `<div class=\"card\">\n <table>\n <thead><tr><th>Repository</th><th>Table</th><th>Type</th><th>Schema</th><th>Actions</th></tr></thead>\n <tbody>${rows}</tbody>\n </table>\n ${queueLink}\n ${configCheckLink}\n </div>`,\n );\n sendHtml(res, html);\n });\n router.get(`${basePath}`, (req, res) => {\n const lb = getLinkBase(req, basePath);\n res.status(302).set(\"Location\", `${lb}/`).send(\"\");\n });\n\n // -- Health Check -------------------------------------------------------\n if (features.healthCheck) {\n router.get(`${basePath}/:repoName/health`, async (req: Req, res) => {\n const lb = getLinkBase(req, basePath);\n const info = repoInfos.find((r) => r.name === req.params.repoName);\n if (!info) {\n sendHtml(\n res,\n page(\"Not Found\", lb, `<p>Unknown repo: ${req.params.repoName}</p>`),\n 404,\n );\n return;\n }\n if (!info.schema) {\n sendHtml(\n res,\n page(\n \"Health Check\",\n lb,\n `<p class=\"badge badge-warn\">No Zod schema attached to \"${info.name}\"</p>`,\n ),\n );\n return;\n }\n\n const expectedCols = zodSchemaToColumns(info.schema, adapter.dialect, {\n primaryKey: info.documentKey,\n exclude: info.repoCfg?.exclude,\n columnMap: info.repoCfg?.columnMap as\n | Record<string, string>\n | undefined,\n });\n\n let actualCols: string[] = [];\n let tableExists = false;\n let error: string | null = null;\n try {\n tableExists = await adapter.tableExists(info.tableName);\n if (tableExists) {\n actualCols = await adapter.getTableColumns(info.tableName);\n }\n } catch (e: any) {\n error = e?.message ?? String(e);\n }\n\n const actualSet = new Set(actualCols);\n const expectedSet = new Set(expectedCols.map((c) => c.name));\n\n const missing = expectedCols.filter((c) => !actualSet.has(c.name));\n const extra = actualCols.filter((c) => !expectedSet.has(c));\n const matched = expectedCols.filter((c) => actualSet.has(c.name));\n\n const isHealthy = tableExists && missing.length === 0 && !error;\n\n if (isJsonRequest(req)) {\n sendJson(res, {\n repo: info.name,\n table: info.tableName,\n tableExists,\n healthy: isHealthy,\n error,\n columns: {\n expected: expectedCols.map((c) => ({\n name: c.name,\n type: c.sqlType,\n nullable: c.nullable,\n isPrimaryKey: c.isPrimaryKey,\n })),\n actual: actualCols,\n matched: matched.map((c) => c.name),\n missing: missing.map((c) => ({\n name: c.name,\n type: c.sqlType,\n })),\n extra,\n },\n });\n return;\n }\n\n const statusBadge = isHealthy\n ? '<span class=\"badge badge-ok\">Healthy</span>'\n : '<span class=\"badge badge-err\">Unhealthy</span>';\n\n const colRows = expectedCols\n .map((c) => {\n const status = actualSet.has(c.name)\n ? '<span class=\"badge badge-ok\">OK</span>'\n : '<span class=\"badge badge-err\">MISSING</span>';\n return `<tr><td>${c.name}</td><td>${c.sqlType}</td><td>${c.nullable ? \"Yes\" : \"No\"}</td><td>${c.isPrimaryKey ? \"✓\" : \"\"}</td><td>${status}</td></tr>`;\n })\n .join(\"\\n\");\n\n const extraRows = extra\n .map(\n (c) =>\n `<tr><td>${c}</td><td colspan=\"3\" class=\"muted\">not in schema</td><td><span class=\"badge badge-warn\">EXTRA</span></td></tr>`,\n )\n .join(\"\\n\");\n\n const html = page(\n `Health: ${info.name}`,\n lb,\n `<div class=\"card\">\n <p>Table: <code>${info.tableName}</code> ${!tableExists ? '<span class=\"badge badge-err\">NOT FOUND</span>' : statusBadge}</p>\n ${error ? `<p class=\"badge badge-err\">Error: ${error}</p>` : \"\"}\n <h2>Columns</h2>\n <table>\n <thead><tr><th>Column</th><th>SQL Type</th><th>Nullable</th><th>PK</th><th>Status</th></tr></thead>\n <tbody>${colRows}${extraRows}</tbody>\n </table>\n </div>`,\n );\n sendHtml(res, html);\n });\n }\n\n // -- Force Sync ---------------------------------------------------------\n if (features.manualSync) {\n // GET — confirmation page\n router.get(`${basePath}/:repoName/force-sync`, (req: Req, res) => {\n const lb = getLinkBase(req, basePath);\n const info = repoInfos.find((r) => r.name === req.params.repoName);\n if (!info) {\n sendHtml(\n res,\n page(\"Not Found\", lb, `<p>Unknown repo: ${req.params.repoName}</p>`),\n 404,\n );\n return;\n }\n\n const html = page(\n `Force Sync: ${info.name}`,\n lb,\n `<div class=\"card\">\n <p>This will read <strong>all</strong> documents from the <code>${info.name}</code> Firestore collection\n and upsert them into the <code>${info.tableName}</code> SQL table.</p>\n <p class=\"muted\" style=\"margin:.75rem 0\">This may take a while for large collections.</p>\n <form method=\"POST\" action=\"${lb}/${info.name}/force-sync\">\n <button type=\"submit\" class=\"btn btn-primary\">Start Force Sync</button>\n </form>\n </div>`,\n );\n sendHtml(res, html);\n });\n\n // POST — execute\n router.post(`${basePath}/:repoName/force-sync`, async (req: Req, res) => {\n const lb = getLinkBase(req, basePath);\n const info = repoInfos.find((r) => r.name === req.params.repoName);\n if (!info) {\n sendJson(res, { error: `Unknown repo: ${req.params.repoName}` }, 404);\n return;\n }\n\n // Use the repository's collectionGroup or collection query\n const collRef = info.repo.ref;\n if (!collRef) {\n sendJson(\n res,\n { error: `No collection reference for \"${info.name}\"` },\n 400,\n );\n return;\n }\n\n let synced = 0;\n let errors = 0;\n const errorSamples: string[] = [];\n const batchSize = 500;\n const query = collRef.limit(batchSize);\n let lastDoc: any = null;\n\n try {\n // eslint-disable-next-line no-constant-condition\n while (true) {\n const paginatedQuery = lastDoc ? query.startAfter(lastDoc) : query;\n const snapshot = await paginatedQuery.get();\n if (snapshot.empty) break;\n\n for (const doc of snapshot.docs) {\n const data = doc.data() as Record<string, unknown>;\n const docId = String(data[info.documentKey] ?? doc.id);\n const serialized = serializeDocument(data, {\n exclude: info.repoCfg?.exclude,\n columnMap: info.repoCfg?.columnMap,\n });\n\n try {\n await handleMessage({\n operation: \"UPSERT\",\n repoName: info.name,\n docId,\n data: serialized,\n timestamp: new Date().toISOString(),\n });\n synced++;\n } catch (e: any) {\n errors++;\n const msg = e?.message ?? String(e);\n console.error(\n `[ForceSync:${info.name}] doc=${docId} failed:`,\n e,\n );\n if (errorSamples.length < 5) errorSamples.push(`${docId}: ${msg}`);\n }\n }\n\n lastDoc = snapshot.docs[snapshot.docs.length - 1];\n if (snapshot.docs.length < batchSize) break;\n }\n\n // Flush the queue for this repo\n const queue = queues.get(info.name);\n if (queue) await queue.flush();\n } catch (e: any) {\n if (isJsonRequest(req)) {\n sendJson(\n res,\n { error: e?.message ?? String(e), synced, errors },\n 500,\n );\n return;\n }\n sendHtml(\n res,\n page(\n `Force Sync: ${info.name}`,\n lb,\n `<div class=\"card\">\n <p class=\"badge badge-err\">Error: ${e?.message ?? String(e)}</p>\n <p>Synced ${synced} docs before failure (${errors} errors).</p>\n </div>`,\n ),\n 500,\n );\n return;\n }\n\n if (isJsonRequest(req)) {\n sendJson(res, {\n repo: info.name,\n table: info.tableName,\n synced,\n errors,\n ...(errorSamples.length > 0 && { errorSamples }),\n });\n return;\n }\n\n const errorBlock =\n errorSamples.length > 0\n ? `<details style=\"margin-top:1rem\"><summary>First ${errorSamples.length} error(s)</summary>\n <pre style=\"white-space:pre-wrap\">${errorSamples\n .map((s) => s.replace(/[<>&]/g, (c) => `&#${c.charCodeAt(0)};`))\n .join(\"\\n\\n\")}</pre></details>`\n : \"\";\n\n const html = page(\n `Force Sync: ${info.name}`,\n lb,\n `<div class=\"card\">\n <p class=\"badge ${errors > 0 ? \"badge-warn\" : \"badge-ok\"}\">${errors > 0 ? \"Completed with errors\" : \"Complete\"}</p>\n <p>Synced <strong>${synced}</strong> documents to <code>${info.tableName}</code>.</p>\n ${errors > 0 ? `<p class=\"badge badge-warn\">${errors} error(s)</p>` : \"\"}\n ${errorBlock}\n </div>`,\n );\n sendHtml(res, html);\n });\n }\n\n // -- View Queues --------------------------------------------------------\n if (features.viewQueue) {\n router.get(`${basePath}/queues`, (req, res) => {\n const lb = getLinkBase(req, basePath);\n const queueData: Array<{\n repo: string;\n table: string;\n pending: number;\n }> = [];\n\n for (const info of repoInfos) {\n const q = queues.get(info.name);\n queueData.push({\n repo: info.name,\n table: info.tableName,\n pending: q ? q.size : 0,\n });\n }\n\n if (isJsonRequest(req)) {\n sendJson(res, { queues: queueData });\n return;\n }\n\n const rows = queueData\n .map(\n (q) =>\n `<tr><td>${q.repo}</td><td>${q.table}</td><td>${q.pending === 0 ? '<span class=\"badge badge-ok\">0</span>' : `<span class=\"badge badge-warn\">${q.pending}</span>`}</td></tr>`,\n )\n .join(\"\\n\");\n\n const html = page(\n \"Sync Queues\",\n lb,\n `<div class=\"card\">\n <table>\n <thead><tr><th>Repository</th><th>Table</th><th>Pending</th></tr></thead>\n <tbody>${rows}</tbody>\n </table>\n </div>`,\n );\n sendHtml(res, html);\n });\n }\n\n // -- Config Check -------------------------------------------------------\n if (features.configCheck) {\n router.get(`${basePath}/config-check`, async (req, res) => {\n const lb = getLinkBase(req, basePath);\n const project =\n process.env[\"GCLOUD_PROJECT\"] ??\n process.env[\"GOOGLE_CLOUD_PROJECT\"] ??\n process.env[\"GCP_PROJECT\"] ??\n \"unknown\";\n const consoleBase = `https://console.cloud.google.com`;\n const tPrefix = topicPrefix ?? \"firestore-sync\";\n\n interface CheckResult {\n name: string;\n category: \"bigquery\" | \"pubsub\" | \"firestore\";\n status: \"ok\" | \"error\" | \"warn\";\n message: string;\n fix?: { gcloud?: string; console?: string; hint?: string };\n }\n\n const checks: CheckResult[] = [];\n\n // --- BigQuery checks ---\n // 1. General BQ connectivity (try listing tables via a simple exists check)\n try {\n await adapter.tableExists(\"__nonexistent_health_check__\");\n checks.push({\n name: \"BigQuery API\",\n category: \"bigquery\",\n status: \"ok\",\n message: \"BigQuery API is reachable\",\n });\n } catch (e: any) {\n const msg = e?.message ?? String(e);\n const msgLower = msg.toLowerCase();\n const isApiDisabled =\n msgLower.includes(\"disabled\") ||\n msgLower.includes(\"has not been used\") ||\n msgLower.includes(\"accessnotconfigured\");\n const isPermission =\n msgLower.includes(\"permission\") ||\n msg.includes(\"403\") ||\n msgLower.includes(\"access denied\");\n const isProjectNotFound =\n msgLower.includes(\"project\") && msgLower.includes(\"not found\");\n const isNotFound =\n msgLower.includes(\"not found\") || msg.includes(\"404\");\n\n if (isApiDisabled) {\n checks.push({\n name: \"BigQuery API\",\n category: \"bigquery\",\n status: \"error\",\n message: \"BigQuery API is not enabled\",\n fix: {\n gcloud: `gcloud services enable bigquery.googleapis.com --project=${project}`,\n console: `${consoleBase}/apis/library/bigquery.googleapis.com?project=${project}`,\n },\n });\n } else if (isProjectNotFound) {\n checks.push({\n name: \"BigQuery Project\",\n category: \"bigquery\",\n status: \"error\",\n message: msg,\n fix: {\n hint:\n \"The GCP project does not exist or the credentials don't have access to it. \" +\n \"In the Firebase emulator, GCLOUD_PROJECT may override the configured projectId. \" +\n \"Ensure you pass the correct projectId to the BigQuery constructor and have valid credentials.\",\n console: `${consoleBase}/home/dashboard`,\n },\n });\n } else if (isPermission) {\n checks.push({\n name: \"BigQuery API\",\n category: \"bigquery\",\n status: \"error\",\n message: `Permission denied: ${msg}`,\n fix: {\n hint: \"Grant the service account BigQuery Data Editor + BigQuery Job User roles\",\n gcloud: [\n `SA=$(gcloud run services describe YOUR_SERVICE --region=YOUR_REGION --format=\"value(spec.template.spec.serviceAccountName)\" --project=${project})`,\n `gcloud projects add-iam-policy-binding ${project} --member=\"serviceAccount:$SA\" --role=\"roles/bigquery.dataEditor\"`,\n `gcloud projects add-iam-policy-binding ${project} --member=\"serviceAccount:$SA\" --role=\"roles/bigquery.jobUser\"`,\n ].join(\"\\n\"),\n console: `${consoleBase}/iam-admin/iam?project=${project}`,\n },\n });\n } else if (isNotFound) {\n checks.push({\n name: \"BigQuery Dataset\",\n category: \"bigquery\",\n status: \"error\",\n message: `Dataset not found: ${msg}`,\n fix: {\n hint: \"Create the dataset first\",\n gcloud: `bq mk --dataset ${project}:YOUR_DATASET_ID`,\n console: `${consoleBase}/bigquery?project=${project}`,\n },\n });\n } else {\n checks.push({\n name: \"BigQuery API\",\n category: \"bigquery\",\n status: \"ok\",\n message:\n \"BigQuery API is reachable (table lookup returned expected error)\",\n });\n }\n }\n\n // 2. Per-repo table existence\n for (const info of repoInfos) {\n try {\n const exists = await adapter.tableExists(info.tableName);\n checks.push({\n name: `Table: ${info.tableName}`,\n category: \"bigquery\",\n status: exists ? \"ok\" : \"warn\",\n message: exists\n ? `Table \\`${info.tableName}\\` exists`\n : `Table \\`${info.tableName}\\` does not exist yet`,\n ...(!exists && {\n fix: {\n hint: \"Table will be auto-created on first sync if autoMigrate is enabled. Or create it manually.\",\n },\n }),\n });\n } catch (e: any) {\n checks.push({\n name: `Table: ${info.tableName}`,\n category: \"bigquery\",\n status: \"error\",\n message: e?.message ?? String(e),\n });\n }\n }\n\n // --- Pub/Sub checks ---\n if (pubsub) {\n for (const info of repoInfos) {\n const topicName = `${tPrefix}-${info.name}`;\n try {\n // Try to get topic metadata — succeeds if it exists\n const topic = (pubsub as any).topic(topicName);\n if (typeof topic.exists === \"function\") {\n const [exists] = await topic.exists();\n checks.push({\n name: `Topic: ${topicName}`,\n category: \"pubsub\",\n status: exists ? \"ok\" : \"error\",\n message: exists\n ? `Topic \\`${topicName}\\` exists`\n : `Topic \\`${topicName}\\` does not exist`,\n ...(!exists && {\n fix: {\n gcloud: `gcloud pubsub topics create ${topicName} --project=${project}`,\n console: `${consoleBase}/cloudpubsub/topic/list?project=${project}`,\n },\n }),\n });\n } else {\n // Minimal PubSub client — can't check existence, try publishing a no-op\n checks.push({\n name: `Topic: ${topicName}`,\n category: \"pubsub\",\n status: \"warn\",\n message:\n \"Cannot verify topic existence (PubSub client doesn't expose .exists())\",\n fix: {\n gcloud: `gcloud pubsub topics create ${topicName} --project=${project}`,\n console: `${consoleBase}/cloudpubsub/topic/list?project=${project}`,\n hint: \"Ensure the topic exists. It is auto-created by the Firebase emulator but must exist in production.\",\n },\n });\n }\n } catch (e: any) {\n const msg = e?.message ?? String(e);\n const isApiDisabled =\n msg.includes(\"disabled\") || msg.includes(\"has not been used\");\n checks.push({\n name: isApiDisabled ? \"Pub/Sub API\" : `Topic: ${topicName}`,\n category: \"pubsub\",\n status: \"error\",\n message: isApiDisabled ? \"Pub/Sub API is not enabled\" : msg,\n fix: isApiDisabled\n ? {\n gcloud: `gcloud services enable pubsub.googleapis.com --project=${project}`,\n console: `${consoleBase}/apis/library/pubsub.googleapis.com?project=${project}`,\n }\n : {\n gcloud: `gcloud pubsub topics create ${topicName} --project=${project}`,\n console: `${consoleBase}/cloudpubsub/topic/list?project=${project}`,\n },\n });\n // If the API itself is disabled, skip remaining topic checks\n if (isApiDisabled) break;\n }\n }\n } else {\n checks.push({\n name: \"Pub/Sub Client\",\n category: \"pubsub\",\n status: \"warn\",\n message: \"PubSub client not available for config check\",\n });\n }\n\n // --- JSON response ---\n if (isJsonRequest(req)) {\n const allOk = checks.every((c) => c.status === \"ok\");\n sendJson(res, { project, healthy: allOk, checks });\n return;\n }\n\n // --- HTML response ---\n const statusIcon = (s: string) =>\n s === \"ok\"\n ? '<span class=\"badge badge-ok\">OK</span>'\n : s === \"warn\"\n ? '<span class=\"badge badge-warn\">WARN</span>'\n : '<span class=\"badge badge-err\">ERROR</span>';\n\n const grouped = {\n bigquery: checks.filter((c) => c.category === \"bigquery\"),\n pubsub: checks.filter((c) => c.category === \"pubsub\"),\n firestore: checks.filter((c) => c.category === \"firestore\"),\n };\n\n const renderSection = (title: string, items: CheckResult[]) => {\n if (items.length === 0) return \"\";\n const rows = items\n .map((c) => {\n let fixHtml = \"\";\n if (c.fix) {\n const parts: string[] = [];\n if (c.fix.hint) parts.push(`<p class=\"muted\">${c.fix.hint}</p>`);\n if (c.fix.gcloud) parts.push(`<pre>$ ${c.fix.gcloud}</pre>`);\n if (c.fix.console)\n parts.push(\n `<p><a href=\"${c.fix.console}\" target=\"_blank\">Open GCP Console →</a></p>`,\n );\n fixHtml = `<div style=\"margin-top:.5rem\">${parts.join(\"\")}</div>`;\n }\n return `<tr>\n <td>${statusIcon(c.status)}</td>\n <td><strong>${c.name}</strong><br><span class=\"muted\">${c.message}</span>${fixHtml}</td>\n </tr>`;\n })\n .join(\"\\n\");\n return `<h2>${title}</h2>\n <table><thead><tr><th style=\"width:80px\">Status</th><th>Check</th></tr></thead>\n <tbody>${rows}</tbody></table>`;\n };\n\n const allOk = checks.every((c) => c.status === \"ok\");\n const overallBadge = allOk\n ? '<span class=\"badge badge-ok\">All checks passed</span>'\n : '<span class=\"badge badge-warn\">Some issues found</span>';\n\n const html = page(\n \"Config Check\",\n lb,\n `<div class=\"card\">\n <p>Project: <code>${project}</code> ${overallBadge}</p>\n ${renderSection(\"BigQuery\", grouped.bigquery)}\n ${renderSection(\"Pub/Sub\", grouped.pubsub)}\n ${renderSection(\"Firestore\", grouped.firestore)}\n </div>`,\n );\n sendHtml(res, html);\n });\n }\n\n // -- Request handler ----------------------------------------------------\n return async (req: any, res: any): Promise<void> => {\n await router.handle(req, res);\n };\n}\n","/**\n * Firestore Cloud Function triggers that publish {@link SyncEvent}s to\n * Google Cloud PubSub.\n *\n * Dependencies (`firebase-functions`, `@google-cloud/pubsub`) are injected\n * via the `deps` config property — no lazy loading or module resolution issues.\n *\n * Out-of-order delivery is handled at the application level: every event\n * carries a `version` (publish-time `Date.now()` in ms) which is propagated\n * to SQL as the `__sync_version` column. The worker's MERGE only updates a\n * row when the incoming `version` is strictly greater than the stored one —\n * so a stale event delivered after a newer one is silently skipped.\n *\n * @example\n * ```typescript\n * import { createSyncTriggers } from \"@lpdjs/firestore-repo-service/sync\";\n * import * as firestoreTriggers from \"firebase-functions/v2/firestore\";\n * import { PubSub } from \"@google-cloud/pubsub\";\n *\n * const triggers = createSyncTriggers(repos, {\n * deps: { firestoreTriggers, pubsub: new PubSub() },\n * topicPrefix: \"my-sync\",\n * repos: { users: { exclude: [\"password\"] } },\n * });\n *\n * export const { users_onCreate, users_onUpdate, users_onDelete } = triggers;\n * ```\n */\n\nimport { serializeDocument } from \"./serializer\";\nimport type { RepoSyncConfig, SyncEvent, SyncTriggersConfig } from \"./types\";\n\nconst DEFAULT_TOPIC_PREFIX = \"firestore-sync\";\n\n/**\n * Derive the Firestore document path pattern for a trigger.\n * Returns `null` when the collection path cannot be determined.\n */\nfunction buildDocumentPath(repoName: string, repo: any): string | null {\n const collectionPath: string | undefined =\n (repo as any).ref?.path ?? undefined;\n\n if (!collectionPath) {\n console.warn(\n `[SyncTriggers] Cannot determine collection path for \"${repoName}\". Skipping.`,\n );\n return null;\n }\n\n return `${collectionPath}/{docId}`;\n}\n\n/**\n * Create Firestore Cloud Functions (v2) triggers that publish\n * {@link SyncEvent}s to PubSub for each repository in `repoMapping`.\n *\n * For each non-group repository, three triggers are created:\n * - `{repoName}_onCreate` → publishes an `INSERT` event\n * - `{repoName}_onUpdate` → publishes an `UPSERT` event\n * - `{repoName}_onDelete` → publishes a `DELETE` event\n *\n * Each event carries a monotonic `version` (`Date.now()` in ms) used by\n * the worker to discard out-of-order PubSub deliveries.\n */\nexport function createSyncTriggers<M extends Record<string, any>>(\n repoMapping: M,\n config: SyncTriggersConfig<NoInfer<M>>,\n): Record<string, any> {\n const { onDocumentCreated, onDocumentUpdated, onDocumentDeleted } =\n config.deps.firestoreTriggers;\n const pubsub = config.deps.pubsub;\n\n const topicPrefix = config?.topicPrefix ?? DEFAULT_TOPIC_PREFIX;\n const triggers: Record<string, any> = {};\n\n // Cache topic clients so the publisher reuses the same batching state\n // for a given topic across invocations.\n const topicCache = new Map<string, any>();\n function getTopic(topicName: string): any {\n let t = topicCache.get(topicName);\n if (t) return t;\n t = (pubsub as any).topic(topicName);\n topicCache.set(topicName, t);\n return t;\n }\n\n async function publish(\n topicName: string,\n syncEvent: SyncEvent,\n ): Promise<void> {\n const topic = getTopic(topicName);\n await topic.publishMessage({ json: syncEvent });\n }\n\n for (const [repoName, repo] of Object.entries(repoMapping) as [\n string,\n any,\n ][]) {\n const repoCfg = (\n config?.repos as Record<string, RepoSyncConfig<string>> | undefined\n )?.[repoName];\n\n let documentPath: string | null;\n\n if ((repo as any)._isGroup) {\n if (!repoCfg?.triggerPath) {\n console.warn(\n `[SyncTriggers] Skipping collection-group repo \"${repoName}\". ` +\n \"Provide a triggerPath in the sync repos config for group collections.\",\n );\n continue;\n }\n documentPath = repoCfg.triggerPath;\n } else {\n documentPath = repoCfg?.triggerPath ?? buildDocumentPath(repoName, repo);\n }\n if (!documentPath) continue;\n\n const documentKey: string = (repo as any)._systemKeys?.[0] ?? \"docId\";\n const topicName = `${topicPrefix}-${repoName}`;\n\n triggers[`${repoName}_onCreate`] = onDocumentCreated(\n documentPath,\n async (event: any) => {\n const snap = event.data;\n if (!snap) return;\n\n const data = snap.data() as Record<string, unknown> | undefined;\n if (!data) return;\n\n const docId = String(data[documentKey] ?? snap.id);\n const serialized = serializeDocument(data, {\n exclude: repoCfg?.exclude,\n columnMap: repoCfg?.columnMap,\n });\n\n const syncEvent: SyncEvent = {\n operation: \"INSERT\",\n repoName,\n docId,\n data: serialized,\n timestamp: new Date().toISOString(),\n version: Date.now(),\n };\n\n await publish(topicName, syncEvent);\n },\n );\n\n triggers[`${repoName}_onUpdate`] = onDocumentUpdated(\n documentPath,\n async (event: any) => {\n const snap = event.data?.after;\n if (!snap) return;\n\n const data = snap.data() as Record<string, unknown> | undefined;\n if (!data) return;\n\n const docId = String(data[documentKey] ?? snap.id);\n const serialized = serializeDocument(data, {\n exclude: repoCfg?.exclude,\n columnMap: repoCfg?.columnMap,\n });\n\n const syncEvent: SyncEvent = {\n operation: \"UPSERT\",\n repoName,\n docId,\n data: serialized,\n timestamp: new Date().toISOString(),\n version: Date.now(),\n };\n\n await publish(topicName, syncEvent);\n },\n );\n\n triggers[`${repoName}_onDelete`] = onDocumentDeleted(\n documentPath,\n async (event: any) => {\n const snap = event.data;\n if (!snap) return;\n\n const data = snap.data() as Record<string, unknown> | undefined;\n const docId = String(data?.[documentKey] ?? snap.id);\n\n const syncEvent: SyncEvent = {\n operation: \"DELETE\",\n repoName,\n docId,\n data: null,\n timestamp: new Date().toISOString(),\n version: Date.now(),\n };\n\n await publish(topicName, syncEvent);\n },\n );\n }\n\n return triggers;\n}\n","/**\n * Per-repo in-memory batch buffer.\n *\n * Accumulates {@link SyncEvent}s and flushes them in batches to a\n * {@link SqlAdapter}. On flush failure the events are re-published\n * to PubSub for retry (if a PubSub re-publisher is provided).\n */\n\nimport { SYNC_VERSION_COLUMN } from \"./constants\";\nimport type { SqlAdapter, SyncEvent } from \"./types\";\n\nexport interface SyncQueueOptions {\n /** SQL adapter to flush data to */\n adapter: SqlAdapter;\n /** SQL table name */\n tableName: string;\n /** Primary key column name */\n primaryKey: string;\n /** Max rows per flush (default: 100) */\n batchSize?: number;\n /** Auto-flush interval in ms (default: 5_000). 0 = manual only. */\n flushIntervalMs?: number;\n /** Called on flush failure with the failed events. Typically re-publishes to PubSub. */\n onFlushError?: (events: SyncEvent[], error: unknown) => Promise<void>;\n}\n\n/**\n * In-memory buffer that batches sync events per-repo and flushes them\n * to a SQL adapter.\n */\nexport class SyncQueue {\n private buffer: SyncEvent[] = [];\n private flushing = false;\n private timer: ReturnType<typeof setInterval> | null = null;\n\n private readonly adapter: SqlAdapter;\n private readonly tableName: string;\n private readonly primaryKey: string;\n private readonly batchSize: number;\n private readonly onFlushError?: SyncQueueOptions[\"onFlushError\"];\n\n constructor(opts: SyncQueueOptions) {\n this.adapter = opts.adapter;\n this.tableName = opts.tableName;\n this.primaryKey = opts.primaryKey;\n this.batchSize = opts.batchSize ?? 100;\n this.onFlushError = opts.onFlushError;\n\n const interval = opts.flushIntervalMs ?? 5_000;\n if (interval > 0) {\n this.timer = setInterval(() => void this.flush(), interval);\n // Allow the Node process to exit even if the timer is running\n if (typeof this.timer === \"object\" && \"unref\" in this.timer) {\n this.timer.unref();\n }\n }\n }\n\n /** Number of events waiting in the buffer. */\n get size(): number {\n return this.buffer.length;\n }\n\n /** Push one or more events into the buffer. Triggers auto-flush if batchSize reached. */\n enqueue(...events: SyncEvent[]): void {\n this.buffer.push(...events);\n if (this.buffer.length >= this.batchSize) {\n void this.flush();\n }\n }\n\n /**\n * Flush all buffered events to the SQL adapter.\n * Upserts and deletes are batched separately.\n */\n async flush(): Promise<void> {\n if (this.flushing || this.buffer.length === 0) return;\n this.flushing = true;\n\n // Drain the buffer atomically\n const batch = this.buffer.splice(0, this.batchSize);\n\n try {\n const upsertsById = new Map<string, Record<string, unknown>>();\n const deleteIds: string[] = [];\n\n for (const evt of batch) {\n if (evt.operation === \"DELETE\") {\n deleteIds.push(evt.docId);\n // A delete supersedes any pending upsert in the same batch.\n upsertsById.delete(evt.docId);\n } else if (evt.data) {\n // Multiple updates to the same doc within a single batch would\n // make BigQuery MERGE error out (\"UPDATE/MERGE must match at\n // most one source row for each target row\"). Keep only the row\n // with the highest __sync_version per docId.\n const existing = upsertsById.get(evt.docId);\n if (!existing) {\n upsertsById.set(evt.docId, evt.data);\n } else {\n const a = Number(existing[SYNC_VERSION_COLUMN] ?? 0);\n const b = Number(evt.data[SYNC_VERSION_COLUMN] ?? 0);\n if (b >= a) upsertsById.set(evt.docId, evt.data);\n }\n }\n }\n\n const upserts = Array.from(upsertsById.values());\n\n if (upserts.length > 0) {\n await this.adapter.upsertRows(this.tableName, upserts, this.primaryKey);\n }\n if (deleteIds.length > 0) {\n await this.adapter.deleteRows(\n this.tableName,\n this.primaryKey,\n deleteIds,\n );\n }\n } catch (err) {\n if (this.onFlushError) {\n await this.onFlushError(batch, err).catch((handlerErr) => {\n console.error(\n `[SyncQueue] Flush error for ${this.tableName}:`,\n err,\n );\n console.error(\n `[SyncQueue] Error handler also failed:`,\n handlerErr,\n );\n });\n } else {\n // Re-insert at the front so we retry next flush\n this.buffer.unshift(...batch);\n console.error(`[SyncQueue] Flush failed for ${this.tableName}:`, err);\n }\n } finally {\n this.flushing = false;\n }\n }\n\n /** Stop the auto-flush timer and flush remaining events. */\n async shutdown(): Promise<void> {\n if (this.timer) {\n clearInterval(this.timer);\n this.timer = null;\n }\n await this.flush();\n }\n}\n","/**\n * PubSub worker — creates a Cloud Function that receives {@link SyncEvent}\n * messages from PubSub, routes them to per-repo {@link SyncQueue}s, and\n * flushes batches to the configured {@link SqlAdapter}.\n *\n * Dependencies (`firebase-functions`, `@google-cloud/pubsub`) are injected\n * via the `deps` config property.\n */\n\nimport { z } from \"zod\";\nimport { SYNC_VERSION_COLUMN } from \"./constants\";\nimport { SyncQueue } from \"./queue\";\nimport { zodSchemaToColumns } from \"./schema-mapper\";\nimport type {\n RepoSyncConfig,\n SqlAdapter,\n SyncEvent,\n SyncWorkerConfig,\n} from \"./types\";\n\n// ---------------------------------------------------------------------------\n// Migration tracking\n// ---------------------------------------------------------------------------\n\n/** Set of repo names that have already been migrated in this process lifetime. */\nconst migratedRepos = new Set<string>();\n\nasync function ensureMigrated(\n repoName: string,\n adapter: SqlAdapter,\n schema: z.ZodObject<any>,\n tableName: string,\n primaryKey: string,\n exclude?: string[],\n columnMap?: Record<string, string>,\n): Promise<void> {\n if (migratedRepos.has(repoName)) return;\n\n const columns = zodSchemaToColumns(schema, adapter.dialect, {\n primaryKey,\n exclude,\n columnMap,\n });\n\n const exists = await adapter.tableExists(tableName);\n if (!exists) {\n await adapter.createTable({ tableName, columns });\n } else {\n const existing = new Set(await adapter.getTableColumns(tableName));\n const newCols = columns.filter((c) => !existing.has(c.name));\n if (newCols.length > 0) {\n await adapter.addColumns(tableName, newCols);\n }\n }\n\n migratedRepos.add(repoName);\n}\n\n// ---------------------------------------------------------------------------\n// Worker factory\n// ---------------------------------------------------------------------------\n\n/**\n * Create a PubSub-triggered Cloud Function that syncs Firestore changes\n * to a SQL database.\n *\n * Returns an object with:\n * - `createHandler` — creates a Cloud Function for a PubSub topic\n * - `handleMessage` — process a SyncEvent directly (for testing)\n * - `queues` — internal SyncQueue map (for testing / manual flush)\n * - `shutdown()` — flush all queues and stop timers\n */\nexport function createSyncWorker<M extends Record<string, any>>(\n repoMapping: M,\n config: SyncWorkerConfig<NoInfer<M>>,\n) {\n const {\n deps,\n adapter,\n batchSize = 100,\n flushIntervalMs = 5_000,\n autoMigrate = false,\n topicPrefix = \"firestore-sync\",\n workerOptions,\n repos: repoConfigs = {} as Record<\n string,\n RepoSyncConfig<string> | undefined\n >,\n } = config;\n\n // Build per-repo queues lazily\n const queues = new Map<string, SyncQueue>();\n\n function getQueue(repoName: string, primaryKey: string): SyncQueue {\n let q = queues.get(repoName);\n if (q) return q;\n\n const repoCfg = repoConfigs[repoName];\n const tableName = repoCfg?.tableName ?? repoName;\n\n // On flush failure → log error + re-publish to PubSub dead-letter\n const onFlushError = async (\n events: SyncEvent[],\n error: unknown,\n ): Promise<void> => {\n console.error(\n `[SyncWorker] Flush failed for \"${repoName}\" (${events.length} events):`,\n error,\n );\n try {\n const dlTopicName = `${topicPrefix}-${repoName}-dlq`;\n const dlTopic = deps.pubsub.topic(dlTopicName);\n const [exists] = await dlTopic.exists();\n if (!exists) {\n await dlTopic.create();\n console.info(`[SyncWorker] Created DLQ topic \"${dlTopicName}\"`);\n }\n for (const evt of events) {\n await dlTopic.publishMessage({ json: evt });\n }\n } catch (dlErr) {\n console.error(\n `[SyncWorker] Dead-letter publish also failed for ${repoName}:`,\n dlErr,\n );\n }\n };\n\n q = new SyncQueue({\n adapter,\n tableName,\n primaryKey,\n batchSize,\n flushIntervalMs,\n onFlushError,\n });\n queues.set(repoName, q);\n return q;\n }\n\n // Message handler (works with or without Cloud Functions wrapper)\n async function handleMessage(syncEvent: SyncEvent): Promise<void> {\n const { repoName } = syncEvent;\n const repo = (repoMapping as Record<string, any>)[repoName];\n if (!repo) {\n console.warn(`[SyncWorker] Unknown repo \"${repoName}\", skipping event`);\n return;\n }\n\n const documentKey: string =\n (repo as any)._systemKeys?.[0] ?? (repo as any).documentKey ?? \"docId\";\n\n const repoCfg = repoConfigs[repoName];\n const columnMap = repoCfg?.columnMap as Record<string, string> | undefined;\n // The primaryKey for BigQuery must use the mapped column name (e.g. docId → user_id)\n const primaryKey = columnMap?.[documentKey] ?? documentKey;\n\n if (autoMigrate) {\n const schema: z.ZodObject<any> | undefined =\n (repo as any).schema ?? undefined;\n if (schema) {\n const tableName = repoCfg?.tableName ?? repoName;\n await ensureMigrated(\n repoName,\n adapter,\n schema,\n tableName,\n documentKey,\n repoCfg?.exclude,\n columnMap,\n );\n }\n }\n\n const queue = getQueue(repoName, primaryKey);\n\n // Stamp the row with the publish version so the SQL adapter can skip\n // stale (out-of-order) updates. Force-sync events without a version\n // fall back to the wall clock — still monotonic per-process.\n if (syncEvent.data) {\n syncEvent.data[SYNC_VERSION_COLUMN] = syncEvent.version ?? Date.now();\n }\n\n queue.enqueue(syncEvent);\n }\n\n // Cloud Function v2 PubSub handler (sync — deps are already available)\n function createHandler(topicName: string) {\n const handlerFn = async (event: any) => {\n const data: SyncEvent = event.data?.message?.json ?? event.data?.json;\n if (!data) {\n console.warn(\"[SyncWorker] Received empty PubSub message\");\n return;\n }\n await handleMessage(data);\n // Flush so data is persisted before the Cloud Function container shuts down.\n // Force-sync (admin) handles its own flush after the batch loop.\n const q = queues.get(data.repoName);\n if (q) await q.flush();\n };\n\n if (workerOptions) {\n return deps.pubsubHandler.onMessagePublished(\n { topic: topicName, ...workerOptions },\n handlerFn,\n );\n }\n return deps.pubsubHandler.onMessagePublished(topicName, handlerFn);\n }\n\n return {\n /** Process a SyncEvent directly (for testing or custom PubSub integration). */\n handleMessage,\n /** Create a Cloud Function handler for a specific PubSub topic. */\n createHandler,\n /** Internal queue map (for testing). */\n queues,\n /** Flush all queues and stop timers. */\n async shutdown(): Promise<void> {\n const promises: Promise<void>[] = [];\n for (const q of queues.values()) {\n promises.push(q.shutdown());\n }\n await Promise.all(promises);\n },\n };\n}\n","/**\n * Unified wrapper — combines triggers + worker into a single call.\n *\n * @example\n * ```typescript\n * import * as firestoreTriggers from \"firebase-functions/v2/firestore\";\n * import * as pubsubHandler from \"firebase-functions/v2/pubsub\";\n * import { PubSub } from \"@google-cloud/pubsub\";\n *\n * const sync = createFirestoreSync(repos, {\n * deps: { firestoreTriggers, pubsubHandler, pubsub: new PubSub() },\n * adapter,\n * topicPrefix: \"firestore-sync\",\n * autoMigrate: true,\n * admin: {\n * auth: { type: \"basic\", username: \"admin\", password: \"secret\" },\n * featuresFlag: { healthCheck: true, manualSync: true, viewQueue: true },\n * },\n * repos: {\n * users: { exclude: [\"documentPath\"], columnMap: { docId: \"user_id\" } },\n * posts: { columnMap: { docId: \"post_id\" } },\n * },\n * });\n *\n * // Triggers + PubSub handlers\n * export const { users_onCreate, users_onUpdate, users_onDelete, sync_users } = sync.functions;\n *\n * // Admin endpoint — wrap with onRequest yourself\n * export const adminsync = onRequest(sync.adminHandler!);\n *\n * // Or pass onRequest in admin config to auto-add to sync.functions:\n * // admin: { onRequest, ... } → export const { adminsync } = sync.functions;\n * ```\n */\n\nimport { createadminsyncServer } from \"./admin\";\nimport type { SyncQueue } from \"./queue\";\nimport { createSyncTriggers } from \"./triggers\";\nimport type { FirestoreSyncConfig, OrFactory, RepoSyncConfig, SyncEvent } from \"./types\";\nimport { createSyncWorker } from \"./worker\";\n\nconst DEFAULT_TOPIC_PREFIX = \"firestore-sync\";\n\n/**\n * Wraps a value-or-factory into a lazy proxy that only instantiates\n * when a property is first accessed. If the value is already an instance,\n * returns it as-is (zero overhead).\n */\nfunction lazyProxy<T extends object>(v: OrFactory<T>): T {\n if (typeof v !== \"function\") return v;\n const factory = v as () => T;\n let instance: T | undefined;\n return new Proxy({} as T, {\n get(_, prop) {\n if (!instance) instance = factory();\n return (instance as any)[prop];\n },\n has(_, prop) {\n if (!instance) instance = factory();\n return prop in (instance as object);\n },\n });\n}\n\nexport function createFirestoreSync<M extends Record<string, any>>(\n repoMapping: M,\n config: FirestoreSyncConfig<NoInfer<M>>,\n) {\n const {\n deps,\n adapter: rawAdapter,\n topicPrefix = DEFAULT_TOPIC_PREFIX,\n batchSize,\n flushIntervalMs,\n autoMigrate,\n admin: adminConfig,\n workerOptions,\n repos: repoConfigs,\n } = config;\n\n // Resolve lazy deps — instances are returned as-is, factories are wrapped\n // in a proxy that defers construction until the first property access.\n const pubsub = lazyProxy(deps.pubsub);\n const adapter = lazyProxy(rawAdapter);\n\n // Create triggers (Firestore → PubSub)\n const triggers = createSyncTriggers(repoMapping, {\n deps: { firestoreTriggers: deps.firestoreTriggers, pubsub },\n topicPrefix,\n repos: repoConfigs,\n });\n\n // Create worker (PubSub → SQL)\n const worker = createSyncWorker(repoMapping, {\n deps: { pubsubHandler: deps.pubsubHandler, pubsub },\n adapter,\n batchSize,\n flushIntervalMs,\n autoMigrate,\n topicPrefix,\n workerOptions,\n repos: repoConfigs,\n });\n\n // Auto-create a PubSub handler per repo\n const handlers: Record<string, any> = {};\n for (const repoName of Object.keys(repoMapping)) {\n handlers[`sync_${repoName}`] = worker.createHandler(\n `${topicPrefix}-${repoName}`,\n );\n }\n\n // Optional admin endpoint\n let adminHandler: ((req: any, res: any) => Promise<void>) | null = null;\n if (adminConfig) {\n adminHandler = createadminsyncServer(\n repoMapping,\n adapter,\n worker.queues as Map<string, SyncQueue>,\n worker.handleMessage as (event: SyncEvent) => Promise<void>,\n adminConfig,\n (repoConfigs ?? {}) as Record<string, RepoSyncConfig<string> | undefined>,\n pubsub,\n topicPrefix,\n );\n // If onRequest is provided, wrap it as a Cloud Function automatically.\n // Otherwise expose the raw handler so the user can wrap it.\n handlers[\"adminsync\"] = adminConfig.onRequest\n ? adminConfig.httpsOptions\n ? adminConfig.onRequest(adminConfig.httpsOptions, adminHandler)\n : adminConfig.onRequest(adminHandler)\n : adminHandler;\n }\n\n const result = {\n /** All Cloud Functions (triggers + handlers + optional admin) — spread into exports */\n functions: { ...triggers, ...handlers } as Record<string, any>,\n /**\n * Raw admin HTTP handler — wrap with `onRequest()` yourself if you\n * didn't pass `onRequest` in the admin config.\n * @example\n * ```ts\n * export const adminsync = onRequest(sync.adminHandler!);\n * ```\n */\n adminHandler: adminHandler as\n | ((req: any, res: any) => Promise<void>)\n | null,\n /** Process a SyncEvent directly (for testing) */\n handleMessage: worker.handleMessage as (event: SyncEvent) => Promise<void>,\n /** Internal queue map (for testing) */\n queues: worker.queues as Map<string, SyncQueue>,\n /** Flush all queues and stop timers */\n shutdown: worker.shutdown as () => Promise<void>,\n };\n\n // Hide non-function properties from Firebase's recursive discovery.\n // Only `functions` is enumerable — the rest is accessible but invisible to Object.keys().\n for (const key of [\n \"adminHandler\",\n \"handleMessage\",\n \"queues\",\n \"shutdown\",\n ] as const) {\n Object.defineProperty(result, key, { enumerable: false });\n }\n\n return result;\n}\n","/**\n * HTTP route handlers for the admin ORM server.\n * Each handler corresponds to a URL pattern registered in the router.\n *\n * Routes:\n * GET / → dashboard GET /:repoName → document list (paginated)\n * GET /:repoName/create → create form\n * POST /:repoName/create → submit create\n * GET /:repoName/:id/edit → edit form (pre-filled)\n * POST /:repoName/:id/edit → submit update\n * POST /:repoName/:id/delete → delete document\n */\n\nimport { z } from \"zod\";\nimport type { ConfiguredRepository } from \"../../repositories/types\";\nimport type { RepositoryConfig } from \"../../shared/types\";\nimport {\n getEnumValues,\n getInnerType,\n getLiteralValue,\n getNativeEnumValues,\n getShape,\n getTypeName,\n} from \"../../shared/zod-compat\";\nimport { renderForm, zodToFields, type FieldDescriptor } from \"./form-gen\";\nimport type {\n ColumnMeta,\n FilterState,\n RelationalFieldMeta,\n WhereOp,\n} from \"./renderer\";\nimport { renderDashboard, renderFormPage, renderList, renderPage } from \"./renderer\";\nimport type { AnyReq, AnyRes, RouteParams } from \"./router\";\nimport { isMissingIndexError, toQueryError } from \"./index-url\";\n\n// ---------------------------------------------------------------------------\n// Registry type\n// ---------------------------------------------------------------------------\n\nexport interface AdminRepoEntry {\n name: string;\n path: string;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n repo: ConfiguredRepository<\n RepositoryConfig<any, any, any, any, any, any, any, any, any, any>\n >;\n schema: z.ZodObject<any>;\n /** document key field name (default: \"docId\") */\n documentKey?: string;\n /** Field name that stores the full Firestore document path (e.g. \"documentPath\") */\n pathKey?: string;\n /** Whether this repo is a collection group (subcollection) */\n isGroup?: boolean;\n /** Parent key field names needed to build a subcollection document ref (auto-detected from refCb) */\n parentKeys?: string[];\n /** Field name for the creation timestamp (auto-set on create) */\n createdKey?: string;\n /** List of columns to display in the table (defaults to schema keys) */\n listColumns?: string[];\n /** Page size for list view (default: 25) */\n pageSize?: number;\n /** Fields exposed in the filter bar (defaults to all schema keys) */\n filterableFields?: string[];\n /** Fields shown in the edit form (defaults to all schema fields if unset) */\n mutableFields?: string[];\n /** Fields shown in the create form (defaults to all schema fields if unset) */\n createFields?: string[];\n /** Whether delete is allowed (default: false) */\n allowDelete?: boolean;\n /**\n * Fields that link to another repository.\n * Populated automatically from the repo's relationalKeys.\n */\n relationalMeta?: RelationalFieldMeta[];\n}\n\nexport type RepoRegistry = Record<string, AdminRepoEntry>;\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nconst _idChars =\n \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\";\n\n/** Generate a random 20-char alphanumeric ID matching Firestore's native format. */\nfunction generateFirestoreId(): string {\n let id = \"\";\n for (let i = 0; i < 20; i++) {\n id += _idChars.charAt(Math.floor(Math.random() * _idChars.length));\n }\n return id;\n}\n\n/**\n * Extract Firestore document path args from a document's stored path.\n * e.g. \"posts/abc/comments/xyz\" → [\"abc\", \"xyz\"] (the doc-ID segments).\n * Returns `undefined` when no usable path is available.\n */\nfunction extractPathArgs(\n doc: Record<string, unknown>,\n pathKey?: string,\n): string[] | undefined {\n if (!pathKey) return undefined;\n const fullPath = doc[pathKey];\n if (typeof fullPath !== \"string\" || !fullPath) return undefined;\n const segments = fullPath.split(\"/\").filter(Boolean);\n // Doc IDs are at odd indices: col/id/col/id/...\n const args: string[] = [];\n for (let i = 1; i < segments.length; i += 2) {\n args.push(segments[i]!);\n }\n return args.length > 0 ? args : undefined;\n}\n\n/**\n * Fetch a single document by its documentKey, with fallback to query\n * for collection-group repos where direct documentRef may fail.\n */\nasync function fetchDocById(\n entry: AdminRepoEntry,\n docId: string,\n): Promise<Record<string, unknown> | null> {\n const docKey = entry.documentKey ?? \"docId\";\n const getMethod =\n `by${docKey.charAt(0).toUpperCase()}${docKey.slice(1)}` as keyof typeof entry.repo.get;\n\n // Try direct get first\n if (typeof entry.repo.get[getMethod] === \"function\") {\n try {\n const doc = (await (entry.repo.get[getMethod] as Function)(\n docId,\n )) as Record<string, unknown> | null;\n if (doc) return doc;\n } catch {\n // Direct ref may fail for subcollections — fall through to query\n }\n }\n\n // Fallback: query-based lookup (works for collectionGroup)\n const results = await entry.repo.query.by({\n where: [[docKey, \"==\", docId]],\n limit: 1,\n });\n return (results[0] as Record<string, unknown>) ?? null;\n}\n\n/**\n * Build a `flash` payload (with optional \"Create Index\" CTA) from a Firestore\n * error raised while loading a single document. Returns `undefined` if the\n * error is not interesting enough to render as a structured alert.\n */\nfunction flashFromDocFetchError(\n entry: AdminRepoEntry,\n docId: string,\n err: unknown,\n): { type: \"warning\" | \"error\"; message: string; action?: { href: string; label: string; external?: boolean } } {\n const docKey = entry.documentKey ?? \"docId\";\n const qe = toQueryError(err, {\n ref: entry.repo.ref,\n path: entry.path,\n isGroup: !!entry.isGroup,\n filters: [{ field: docKey, op: \"==\", value: docId }],\n });\n if (qe.type === \"index\") {\n return {\n type: \"warning\",\n message:\n \"Loading this document requires a composite index that does not exist yet.\",\n ...(qe.indexUrl\n ? {\n action: {\n href: qe.indexUrl,\n label: \"Create Index →\",\n external: true,\n },\n }\n : {}),\n };\n }\n return {\n type: \"error\",\n message: qe.message,\n };\n}\n\nfunction sendHtml(res: AnyRes, html: string, status = 200): void {\n res.status(status).set(\"Content-Type\", \"text/html; charset=utf-8\").send(html);\n}\n\nfunction redirect(res: AnyRes, to: string): void {\n res.status(302).set(\"Location\", to).send(\"\");\n}\n\n/**\n * Parse a flat form body (from `application/x-www-form-urlencoded`) into a\n * typed object using the Zod schema as guide.\n * Handles: dot-notation nested fields (e.g. address.street), JSON textarea\n * values, booleans (checkbox), numbers.\n */\nfunction parseFormBody(\n raw: Record<string, string | string[] | undefined>,\n schema: z.ZodObject<any>,\n): Record<string, unknown> {\n const shape = schema.shape;\n const result: Record<string, unknown> = {};\n\n for (const [key, zodField] of Object.entries(shape)) {\n const tn = resolveTypeName(zodField as z.ZodType);\n\n // ── ZodObject: prefer dot-notation sub-keys over raw JSON textarea ──────\n if (tn === \"ZodObject\") {\n // Check for explicit null marker first\n if (raw[key + \"__isnull\"] === \"1\") {\n result[key] = null;\n continue;\n }\n const subRaw: Record<string, string | string[] | undefined> = {};\n let hasDotKeys = false;\n for (const [k, v] of Object.entries(raw)) {\n if (k.startsWith(`${key}.`)) {\n subRaw[k.slice(key.length + 1)] = v;\n hasDotKeys = true;\n }\n }\n if (hasDotKeys) {\n // Unwrap to the inner ZodObject schema and recurse\n let innerSchema: z.ZodType = zodField as z.ZodType;\n while (true) {\n const itn = getTypeName(innerSchema);\n if (\n itn === \"ZodOptional\" ||\n itn === \"ZodNullable\" ||\n itn === \"ZodDefault\"\n ) {\n innerSchema = getInnerType(innerSchema)!;\n } else break;\n }\n result[key] = parseFormBody(subRaw, innerSchema as z.ZodObject<any>);\n continue;\n }\n // Fallback: try to JSON-parse the textarea value\n const rawVal = raw[key];\n const strVal = Array.isArray(rawVal) ? rawVal[rawVal.length - 1] : rawVal;\n if (strVal) {\n try {\n result[key] = JSON.parse(strVal);\n } catch {\n result[key] = strVal;\n }\n }\n continue;\n }\n\n // ── All other types ─────────────────────────────────────────────────────\n const rawVal = raw[key];\n const strVal = Array.isArray(rawVal) ? rawVal[rawVal.length - 1] : rawVal;\n // Nullable field explicitly set to null via the toggle\n if (raw[key + \"__isnull\"] === \"1\") {\n result[key] = null;\n continue;\n }\n if (strVal === undefined || strVal === \"\") {\n // Checkbox unchecked → false; everything else → omit\n if (tn === \"ZodBoolean\") result[key] = false;\n continue;\n }\n\n switch (tn) {\n case \"ZodBoolean\":\n if (strVal === \"__null__\") {\n result[key] = null;\n } else {\n result[key] = strVal === \"true\" || strVal === \"on\" || strVal === \"1\";\n }\n break;\n case \"ZodNumber\":\n case \"ZodBigInt\":\n result[key] = Number(strVal);\n break;\n case \"ZodDate\":\n result[key] = new Date(strVal);\n break;\n case \"ZodArray\":\n try {\n result[key] = JSON.parse(strVal);\n } catch {\n result[key] = strVal;\n }\n break;\n default:\n // Try JSON for inline JSON textareas, fall back to string\n if (strVal.startsWith(\"{\") || strVal.startsWith(\"[\")) {\n try {\n result[key] = JSON.parse(strVal);\n break;\n } catch {\n /* fall through */\n }\n }\n result[key] = strVal;\n }\n }\n\n return result;\n}\n\n/**\n * Convert any date-like value to the \"yyyy-MM-ddThh:mm\" string required by\n * `<input type=\"datetime-local\">`.\n * Handles: native Date, Firestore Timestamp ({_seconds, _nanoseconds}),\n * Firestore Timestamp with .toDate(), ISO strings, unix numbers.\n */\nfunction toDatetimeLocal(val: unknown): string | null {\n let date: Date | null = null;\n\n if (val instanceof Date) {\n date = val;\n } else if (\n typeof val === \"object\" &&\n val !== null &&\n typeof (val as any).toDate === \"function\"\n ) {\n // Firestore Timestamp SDK object\n date = (val as any).toDate() as Date;\n } else if (\n typeof val === \"object\" &&\n val !== null &&\n \"_seconds\" in val &&\n \"_nanoseconds\" in val\n ) {\n // Plain serialized Firestore Timestamp { _seconds, _nanoseconds }\n date = new Date(\n (val as any)._seconds * 1000 +\n Math.floor((val as any)._nanoseconds / 1_000_000),\n );\n } else if (typeof val === \"string\" || typeof val === \"number\") {\n const d = new Date(val as string | number);\n if (!isNaN(d.getTime())) date = d;\n }\n\n if (!date || isNaN(date.getTime())) return null;\n\n // Format as local time yyyy-MM-ddThh:mm (what datetime-local expects)\n const pad = (n: number) => String(n).padStart(2, \"0\");\n return (\n `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}` +\n `T${pad(date.getHours())}:${pad(date.getMinutes())}`\n );\n}\n\n/** Resolve the innermost Zod type name (unwrapping Optional/Nullable/Default) */\nfunction resolveTypeName(schema: z.ZodType): string {\n let s: z.ZodType = schema;\n // eslint-disable-next-line no-constant-condition\n while (true) {\n const tn = getTypeName(s);\n if (tn === \"ZodOptional\" || tn === \"ZodNullable\" || tn === \"ZodDefault\") {\n s = getInnerType(s)!;\n } else {\n return tn;\n }\n }\n}\n\n/** Resolve the innermost Zod schema (unwrapping Optional/Nullable/Default) */\nfunction resolveInnerSchema(schema: z.ZodType): z.ZodType {\n let s: z.ZodType = schema;\n // eslint-disable-next-line no-constant-condition\n while (true) {\n const tn = getTypeName(s);\n if (tn === \"ZodOptional\" || tn === \"ZodNullable\" || tn === \"ZodDefault\") {\n s = getInnerType(s)!;\n } else {\n return s;\n }\n }\n}\n\n/** True if the schema is wrapped in ZodOptional or ZodNullable (recursively). */\nfunction isFieldNullable(schema: z.ZodType): boolean {\n let s: z.ZodType = schema;\n // eslint-disable-next-line no-constant-condition\n while (true) {\n const tn = getTypeName(s);\n if (tn === \"ZodOptional\" || tn === \"ZodNullable\") return true;\n if (tn === \"ZodDefault\") {\n s = getInnerType(s)!;\n continue;\n }\n return false;\n }\n}\n\n/** Extract enum values from a (possibly wrapped) ZodEnum / ZodNativeEnum / ZodLiteral. Returns undefined if not an enum. */\nfunction extractEnumValues(schema: z.ZodType): readonly string[] | undefined {\n const inner = resolveInnerSchema(schema);\n const tn = getTypeName(inner);\n if (tn === \"ZodEnum\") {\n const v = getEnumValues(inner);\n return v.length > 0 ? v : undefined;\n }\n if (tn === \"ZodNativeEnum\") {\n const obj = getNativeEnumValues(inner);\n const vals = Object.values(obj).filter(\n (v) => typeof v === \"string\",\n ) as string[];\n return vals.length > 0 ? vals : undefined;\n }\n if (tn === \"ZodLiteral\") {\n const v = getLiteralValue(inner);\n return typeof v === \"string\" ? [v] : undefined;\n }\n return undefined;\n}\n\n/**\n * Prefill a Zod schema fields with existing document values.\n * For ZodObject fields, recurses into nested sub-fields using dot-notation keys\n * so that individual sub-inputs (e.g. address.street) are properly pre-filled.\n */\nfunction prefillFromDoc(\n doc: Record<string, unknown>,\n schema: z.ZodObject<any>,\n prefix = \"\",\n): Record<string, string> {\n const result: Record<string, string> = {};\n for (const key of Object.keys(schema.shape)) {\n const fullKey = prefix ? `${prefix}.${key}` : key;\n const val = doc[key];\n // Sentinel \"__null__\" tells renderField to pre-check the null toggle\n if (val === null) {\n result[fullKey] = \"__null__\";\n continue;\n }\n if (val === undefined) continue;\n\n // Unwrap Optional/Nullable/Default to check inner type\n let innerSchema: z.ZodType = schema.shape[key] as z.ZodType;\n while (true) {\n const itn = getTypeName(innerSchema);\n if (\n itn === \"ZodOptional\" ||\n itn === \"ZodNullable\" ||\n itn === \"ZodDefault\"\n ) {\n innerSchema = getInnerType(innerSchema)!;\n } else break;\n }\n const innerTn = getTypeName(innerSchema);\n\n if (\n innerTn === \"ZodObject\" &&\n typeof val === \"object\" &&\n val !== null &&\n !Array.isArray(val)\n ) {\n // Recursively flatten nested object fields with dot-notation\n const nested = prefillFromDoc(\n val as Record<string, unknown>,\n innerSchema as z.ZodObject<any>,\n fullKey,\n );\n Object.assign(result, nested);\n } else if (innerTn === \"ZodDate\") {\n // Convert Date / Firestore Timestamp → datetime-local string\n const dtLocal = toDatetimeLocal(val);\n if (dtLocal !== null) result[fullKey] = dtLocal;\n } else if (\n typeof val === \"object\" &&\n val !== null &&\n !Array.isArray(val) &&\n (\"_seconds\" in val || typeof (val as any).toDate === \"function\")\n ) {\n // Untyped Timestamp-like value: try datetime-local, fall back to JSON\n const dtLocal = toDatetimeLocal(val);\n result[fullKey] = dtLocal ?? JSON.stringify(val, null, 2);\n } else if (typeof val === \"object\") {\n result[fullKey] = JSON.stringify(val, null, 2);\n } else {\n result[fullKey] = String(val);\n }\n }\n return result;\n}\n\n/**\n * Recursively apply prefilled string values to a tree of FieldDescriptors.\n * Handles dot-notation keys for nested objects (e.g. \"address.street\").\n */\nfunction applyPrefill(\n fields: FieldDescriptor[],\n prefilled: Record<string, string>,\n): FieldDescriptor[] {\n return fields.map((f) => ({\n ...f,\n defaultValue: prefilled[f.name] ?? f.defaultValue,\n nested: f.nested ? applyPrefill(f.nested, prefilled) : undefined,\n }));\n}\n\n// ---------------------------------------------------------------------------\n// Filter helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Extract active filters from URL query params.\n * Params: fv_{field} = value, fo_{field} = operator (default ==)\n */\nfunction parseFilters(\n query: Record<string, string>,\n validFields: Set<string>,\n): FilterState[] {\n const validOps = new Set<string>([\n \"==\",\n \"!=\",\n \"<\",\n \"<=\",\n \">\",\n \">=\",\n \"in\",\n \"not-in\",\n \"array-contains\",\n \"array-contains-any\",\n ]);\n const filters: FilterState[] = [];\n for (const [k, v] of Object.entries(query)) {\n if (!k.startsWith(\"fv_\")) continue;\n const field = k.slice(3);\n if (!validFields.has(field)) continue;\n const value = (v ?? \"\").trim();\n if (!value) continue;\n const opRaw = query[`fo_${field}`] ?? \"==\";\n const op = validOps.has(opRaw) ? (opRaw as WhereOp) : \"==\";\n filters.push({ field, op, value });\n }\n return filters;\n}\n\n/**\n * Convert FilterState[] to the where-clause tuples expected by the query engine.\n * Coerces string values to boolean/number when unambiguous.\n */\nfunction filtersToWhere(filters: FilterState[]): [string, WhereOp, unknown][] {\n const NULL_SENTINEL = \"__null__\";\n const coerce = (v: string): unknown => {\n if (v === NULL_SENTINEL) return null;\n if (v === \"true\") return true;\n if (v === \"false\") return false;\n if (v !== \"\" && !isNaN(Number(v))) return Number(v);\n return v;\n };\n return filters.map((f) => {\n if (f.op === \"array-contains-any\" || f.op === \"in\" || f.op === \"not-in\") {\n // CSV list → array, each element coerced (drop empty / null sentinels —\n // Firestore rejects null inside `in`/`not-in`).\n const arr = f.value\n .split(\",\")\n .map((s) => s.trim())\n .filter((s) => s !== \"\" && s !== NULL_SENTINEL)\n .map((s) => coerce(s));\n return [f.field, f.op, arr];\n }\n return [f.field, f.op, coerce(f.value)];\n });\n}\n\n/** Build ColumnMeta for displayable columns, recursing into ZodObject sub-fields (dot-notation). */\nfunction buildColumnMeta(\n columns: string[],\n schema: z.ZodObject<any>,\n prefix = \"\",\n): ColumnMeta[] {\n const result: ColumnMeta[] = [];\n for (const col of columns) {\n const fullName = prefix ? `${prefix}.${col}` : col;\n const field = schema.shape[col] as z.ZodType | undefined;\n if (!field) {\n result.push({ name: fullName, zodType: \"ZodString\" });\n continue;\n }\n const zodType = resolveTypeName(field);\n if (zodType === \"ZodObject\") {\n // Unwrap wrappers to reach the inner ZodObject\n let inner: z.ZodType = field;\n while (true) {\n const itn = getTypeName(inner);\n if (\n itn === \"ZodOptional\" ||\n itn === \"ZodNullable\" ||\n itn === \"ZodDefault\"\n ) {\n inner = getInnerType(inner)!;\n } else break;\n }\n const subShape = getShape(inner);\n result.push(\n ...buildColumnMeta(\n Object.keys(subShape),\n inner as z.ZodObject<any>,\n fullName,\n ),\n );\n } else {\n result.push({\n name: fullName,\n zodType,\n nullable: isFieldNullable(field),\n enumValues: extractEnumValues(field),\n });\n }\n }\n return result;\n}\n\n// ---------------------------------------------------------------------------\n// Handler factory\n// ---------------------------------------------------------------------------\n\n/**\n * Resolve the ZodType at a dot-notation path (e.g. \"address.city\") within a schema.\n * Returns null if the path cannot be resolved.\n */\nfunction resolveZodAtPath(\n schema: z.ZodObject<any>,\n path: string,\n): z.ZodType | null {\n const parts = path.split(\".\");\n let s: z.ZodType = schema as z.ZodType;\n for (const part of parts) {\n // Unwrap Optional / Nullable / Default wrappers\n while (true) {\n const itn = getTypeName(s);\n if (\n itn === \"ZodOptional\" ||\n itn === \"ZodNullable\" ||\n itn === \"ZodDefault\"\n ) {\n s = getInnerType(s)!;\n } else break;\n }\n const shape = getShape(s);\n if (!(part in shape)) return null;\n s = shape[part]!;\n }\n return s;\n}\n\n/**\n * Returns a Zod schema restricted to `fields` when defined.\n * Supports dot-notation paths (e.g. \"address.city\") by building partial\n * nested sub-schemas — useful for edit/create forms.\n * Falls back to the full schema if fields is undefined/empty.\n */\nfunction getMutableSchema(\n schema: z.ZodObject<any>,\n fields: string[] | undefined,\n): z.ZodObject<any> {\n if (!fields || fields.length === 0) return schema;\n\n const topLevel: string[] = [];\n // parent key → list of sub-field names requested\n const dotGroups = new Map<string, string[]>();\n\n for (const f of fields) {\n const dot = f.indexOf(\".\");\n if (dot === -1) {\n topLevel.push(f);\n } else {\n const parent = f.slice(0, dot);\n const child = f.slice(dot + 1);\n if (!dotGroups.has(parent)) dotGroups.set(parent, []);\n dotGroups.get(parent)!.push(child);\n }\n }\n\n const picked: Record<string, z.ZodType> = {};\n\n // Direct top-level fields\n for (const f of topLevel) {\n if (f in schema.shape) picked[f] = schema.shape[f]!;\n }\n\n // Partial nested objects for dot-notation entries\n for (const [parent, subFields] of dotGroups) {\n if (!(parent in schema.shape)) continue;\n // Unwrap to the inner ZodObject\n let inner: z.ZodType = schema.shape[parent] as z.ZodType;\n while (true) {\n const itn = getTypeName(inner);\n if (\n itn === \"ZodOptional\" ||\n itn === \"ZodNullable\" ||\n itn === \"ZodDefault\"\n ) {\n inner = getInnerType(inner)!;\n } else break;\n }\n if (getTypeName(inner) !== \"ZodObject\") {\n // Not an object — include as-is\n picked[parent] = schema.shape[parent]!;\n continue;\n }\n // Recurse: build a partial sub-schema for the requested sub-fields\n picked[parent] = getMutableSchema(inner as z.ZodObject<any>, subFields);\n }\n\n return z.object(picked);\n}\n/**\n * Compute the link base for all UI links.\n *\n * ── Emulator (FUNCTIONS_EMULATOR=true) ──────────────────────────────────────\n * Firebase emulator exposes functions at:\n * http://localhost:5001/{GCLOUD_PROJECT}/{FUNCTION_REGION}/{FUNCTION_TARGET}/...\n * env vars set by the emulator:\n * GCLOUD_PROJECT / GOOGLE_CLOUD_PROJECT → project id\n * FUNCTION_REGION → region (default: us-central1)\n * FUNCTION_TARGET → function export name (e.g. \"admin\")\n *\n * ── Production ──────────────────────────────────────────────────────────────\n * Firebase proxy strips the prefix before reaching the handler, so links\n * are relative to \"/\" and `staticBasePath` is used as-is.\n */\nfunction getLinkBase(req: AnyReq, staticBasePath: string): string {\n const base = staticBasePath === \"/\" ? \"\" : staticBasePath.replace(/\\/$/, \"\");\n\n if (process.env[\"FUNCTIONS_EMULATOR\"] === \"true\") {\n const project =\n process.env[\"GCLOUD_PROJECT\"] ??\n process.env[\"GOOGLE_CLOUD_PROJECT\"] ??\n \"demo-project\";\n const region = process.env[\"FUNCTION_REGION\"] ?? \"us-central1\";\n // FUNCTION_TARGET uses dots (e.g. \"sync.functions.adminsync\") but the\n // emulator URL uses hyphens (\"sync-functions-adminsync\").\n const target = (process.env[\"FUNCTION_TARGET\"] ?? \"\").replace(/\\./g, \"-\");\n return `/${project}/${region}/${target}${base}`;\n }\n\n // Cloud Functions v2: K_SERVICE = function name = URL path prefix.\n // Only add it when accessed via cloudfunctions.net (not custom domains).\n // Cloud Run (Gen 2) lowercases service names, but K_SERVICE may still\n // carry the original mixed-case export name — normalise to lowercase\n // so that generated links match the canonical URL.\n const service = process.env[\"K_SERVICE\"];\n const host: string =\n (req as any).hostname ?? (req.headers as any)?.[\"host\"] ?? \"\";\n if (service && host.includes(\"cloudfunctions.net\")) {\n return `/${service.toLowerCase()}${base}`;\n }\n\n return base;\n}\n\nexport function createAdminHandlers(registry: RepoRegistry, basePath: string) {\n // ── Dashboard ─────────────────────────────────────────────────────────────\n const handleDashboard = (\n req: AnyReq & { params: RouteParams },\n res: AnyRes,\n ): void => {\n const lb = getLinkBase(req, basePath);\n const repos = Object.values(registry).map((e) => ({\n name: e.name,\n path: e.path,\n }));\n sendHtml(res, renderDashboard(repos, lb));\n };\n\n // ── List documents ────────────────────────────────────────────────────────\n const handleList = async (\n req: AnyReq & { params: RouteParams },\n res: AnyRes,\n ): Promise<void> => {\n const repoName = req.params[\"repoName\"];\n if (!repoName) {\n sendHtml(res, \"Bad request\", 400);\n return;\n }\n const entry = registry[repoName];\n if (!entry) {\n sendHtml(res, \"Repository not found\", 404);\n return;\n }\n\n const pageSize = entry.pageSize ?? 25;\n const query = (req.query ?? {}) as Record<string, string>;\n const cursorStr = query[\"cursor\"];\n const dir = query[\"dir\"] === \"prev\" ? \"prev\" : \"next\";\n\n // Sort\n const sortField = query[\"ob\"] ?? \"\";\n const sortDir = (query[\"od\"] === \"desc\" ? \"desc\" : \"asc\") as \"asc\" | \"desc\";\n const sortState = sortField\n ? { field: sortField, dir: sortDir }\n : undefined;\n\n // Rows per page (query ?ps= overrides config, capped at 200)\n const psRaw = parseInt(query[\"ps\"] ?? \"\");\n const currentPageSize =\n Number.isFinite(psRaw) && psRaw > 0 ? Math.min(psRaw, 200) : pageSize;\n\n const allColumns = entry.listColumns ?? Object.keys(entry.schema.shape);\n const docKey = entry.documentKey ?? \"docId\";\n const columns = [docKey, ...allColumns.filter((c: string) => c !== docKey)];\n // Restrict filterable columns to filterableFields when defined.\n // Dot-notation paths (e.g. \"address.city\") are passed through directly;\n // top-level keys expand to sub-fields via buildColumnMeta as before.\n const filterableColumns: string[] = entry.filterableFields\n ? (() => {\n const out: string[] = [];\n for (const f of entry.filterableFields!) {\n if (f.includes(\".\")) {\n out.push(f); // direct dot-notation path\n } else if (allColumns.includes(f)) {\n out.push(f); // regular top-level key\n }\n }\n return out;\n })()\n : allColumns;\n // For dot-notation entries, resolve the correct ZodType; for top-level\n // keys, delegate to the existing buildColumnMeta (handles ZodObject expansion).\n const columnMeta: import(\"./renderer\").ColumnMeta[] = (() => {\n const out: import(\"./renderer\").ColumnMeta[] = [];\n for (const col of filterableColumns) {\n if (col.includes(\".\")) {\n const resolved = resolveZodAtPath(entry.schema, col);\n out.push({\n name: col,\n zodType: resolved ? resolveTypeName(resolved) : \"ZodString\",\n nullable: resolved ? isFieldNullable(resolved) : false,\n enumValues: resolved ? extractEnumValues(resolved) : undefined,\n });\n } else {\n out.push(...buildColumnMeta([col], entry.schema));\n }\n }\n return out;\n })();\n\n // Parse and validate filters from query params\n // validFields built from columnMeta so dot-notation fields (address.city) are accepted\n const validFields = new Set(columnMeta.map((c) => c.name));\n const activeFilters = parseFilters(query, validFields);\n const whereFilters = filtersToWhere(activeFilters);\n\n // Attempt to rehydrate cursor\n let cursorSnapshot:\n | import(\"firebase-admin/firestore\").DocumentSnapshot\n | undefined;\n if (cursorStr) {\n try {\n const colRef = entry.repo.ref as any;\n if (typeof colRef.doc === \"function\") {\n cursorSnapshot = await colRef.doc(cursorStr).get();\n }\n } catch {\n /* ignore */\n }\n }\n\n const [result, totalCount] = await Promise.all([\n entry.repo.query\n .paginate({\n pageSize: currentPageSize,\n cursor: cursorSnapshot,\n // direction + where + orderBy are supported at runtime but not in the strict typed interface\n ...{ direction: dir },\n ...(whereFilters.length > 0 ? { where: whereFilters } : {}),\n ...(sortState\n ? {\n orderBy: [\n { field: sortState.field as any, direction: sortState.dir },\n ],\n }\n : {}),\n })\n .catch(\n (err: unknown) =>\n ({\n queryError: toQueryError(err, {\n ref: entry.repo.ref,\n path: entry.path,\n isGroup: !!entry.isGroup,\n filters: activeFilters,\n sort: sortState,\n }),\n }) as const,\n ),\n entry.repo.aggregate\n .count(\n (whereFilters.length > 0\n ? { where: whereFilters as any }\n : {}) as any,\n )\n .catch(() => undefined as number | undefined),\n ]);\n\n // Discriminate between success and error results\n const isError = \"queryError\" in result;\n const docs = isError ? [] : (result.data as Record<string, unknown>[]);\n const nextCursorId = isError ? \"\" : (result.nextCursor?.id ?? \"\");\n const prevCursorId = isError ? \"\" : (result.prevCursor?.id ?? \"\");\n const queryError = isError ? result.queryError : undefined;\n const lb = getLinkBase(req, basePath);\n\n sendHtml(\n res,\n renderList(\n entry.name,\n docs,\n columns,\n lb,\n {\n hasPrev: isError ? false : result.hasPrevPage,\n hasNext: isError ? false : result.hasNextPage,\n prevCursor: prevCursorId,\n nextCursor: nextCursorId,\n },\n undefined,\n columnMeta,\n activeFilters,\n entry.allowDelete ?? false,\n entry.relationalMeta,\n sortState,\n currentPageSize,\n queryError,\n entry.isGroup,\n totalCount,\n entry.mutableFields,\n entry.schema,\n ),\n );\n };\n\n // ── Create form ───────────────────────────────────────────────────────────\n const handleCreateForm = (\n req: AnyReq & { params: RouteParams },\n res: AnyRes,\n ): void => {\n const repoName = req.params[\"repoName\"];\n if (!repoName) {\n sendHtml(res, \"Bad request\", 400);\n return;\n }\n const entry = registry[repoName];\n if (!entry) {\n sendHtml(res, \"Repository not found\", 404);\n return;\n }\n\n const lb = getLinkBase(req, basePath);\n const createSchema = getMutableSchema(entry.schema, entry.createFields);\n const fields = zodToFields(createSchema);\n const actionUrl = `${lb}/${entry.name}/create`;\n const formHtml = renderForm(fields, actionUrl, \"POST\", \"Create document\");\n\n sendHtml(res, renderFormPage(entry.name, formHtml, \"create\", null, lb));\n };\n\n // ── Create submit ─────────────────────────────────────────────────────────\n const handleCreateSubmit = async (\n req: AnyReq & { params: RouteParams },\n res: AnyRes,\n ): Promise<void> => {\n const repoName = req.params[\"repoName\"];\n if (!repoName) {\n sendHtml(res, \"Bad request\", 400);\n return;\n }\n const entry = registry[repoName];\n if (!entry) {\n sendHtml(res, \"Repository not found\", 404);\n return;\n }\n\n const lb = getLinkBase(req, basePath);\n const rawBody =\n (req.body as Record<string, string | string[] | undefined>) ?? {};\n const parsed = parseFormBody(rawBody, entry.schema);\n const createSchema = getMutableSchema(entry.schema, entry.createFields);\n const validation = createSchema.safeParse(parsed);\n\n if (!validation.success) {\n const fields = zodToFields(createSchema);\n const actionUrl = `${lb}/${entry.name}/create`;\n const formHtml = renderForm(fields, actionUrl, \"POST\", \"Create document\");\n const errorMsg = validation.error.issues\n .map((e) => `${e.path.join(\".\")}: ${e.message}`)\n .join(\", \");\n sendHtml(\n res,\n renderFormPage(entry.name, formHtml, \"create\", null, lb, {\n type: \"error\",\n message: `Validation error: ${errorMsg}`,\n }),\n 422,\n );\n return;\n }\n\n try {\n if (entry.isGroup && entry.parentKeys && entry.parentKeys.length > 0) {\n // Collection-group repos cannot use create(); use set() with parent path args.\n const data: Record<string, any> = { ...validation.data };\n // set() doesn't auto-set createdKey, so inject it here\n if (entry.createdKey) {\n data[entry.createdKey] = new Date();\n }\n const missingKeys = entry.parentKeys.filter((k) => !data[k]);\n if (missingKeys.length > 0) {\n throw new Error(\n `Missing parent key(s) for subcollection create: ${missingKeys.join(\", \")}`,\n );\n }\n const parentIds = entry.parentKeys.map((k) => data[k] as string);\n const docKey = entry.documentKey ?? \"docId\";\n const docId = data[docKey] || generateFirestoreId();\n await entry.repo.set(...parentIds, docId, data);\n } else {\n await entry.repo.create(validation.data);\n }\n redirect(res, `${lb}/${entry.name}?flash=created`);\n } catch (err) {\n const createSchema2 = getMutableSchema(entry.schema, entry.createFields);\n const fields = zodToFields(createSchema2);\n const actionUrl = `${lb}/${entry.name}/create`;\n const formHtml = renderForm(fields, actionUrl, \"POST\", \"Create document\");\n sendHtml(\n res,\n renderFormPage(entry.name, formHtml, \"create\", null, lb, {\n type: \"error\",\n message: `Save error: ${(err as Error).message}`,\n }),\n 500,\n );\n }\n };\n\n // ── Edit form ─────────────────────────────────────────────────────────────\n const handleEditForm = async (\n req: AnyReq & { params: RouteParams },\n res: AnyRes,\n ): Promise<void> => {\n const repoName = req.params[\"repoName\"];\n const docId = req.params[\"id\"];\n if (!repoName || !docId) {\n sendHtml(res, \"Bad request\", 400);\n return;\n }\n const entry = registry[repoName];\n if (!entry) {\n sendHtml(res, \"Repository not found\", 404);\n return;\n }\n\n const lb = getLinkBase(req, basePath);\n\n let doc: Record<string, unknown> | null = null;\n try {\n doc = await fetchDocById(entry, docId);\n } catch (err) {\n const flash = flashFromDocFetchError(entry, docId, err);\n const status = isMissingIndexError(err) ? 424 : 500;\n sendHtml(\n res,\n renderPage(\"\", {\n title: `Edit ${entry.name} / ${docId}`,\n basePath: lb,\n breadcrumb: [\n { label: \"Repositories\", href: lb },\n { label: entry.name, href: `${lb}/${entry.name}` },\n { label: `Edit ${docId}` },\n ],\n flash,\n }),\n status,\n );\n return;\n }\n\n if (!doc) {\n sendHtml(res, \"Document not found\", 404);\n return;\n }\n\n const prefilled = prefillFromDoc(doc, entry.schema);\n const mutableSchema = getMutableSchema(entry.schema, entry.mutableFields);\n const fields = applyPrefill(zodToFields(mutableSchema), prefilled);\n\n const actionUrl = `${lb}/${entry.name}/${encodeURIComponent(docId)}/edit`;\n const formHtml = renderForm(fields, actionUrl, \"POST\", \"Save changes\");\n\n sendHtml(res, renderFormPage(entry.name, formHtml, \"edit\", docId, lb));\n };\n\n // ── Edit submit ───────────────────────────────────────────────────────────\n const handleEditSubmit = async (\n req: AnyReq & { params: RouteParams },\n res: AnyRes,\n ): Promise<void> => {\n const repoName = req.params[\"repoName\"];\n const docId = req.params[\"id\"];\n if (!repoName || !docId) {\n sendHtml(res, \"Bad request\", 400);\n return;\n }\n const entry = registry[repoName];\n if (!entry) {\n sendHtml(res, \"Repository not found\", 404);\n return;\n }\n const lb = getLinkBase(req, basePath);\n const rawBody =\n (req.body as Record<string, string | string[] | undefined>) ?? {};\n const parsed = parseFormBody(rawBody, entry.schema);\n\n // Partial validation for updates (restricted to mutableFields)\n const mutableSchema = getMutableSchema(entry.schema, entry.mutableFields);\n const partialSchema = mutableSchema.partial();\n const validation = partialSchema.safeParse(parsed);\n\n if (!validation.success) {\n const prefilled = Object.fromEntries(\n Object.entries(rawBody).map(([k, v]) => [\n k,\n Array.isArray(v) ? v.join(\",\") : (v ?? \"\"),\n ]),\n );\n const fields = applyPrefill(zodToFields(mutableSchema), prefilled);\n const actionUrl = `${lb}/${entry.name}/${encodeURIComponent(docId)}/edit`;\n const formHtml = renderForm(fields, actionUrl, \"POST\", \"Save changes\");\n const errorMsg = validation.error.issues\n .map((e) => `${e.path.join(\".\")}: ${e.message}`)\n .join(\", \");\n sendHtml(\n res,\n renderFormPage(entry.name, formHtml, \"edit\", docId, lb, {\n type: \"error\",\n message: `Validation error: ${errorMsg}`,\n }),\n 422,\n );\n return;\n }\n\n try {\n // Fetch document to extract path args for subcollection repos\n const doc = await fetchDocById(entry, docId);\n const pathArgs = (doc && extractPathArgs(doc, entry.pathKey)) ?? [docId];\n await entry.repo.update(...pathArgs, validation.data);\n redirect(res, `${lb}/${entry.name}?flash=updated`);\n } catch (err) {\n const mutableSchema2 = getMutableSchema(\n entry.schema,\n entry.mutableFields,\n );\n const fields = zodToFields(mutableSchema2);\n const actionUrl = `${lb}/${entry.name}/${encodeURIComponent(docId)}/edit`;\n const formHtml = renderForm(fields, actionUrl, \"POST\", \"Save changes\");\n const flash = isMissingIndexError(err)\n ? flashFromDocFetchError(entry, docId, err)\n : { type: \"error\" as const, message: `Save error: ${(err as Error).message}` };\n const status = isMissingIndexError(err) ? 424 : 500;\n sendHtml(\n res,\n renderFormPage(entry.name, formHtml, \"edit\", docId, lb, flash),\n status,\n );\n }\n };\n\n // ── Delete ────────────────────────────────────────────────────────────────\n const handleDelete = async (\n req: AnyReq & { params: RouteParams },\n res: AnyRes,\n ): Promise<void> => {\n const repoName = req.params[\"repoName\"];\n const docId = req.params[\"id\"];\n if (!repoName || !docId) {\n sendHtml(res, \"Bad request\", 400);\n return;\n }\n const entry = registry[repoName];\n if (!entry) {\n sendHtml(res, \"Repository not found\", 404);\n return;\n }\n if (!entry.allowDelete) {\n sendHtml(res, \"Delete is not allowed for this repository\", 403);\n return;\n }\n const lb = getLinkBase(req, basePath);\n try {\n // Fetch document to extract path args for subcollection repos\n const doc = await fetchDocById(entry, docId);\n const pathArgs = (doc && extractPathArgs(doc, entry.pathKey)) ?? [docId];\n await entry.repo.delete(...pathArgs);\n redirect(res, `${lb}/${entry.name}?flash=deleted`);\n } catch (err) {\n const flash = isMissingIndexError(err)\n ? flashFromDocFetchError(entry, docId, err)\n : { type: \"error\" as const, message: `Delete error: ${(err as Error).message}` };\n const status = isMissingIndexError(err) ? 424 : 500;\n sendHtml(\n res,\n renderPage(\"\", {\n title: `Delete ${entry.name} / ${docId}`,\n basePath: lb,\n breadcrumb: [\n { label: \"Repositories\", href: lb },\n { label: entry.name, href: `${lb}/${entry.name}` },\n { label: `Delete ${docId}` },\n ],\n flash,\n }),\n status,\n );\n }\n };\n\n // ── Relation right-panel preview (HTML fragment, no shell) ───────────────\n const handlePanel = async (\n req: AnyReq & { params: RouteParams },\n res: AnyRes,\n ): Promise<void> => {\n const repoName = req.params[\"repoName\"];\n if (!repoName) {\n sendHtml(res, \"Bad request\", 400);\n return;\n }\n const entry = registry[repoName];\n if (!entry) {\n sendHtml(res, \"Repository not found\", 404);\n return;\n }\n const lb = getLinkBase(req, basePath);\n const query = (req as any).query as Record<string, string> | undefined;\n const type = query?.[\"type\"] === \"many\" ? \"many\" : \"one\";\n const ps = Math.max(1, Math.min(100, Number(query?.[\"ps\"] ?? 25) || 25));\n const allColumns = entry.listColumns ?? Object.keys(getShape(entry.schema));\n\n // Lazy import the panel components — they're only used by this route.\n const { PanelOne, PanelMany } = await import(\"./components/right-panel\");\n const { renderToString } = await import(\"hono/jsx/dom/server\");\n\n if (type === \"one\") {\n const id = String(query?.[\"id\"] ?? \"\");\n if (!id) {\n sendHtml(res, \"<div class='p-6 text-error'>Missing id parameter.</div>\", 400);\n return;\n }\n try {\n const doc = await fetchDocById(entry, id);\n const html = renderToString(\n PanelOne({\n doc,\n repoName: entry.name,\n basePath: lb,\n schema: entry.schema,\n columns: allColumns,\n }) as any,\n );\n sendHtml(res, html);\n } catch (err) {\n sendHtml(\n res,\n `<div class='p-6 text-error text-sm'>Error: ${(err as Error).message}</div>`,\n 500,\n );\n }\n return;\n }\n\n // many\n const fk = String(query?.[\"fk\"] ?? \"\");\n const fv = String(query?.[\"fv\"] ?? \"\");\n if (!fk || !fv) {\n sendHtml(res, \"<div class='p-6 text-error'>Missing fk/fv parameters.</div>\", 400);\n return;\n }\n const cursorStr = query?.[\"cursor\"] ?? \"\";\n const dir = query?.[\"dir\"] === \"prev\" ? \"prev\" : \"next\";\n let cursorSnapshot:\n | import(\"firebase-admin/firestore\").DocumentSnapshot\n | undefined;\n if (cursorStr) {\n try {\n const colRef = entry.repo.ref as any;\n if (typeof colRef.doc === \"function\") {\n cursorSnapshot = await colRef.doc(cursorStr).get();\n }\n } catch {\n /* ignore */\n }\n }\n try {\n const result = await entry.repo.query.paginate({\n pageSize: ps,\n cursor: cursorSnapshot,\n ...{ direction: dir },\n ...{ where: [[fk, \"==\", coerceFilterValue(fv)]] },\n } as any);\n const html = renderToString(\n PanelMany({\n docs: result.data as Record<string, unknown>[],\n repoName: entry.name,\n basePath: lb,\n fk,\n fv,\n columns: allColumns,\n schema: entry.schema,\n pagination: {\n hasPrev: result.hasPrevPage,\n hasNext: result.hasNextPage,\n prevCursor: result.prevCursor?.id ?? \"\",\n nextCursor: result.nextCursor?.id ?? \"\",\n pageSize: ps,\n },\n }) as any,\n );\n sendHtml(res, html);\n } catch (err) {\n sendHtml(\n res,\n `<div class='p-6 text-error text-sm'>Error: ${(err as Error).message}</div>`,\n 500,\n );\n }\n };\n\n // ── Bulk operations ──────────────────────────────────────────────────────\n /** Build DocumentReferences for a list of docIds, handling subcollections via fetchDocById. */\n const resolveRefs = async (\n entry: AdminRepoEntry,\n ids: string[],\n ): Promise<import(\"firebase-admin/firestore\").DocumentReference[]> => {\n const refs: import(\"firebase-admin/firestore\").DocumentReference[] = [];\n for (const id of ids) {\n let pathArgs: string[] | undefined;\n if (entry.isGroup || entry.parentKeys?.length) {\n const doc = await fetchDocById(entry, id);\n pathArgs = doc ? extractPathArgs(doc, entry.pathKey) : undefined;\n }\n if (!pathArgs) pathArgs = [id];\n try {\n const ref = (entry.repo as any).documentRef(...pathArgs);\n if (ref) refs.push(ref);\n } catch {\n /* ignore */\n }\n }\n return refs;\n };\n\n /** Resolve all docIds matching a set of filters by streaming the query in pages. */\n const resolveAllIds = async (\n entry: AdminRepoEntry,\n filters: FilterState[],\n ): Promise<string[]> => {\n const where = filtersToWhere(filters);\n const docKey = entry.documentKey ?? \"docId\";\n const ids: string[] = [];\n let cursor: import(\"firebase-admin/firestore\").DocumentSnapshot | undefined;\n // Stream in pages of 500\n // eslint-disable-next-line no-constant-condition\n while (true) {\n const page: any = await entry.repo.query.paginate({\n pageSize: 500,\n cursor,\n ...{ direction: \"next\" },\n ...(where.length > 0 ? { where } : {}),\n } as any);\n for (const d of page.data as Record<string, unknown>[]) {\n const id = String(d[docKey] ?? d[\"id\"] ?? \"\");\n if (id) ids.push(id);\n }\n if (!page.hasNextPage || !page.nextCursor) break;\n cursor = page.nextCursor;\n }\n return ids;\n };\n\n const handleBulkDelete = async (\n req: AnyReq & { params: RouteParams },\n res: AnyRes,\n ): Promise<void> => {\n const repoName = req.params[\"repoName\"];\n if (!repoName) {\n sendJson(res, { error: \"Bad request\" }, 400);\n return;\n }\n const entry = registry[repoName];\n if (!entry) {\n sendJson(res, { error: \"Repository not found\" }, 404);\n return;\n }\n if (!entry.allowDelete) {\n sendJson(res, { error: \"Delete is not allowed for this repository\" }, 403);\n return;\n }\n const body = ((req as any).body ?? {}) as {\n ids?: unknown;\n selectAll?: unknown;\n filters?: unknown;\n };\n try {\n const ids = await collectTargetIds(entry, body);\n if (ids.length === 0) {\n sendJson(res, { deleted: 0 });\n return;\n }\n const refs = await resolveRefs(entry, ids);\n // Chunk to 500 per Firestore batched-write limit\n for (let i = 0; i < refs.length; i += 500) {\n await entry.repo.bulk.delete(refs.slice(i, i + 500));\n }\n sendJson(res, { deleted: refs.length });\n } catch (err) {\n sendJson(res, { error: (err as Error).message }, 500);\n }\n };\n\n const handleBulkUpdate = async (\n req: AnyReq & { params: RouteParams },\n res: AnyRes,\n ): Promise<void> => {\n const repoName = req.params[\"repoName\"];\n if (!repoName) {\n sendJson(res, { error: \"Bad request\" }, 400);\n return;\n }\n const entry = registry[repoName];\n if (!entry) {\n sendJson(res, { error: \"Repository not found\" }, 404);\n return;\n }\n const body = ((req as any).body ?? {}) as {\n ids?: unknown;\n selectAll?: unknown;\n filters?: unknown;\n field?: unknown;\n value?: unknown;\n };\n const field = String(body.field ?? \"\");\n if (!field) {\n sendJson(res, { error: \"Missing 'field'\" }, 400);\n return;\n }\n // SECURITY: Strict allow-list of fields\n if (!entry.mutableFields || !entry.mutableFields.includes(field)) {\n sendJson(res, { error: `Field '${field}' is not bulk-updatable` }, 403);\n return;\n }\n // Parse value through the field's Zod schema for validation/coercion\n const fieldSchema = (entry.schema as any).shape?.[field] as\n | z.ZodType\n | undefined;\n let parsedValue: unknown = body.value;\n if (fieldSchema) {\n const parsed = fieldSchema.safeParse(body.value);\n if (!parsed.success) {\n sendJson(\n res,\n { error: `Invalid value for '${field}': ${parsed.error.message}` },\n 400,\n );\n return;\n }\n parsedValue = parsed.data;\n }\n try {\n const ids = await collectTargetIds(entry, body);\n if (ids.length === 0) {\n sendJson(res, { updated: 0 });\n return;\n }\n const refs = await resolveRefs(entry, ids);\n const items = refs.map((docRef) => ({\n docRef,\n data: { [field]: parsedValue } as any,\n }));\n for (let i = 0; i < items.length; i += 500) {\n await entry.repo.bulk.update(items.slice(i, i + 500));\n }\n sendJson(res, { updated: items.length });\n } catch (err) {\n sendJson(res, { error: (err as Error).message }, 500);\n }\n };\n\n /** Shared logic: extract target IDs from a request body (`ids[]` OR `selectAll + filters`). */\n async function collectTargetIds(\n entry: AdminRepoEntry,\n body: { ids?: unknown; selectAll?: unknown; filters?: unknown },\n ): Promise<string[]> {\n if (body.selectAll) {\n const filters = sanitizeFilters(body.filters, entry);\n return await resolveAllIds(entry, filters);\n }\n if (Array.isArray(body.ids)) {\n return body.ids.filter((x): x is string => typeof x === \"string\" && !!x);\n }\n return [];\n }\n\n function sanitizeFilters(\n raw: unknown,\n entry: AdminRepoEntry,\n ): FilterState[] {\n if (!Array.isArray(raw)) return [];\n const validFields = new Set(\n (entry.filterableFields ?? Object.keys(getShape(entry.schema))).map((s) =>\n String(s),\n ),\n );\n const validOps = new Set([\n \"==\",\n \"!=\",\n \"<\",\n \"<=\",\n \">\",\n \">=\",\n \"in\",\n \"not-in\",\n \"array-contains\",\n \"array-contains-any\",\n ]);\n const out: FilterState[] = [];\n for (const f of raw) {\n if (\n f &&\n typeof f === \"object\" &&\n typeof (f as any).field === \"string\" &&\n validFields.has((f as any).field) &&\n typeof (f as any).value === \"string\" &&\n validOps.has(String((f as any).op))\n ) {\n out.push({\n field: (f as any).field,\n op: (f as any).op,\n value: (f as any).value,\n });\n }\n }\n return out;\n }\n\n return {\n handleDashboard,\n handleList,\n handleCreateForm,\n handleCreateSubmit,\n handleEditForm,\n handleEditSubmit,\n handleDelete,\n handlePanel,\n handleBulkDelete,\n handleBulkUpdate,\n };\n}\n\nfunction sendJson(res: AnyRes, payload: unknown, status = 200): void {\n res\n .status(status)\n .set(\"Content-Type\", \"application/json; charset=utf-8\")\n .send(JSON.stringify(payload));\n}\n\n/** Coerce a string filter value to the most likely runtime type for a Firestore where clause. */\nfunction coerceFilterValue(v: string): unknown {\n if (v === \"true\") return true;\n if (v === \"false\") return false;\n if (v !== \"\" && !isNaN(Number(v))) return Number(v);\n return v;\n}\n","/**\n * Zod-to-HTML form generator.\n * Inspects a Zod schema's `_def` to produce typed HTML `<input>` / `<select>`\n * elements — no extra dependencies needed.\n *\n * Supported Zod types:\n * ZodString, ZodNumber, ZodBoolean, ZodDate, ZodEnum,\n * ZodOptional, ZodNullable, ZodDefault, ZodObject, ZodArray, ZodLiteral\n *\n * For ZodObject fields, nested sections are rendered with indentation.\n * For ZodArray and unknown types, a `<textarea>` with JSON hint is used.\n *\n * @example\n * ```typescript\n * import { zodToFields, renderForm } from \"@lpdjs/firestore-repo-service/servers/admin\";\n *\n * // Convert Zod schema to field descriptors\n * const schema = z.object({\n * name: z.string(),\n * email: z.string().email(),\n * age: z.number().optional(),\n * role: z.enum([\"admin\", \"user\"]),\n * isActive: z.boolean().default(true),\n * address: z.object({\n * street: z.string(),\n * city: z.string(),\n * }),\n * });\n *\n * const fields = zodToFields(schema);\n * // Returns:\n * // [\n * // { name: \"name\", type: \"text\", required: true, ... },\n * // { name: \"email\", type: \"text\", required: true, hint: \"email\", ... },\n * // { name: \"age\", type: \"number\", required: false, ... },\n * // { name: \"role\", type: \"select\", options: [\"admin\", \"user\"], ... },\n * // { name: \"isActive\", type: \"checkbox\", defaultValue: true, ... },\n * // { name: \"address\", nested: [...], ... },\n * // ]\n *\n * // Render form HTML\n * const html = renderForm(fields, \"create\", {\n * name: \"John\",\n * email: \"john@example.com\",\n * });\n *\n * // Render single field\n * const fieldHtml = renderField(fields[0], { name: \"Jane\" });\n * ```\n */\n\nimport type { z } from \"zod\";\nimport {\n getArrayElementType,\n getDefaultValue,\n getEnumValues,\n getInnerType,\n getLiteralValue,\n getNativeEnumValues,\n getShape,\n getStringChecks,\n getTypeName,\n} from \"../../shared/zod-compat\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface FieldDescriptor {\n name: string;\n label: string;\n type:\n | \"text\"\n | \"number\"\n | \"checkbox\"\n | \"datetime-local\"\n | \"select\"\n | \"textarea\";\n required: boolean;\n nullable: boolean;\n options?: string[]; // for select\n defaultValue?: unknown;\n nested?: FieldDescriptor[]; // for objects\n hint?: string;\n /** For array fields: the element input type */\n arrayElementType?:\n | \"text\"\n | \"number\"\n | \"checkbox\"\n | \"select\"\n | \"datetime-local\"\n | \"object\";\n /** For enum arrays: the allowed values */\n arrayElementOptions?: string[];\n /** For object arrays: the field descriptors for one element */\n arrayElementFields?: FieldDescriptor[];\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/** Convert camelCase / snake_case to \"Human Label\" */\nfunction toLabel(name: string): string {\n return name\n .replace(/([A-Z])/g, \" $1\")\n .replace(/_/g, \" \")\n .replace(/^\\s/, \"\")\n .replace(/^./, (c) => c.toUpperCase());\n}\n\n/** Unwrap ZodOptional / ZodNullable / ZodDefault to the inner schema */\nfunction unwrap(schema: z.ZodType): {\n inner: z.ZodType;\n required: boolean;\n nullable: boolean;\n defaultValue: unknown;\n} {\n let inner: z.ZodType = schema;\n let required = true;\n let nullable = false;\n let defaultValue: unknown = undefined;\n\n // eslint-disable-next-line no-constant-condition\n while (true) {\n const tn = getTypeName(inner);\n if (tn === \"ZodOptional\") {\n required = false;\n inner = getInnerType(inner)!;\n } else if (tn === \"ZodNullable\") {\n required = false;\n nullable = true;\n inner = getInnerType(inner)!;\n } else if (tn === \"ZodDefault\") {\n required = false;\n defaultValue = getDefaultValue(inner);\n inner = getInnerType(inner)!;\n } else {\n break;\n }\n }\n\n return { inner, required, nullable, defaultValue };\n}\n\n// ---------------------------------------------------------------------------\n// Core introspection\n// ---------------------------------------------------------------------------\n\nexport function zodToFields(\n schema: z.ZodType,\n namePrefix = \"\",\n): FieldDescriptor[] {\n const tn = getTypeName(schema);\n\n if (tn === \"ZodObject\") {\n const shape: Record<string, z.ZodType> = getShape(schema);\n return Object.entries(shape).map(([fieldName, fieldSchema]) =>\n zodFieldToDescriptor(\n namePrefix ? `${namePrefix}.${fieldName}` : fieldName,\n fieldName,\n fieldSchema,\n ),\n );\n }\n\n // If the root schema is not an object, treat it as a single field\n return [\n zodFieldToDescriptor(namePrefix || \"value\", namePrefix || \"value\", schema),\n ];\n}\n\nfunction zodFieldToDescriptor(\n name: string,\n rawName: string,\n schema: z.ZodType,\n): FieldDescriptor {\n const { inner, required, nullable, defaultValue } = unwrap(schema);\n const tn = getTypeName(inner);\n const label = toLabel(rawName.split(\".\").pop() ?? rawName);\n\n switch (tn) {\n case \"ZodString\": {\n const checks = getStringChecks(inner);\n const isEmail = checks.includes(\"email\");\n const isUrl = checks.includes(\"url\");\n return {\n name,\n label,\n type: \"text\",\n required,\n nullable,\n defaultValue,\n hint: isEmail ? \"email\" : isUrl ? \"url\" : undefined,\n };\n }\n\n case \"ZodNumber\":\n case \"ZodBigInt\":\n return { name, label, type: \"number\", required, nullable, defaultValue };\n\n case \"ZodBoolean\":\n return {\n name,\n label,\n type: \"checkbox\",\n required,\n nullable,\n defaultValue,\n };\n\n case \"ZodDate\":\n case \"ZodCoerce\":\n return {\n name,\n label,\n type: \"datetime-local\",\n required,\n nullable,\n defaultValue,\n };\n\n case \"ZodEnum\": {\n const values = getEnumValues(inner);\n return {\n name,\n label,\n type: \"select\",\n required,\n nullable,\n defaultValue,\n options: values,\n };\n }\n\n case \"ZodNativeEnum\": {\n const enumObj = getNativeEnumValues(inner);\n const values = Object.values(enumObj).filter(\n (v) => typeof v === \"string\",\n ) as string[];\n return {\n name,\n label,\n type: \"select\",\n required,\n nullable,\n defaultValue,\n options: values,\n };\n }\n\n case \"ZodLiteral\": {\n const value = String(getLiteralValue(inner) ?? \"\");\n return {\n name,\n label,\n type: \"select\",\n required,\n nullable,\n defaultValue,\n options: [value],\n };\n }\n\n case \"ZodObject\": {\n const nested = zodToFields(inner, name);\n return {\n name,\n label,\n type: \"textarea\",\n required,\n nullable,\n defaultValue,\n nested,\n hint: \"JSON object\",\n };\n }\n\n case \"ZodArray\": {\n const elSchema = getArrayElementType(inner);\n if (!elSchema) {\n return {\n name,\n label,\n type: \"textarea\",\n required,\n nullable,\n defaultValue,\n hint: \"JSON array\",\n };\n }\n const { inner: elInner } = unwrap(elSchema);\n const elTn = getTypeName(elInner);\n\n let arrayElementType: FieldDescriptor[\"arrayElementType\"];\n let arrayElementOptions: string[] | undefined;\n let arrayElementFields: FieldDescriptor[] | undefined;\n\n switch (elTn) {\n case \"ZodString\":\n arrayElementType = \"text\";\n break;\n case \"ZodNumber\":\n case \"ZodBigInt\":\n arrayElementType = \"number\";\n break;\n case \"ZodBoolean\":\n arrayElementType = \"checkbox\";\n break;\n case \"ZodDate\":\n arrayElementType = \"datetime-local\";\n break;\n case \"ZodEnum\":\n arrayElementType = \"select\";\n arrayElementOptions = getEnumValues(elInner);\n break;\n case \"ZodNativeEnum\":\n arrayElementType = \"select\";\n arrayElementOptions = Object.values(\n getNativeEnumValues(elInner),\n ).filter((v) => typeof v === \"string\") as string[];\n break;\n case \"ZodObject\":\n arrayElementType = \"object\";\n arrayElementFields = zodToFields(elInner);\n break;\n default:\n // Unknown element type → JSON textarea fallback\n return {\n name,\n label,\n type: \"textarea\",\n required,\n nullable,\n defaultValue,\n hint: \"JSON array\",\n };\n }\n\n return {\n name,\n label,\n type: \"textarea\",\n required,\n nullable,\n defaultValue,\n arrayElementType,\n arrayElementOptions,\n arrayElementFields,\n };\n }\n\n default:\n return {\n name,\n label,\n type: \"textarea\",\n required,\n nullable,\n defaultValue,\n hint: \"JSON\",\n };\n }\n}\n\n// ---------------------------------------------------------------------------\n// HTML generation — DaisyUI + Tailwind classes\n// ---------------------------------------------------------------------------\n\nexport function renderField(field: FieldDescriptor, depth = 0): string {\n const indent = depth > 0 ? `ml-${depth * 4}` : \"\";\n const id = `field_${field.name.replace(/\\./g, \"__\")}`;\n const nameAttr = field.name;\n const requiredAttr = field.required ? \" required\" : \"\";\n // \"__null__\" is the sentinel value used when a nullable field is set to null\n const isNullValue = field.defaultValue === \"__null__\";\n const defaultStr =\n !isNullValue && field.defaultValue != null\n ? String(field.defaultValue)\n : \"\";\n\n // Null toggle — rendered inline to the right of the input for nullable non-checkbox fields\n const nullToggle =\n field.nullable && field.type !== \"checkbox\"\n ? `<span class=\"flex items-center gap-1 shrink-0\">\n <input type=\"hidden\" id=\"${id}__isnull\" name=\"${nameAttr}__isnull\" value=\"${isNullValue ? \"1\" : \"\"}\">\n <label class=\"flex items-center gap-1 cursor-pointer select-none text-xs text-base-content/40 hover:text-base-content/70 border border-base-300 rounded px-2 py-1\">\n <input type=\"checkbox\" class=\"checkbox checkbox-xs\" ${isNullValue ? \"checked\" : \"\"}\n onchange=\"(function(cb){\n var inp = document.getElementById('${id}');\n var h = document.getElementById('${id}__isnull');\n if (cb.checked) { inp.disabled=true; inp.style.opacity='0.35'; h.value='1'; }\n else { inp.disabled=false; inp.style.opacity=''; h.value=''; }\n })(this)\">\n <span>null</span>\n </label>\n </span>`\n : \"\";\n\n let input: string;\n\n switch (field.type) {\n case \"checkbox\":\n // Nullable boolean → 3-state select (null / true / false)\n if (field.nullable) {\n const sel3 = isNullValue\n ? \"__null__\"\n : defaultStr === \"true\"\n ? \"true\"\n : defaultStr === \"false\"\n ? \"false\"\n : \"__null__\";\n return `\n <div class=\"form-control mb-3 ${indent}\">\n <label for=\"${id}\" class=\"label pb-1\">\n <span class=\"label-text font-medium\">\n ${e(field.label)}\n <span class=\"text-base-content/40 text-xs ml-1\">(nullable)</span>\n </span>\n </label>\n <select id=\"${id}\" name=\"${nameAttr}\" class=\"select select-bordered select-sm w-full\">\n <option value=\"__null__\"${sel3 === \"__null__\" ? \" selected\" : \"\"}>— null —</option>\n <option value=\"true\"${sel3 === \"true\" ? \" selected\" : \"\"}>✓ true</option>\n <option value=\"false\"${sel3 === \"false\" ? \" selected\" : \"\"}>✗ false</option>\n </select>\n </div>`;\n }\n return `\n <div class=\"form-control ${indent}\">\n <label class=\"label cursor-pointer justify-start gap-3\">\n <input type=\"checkbox\" id=\"${id}\" name=\"${nameAttr}\" value=\"true\"${\n defaultStr === \"true\" ? \" checked\" : \"\"\n } class=\"checkbox checkbox-primary checkbox-sm\">\n <span class=\"label-text font-medium\">\n ${e(field.label)}${field.required ? ` <span class=\"text-error\">*</span>` : \"\"}\n </span>\n </label>\n </div>`;\n\n case \"select\":\n input = `<select id=\"${id}\" name=\"${nameAttr}\"${requiredAttr}${isNullValue ? ' disabled style=\"opacity:0.35\"' : \"\"} class=\"select select-bordered select-sm w-full\">\n ${field.required && !field.nullable ? \"\" : `<option value=\"\">— optional —</option>`}\n ${(field.options ?? []).map((o) => `<option value=\"${e(o)}\"${defaultStr === o ? \" selected\" : \"\"}>${e(o)}</option>`).join(\"\\n \")}\n </select>`;\n break;\n\n case \"textarea\":\n if (field.arrayElementType) {\n return renderArrayField(field, depth);\n }\n if (field.nested && field.nested.length > 0) {\n const subFields = field.nested\n .map((f) => renderField(f, depth + 1))\n .join(\"\\n\");\n return `\n <fieldset class=\"fieldset border border-base-300 rounded-box p-3 mb-3 ${indent}\">\n <legend class=\"fieldset-legend text-xs font-semibold text-base-content/60 px-1\">\n ${e(field.label)}${field.required ? ` <span class=\"text-error\">*</span>` : \"\"}\n </legend>\n ${subFields}\n </fieldset>`;\n }\n input = `<textarea id=\"${id}\" name=\"${nameAttr}\"${requiredAttr} rows=\"3\"${isNullValue ? ' disabled style=\"opacity:0.35\"' : \"\"}\n data-json\n class=\"textarea textarea-bordered textarea-sm w-full font-mono text-xs\"\n placeholder=\"${e(field.hint ?? \"JSON\")}\">${e(defaultStr)}</textarea>`;\n break;\n\n default:\n input = `<input type=\"${field.type}\" id=\"${id}\" name=\"${nameAttr}\"${requiredAttr}${isNullValue ? ' disabled style=\"opacity:0.35\"' : \"\"}\n value=\"${e(defaultStr)}\"\n class=\"input input-bordered input-sm w-full\"${\n field.hint === \"email\"\n ? ' autocomplete=\"email\"'\n : field.hint === \"url\"\n ? ' autocomplete=\"url\"'\n : \"\"\n }>`;\n }\n\n return `\n <div class=\"form-control mb-3 ${indent}\">\n <label for=\"${id}\" class=\"label pb-1\">\n <span class=\"label-text font-medium\">\n ${e(field.label)}${field.required ? ` <span class=\"text-error\">*</span>` : \"\"}\n ${field.hint ? `<span class=\"text-base-content/40 text-xs ml-1\">(${e(field.hint)})</span>` : \"\"}\n </span>\n </label>\n <div class=\"flex items-center gap-2\">\n <div class=\"flex-1 min-w-0\">${input}</div>\n ${nullToggle}\n </div>\n </div>`;\n}\n\n/** Minimal HTML escape */\nfunction e(s: string): string {\n return s\n .replace(/&/g, \"&\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\")\n .replace(/\"/g, \""\")\n .replace(/'/g, \"'\");\n}\n\n// ---------------------------------------------------------------------------\n// Array field rendering\n// ---------------------------------------------------------------------------\n\nfunction renderArrayField(field: FieldDescriptor, depth: number): string {\n const indent = depth > 0 ? `ml-${depth * 4}` : \"\";\n const id = `field_${field.name.replace(/\\./g, \"__\")}`;\n const isNullValue = field.defaultValue === \"__null__\";\n const isObject = field.arrayElementType === \"object\";\n\n // Parse existing value (JSON string → array)\n let items: unknown[] = [];\n if (\n field.defaultValue != null &&\n field.defaultValue !== \"\" &&\n field.defaultValue !== \"__null__\"\n ) {\n try {\n items = JSON.parse(String(field.defaultValue));\n } catch {\n /* ignore */\n }\n }\n if (!Array.isArray(items)) items = [];\n\n const itemsHtml = isObject\n ? items\n .map((item) =>\n renderObjectItem(field, (item as Record<string, unknown>) ?? {}),\n )\n .join(\"\\n\")\n : items.map((item) => renderPrimitiveItem(field, item)).join(\"\\n\");\n\n const templateHtml = isObject\n ? renderObjectItem(field, {})\n : renderPrimitiveItem(field, \"\");\n\n // Null toggle for nullable array fields\n const nullToggle =\n field.nullable\n ? `<span class=\"flex items-center gap-1 mt-2\">\n <input type=\"hidden\" id=\"${id}__isnull\" name=\"${e(field.name)}__isnull\" value=\"${isNullValue ? \"1\" : \"\"}\">\n <label class=\"flex items-center gap-1 cursor-pointer select-none text-xs text-base-content/40 hover:text-base-content/70 border border-base-300 rounded px-2 py-1\">\n <input type=\"checkbox\" class=\"checkbox checkbox-xs\" ${isNullValue ? \"checked\" : \"\"}\n onchange=\"(function(cb){\n var fs = cb.closest('[data-frs-array]');\n var h = document.getElementById('${id}__isnull');\n var hidden = document.getElementById('${id}');\n if (cb.checked) { fs.querySelector('[data-frs-array-items]').style.opacity='0.35'; h.value='1'; hidden.disabled=true; }\n else { fs.querySelector('[data-frs-array-items]').style.opacity=''; h.value=''; hidden.disabled=false; }\n })(this)\">\n <span>null</span>\n </label>\n </span>`\n : \"\";\n\n return `\n <fieldset class=\"fieldset border border-base-300 rounded-box p-3 mb-3 ${indent}\"\n data-frs-array=\"${e(field.name)}\" data-frs-array-type=\"${e(field.arrayElementType ?? \"text\")}\">\n <legend class=\"fieldset-legend text-xs font-semibold text-base-content/60 px-1\">\n ${e(field.label)}${field.required ? ` <span class=\"text-error\">*</span>` : \"\"}\n </legend>\n <input type=\"hidden\" id=\"${id}\" name=\"${e(field.name)}\" value=\"${e(JSON.stringify(items))}\"${isNullValue ? \" disabled\" : \"\"}>\n <div data-frs-array-items${isNullValue ? ' style=\"opacity:0.35\"' : \"\"}>\n ${itemsHtml}\n </div>\n <template data-frs-array-tpl>${templateHtml}</template>\n <button type=\"button\" class=\"btn btn-xs btn-outline mt-1\" data-frs-array-add>+ Add</button>\n ${nullToggle}\n </fieldset>`;\n}\n\nfunction renderPrimitiveItem(\n field: FieldDescriptor,\n value: unknown,\n): string {\n const strVal = value != null ? String(value) : \"\";\n let inputHtml: string;\n\n switch (field.arrayElementType) {\n case \"select\":\n inputHtml = `<select data-frs-val class=\"select select-bordered select-sm flex-1\">\n <option value=\"\">—</option>\n ${(field.arrayElementOptions ?? []).map((o) => `<option value=\"${e(o)}\"${strVal === o ? \" selected\" : \"\"}>${e(o)}</option>`).join(\"\")}\n </select>`;\n break;\n case \"checkbox\":\n inputHtml = `<label class=\"flex items-center gap-2 flex-1 cursor-pointer\">\n <input type=\"checkbox\" data-frs-val class=\"checkbox checkbox-sm checkbox-primary\"${strVal === \"true\" ? \" checked\" : \"\"}>\n <span class=\"text-sm\">true</span>\n </label>`;\n break;\n case \"number\":\n inputHtml = `<input type=\"number\" data-frs-val value=\"${e(strVal)}\" class=\"input input-bordered input-sm flex-1\">`;\n break;\n case \"datetime-local\":\n inputHtml = `<input type=\"datetime-local\" data-frs-val value=\"${e(strVal)}\" class=\"input input-bordered input-sm flex-1\">`;\n break;\n default:\n inputHtml = `<input type=\"text\" data-frs-val value=\"${e(strVal)}\" class=\"input input-bordered input-sm flex-1\">`;\n }\n\n return `<div class=\"flex items-center gap-2 mb-2\" data-frs-array-item>\n ${inputHtml}\n <button type=\"button\" class=\"btn btn-xs btn-ghost text-error\" data-frs-array-rm>×</button>\n </div>`;\n}\n\nfunction renderObjectItem(\n field: FieldDescriptor,\n obj: Record<string, unknown>,\n): string {\n const elFields = field.arrayElementFields ?? [];\n\n const fieldsHtml = elFields\n .map((f) => {\n const val = obj[f.name];\n const strVal =\n val == null\n ? \"\"\n : typeof val === \"object\"\n ? JSON.stringify(val)\n : String(val);\n\n switch (f.type) {\n case \"checkbox\":\n return `<div class=\"form-control mb-2\">\n <label class=\"label cursor-pointer justify-start gap-3\">\n <input type=\"checkbox\" data-frs-key=\"${e(f.name)}\" class=\"checkbox checkbox-sm checkbox-primary\"${strVal === \"true\" ? \" checked\" : \"\"}>\n <span class=\"label-text text-sm\">${e(f.label)}</span>\n </label>\n </div>`;\n case \"select\":\n return `<div class=\"form-control mb-2\">\n <label class=\"label pb-1\"><span class=\"label-text text-sm\">${e(f.label)}</span></label>\n <select data-frs-key=\"${e(f.name)}\" class=\"select select-bordered select-sm w-full\">\n ${f.required ? \"\" : `<option value=\"\">—</option>`}\n ${(f.options ?? []).map((o) => `<option value=\"${e(o)}\"${strVal === o ? \" selected\" : \"\"}>${e(o)}</option>`).join(\"\")}\n </select>\n </div>`;\n case \"number\":\n return `<div class=\"form-control mb-2\">\n <label class=\"label pb-1\"><span class=\"label-text text-sm\">${e(f.label)}</span></label>\n <input type=\"number\" data-frs-key=\"${e(f.name)}\" value=\"${e(strVal)}\" class=\"input input-bordered input-sm w-full\">\n </div>`;\n case \"datetime-local\":\n return `<div class=\"form-control mb-2\">\n <label class=\"label pb-1\"><span class=\"label-text text-sm\">${e(f.label)}</span></label>\n <input type=\"datetime-local\" data-frs-key=\"${e(f.name)}\" value=\"${e(strVal)}\" class=\"input input-bordered input-sm w-full\">\n </div>`;\n case \"textarea\":\n return `<div class=\"form-control mb-2\">\n <label class=\"label pb-1\"><span class=\"label-text text-sm\">${e(f.label)}</span></label>\n <textarea data-frs-key=\"${e(f.name)}\" rows=\"2\" class=\"textarea textarea-bordered textarea-sm w-full font-mono text-xs\" placeholder=\"JSON\">${e(strVal)}</textarea>\n </div>`;\n default:\n return `<div class=\"form-control mb-2\">\n <label class=\"label pb-1\"><span class=\"label-text text-sm\">${e(f.label)}</span></label>\n <input type=\"text\" data-frs-key=\"${e(f.name)}\" value=\"${e(strVal)}\" class=\"input input-bordered input-sm w-full\">\n </div>`;\n }\n })\n .join(\"\\n\");\n\n return `<div class=\"border border-base-200 rounded p-3 mb-2\" data-frs-array-item>\n <div class=\"flex justify-end mb-1\">\n <button type=\"button\" class=\"btn btn-xs btn-ghost text-error\" data-frs-array-rm>×</button>\n </div>\n ${fieldsHtml}\n </div>`;\n}\n\n// ---------------------------------------------------------------------------\n// Full form render\n// ---------------------------------------------------------------------------\n\nexport function renderForm(\n fields: FieldDescriptor[],\n action: string,\n method: \"GET\" | \"POST\",\n submitLabel = \"Save\",\n): string {\n const fieldsHtml = fields.map((f) => renderField(f)).join(\"\\n\");\n return `\n <form action=\"${e(action)}\" method=\"${method}\" novalidate data-frs-form>\n ${fieldsHtml}\n <div class=\"flex gap-2 mt-4 pt-4 border-t border-base-200\">\n <button type=\"submit\" class=\"btn btn-primary btn-sm\">${e(submitLabel)}</button>\n <button type=\"button\" class=\"btn btn-ghost btn-sm\" onclick=\"history.back()\">Cancel</button>\n </div>\n </form>`;\n}\n","export { CellValue } from \"./cell-value\";\nexport { ClientScript } from \"./client-script\";\nexport { renderDashboardJsx } from \"./dashboard\";\nexport { FilterBar } from \"./filter-bar\";\nexport { renderFormPageJsx } from \"./form\";\nexport { renderListJsx } from \"./list\";\nexport { PageShell, renderHtml, renderPageJsx } from \"./shell\";\nexport type {\n ColumnMeta,\n FilterState,\n PageOptions,\n QueryError,\n RelationalFieldMeta,\n SortState,\n WhereOp,\n} from \"./types\";\n","// ── Right panel (relations preview) ─────────────────────────────────────────\n(function () {\n function panelEls() {\n return {\n root: document.querySelector(\"[data-frs-panel-root]\"),\n backdrop: document.querySelector(\"[data-frs-panel-backdrop]\"),\n panel: document.querySelector(\"[data-frs-panel]\"),\n title: document.querySelector(\"[data-frs-panel-title]\"),\n body: document.querySelector(\"[data-frs-panel-body]\"),\n };\n }\n function openPanel(label) {\n var els = panelEls();\n if (!els.root || !els.panel) return;\n els.root.classList.remove(\"hidden\");\n els.root.setAttribute(\"aria-hidden\", \"false\");\n requestAnimationFrame(function () {\n if (els.backdrop) els.backdrop.style.opacity = \"1\";\n if (els.panel) els.panel.style.transform = \"translateX(0)\";\n });\n if (els.title) els.title.textContent = label || \"Relation\";\n if (els.body) {\n els.body.innerHTML =\n '<div class=\"flex items-center justify-center py-12 text-base-content/40\"><span class=\"loading loading-spinner loading-md\"></span></div>';\n }\n }\n function closePanel() {\n var els = panelEls();\n if (!els.root || !els.panel) return;\n if (els.backdrop) els.backdrop.style.opacity = \"0\";\n if (els.panel) els.panel.style.transform = \"translateX(100%)\";\n setTimeout(function () {\n els.root.classList.add(\"hidden\");\n els.root.setAttribute(\"aria-hidden\", \"true\");\n }, 200);\n }\n function basePathFromLocation() {\n // The current list page is at <basePath>/<repoName>...; we strip everything after the basePath.\n // We can't know basePath without context, so we derive it from the current URL up to the repoName segment.\n // Caller passes the absolute fragment URL via data attribute; we just need the prefix here.\n return window.location.pathname.replace(/\\/[^/]*\\/?$/, \"\");\n }\n function fetchPanel(url, label) {\n openPanel(label);\n fetch(url, { credentials: \"same-origin\" })\n .then(function (r) {\n return r.text();\n })\n .then(function (html) {\n var els = panelEls();\n if (els.body) els.body.innerHTML = html;\n })\n .catch(function (err) {\n var els = panelEls();\n if (els.body) {\n els.body.innerHTML =\n '<div class=\"p-6 text-error text-sm\">Error: ' +\n (err && err.message ? err.message : String(err)) +\n \"</div>\";\n }\n });\n }\n document.addEventListener(\"click\", function (e) {\n var trigger = e.target.closest(\"[data-frs-relation]\");\n if (trigger) {\n e.preventDefault();\n var type = trigger.getAttribute(\"data-frs-rel-type\");\n var repo = trigger.getAttribute(\"data-frs-rel-repo\");\n var fk = trigger.getAttribute(\"data-frs-rel-fk\");\n var val = trigger.getAttribute(\"data-frs-rel-val\");\n var label = trigger.getAttribute(\"data-frs-rel-label\") || \"Relation\";\n var bp = basePathFromLocation();\n var url;\n if (type === \"one\") {\n url =\n bp +\n \"/\" +\n encodeURIComponent(repo) +\n \"/_panel?type=one&id=\" +\n encodeURIComponent(val);\n } else {\n url =\n bp +\n \"/\" +\n encodeURIComponent(repo) +\n \"/_panel?type=many&fk=\" +\n encodeURIComponent(fk) +\n \"&fv=\" +\n encodeURIComponent(val);\n }\n fetchPanel(url, repo + \" · \" + label);\n return;\n }\n if (e.target.closest(\"[data-frs-panel-close]\")) {\n closePanel();\n return;\n }\n if (e.target.closest(\"[data-frs-panel-backdrop]\")) {\n closePanel();\n return;\n }\n var pageBtn = e.target.closest(\"[data-frs-panel-page]\");\n if (pageBtn) {\n // Recompute URL by inspecting the current open panel context — encoded in the body's first anchor \"Full view →\"\n // Simpler: rebuild via the previous URL stored in data-attr.\n var fullViewLink = document.querySelector(\n \"[data-frs-panel-body] a.btn-outline[href]\",\n );\n if (!fullViewLink) return;\n var dir = pageBtn.getAttribute(\"data-frs-panel-page\");\n var cursor = pageBtn.getAttribute(\"data-cursor\") || \"\";\n var fullViewUrl = new URL(fullViewLink.href, window.location.href);\n var repo = fullViewUrl.pathname.split(\"/\").filter(Boolean).pop();\n var bp = fullViewUrl.pathname.replace(/\\/[^/]+\\/?$/, \"\");\n var fk = \"\";\n var fv = \"\";\n fullViewUrl.searchParams.forEach(function (v, k) {\n if (k.indexOf(\"fv_\") === 0) {\n fk = k.slice(3);\n fv = v;\n }\n });\n var url =\n bp +\n \"/\" +\n encodeURIComponent(repo) +\n \"/_panel?type=many&fk=\" +\n encodeURIComponent(fk) +\n \"&fv=\" +\n encodeURIComponent(fv) +\n \"&cursor=\" +\n encodeURIComponent(cursor) +\n \"&dir=\" +\n encodeURIComponent(dir);\n fetchPanel(url, repo);\n }\n });\n document.addEventListener(\"keydown\", function (e) {\n if (e.key === \"Escape\") closePanel();\n });\n})();\n\n// ── Bulk selection + actions ────────────────────────────────────────────────\n(function () {\n var state = {\n selectAllAcrossQuery: false,\n // Keep a Set of selected ids on the current page (cleared on navigation).\n selected: new Set(),\n };\n\n function bar() {\n return document.querySelector(\"[data-frs-bulk-bar]\");\n }\n function summarize() {\n var b = bar();\n if (!b) return;\n var total = parseInt(b.getAttribute(\"data-frs-total\") || \"0\", 10);\n var summary = b.querySelector(\"[data-frs-bulk-summary]\");\n var selectAllBtn = b.querySelector(\"[data-frs-bulk-select-all]\");\n var allActive = b.querySelector(\"[data-frs-bulk-all-active]\");\n var pageSize = parseInt(b.getAttribute(\"data-frs-page-size\") || \"0\", 10);\n var n = state.selected.size;\n if (state.selectAllAcrossQuery) {\n if (allActive) allActive.classList.remove(\"hidden\");\n if (selectAllBtn) selectAllBtn.classList.add(\"hidden\");\n if (summary) summary.textContent = \"\";\n b.classList.remove(\"hidden\");\n return;\n }\n if (n === 0) {\n b.classList.add(\"hidden\");\n if (selectAllBtn) selectAllBtn.classList.add(\"hidden\");\n if (allActive) allActive.classList.add(\"hidden\");\n return;\n }\n b.classList.remove(\"hidden\");\n if (allActive) allActive.classList.add(\"hidden\");\n if (summary) {\n summary.textContent =\n n + \" selected\" + (pageSize ? \" on this page\" : \"\");\n }\n if (selectAllBtn && total > n) {\n selectAllBtn.classList.remove(\"hidden\");\n } else if (selectAllBtn) {\n selectAllBtn.classList.add(\"hidden\");\n }\n }\n function syncHeader() {\n var head = document.querySelector(\"[data-frs-select-page]\");\n if (!head) return;\n var rows = document.querySelectorAll(\"[data-frs-select-row]\");\n var checked = 0;\n rows.forEach(function (r) {\n if (r.checked) checked++;\n });\n head.indeterminate = checked > 0 && checked < rows.length;\n head.checked = rows.length > 0 && checked === rows.length;\n }\n document.addEventListener(\"change\", function (e) {\n if (e.target.matches(\"[data-frs-select-row]\")) {\n var id = e.target.value;\n if (e.target.checked) state.selected.add(id);\n else state.selected.delete(id);\n state.selectAllAcrossQuery = false;\n syncHeader();\n summarize();\n } else if (e.target.matches(\"[data-frs-select-page]\")) {\n var rows = document.querySelectorAll(\"[data-frs-select-row]\");\n rows.forEach(function (r) {\n r.checked = e.target.checked;\n if (e.target.checked) state.selected.add(r.value);\n else state.selected.delete(r.value);\n });\n state.selectAllAcrossQuery = false;\n summarize();\n }\n });\n document.addEventListener(\"click\", function (e) {\n var sa = e.target.closest(\"[data-frs-bulk-select-all]\");\n if (sa) {\n state.selectAllAcrossQuery = true;\n summarize();\n return;\n }\n var clear = e.target.closest(\"[data-frs-bulk-clear]\");\n if (clear) {\n state.selectAllAcrossQuery = false;\n state.selected.clear();\n document\n .querySelectorAll(\"[data-frs-select-row]\")\n .forEach(function (r) {\n r.checked = false;\n });\n syncHeader();\n summarize();\n return;\n }\n var actBtn = e.target.closest(\"[data-frs-bulk-action]\");\n if (actBtn) {\n var action = actBtn.getAttribute(\"data-frs-bulk-action\");\n if (action === \"delete\") doBulkDelete();\n else if (action === \"update\") openBulkUpdateModal();\n }\n });\n\n function buildPayload() {\n var b = bar();\n if (!b) return null;\n if (state.selectAllAcrossQuery) {\n var filters = [];\n try {\n filters = JSON.parse(b.getAttribute(\"data-frs-filters\") || \"[]\");\n } catch (_) {}\n return { selectAll: true, filters: filters };\n }\n return { ids: Array.from(state.selected) };\n }\n\n function repoEndpoint(action) {\n var b = bar();\n if (!b) return null;\n var repo = b.getAttribute(\"data-frs-repo\");\n var bp = window.location.pathname.replace(/\\/[^/]*\\/?$/, \"\");\n return bp + \"/\" + encodeURIComponent(repo) + \"/_bulk/\" + action;\n }\n\n function doBulkDelete() {\n var payload = buildPayload();\n if (!payload) return;\n var n = state.selectAllAcrossQuery\n ? \"all matching\"\n : payload.ids.length + \"\";\n if (!confirm(\"Delete \" + n + \" documents? This cannot be undone.\")) return;\n var url = repoEndpoint(\"delete\");\n if (!url) return;\n fetch(url, {\n method: \"POST\",\n credentials: \"same-origin\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(payload),\n })\n .then(function (r) {\n return r.json().then(function (j) {\n return { ok: r.ok, body: j };\n });\n })\n .then(function (res) {\n if (!res.ok) {\n alert(\"Bulk delete failed: \" + (res.body && res.body.error));\n return;\n }\n window.location.reload();\n })\n .catch(function (err) {\n alert(\"Bulk delete failed: \" + err.message);\n });\n }\n\n function openBulkUpdateModal() {\n var b = bar();\n var dialog = document.getElementById(\"frs-bulk-update-modal\");\n if (!b || !dialog) return;\n var fields = [];\n try {\n fields = JSON.parse(b.getAttribute(\"data-frs-fields\") || \"[]\");\n } catch (_) {}\n if (fields.length === 0) return;\n var summary = dialog.querySelector(\n \"[data-frs-bulk-update-summary]\",\n );\n if (summary) {\n summary.textContent = state.selectAllAcrossQuery\n ? \"Update one field on all matching documents.\"\n : \"Update one field on \" +\n state.selected.size +\n \" selected document\" +\n (state.selected.size !== 1 ? \"s\" : \"\") +\n \".\";\n }\n var select = dialog.querySelector(\"[data-frs-bulk-field-select]\");\n var valueContainer = dialog.querySelector(\n \"[data-frs-bulk-value-container]\",\n );\n var renderValueInput = function () {\n if (!valueContainer || !select) return;\n var name = select.value;\n var meta = fields.filter(function (f) {\n return f.name === name;\n })[0];\n if (!meta) {\n valueContainer.innerHTML = \"\";\n return;\n }\n var inputHtml = \"\";\n var label =\n '<div class=\"label\"><span class=\"label-text text-xs uppercase tracking-wide\">Value</span></div>';\n if (meta.type === \"boolean\") {\n inputHtml =\n '<select name=\"value\" class=\"select select-bordered select-sm w-full\">' +\n '<option value=\"true\">true</option><option value=\"false\">false</option>' +\n \"</select>\";\n } else if (\n (meta.type === \"enum\" || meta.type === \"literal\") &&\n meta.enumValues &&\n meta.enumValues.length\n ) {\n inputHtml =\n '<select name=\"value\" class=\"select select-bordered select-sm w-full\">';\n meta.enumValues.forEach(function (v) {\n inputHtml +=\n '<option value=\"' + escapeAttr(v) + '\">' + escapeHtml(v) + \"</option>\";\n });\n inputHtml += \"</select>\";\n } else if (meta.type === \"number\" || meta.type === \"bigint\") {\n inputHtml =\n '<input type=\"number\" step=\"any\" name=\"value\" class=\"input input-bordered input-sm w-full\" />';\n } else {\n inputHtml =\n '<input type=\"text\" name=\"value\" class=\"input input-bordered input-sm w-full\" />';\n }\n valueContainer.innerHTML =\n '<label class=\"form-control w-full\">' + label + inputHtml + \"</label>\";\n };\n if (select) {\n select.value = \"\";\n select.onchange = renderValueInput;\n }\n if (valueContainer) valueContainer.innerHTML = \"\";\n var form = dialog.querySelector(\"[data-frs-bulk-update-form]\");\n if (form) {\n form.onsubmit = function (e) {\n e.preventDefault();\n if (!select || !select.value) return;\n var meta = fields.filter(function (f) {\n return f.name === select.value;\n })[0];\n if (!meta) return;\n var input = valueContainer.querySelector(\n 'input[name=\"value\"], select[name=\"value\"]',\n );\n if (!input) return;\n var raw = input.value;\n var typed;\n if (meta.type === \"boolean\") typed = raw === \"true\";\n else if (meta.type === \"number\") typed = raw === \"\" ? null : Number(raw);\n else if (meta.type === \"bigint\") typed = raw === \"\" ? null : Number(raw);\n else typed = raw;\n var payload = buildPayload();\n if (!payload) return;\n payload.field = select.value;\n payload.value = typed;\n var url = repoEndpoint(\"update\");\n if (!url) return;\n fetch(url, {\n method: \"POST\",\n credentials: \"same-origin\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(payload),\n })\n .then(function (r) {\n return r.json().then(function (j) {\n return { ok: r.ok, body: j };\n });\n })\n .then(function (res) {\n if (!res.ok) {\n alert(\"Bulk update failed: \" + (res.body && res.body.error));\n return;\n }\n dialog.close();\n window.location.reload();\n })\n .catch(function (err) {\n alert(\"Bulk update failed: \" + err.message);\n });\n };\n }\n var cancel = dialog.querySelector(\"[data-frs-bulk-update-cancel]\");\n if (cancel)\n cancel.onclick = function () {\n dialog.close();\n };\n if (typeof dialog.showModal === \"function\") dialog.showModal();\n else dialog.setAttribute(\"open\", \"\");\n }\n\n function escapeHtml(s) {\n return String(s).replace(/[&<>\"']/g, function (c) {\n return (\n { \"&\": \"&\", \"<\": \"<\", \">\": \">\", '\"': \""\", \"'\": \"'\" }[\n c\n ] || c\n );\n });\n }\n function escapeAttr(s) {\n return escapeHtml(s);\n }\n})();\n\n// ── Theme switcher ──────────────────────────────────────────────────────────\n(function () {\n function syncThemeUI() {\n var current =\n document.documentElement.getAttribute(\"data-theme\") || \"corporate\";\n var label = document.querySelector(\"[data-frs-theme-current]\");\n if (label) label.textContent = current;\n document.querySelectorAll(\"[data-frs-theme-check]\").forEach(function (el) {\n el.classList.toggle(\n \"hidden\",\n el.getAttribute(\"data-frs-theme-check\") !== current,\n );\n });\n }\n document.addEventListener(\"DOMContentLoaded\", syncThemeUI);\n document.addEventListener(\"click\", function (e) {\n var btn = e.target.closest(\"[data-frs-theme]\");\n if (!btn) return;\n var theme = btn.getAttribute(\"data-frs-theme\");\n if (!theme) return;\n document.documentElement.setAttribute(\"data-theme\", theme);\n try {\n localStorage.setItem(\"frs-admin-theme\", theme);\n } catch (_) {}\n syncThemeUI();\n // Close the dropdown by blurring focus (DaisyUI dropdown closes on focusout)\n if (document.activeElement && document.activeElement.blur) {\n document.activeElement.blur();\n }\n });\n})();\n\n// ── Form validation + array serialization ───────────────────────────────────\ndocument.addEventListener(\"submit\", function (e) {\n var form = e.target;\n if (!form.hasAttribute(\"data-frs-form\")) return;\n\n // 1. Validate JSON textareas\n var valid = true;\n form.querySelectorAll(\"textarea[data-json]\").forEach(function (ta) {\n var v = ta.value.trim();\n if (!v) return;\n try {\n JSON.parse(v);\n } catch (err) {\n valid = false;\n e.preventDefault();\n alert('Invalid JSON in field \"' + ta.name + '\":\\n' + err.message);\n }\n });\n if (!valid) return;\n\n // 2. Serialize array fields into hidden inputs\n form.querySelectorAll(\"[data-frs-array]\").forEach(function (fieldset) {\n var hidden = fieldset.querySelector(\"input[type=hidden][name]\");\n if (!hidden || hidden.disabled) return;\n\n var type = fieldset.getAttribute(\"data-frs-array-type\");\n var items = fieldset.querySelectorAll(\"[data-frs-array-item]\");\n var arr = [];\n\n if (type === \"object\") {\n items.forEach(function (item) {\n var obj = {};\n item.querySelectorAll(\"[data-frs-key]\").forEach(function (inp) {\n var key = inp.getAttribute(\"data-frs-key\");\n if (inp.type === \"checkbox\") {\n obj[key] = inp.checked;\n } else if (inp.type === \"number\") {\n obj[key] = inp.value === \"\" ? null : Number(inp.value);\n } else if (inp.tagName === \"TEXTAREA\") {\n var v = inp.value.trim();\n if (v) {\n try {\n obj[key] = JSON.parse(v);\n } catch (_) {\n obj[key] = v;\n }\n } else {\n obj[key] = null;\n }\n } else {\n obj[key] = inp.value;\n }\n });\n arr.push(obj);\n });\n } else {\n items.forEach(function (item) {\n var inp = item.querySelector(\"[data-frs-val]\");\n if (!inp) return;\n if (type === \"checkbox\") {\n arr.push(inp.checked);\n } else if (type === \"number\") {\n if (inp.value !== \"\") arr.push(Number(inp.value));\n } else {\n if (inp.value !== \"\") arr.push(inp.value);\n }\n });\n }\n\n hidden.value = JSON.stringify(arr);\n });\n});\n\n// ── Array add / remove buttons ──────────────────────────────────────────────\ndocument.addEventListener(\"click\", function (e) {\n // Add item\n var addBtn = e.target.closest(\"[data-frs-array-add]\");\n if (addBtn) {\n var fieldset = addBtn.closest(\"[data-frs-array]\");\n if (!fieldset) return;\n var tpl = fieldset.querySelector(\"template[data-frs-array-tpl]\");\n var container = fieldset.querySelector(\"[data-frs-array-items]\");\n if (!tpl || !container) return;\n var clone = tpl.content.cloneNode(true);\n container.appendChild(clone);\n var last = container.lastElementChild;\n if (last) {\n var firstInp = last.querySelector(\"input,select,textarea\");\n if (firstInp) firstInp.focus();\n }\n return;\n }\n\n // Remove item\n var rmBtn = e.target.closest(\"[data-frs-array-rm]\");\n if (rmBtn) {\n var item = rmBtn.closest(\"[data-frs-array-item]\");\n if (item) item.remove();\n }\n});\n\n// ── Table enhancements ──────────────────────────────────────────────────────\ndocument.addEventListener(\"DOMContentLoaded\", function () {\n document.querySelectorAll(\"table[data-frs-table]\").forEach(initTable);\n});\n\nfunction initTable(table) {\n tagOriginalIndices(table);\n applySavedColumnOrder(table);\n initColumnResize(table);\n initColumnVisibility(table);\n initColumnReorder(table);\n}\n\n// ── Tag original column indices ─────────────────────────────────────────────\nfunction tagOriginalIndices(table) {\n var ths = Array.from(table.querySelectorAll(\"thead th\"));\n var dataCount = countDataColumns(table, ths);\n for (var i = 0; i < dataCount; i++) {\n ths[i].setAttribute(\"data-orig-col\", String(i));\n }\n table.querySelectorAll(\"tbody tr\").forEach(function (row) {\n var tds = Array.from(row.querySelectorAll(\"td\"));\n for (var j = 0; j < dataCount && j < tds.length; j++) {\n tds[j].setAttribute(\"data-orig-col\", String(j));\n }\n });\n}\n\nfunction countDataColumns(table, ths) {\n var explicit = table.getAttribute(\"data-frs-colcount\");\n if (explicit) return parseInt(explicit, 10);\n var count = 0;\n for (var i = 0; i < ths.length; i++) {\n if (ths[i].querySelector(\"a[href]\")) count++;\n else break;\n }\n return count || Math.max(0, ths.length - 1);\n}\n\n// ── Apply saved column order ────────────────────────────────────────────────\nfunction applySavedColumnOrder(table) {\n var repo = table.getAttribute(\"data-frs-repo\") || \"default\";\n var saved;\n try {\n saved = JSON.parse(localStorage.getItem(\"frs_colorder_\" + repo));\n } catch (_) {\n return;\n }\n if (!saved || !Array.isArray(saved) || saved.length === 0) return;\n reorderColumns(table, saved);\n}\n\n// ── Reorder columns by orig-index array ─────────────────────────────────────\nfunction reorderColumns(table, order) {\n var headRow = table.querySelector(\"thead tr\");\n if (!headRow) return;\n reorderRow(headRow, order);\n table.querySelectorAll(\"tbody tr\").forEach(function (row) {\n reorderRow(row, order);\n });\n}\n\nfunction reorderRow(row, order) {\n var cells = Array.from(row.children);\n var dataCells = cells.filter(function (c) {\n return c.hasAttribute(\"data-orig-col\");\n });\n var tailCells = cells.filter(function (c) {\n return !c.hasAttribute(\"data-orig-col\");\n });\n var cellMap = {};\n dataCells.forEach(function (c) {\n cellMap[c.getAttribute(\"data-orig-col\")] = c;\n });\n while (row.firstChild) row.removeChild(row.firstChild);\n order.forEach(function (origIdx) {\n if (cellMap[origIdx]) row.appendChild(cellMap[origIdx]);\n });\n dataCells.forEach(function (c) {\n if (!row.contains(c)) row.appendChild(c);\n });\n tailCells.forEach(function (c) {\n row.appendChild(c);\n });\n}\n\n// ── Column resize ───────────────────────────────────────────────────────────\nfunction initColumnResize(table) {\n var ths = Array.from(table.querySelectorAll(\"thead th\"));\n ths.forEach(function (th, i) {\n if (i === ths.length - 1) return;\n th.style.position = \"relative\";\n var handle = document.createElement(\"div\");\n handle.style.cssText =\n \"position:absolute;right:0;top:0;bottom:0;width:5px;cursor:col-resize;z-index:10;\";\n handle.addEventListener(\"mousedown\", function (e) {\n e.preventDefault();\n e.stopPropagation();\n var startX = e.clientX,\n startW = th.offsetWidth;\n var line = document.createElement(\"div\");\n line.style.cssText =\n \"position:fixed;top:0;bottom:0;width:2px;background:oklch(0.585 0.233 277.117);opacity:0.5;pointer-events:none;z-index:9999;\";\n line.style.left = e.clientX + \"px\";\n document.body.appendChild(line);\n function onMove(ev) {\n var newW = Math.max(40, startW + ev.clientX - startX);\n th.style.width = newW + \"px\";\n th.style.minWidth = newW + \"px\";\n line.style.left = ev.clientX + \"px\";\n }\n function onUp() {\n document.body.removeChild(line);\n document.removeEventListener(\"mousemove\", onMove);\n document.removeEventListener(\"mouseup\", onUp);\n }\n document.addEventListener(\"mousemove\", onMove);\n document.addEventListener(\"mouseup\", onUp);\n });\n th.appendChild(handle);\n });\n}\n\n// ── Column visibility (Columns dropdown with checkboxes) ────────────────────\nfunction initColumnVisibility(table) {\n var dataThs = Array.from(table.querySelectorAll(\"thead th[data-orig-col]\"));\n if (dataThs.length === 0) return;\n\n var wrap = table.closest(\"[data-frs-table-wrap]\");\n var toolbar = wrap && wrap.previousElementSibling;\n if (!toolbar) return;\n\n var repo = table.getAttribute(\"data-frs-repo\") || \"default\";\n var storageKey = \"frs_cols_\" + repo;\n var savedState = {};\n try {\n savedState = JSON.parse(localStorage.getItem(storageKey) || \"{}\");\n } catch (_) {}\n\n function saveState(origIdx, visible) {\n savedState[origIdx] = visible;\n try {\n localStorage.setItem(storageKey, JSON.stringify(savedState));\n } catch (_) {}\n }\n\n function setColVisible(origIdx, visible) {\n var th = table.querySelector('thead th[data-orig-col=\"' + origIdx + '\"]');\n if (th) th.style.display = visible ? \"\" : \"none\";\n table\n .querySelectorAll('tbody td[data-orig-col=\"' + origIdx + '\"]')\n .forEach(function (td) {\n td.style.display = visible ? \"\" : \"none\";\n });\n }\n\n var cols = dataThs.map(function (th) {\n var origIdx = parseInt(th.getAttribute(\"data-orig-col\"), 10);\n return {\n origIndex: origIdx,\n label: th.textContent.replace(/\\s+/g, \" \").trim(),\n };\n });\n\n // Build dropdown\n var dropdown = document.createElement(\"div\");\n dropdown.className = \"dropdown dropdown-end\";\n\n var btn = document.createElement(\"button\");\n btn.type = \"button\";\n btn.tabIndex = 0;\n btn.className = \"btn btn-sm btn-outline gap-1\";\n btn.innerHTML =\n '<svg xmlns=\"http://www.w3.org/2000/svg\" class=\"size-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\">' +\n '<path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 4v16M15 4v16M4 9h16M4 15h16\"/>' +\n \"</svg> Columns\";\n dropdown.appendChild(btn);\n\n var menu = document.createElement(\"ul\");\n menu.tabIndex = 0;\n menu.className =\n \"dropdown-content menu bg-base-100 rounded-box z-50 p-2 shadow-lg border border-base-300 w-56 max-h-80 overflow-y-auto flex-nowrap\";\n\n cols.forEach(function (col) {\n var li = document.createElement(\"li\");\n var label = document.createElement(\"label\");\n label.className =\n \"flex items-center gap-2 cursor-pointer px-2 py-1.5 rounded hover:bg-base-200\";\n\n var cb = document.createElement(\"input\");\n cb.type = \"checkbox\";\n cb.className = \"checkbox checkbox-xs checkbox-primary\";\n var isVisible = savedState[col.origIndex] !== false;\n cb.checked = isVisible;\n\n var span = document.createElement(\"span\");\n span.className = \"text-sm select-none\";\n span.textContent = col.label || \"Column \" + (col.origIndex + 1);\n\n label.appendChild(cb);\n label.appendChild(span);\n li.appendChild(label);\n\n if (!isVisible) setColVisible(col.origIndex, false);\n\n cb.addEventListener(\"change\", function (e) {\n var visible = e.target.checked;\n setColVisible(col.origIndex, visible);\n saveState(col.origIndex, visible);\n });\n\n menu.appendChild(li);\n });\n\n dropdown.appendChild(menu);\n toolbar.appendChild(dropdown);\n}\n\n// ── Column reorder (drag grip handles on headers) ───────────────────────────\nfunction initColumnReorder(table) {\n var repo = table.getAttribute(\"data-frs-repo\") || \"default\";\n var orderKey = \"frs_colorder_\" + repo;\n var dragSrcTh = null;\n var allDataThs = Array.from(\n table.querySelectorAll(\"thead th[data-orig-col]\"),\n );\n if (allDataThs.length < 2) return;\n\n allDataThs.forEach(function (th) {\n // Prepend a drag grip\n var grip = document.createElement(\"span\");\n grip.draggable = true;\n grip.textContent = \"\\u2807\";\n grip.style.cssText =\n \"cursor:grab;opacity:0.18;margin-right:4px;font-size:14px;vertical-align:middle;user-select:none;display:inline-block;\";\n grip.addEventListener(\"mouseenter\", function () {\n grip.style.opacity = \"0.5\";\n });\n grip.addEventListener(\"mouseleave\", function () {\n grip.style.opacity = \"0.18\";\n });\n th.insertBefore(grip, th.firstChild);\n\n // Drag starts from the grip only\n grip.addEventListener(\"dragstart\", function (e) {\n dragSrcTh = th;\n th.style.opacity = \"0.35\";\n e.dataTransfer.effectAllowed = \"move\";\n e.dataTransfer.setData(\"text/plain\", \"col\");\n try {\n e.dataTransfer.setDragImage(th, 20, 16);\n } catch (_) {}\n });\n\n grip.addEventListener(\"dragend\", function () {\n if (dragSrcTh) dragSrcTh.style.opacity = \"\";\n dragSrcTh = null;\n allDataThs.forEach(function (t) {\n t.style.boxShadow = \"\";\n });\n });\n\n // Drop target is the full <th>\n th.addEventListener(\"dragover\", function (e) {\n if (!dragSrcTh || dragSrcTh === th) return;\n e.preventDefault();\n e.dataTransfer.dropEffect = \"move\";\n allDataThs.forEach(function (t) {\n t.style.boxShadow = \"\";\n });\n var rect = th.getBoundingClientRect();\n var midX = rect.left + rect.width / 2;\n if (e.clientX < midX) {\n th.style.boxShadow = \"inset 3px 0 0 oklch(0.585 0.233 277.117)\";\n } else {\n th.style.boxShadow = \"inset -3px 0 0 oklch(0.585 0.233 277.117)\";\n }\n });\n\n th.addEventListener(\"dragleave\", function () {\n th.style.boxShadow = \"\";\n });\n\n th.addEventListener(\"drop\", function (e) {\n e.preventDefault();\n if (!dragSrcTh || dragSrcTh === th) return;\n allDataThs.forEach(function (t) {\n t.style.boxShadow = \"\";\n });\n\n var headRow = th.parentNode;\n var rect = th.getBoundingClientRect();\n var midX = rect.left + rect.width / 2;\n if (e.clientX < midX) {\n headRow.insertBefore(dragSrcTh, th);\n } else {\n headRow.insertBefore(dragSrcTh, th.nextElementSibling);\n }\n\n // Read new order from the reordered thead\n var newOrder = Array.from(\n table.querySelectorAll(\"thead th[data-orig-col]\"),\n ).map(function (t) {\n return parseInt(t.getAttribute(\"data-orig-col\"), 10);\n });\n\n // Apply the same order to all tbody rows\n table.querySelectorAll(\"tbody tr\").forEach(function (row) {\n reorderRow(row, newOrder);\n });\n\n // Persist\n try {\n localStorage.setItem(orderKey, JSON.stringify(newOrder));\n } catch (_) {}\n });\n });\n}\n","import JS from \"./client-script.raw.js\";\n\nexport function ClientScript() {\n // dangerouslySetInnerHTML is required here: JSX would escape < > & inside\n // a <script> text child, breaking the JavaScript at runtime.\n return <script dangerouslySetInnerHTML={{ __html: JS }} />;\n}\n","import type { Child, FC, PropsWithChildren } from \"hono/jsx\";\nimport { renderToString } from \"hono/jsx/dom/server\";\nimport { ClientScript } from \"./client-script\";\nimport { RightPanel } from \"./right-panel\";\nimport type { PageOptions } from \"./types\";\n\n/** Render a JSX element to a complete HTML string (includes <!DOCTYPE html>) */\nexport function renderHtml(element: Child): string {\n return \"<!DOCTYPE html>\" + renderToString(element);\n}\n\n/** Available themes (DaisyUI 5). Order matters — first is the default. */\nconst THEMES = [\"corporate\", \"silk\", \"dark\"] as const;\n\nconst ThemeSwitcher: FC = () => (\n <div class=\"dropdown dropdown-end\" data-frs-theme-switcher>\n <button\n type=\"button\"\n tabIndex={0}\n class=\"btn btn-sm btn-ghost text-neutral-content gap-1.5\"\n aria-label=\"Switch theme\"\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n class=\"size-4\"\n >\n <circle cx=\"12\" cy=\"12\" r=\"4\" />\n <path d=\"M12 2v2M12 20v2M4.93 4.93l1.41 1.41M17.66 17.66l1.41 1.41M2 12h2M20 12h2M4.93 19.07l1.41-1.41M17.66 6.34l1.41-1.41\" />\n </svg>\n <span class=\"text-xs hidden sm:inline\" data-frs-theme-current>\n Theme\n </span>\n </button>\n <ul\n tabIndex={0}\n class=\"dropdown-content menu menu-sm bg-base-100 text-base-content rounded-box z-50 mt-2 w-40 p-1 shadow-lg border border-base-300\"\n >\n {THEMES.map((t) => (\n <li key={t}>\n <button\n type=\"button\"\n data-frs-theme={t}\n class=\"capitalize justify-between\"\n >\n <span>{t}</span>\n <span class=\"hidden text-primary\" data-frs-theme-check={t}>\n ✓\n </span>\n </button>\n </li>\n ))}\n </ul>\n </div>\n);\n\nexport const PageShell: FC<PropsWithChildren<{ opts: PageOptions }>> = ({\n opts,\n children,\n}) => {\n const { title, breadcrumb, flash, basePath = \"/\" } = opts;\n\n return (\n <html lang=\"en\" data-theme=\"corporate\">\n <head>\n <meta charset=\"UTF-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n <title>{title} — FRS Admin</title>\n {/* Early theme hydration — runs before paint to avoid flash of unstyled theme */}\n <script\n dangerouslySetInnerHTML={{\n __html:\n \"(function(){try{var t=localStorage.getItem('frs-admin-theme');if(t){document.documentElement.setAttribute('data-theme',t);}}catch(_){}})();\",\n }}\n />\n <link\n href=\"https://cdn.jsdelivr.net/npm/daisyui@5/themes.css\"\n rel=\"stylesheet\"\n type=\"text/css\"\n />\n <link\n href=\"https://cdn.jsdelivr.net/npm/daisyui@5/daisyui.css\"\n rel=\"stylesheet\"\n type=\"text/css\"\n />\n <script src=\"https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4\" />\n </head>\n <body class=\"bg-base-200/50 min-h-screen flex flex-col\">\n {/* Navbar */}\n <div class=\"navbar bg-neutral text-neutral-content shadow-sm sticky top-0 z-50 px-6\">\n <div class=\"flex-1\">\n <a\n href={basePath}\n class=\"font-bold text-lg tracking-tight hover:opacity-80 transition-opacity\"\n >\n FRS Admin\n </a>\n </div>\n <div class=\"flex-none\">\n <ThemeSwitcher />\n </div>\n </div>\n\n <main class=\"px-6 py-8 w-full flex-1\">\n {/* Breadcrumbs */}\n {breadcrumb && breadcrumb.length > 0 && (\n <div class=\"text-sm breadcrumbs mb-4\">\n <ul>\n {breadcrumb.map((c, i) =>\n c.href ? (\n <li key={i}>\n <a href={c.href}>{c.label}</a>\n </li>\n ) : (\n <li key={i} class=\"text-base-content/60\">\n {c.label}\n </li>\n ),\n )}\n </ul>\n </div>\n )}\n\n <h1 class=\"text-2xl font-bold mb-6\">{title}</h1>\n\n {/* Flash message */}\n {flash && (\n <div\n role=\"alert\"\n class={`alert ${\n flash.type === \"success\"\n ? \"alert-success\"\n : flash.type === \"warning\"\n ? \"alert-warning\"\n : \"alert-error\"\n } mb-6`}\n >\n <span class=\"flex-1\">{flash.message}</span>\n {flash.action && (\n <a\n href={flash.action.href}\n {...(flash.action.external\n ? { target: \"_blank\", rel: \"noopener noreferrer\" }\n : {})}\n class=\"btn btn-sm btn-outline\"\n >\n {flash.action.label}\n </a>\n )}\n </div>\n )}\n\n {children}\n </main>\n\n <RightPanel />\n <ClientScript />\n </body>\n </html>\n );\n};\n\n/** Wrap a raw HTML string in the page shell (backward compat). */\nexport function renderPageJsx(content: string, opts: PageOptions): string {\n return renderHtml(\n <PageShell opts={opts}>\n <div dangerouslySetInnerHTML={{ __html: content }} />\n </PageShell>,\n );\n}\n","import { PageShell, renderHtml } from \"./shell\";\n\nexport function renderDashboardJsx(\n repos: { name: string; path: string }[],\n basePath: string,\n): string {\n return renderHtml(\n <PageShell opts={{ title: \"Repositories\", basePath }}>\n {repos.length === 0 ? (\n <div class=\"text-center py-20 text-base-content/50\">\n <p class=\"text-lg font-medium mb-1\">No repositories configured</p>\n <p class=\"text-sm\">\n Add a repository to your FRS config to get started.\n </p>\n </div>\n ) : (\n <div class=\"grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-4\">\n {repos.map((r) => (\n <a\n key={r.name}\n href={`${basePath}/${r.name}`}\n class=\"card bg-base-100 border border-base-300 hover:shadow-md no-underline transition-shadow\"\n >\n <div class=\"card-body p-5\">\n <h2 class=\"card-title text-sm font-semibold\">{r.name}</h2>\n <p class=\"text-xs text-base-content/50 font-mono\">{r.path}</p>\n </div>\n </a>\n ))}\n </div>\n )}\n </PageShell>,\n );\n}\n","import type { ColumnMeta, FilterState, WhereOp } from \"./types\";\n\n// ---------------------------------------------------------------------------\n// Operator definitions per Zod type\n// ---------------------------------------------------------------------------\n\ntype OpDef = { value: WhereOp; label: string };\n\nconst OPS_TEXT: OpDef[] = [\n { value: \"==\", label: \"=\" },\n { value: \"!=\", label: \"≠\" },\n { value: \"in\", label: \"in\" },\n { value: \"not-in\", label: \"not in\" },\n];\nconst OPS_NUMERIC: OpDef[] = [\n { value: \"==\", label: \"=\" },\n { value: \"!=\", label: \"≠\" },\n { value: \"<\", label: \"<\" },\n { value: \"<=\", label: \"≤\" },\n { value: \">\", label: \">\" },\n { value: \">=\", label: \"≥\" },\n { value: \"in\", label: \"in\" },\n { value: \"not-in\", label: \"not in\" },\n];\nconst OPS_ARRAY: OpDef[] = [\n { value: \"array-contains\", label: \"contains\" },\n { value: \"array-contains-any\", label: \"contains any\" },\n];\n\nfunction opsForType(zodType: string): OpDef[] {\n switch (zodType) {\n case \"ZodNumber\":\n case \"ZodBigInt\":\n case \"ZodDate\":\n return OPS_NUMERIC;\n case \"ZodBoolean\":\n return OPS_TEXT;\n case \"ZodArray\":\n return OPS_ARRAY;\n default:\n return OPS_TEXT;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Value input per type\n// ---------------------------------------------------------------------------\n\nconst NULL_SENTINEL = \"__null__\";\n\n/**\n * Inline JS toggle that sets the sibling input's value to \"__null__\" / restores it.\n * Keeps the input enabled so it stays in the form payload (disabled inputs are NOT\n * submitted, which would silently drop the filter). Swaps number/date inputs to\n * text temporarily because they reject the sentinel value.\n */\nfunction nullToggleScript(inputId: string): string {\n return `(function(cb){var i=document.getElementById('${inputId}');if(!i)return;if(cb.checked){i.dataset._prev=i.value;if(i.tagName==='SELECT'){var o=i.querySelector('option[value=\"${NULL_SENTINEL}\"]');if(!o){o=document.createElement('option');o.value='${NULL_SENTINEL}';o.textContent='∅ null';o.dataset._auto='1';i.appendChild(o);}o.selected=true;}else{if(i.type==='number'||i.type==='datetime-local'){i.dataset._type=i.type;i.type='text';}i.value='${NULL_SENTINEL}';i.readOnly=true;}i.style.opacity='0.55';}else{i.style.opacity='';if(i.tagName==='SELECT'){var o2=i.querySelector('option[value=\"${NULL_SENTINEL}\"][data-_auto=\"1\"]');if(o2)o2.remove();var prev=i.dataset._prev||'';for(var k=0;k<i.options.length;k++)i.options[k].selected=(i.options[k].value===prev);}else{if(i.dataset._type){i.type=i.dataset._type;delete i.dataset._type;}i.readOnly=false;i.value=(i.dataset._prev&&i.dataset._prev!=='${NULL_SENTINEL}')?i.dataset._prev:'';}}})(this)`;\n}\n\n/** Inline JS that syncs a list of enum checkboxes into a CSV hidden input. */\nfunction enumChecklistScript(hiddenId: string, group: string): string {\n return `(function(){var h=document.getElementById('${hiddenId}');var boxes=document.querySelectorAll('input[data-enum-group=\"${group}\"]');h.value=Array.from(boxes).filter(function(b){return b.checked;}).map(function(b){return b.value;}).join(',');})()`;\n}\n\nfunction NullToggle({\n inputId,\n active,\n}: {\n inputId: string;\n active: boolean;\n}) {\n return (\n <label\n class=\"flex items-center gap-1 cursor-pointer select-none text-xs text-base-content/60 hover:text-base-content border border-base-300 rounded-md px-1.5 py-1 shrink-0 leading-none h-8\"\n title=\"Filter where field IS NULL\"\n >\n <input\n type=\"checkbox\"\n class=\"checkbox checkbox-xs\"\n checked={active}\n onchange={nullToggleScript(inputId)}\n />\n <span>∅</span>\n </label>\n );\n}\n\nfunction FilterValueInput({\n col,\n active,\n}: {\n col: ColumnMeta;\n active?: FilterState;\n}) {\n const val = active?.value ?? \"\";\n const isNull = val === NULL_SENTINEL;\n const inputId = `fv_input_${col.name.replace(/\\./g, \"__\")}`;\n const op = active?.op;\n const isMultiOp = op === \"in\" || op === \"not-in\";\n\n // ── Enum / Literal columns ────────────────────────────────────────────────\n if (col.enumValues && col.enumValues.length > 0) {\n if (isMultiOp) {\n // Multi-select via checkbox group + hidden CSV input\n const selected = new Set(\n val\n .split(\",\")\n .map((s) => s.trim())\n .filter(Boolean),\n );\n const group = `eg_${col.name.replace(/\\./g, \"__\")}`;\n return (\n <div class=\"flex flex-wrap items-center gap-1 w-full\">\n <input\n type=\"hidden\"\n id={inputId}\n name={`fv_${col.name}`}\n value={val}\n />\n {col.enumValues.map((v) => (\n <label\n key={v}\n class=\"flex items-center gap-1 text-xs border border-base-300 rounded px-2 cursor-pointer hover:bg-base-200\"\n >\n <input\n type=\"checkbox\"\n class=\"checkbox checkbox-xs\"\n value={v}\n checked={selected.has(v)}\n data-enum-group={group}\n onchange={enumChecklistScript(inputId, group)}\n />\n <span>{v}</span>\n </label>\n ))}\n </div>\n );\n }\n // Single-select for ==, !=, etc.\n return (\n <div class=\"flex items-center gap-1 w-full\">\n <select\n id={inputId}\n name={`fv_${col.name}`}\n class=\"select select-sm select-bordered w-full\"\n style={isNull ? \"opacity:0.55\" : undefined}\n >\n <option value=\"\" selected={val === \"\" && !isNull}>\n —\n </option>\n {col.enumValues.map((v) => (\n <option key={v} value={v} selected={val === v}>\n {v}\n </option>\n ))}\n {col.nullable && (\n <option value={NULL_SENTINEL} data-_auto=\"1\" selected={isNull}>\n ∅ null\n </option>\n )}\n </select>\n {col.nullable && <NullToggle inputId={inputId} active={isNull} />}\n </div>\n );\n }\n\n // ── Boolean ────────────────────────────────────────────────────────────────\n if (col.zodType === \"ZodBoolean\") {\n return (\n <div class=\"flex items-center gap-1 w-full\">\n <select\n id={inputId}\n name={`fv_${col.name}`}\n class=\"select select-sm select-bordered w-full\"\n style={isNull ? \"opacity:0.55\" : undefined}\n >\n <option value=\"\" selected={val === \"\" && !isNull}>\n —\n </option>\n <option value=\"true\" selected={val === \"true\"}>\n true\n </option>\n <option value=\"false\" selected={val === \"false\"}>\n false\n </option>\n {col.nullable && (\n <option value={NULL_SENTINEL} data-_auto=\"1\" selected={isNull}>\n ∅ null\n </option>\n )}\n </select>\n {col.nullable && <NullToggle inputId={inputId} active={isNull} />}\n </div>\n );\n }\n\n // ── Array (no nullable toggle: array-contains semantics differ) ───────────\n if (col.zodType === \"ZodArray\") {\n const isAny = active?.op === \"array-contains-any\";\n return (\n <input\n id={inputId}\n type=\"text\"\n name={`fv_${col.name}`}\n value={val}\n placeholder={isAny ? \"val1, val2, …\" : \"value\"}\n class=\"input input-sm input-bordered w-full\"\n />\n );\n }\n\n // ── Numeric ────────────────────────────────────────────────────────────────\n if (col.zodType === \"ZodNumber\" || col.zodType === \"ZodBigInt\") {\n return (\n <div class=\"flex items-center gap-1 w-full\">\n <input\n id={inputId}\n type={isNull ? \"text\" : \"number\"}\n name={`fv_${col.name}`}\n value={val}\n placeholder=\"value\"\n class=\"input input-sm input-bordered w-full\"\n readOnly={isNull}\n style={isNull ? \"opacity:0.55\" : undefined}\n data-_type={isNull ? \"number\" : undefined}\n />\n {col.nullable && <NullToggle inputId={inputId} active={isNull} />}\n </div>\n );\n }\n\n // ── Date ───────────────────────────────────────────────────────────────────\n if (col.zodType === \"ZodDate\") {\n return (\n <div class=\"flex items-center gap-1 w-full\">\n <input\n id={inputId}\n type={isNull ? \"text\" : \"datetime-local\"}\n name={`fv_${col.name}`}\n value={val}\n class=\"input input-sm input-bordered w-full\"\n readOnly={isNull}\n style={isNull ? \"opacity:0.55\" : undefined}\n data-_type={isNull ? \"datetime-local\" : undefined}\n />\n {col.nullable && <NullToggle inputId={inputId} active={isNull} />}\n </div>\n );\n }\n\n // ── Default text ───────────────────────────────────────────────────────────\n return (\n <div class=\"flex items-center gap-1 w-full\">\n <input\n id={inputId}\n type=\"text\"\n name={`fv_${col.name}`}\n value={val}\n placeholder=\"value\"\n class=\"input input-sm input-bordered w-full\"\n readOnly={isNull}\n style={isNull ? \"opacity:0.55\" : undefined}\n />\n {col.nullable && <NullToggle inputId={inputId} active={isNull} />}\n </div>\n );\n}\n\n// ---------------------------------------------------------------------------\n// FilterBar\n// ---------------------------------------------------------------------------\n\nexport function FilterBar({\n action,\n columnMeta,\n activeFilters,\n isGroup,\n}: {\n /** Form action URL (list page URL, without query params) */\n action: string;\n columnMeta: ColumnMeta[];\n activeFilters: FilterState[];\n /** Whether this repo is a collection group (subcollection) */\n isGroup?: boolean;\n}) {\n const activeMap = Object.fromEntries(activeFilters.map((f) => [f.field, f]));\n const hasActive = activeFilters.length > 0;\n const needsIndexHint = activeFilters.length >= 2 || (isGroup && hasActive);\n\n // Columns that can be filtered (exclude pure-object columns)\n const filterable = columnMeta.filter(\n (c) => c.zodType !== \"ZodObject\" && c.zodType !== \"ZodRecord\",\n );\n\n return (\n <details\n class=\"collapse collapse-arrow bg-base-100 border border-base-300 rounded-box mb-6 shadow-sm\"\n open={hasActive ? true : undefined}\n >\n <summary class=\"collapse-title text-sm font-medium py-2 min-h-0\">\n Filters\n {hasActive && (\n <span class=\"badge badge-primary badge-sm ml-2\">\n {activeFilters.length} active\n </span>\n )}\n </summary>\n <div class=\"collapse-content pb-4 pt-2\">\n <form method=\"get\" action={action}>\n <div class=\"grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-4\">\n {filterable.map((col) => {\n const ops = opsForType(col.zodType);\n const active = activeMap[col.name];\n const currentOp: WhereOp = active?.op ?? ops[0]!.value;\n return (\n <div key={col.name} class=\"flex flex-col gap-1.5\">\n <label class=\"text-xs font-semibold text-base-content/60 uppercase tracking-wide\">\n {col.name}\n </label>\n <div class=\"flex gap-1.5\">\n {ops.length > 1 ? (\n <select\n name={`fo_${col.name}`}\n class=\"select select-sm select-bordered w-20 shrink-0\"\n >\n {ops.map((o) => (\n <option\n key={o.value}\n value={o.value}\n selected={o.value === currentOp}\n >\n {o.label}\n </option>\n ))}\n </select>\n ) : (\n // Single op → hidden input, no select to clutter UI\n <input\n type=\"hidden\"\n name={`fo_${col.name}`}\n value={ops[0]!.value}\n />\n )}\n <FilterValueInput col={col} active={active} />\n </div>\n </div>\n );\n })}\n </div>\n\n <div class=\"flex flex-wrap gap-2 mt-4 pt-3 border-t border-base-200 items-center\">\n <button type=\"submit\" class=\"btn btn-sm btn-primary\">\n Apply\n </button>\n {hasActive && (\n <a href={action} class=\"btn btn-sm btn-ghost\">\n Clear\n </a>\n )}\n {needsIndexHint && (\n <span class=\"text-xs text-warning ml-auto flex items-center gap-1\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n class=\"h-4 w-4\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n stroke-width=\"2\"\n d=\"M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z\"\n />\n </svg>\n {isGroup\n ? \"Collection group queries require a composite index\"\n : \"Multiple filters may require a composite index\"}\n </span>\n )}\n </div>\n </form>\n </div>\n </details>\n );\n}\n","import { PageShell, renderHtml } from \"./shell\";\nimport type { PageOptions } from \"./types\";\n\nexport function renderFormPageJsx(\n repoName: string,\n formHtml: string,\n mode: \"create\" | \"edit\",\n docId: string | null,\n basePath: string,\n flash?: PageOptions[\"flash\"],\n): string {\n const title =\n mode === \"create\"\n ? `Create ${repoName}`\n : `Edit ${repoName} / ${docId ?? \"\"}`;\n\n const crumbs =\n mode === \"create\"\n ? [\n { label: \"Repositories\", href: basePath },\n { label: repoName, href: `${basePath}/${repoName}` },\n { label: \"New document\" },\n ]\n : [\n { label: \"Repositories\", href: basePath },\n { label: repoName, href: `${basePath}/${repoName}` },\n { label: `Edit ${docId ?? \"\"}` },\n ];\n\n return renderHtml(\n <PageShell opts={{ title, breadcrumb: crumbs, basePath, flash }}>\n <div class=\"card bg-base-100 border border-base-300\">\n <div class=\"card-body p-6\">\n <div dangerouslySetInnerHTML={{ __html: formHtml }} />\n </div>\n </div>\n </PageShell>,\n );\n}\n","import type { z } from \"zod\";\nimport { CellValue } from \"./cell-value\";\nimport { FilterBar } from \"./filter-bar\";\nimport { PageShell, renderHtml } from \"./shell\";\nimport type { ExpectedType } from \"./type-check\";\nimport { expectedTypeOf, mismatchMessage, resolveAtPath } from \"./type-check\";\nimport type {\n ColumnMeta,\n FilterState,\n PageOptions,\n QueryError,\n RelationalFieldMeta,\n SortState,\n} from \"./types\";\n\n/** Shared helper — gather filter params into URLSearchParams. */\nfunction baseParams(\n filters: FilterState[],\n sort?: SortState,\n pageSize?: number,\n): URLSearchParams {\n const p = new URLSearchParams();\n for (const f of filters) {\n p.set(`fv_${f.field}`, f.value);\n p.set(`fo_${f.field}`, f.op);\n }\n if (sort) {\n p.set(\"ob\", sort.field);\n p.set(\"od\", sort.dir);\n }\n if (pageSize) p.set(\"ps\", String(pageSize));\n return p;\n}\n\n/**\n * Build a query-string for pagination (preserves filters, sort, page-size).\n */\nfunction paginationHref(\n filters: FilterState[],\n cursor: string,\n dir: \"prev\" | \"next\",\n sort?: SortState,\n pageSize?: number,\n): string {\n const p = baseParams(filters, sort, pageSize);\n p.set(\"cursor\", cursor);\n p.set(\"dir\", dir);\n return `?${p.toString()}`;\n}\n\n/**\n * Build a query-string that toggles / cycles the sort on a column.\n * Clears the cursor so the user starts from page 1 of the new order.\n */\nfunction sortHref(\n col: string,\n current: SortState | undefined,\n filters: FilterState[],\n pageSize?: number,\n): string {\n const p = baseParams(filters, undefined, pageSize);\n if (current?.field === col) {\n if (current.dir === \"asc\") {\n p.set(\"ob\", col);\n p.set(\"od\", \"desc\");\n }\n // desc → no ob/od (back to default order)\n } else {\n p.set(\"ob\", col);\n p.set(\"od\", \"asc\");\n }\n return `?${p.toString()}`;\n}\n\n/** Build a query-string that changes page size (clears cursor). */\nfunction pageSizeHref(\n newPs: number,\n filters: FilterState[],\n sort?: SortState,\n): string {\n const p = baseParams(filters, sort, newPs);\n return `?${p.toString()}`;\n}\n\nexport function renderListJsx(\n repoName: string,\n docs: Record<string, unknown>[],\n columns: string[],\n basePath: string,\n pagination: {\n hasPrev: boolean;\n hasNext: boolean;\n prevCursor: string;\n nextCursor: string;\n },\n flash?: PageOptions[\"flash\"],\n columnMeta: ColumnMeta[] = [],\n activeFilters: FilterState[] = [],\n allowDelete = false,\n relationalMeta: RelationalFieldMeta[] = [],\n sortState?: SortState,\n currentPageSize?: number,\n queryError?: QueryError,\n isGroup?: boolean,\n totalCount?: number,\n mutableFields?: string[],\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n schema?: z.ZodObject<any>,\n): string {\n const listUrl = `${basePath}/${repoName}`;\n const createUrl = `${listUrl}/create`;\n\n // Build expected-type map for type-mismatch indicator\n const expectedTypes: Record<string, ExpectedType> = {};\n if (schema) {\n for (const c of columns) {\n expectedTypes[c] = expectedTypeOf(resolveAtPath(schema, c));\n }\n }\n\n // Bulk capability: scalar mutable fields (excluding object/array/date/unknown)\n const scalarMutable = (mutableFields ?? []).filter((f) => {\n const t = expectedTypes[f] ?? expectedTypeOf(resolveAtPath(schema, f));\n return (\n t === \"string\" ||\n t === \"number\" ||\n t === \"bigint\" ||\n t === \"boolean\" ||\n t === \"enum\" ||\n t === \"literal\"\n );\n });\n const canBulkUpdate = scalarMutable.length > 0;\n const canBulkDelete = allowDelete;\n const showSelection = canBulkDelete || canBulkUpdate;\n\n // Bulk-update field metadata: gives the client what it needs to render the right input type\n const bulkFieldsMeta = scalarMutable.map((f) => {\n const sub = resolveAtPath(schema, f);\n const t = expectedTypeOf(sub);\n const meta = columnMeta.find((m) => m.name === f);\n return {\n name: f,\n type: t,\n enumValues: meta?.enumValues ?? null,\n nullable: meta?.nullable ?? false,\n };\n });\n\n return renderHtml(\n <PageShell\n opts={{\n title: repoName,\n breadcrumb: [\n { label: \"Repositories\", href: basePath },\n { label: repoName },\n ],\n basePath,\n flash,\n }}\n >\n {/* Filter panel */}\n {columnMeta.length > 0 && (\n <FilterBar\n action={listUrl}\n columnMeta={columnMeta}\n activeFilters={activeFilters}\n isGroup={isGroup}\n />\n )}\n\n {/* Query error alert (missing index or generic) */}\n {queryError && (\n <div\n role=\"alert\"\n class={`alert ${queryError.type === \"index\" ? \"alert-warning\" : \"alert-error\"} mb-6 shadow-sm`}\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n class=\"h-6 w-6 shrink-0 stroke-current\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n >\n {queryError.type === \"index\" ? (\n <path\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n stroke-width=\"2\"\n d=\"M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z\"\n />\n ) : (\n <path\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n stroke-width=\"2\"\n d=\"M10 14l2-2m0 0l2-2m-2 2l-2-2m2 2l2 2m7-2a9 9 0 11-18 0 9 9 0 0118 0z\"\n />\n )}\n </svg>\n <div class=\"flex-1\">\n <h3 class=\"font-bold\">\n {queryError.type === \"index\"\n ? \"Composite index required\"\n : \"Query failed\"}\n </h3>\n <div class=\"text-sm\">{queryError.message}</div>\n </div>\n {queryError.indexUrl && (\n <a\n href={queryError.indexUrl}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n class=\"btn btn-sm btn-outline\"\n >\n Create Index →\n </a>\n )}\n </div>\n )}\n\n {/* Toolbar */}\n <div class=\"flex flex-wrap justify-between items-center mb-4 gap-3\">\n <div class=\"flex items-center gap-3\">\n <span class=\"text-sm text-base-content/60\">\n {docs.length}\n {typeof totalCount === \"number\" && (\n <>\n {\" \"}of <span class=\"font-semibold text-base-content/80\">{totalCount}</span>\n </>\n )}\n {\" \"}document{(typeof totalCount === \"number\" ? totalCount : docs.length) !== 1 && \"s\"}\n </span>\n {/* Rows-per-page */}\n <div class=\"flex items-center gap-1.5 text-sm text-base-content/60\">\n <span>Rows</span>\n <div class=\"join\">\n {[10, 25, 50, 100].map((ps) => (\n <a\n key={ps}\n href={pageSizeHref(ps, activeFilters, sortState)}\n class={`join-item btn btn-xs ${currentPageSize === ps ? \"btn-active btn-primary\" : \"btn-outline\"}`}\n >\n {ps}\n </a>\n ))}\n </div>\n </div>\n </div>\n <a href={createUrl} class=\"btn btn-primary btn-sm\">\n + New\n </a>\n </div>\n\n {/* Bulk action bar (hidden until at least one row is selected) */}\n {showSelection && (\n <div\n class=\"hidden mb-3 alert alert-info py-2 px-3\"\n data-frs-bulk-bar\n data-frs-repo={repoName}\n data-frs-total={typeof totalCount === \"number\" ? String(totalCount) : \"\"}\n data-frs-page-size={String(currentPageSize ?? docs.length)}\n data-frs-allow-delete={canBulkDelete ? \"1\" : \"0\"}\n data-frs-allow-update={canBulkUpdate ? \"1\" : \"0\"}\n data-frs-fields={JSON.stringify(bulkFieldsMeta)}\n data-frs-filters={JSON.stringify(activeFilters)}\n >\n <div class=\"flex-1 text-sm\">\n <span data-frs-bulk-summary>0 selected</span>\n {typeof totalCount === \"number\" && totalCount > docs.length && (\n <button\n type=\"button\"\n class=\"ml-3 link link-primary text-sm hidden\"\n data-frs-bulk-select-all\n >\n Select all {totalCount} matching documents\n </button>\n )}\n <span class=\"hidden ml-3 italic\" data-frs-bulk-all-active>\n All {totalCount ?? \"?\"} matching documents are selected.{\" \"}\n <button\n type=\"button\"\n class=\"link\"\n data-frs-bulk-clear\n >\n Clear selection\n </button>\n </span>\n </div>\n <div class=\"flex gap-2\">\n {canBulkUpdate && (\n <button\n type=\"button\"\n class=\"btn btn-sm btn-outline\"\n data-frs-bulk-action=\"update\"\n >\n Update field…\n </button>\n )}\n {canBulkDelete && (\n <button\n type=\"button\"\n class=\"btn btn-sm btn-error btn-outline\"\n data-frs-bulk-action=\"delete\"\n >\n Delete\n </button>\n )}\n </div>\n </div>\n )}\n\n {/* Table */}\n <div\n class=\"overflow-x-auto rounded-box border border-base-300 bg-base-100\"\n data-frs-table-wrap\n >\n <table\n class=\"table table-sm w-full\"\n data-frs-table\n data-frs-repo={repoName}\n data-frs-colcount={columns.length}\n >\n <thead>\n <tr class=\"bg-base-200/50\">\n {showSelection && (\n <th class=\"w-8\">\n <input\n type=\"checkbox\"\n class=\"checkbox checkbox-xs checkbox-primary\"\n data-frs-select-page\n aria-label=\"Select all on this page\"\n />\n </th>\n )}\n {[...columns].map((c, i) => {\n const isSorted = sortState?.field === c;\n const arrow = isSorted\n ? sortState!.dir === \"asc\"\n ? \" ▲\"\n : \" ▼\"\n : \"\";\n return (\n <th\n key={i}\n class=\"text-xs font-semibold text-base-content/60 uppercase tracking-wide\"\n >\n <a\n href={sortHref(\n c,\n sortState,\n activeFilters,\n currentPageSize,\n )}\n class={`hover:text-base-content inline-flex items-center gap-0.5${isSorted ? \" text-primary font-bold\" : \"\"}`}\n >\n {c}\n {arrow}\n </a>\n </th>\n );\n })}\n {relationalMeta.map((m, i) => (\n <th\n key={`rel-${i}`}\n class=\"text-xs font-semibold text-base-content/60 uppercase tracking-wide\"\n >\n {m.column}\n </th>\n ))}\n <th class=\"text-xs font-semibold text-base-content/60 uppercase tracking-wide text-right\">\n Actions\n </th>\n </tr>\n </thead>\n <tbody>\n {docs.length === 0 ? (\n <tr>\n <td\n colspan={\n columns.length +\n relationalMeta.length +\n 1 +\n (showSelection ? 1 : 0)\n }\n class=\"text-center py-16 text-base-content/40\"\n >\n No documents found\n </td>\n </tr>\n ) : (\n docs.map((doc, rowIdx) => {\n const id = String(doc[\"docId\"] ?? doc[\"id\"] ?? \"\");\n const editUrl = `${basePath}/${repoName}/${encodeURIComponent(id)}/edit`;\n const deleteUrl = `${basePath}/${repoName}/${encodeURIComponent(id)}/delete`;\n return (\n <tr key={rowIdx} class=\"hover\" data-frs-row-id={id}>\n {showSelection && (\n <td class=\"align-middle py-2\">\n <input\n type=\"checkbox\"\n class=\"checkbox checkbox-xs checkbox-primary\"\n data-frs-select-row\n value={id}\n aria-label={`Select ${id}`}\n />\n </td>\n )}\n {columns.map((c, ci) => {\n const val = doc[c];\n const expected = expectedTypes[c];\n const mismatch = expected\n ? mismatchMessage(expected, val)\n : null;\n return (\n <td key={ci} class=\"align-top py-2\">\n <CellValue val={val} mismatch={mismatch} />\n </td>\n );\n })}\n {relationalMeta.map((m, mi) => {\n const rawVal = doc[m.key];\n if (rawVal == null || rawVal === \"\") {\n return <td key={`rel-${mi}`} class=\"py-2\" />;\n }\n const fallbackHref =\n m.type === \"one\"\n ? `${basePath}/${m.targetRepo}/${encodeURIComponent(String(rawVal))}/edit`\n : `${basePath}/${m.targetRepo}?fv_${m.targetKey}=${encodeURIComponent(String(rawVal))}`;\n return (\n <td key={`rel-${mi}`} class=\"align-middle py-2\">\n <a\n href={fallbackHref}\n class=\"btn btn-xs btn-ghost btn-outline\"\n data-frs-relation\n data-frs-rel-type={m.type}\n data-frs-rel-repo={m.targetRepo}\n data-frs-rel-fk={m.targetKey}\n data-frs-rel-val={String(rawVal)}\n data-frs-rel-label={m.column}\n >\n {m.column}\n </a>\n </td>\n );\n })}\n <td class=\"align-middle text-right whitespace-nowrap py-2\">\n <div class=\"flex gap-1 justify-end\">\n <a\n href={editUrl}\n class=\"btn btn-xs btn-outline\"\n >\n Edit\n </a>\n {allowDelete && (\n <form\n method=\"post\"\n action={deleteUrl}\n onsubmit=\"return confirm('Delete this document?')\"\n >\n <button\n type=\"submit\"\n class=\"btn btn-xs btn-error btn-outline\"\n >\n Delete\n </button>\n </form>\n )}\n </div>\n </td>\n </tr>\n );\n })\n )}\n </tbody>\n </table>\n </div>\n\n {/* Pagination */}\n {(pagination.hasPrev || pagination.hasNext) && (\n <div class=\"flex flex-col items-center mt-6 gap-2\">\n <div class=\"flex justify-center items-center gap-2\">\n {pagination.hasPrev ? (\n <a\n href={paginationHref(\n activeFilters,\n pagination.prevCursor,\n \"prev\",\n sortState,\n currentPageSize,\n )}\n class=\"btn btn-sm btn-outline\"\n >\n ← Previous\n </a>\n ) : (\n <button class=\"btn btn-sm btn-outline\" disabled>\n ← Previous\n </button>\n )}\n {pagination.hasNext ? (\n <a\n href={paginationHref(\n activeFilters,\n pagination.nextCursor,\n \"next\",\n sortState,\n currentPageSize,\n )}\n class=\"btn btn-sm btn-outline\"\n >\n Next →\n </a>\n ) : (\n <button class=\"btn btn-sm btn-outline\" disabled>\n Next →\n </button>\n )}\n </div>\n {typeof totalCount === \"number\" && (\n <div class=\"text-xs text-base-content/50\">\n {totalCount} total document{totalCount !== 1 ? \"s\" : \"\"}\n {activeFilters.length > 0 ? \" matching filters\" : \"\"}\n </div>\n )}\n </div>\n )}\n\n {/* Bulk update modal — controlled client-side */}\n {showSelection && canBulkUpdate && (\n <dialog id=\"frs-bulk-update-modal\" class=\"modal\">\n <div class=\"modal-box\">\n <h3 class=\"font-bold text-lg mb-3\">Bulk update field</h3>\n <p class=\"text-sm text-base-content/60 mb-4\" data-frs-bulk-update-summary>\n Update one field on the selected documents.\n </p>\n <form method=\"dialog\" data-frs-bulk-update-form>\n <label class=\"form-control w-full mb-3\">\n <div class=\"label\">\n <span class=\"label-text text-xs uppercase tracking-wide\">\n Field\n </span>\n </div>\n <select\n class=\"select select-bordered select-sm w-full\"\n name=\"field\"\n required\n data-frs-bulk-field-select\n >\n <option value=\"\">— Select a field —</option>\n {scalarMutable.map((f) => (\n <option key={f} value={f}>\n {f}\n </option>\n ))}\n </select>\n </label>\n <div class=\"mb-4\" data-frs-bulk-value-container>\n {/* Value input injected by client script based on field type */}\n </div>\n <div class=\"modal-action\">\n <button\n type=\"button\"\n class=\"btn btn-sm btn-ghost\"\n data-frs-bulk-update-cancel\n >\n Cancel\n </button>\n <button\n type=\"submit\"\n class=\"btn btn-sm btn-primary\"\n data-frs-bulk-update-submit\n >\n Apply\n </button>\n </div>\n </form>\n </div>\n <form method=\"dialog\" class=\"modal-backdrop\">\n <button>close</button>\n </form>\n </dialog>\n )}\n </PageShell>,\n );\n}\n","/**\n * Admin UI renderer — HTML generation functions for the admin interface.\n * All HTML generation is done via JSX in components.tsx.\n * This file preserves the original public API for backward compatibility.\n *\n * @example\n * ```typescript\n * import {\n * renderPage,\n * renderDashboard,\n * renderList,\n * renderFormPage,\n * ClientScript,\n * CSS,\n * } from \"@lpdjs/firestore-repo-service/servers/admin\";\n *\n * // Render a complete page with shell\n * const html = renderPage(\"<h1>Content</h1>\", {\n * title: \"My Admin\",\n * basePath: \"/admin\",\n * });\n *\n * // Render dashboard listing all repositories\n * const dashboard = renderDashboard(\n * [\n * { name: \"users\", path: \"users\", docCount: 150 },\n * { name: \"posts\", path: \"posts\", docCount: 42 },\n * ],\n * \"/admin\"\n * );\n *\n * // Render document list with pagination\n * const list = renderList(\n * \"users\",\n * [{ docId: \"1\", name: \"John\" }, { docId: \"2\", name: \"Jane\" }],\n * [\"docId\", \"name\"],\n * \"/admin\",\n * { hasPrev: false, hasNext: true, prevCursor: \"\", nextCursor: \"abc123\" },\n * { type: \"success\", message: \"User created!\" }, // Optional flash\n * [{ key: \"name\", label: \"Name\" }], // Column metadata\n * [{ field: \"name\", op: \"==\", value: \"John\" }], // Active filters\n * true, // Allow delete\n * [{ key: \"docId\", column: \"Posts\", targetRepo: \"posts\", targetKey: \"userId\", type: \"many\" }],\n * { field: \"name\", direction: \"asc\" }, // Sort state\n * 25, // Current page size\n * );\n *\n * // Render create/edit form page\n * const form = renderFormPage(\n * \"users\",\n * \"<form>...</form>\",\n * \"edit\",\n * \"user-123\",\n * \"/admin\",\n * { type: \"error\", message: \"Validation failed\" }\n * );\n * ```\n */\n\nexport { ClientScript } from \"./components\";\nexport type {\n ColumnMeta,\n FilterState,\n PageOptions,\n QueryError,\n RelationalFieldMeta,\n SortState,\n WhereOp,\n} from \"./components\";\n\n/** @deprecated Styles come from DaisyUI CDN — no inline CSS needed */\nexport const CSS = \"\";\n\nimport type {\n ColumnMeta,\n FilterState,\n PageOptions,\n QueryError,\n RelationalFieldMeta,\n SortState,\n} from \"./components\";\nimport {\n renderDashboardJsx,\n renderFormPageJsx,\n renderListJsx,\n renderPageJsx,\n} from \"./components\";\nimport type { z } from \"zod\";\n\nexport function renderPage(content: string, opts: PageOptions): string {\n return renderPageJsx(content, opts);\n}\n\nexport function renderDashboard(\n repos: { name: string; path: string; docCount?: number }[],\n basePath: string,\n): string {\n return renderDashboardJsx(repos, basePath);\n}\n\nexport function renderList(\n repoName: string,\n docs: Record<string, unknown>[],\n columns: string[],\n basePath: string,\n pagination: {\n hasPrev: boolean;\n hasNext: boolean;\n prevCursor: string;\n nextCursor: string;\n },\n flash?: PageOptions[\"flash\"],\n columnMeta?: ColumnMeta[],\n activeFilters?: FilterState[],\n allowDelete?: boolean,\n relationalMeta?: RelationalFieldMeta[],\n sortState?: SortState,\n currentPageSize?: number,\n queryError?: QueryError,\n isGroup?: boolean,\n totalCount?: number,\n mutableFields?: string[],\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n schema?: z.ZodObject<any>,\n): string {\n return renderListJsx(\n repoName,\n docs,\n columns,\n basePath,\n pagination,\n flash,\n columnMeta,\n activeFilters,\n allowDelete,\n relationalMeta,\n sortState,\n currentPageSize,\n queryError,\n isGroup,\n totalCount,\n mutableFields,\n schema,\n );\n}\n\nexport function renderFormPage(\n repoName: string,\n formHtml: string,\n mode: \"create\" | \"edit\",\n docId: string | null,\n basePath: string,\n flash?: PageOptions[\"flash\"],\n): string {\n return renderFormPageJsx(repoName, formHtml, mode, docId, basePath, flash);\n}\n","/**\n * Generates a Firebase Console URL to create a composite index OR a\n * single-field index exemption.\n *\n * When Firestore throws FAILED_PRECONDITION (code 9) for missing indexes,\n * the error message sometimes includes a creation link (regular collections)\n * but often does NOT include it (collection groups). This utility builds the\n * link from the query context so the admin UI can always present it.\n *\n * Two URL shapes are produced depending on the query:\n *\n * - **Composite index** (≥ 2 indexed fields, or any COLLECTION-scope multi-field\n * query). Encoded as a JSON `create_composite=` parameter under\n * `/v1/r/project/{p}/firestore/indexes`.\n *\n * - **Single-field exemption** (exactly one indexed field on a COLLECTION_GROUP\n * query — Firestore disables single-field collection-group indexes by\n * default and requires an explicit exemption). Encoded as a base64\n * protobuf `create_exemption=` parameter under\n * `/project/{p}/firestore/databases/-default-/indexes/automatic`.\n */\n\nimport type {\n FilterState,\n QueryError,\n SortState,\n WhereOp,\n} from \"./components/types\";\n\n// ── Types ────────────────────────────────────────────────────────────────────\n\ninterface IndexField {\n fieldPath: string;\n order?: \"ASCENDING\" | \"DESCENDING\";\n arrayConfig?: \"CONTAINS\";\n}\n\n// ── Helpers ──────────────────────────────────────────────────────────────────\n\nconst RANGE_OPS = new Set<WhereOp>([\"<\", \"<=\", \">\", \">=\", \"!=\"]);\nconst ARRAY_OPS = new Set<WhereOp>([\"array-contains\", \"array-contains-any\"]);\n\nfunction toIndexOrder(dir?: \"asc\" | \"desc\"): \"ASCENDING\" | \"DESCENDING\" {\n return dir === \"desc\" ? \"DESCENDING\" : \"ASCENDING\";\n}\n\n/**\n * Extract the collection ID (last path segment) from a Firestore path.\n * e.g. \"posts/{postId}/comments\" → \"comments\"\n */\nexport function collectionIdFromPath(path: string): string {\n const segments = path.split(\"/\").filter(Boolean);\n return segments[segments.length - 1] ?? path;\n}\n\n// ── Main ─────────────────────────────────────────────────────────────────────\n\n/**\n * Build a Firebase Console URL that pre-fills the composite-index creation form.\n *\n * @param projectId - GCP project ID (e.g. \"firestore-repo-services\")\n * @param collectionId - Firestore collection ID (e.g. \"posts\", \"comments\")\n * @param isGroup - Whether this is a collection group query\n * @param filters - Active filter states from the admin UI\n * @param sort - Active sort state (optional)\n * @returns - Full HTTPS URL to the Firebase Console index wizard\n */\nexport function buildIndexUrl(\n projectId: string,\n collectionId: string,\n isGroup: boolean,\n filters: FilterState[],\n sort?: SortState,\n): string {\n const fields: IndexField[] = [];\n const seen = new Set<string>();\n\n // 1. Equality filters first (order doesn't matter for equality)\n for (const f of filters) {\n if (f.op === \"==\" || f.op === \"in\" || f.op === \"not-in\") {\n if (seen.has(f.field)) continue;\n seen.add(f.field);\n fields.push({ fieldPath: f.field, order: \"ASCENDING\" });\n }\n }\n\n // 2. Array operators\n for (const f of filters) {\n if (ARRAY_OPS.has(f.op)) {\n if (seen.has(f.field)) continue;\n seen.add(f.field);\n fields.push({ fieldPath: f.field, arrayConfig: \"CONTAINS\" });\n }\n }\n\n // 3. Range / inequality filters\n for (const f of filters) {\n if (RANGE_OPS.has(f.op)) {\n if (seen.has(f.field)) continue;\n seen.add(f.field);\n // Use the sort direction if the range field matches the orderBy field\n const dir =\n sort?.field === f.field ? toIndexOrder(sort.dir) : \"ASCENDING\";\n fields.push({ fieldPath: f.field, order: dir });\n }\n }\n\n // 4. OrderBy fields not already covered by filters\n if (sort && !seen.has(sort.field)) {\n fields.push({ fieldPath: sort.field, order: toIndexOrder(sort.dir) });\n }\n\n // ── Single-field collection-group exemption ──────────────────────────────\n // Firestore disables single-field collection-group indexes by default; you\n // must create an explicit \"field exemption\". The Firebase Console wizard\n // for that uses a totally different URL (`create_exemption=`) with its own\n // protobuf shape — see buildExemptionUrl below.\n if (fields.length === 1 && isGroup) {\n return buildExemptionUrl(projectId, collectionId, fields[0]!);\n }\n\n // ── Composite index ──────────────────────────────────────────────────────\n // Firebase Console encodes composite indexes as a base64 protobuf payload\n // under `create_composite=`. Every composite index implicitly ends with\n // `__name__` as a tie-breaker, so we always append it (matches what the\n // Console itself produces).\n const lastDir =\n sort && fields.some((f) => f.fieldPath === sort.field)\n ? toIndexOrder(sort.dir)\n : \"ASCENDING\";\n fields.push({ fieldPath: \"__name__\", order: lastDir });\n\n return buildCompositeUrl(projectId, collectionId, isGroup, fields);\n}\n\n/**\n * Build a Firebase Console URL that pre-fills the composite index creation\n * form for either a regular collection or a collection-group query.\n *\n * The URL uses a base64-encoded protobuf payload (the same shape the Console\n * itself produces when you click \"Add index\" in the UI). Schema:\n *\n * message CompositeIndex {\n * string resource_path = 1; // projects/.../collectionGroups/{cg}/indexes/_\n * int32 query_scope = 2; // 1 = COLLECTION, 2 = COLLECTION_GROUP\n * repeated IndexField fields = 3;\n * }\n */\nexport function buildCompositeUrl(\n projectId: string,\n collectionId: string,\n isGroup: boolean,\n fields: IndexField[],\n databaseId: string = \"(default)\",\n): string {\n const resource = `projects/${projectId}/databases/${databaseId}/collectionGroups/${collectionId}/indexes/_`;\n\n const payload: number[] = [\n ...pbString(1, resource),\n ...pbInt(2, isGroup ? 2 : 1),\n ];\n for (const f of fields) {\n payload.push(...pbMessage(3, encodeIndexField(f)));\n }\n\n const urlDbId = databaseId === \"(default)\" ? \"-default-\" : databaseId;\n const encoded = encodeURIComponent(toBase64(payload));\n return `https://console.firebase.google.com/project/${projectId}/firestore/databases/${urlDbId}/indexes?create_composite=${encoded}`;\n}\n\n/**\n * Try to extract an index-creation URL from a Firestore error message.\n * Returns `undefined` if no URL is found.\n */\nexport function extractIndexUrl(message: string): string | undefined {\n const match = message.match(\n /https:\\/\\/console\\.firebase\\.google\\.com[^\\s)\"]*/,\n );\n return match?.[0];\n}\n\n// ── Single-field exemption URL (collection-group) ────────────────────────────\n\n/**\n * Minimal protobuf encoder for the field-exemption payload used by the\n * Firebase Console URL `?create_exemption=…`.\n *\n * Wire format (subset):\n * tag = (field_number << 3) | wire_type\n * wire types: 0 = varint, 2 = length-delimited\n *\n * Schema we encode (reverse-engineered from real Firebase Console URLs):\n * message FieldExemption {\n * string resource_path = 1; // projects/.../fields/{field}\n * int32 query_scope = 2; // 1 = COLLECTION, 2 = COLLECTION_GROUP\n * IndexConfig index = 3;\n * }\n * message IndexConfig {\n * string field_path = 1;\n * int32 order = 2; // 1 = ASCENDING, 2 = DESCENDING\n * int32 array_config = 3; // 1 = CONTAINS (mutually exclusive with order)\n * }\n */\nfunction pbVarint(n: number): number[] {\n const out: number[] = [];\n let v = n >>> 0;\n while (v >= 0x80) {\n out.push((v & 0x7f) | 0x80);\n v >>>= 7;\n }\n out.push(v & 0x7f);\n return out;\n}\n\nfunction pbTag(fieldNumber: number, wireType: 0 | 2): number {\n return (fieldNumber << 3) | wireType;\n}\n\nfunction pbString(fieldNumber: number, value: string): number[] {\n const bytes = Array.from(new TextEncoder().encode(value));\n return [pbTag(fieldNumber, 2), ...pbVarint(bytes.length), ...bytes];\n}\n\nfunction pbInt(fieldNumber: number, value: number): number[] {\n return [pbTag(fieldNumber, 0), ...pbVarint(value)];\n}\n\nfunction pbMessage(fieldNumber: number, payload: number[]): number[] {\n return [pbTag(fieldNumber, 2), ...pbVarint(payload.length), ...payload];\n}\n\n/** Encode an IndexField submessage: { field_path:1, order:2 OR array_config:3 } */\nfunction encodeIndexField(f: IndexField): number[] {\n const out: number[] = [...pbString(1, f.fieldPath)];\n if (f.arrayConfig === \"CONTAINS\") {\n out.push(...pbInt(3, 1));\n } else {\n out.push(...pbInt(2, f.order === \"DESCENDING\" ? 2 : 1));\n }\n return out;\n}\n\nfunction toBase64(bytes: number[]): string {\n // Standard base64 (no padding) — matches what Firebase Console produces.\n // Use Buffer when available (Node), otherwise fall back to btoa.\n const bin = String.fromCharCode(...bytes);\n let b64: string;\n if (typeof Buffer !== \"undefined\") {\n b64 = Buffer.from(bytes).toString(\"base64\");\n } else if (typeof btoa !== \"undefined\") {\n b64 = btoa(bin);\n } else {\n throw new Error(\"No base64 encoder available\");\n }\n return b64.replace(/=+$/, \"\");\n}\n\n/**\n * Build a Firebase Console URL that pre-fills the single-field index\n * exemption form for a collection-group query.\n */\nexport function buildExemptionUrl(\n projectId: string,\n collectionId: string,\n field: IndexField,\n databaseId: string = \"(default)\",\n): string {\n const resource = `projects/${projectId}/databases/${databaseId}/collectionGroups/${collectionId}/fields/${field.fieldPath}`;\n\n const payload: number[] = [\n ...pbString(1, resource),\n ...pbInt(2, 2), // COLLECTION_GROUP\n ...pbMessage(3, encodeIndexField(field)),\n ];\n\n // Database ID for the URL path: \"(default)\" → \"-default-\",\n // any other ID is used as-is (Firebase Console uses the bare ID).\n const urlDbId = databaseId === \"(default)\" ? \"-default-\" : databaseId;\n\n // create_exemption is base64 (URL-safe characters only — `+` and `/` are\n // valid in query string values per RFC, and Firebase accepts them, but we\n // URL-encode just to be safe).\n const encoded = encodeURIComponent(toBase64(payload));\n return `https://console.firebase.google.com/project/${projectId}/firestore/databases/${urlDbId}/indexes/automatic?create_exemption=${encoded}`;\n}\n\n// ── Project ID extraction ────────────────────────────────────────────────────\n\n/**\n * Robustly extract the GCP project ID from a Firestore reference.\n * Falls back through several known locations across firebase-admin versions\n * and finally to standard environment variables.\n */\nexport function extractProjectId(ref: unknown): string | undefined {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const r = ref as any;\n const candidates: unknown[] = [\n r?.firestore?.projectId,\n r?.firestore?.app?.options?.projectId,\n r?.firestore?._settings?.projectId,\n r?.firestore?.databaseId?.projectId,\n r?._firestore?.projectId,\n ];\n for (const c of candidates) {\n if (typeof c === \"string\" && c.length > 0) return c;\n }\n const env =\n process.env[\"GCLOUD_PROJECT\"] ||\n process.env[\"GOOGLE_CLOUD_PROJECT\"] ||\n process.env[\"FIREBASE_PROJECT_ID\"];\n return env || undefined;\n}\n\n// ── Centralized error → QueryError conversion ────────────────────────────────\n\n/**\n * Context required to build a fallback index URL when Firestore does not\n * include one in its error (typical for collection-group queries).\n */\nexport interface QueryErrorContext {\n /** Repository ref (CollectionReference / Query) used to extract project id */\n ref: unknown;\n /** Firestore collection path of the repo (e.g. \"posts/{postId}/comments\") */\n path: string;\n /** Whether the repo is a collection-group */\n isGroup: boolean;\n /** Active where filters at the time of the failed query */\n filters: FilterState[];\n /** Active orderBy state at the time of the failed query (if any) */\n sort?: SortState;\n}\n\n/**\n * Detect whether an unknown error thrown by Firestore is a missing-index\n * (`FAILED_PRECONDITION` / code 9) error.\n */\nexport function isMissingIndexError(err: unknown): boolean {\n const fe = err as { code?: number; message?: string } | null | undefined;\n if (!fe) return false;\n if (fe.code === 9) return true;\n return typeof fe.message === \"string\"\n ? fe.message.includes(\"requires an index\")\n : false;\n}\n\n/**\n * Convert a Firestore error into a typed `QueryError` with a guaranteed\n * `indexUrl` for missing-index cases (extracted from the message when\n * present, otherwise rebuilt from the query context — necessary for\n * collection-group queries where the SDK omits the link).\n *\n * Returns `null` when `err` is falsy.\n */\nexport function toQueryError(\n err: unknown,\n ctx: QueryErrorContext,\n): QueryError {\n const fe = (err ?? {}) as { code?: number; message?: string };\n const isIndex = isMissingIndexError(err);\n\n let indexUrl: string | undefined;\n if (isIndex) {\n indexUrl = fe.message ? extractIndexUrl(fe.message) : undefined;\n if (!indexUrl) {\n const projectId = extractProjectId(ctx.ref);\n if (projectId) {\n const colId = collectionIdFromPath(ctx.path);\n indexUrl = buildIndexUrl(\n projectId,\n colId,\n ctx.isGroup,\n ctx.filters,\n ctx.sort,\n );\n }\n }\n }\n\n return {\n type: isIndex ? \"index\" : \"error\",\n message: isIndex\n ? \"This query requires a composite index that does not exist yet.\"\n : (fe.message ?? \"Query failed\"),\n indexUrl,\n };\n}\n","/**\n * @module servers/admin\n *\n * Creates a static ORM admin interface served as a Firebase HTTPS function.\n *\n * Features:\n * - Dashboard listing all registered repositories\n * - Document list with cursor-based pagination\n * - Create / Edit / Delete forms generated from Zod schemas\n * - Forms map **exactly** to the repository model type\n * - Zero JavaScript framework — plain HTML + inline CSS + vanilla JS\n * - Body parsing for `application/x-www-form-urlencoded` (default HTML forms)\n * and `application/json` (API clients)\n *\n * @example\n * ```ts\n * import * as functions from \"firebase-functions\";\n * import { z } from \"zod\";\n * import { createAdminServer } from \"@lpdjs/firestore-repo-service/servers/admin\";\n *\n * const postSchema = z.object({\n * title: z.string().min(1),\n * content: z.string(),\n * status: z.enum([\"draft\", \"published\"]),\n * authorId: z.string(),\n * });\n *\n * export const adminApp = functions.https.onRequest(\n * createAdminServer({\n * basePath: \"/admin\",\n * repos: {\n * posts: { repo: repos.posts, schema: postSchema, path: \"posts\" },\n * },\n * })\n * );\n * ```\n */\n\nimport type { z } from \"zod\";\nimport type { HttpsOptions } from \"firebase-functions/v2/https\";\nimport type { ConfiguredRepository } from \"../../repositories/types\";\nimport type { FieldPath, RepositoryConfig } from \"../../shared/types\";\nimport type { FieldRole } from \"../crud/types\";\nimport type { HttpRequest, HttpResponse } from \"../http-types\";\nimport type { AdminRepoEntry, RepoRegistry } from \"./handlers\";\nimport { createAdminHandlers } from \"./handlers\";\nimport type { RelationalFieldMeta } from \"./renderer\";\nimport { type Middleware, MiniRouter } from \"./router\";\n\n// ---------------------------------------------------------------------------\n// Public option types\n// ---------------------------------------------------------------------------\n\n/**\n * Extracts the model type `T` from a `ConfiguredRepository`.\n * Two-step inference so it survives intersection types\n * (e.g. `RepositoryConfig<...> & { schema: ZodObject }` produced by\n * `createRepositoryConfig(schema)`).\n * @internal\n */\ntype RepoModelType<TRepo> =\n TRepo extends ConfiguredRepository<infer C>\n ? C extends RepositoryConfig<infer T, any, any, any, any, any, any, any, any, any>\n ? T\n : never\n : never;\n\n/**\n * Configuration for a single repository in the admin server.\n *\n * @template TRepo - The `ConfiguredRepository` type; used to derive typed field names.\n *\n * If the repository was created with `createRepositoryConfig(schema)(config)`,\n * the `schema` field is optional — it is auto-detected from the repo.\n * Otherwise, pass `schema` explicitly.\n *\n * @example\n * ```ts\n * posts: {\n * repo: repos.posts,\n * fieldsConfig: {\n * title: [\"create\", \"mutable\", \"filterable\"],\n * content: [\"create\", \"mutable\"],\n * status: [\"create\", \"filterable\"],\n * },\n * allowDelete: true,\n * }\n * ```\n */\nexport interface AdminRepoConfig<\n TRepo extends ConfiguredRepository<any> = ConfiguredRepository<any>,\n> {\n /** The configured repository instance. Drives type inference for all other fields. */\n repo: TRepo;\n /**\n * Zod schema — optional when the repo was created with `createRepositoryConfig(schema)`.\n * Pass explicitly for repos created with the legacy `createRepositoryConfig<T>()` form.\n */\n schema?: z.ZodObject<any>;\n /** Firestore collection path (for display only) */\n path: string;\n /** Key used to identify documents (default: \"docId\") */\n documentKey?: string;\n /** Columns to display in the list view (default: all schema keys) */\n listColumns?: string[];\n /** Number of documents per page in the list view (default: 25) */\n pageSize?: number;\n /**\n * Per-field role configuration.\n * Each key is a model field (with autocomplete); the value is an array of roles.\n *\n * Roles:\n * - `\"create\"` — field is shown in the create form\n * - `\"mutable\"` — field is shown in the edit form\n * - `\"filterable\"` — field is shown in the filter bar\n *\n * If omitted, all schema fields are shown in all contexts.\n *\n * @example\n * ```ts\n * fieldsConfig: {\n * title: [\"create\", \"mutable\", \"filterable\"],\n * content: [\"create\", \"mutable\"],\n * status: [\"create\", \"filterable\"],\n * }\n * ```\n */\n fieldsConfig?: Partial<Record<FieldPath<RepoModelType<TRepo>>, readonly FieldRole[]>>;\n /**\n * Whether to show the delete button in the list view.\n * Default: false — delete is disabled unless explicitly set to true.\n */\n allowDelete?: boolean;\n /**\n * Relational action columns appended to the list table.\n * Each entry adds a dedicated button that navigates to the linked repository.\n *\n * - **type \"one\"** (e.g. `userId` on a post) → button links to the target\n * document edit page: `/{targetRepo}/{value}/edit`\n * - **type \"many\"** (e.g. `docId` on a user) → button links to the target\n * repo list filtered by value: `/{targetRepo}?fv_{targetKey}={value}`\n *\n * @example\n * ```ts\n * users: {\n * repo: repos.users,\n * relationalFields: [\n * { key: \"docId\", column: \"Posts\" }, // many → list of posts by this user\n * ]\n * }\n * posts: {\n * repo: repos.posts,\n * relationalFields: [\n * { key: \"userId\", column: \"Author\" }, // one → edit page of the user\n * ]\n * }\n * ```\n */\n relationalFields?: {\n key: keyof RepoModelType<TRepo> & string;\n column: string;\n }[];\n}\n\n/**\n * HTTP Basic Auth configuration.\n * The browser will show a native login dialog.\n */\nexport interface BasicAuthConfig {\n type: \"basic\";\n /** Realm displayed in the browser login dialog */\n realm?: string;\n username: string;\n password: string;\n}\n\n/**\n * Options for `createAdminServer`.\n *\n * Made generic so TypeScript can infer the model type of each repo entry\n * and provide autocomplete + type-checking on `fieldsConfig`.\n *\n * @template TRepos - Shape of the repos map (inferred automatically at the call site)\n */\nexport interface AdminServerOptions<\n TRepos extends Record<string, ConfiguredRepository<any>> = Record<\n string,\n ConfiguredRepository<any>\n >,\n> {\n /**\n * Base URL path of the function (e.g. \"/admin\").\n * Must match the path where the Firebase Function is mounted.\n * Default: \"/\"\n */\n basePath?: string;\n\n /**\n * Repository entries keyed by a display name.\n * TypeScript infers the model type from each `repo` field,\n * so `fieldsConfig` keys are typed to that model's field paths.\n *\n * @example\n * ```ts\n * repos: {\n * posts: {\n * repo: repos.posts,\n * fieldsConfig: {\n * title: [\"create\", \"mutable\", \"filterable\"],\n * content: [\"create\", \"mutable\"],\n * status: [\"create\", \"filterable\"],\n * },\n * },\n * }\n * ```\n */\n repos: { [K in keyof TRepos]: AdminRepoConfig<TRepos[K]> };\n\n /** Whether to parse URL-encoded bodies. Default: true. */\n parseBody?: boolean;\n\n /**\n * Authentication guard executed before every request.\n * - Pass a `BasicAuthConfig` to enable HTTP Basic Auth.\n * - Pass a `Middleware` function for custom auth logic.\n */\n auth?: BasicAuthConfig | Middleware;\n\n /**\n * Additional middleware functions executed after auth, before route handlers.\n */\n middleware?: Middleware[];\n\n /**\n * Options forwarded to `onRequest()` from `firebase-functions/v2/https`.\n * Stored on the returned handler as `.httpsOptions` for easy access.\n *\n * @example\n * ```ts\n * const handler = createAdminServer({ httpsOptions: { invoker: \"public\" }, ... });\n * export const admin = onRequest(handler.httpsOptions!, handler);\n * ```\n */\n httpsOptions?: HttpsOptions;\n}\n// ---------------------------------------------------------------------------\n\n/** Eagerly reads the raw request body as a string */\nasync function readRawBody(req: HttpRequest): Promise<string> {\n if (typeof (req as any).rawBody === \"string\")\n return (req as any).rawBody as string;\n if (Buffer.isBuffer((req as any).rawBody))\n return ((req as any).rawBody as Buffer).toString(\"utf8\");\n // Firebase Functions v2 / Cloud Run: body may already be parsed\n return \"\";\n}\n\nfunction parseUrlEncoded(body: string): Record<string, string | string[]> {\n const result: Record<string, string | string[]> = {};\n if (!body) return result;\n for (const pair of body.split(\"&\")) {\n const idx = pair.indexOf(\"=\");\n if (idx === -1) continue;\n const key = decodeURIComponent(pair.slice(0, idx).replace(/\\+/g, \" \"));\n const val = decodeURIComponent(pair.slice(idx + 1).replace(/\\+/g, \" \"));\n const existing = result[key];\n if (existing === undefined) {\n result[key] = val;\n } else if (Array.isArray(existing)) {\n existing.push(val);\n } else {\n result[key] = [existing, val];\n }\n }\n return result;\n}\n\n// ---------------------------------------------------------------------------\n// Factory\n// ---------------------------------------------------------------------------\n\n/**\n * Creates an Express-compatible request handler for the admin ORM UI.\n * Generates a complete admin interface with dashboard, lists, and CRUD forms.\n *\n * @template TRepos - Shape of the repos map (inferred automatically)\n * @param options - Admin server configuration\n * @returns Express-compatible request handler for Firebase Functions\n *\n * @example\n * ```typescript\n * // Basic admin server\n * import { onRequest } from \"firebase-functions/https\";\n * import { createAdminServer } from \"@lpdjs/firestore-repo-service/servers/admin\";\n *\n * export const admin = onRequest(\n * createAdminServer({\n * basePath: \"/admin\",\n * repos: {\n * users: {\n * repo: repos.users,\n * path: \"users\",\n * },\n * posts: {\n * repo: repos.posts,\n * path: \"posts\",\n * },\n * },\n * })\n * );\n *\n * // With HTTP Basic Auth\n * export const admin = onRequest(\n * createAdminServer({\n * basePath: \"/admin\",\n * auth: {\n * type: \"basic\",\n * realm: \"Admin Area\",\n * username: \"admin\",\n * password: process.env.ADMIN_PASSWORD!,\n * },\n * repos: { ... },\n * })\n * );\n *\n * // With custom auth middleware\n * export const admin = onRequest(\n * createAdminServer({\n * auth: async (req, res, next) => {\n * const token = req.headers?.authorization?.replace(\"Bearer \", \"\");\n * if (!token || !(await verifyToken(token))) {\n * res.status(401).send(\"Unauthorized\");\n * return;\n * }\n * next();\n * },\n * repos: { ... },\n * })\n * );\n *\n * // Full configuration with all options\n * export const admin = onRequest(\n * createAdminServer({\n * basePath: \"/admin\",\n * parseBody: true, // Parse URL-encoded bodies\n * auth: { type: \"basic\", username: \"admin\", password: \"secret\" },\n * middleware: [loggingMiddleware], // Additional middleware\n * repos: {\n * posts: {\n * repo: repos.posts,\n * path: \"posts\",\n * documentKey: \"docId\", // Field used as document ID\n * listColumns: [\"title\", \"status\", \"createdAt\"], // Columns in list\n * pageSize: 25, // Items per page in list\n * fieldsConfig: {\n * title: [\"create\", \"mutable\", \"filterable\"],\n * content: [\"create\", \"mutable\"],\n * status: [\"create\", \"mutable\", \"filterable\"],\n * userId: [\"filterable\"],\n * },\n * allowDelete: true, // Enable delete button\n * relationalFields: [ // Relation navigation buttons\n * { key: \"userId\", column: \"Author\" }, // Link to user\n * { key: \"docId\", column: \"Comments\" }, // Link to comments list\n * ],\n * },\n * users: {\n * repo: repos.users,\n * path: \"users\",\n * fieldsConfig: {\n * name: [\"create\", \"mutable\"],\n * email: [\"create\", \"mutable\", \"filterable\"],\n * isActive: [\"mutable\", \"filterable\"],\n * },\n * allowDelete: false,\n * relationalFields: [\n * { key: \"docId\", column: \"Posts\" },\n * ],\n * },\n * },\n * })\n * );\n *\n * // Routes generated automatically:\n * // GET /admin/ → Dashboard (list of repos)\n * // GET /admin/:repo → Document list with pagination\n * // GET /admin/:repo/create → Create form\n * // POST /admin/:repo/create → Submit create\n * // GET /admin/:repo/:id/edit → Edit form\n * // POST /admin/:repo/:id/edit → Submit edit\n * // POST /admin/:repo/:id/delete → Delete document\n * ```\n */\nexport function createAdminServer<\n TRepos extends Record<string, ConfiguredRepository<any>>,\n>(\n options: AdminServerOptions<TRepos>,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n): ((req: any, res: any) => Promise<void>) & { httpsOptions?: HttpsOptions } {\n const {\n basePath = \"/\",\n repos,\n parseBody = true,\n auth,\n middleware: extraMiddleware = [],\n httpsOptions,\n } = options;\n\n // Normalise basePath: no trailing slash\n const base = basePath === \"/\" ? \"\" : basePath.replace(/\\/$/, \"\");\n\n // Build the registry\n const registry: RepoRegistry = {};\n for (const [name, cfg] of Object.entries(repos)) {\n // Schema resolution: explicit cfg.schema > embedded in repo (createRepositoryConfig(schema))\n const resolvedSchema = cfg.schema ?? (cfg.repo as any).schema ?? null;\n if (!resolvedSchema) {\n throw new Error(\n `[createAdminServer] Repository \"${name}\" has no Zod schema. ` +\n `Either use createRepositoryConfig(schema)(config) or pass schema: explicitly.`,\n );\n }\n // Resolve fieldsConfig → separate arrays for runtime\n let filterableFields: string[] | undefined;\n let mutableFields: string[] | undefined;\n let createFields: string[] | undefined;\n if (cfg.fieldsConfig) {\n const fc = cfg.fieldsConfig as Record<string, readonly string[]>;\n filterableFields = [];\n mutableFields = [];\n createFields = [];\n for (const [field, roles] of Object.entries(fc)) {\n for (const role of roles) {\n if (role === \"filterable\") filterableFields.push(field);\n else if (role === \"mutable\") mutableFields.push(field);\n else if (role === \"create\") createFields.push(field);\n }\n }\n if (filterableFields.length === 0) filterableFields = undefined;\n if (mutableFields.length === 0) mutableFields = undefined;\n if (createFields.length === 0) createFields = undefined;\n }\n\n // For collection-group repos, ensure parentKeys are included in createFields\n // so the form/validation allows the user to provide them.\n const parentKeys = (() => {\n const pk = (cfg.repo as any)._parentKeys as string[] | undefined;\n return pk && pk.length > 0 ? pk : undefined;\n })();\n if (parentKeys && createFields) {\n for (const pk of parentKeys) {\n if (!createFields.includes(pk)) createFields.push(pk);\n }\n }\n\n const entry: AdminRepoEntry = {\n name,\n path: cfg.path,\n repo: cfg.repo,\n schema: resolvedSchema,\n documentKey: cfg.documentKey ?? \"docId\",\n pathKey: (cfg.repo as any)._pathKey ?? undefined,\n isGroup: !!(cfg.repo as any)._isGroup,\n parentKeys,\n createdKey: (cfg.repo as any)._createdKey ?? undefined,\n listColumns: cfg.listColumns,\n pageSize: cfg.pageSize,\n filterableFields,\n mutableFields,\n createFields,\n allowDelete: cfg.allowDelete ?? false,\n relationalMeta: (() => {\n if (!cfg.relationalFields || cfg.relationalFields.length === 0)\n return undefined;\n const repoRelKeys = (cfg.repo as any).relationalKeys ?? {};\n const meta: RelationalFieldMeta[] = [];\n for (const entry of cfg.relationalFields) {\n const rel = repoRelKeys[entry.key];\n if (rel) {\n meta.push({\n key: entry.key,\n column: entry.column,\n targetRepo: String(rel.repo),\n targetKey: String(rel.key),\n type: rel.type as \"one\" | \"many\",\n });\n }\n }\n return meta.length > 0 ? meta : undefined;\n })(),\n };\n registry[name] = entry;\n }\n\n const handlers = createAdminHandlers(registry, base);\n\n // ── Router ─────────────────────────────────────────────────────────────\n const router = new MiniRouter();\n\n // ── 1. Body-parsing middleware ──────────────────────────────────────────\n if (parseBody) {\n router.use(async (req, _res, next) => {\n const r = req as unknown as HttpRequest;\n const contentType = String(r.headers?.[\"content-type\"] ?? \"\");\n if (contentType.includes(\"application/x-www-form-urlencoded\")) {\n const raw = await readRawBody(r);\n (req as any).body = parseUrlEncoded(raw);\n } else if (\n contentType.includes(\"application/json\") &&\n typeof r.body === \"string\"\n ) {\n try {\n (req as any).body = JSON.parse(r.body as string);\n } catch {\n /* keep as string */\n }\n }\n await next();\n });\n }\n\n // ── 2. Auth middleware ──────────────────────────────────────────────────\n if (auth) {\n if (typeof auth === \"function\") {\n // Custom middleware\n router.use(auth);\n } else {\n // HTTP Basic Auth\n const realm = auth.realm ?? \"Admin\";\n const expected =\n \"Basic \" +\n Buffer.from(`${auth.username}:${auth.password}`).toString(\"base64\");\n router.use((req, res, next) => {\n const authorization = (req as any).headers?.[\"authorization\"] ?? \"\";\n if (authorization !== expected) {\n res\n .status(401)\n .set(\"WWW-Authenticate\", `Basic realm=\"${realm}\"`)\n .set(\"Content-Type\", \"text/plain\")\n .send(\"Unauthorized\");\n return;\n }\n next();\n });\n }\n }\n\n // ── 3. Extra user middleware ────────────────────────────────────────────\n for (const mw of extraMiddleware) {\n router.use(mw);\n }\n\n // ── 4. Routes ─────────────────────────────────────────────────────────────\n router.get(`${base}/`, handlers.handleDashboard);\n router.get(`${base}`, handlers.handleDashboard);\n\n // Specific routes (with literal \"_panel\" / \"_bulk\" segments) MUST come before\n // the generic \":repoName/:id/...\" routes so they take precedence.\n router.get(`${base}/:repoName/_panel`, handlers.handlePanel as any);\n router.post(`${base}/:repoName/_bulk/delete`, handlers.handleBulkDelete as any);\n router.post(`${base}/:repoName/_bulk/update`, handlers.handleBulkUpdate as any);\n\n router.get(`${base}/:repoName`, handlers.handleList);\n\n router.get(`${base}/:repoName/create`, handlers.handleCreateForm);\n router.post(`${base}/:repoName/create`, handlers.handleCreateSubmit as any);\n\n router.get(`${base}/:repoName/:id/edit`, handlers.handleEditForm as any);\n router.post(`${base}/:repoName/:id/edit`, handlers.handleEditSubmit as any);\n\n router.post(`${base}/:repoName/:id/delete`, handlers.handleDelete as any);\n\n // ── Request handler ─────────────────────────────────────────────────────\n const handler = async (req: HttpRequest, res: HttpResponse): Promise<void> => {\n await router.handle(req as any, res as any);\n };\n if (httpsOptions) (handler as any).httpsOptions = httpsOptions;\n return handler as ((req: any, res: any) => Promise<void>) & { httpsOptions?: HttpsOptions };\n}\n\n// Re-exports for convenience\nexport type { AdminRepoEntry, RepoRegistry } from \"./handlers\";\nexport { MiniRouter } from \"./router\";\nexport type { Middleware, RouteHandler } from \"./router\";\n","/**\n * HTTP route handlers for the CRUD API server.\n *\n * Routes:\n * GET /:repoName → list documents (paginated)\n * GET /:repoName/:id → get single document\n * POST /:repoName → create document\n * PUT /:repoName/:id → update document (full)\n * PATCH /:repoName/:id → update document (partial)\n * DELETE /:repoName/:id → delete document\n */\n\nimport { z } from \"zod\";\nimport {\n coerceToDate,\n getDateHandling,\n maybeNormalize,\n} from \"../../shared/date-config\";\nimport {\n isMissingIndexError,\n toQueryError,\n type QueryErrorContext,\n} from \"../admin/index-url\";\nimport type {\n ApiResponse,\n CrudRepoEntry,\n CrudRepoRegistry,\n ListResponseData,\n QueryRequestBody,\n} from \"./types\";\n\n// ---------------------------------------------------------------------------\n// Response helpers\n// ---------------------------------------------------------------------------\n\nfunction sendJson<T>(res: any, data: ApiResponse<T>, status = 200): void {\n const payload = maybeNormalize(data);\n res\n .status(status)\n .set(\"Content-Type\", \"application/json; charset=utf-8\")\n .send(JSON.stringify(payload));\n}\n\nfunction sendSuccess<T>(\n res: any,\n data: T,\n meta?: ApiResponse[\"meta\"],\n status = 200,\n): void {\n sendJson(res, { success: true, data, meta }, status);\n}\n\nfunction sendError(res: any, error: string, status = 400): void {\n sendJson(res, { success: false, error }, status);\n}\n\n/**\n * Send a structured error response. When the underlying Firestore error is a\n * missing-index (`FAILED_PRECONDITION` / code 9), include `errorType: \"index\"`\n * and an `indexUrl` pointing to the Firebase Console index-creation wizard —\n * crucial for collection-group queries where the SDK omits the link.\n */\nfunction sendQueryError(\n res: any,\n err: unknown,\n ctx: QueryErrorContext,\n fallbackMessage: string,\n verbose: boolean,\n): void {\n const qe = toQueryError(err, ctx);\n const isIndex = qe.type === \"index\";\n const status = isIndex ? 424 : 500;\n const message = isIndex\n ? qe.message\n : verbose && err instanceof Error\n ? err.message\n : fallbackMessage;\n const payload: ApiResponse = { success: false, error: message };\n if (isIndex) {\n payload.errorType = \"index\";\n if (qe.indexUrl) payload.indexUrl = qe.indexUrl;\n }\n sendJson(res, payload, status);\n}\n\n// ---------------------------------------------------------------------------\n// ID generation\n// ---------------------------------------------------------------------------\n\nconst _idChars =\n \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\";\n\n/** Generate a random 20-char alphanumeric ID matching Firestore's native format. */\nfunction generateFirestoreId(): string {\n let id = \"\";\n for (let i = 0; i < 20; i++) {\n id += _idChars.charAt(Math.floor(Math.random() * _idChars.length));\n }\n return id;\n}\n\n// ---------------------------------------------------------------------------\n// Zod schema helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Recursively wrap z.date() with z.preprocess(coerceToDate) so that ISO strings,\n * Firestore Timestamps and {_seconds,_nanoseconds} payloads are accepted as input.\n * Only invoked when global date handling mode is \"normalize\".\n */\nfunction wrapDateSchemas(schema: z.ZodType): z.ZodType {\n const def = (schema as any)._def ?? (schema as any).def;\n if (!def) return schema;\n const typeName = def.typeName ?? def.type;\n\n if (typeName === \"ZodDate\" || typeName === \"date\") {\n return z.preprocess((v) => coerceToDate(v) ?? v, schema as z.ZodDate);\n }\n if (typeName === \"ZodObject\" || typeName === \"object\") {\n const shape = (schema as z.ZodObject<any>).shape;\n const wrapped: Record<string, z.ZodType> = {};\n for (const [k, v] of Object.entries(shape)) {\n wrapped[k] = wrapDateSchemas(v as z.ZodType);\n }\n return z.object(wrapped);\n }\n if (typeName === \"ZodArray\" || typeName === \"array\") {\n const inner = def.element ?? def.type;\n if (inner) return z.array(wrapDateSchemas(inner));\n }\n if (typeName === \"ZodOptional\" || typeName === \"optional\") {\n const inner = def.innerType;\n if (inner) return wrapDateSchemas(inner).optional();\n }\n if (typeName === \"ZodNullable\" || typeName === \"nullable\") {\n const inner = def.innerType;\n if (inner) return wrapDateSchemas(inner).nullable();\n }\n if (typeName === \"ZodDefault\" || typeName === \"default\") {\n const inner = def.innerType;\n const dflt = def.defaultValue;\n if (inner) {\n const wrapped = wrapDateSchemas(inner);\n return typeof dflt === \"function\"\n ? wrapped.default(dflt())\n : wrapped.default(dflt);\n }\n }\n return schema;\n}\n\n/**\n * Pick only specified fields from a Zod schema, always excluding system-managed keys.\n *\n * - `fields` undefined or empty → all schema fields minus systemKeys\n * - `fields` with values → only those fields, minus systemKeys\n */\nfunction pickSchemaFields(\n schema: z.ZodObject<any>,\n fields: string[] | undefined,\n systemKeys: string[] = [],\n): z.ZodObject<any> {\n const shape = schema.shape;\n const picked: Record<string, z.ZodType> = {};\n\n const source = fields && fields.length > 0 ? fields : Object.keys(shape);\n\n for (const field of source) {\n if (systemKeys.includes(field)) continue;\n const topLevel = field.split(\".\")[0];\n if (topLevel && shape[topLevel]) {\n picked[topLevel] = shape[topLevel]!;\n }\n }\n\n return z.object(picked);\n}\n\n/**\n * Validate data against schema and return parsed result or error.\n */\nfunction validateData(\n schema: z.ZodObject<any>,\n data: unknown,\n fields: string[] | undefined,\n partial = false,\n systemKeys: string[] = [],\n):\n | { success: true; data: Record<string, unknown> }\n | { success: false; error: string } {\n try {\n const targetSchema = pickSchemaFields(schema, fields, systemKeys);\n const partialSchema = partial ? targetSchema.partial() : targetSchema;\n const finalSchema =\n getDateHandling() === \"normalize\"\n ? (wrapDateSchemas(partialSchema) as z.ZodObject<any>)\n : partialSchema;\n const parsed = finalSchema.parse(data);\n return { success: true, data: parsed as Record<string, unknown> };\n } catch (err) {\n if (err instanceof z.ZodError) {\n const messages = err.issues.map(\n (e) => `${e.path.join(\".\")}: ${e.message}`,\n );\n return {\n success: false,\n error: `Validation failed: ${messages.join(\", \")}`,\n };\n }\n return { success: false, error: \"Validation failed\" };\n }\n}\n\n// ---------------------------------------------------------------------------\n// Filter parsing\n// ---------------------------------------------------------------------------\n\ntype WhereOp =\n | \"==\"\n | \"!=\"\n | \"<\"\n | \"<=\"\n | \">\"\n | \">=\"\n | \"in\"\n | \"not-in\"\n | \"array-contains\"\n | \"array-contains-any\";\n\ninterface ParsedFilter {\n field: string;\n op: WhereOp;\n value: unknown;\n}\n\n/**\n * Parse query params into filter conditions.\n * Supports:\n * - field=value → field == value\n * - field__op=value → field op value (e.g., status__ne=draft → status != draft)\n * - field__in=a,b,c → field in [a, b, c]\n */\nfunction parseFilters(\n query: Record<string, string | string[] | undefined>,\n filterableFields: string[] | undefined,\n): ParsedFilter[] {\n const filters: ParsedFilter[] = [];\n const allowedFields = filterableFields ? new Set(filterableFields) : null;\n\n const opMap: Record<string, WhereOp> = {\n eq: \"==\",\n ne: \"!=\",\n lt: \"<\",\n lte: \"<=\",\n gt: \">\",\n gte: \">=\",\n in: \"in\",\n nin: \"not-in\",\n contains: \"array-contains\",\n containsAny: \"array-contains-any\",\n };\n\n for (const [key, rawVal] of Object.entries(query)) {\n if (rawVal === undefined) continue;\n\n // Skip pagination/meta params\n if (\n [\"cursor\", \"limit\", \"pageSize\", \"orderBy\", \"orderDir\", \"select\"].includes(\n key,\n )\n )\n continue;\n\n const val = Array.isArray(rawVal) ? rawVal[0] : rawVal;\n if (val === undefined || val === \"\") continue;\n\n // Parse field__op format\n const match = key.match(/^(\\w+)__(\\w+)$/);\n let field: string;\n let op: WhereOp = \"==\";\n\n if (match && match[1] && match[2]) {\n field = match[1];\n const opKey = match[2];\n if (opMap[opKey]) {\n op = opMap[opKey];\n } else {\n continue; // Unknown operator, skip\n }\n } else if (!match) {\n field = key;\n } else {\n continue; // Invalid match\n }\n\n // Check if field is filterable\n if (allowedFields && !allowedFields.has(field)) continue;\n\n // Parse value\n let parsedVal: unknown = val;\n\n // Handle \"in\" and \"not-in\" operators (comma-separated)\n if (op === \"in\" || op === \"not-in\" || op === \"array-contains-any\") {\n parsedVal = val.split(\",\").map((v) => parseValue(v.trim()));\n } else {\n parsedVal = parseValue(val);\n }\n\n filters.push({ field, op, value: parsedVal });\n }\n\n return filters;\n}\n\n/**\n * Parse a string value into appropriate type.\n */\nfunction parseValue(val: string): unknown {\n // Boolean\n if (val === \"true\") return true;\n if (val === \"false\") return false;\n if (val === \"null\") return null;\n\n // Number\n const num = Number(val);\n if (!isNaN(num) && val !== \"\") return num;\n\n // String\n return val;\n}\n\n// ---------------------------------------------------------------------------\n// Cursor serialization helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Serialize a Firestore DocumentSnapshot to a JSON-safe cursor object.\n */\nfunction serializeCursor(\n snapshot: import(\"firebase-admin/firestore\").DocumentSnapshot | undefined,\n): Record<string, unknown> | null {\n if (!snapshot) return null;\n return { docId: snapshot.id };\n}\n\n/**\n * Deserialize a cursor object back to a DocumentSnapshot.\n * Fetches the document from Firestore to get the actual snapshot.\n */\nasync function deserializeCursor(\n entry: CrudRepoEntry,\n cursor: unknown,\n): Promise<import(\"firebase-admin/firestore\").DocumentSnapshot | undefined> {\n if (!cursor || typeof cursor !== \"object\") return undefined;\n const docId = (cursor as Record<string, unknown>).docId;\n if (typeof docId !== \"string\") return undefined;\n\n try {\n // Get the collection reference from the repo\n const colRef = entry.repo\n .ref as import(\"firebase-admin/firestore\").CollectionReference;\n if (typeof colRef.doc !== \"function\") return undefined;\n const snapshot = await colRef.doc(docId).get();\n return snapshot.exists ? snapshot : undefined;\n } catch {\n return undefined;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Handlers factory\n// ---------------------------------------------------------------------------\n\nexport function createCrudHandlers(\n registry: CrudRepoRegistry,\n basePath: string,\n verbose: boolean,\n) {\n // ── Helper to get repo entry ────────────────────────────────────────────\n function getRepoEntry(\n repoName: string | undefined,\n res: any,\n ): CrudRepoEntry | null {\n if (!repoName || !registry[repoName]) {\n sendError(res, `Repository \"${repoName}\" not found`, 404);\n return null;\n }\n return registry[repoName];\n }\n\n /**\n * Extract Firestore document path args from a document's stored path.\n * e.g. \"posts/abc/comments/xyz\" → [\"abc\", \"xyz\"] (the doc-ID segments).\n */\n function extractPathArgs(\n doc: Record<string, unknown>,\n pathKey?: string,\n ): string[] | undefined {\n if (!pathKey) return undefined;\n const fullPath = doc[pathKey];\n if (typeof fullPath !== \"string\" || !fullPath) return undefined;\n const segments = fullPath.split(\"/\").filter(Boolean);\n const args: string[] = [];\n for (let i = 1; i < segments.length; i += 2) {\n args.push(segments[i]!);\n }\n return args.length > 0 ? args : undefined;\n }\n\n /**\n * Fetch a single document by its documentKey, with fallback to query\n * for collection-group repos where direct documentRef may fail.\n */\n async function fetchDocById(\n entry: CrudRepoEntry,\n docId: string,\n ): Promise<Record<string, unknown> | null> {\n const getterName = `by${entry.documentKey.charAt(0).toUpperCase()}${entry.documentKey.slice(1)}`;\n const getter = (entry.repo.get as any)[getterName];\n\n if (typeof getter === \"function\") {\n try {\n const doc = (await getter(docId)) as Record<string, unknown> | null;\n if (doc) return doc;\n } catch {\n // Direct ref may fail for subcollections — fall through to query\n }\n }\n\n const results = await entry.repo.query.by({\n where: [[entry.documentKey, \"==\", docId]],\n limit: 1,\n });\n return (results[0] as Record<string, unknown>) ?? null;\n }\n\n // ── LIST: GET /:repoName ────────────────────────────────────────────────\n async function handleList(req: any, res: any): Promise<void> {\n const params = req.params || {};\n const entry = getRepoEntry(params.repoName, res);\n if (!entry) return;\n\n // Captured for error handling (so the catch can build an index URL)\n let ctxFilters: { field: string; op: any; value: string }[] = [];\n let ctxSort: { field: string; dir: \"asc\" | \"desc\" } | undefined;\n\n try {\n const query = req.query ?? {};\n const pageSize = Math.min(\n Number(query.pageSize) || entry.pageSize,\n 100, // Max page size\n );\n const cursor = query.cursor as string | undefined;\n const direction =\n (query.direction as string)?.toLowerCase() === \"prev\" ? \"prev\" : \"next\";\n const orderBy = query.orderBy as string | undefined;\n const orderDir =\n (query.orderDir as string)?.toLowerCase() === \"desc\" ? \"desc\" : \"asc\";\n const selectStr = query.select as string | undefined;\n const select = selectStr\n ? selectStr.split(\",\").map((s) => s.trim())\n : undefined;\n\n // Parse includes (relation population)\n let includes:\n | (string | { relation: string; select?: string[] })[]\n | undefined;\n if (entry.allowedIncludes && query.includes) {\n const rawIncludes =\n typeof query.includes === \"string\"\n ? query.includes.split(\",\").map((s: string) => s.trim())\n : Array.isArray(query.includes)\n ? query.includes\n : [];\n includes = rawIncludes.filter(\n (inc: string) =>\n typeof inc === \"string\" && entry.allowedIncludes!.includes(inc),\n );\n if (includes?.length === 0) includes = undefined;\n }\n\n // Parse filters\n const filters = parseFilters(query, entry.filterableFields);\n ctxFilters = filters.map((f) => ({\n field: f.field,\n op: f.op,\n value: String(f.value ?? \"\"),\n }));\n if (orderBy) ctxSort = { field: orderBy, dir: orderDir };\n\n // Build query options\n const queryOptions: any = {\n pageSize,\n direction,\n };\n\n if (cursor) {\n try {\n const cursorObj =\n typeof cursor === \"string\" ? JSON.parse(cursor) : cursor;\n queryOptions.cursor = await deserializeCursor(entry, cursorObj);\n } catch {\n // Invalid cursor, ignore\n }\n }\n\n if (orderBy) {\n queryOptions.orderBy = [{ field: orderBy, direction: orderDir }];\n }\n\n if (filters.length > 0) {\n queryOptions.where = filters.map((f) => [f.field, f.op, f.value]);\n }\n\n if (select) {\n queryOptions.select = select as any;\n }\n\n if (includes) {\n queryOptions.include = includes as any;\n }\n\n // Execute query\n const result = await entry.repo.query.paginate(queryOptions);\n\n const responseData: ListResponseData = {\n items: result.data,\n hasNextPage: result.hasNextPage,\n hasPrevPage: result.hasPrevPage,\n nextCursor: serializeCursor(result.nextCursor),\n prevCursor: serializeCursor(result.prevCursor),\n };\n\n sendSuccess(res, responseData, {\n pageSize,\n hasMore: result.hasNextPage,\n });\n } catch (err) {\n sendQueryError(\n res,\n err,\n {\n ref: entry.repo.ref,\n path: entry.path,\n isGroup: !!entry.isGroup,\n filters: ctxFilters,\n sort: ctxSort,\n },\n \"Failed to fetch documents\",\n verbose,\n );\n }\n }\n\n // ── QUERY: POST /:repoName/query ────────────────────────────────────────\n // Advanced query endpoint supporting OR conditions, array filters, etc.\n async function handleQuery(req: any, res: any): Promise<void> {\n const params = req.params || {};\n const entry = getRepoEntry(params.repoName, res);\n if (!entry) return;\n\n // Captured for error handling (so the catch can build an index URL)\n let ctxFilters: { field: string; op: any; value: string }[] = [];\n let ctxSort: { field: string; dir: \"asc\" | \"desc\" } | undefined;\n\n try {\n const body: QueryRequestBody = req.body ?? {};\n const pageSize = Math.min(body.pageSize || entry.pageSize, 100);\n const direction = body.direction === \"prev\" ? \"prev\" : \"next\";\n\n // Capture context for index URL fallback\n if (body.where) {\n ctxFilters = body.where.map((w) => ({\n field: String(w[0]),\n op: w[1] as any,\n value: String(w[2] ?? \"\"),\n }));\n }\n if (body.orderBy && body.orderBy[0]) {\n ctxSort = {\n field: body.orderBy[0].field,\n dir: body.orderBy[0].direction === \"desc\" ? \"desc\" : \"asc\",\n };\n }\n\n // Build query options\n const queryOptions: any = {\n pageSize,\n direction,\n };\n\n // Cursor\n if (body.cursor) {\n try {\n const cursorObj =\n typeof body.cursor === \"string\"\n ? JSON.parse(body.cursor)\n : body.cursor;\n queryOptions.cursor = await deserializeCursor(entry, cursorObj);\n } catch {\n // Invalid cursor, ignore\n }\n }\n\n // Includes (relation population)\n if (entry.allowedIncludes && body.includes && body.includes.length > 0) {\n const validIncludes = body.includes.filter((inc) => {\n if (typeof inc === \"string\") {\n return entry.allowedIncludes!.includes(inc);\n }\n if (\n typeof inc === \"object\" &&\n inc !== null &&\n \"relation\" in inc &&\n typeof inc.relation === \"string\"\n ) {\n return entry.allowedIncludes!.includes(inc.relation);\n }\n return false;\n });\n if (validIncludes.length > 0) {\n queryOptions.include = validIncludes as any;\n }\n }\n\n // Where conditions (AND)\n if (body.where && body.where.length > 0) {\n // Validate filterable fields if configured\n if (entry.filterableFields) {\n const allowed = new Set(entry.filterableFields);\n const invalid = body.where.filter((w) => !allowed.has(w[0]));\n if (invalid.length > 0) {\n sendError(\n res,\n `Fields not filterable: ${invalid.map((w) => w[0]).join(\", \")}`,\n 400,\n );\n return;\n }\n }\n queryOptions.where = body.where;\n }\n\n // OR where conditions (simple)\n if (body.orWhere && body.orWhere.length > 0) {\n if (entry.filterableFields) {\n const allowed = new Set(entry.filterableFields);\n const invalid = body.orWhere.filter((w) => !allowed.has(w[0]));\n if (invalid.length > 0) {\n sendError(\n res,\n `Fields not filterable: ${invalid.map((w) => w[0]).join(\", \")}`,\n 400,\n );\n return;\n }\n }\n queryOptions.orWhere = body.orWhere;\n }\n\n // OR where groups (advanced)\n if (body.orWhereGroups && body.orWhereGroups.length > 0) {\n if (entry.filterableFields) {\n const allowed = new Set(entry.filterableFields);\n for (const group of body.orWhereGroups) {\n const invalid = group.filter((w) => !allowed.has(w[0]));\n if (invalid.length > 0) {\n sendError(\n res,\n `Fields not filterable: ${invalid.map((w) => w[0]).join(\", \")}`,\n 400,\n );\n return;\n }\n }\n }\n queryOptions.orWhereGroups = body.orWhereGroups;\n }\n\n // Order by\n if (body.orderBy && body.orderBy.length > 0) {\n queryOptions.orderBy = body.orderBy;\n }\n\n // Select\n if (body.select && body.select.length > 0) {\n queryOptions.select = body.select;\n }\n\n // Execute query\n const result = await entry.repo.query.paginate(queryOptions);\n\n const responseData: ListResponseData = {\n items: result.data,\n hasNextPage: result.hasNextPage,\n hasPrevPage: result.hasPrevPage,\n nextCursor: serializeCursor(result.nextCursor),\n prevCursor: serializeCursor(result.prevCursor),\n };\n\n sendSuccess(res, responseData, {\n pageSize,\n hasMore: result.hasNextPage,\n });\n } catch (err) {\n sendQueryError(\n res,\n err,\n {\n ref: entry.repo.ref,\n path: entry.path,\n isGroup: !!entry.isGroup,\n filters: ctxFilters,\n sort: ctxSort,\n },\n \"Failed to query documents\",\n verbose,\n );\n }\n }\n\n // ── GET: GET /:repoName/:id ─────────────────────────────────────────────\n async function handleGet(req: any, res: any): Promise<void> {\n const params = req.params || {};\n const entry = getRepoEntry(params.repoName, res);\n if (!entry) return;\n\n const id = params.id;\n if (!id) {\n sendError(res, \"Document ID required\", 400);\n return;\n }\n\n try {\n const doc = await fetchDocById(entry, id);\n\n if (!doc) {\n sendError(res, \"Document not found\", 404);\n return;\n }\n\n sendSuccess(res, doc);\n } catch (err) {\n sendQueryError(\n res,\n err,\n {\n ref: entry.repo.ref,\n path: entry.path,\n isGroup: !!entry.isGroup,\n filters: [{ field: entry.documentKey, op: \"==\", value: id }],\n },\n \"Failed to fetch document\",\n verbose,\n );\n }\n }\n\n // ── CREATE: POST /:repoName ─────────────────────────────────────────────\n async function handleCreate(req: any, res: any): Promise<void> {\n const params = req.params || {};\n const entry = getRepoEntry(params.repoName, res);\n if (!entry) return;\n\n try {\n const body = req.body ?? {};\n\n // Validate against schema\n const validation = validateData(\n entry.schema,\n body,\n entry.createFields,\n false,\n entry.systemKeys,\n );\n if (!validation.success) {\n sendError(res, validation.error, 400);\n return;\n }\n\n // Custom validation\n if (entry.validate) {\n const customError = await entry.validate(validation.data, \"create\");\n if (customError) {\n sendError(res, customError, 400);\n return;\n }\n }\n\n // Create document\n let created: any;\n if (entry.isGroup && entry.parentKeys && entry.parentKeys.length > 0) {\n // Collection-group repos cannot use create(); use set() with parent path args.\n const data: Record<string, any> = { ...validation.data };\n // set() doesn't auto-set createdKey, so inject it here\n if (entry.createdKey) {\n data[entry.createdKey] = new Date();\n }\n const missingKeys = entry.parentKeys.filter((k) => !data[k]);\n if (missingKeys.length > 0) {\n sendError(\n res,\n `Missing parent key(s) for subcollection create: ${missingKeys.join(\", \")}`,\n 400,\n );\n return;\n }\n const parentIds = entry.parentKeys.map((k) => data[k] as string);\n const docId =\n data[entry.documentKey] || generateFirestoreId();\n created = await entry.repo.set(...parentIds, docId, data);\n } else {\n created = await entry.repo.create(validation.data as any);\n }\n\n sendSuccess(res, created, undefined, 201);\n } catch (err) {\n const message =\n verbose && err instanceof Error\n ? err.message\n : \"Failed to create document\";\n sendError(res, message, 500);\n }\n }\n\n // ── UPDATE: PUT/PATCH /:repoName/:id ────────────────────────────────────\n async function handleUpdate(\n req: any,\n res: any,\n partial: boolean,\n ): Promise<void> {\n const params = req.params || {};\n const entry = getRepoEntry(params.repoName, res);\n if (!entry) return;\n\n const id = params.id;\n if (!id) {\n sendError(res, \"Document ID required\", 400);\n return;\n }\n\n try {\n const body = req.body ?? {};\n\n // Validate against schema\n const validation = validateData(\n entry.schema,\n body,\n entry.mutableFields,\n partial,\n entry.systemKeys,\n );\n if (!validation.success) {\n sendError(res, validation.error, 400);\n return;\n }\n\n // Custom validation\n if (entry.validate) {\n const customError = await entry.validate(validation.data, \"update\");\n if (customError) {\n sendError(res, customError, 400);\n return;\n }\n }\n\n // Update document — fetch first to get path args for subcollections\n const existingDoc = await fetchDocById(entry, id);\n const pathArgs =\n (existingDoc && extractPathArgs(existingDoc, entry.pathKey)) ?? [id];\n const updated = await entry.repo.update(\n ...pathArgs,\n validation.data as any,\n );\n\n sendSuccess(res, updated);\n } catch (err) {\n const message =\n verbose && err instanceof Error\n ? err.message\n : \"Failed to update document\";\n sendError(res, message, 500);\n }\n }\n\n // ── DELETE: DELETE /:repoName/:id ───────────────────────────────────────\n async function handleDelete(req: any, res: any): Promise<void> {\n const params = req.params || {};\n const entry = getRepoEntry(params.repoName, res);\n if (!entry) return;\n\n if (!entry.allowDelete) {\n sendError(res, \"Delete not allowed for this repository\", 403);\n return;\n }\n\n const id = params.id;\n if (!id) {\n sendError(res, \"Document ID required\", 400);\n return;\n }\n\n try {\n // Fetch first to get path args for subcollections\n const doc = await fetchDocById(entry, id);\n const pathArgs =\n (doc && extractPathArgs(doc, entry.pathKey)) ?? [id];\n await entry.repo.delete(...pathArgs);\n sendSuccess(res, { deleted: true });\n } catch (err) {\n const message =\n verbose && err instanceof Error\n ? err.message\n : \"Failed to delete document\";\n sendError(res, message, 500);\n }\n }\n\n // ── OPTIONS: for CORS preflight ─────────────────────────────────────────\n function handleOptions(req: any, res: any): void {\n res\n .status(204)\n .set(\n \"Access-Control-Allow-Methods\",\n \"GET, POST, PUT, PATCH, DELETE, OPTIONS\",\n )\n .set(\"Access-Control-Allow-Headers\", \"Content-Type, Authorization\")\n .set(\"Access-Control-Max-Age\", \"86400\")\n .send(\"\");\n }\n\n return {\n handleList,\n handleQuery,\n handleGet,\n handleCreate,\n handleUpdate,\n handleDelete,\n handleOptions,\n };\n}\n","/**\n * OpenAPI 3.1 specification generator for the CRUD server.\n *\n * Introspects each `CrudRepoEntry` and uses Zod 4's native `z.toJSONSchema()`\n * to produce a fully typed OpenAPI document ready for Scalar UI or codegen.\n *\n * @module servers/crud/openapi\n */\n\nimport { z } from \"zod\";\nimport type { CrudRepoEntry, CrudRepoRegistry, OpenAPISpecOptions } from \"./types\";\n\nexport type { OpenAPISpecOptions };\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/** Minimal subset of an OpenAPI 3.1 document we produce. */\nexport interface OpenAPIDocument {\n openapi: \"3.1.0\";\n info: OpenAPIInfo;\n servers?: { url: string; description?: string }[];\n paths: Record<string, Record<string, OpenAPIOperation>>;\n components: {\n schemas: Record<string, Record<string, unknown>>;\n securitySchemes?: Record<string, Record<string, unknown>>;\n };\n security?: Record<string, string[]>[];\n tags?: { name: string; description?: string }[];\n}\n\nexport interface OpenAPIInfo {\n title: string;\n version: string;\n description?: string;\n}\n\ninterface OpenAPIOperation {\n operationId: string;\n summary: string;\n tags: string[];\n parameters?: Record<string, unknown>[];\n requestBody?: Record<string, unknown>;\n responses: Record<string, Record<string, unknown>>;\n security?: Record<string, string[]>[];\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Convert a Zod schema to a JSON Schema object suitable for OpenAPI 3.1.\n *\n * Uses `unrepresentable: \"any\"` so that types Zod can't natively serialize\n * (e.g. `z.date()`, `z.bigint()`, custom classes — common with Firestore\n * Timestamps stored as `Date`) don't throw and collapse the whole schema to\n * a bare `{ type: \"object\" }`. We additionally override a few well-known\n * cases to a sensible OpenAPI representation.\n */\nfunction zodToJsonSchema(schema: z.ZodType): Record<string, unknown> {\n try {\n return z.toJSONSchema(schema, {\n target: \"openapi-3.1\",\n unrepresentable: \"any\",\n override: (ctx) => {\n const def: any = (ctx.zodSchema as any)?._zod?.def;\n if (!def) return;\n if (def.type === \"date\") {\n (ctx.jsonSchema as any).type = \"string\";\n (ctx.jsonSchema as any).format = \"date-time\";\n } else if (def.type === \"bigint\") {\n (ctx.jsonSchema as any).type = \"string\";\n (ctx.jsonSchema as any).format = \"int64\";\n }\n },\n }) as Record<string, unknown>;\n } catch (err) {\n if (typeof console !== \"undefined\" && console.warn) {\n console.warn(\n \"[generateOpenAPISpec] Failed to convert Zod schema to JSON Schema; falling back to {type:object}.\",\n err,\n );\n }\n return { type: \"object\" };\n }\n}\n\n/** Wraps a JSON Schema in a `#/components/schemas/<name>` $ref. */\nfunction schemaRef(name: string): Record<string, unknown> {\n return { $ref: `#/components/schemas/${name}` };\n}\n\n/** Standard error response schema. */\nfunction errorResponse(description: string): Record<string, unknown> {\n return {\n description,\n content: {\n \"application/json\": {\n schema: schemaRef(\"ErrorResponse\"),\n },\n },\n };\n}\n\n/** Standard success response wrapping data. */\nfunction successResponse(\n description: string,\n dataSchema: Record<string, unknown>,\n): Record<string, unknown> {\n return {\n description,\n content: {\n \"application/json\": {\n schema: {\n type: \"object\",\n properties: {\n success: { type: \"boolean\", enum: [true] },\n data: dataSchema,\n },\n required: [\"success\", \"data\"],\n },\n },\n },\n };\n}\n\n/** Build list response with pagination metadata. */\nfunction listResponse(\n itemSchema: Record<string, unknown>,\n): Record<string, unknown> {\n return {\n description: \"Paginated list of documents\",\n content: {\n \"application/json\": {\n schema: {\n type: \"object\",\n properties: {\n success: { type: \"boolean\", enum: [true] },\n data: {\n type: \"object\",\n properties: {\n items: { type: \"array\", items: itemSchema },\n nextCursor: {\n oneOf: [{ type: \"object\" }, { type: \"null\" }],\n },\n prevCursor: {\n oneOf: [{ type: \"object\" }, { type: \"null\" }],\n },\n hasNextPage: { type: \"boolean\" },\n hasPrevPage: { type: \"boolean\" },\n },\n required: [\"items\", \"hasNextPage\", \"hasPrevPage\"],\n },\n meta: {\n type: \"object\",\n properties: {\n pageSize: { type: \"integer\" },\n hasMore: { type: \"boolean\" },\n cursor: {\n oneOf: [{ type: \"string\" }, { type: \"null\" }],\n },\n },\n },\n },\n required: [\"success\", \"data\"],\n },\n },\n },\n };\n}\n\n// ---------------------------------------------------------------------------\n// Pagination / filter query parameters (shared across list endpoints)\n// ---------------------------------------------------------------------------\n\nfunction paginationParams(entry: CrudRepoEntry): Record<string, unknown>[] {\n return [\n {\n name: \"pageSize\",\n in: \"query\",\n schema: { type: \"integer\", default: entry.pageSize, maximum: 100 },\n description: \"Number of items per page\",\n },\n {\n name: \"cursor\",\n in: \"query\",\n schema: { type: \"string\" },\n description: \"Base64 pagination cursor\",\n },\n {\n name: \"orderBy\",\n in: \"query\",\n schema: { type: \"string\" },\n description: \"Field name to order by\",\n },\n {\n name: \"orderDir\",\n in: \"query\",\n schema: { type: \"string\", enum: [\"asc\", \"desc\"] },\n description: \"Order direction\",\n },\n {\n name: \"select\",\n in: \"query\",\n schema: { type: \"string\" },\n description: \"Comma-separated list of fields to return\",\n },\n ];\n}\n\nfunction filterParams(entry: CrudRepoEntry): Record<string, unknown>[] {\n const fields = entry.filterableFields ?? Object.keys(entry.schema.shape);\n const ops = [\"eq\", \"ne\", \"lt\", \"lte\", \"gt\", \"gte\", \"in\", \"nin\", \"contains\"];\n\n const params: Record<string, unknown>[] = [];\n for (const field of fields) {\n // Direct equality filter: ?field=value\n params.push({\n name: field,\n in: \"query\",\n schema: { type: \"string\" },\n description: `Filter by ${field} (equality)`,\n });\n // Operator filters: ?field__op=value\n for (const op of ops) {\n params.push({\n name: `${field}__${op}`,\n in: \"query\",\n schema: { type: \"string\" },\n description: `Filter ${field} with operator ${op}`,\n });\n }\n }\n return params;\n}\n\n// ---------------------------------------------------------------------------\n// Query body schema (POST /query)\n// ---------------------------------------------------------------------------\n\nfunction queryBodySchema(): Record<string, unknown> {\n return {\n type: \"object\",\n properties: {\n where: {\n type: \"array\",\n items: {\n type: \"array\",\n items: {},\n minItems: 3,\n maxItems: 3,\n },\n description: \"AND conditions: [field, operator, value][]\",\n },\n orWhere: {\n type: \"array\",\n items: {\n type: \"array\",\n items: {},\n minItems: 3,\n maxItems: 3,\n },\n description: \"Simple OR conditions (each independently OR'd)\",\n },\n orWhereGroups: {\n type: \"array\",\n items: {\n type: \"array\",\n items: {\n type: \"array\",\n items: {},\n minItems: 3,\n maxItems: 3,\n },\n },\n description: \"Advanced OR groups (AND within, OR across groups)\",\n },\n orderBy: {\n type: \"array\",\n items: {\n type: \"object\",\n properties: {\n field: { type: \"string\" },\n direction: { type: \"string\", enum: [\"asc\", \"desc\"] },\n },\n required: [\"field\"],\n },\n },\n select: {\n type: \"array\",\n items: { type: \"string\" },\n description: \"Fields to select (projection)\",\n },\n pageSize: {\n type: \"integer\",\n maximum: 100,\n description: \"Number of items per page\",\n },\n cursor: {\n oneOf: [{ type: \"string\" }, { type: \"object\" }],\n description: \"Pagination cursor\",\n },\n direction: {\n type: \"string\",\n enum: [\"next\", \"prev\"],\n description: \"Pagination direction\",\n },\n includes: {\n type: \"array\",\n items: {\n oneOf: [\n { type: \"string\" },\n {\n type: \"object\",\n properties: {\n relation: { type: \"string\" },\n select: { type: \"array\", items: { type: \"string\" } },\n },\n required: [\"relation\"],\n },\n ],\n },\n description: \"Relations to include (populate)\",\n },\n },\n };\n}\n\n// ---------------------------------------------------------------------------\n// Path generation per repo entry\n// ---------------------------------------------------------------------------\n\nfunction buildPathsForEntry(\n entry: CrudRepoEntry,\n base: string,\n modelSchemaName: string,\n createSchemaName: string | null,\n updateSchemaName: string | null,\n): Record<string, Record<string, OpenAPIOperation>> {\n const paths: Record<string, Record<string, OpenAPIOperation>> = {};\n const tag = entry.name;\n const collectionPath = `${base}/${entry.name}`;\n const documentPath = `${collectionPath}/{${entry.documentKey}}`;\n\n const idParam = {\n name: entry.documentKey,\n in: \"path\",\n required: true,\n schema: { type: \"string\" },\n description: `Unique document identifier`,\n };\n\n // ── GET /:repo → list ──────────────────────────────────────────────\n paths[collectionPath] = {\n get: {\n operationId: `list${capitalize(entry.name)}`,\n summary: `List ${entry.name} (paginated)`,\n tags: [tag],\n parameters: [...paginationParams(entry), ...filterParams(entry)],\n responses: {\n \"200\": listResponse(schemaRef(modelSchemaName)),\n \"500\": errorResponse(\"Internal server error\"),\n },\n },\n // ── POST /:repo → create ────────────────────────────────────────\n post: {\n operationId: `create${capitalize(entry.name)}`,\n summary: `Create a ${singularize(entry.name)}`,\n tags: [tag],\n requestBody: {\n required: true,\n content: {\n \"application/json\": {\n schema: schemaRef(createSchemaName ?? modelSchemaName),\n },\n },\n },\n responses: {\n \"201\": successResponse(\"Document created\", schemaRef(modelSchemaName)),\n \"400\": errorResponse(\"Validation error\"),\n \"500\": errorResponse(\"Internal server error\"),\n },\n },\n };\n\n // ── POST /:repo/query → advanced query ────────────────────────────\n paths[`${collectionPath}/query`] = {\n post: {\n operationId: `query${capitalize(entry.name)}`,\n summary: `Query ${entry.name} with advanced filters`,\n tags: [tag],\n requestBody: {\n required: true,\n content: {\n \"application/json\": {\n schema: schemaRef(\"QueryRequestBody\"),\n },\n },\n },\n responses: {\n \"200\": listResponse(schemaRef(modelSchemaName)),\n \"400\": errorResponse(\"Invalid query\"),\n \"500\": errorResponse(\"Internal server error\"),\n },\n },\n };\n\n // ── Single-document paths ────────────────────────────────────────\n const docOps: Record<string, OpenAPIOperation> = {};\n\n // GET /:repo/:id\n docOps.get = {\n operationId: `get${capitalize(singularize(entry.name))}`,\n summary: `Get a single ${singularize(entry.name)}`,\n tags: [tag],\n parameters: [idParam],\n responses: {\n \"200\": successResponse(\"Document found\", schemaRef(modelSchemaName)),\n \"404\": errorResponse(\"Document not found\"),\n \"500\": errorResponse(\"Internal server error\"),\n },\n };\n\n // PUT /:repo/:id (full update)\n docOps.put = {\n operationId: `update${capitalize(singularize(entry.name))}`,\n summary: `Update a ${singularize(entry.name)} (full replace)`,\n tags: [tag],\n parameters: [idParam],\n requestBody: {\n required: true,\n content: {\n \"application/json\": {\n schema: schemaRef(updateSchemaName ?? modelSchemaName),\n },\n },\n },\n responses: {\n \"200\": successResponse(\"Document updated\", schemaRef(modelSchemaName)),\n \"400\": errorResponse(\"Validation error\"),\n \"404\": errorResponse(\"Document not found\"),\n \"500\": errorResponse(\"Internal server error\"),\n },\n };\n\n // PATCH /:repo/:id (partial update)\n docOps.patch = {\n operationId: `patch${capitalize(singularize(entry.name))}`,\n summary: `Partially update a ${singularize(entry.name)}`,\n tags: [tag],\n parameters: [idParam],\n requestBody: {\n required: true,\n content: {\n \"application/json\": {\n schema: {\n allOf: [schemaRef(updateSchemaName ?? modelSchemaName)],\n description: \"All fields are optional for partial updates\",\n },\n },\n },\n },\n responses: {\n \"200\": successResponse(\"Document patched\", schemaRef(modelSchemaName)),\n \"400\": errorResponse(\"Validation error\"),\n \"404\": errorResponse(\"Document not found\"),\n \"500\": errorResponse(\"Internal server error\"),\n },\n };\n\n // DELETE /:repo/:id (only if allowDelete)\n if (entry.allowDelete) {\n docOps.delete = {\n operationId: `delete${capitalize(singularize(entry.name))}`,\n summary: `Delete a ${singularize(entry.name)}`,\n tags: [tag],\n parameters: [idParam],\n responses: {\n \"200\": successResponse(\"Document deleted\", {\n type: \"object\",\n properties: { id: { type: \"string\" } },\n }),\n \"404\": errorResponse(\"Document not found\"),\n \"500\": errorResponse(\"Internal server error\"),\n },\n };\n }\n\n paths[documentPath] = docOps;\n\n return paths;\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Generate a full OpenAPI 3.1 specification from a `CrudRepoRegistry`.\n *\n * Uses Zod 4's native `z.toJSONSchema()` to convert each repo's schema\n * into a JSON Schema component, then assembles paths for the standard\n * CRUD endpoints.\n *\n * @example\n * ```ts\n * import { generateOpenAPISpec } from \"@lpdjs/firestore-repo-service/servers/crud\";\n *\n * const spec = generateOpenAPISpec(registry, \"/api\", {\n * title: \"My API\",\n * version: \"1.0.0\",\n * servers: [{ url: \"https://my-api.example.com\" }],\n * auth: \"bearer\",\n * });\n *\n * // Write to file\n * fs.writeFileSync(\"openapi.json\", JSON.stringify(spec, null, 2));\n * ```\n */\nexport function generateOpenAPISpec(\n registry: CrudRepoRegistry,\n basePath: string,\n options: OpenAPISpecOptions = {},\n): OpenAPIDocument {\n const {\n title = \"CRUD API\",\n version = \"1.0.0\",\n description,\n servers,\n auth = false,\n } = options;\n\n const base = basePath === \"/\" ? \"\" : basePath.replace(/\\/$/, \"\");\n\n // ── Components: schemas ───────────────────────────────────────────\n const schemas: Record<string, Record<string, unknown>> = {};\n const allPaths: Record<string, Record<string, OpenAPIOperation>> = {};\n const tags: { name: string; description?: string }[] = [];\n\n // Shared schemas\n schemas[\"ErrorResponse\"] = {\n type: \"object\",\n properties: {\n success: { type: \"boolean\", enum: [false] },\n error: { type: \"string\" },\n },\n required: [\"success\", \"error\"],\n };\n\n schemas[\"QueryRequestBody\"] = queryBodySchema();\n\n // Per-repo schemas & paths\n for (const [name, entry] of Object.entries(registry)) {\n const modelName = capitalize(singularize(name));\n const createName = `${modelName}Create`;\n const updateName = `${modelName}Update`;\n\n // Full model schema\n schemas[modelName] = zodToJsonSchema(entry.schema);\n\n // Helper: build a filtered shape (respects systemKeys + field list)\n const buildShape = (\n fieldList: string[] | undefined,\n ): Record<string, z.ZodType> => {\n const source =\n fieldList && fieldList.length > 0\n ? fieldList\n : Object.keys(entry.schema.shape);\n const shape: Record<string, z.ZodType> = {};\n for (const f of source) {\n const top = f.split(\".\")[0];\n if (top && entry.schema.shape[top] && !entry.systemKeys.includes(top)) {\n shape[top] = entry.schema.shape[top];\n }\n }\n return shape;\n };\n\n // Create schema\n let createSchemaName: string | null = null;\n const createShape = buildShape(entry.createFields);\n if (Object.keys(createShape).length > 0) {\n schemas[createName] = zodToJsonSchema(z.object(createShape));\n createSchemaName = createName;\n }\n\n // Update schema\n let updateSchemaName: string | null = null;\n const updateShape = buildShape(entry.mutableFields);\n if (Object.keys(updateShape).length > 0) {\n schemas[updateName] = zodToJsonSchema(z.object(updateShape));\n updateSchemaName = updateName;\n }\n\n // Build paths\n const entryPaths = buildPathsForEntry(\n entry,\n base,\n modelName,\n createSchemaName,\n updateSchemaName,\n );\n Object.assign(allPaths, entryPaths);\n\n // Tag\n tags.push({\n name,\n description: `Operations on ${name} (collection: ${entry.path})`,\n });\n }\n\n // ── Security ──────────────────────────────────────────────────────\n const securitySchemes: Record<string, Record<string, unknown>> = {};\n let security: Record<string, string[]>[] | undefined;\n\n if (auth === \"basic\") {\n securitySchemes[\"basicAuth\"] = {\n type: \"http\",\n scheme: \"basic\",\n };\n security = [{ basicAuth: [] }];\n } else if (auth === \"bearer\") {\n securitySchemes[\"bearerAuth\"] = {\n type: \"http\",\n scheme: \"bearer\",\n bearerFormat: \"JWT\",\n };\n security = [{ bearerAuth: [] }];\n }\n\n // ── Assemble ──────────────────────────────────────────────────────\n const doc: OpenAPIDocument = {\n openapi: \"3.1.0\",\n info: {\n title,\n version,\n ...(description ? { description } : {}),\n },\n ...(servers && servers.length > 0 ? { servers } : {}),\n paths: allPaths,\n components: {\n schemas,\n ...(Object.keys(securitySchemes).length > 0 ? { securitySchemes } : {}),\n },\n ...(security ? { security } : {}),\n tags,\n };\n\n return doc;\n}\n\n// ---------------------------------------------------------------------------\n// Utility\n// ---------------------------------------------------------------------------\n\nfunction capitalize(s: string): string {\n return s.charAt(0).toUpperCase() + s.slice(1);\n}\n\n/** Naive singularize: strip trailing 's' for display. */\nfunction singularize(s: string): string {\n if (s.endsWith(\"ies\")) return s.slice(0, -3) + \"y\";\n if (s.endsWith(\"ses\") || s.endsWith(\"xes\") || s.endsWith(\"zes\"))\n return s.slice(0, -2);\n if (s.endsWith(\"s\") && !s.endsWith(\"ss\")) return s.slice(0, -1);\n return s;\n}\n","/**\n * @module servers/crud\n *\n * Creates a REST API server for CRUD operations on Firestore repositories.\n *\n * Features:\n * - RESTful endpoints for List, Get, Create, Update, Delete\n * - Request validation using Zod schemas\n * - Cursor-based pagination\n * - Query filtering with operators (eq, ne, lt, gt, in, etc.)\n * - Field selection\n * - CORS support\n * - Configurable auth (Basic Auth or custom middleware)\n *\n * @example\n * ```ts\n * import * as functions from \"firebase-functions\";\n * import { z } from \"zod\";\n * import { createCrudServer } from \"@lpdjs/firestore-repo-service/servers/crud\";\n *\n * const postSchema = z.object({\n * title: z.string().min(1),\n * content: z.string(),\n * status: z.enum([\"draft\", \"published\"]),\n * authorId: z.string(),\n * });\n *\n * export const api = functions.https.onRequest(\n * createCrudServer({\n * basePath: \"/api\",\n * repos: {\n * posts: {\n * repo: repos.posts,\n * schema: postSchema,\n * path: \"posts\",\n * fieldsConfig: {\n * status: [\"filterable\"],\n * authorId: [\"filterable\"],\n * },\n * allowDelete: true,\n * },\n * },\n * })\n * );\n * ```\n *\n * ## API Endpoints\n *\n * | Method | Path | Description |\n * |--------|-------------------|--------------------------|\n * | GET | /:repo | List documents (paginated) |\n * | GET | /:repo/:id | Get single document |\n * | POST | /:repo | Create document |\n * | PUT | /:repo/:id | Update document (full) |\n * | PATCH | /:repo/:id | Update document (partial)|\n * | DELETE | /:repo/:id | Delete document |\n *\n * ## Query Parameters (GET list)\n *\n * | Param | Description |\n * |------------|------------------------------------------|\n * | pageSize | Number of items per page (max 100) |\n * | cursor | Base64 pagination cursor |\n * | orderBy | Field to order by |\n * | orderDir | Order direction (asc/desc) |\n * | select | Comma-separated fields to return |\n * | field | Filter by field (field=value) |\n * | field__op | Filter with operator (field__gt=10) |\n *\n * ## Filter Operators\n *\n * | Suffix | Firestore Op | Example |\n * |-------------|-------------------|-----------------------|\n * | (none) | == | status=active |\n * | __eq | == | status__eq=active |\n * | __ne | != | status__ne=draft |\n * | __lt | < | age__lt=18 |\n * | __lte | <= | age__lte=18 |\n * | __gt | > | age__gt=18 |\n * | __gte | >= | age__gte=18 |\n * | __in | in | status__in=a,b,c |\n * | __nin | not-in | status__nin=x,y |\n * | __contains | array-contains | tags__contains=news |\n */\n\nimport { MiniRouter } from \"../admin/router\";\nimport type { HttpsOptions } from \"firebase-functions/v2/https\";\nimport type { HttpRequest, HttpResponse } from \"../http-types\";\nimport type { ConfiguredRepository } from \"../../repositories/types\";\nimport { createCrudHandlers } from \"./handlers\";\nimport { generateOpenAPISpec, type OpenAPIDocument } from \"./openapi\";\nimport type {\n CrudRepoEntry,\n CrudRepoRegistry,\n CrudServerOptions,\n} from \"./types\";\n\n// ---------------------------------------------------------------------------\n// Scalar API docs HTML template\n// ---------------------------------------------------------------------------\n\n/** Returns a self-contained HTML page using Scalar to render the spec. */\nfunction scalarDocsHtml(title: string, specUrl: string): string {\n return `<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"utf-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n <title>${title}</title>\n</head>\n<body>\n <script id=\"api-reference\" data-url=\"${specUrl}\"></script>\n <script src=\"https://cdn.jsdelivr.net/npm/@scalar/api-reference\"></script>\n</body>\n</html>`;\n}\n\n/**\n * Compute the URL prefix for links / spec URLs.\n * In the Firebase emulator the /{project}/{region}/{functionTarget} prefix\n * is visible in URLs but stripped before the handler receives `req.url`.\n * In production Firebase proxy strips it automatically.\n */\nfunction getLinkBase(req: any, staticBasePath: string): string {\n const base = staticBasePath === \"/\" ? \"\" : staticBasePath.replace(/\\/$/, \"\");\n\n if (process.env[\"FUNCTIONS_EMULATOR\"] === \"true\") {\n const project =\n process.env[\"GCLOUD_PROJECT\"] ??\n process.env[\"GOOGLE_CLOUD_PROJECT\"] ??\n \"demo-project\";\n const region = process.env[\"FUNCTION_REGION\"] ?? \"us-central1\";\n const target = process.env[\"FUNCTION_TARGET\"] ?? \"\";\n return `/${project}/${region}/${target}${base}`;\n }\n\n // Cloud Functions v2: K_SERVICE = function name = URL path prefix.\n // Only add it when accessed via cloudfunctions.net (not custom domains).\n // Cloud Run (Gen 2) lowercases service names, but K_SERVICE may still\n // carry the original mixed-case export name — normalise to lowercase\n // so that generated links match the canonical URL.\n const service = process.env[\"K_SERVICE\"];\n const host: string = req?.hostname ?? req?.headers?.[\"host\"] ?? \"\";\n if (service && host.includes(\"cloudfunctions.net\")) {\n return `/${service.toLowerCase()}${base}`;\n }\n\n return base;\n}\n\n// ---------------------------------------------------------------------------\n// Body parser\n// ---------------------------------------------------------------------------\n\n/** Eagerly reads the raw request body as a string */\nasync function readRawBody(req: HttpRequest): Promise<string> {\n if (typeof (req as any).rawBody === \"string\")\n return (req as any).rawBody as string;\n if (Buffer.isBuffer((req as any).rawBody))\n return ((req as any).rawBody as Buffer).toString(\"utf8\");\n return \"\";\n}\n\n// ---------------------------------------------------------------------------\n// Factory\n// ---------------------------------------------------------------------------\n\n/**\n * Creates an Express-compatible request handler for a REST CRUD API.\n *\n * @template TRepos - Shape of the repos map (inferred automatically)\n * @param options - CRUD server configuration\n * @returns Express-compatible request handler for Firebase Functions\n *\n * @example\n * ```typescript\n * // Basic CRUD server\n * import { onRequest } from \"firebase-functions/https\";\n * import { createCrudServer } from \"@lpdjs/firestore-repo-service/servers/crud\";\n *\n * export const api = onRequest(\n * createCrudServer({\n * basePath: \"/api\",\n * repos: {\n * users: {\n * repo: repos.users,\n * path: \"users\",\n * fieldsConfig: {\n * name: [\"create\", \"mutable\"],\n * email: [\"create\", \"mutable\", \"filterable\"],\n * isActive: [\"filterable\"],\n * },\n * allowDelete: false,\n * },\n * posts: {\n * repo: repos.posts,\n * path: \"posts\",\n * fieldsConfig: {\n * status: [\"filterable\"],\n * userId: [\"filterable\"],\n * },\n * allowDelete: true,\n * },\n * },\n * })\n * );\n *\n * // With authentication\n * export const api = onRequest(\n * createCrudServer({\n * basePath: \"/api\",\n * auth: {\n * type: \"basic\",\n * username: \"api\",\n * password: process.env.API_PASSWORD!,\n * },\n * repos: { ... },\n * })\n * );\n *\n * // With custom auth middleware\n * export const api = onRequest(\n * createCrudServer({\n * auth: async (req, res, next) => {\n * const token = req.headers?.authorization?.replace(\"Bearer \", \"\");\n * if (!token || !(await verifyToken(token))) {\n * res.status(401).json({ success: false, error: \"Unauthorized\" });\n * return;\n * }\n * next();\n * },\n * repos: { ... },\n * })\n * );\n *\n * // With custom validation\n * export const api = onRequest(\n * createCrudServer({\n * repos: {\n * posts: {\n * repo: repos.posts,\n * path: \"posts\",\n * validate: async (data, operation) => {\n * if (operation === \"create\" && !data.title) {\n * return \"Title is required\";\n * }\n * return undefined;\n * },\n * },\n * },\n * })\n * );\n * ```\n */\nexport function createCrudServer<\n TRepos extends Record<string, ConfiguredRepository<any>>,\n>(\n options: CrudServerOptions<TRepos>,\n): ((req: any, res: any) => Promise<void>) & { spec: () => OpenAPIDocument; httpsOptions?: HttpsOptions } {\n const {\n basePath = \"/\",\n repos,\n parseBody = true,\n auth,\n middleware: extraMiddleware = [],\n verbose = false,\n httpsOptions,\n } = options;\n\n // Normalise basePath: no trailing slash\n const base = basePath === \"/\" ? \"\" : basePath.replace(/\\/$/, \"\");\n\n // Build the registry\n const registry: CrudRepoRegistry = {};\n for (const [name, cfg] of Object.entries(repos)) {\n // Schema resolution: explicit cfg.schema > embedded in repo (createRepositoryConfig(schema))\n const resolvedSchema = cfg.schema ?? (cfg.repo as any).schema ?? null;\n if (!resolvedSchema) {\n throw new Error(\n `[createCrudServer] Repository \"${name}\" has no Zod schema. ` +\n `Either use createRepositoryConfig(schema)(config) or pass schema: explicitly.`,\n );\n }\n\n // Resolve fieldsConfig → separate arrays for runtime\n let filterableFields: string[] | undefined;\n let mutableFields: string[] | undefined;\n let createFields: string[] | undefined;\n if (cfg.fieldsConfig) {\n const fc = cfg.fieldsConfig as Record<string, readonly string[]>;\n filterableFields = [];\n mutableFields = [];\n createFields = [];\n for (const [field, roles] of Object.entries(fc)) {\n for (const role of roles) {\n if (role === \"filterable\") filterableFields.push(field);\n else if (role === \"mutable\") mutableFields.push(field);\n else if (role === \"create\") createFields.push(field);\n }\n }\n if (filterableFields.length === 0) filterableFields = undefined;\n if (mutableFields.length === 0) mutableFields = undefined;\n if (createFields.length === 0) createFields = undefined;\n }\n\n // For collection-group repos, ensure parentKeys are included in createFields\n // so the validation accepts them in the request body.\n const parentKeys = (() => {\n const pk = (cfg.repo as any)._parentKeys as string[] | undefined;\n return pk && pk.length > 0 ? pk : undefined;\n })();\n if (parentKeys && createFields) {\n for (const pk of parentKeys) {\n if (!createFields.includes(pk)) createFields.push(pk);\n }\n }\n\n const entry: CrudRepoEntry = {\n name,\n path: cfg.path,\n repo: cfg.repo,\n schema: resolvedSchema,\n systemKeys: (cfg.repo as any)._systemKeys ?? [cfg.documentKey ?? \"docId\"],\n documentKey: cfg.documentKey ?? \"docId\",\n pathKey: (cfg.repo as any)._pathKey ?? undefined,\n isGroup: !!(cfg.repo as any)._isGroup,\n parentKeys,\n createdKey: (cfg.repo as any)._createdKey ?? undefined,\n pageSize: cfg.pageSize ?? 25,\n filterableFields,\n mutableFields,\n createFields,\n allowDelete: cfg.allowDelete ?? false,\n allowedIncludes: cfg.allowedIncludes as string[] | undefined,\n validate: cfg.validate as CrudRepoEntry[\"validate\"],\n };\n\n registry[name] = entry;\n }\n\n const handlers = createCrudHandlers(registry, base, verbose);\n\n // ── OpenAPI spec (cached) ─────────────────────────────────────────────\n const openapi = options.openapi;\n const openapiOpts = openapi && typeof openapi === \"object\" ? openapi : {};\n let _specCache: OpenAPIDocument | null = null;\n function getSpec(): OpenAPIDocument {\n if (!_specCache) {\n const authType =\n auth && typeof auth !== \"function\"\n ? (\"basic\" as const)\n : auth\n ? (\"bearer\" as const)\n : false;\n _specCache = generateOpenAPISpec(registry, base, {\n ...openapiOpts,\n auth: openapiOpts.auth ?? authType,\n });\n }\n return _specCache;\n }\n\n // ── Router ─────────────────────────────────────────────────────────────\n const router = new MiniRouter();\n\n // ── CORS middleware ─────────────────────────────────────────────────────\n router.use((req, res, next) => {\n res.set(\"Access-Control-Allow-Origin\", \"*\");\n res.set(\"Access-Control-Allow-Credentials\", \"true\");\n next();\n });\n\n // ── 1. Body-parsing middleware ──────────────────────────────────────────\n if (parseBody) {\n router.use(async (req, _res, next) => {\n const r = req as unknown as HttpRequest;\n const contentType = String(r.headers?.[\"content-type\"] ?? \"\");\n if (contentType.includes(\"application/json\")) {\n if (typeof r.body === \"string\") {\n try {\n (req as any).body = JSON.parse(r.body);\n } catch {\n /* keep as string */\n }\n } else if (Buffer.isBuffer((req as any).rawBody)) {\n try {\n const raw = await readRawBody(r);\n (req as any).body = JSON.parse(raw);\n } catch {\n /* keep as is */\n }\n }\n }\n await next();\n });\n }\n\n // ── 2. Auth middleware ──────────────────────────────────────────────────\n if (auth) {\n if (typeof auth === \"function\") {\n // Custom middleware\n router.use(auth);\n } else {\n // HTTP Basic Auth\n const realm = auth.realm ?? \"API\";\n const expected =\n \"Basic \" +\n Buffer.from(`${auth.username}:${auth.password}`).toString(\"base64\");\n router.use((req, res, next) => {\n const authorization = (req as any).headers?.[\"authorization\"] ?? \"\";\n if (authorization !== expected) {\n res\n .status(401)\n .set(\"WWW-Authenticate\", `Basic realm=\"${realm}\"`)\n .set(\"Content-Type\", \"application/json\")\n .send(JSON.stringify({ success: false, error: \"Unauthorized\" }));\n return;\n }\n next();\n });\n }\n }\n\n // ── 3. Extra user middleware ────────────────────────────────────────────\n for (const mw of extraMiddleware) {\n router.use(mw);\n }\n\n // ── 4. Routes ─────────────────────────────────────────────────────────────\n\n // ── OpenAPI spec & docs endpoints (before auth so they're public) ────\n if (openapi !== false) {\n const specPath = `${base}/__spec.json`;\n const docsPath = `${base}/__docs`;\n\n router.get(specPath, (_req: any, res: any) => {\n const spec = getSpec();\n res\n .status(200)\n .set(\"Content-Type\", \"application/json; charset=utf-8\")\n .send(JSON.stringify(spec, null, 2));\n });\n\n router.get(docsPath, (req: any, res: any) => {\n // Rebuild spec URL with the correct prefix for the current context\n // (emulator, Cloud Functions URL, or custom domain).\n const specUrl = getLinkBase(req, base) + \"/__spec.json\";\n const html = scalarDocsHtml(openapiOpts.title ?? \"CRUD API\", specUrl);\n res\n .status(200)\n .set(\"Content-Type\", \"text/html; charset=utf-8\")\n .send(html);\n });\n }\n\n // OPTIONS for CORS preflight\n router.use((req, res, next) => {\n if (req.method === \"OPTIONS\") {\n handlers.handleOptions(req, res);\n return;\n }\n next();\n });\n\n // List: GET /:repoName\n router.get(`${base}/:repoName`, handlers.handleList);\n\n // Query: POST /:repoName/query (advanced filtering with body)\n router.post(`${base}/:repoName/query`, handlers.handleQuery);\n\n // Get: GET /:repoName/:id\n router.get(`${base}/:repoName/:id`, handlers.handleGet);\n\n // Create: POST /:repoName\n router.post(`${base}/:repoName`, handlers.handleCreate);\n\n // Update (full): PUT /:repoName/:id\n router.put(`${base}/:repoName/:id`, (req: any, res: any) =>\n handlers.handleUpdate(req, res, false),\n );\n\n // Update (partial): PATCH /:repoName/:id\n router.patch(`${base}/:repoName/:id`, (req: any, res: any) =>\n handlers.handleUpdate(req, res, true),\n );\n\n // Delete: DELETE /:repoName/:id\n router.delete(`${base}/:repoName/:id`, handlers.handleDelete);\n\n // ── Request handler ─────────────────────────────────────────────────────\n const handler = async (\n req: HttpRequest,\n res: HttpResponse,\n ): Promise<void> => {\n await router.handle(req as any, res as any);\n };\n\n // Attach spec getter so users can call server.spec() programmatically\n (handler as any).spec = getSpec;\n if (httpsOptions) (handler as any).httpsOptions = httpsOptions;\n\n return handler as ((req: any, res: any) => Promise<void>) & {\n /** Return the generated OpenAPI 3.1 document. */\n spec: () => OpenAPIDocument;\n /** Options to forward to `onRequest()` from firebase-functions. */\n httpsOptions?: HttpsOptions;\n };\n}\n\n// Re-exports for convenience\nexport { generateOpenAPISpec } from \"./openapi\";\nexport type { OpenAPIDocument, OpenAPISpecOptions } from \"./openapi\";\nexport type {\n ApiResponse,\n BasicAuthConfig,\n CrudRepoConfig,\n CrudRepoEntry,\n CrudRepoRegistry,\n CrudServerOptions,\n FieldRole,\n ListResponseData,\n Middleware,\n QueryRequestBody,\n RepoFieldPath,\n RepoRelationKeys,\n UserFieldPath,\n} from \"./types\";\n","/**\n * @module servers/create-servers\n *\n * Unified factory that pre-binds a repository mapping to all server builders\n * (admin UI, CRUD REST API, Firestore→SQL sync admin).\n *\n * The goal is purely DX: instead of repeating `repo: repos.posts` for each\n * entry — and losing strong inference on `keyof Model` paths because the key\n * `\"posts\"` is decoupled from the value `repos.posts` — the bound builders\n * derive the repo (and thus the model type) from the registry key:\n *\n * ```ts\n * const servers = createServers(repos, { onRequest });\n *\n * export const admin = servers.admin({\n * basePath: \"/admin\",\n * repos: {\n * posts: { path: \"posts\", fieldsConfig: { title: [\"create\"] } },\n * // ^ typed against repos.posts model\n * },\n * });\n *\n * export const api = servers.crud({\n * basePath: \"/api\",\n * repos: {\n * posts: { path: \"posts\", allowDelete: true },\n * },\n * });\n *\n * export const { functions } = servers.sync({\n * deps: { firestoreTriggers, pubsubHandler, pubsub },\n * adapter,\n * admin: { auth: { type: \"basic\", username: \"admin\", password: \"secret\" } },\n * });\n * ```\n *\n * When `onRequest` is provided to `createServers`, the admin and CRUD\n * builders return a ready-to-export Cloud Function (wrapped with the\n * caller-provided `onRequest`). Otherwise they return the raw handler.\n */\n\nimport type { HttpsOptions, onRequest as OnRequestFn } from \"firebase-functions/v2/https\";\nimport type { ConfiguredRepository } from \"../repositories/types\";\nimport type { FirestoreSyncConfig } from \"../sync/types\";\nimport { createFirestoreSync } from \"../sync/create-sync\";\nimport {\n type AdminRepoConfig,\n type AdminServerOptions,\n createAdminServer,\n} from \"./admin/index\";\nimport { createCrudServer } from \"./crud/index\";\nimport type { CrudRepoConfig, CrudServerOptions } from \"./crud/types\";\n\n// ---------------------------------------------------------------------------\n// Bound option types\n// ---------------------------------------------------------------------------\n\n/** Per-repo admin config with `repo` omitted (auto-bound from the registry key). */\nexport type BoundAdminRepoConfig<TRepo extends ConfiguredRepository<any>> = Omit<\n AdminRepoConfig<TRepo>,\n \"repo\"\n>;\n\n/** Per-repo CRUD config with `repo` omitted (auto-bound from the registry key). */\nexport type BoundCrudRepoConfig<TRepo extends ConfiguredRepository<any>> = Omit<\n CrudRepoConfig<TRepo>,\n \"repo\"\n>;\n\n/**\n * Admin server options for the bound builder.\n * `repos` becomes a partial record so callers can expose a subset of the\n * underlying registry, and each entry omits `repo` (injected from the key).\n */\nexport interface BoundAdminServerOptions<\n TRepos extends Record<string, ConfiguredRepository<any>>,\n> extends Omit<AdminServerOptions<TRepos>, \"repos\"> {\n repos: { [K in keyof TRepos]?: BoundAdminRepoConfig<TRepos[K]> };\n}\n\n/** CRUD server options for the bound builder. */\nexport interface BoundCrudServerOptions<\n TRepos extends Record<string, ConfiguredRepository<any>>,\n> extends Omit<CrudServerOptions<TRepos>, \"repos\"> {\n repos: { [K in keyof TRepos]?: BoundCrudRepoConfig<TRepos[K]> };\n}\n\n/**\n * Sync config for the bound builder — identical to `FirestoreSyncConfig`\n * but the top-level `repoMapping` argument is supplied by `createServers`.\n */\nexport type BoundFirestoreSyncConfig<TRepos extends Record<string, any>> =\n FirestoreSyncConfig<TRepos>;\n\n// ---------------------------------------------------------------------------\n// Shared deps\n// ---------------------------------------------------------------------------\n\n/** Optional dependencies shared across every server. */\nexport interface CreateServersDeps {\n /**\n * `onRequest` from `firebase-functions/v2/https`. When provided, the\n * admin/CRUD builders return a ready-to-export Cloud Function instead of\n * the raw handler. Also forwarded to the sync admin (so the bundled\n * `adminsync` Cloud Function is generated automatically).\n */\n onRequest?: typeof OnRequestFn;\n /**\n * Default `httpsOptions` applied to every server. Per-server options\n * override these defaults.\n */\n httpsOptions?: HttpsOptions;\n}\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\ntype RawHandler = ((req: any, res: any) => any) & {\n httpsOptions?: HttpsOptions;\n};\n\nfunction maybeWrap<H extends RawHandler>(\n handler: H,\n deps: CreateServersDeps,\n): H | ReturnType<typeof OnRequestFn> {\n if (!deps.onRequest) return handler;\n const opts = handler.httpsOptions ?? deps.httpsOptions;\n return opts ? deps.onRequest(opts, handler) : deps.onRequest(handler);\n}\n\nfunction injectRepos<\n TRepos extends Record<string, ConfiguredRepository<any>>,\n TBoundCfg,\n>(\n repos: TRepos,\n bound: { [K in keyof TRepos]?: TBoundCfg },\n serverName: string,\n): Record<string, TBoundCfg & { repo: ConfiguredRepository<any> }> {\n const out: Record<string, any> = {};\n for (const [name, cfg] of Object.entries(bound)) {\n if (!cfg) continue;\n const repo = repos[name as keyof TRepos];\n if (!repo) {\n throw new Error(\n `[createServers.${serverName}] Unknown repo \"${name}\" — not present in the registry passed to createServers().`,\n );\n }\n out[name] = { ...(cfg as object), repo } as any;\n }\n return out;\n}\n\n// ---------------------------------------------------------------------------\n// Factory\n// ---------------------------------------------------------------------------\n\n/**\n * Pre-binds a repository mapping to all server builders.\n *\n * @template TRepos - Repository registry; inferred at the call site.\n * @param repos - The repository mapping (e.g. result of `createRepositoryMapping`).\n * @param deps - Optional shared deps (notably `onRequest` for auto-wrapping).\n *\n * @example\n * ```ts\n * import { onRequest } from \"firebase-functions/v2/https\";\n * import { createServers } from \"@lpdjs/firestore-repo-service/servers\";\n *\n * const servers = createServers(repos, { onRequest });\n *\n * export const admin = servers.admin({\n * basePath: \"/admin\",\n * repos: {\n * posts: { path: \"posts\", allowDelete: true },\n * users: { path: \"users\" },\n * },\n * });\n * ```\n */\nexport function createServers<\n TRepos extends Record<string, ConfiguredRepository<any>>,\n>(repos: TRepos, deps: CreateServersDeps = {}) {\n return {\n /**\n * Build the admin UI handler with `repo` auto-injected from each registry key.\n * Returns a Cloud Function when `onRequest` was passed to `createServers`,\n * otherwise the raw HTTP handler.\n */\n admin(options: BoundAdminServerOptions<TRepos>) {\n const fullRepos = injectRepos<TRepos, BoundAdminRepoConfig<any>>(\n repos,\n options.repos,\n \"admin\",\n );\n const handler = createAdminServer({\n ...options,\n repos: fullRepos as AdminServerOptions<TRepos>[\"repos\"],\n httpsOptions: options.httpsOptions ?? deps.httpsOptions,\n });\n return maybeWrap(handler, deps);\n },\n\n /**\n * Build the CRUD REST API handler with `repo` auto-injected from each\n * registry key. Returns a Cloud Function when `onRequest` was passed to\n * `createServers`, otherwise the raw HTTP handler (which still exposes\n * `.spec()` and `.httpsOptions` on the raw form).\n */\n crud(options: BoundCrudServerOptions<TRepos>) {\n const fullRepos = injectRepos<TRepos, BoundCrudRepoConfig<any>>(\n repos,\n options.repos,\n \"crud\",\n );\n const handler = createCrudServer({\n ...options,\n repos: fullRepos as CrudServerOptions<TRepos>[\"repos\"],\n httpsOptions: options.httpsOptions ?? deps.httpsOptions,\n });\n return maybeWrap(handler, deps);\n },\n\n /**\n * Build the Firestore→SQL sync pipeline using the bound registry.\n * Forwards the shared `onRequest` to the sync admin config so the\n * bundled `adminsync` Cloud Function is auto-generated.\n */\n sync(config: BoundFirestoreSyncConfig<TRepos>) {\n const merged: BoundFirestoreSyncConfig<TRepos> = { ...config };\n if (deps.onRequest && merged.admin && !merged.admin.onRequest) {\n merged.admin = {\n ...merged.admin,\n onRequest: deps.onRequest as any,\n httpsOptions: merged.admin.httpsOptions ?? deps.httpsOptions,\n };\n }\n return createFirestoreSync(repos, merged);\n },\n };\n}\n","/* eslint-disable @typescript-eslint/no-empty-object-type */\n\nimport type { Firestore } from \"firebase-admin/firestore\";\nimport type { z } from \"zod\";\n\n// ============================================\n// Re-exports from modules\n// ============================================\n\n// Shared types\nexport type {\n ExtractDocumentRefSignature,\n ExtractUpdateSignature,\n FieldPath,\n GetOptions,\n GetResult,\n QueryOptions,\n RelationalKeys,\n RelationConfig,\n RepositoryConfig,\n WhereClause,\n} from \"./shared/types\";\n\n// Pagination\nexport {\n applyQueryOptions as applyPaginationQueryOptions,\n createPaginationIterator,\n executePaginatedQuery,\n} from \"./pagination\";\nexport type { PaginationOptions, PaginationResult } from \"./pagination\";\n\n// Query pagination with include\nexport type {\n IncludeConfig,\n PaginationWithIncludeOptions,\n} from \"./methods/query\";\n\n// Populate options\nexport type { PopulateOptions } from \"./methods/relations\";\n\n// Query builder\nexport { buildAndExecuteQuery } from \"./query-builder\";\n\n// Repository types\nexport type {\n ConfiguredRepository,\n GenerateGetMethods,\n GenerateQueryMethods,\n IncludeConfigTyped,\n PaginationWithIncludeOptionsTyped,\n PopulateOptionsTyped,\n} from \"./repositories/types\";\n\n// Date handling (global)\nexport {\n coerceToDate,\n getDateHandling,\n normalizeTimestamps,\n setDateHandling,\n} from \"./shared/date-config\";\nexport type { DateHandlingMode } from \"./shared/date-config\";\n\n// ============================================\n// Imports for internal use\n// ============================================\n\nimport { createRepository } from \"./repositories/factory\";\nimport type { ConfiguredRepository } from \"./repositories/types\";\nimport type { RelationConfig, RepositoryConfig } from \"./shared/types\";\n\n// ============================================\n// Repository Configuration Helper\n// ============================================\n\n/**\n * Helper to create a typed repository configuration with literal type preservation.\n * Uses currying pattern to allow type parameter inference.\n *\n * **IMPORTANT:** A Zod schema is required. The model type is automatically\n * inferred from the schema via `z.infer<TSchema>`.\n *\n * @template TSchema - Zod schema that defines the model structure\n * @param schema - The Zod schema for validation and type inference\n * @returns Builder function that accepts repository configuration\n *\n * @example\n * ```typescript\n * const userSchema = z.object({\n * docId: z.string(),\n * email: z.string().email(),\n * name: z.string(),\n * isActive: z.boolean(),\n * });\n *\n * const postSchema = z.object({\n * docId: z.string(),\n * userId: z.string(),\n * title: z.string(),\n * content: z.string(),\n * status: z.enum([\"draft\", \"published\"]),\n * });\n *\n * const mapping = {\n * users: createRepositoryConfig(userSchema)({\n * path: \"users\",\n * isGroup: false,\n * foreignKeys: [\"docId\", \"email\"] as const,\n * queryKeys: [\"isActive\"] as const,\n * documentKey: \"docId\",\n * refCb: (db, docId: string) => db.collection(\"users\").doc(docId),\n * }),\n * posts: createRepositoryConfig(postSchema)({\n * path: \"posts\",\n * isGroup: false,\n * foreignKeys: [\"docId\", \"userId\"] as const,\n * queryKeys: [\"status\"] as const,\n * documentKey: \"docId\",\n * refCb: (db, docId: string) => db.collection(\"posts\").doc(docId),\n * }),\n * };\n *\n * const repos = createRepositoryMapping(db, mapping);\n * ```\n */\nexport function createRepositoryConfig<TSchema extends z.ZodObject<any>>(\n schema: TSchema,\n): <\n const TForeignKeys extends readonly (keyof z.infer<TSchema>)[],\n const TQueryKeys extends readonly (keyof z.infer<TSchema>)[],\n const TIsGroup extends boolean,\n const TDocumentKey extends keyof z.infer<TSchema>,\n const TPathKey extends keyof z.infer<TSchema> | undefined = undefined,\n const TCreatedKey extends keyof z.infer<TSchema> | undefined = undefined,\n const TUpdatedKey extends keyof z.infer<TSchema> | undefined = undefined,\n TRefCb = undefined,\n>(config: {\n path: string;\n isGroup: TIsGroup;\n foreignKeys: TForeignKeys;\n queryKeys: TQueryKeys;\n documentKey: TDocumentKey;\n pathKey?: TPathKey;\n createdKey?: TCreatedKey;\n updatedKey?: TUpdatedKey;\n refCb: TRefCb;\n}) => RepositoryConfig<\n z.infer<TSchema>,\n TForeignKeys,\n TQueryKeys,\n TIsGroup,\n TRefCb,\n {},\n TDocumentKey,\n TPathKey,\n TCreatedKey,\n TUpdatedKey\n> & { schema: TSchema } {\n return (config: any): any => ({\n ...config,\n schema,\n type: null as any,\n documentRef: null as any,\n update: null as any,\n });\n}\n\n/**\n * Helper type to resolve a single relation configuration\n * Extracts the target model type from the mapping\n */\ntype ResolveRelation<TMapping, TRelationConfig> = TRelationConfig extends {\n repo: infer R;\n key: infer FK;\n type: infer RT;\n}\n ? R extends keyof TMapping\n ? TMapping[R] extends { type: infer TTarget }\n ? RelationConfig<R & string, FK & string, RT & (\"one\" | \"many\"), TTarget>\n : never\n : never\n : never;\n\n/**\n * Helper to add relations to a repository mapping with full type validation\n * Validates that repo names and foreign keys exist in the mapping\n * @template TMapping - The complete repository mapping for validation\n * @template TRelations - Relations configuration with strict typing\n * @param mapping - The base repository mapping\n * @param relations - Relations configuration for each repository\n * @returns Updated mapping with relations and full type safety\n * @example\n * ```typescript\n * const mapping = {\n * users: createRepositoryConfig<UserModel>()({ ... }),\n * posts: createRepositoryConfig<PostModel>()({ ... }),\n * };\n *\n * const mappingWithRelations = buildRepositoryRelations(mapping, {\n * posts: {\n * userId: { repo: \"users\", key: \"docId\", type: \"one\" as const }\n * }\n * });\n *\n * const repos = createRepositoryMapping(db, mappingWithRelations);\n * ```\n */\nexport function buildRepositoryRelations<\n TMapping extends Record<string, any>,\n const TRelations extends {\n [K in keyof TMapping]?: TMapping[K] extends RepositoryConfig<\n infer T,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any\n >\n ? {\n [RK in keyof T]?: {\n [R in keyof TMapping]: TMapping[R] extends RepositoryConfig<\n infer TTargetModel,\n infer TForeignKeys,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any\n >\n ? {\n repo: R;\n key: TForeignKeys[number];\n type: \"one\" | \"many\";\n }\n : never;\n }[keyof TMapping];\n }\n : never;\n },\n>(\n mapping: TMapping,\n relations: TRelations,\n): {\n [K in keyof TMapping]: K extends keyof TRelations\n ? TMapping[K] extends RepositoryConfig<\n infer T,\n infer TForeignKeys,\n infer TQueryKeys,\n infer TIsGroup,\n infer TRefCb,\n any,\n infer TDocumentKey,\n infer TPathKey,\n infer TCreatedKey,\n infer TUpdatedKey\n >\n ? RepositoryConfig<\n T,\n TForeignKeys,\n TQueryKeys,\n TIsGroup,\n TRefCb,\n {\n [RK in keyof TRelations[K]]: ResolveRelation<\n TMapping,\n TRelations[K][RK]\n >;\n },\n TDocumentKey,\n TPathKey,\n TCreatedKey,\n TUpdatedKey\n >\n : TMapping[K]\n : TMapping[K];\n} {\n const result: any = { ...mapping };\n\n for (const repoKey in relations) {\n if (relations[repoKey]) {\n result[repoKey] = {\n ...mapping[repoKey],\n relationalKeys: relations[repoKey],\n };\n }\n }\n\n return result as any;\n}\n\n// ============================================\n// Repository Mapping Class\n// ============================================\n\n/**\n * Repository mapping class that manages Firestore repositories with type safety\n * @template T - Record of repository configurations\n */\nexport class RepositoryMapping<T extends Record<string, any>> {\n private db: Firestore;\n private repositoryCache = new Map<string, any>();\n private mapping: T;\n private allRepositories: Record<string, any> = {};\n\n /**\n * Creates a new RepositoryMapping instance\n * @param db - Firestore instance from firebase-admin\n * @param mapping - Repository configuration mapping\n */\n constructor(db: Firestore, mapping: T) {\n this.db = db;\n this.mapping = mapping;\n // Pre-initialize all repositories to allow cross-references\n this.initializeRepositories();\n }\n\n /**\n * Initialize all repositories in two passes to handle circular dependencies\n * @private\n */\n private initializeRepositories() {\n // Pass 1: Create all repositories without populate methods\n for (const key of Object.keys(this.mapping)) {\n this.allRepositories[key] = createRepository(\n this.db,\n this.mapping[key],\n {},\n );\n }\n\n // Pass 2: Update all repositories with complete allRepositories map\n for (const key of Object.keys(this.mapping)) {\n this.allRepositories[key] = createRepository(\n this.db,\n this.mapping[key],\n this.allRepositories,\n );\n }\n }\n\n /**\n * Gets a repository (already initialized)\n * @template K - Repository key\n * @param key - Repository identifier\n * @returns Configured repository instance\n */\n getRepository<K extends keyof T>(key: K): ConfiguredRepository<T[K]> {\n return this.allRepositories[key as string];\n }\n}\n\n// ============================================\n// Repository Mapping Factory\n// ============================================\n\n/**\n * Helper function to create a RepositoryMapping instance with full typing\n * @template T - Record of repository configurations\n * @param db - Firestore instance from firebase-admin\n * @param mapping - Repository configurations\n * @returns RepositoryMapping instance with repository access via getters\n * @example\n * ```typescript\n * import * as admin from 'firebase-admin';\n *\n * admin.initializeApp();\n * const db = admin.firestore();\n *\n * const repos = createRepositoryMapping(db, {\n * users: createRepositoryConfig<UserModel>()({\n * path: \"users\",\n * isGroup: false,\n * foreignKeys: [\"docId\", \"email\"] as const,\n * queryKeys: [\"isActive\"] as const,\n * refCb: (db, docId: string) => db.collection(\"users\").doc(docId),\n * }),\n * });\n *\n * // Access repositories directly\n * const user = await repos.users.get.byDocId(\"123\");\n * ```\n */\nexport function createRepositoryMapping<T extends Record<string, any>>(\n db: Firestore,\n mapping: T,\n): { [K in keyof T]: ConfiguredRepository<T[K]> } {\n const instance = new RepositoryMapping(db, mapping);\n\n const mappingKeys = Object.keys(mapping);\n\n // Proxy exposes only the mapping keys as own properties,\n // hiding internal class fields (db, repositoryCache, etc.)\n return new Proxy(instance, {\n get(target, prop) {\n if (typeof prop === \"string\" && prop in mapping) {\n return target.getRepository(prop as keyof T);\n }\n return (target as any)[prop];\n },\n ownKeys() {\n return mappingKeys;\n },\n getOwnPropertyDescriptor(_target, prop) {\n if (typeof prop === \"string\" && prop in mapping) {\n return { configurable: true, enumerable: true, writable: false };\n }\n return undefined;\n },\n }) as any;\n}\n\n// ============================================\n// Servers (admin ORM & CRUD API)\n// ============================================\nexport {\n createServers,\n MiniRouter,\n} from \"./servers/index\";\nexport type {\n AdminRepoConfig,\n AdminRepoEntry,\n AdminServerOptions,\n ApiResponse,\n BasicAuthConfig,\n BoundAdminRepoConfig,\n BoundAdminServerOptions,\n BoundCrudRepoConfig,\n BoundCrudServerOptions,\n BoundFirestoreSyncConfig,\n CreateServersDeps,\n CrudRepoConfig,\n CrudServerOptions,\n FieldRole,\n ListResponseData,\n QueryRequestBody,\n RepoFieldPath,\n RepoRelationKeys,\n UserFieldPath,\n} from \"./servers/index\";\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/shared/zod-compat.ts","../src/servers/admin/components/cell-value.tsx","../src/servers/admin/components/type-check.ts","../src/servers/admin/components/right-panel.tsx","../src/query-builder.ts","../src/shared/date-config.ts","../src/shared/utils.ts","../src/pagination.ts","../src/history/diff.ts","../src/history/normalize.ts","../src/history/write.ts","../src/history/read.ts","../src/methods/aggregate.ts","../src/methods/batch.ts","../src/methods/bulk.ts","../src/methods/crud.ts","../src/methods/get.ts","../src/methods/query.ts","../src/methods/relations.ts","../src/methods/transaction.ts","../src/repositories/factory.ts","../src/servers/admin/router.ts","../src/sync/schema-mapper.ts","../src/sync/constants.ts","../src/sync/serializer.ts","../src/sync/admin.ts","../src/sync/triggers.ts","../src/sync/queue.ts","../src/sync/worker.ts","../src/sync/create-sync.ts","../src/servers/admin/handlers.ts","../src/servers/admin/form-gen.ts","../src/servers/admin/components/index.ts","../src/servers/admin/components/client-script.raw.js","../src/servers/admin/components/client-script.tsx","../src/servers/admin/components/shell.tsx","../src/servers/admin/components/dashboard.tsx","../src/servers/admin/components/filter-bar.tsx","../src/servers/admin/components/form.tsx","../src/servers/admin/components/list.tsx","../src/servers/admin/renderer.ts","../src/servers/admin/index-url.ts","../src/servers/admin/index.ts","../src/servers/crud/handlers.ts","../src/servers/crud/openapi.ts","../src/servers/crud/index.ts","../src/servers/create-servers.ts","../src/index.ts"],"names":["getTypeName","schema","s","v4Type","TYPE_MAP","v3Type","getInnerType","getArrayElementType","getDefaultValue","v","getShape","getEnumValues","getNativeEnumValues","getLiteralValue","getStringChecks","kinds","v4Checks","c","v3Checks","init_zod_compat","__esmMin","CellDate","val","jsx","TypeMismatchBadge","message","CellValue","mismatch","inner","renderInner","jsxs","item","i","entries","k","Fragment","str","init_cell_value","expectedTypeOf","unwrap","tn","resolveAtPath","path","segments","cur","seg","actualTypeOf","mismatchMessage","expected","actual","init_type_check","right_panel_exports","__export","PanelMany","PanelOne","RightPanel","doc","repoName","basePath","columns","id","editUrl","expectedTypes","buildExpectedMap","docs","fk","fv","pagination","fullViewUrl","d","ri","ci","out","init_right_panel","chunkArray","array","size","chunks","applyBasicQueryOptions","q","options","o","f","needsSplitting","clause","operator","value","splitWhereClause","field","chunk","applyWhereClausesToQuery","baseQuery","whereClauses","executeAndMergeQueries","queries","snapshots","docsMap","snapshot","firstSnapshot","buildAndExecuteQuery","hasOrWhere","hasOrWhereGroups","splitClauses","cartesianProduct","combination","baseClauses","rawGroups","allQueries","orGroup","fullGroup","groupQueries","arrays","first","rest","restProduct","result","combo","currentMode","setDateHandling","mode","getDateHandling","isTimestampLike","coerceToDate","Timestamp","isPlainObject","proto","normalizeTimestamps","maybeNormalize","capitalize","applyQueryOptions","executePaginatedQuery","queryOptions","hasMore","actualDocs","data","isPrev","createPaginationIterator","cursor","valueType","valuesEqual","a","b","computeDiff","before","after","opts","excludeSet","includeSet","beforeObj","afterObj","keys","changes","key","oldValue","newValue","DEFAULT_GROUP_TOLERANCE_MS","isV2","legacyTypeToHistoryType","t","v2ToEntry","v1MetaOf","meta","extra","extras","anyExtra","v1FieldChange","declaredOld","declaredNew","v1ToEntry","change","tsClose","toleranceMs","sameAuthor","normalizeHistoryDocs","tol","entry","last","MAX_DOC_BYTES","buildHistoryEntry","params","ttl","randomUUID","sizeOf","obj","_k","truncated","oldSize","newSize","writeHistoryEntry","historyRef","config","ctx","toWrite","extractMeta","source","src","m","pickStr","userId","userEmail","reason","comment","any","metaFieldsOf","list","DEFAULT_SUBCOLLECTION","DEFAULT_LIMIT","getHistoryRef","documentRef","subcollection","args","getDocId","createHistoryMethods","systemKeys","raw","pathArgs","ref","direction","limit","fetchLimit","rawDocs","set","e","byField","byOperation","op","recordManual","payload","entityId","createAggregateMethods","collectionRef","total","count","createBatchMethods","db","documentKey","pathKey","createdKey","updatedKey","now","batch","lastArg","hasOptions","mergeOption","docRef","enrichedData","docIdValue","createBulkMethods","items","bulkWriter","pendingOps","merge","docRefs","createCrudMethods","actualCollection","docId","dataWithPath","updates","createdDoc","setDocument","updatedDoc","createGetMethods","foreignKeys","getMethods","values","results","foreignKey","methodName","createQueryMethods","queryKeys","relationalKeys","allRepositories","queryMethods","populateDocuments","documents","includeConfigs","normalizedConfigs","cfg","select","relation","targetRepo","fieldValue","method","err","populated","queryKey","mergedOptions","onNext","onError","include","paginationOptions","populatedData","page","createPopulateMethods","document","relationKeyOrOptions","selectMap","selectFields","createTransactionMethods","updateFunction","rawTransaction","docSnap","extractParentKeys","refCb","match","p","createRepository","aggregateMethods","crudMethods","batchMethods","transactionMethods","bulkMethods","populateMethods","historyConfig","history","compilePath","paramNames","_match","name","extractPath","req","idx","MiniRouter","_req","res","middleware","handler","pattern","matchedRoute","route","enrichedReq","finalHandler","index","next","mw","SYNC_VERSION_COLUMN","WRAPPER_TYPES","current","nullable","LOGICAL_MAP","flattenSchema","shape","dialect","prefix","parentNullable","columnMap","primaryKey","fieldSchema","fullKey","typeName","isNullable","nestedShape","logical","isPK","colName","zodSchemaToColumns","exclude","serializeValue","geo","flattenObject","flatKey","serializeDocument","flat","topLevel","column","getLinkBase","base","project","region","target","service","host","title","linkBase","body","sendHtml","html","status","sendJson","isJsonRequest","createadminsyncServer","repoMapping","adapter","queues","handleMessage","repoConfigs","pubsub","topicPrefix","features","repoInfos","repo","repoCfg","router","realm","lb","rows","r","links","queueLink","configCheckLink","info","expectedCols","actualCols","tableExists","error","actualSet","expectedSet","missing","matched","isHealthy","statusBadge","colRows","extraRows","collRef","synced","errors","errorSamples","batchSize","query","lastDoc","serialized","msg","queue","errorBlock","queueData","consoleBase","tPrefix","checks","msgLower","isApiDisabled","isPermission","isProjectNotFound","isNotFound","exists","topicName","topic","allOk","statusIcon","grouped","renderSection","fixHtml","parts","overallBadge","DEFAULT_TOPIC_PREFIX","buildDocumentPath","collectionPath","createSyncTriggers","onDocumentCreated","onDocumentUpdated","onDocumentDeleted","triggers","topicCache","getTopic","publish","syncEvent","documentPath","event","snap","SyncQueue","interval","events","upsertsById","deleteIds","evt","existing","upserts","handlerErr","migratedRepos","ensureMigrated","tableName","newCols","createSyncWorker","deps","flushIntervalMs","autoMigrate","workerOptions","getQueue","onFlushError","dlTopicName","dlTopic","dlErr","createHandler","handlerFn","promises","lazyProxy","factory","instance","_","prop","createFirestoreSync","rawAdapter","adminConfig","worker","handlers","adminHandler","toLabel","required","defaultValue","zodToFields","namePrefix","fieldName","zodFieldToDescriptor","rawName","label","isEmail","isUrl","enumObj","nested","elSchema","elInner","elTn","arrayElementType","arrayElementOptions","arrayElementFields","renderField","depth","indent","nameAttr","requiredAttr","isNullValue","defaultStr","nullToggle","input","sel3","renderArrayField","subFields","isObject","itemsHtml","renderObjectItem","renderPrimitiveItem","templateHtml","strVal","inputHtml","renderForm","fields","action","submitLabel","fieldsHtml","client_script_raw_default","ClientScript","renderHtml","element","renderToString","THEMES","ThemeSwitcher","PageShell","children","breadcrumb","flash","renderPageJsx","content","renderDashboardJsx","repos","OPS_TEXT","OPS_NUMERIC","OPS_ARRAY","opsForType","zodType","NULL_SENTINEL","nullToggleScript","inputId","enumChecklistScript","hiddenId","group","NullToggle","active","FilterValueInput","col","isNull","isMultiOp","selected","isAny","FilterBar","columnMeta","activeFilters","isGroup","activeMap","hasActive","needsIndexHint","filterable","ops","currentOp","renderFormPageJsx","formHtml","crumbs","baseParams","filters","sort","pageSize","paginationHref","dir","sortHref","pageSizeHref","newPs","renderListJsx","allowDelete","relationalMeta","sortState","currentPageSize","queryError","totalCount","mutableFields","listUrl","createUrl","scalarMutable","canBulkUpdate","canBulkDelete","showSelection","bulkFieldsMeta","sub","ps","isSorted","arrow","rowIdx","deleteUrl","mi","rawVal","fallbackHref","renderPage","renderDashboard","renderList","renderFormPage","RANGE_OPS","ARRAY_OPS","toIndexOrder","collectionIdFromPath","buildIndexUrl","projectId","collectionId","seen","buildExemptionUrl","lastDir","buildCompositeUrl","databaseId","resource","pbString","pbInt","pbMessage","encodeIndexField","urlDbId","encoded","toBase64","extractIndexUrl","pbVarint","n","pbTag","fieldNumber","wireType","bytes","bin","b64","extractProjectId","candidates","isMissingIndexError","fe","toQueryError","isIndex","indexUrl","colId","_idChars","generateFirestoreId","extractPathArgs","fullPath","fetchDocById","docKey","getMethod","flashFromDocFetchError","qe","redirect","to","parseFormBody","zodField","resolveTypeName","subRaw","hasDotKeys","innerSchema","itn","toDatetimeLocal","date","pad","resolveInnerSchema","isFieldNullable","extractEnumValues","vals","prefillFromDoc","innerTn","dtLocal","applyPrefill","prefilled","parseFilters","validFields","validOps","opRaw","filtersToWhere","coerce","arr","buildColumnMeta","fullName","subShape","resolveZodAtPath","part","getMutableSchema","dotGroups","dot","parent","child","picked","z","staticBasePath","createAdminHandlers","registry","handleDashboard","handleList","cursorStr","sortField","sortDir","psRaw","allColumns","filterableColumns","resolved","whereFilters","cursorSnapshot","colRef","isError","nextCursorId","prevCursorId","handleCreateForm","createSchema","actionUrl","handleCreateSubmit","rawBody","parsed","validation","errorMsg","missingKeys","parentIds","createSchema2","handleEditForm","mutableSchema","handleEditSubmit","mutableSchema2","handleDelete","handlePanel","type","coerceFilterValue","resolveRefs","ids","refs","resolveAllIds","where","handleBulkDelete","collectTargetIds","handleBulkUpdate","parsedValue","sanitizeFilters","x","readRawBody","parseUrlEncoded","pair","createAdminServer","parseBody","auth","extraMiddleware","httpsOptions","resolvedSchema","filterableFields","createFields","fc","roles","role","parentKeys","pk","repoRelKeys","rel","_res","contentType","sendSuccess","sendError","sendQueryError","fallbackMessage","verbose","wrapDateSchemas","def","wrapped","dflt","pickSchemaFields","validateData","partial","targetSchema","partialSchema","allowedFields","opMap","opKey","parsedVal","parseValue","num","serializeCursor","deserializeCursor","createCrudHandlers","getRepoEntry","getterName","getter","ctxFilters","ctxSort","orderBy","orderDir","selectStr","includes","inc","cursorObj","responseData","handleQuery","w","validIncludes","allowed","invalid","handleGet","handleCreate","customError","created","handleUpdate","existingDoc","updated","handleOptions","zodToJsonSchema","schemaRef","errorResponse","description","successResponse","dataSchema","listResponse","itemSchema","paginationParams","filterParams","queryBodySchema","buildPathsForEntry","modelSchemaName","createSchemaName","updateSchemaName","paths","tag","idParam","singularize","docOps","generateOpenAPISpec","version","servers","schemas","allPaths","tags","modelName","createName","updateName","buildShape","fieldList","top","createShape","updateShape","entryPaths","securitySchemes","security","scalarDocsHtml","specUrl","createCrudServer","openapi","openapiOpts","_specCache","getSpec","authType","specPath","docsPath","spec","maybeWrap","injectRepos","bound","serverName","createServers","fullRepos","merged","createRepositoryConfig","buildRepositoryRelations","mapping","relations","repoKey","RepositoryMapping","createRepositoryMapping","mappingKeys","_target"],"mappings":"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;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AA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","file":"index.js","sourcesContent":["/**\n * Zod introspection utilities — compatible with Zod 4.\n *\n * Centralizes all internal `_zod.def` accesses so the rest of the codebase\n * never touches Zod internals directly. If a future Zod version changes\n * the internal layout, only this file needs updating.\n */\n\nimport type { z } from \"zod\";\n\n// ---------------------------------------------------------------------------\n// Type-name resolution\n// ---------------------------------------------------------------------------\n\n/**\n * Canonical Zod type names used in the codebase.\n * These match the **Zod 3** naming convention (e.g. \"ZodString\") that the\n * form-gen / admin handlers already rely on, so we don't need to rewrite\n * every `case \"ZodString\":` branch.\n */\ntype ZodTypeName =\n | \"ZodString\"\n | \"ZodNumber\"\n | \"ZodBigInt\"\n | \"ZodBoolean\"\n | \"ZodDate\"\n | \"ZodEnum\"\n | \"ZodNativeEnum\"\n | \"ZodLiteral\"\n | \"ZodObject\"\n | \"ZodArray\"\n | \"ZodOptional\"\n | \"ZodNullable\"\n | \"ZodDefault\"\n | \"ZodCoerce\"\n | \"ZodUnion\"\n | \"ZodUndefined\"\n | \"ZodUnknown\"\n | \"ZodAny\"\n | \"ZodRecord\"\n | string;\n\n/**\n * Map from Zod 4 `_zod.def.type` (lowercase) → Zod 3 `_def.typeName` format.\n * Any key not in this map is capitalised as `Zod${Capitalised}`.\n */\nconst TYPE_MAP: Record<string, ZodTypeName> = {\n string: \"ZodString\",\n number: \"ZodNumber\",\n bigint: \"ZodBigInt\",\n boolean: \"ZodBoolean\",\n date: \"ZodDate\",\n enum: \"ZodEnum\",\n nativeEnum: \"ZodNativeEnum\",\n literal: \"ZodLiteral\",\n object: \"ZodObject\",\n array: \"ZodArray\",\n optional: \"ZodOptional\",\n nullable: \"ZodNullable\",\n default: \"ZodDefault\",\n coerce: \"ZodCoerce\",\n union: \"ZodUnion\",\n undefined: \"ZodUndefined\",\n unknown: \"ZodUnknown\",\n any: \"ZodAny\",\n record: \"ZodRecord\",\n};\n\n/**\n * Get the canonical type name of a Zod schema.\n *\n * Works with both Zod 3 (`_def.typeName`) and Zod 4 (`_zod.def.type`).\n * Returns names in Zod-3 style (\"ZodString\", \"ZodObject\" …) for\n * backward-compatible switch/case usage.\n */\nexport function getTypeName(schema: z.ZodType): ZodTypeName {\n const s = schema as any;\n\n // Zod 4 path\n const v4Type: string | undefined = s._zod?.def?.type;\n if (v4Type)\n return (\n TYPE_MAP[v4Type] ??\n `Zod${v4Type.charAt(0).toUpperCase()}${v4Type.slice(1)}`\n );\n\n // Zod 3 fallback\n const v3Type: string | undefined = s._def?.typeName;\n if (v3Type) return v3Type;\n\n return \"\";\n}\n\n// ---------------------------------------------------------------------------\n// Unwrapping wrappers (Optional / Nullable / Default)\n// ---------------------------------------------------------------------------\n\n/**\n * Get the inner schema from a wrapper type (Optional / Nullable / Default).\n */\nexport function getInnerType(schema: z.ZodType): z.ZodType | undefined {\n const s = schema as any;\n\n // Zod 4: _zod.def.innerType\n if (s._zod?.def?.innerType) return s._zod.def.innerType;\n\n // Zod 3 compat: _def.innerType\n if (s._def?.innerType) return s._def.innerType;\n\n return undefined;\n}\n\n/**\n * Get the **element schema** from a `ZodArray`.\n * Returns `undefined` for non-array schemas.\n */\nexport function getArrayElementType(\n schema: z.ZodType,\n): z.ZodType | undefined {\n const s = schema as any;\n\n // Zod 4: _zod.def.element\n if (s._zod?.def?.element) return s._zod.def.element;\n\n // Zod 3: _def.type (ZodArray stores element schema in _def.type)\n if (s._def?.type) return s._def.type;\n\n return undefined;\n}\n\n/**\n * Returns the list of **required** (non-optional) top-level keys of a ZodObject.\n * A key is required when its schema is NOT wrapped in ZodOptional.\n * ZodNullable / ZodDefault fields are still considered required — they must be present.\n */\nexport function getRequiredSchemaKeys(schema: z.ZodObject<any>): string[] {\n const required: string[] = [];\n for (const [key, fieldSchema] of Object.entries(schema.shape)) {\n const typeName = getTypeName(fieldSchema as z.ZodType);\n if (typeName !== \"ZodOptional\") {\n required.push(key);\n }\n }\n return required;\n}\n\n/**\n * Get the default value for a ZodDefault schema.\n * In Zod 3 this was `_def.defaultValue()` (function). In Zod 4 it's a direct value.\n */\nexport function getDefaultValue(schema: z.ZodType): unknown {\n const s = schema as any;\n\n // Zod 4\n if (s._zod?.def?.defaultValue !== undefined) return s._zod.def.defaultValue;\n\n // Zod 3 compat\n const v = s._def?.defaultValue;\n if (typeof v === \"function\") return v();\n return v;\n}\n\n// ---------------------------------------------------------------------------\n// Object shape\n// ---------------------------------------------------------------------------\n\n/**\n * Get the shape of a ZodObject schema (Record<string, ZodType>).\n * Handles both Zod 3 (`_def.shape()` function) and Zod 4 (`.shape` property).\n */\nexport function getShape(schema: z.ZodType): Record<string, z.ZodType> {\n const s = schema as any;\n\n // Direct `.shape` property (Zod 3 & 4 for ZodObject instances)\n if (s.shape && typeof s.shape === \"object\") return s.shape;\n\n // Zod 4: _zod.def.shape\n if (s._zod?.def?.shape && typeof s._zod.def.shape === \"object\")\n return s._zod.def.shape;\n\n // Zod 3 fallback: _def.shape() or _def.shape\n if (s._def?.shape) {\n return typeof s._def.shape === \"function\" ? s._def.shape() : s._def.shape;\n }\n\n return {};\n}\n\n// ---------------------------------------------------------------------------\n// Enum / Literal values\n// ---------------------------------------------------------------------------\n\n/**\n * Get the values of a ZodEnum schema as a string[].\n */\nexport function getEnumValues(schema: z.ZodType): string[] {\n const s = schema as any;\n\n // Zod 4: `.options` or `_zod.def.entries`\n if (Array.isArray(s.options)) return s.options;\n if (s._zod?.def?.entries)\n return Object.values(s._zod.def.entries) as string[];\n\n // Zod 3: `_def.values`\n if (Array.isArray(s._def?.values)) return s._def.values;\n\n return [];\n}\n\n/**\n * Get the value object of a ZodNativeEnum schema.\n */\nexport function getNativeEnumValues(\n schema: z.ZodType,\n): Record<string, unknown> {\n const s = schema as any;\n\n // Zod 4: `_zod.def.entries` or `.enum`\n if (s._zod?.def?.entries) return s._zod.def.entries;\n if (s.enum && typeof s.enum === \"object\") return s.enum;\n\n // Zod 3: `_def.values`\n if (s._def?.values && typeof s._def.values === \"object\") return s._def.values;\n\n return {};\n}\n\n/**\n * Get the value of a ZodLiteral schema.\n */\nexport function getLiteralValue(schema: z.ZodType): unknown {\n const s = schema as any;\n\n // Zod 4: `_zod.def.values[0]`\n if (Array.isArray(s._zod?.def?.values)) return s._zod.def.values[0];\n\n // Zod 3: `_def.value`\n return s._def?.value;\n}\n\n// ---------------------------------------------------------------------------\n// String checks\n// ---------------------------------------------------------------------------\n\n/**\n * Get relevant \"check kinds\" from a ZodString schema.\n * Returns an array of kind strings: \"email\", \"url\", etc.\n */\nexport function getStringChecks(schema: z.ZodType): string[] {\n const s = schema as any;\n const kinds: string[] = [];\n\n // Zod 4: checks with `.format` field\n const v4Checks: any[] | undefined = s._zod?.def?.checks;\n if (Array.isArray(v4Checks)) {\n for (const c of v4Checks) {\n if (c.format) kinds.push(c.format);\n }\n if (kinds.length > 0) return kinds;\n }\n\n // Zod 3: _def.checks with `.kind` field\n const v3Checks: any[] | undefined = s._def?.checks;\n if (Array.isArray(v3Checks)) {\n for (const c of v3Checks) {\n if (c.kind) kinds.push(c.kind);\n }\n }\n\n return kinds;\n}\n","function CellDate({ val }: { val: Date }) {\n return (\n <span class=\"text-sm text-base-content/80 font-mono tabular-nums whitespace-nowrap\">\n {val.toLocaleString()}\n </span>\n );\n}\n\n/** Small warning icon with tooltip — rendered next to a cell when its value's runtime type doesn't match the schema. */\nfunction TypeMismatchBadge({ message }: { message: string }) {\n return (\n <span\n class=\"tooltip tooltip-warning tooltip-right inline-flex align-middle ml-1 text-warning\"\n data-tip={message}\n role=\"img\"\n aria-label={message}\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"currentColor\"\n class=\"size-3.5\"\n >\n <path d=\"M12 2 1 22h22L12 2zm0 6 7.5 13h-15L12 8zm-1 4v4h2v-4h-2zm0 5v2h2v-2h-2z\" />\n </svg>\n </span>\n );\n}\n\nexport function CellValue({\n val,\n mismatch,\n}: {\n val: unknown;\n mismatch?: string | null;\n}) {\n const inner = renderInner(val);\n if (!mismatch) return inner;\n return (\n <span class=\"inline-flex items-start gap-0.5\">\n {inner}\n <TypeMismatchBadge message={mismatch} />\n </span>\n );\n}\n\nfunction renderInner(val: unknown) {\n if (val === null || val === undefined) {\n return <span class=\"opacity-30 italic text-xs\">—</span>;\n }\n\n if (typeof val === \"boolean\") {\n return val ? (\n <span class=\"badge badge-success badge-sm\">true</span>\n ) : (\n <span class=\"badge badge-error badge-sm\">false</span>\n );\n }\n\n if (val instanceof Date) {\n return <CellDate val={val} />;\n }\n\n // Firestore Timestamp (.toDate())\n if (\n typeof val === \"object\" &&\n val !== null &&\n typeof (val as any).toDate === \"function\"\n ) {\n return <CellDate val={(val as any).toDate() as Date} />;\n }\n\n if (typeof val === \"number\") {\n return <span class=\"text-sm font-mono tabular-nums\">{String(val)}</span>;\n }\n\n if (Array.isArray(val)) {\n if (val.length === 0)\n return <span class=\"text-xs text-base-content/30\">{\"[]\"}</span>;\n return (\n <ul class=\"list-none p-0 m-0 space-y-0.5 text-xs\">\n {val.slice(0, 8).map((item, i) => (\n <li key={i} class=\"break-all\">\n {typeof item === \"object\" ? JSON.stringify(item) : String(item)}\n </li>\n ))}\n {val.length > 8 && (\n <li class=\"text-base-content/40 italic\">\n +{val.length - 8} more…\n </li>\n )}\n </ul>\n );\n }\n\n if (typeof val === \"object\" && val !== null) {\n const entries = Object.entries(val as Record<string, unknown>);\n if (entries.length === 0)\n return <span class=\"text-xs text-base-content/30\">{\"{}\"}</span>;\n return (\n <dl class=\"grid grid-cols-[auto_1fr] gap-x-2 gap-y-0.5 text-xs m-0\">\n {entries.slice(0, 8).map(([k, v]) => (\n <>\n <dt class=\"text-base-content/50 font-semibold whitespace-nowrap\">\n {k}\n </dt>\n <dd class=\"break-all\">{String(v ?? \"\")}</dd>\n </>\n ))}\n {entries.length > 8 && (\n <dt class=\"col-span-2 text-base-content/40 italic\">\n +{entries.length - 8} more…\n </dt>\n )}\n </dl>\n );\n }\n\n const str = String(val);\n return <span class=\"text-sm break-all\">{str}</span>;\n}\n","/**\n * Runtime type-mismatch detection between a column's declared Zod schema\n * and the actual value returned by Firestore.\n *\n * Used by the list view to surface a small warning indicator + tooltip\n * when the stored data drifts from the model (e.g. the schema declares a\n * `string` but Firestore returns a `number`).\n */\n\nimport type { z } from \"zod\";\nimport {\n getInnerType,\n getShape,\n getTypeName,\n} from \"../../../shared/zod-compat\";\n\nexport type ExpectedType =\n | \"string\"\n | \"number\"\n | \"bigint\"\n | \"boolean\"\n | \"date\"\n | \"array\"\n | \"object\"\n | \"enum\"\n | \"literal\"\n | \"unknown\";\n\n/** Resolve the expected runtime type name from a Zod schema (after unwrapping optional/nullable/default). */\nexport function expectedTypeOf(schema: z.ZodType | undefined): ExpectedType {\n if (!schema) return \"unknown\";\n const inner = unwrap(schema);\n const tn = getTypeName(inner);\n switch (tn) {\n case \"ZodString\":\n return \"string\";\n case \"ZodNumber\":\n return \"number\";\n case \"ZodBigInt\":\n return \"bigint\";\n case \"ZodBoolean\":\n return \"boolean\";\n case \"ZodDate\":\n return \"date\";\n case \"ZodArray\":\n return \"array\";\n case \"ZodObject\":\n case \"ZodRecord\":\n return \"object\";\n case \"ZodEnum\":\n case \"ZodNativeEnum\":\n return \"enum\";\n case \"ZodLiteral\":\n return \"literal\";\n default:\n return \"unknown\";\n }\n}\n\n/** Recursively unwrap Optional/Nullable/Default wrappers. */\nfunction unwrap(schema: z.ZodType): z.ZodType {\n const tn = getTypeName(schema);\n if (\n tn === \"ZodOptional\" ||\n tn === \"ZodNullable\" ||\n tn === \"ZodDefault\"\n ) {\n const inner = getInnerType(schema);\n return inner ? unwrap(inner) : schema;\n }\n return schema;\n}\n\n/** Resolve a Zod schema for a possibly dot-noted column path, returning undefined if unresolvable. */\nexport function resolveAtPath(\n schema: z.ZodType | undefined,\n path: string,\n): z.ZodType | undefined {\n if (!schema) return undefined;\n const segments = path.split(\".\");\n let cur: z.ZodType | undefined = schema;\n for (const seg of segments) {\n if (!cur) return undefined;\n const inner = unwrap(cur);\n const tn = getTypeName(inner);\n if (tn !== \"ZodObject\") return undefined;\n const shape = getShape(inner);\n cur = shape[seg];\n }\n return cur;\n}\n\n/** Best-effort runtime type label of a value, mirroring ExpectedType vocabulary. */\nexport function actualTypeOf(val: unknown): ExpectedType | \"null\" {\n if (val === null || val === undefined) return \"null\";\n if (val instanceof Date) return \"date\";\n if (Array.isArray(val)) return \"array\";\n if (typeof val === \"string\") return \"string\";\n if (typeof val === \"boolean\") return \"boolean\";\n if (typeof val === \"bigint\") return \"bigint\";\n if (typeof val === \"number\") return \"number\";\n if (typeof val === \"object\") {\n // Firestore Timestamp duck-typing\n if (typeof (val as any).toDate === \"function\") return \"date\";\n return \"object\";\n }\n return \"unknown\";\n}\n\n/** Return null if compatible; otherwise a tooltip message describing the mismatch. */\nexport function mismatchMessage(\n expected: ExpectedType,\n val: unknown,\n): string | null {\n if (expected === \"unknown\") return null;\n const actual = actualTypeOf(val);\n // Null is acceptable here — nullability is a separate concern handled by the schema (optional/nullable).\n if (actual === \"null\") return null;\n // enum/literal compatibility — both stored as primitives; we don't validate the value set here.\n if (expected === \"enum\" || expected === \"literal\") {\n if (actual === \"string\" || actual === \"number\") return null;\n return `Expected ${expected} (string/number), got ${actual}`;\n }\n if (expected === actual) return null;\n // Cross-compatible numerics: bigint vs number\n if (\n (expected === \"number\" && actual === \"bigint\") ||\n (expected === \"bigint\" && actual === \"number\")\n ) {\n return null;\n }\n return `Expected ${expected}, got ${actual}`;\n}\n","import type { FC } from \"hono/jsx\";\nimport { CellValue } from \"./cell-value\";\nimport type { ExpectedType } from \"./type-check\";\nimport { expectedTypeOf, mismatchMessage, resolveAtPath } from \"./type-check\";\n\n/** Slide-in right panel container — rendered once in the page shell, populated client-side. */\nexport const RightPanel: FC<{ basePath?: string }> = ({ basePath = \"\" }) => (\n <div\n class=\"fixed inset-0 z-[100] hidden pointer-events-none\"\n data-frs-panel-root\n data-frs-base-path={basePath}\n aria-hidden=\"true\"\n >\n {/* Backdrop */}\n <div\n class=\"absolute inset-0 bg-black/30 opacity-0 transition-opacity duration-200 pointer-events-auto\"\n data-frs-panel-backdrop\n />\n {/* Panel — 50% on md+, full-width on mobile */}\n <aside\n class=\"absolute top-0 right-0 h-full w-full md:w-1/2 bg-base-100 shadow-2xl border-l border-base-300 translate-x-full transition-transform duration-200 pointer-events-auto flex flex-col\"\n data-frs-panel\n role=\"dialog\"\n aria-label=\"Relation preview\"\n >\n <header class=\"flex items-center justify-between px-5 py-3 border-b border-base-300 bg-base-200/40 shrink-0\">\n <h2\n class=\"font-semibold text-base truncate\"\n data-frs-panel-title\n >\n Relation\n </h2>\n <button\n type=\"button\"\n class=\"btn btn-sm btn-ghost btn-circle\"\n data-frs-panel-close\n aria-label=\"Close panel\"\n >\n ✕\n </button>\n </header>\n <div\n class=\"flex-1 overflow-auto p-5 text-sm\"\n data-frs-panel-body\n >\n <div class=\"flex items-center justify-center py-12 text-base-content/40\">\n <span class=\"loading loading-spinner loading-md\" />\n </div>\n </div>\n </aside>\n </div>\n);\n\n// ---------------------------------------------------------------------------\n// Server-rendered HTML fragments served at GET /:repoName/_panel\n// (no <html>/<body> wrapper — they're injected into the panel body by JS)\n// ---------------------------------------------------------------------------\n\n/** Render the \"one\" relation preview: read-only field list + Edit/Open button. */\nexport function PanelOne({\n doc,\n repoName,\n basePath,\n schema,\n columns,\n}: {\n doc: Record<string, unknown> | null;\n repoName: string;\n basePath: string;\n schema?: import(\"zod\").ZodObject<any>;\n columns: string[];\n}) {\n if (!doc) {\n return (\n <div class=\"text-center py-12 text-base-content/50\">\n Document not found.\n </div>\n );\n }\n const id = String(doc[\"docId\"] ?? doc[\"id\"] ?? \"\");\n const editUrl = `${basePath}/${repoName}/${encodeURIComponent(id)}/edit`;\n const expectedTypes = buildExpectedMap(schema, columns);\n return (\n <div class=\"space-y-4\">\n <div class=\"flex items-center justify-between gap-2\">\n <div class=\"text-xs text-base-content/60\">\n <span class=\"font-mono\">{repoName}</span>\n <span class=\"opacity-50\"> · </span>\n <span class=\"font-mono break-all\">{id}</span>\n </div>\n <a href={editUrl} class=\"btn btn-sm btn-primary\">\n Edit →\n </a>\n </div>\n <dl class=\"grid grid-cols-[max-content_1fr] gap-x-4 gap-y-2 border border-base-300 rounded-box p-4 bg-base-100\">\n {columns.map((c) => {\n const val = doc[c];\n const expected = expectedTypes[c];\n const mismatch = expected ? mismatchMessage(expected, val) : null;\n return (\n <>\n <dt class=\"text-xs font-semibold text-base-content/60 uppercase tracking-wide pt-0.5\">\n {c}\n </dt>\n <dd class=\"min-w-0\">\n <CellValue val={val} mismatch={mismatch} />\n </dd>\n </>\n );\n })}\n </dl>\n </div>\n );\n}\n\n/** Render the \"many\" relation preview: full filtered list (compact table). */\nexport function PanelMany({\n docs,\n repoName,\n basePath,\n fk,\n fv,\n columns,\n schema,\n pagination,\n}: {\n docs: Record<string, unknown>[];\n repoName: string;\n basePath: string;\n fk: string;\n fv: string;\n columns: string[];\n schema?: import(\"zod\").ZodObject<any>;\n pagination: {\n hasPrev: boolean;\n hasNext: boolean;\n prevCursor: string;\n nextCursor: string;\n pageSize: number;\n };\n}) {\n const fullViewUrl = `${basePath}/${repoName}?fv_${fk}=${encodeURIComponent(fv)}`;\n const expectedTypes = buildExpectedMap(schema, columns);\n return (\n <div class=\"space-y-4\">\n <div class=\"flex items-center justify-between gap-2\">\n <div class=\"text-xs text-base-content/60\">\n <span class=\"font-mono\">{repoName}</span>\n <span class=\"opacity-50\"> where </span>\n <span class=\"font-mono\">{fk}</span>\n <span class=\"opacity-50\"> = </span>\n <span class=\"font-mono break-all\">{fv}</span>\n <span class=\"opacity-50\"> · </span>\n <span>\n {docs.length} doc{docs.length !== 1 ? \"s\" : \"\"}\n </span>\n </div>\n <a href={fullViewUrl} class=\"btn btn-sm btn-outline\">\n Full view →\n </a>\n </div>\n <div class=\"overflow-x-auto rounded-box border border-base-300 bg-base-100\">\n <table class=\"table table-xs w-full\">\n <thead>\n <tr class=\"bg-base-200/50\">\n {columns.map((c, i) => (\n <th\n key={i}\n class=\"text-xs font-semibold text-base-content/60 uppercase tracking-wide\"\n >\n {c}\n </th>\n ))}\n <th />\n </tr>\n </thead>\n <tbody>\n {docs.length === 0 ? (\n <tr>\n <td\n colspan={columns.length + 1}\n class=\"text-center py-10 text-base-content/40\"\n >\n No related documents\n </td>\n </tr>\n ) : (\n docs.map((d, ri) => {\n const id = String(d[\"docId\"] ?? d[\"id\"] ?? \"\");\n const editUrl = `${basePath}/${repoName}/${encodeURIComponent(id)}/edit`;\n return (\n <tr key={ri} class=\"hover\">\n {columns.map((c, ci) => {\n const val = d[c];\n const expected = expectedTypes[c];\n const mismatch = expected\n ? mismatchMessage(expected, val)\n : null;\n return (\n <td key={ci} class=\"align-top py-1.5\">\n <CellValue val={val} mismatch={mismatch} />\n </td>\n );\n })}\n <td class=\"text-right py-1.5\">\n <a href={editUrl} class=\"btn btn-xs btn-ghost\">\n Edit\n </a>\n </td>\n </tr>\n );\n })\n )}\n </tbody>\n </table>\n </div>\n {(pagination.hasPrev || pagination.hasNext) && (\n <div class=\"flex justify-center items-center gap-2\">\n {pagination.hasPrev ? (\n <button\n type=\"button\"\n class=\"btn btn-xs btn-outline\"\n data-frs-panel-page=\"prev\"\n data-cursor={pagination.prevCursor}\n >\n ← Previous\n </button>\n ) : (\n <button class=\"btn btn-xs btn-outline\" disabled>\n ← Previous\n </button>\n )}\n {pagination.hasNext ? (\n <button\n type=\"button\"\n class=\"btn btn-xs btn-outline\"\n data-frs-panel-page=\"next\"\n data-cursor={pagination.nextCursor}\n >\n Next →\n </button>\n ) : (\n <button class=\"btn btn-xs btn-outline\" disabled>\n Next →\n </button>\n )}\n </div>\n )}\n </div>\n );\n}\n\nfunction buildExpectedMap(\n schema: import(\"zod\").ZodObject<any> | undefined,\n columns: string[],\n): Record<string, ExpectedType> {\n if (!schema) return {};\n const out: Record<string, ExpectedType> = {};\n for (const c of columns) {\n out[c] = expectedTypeOf(resolveAtPath(schema, c));\n }\n return out;\n}\n","import type { Query, QuerySnapshot } from \"firebase-admin/firestore\";\nimport type { QueryOptions, WhereClause } from \"./shared/types\";\n\n/**\n * Chunk array into smaller arrays\n */\nfunction chunkArray<T>(array: T[], size: number): T[][] {\n const chunks: T[][] = [];\n for (let i = 0; i < array.length; i += size) {\n chunks.push(array.slice(i, i + size));\n }\n return chunks;\n}\n\n/**\n * Apply basic query options (orderBy, limit, offset, select, cursors)\n */\nfunction applyBasicQueryOptions<T>(q: Query, options: QueryOptions<T>): Query {\n if (options.orderBy) {\n options.orderBy.forEach((o) => {\n q = q.orderBy(String(o.field), o.direction ?? \"asc\");\n });\n }\n\n if (options.limit) {\n q = q.limit(options.limit);\n }\n\n if (options.offset) {\n q = q.offset(options.offset);\n }\n\n if (options.select && options.select.length > 0) {\n q = q.select(...options.select.map((f) => String(f)));\n }\n\n // Cursor-based pagination\n if (options.startAt) {\n q = Array.isArray(options.startAt)\n ? q.startAt(...options.startAt)\n : q.startAt(options.startAt);\n }\n\n if (options.startAfter) {\n q = Array.isArray(options.startAfter)\n ? q.startAfter(...options.startAfter)\n : q.startAfter(options.startAfter);\n }\n\n if (options.endAt) {\n q = Array.isArray(options.endAt)\n ? q.endAt(...options.endAt)\n : q.endAt(options.endAt);\n }\n\n if (options.endBefore) {\n q = Array.isArray(options.endBefore)\n ? q.endBefore(...options.endBefore)\n : q.endBefore(options.endBefore);\n }\n\n return q;\n}\n\n/**\n * Check if a where clause needs splitting (in or array-contains-any with > 30 values)\n */\nfunction needsSplitting<T>(clause: WhereClause<T>): boolean {\n const [, operator, value] = clause;\n return (\n (operator === \"in\" || operator === \"array-contains-any\") &&\n Array.isArray(value) &&\n value.length > 30\n );\n}\n\n/**\n * Split a where clause into multiple clauses (for in/array-contains-any)\n */\nfunction splitWhereClause<T>(clause: WhereClause<T>): WhereClause<T>[] {\n const [field, operator, value] = clause;\n\n if (!needsSplitting(clause)) {\n return [clause];\n }\n\n // Split array into chunks of 30\n const chunks = chunkArray(value as any[], 30);\n return chunks.map((chunk) => [field, operator, chunk] as WhereClause<T>);\n}\n\n/**\n * Apply where clauses to a query, handling splits for in/array-contains-any\n */\nfunction applyWhereClausesToQuery<T>(\n baseQuery: Query,\n whereClauses: WhereClause<T>[],\n): Query {\n let q = baseQuery;\n\n for (const [field, operator, value] of whereClauses) {\n q = q.where(String(field), operator, value);\n }\n\n return q;\n}\n\n/**\n * Execute multiple queries in parallel and merge results\n */\nasync function executeAndMergeQueries(\n queries: Query[],\n): Promise<QuerySnapshot> {\n const snapshots = await Promise.all(queries.map((q) => q.get()));\n\n // Merge all documents, removing duplicates by ID\n const docsMap = new Map();\n snapshots.forEach((snapshot) => {\n snapshot.docs.forEach((doc) => {\n if (!docsMap.has(doc.id)) {\n docsMap.set(doc.id, doc);\n }\n });\n });\n\n // Return first snapshot with merged docs\n const firstSnapshot = snapshots[0];\n if (!firstSnapshot) {\n throw new Error(\"No snapshots returned\");\n }\n\n // Create a merged snapshot-like object\n return {\n ...firstSnapshot,\n docs: Array.from(docsMap.values()),\n size: docsMap.size,\n empty: docsMap.size === 0,\n } as QuerySnapshot;\n}\n\n/**\n * Build and execute query with automatic splitting for in/array-contains-any\n * Handles both simple AND conditions and complex OR conditions\n */\nexport async function buildAndExecuteQuery<T>(\n baseQuery: Query,\n options: QueryOptions<T>,\n): Promise<QuerySnapshot> {\n const hasOrWhere = options.orWhere && options.orWhere.length > 0;\n const hasOrWhereGroups =\n options.orWhereGroups && options.orWhereGroups.length > 0;\n\n // Case 1: Pure AND query\n if (!hasOrWhere && !hasOrWhereGroups) {\n if (!options.where || options.where.length === 0) {\n const q = applyBasicQueryOptions(baseQuery, options);\n return q.get();\n }\n const needsSplit = options.where.some(needsSplitting);\n if (!needsSplit) {\n let q = applyWhereClausesToQuery(baseQuery, options.where);\n q = applyBasicQueryOptions(q, options);\n return q.get();\n }\n const splitClauses: WhereClause<T>[][] =\n options.where.map(splitWhereClause);\n const combinations = cartesianProduct(splitClauses);\n const queries = combinations.map((combination) => {\n let q = applyWhereClausesToQuery(baseQuery, combination);\n q = applyBasicQueryOptions(q, options);\n return q;\n });\n return executeAndMergeQueries(queries);\n }\n\n // Case 2: OR query — convert orWhere/orWhereGroups into OR groups,\n // then prepend base where conditions to every group.\n const baseClauses: WhereClause<T>[] = options.where ?? [];\n\n // Normalise: orWhere entries are single-clause groups;\n // orWhereGroups entries are multi-clause groups.\n const rawGroups: WhereClause<T>[][] = [\n ...(options.orWhere?.map((clause) => [clause]) ?? []),\n ...(options.orWhereGroups ?? []),\n ];\n\n const allQueries: Query[] = [];\n\n for (const orGroup of rawGroups) {\n // Merge base AND conditions into each OR group\n const fullGroup: WhereClause<T>[] = [...baseClauses, ...orGroup];\n const needsSplit = fullGroup.some(needsSplitting);\n\n if (!needsSplit) {\n let q = applyWhereClausesToQuery(baseQuery, fullGroup);\n q = applyBasicQueryOptions(q, options);\n allQueries.push(q);\n } else {\n const splitClauses = fullGroup.map(splitWhereClause);\n const combinations = cartesianProduct(splitClauses);\n const groupQueries = combinations.map((combination) => {\n let q = applyWhereClausesToQuery(baseQuery, combination);\n q = applyBasicQueryOptions(q, options);\n return q;\n });\n allQueries.push(...groupQueries);\n }\n }\n\n return executeAndMergeQueries(allQueries);\n}\n\n/**\n * Generate Cartesian product of arrays\n * Example: [[a,b], [1,2]] => [[a,1], [a,2], [b,1], [b,2]]\n */\nfunction cartesianProduct<T>(arrays: T[][]): T[][] {\n if (arrays.length === 0) return [[]];\n\n const first = arrays[0];\n if (arrays.length === 1 && first) {\n return first.map((item) => [item]);\n }\n\n if (!first) return [[]];\n\n const rest = arrays.slice(1);\n const restProduct = cartesianProduct(rest);\n\n const result: T[][] = [];\n for (const item of first) {\n for (const combo of restProduct) {\n result.push([item, ...combo]);\n }\n }\n\n return result;\n}\n","import { Timestamp } from \"firebase-admin/firestore\";\n\nexport type DateHandlingMode = \"preserve\" | \"normalize\";\n\nlet currentMode: DateHandlingMode = \"preserve\";\n\nexport function setDateHandling(mode: DateHandlingMode): void {\n currentMode = mode;\n}\n\nexport function getDateHandling(): DateHandlingMode {\n return currentMode;\n}\n\nfunction isTimestampLike(\n v: unknown,\n): v is { _seconds: number; _nanoseconds: number } {\n return (\n typeof v === \"object\" &&\n v !== null &&\n typeof (v as { _seconds?: unknown })._seconds === \"number\" &&\n typeof (v as { _nanoseconds?: unknown })._nanoseconds === \"number\"\n );\n}\n\nexport function coerceToDate(value: unknown): Date | null {\n if (value === null || value === undefined) return null;\n if (value instanceof Date) return Number.isNaN(value.getTime()) ? null : value;\n if (value instanceof Timestamp) return value.toDate();\n if (isTimestampLike(value)) {\n return new Date(\n value._seconds * 1000 + Math.floor(value._nanoseconds / 1e6),\n );\n }\n if (typeof value === \"string\") {\n const d = new Date(value);\n return Number.isNaN(d.getTime()) ? null : d;\n }\n if (typeof value === \"number\") {\n const d = new Date(value);\n return Number.isNaN(d.getTime()) ? null : d;\n }\n return null;\n}\n\nfunction isPlainObject(v: unknown): v is Record<string, unknown> {\n if (typeof v !== \"object\" || v === null) return false;\n const proto = Object.getPrototypeOf(v);\n return proto === Object.prototype || proto === null;\n}\n\nexport function normalizeTimestamps<T>(value: T): T {\n if (value instanceof Timestamp) return value.toDate() as unknown as T;\n if (Array.isArray(value)) {\n return value.map((v) => normalizeTimestamps(v)) as unknown as T;\n }\n if (isPlainObject(value)) {\n const out: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(value)) {\n out[k] = normalizeTimestamps(v);\n }\n return out as unknown as T;\n }\n return value;\n}\n\nexport function maybeNormalize<T>(value: T): T {\n return currentMode === \"normalize\" ? normalizeTimestamps(value) : value;\n}\n","import type { Query } from \"firebase-admin/firestore\";\nimport type { QueryOptions } from \"./types\";\n\n/**\n * Split an array into chunks of specified size\n */\nexport function chunkArray<T>(array: T[], size: number): T[][] {\n const chunks: T[][] = [];\n for (let i = 0; i < array.length; i += size) {\n chunks.push(array.slice(i, i + size));\n }\n return chunks;\n}\n\n/**\n * Capitalize first letter of a string\n */\nexport function capitalize(str: string): string {\n return str.charAt(0).toUpperCase() + str.slice(1);\n}\n\n/**\n * Apply QueryOptions to a Firestore query.\n * Handles where, orderBy, limit, offset, select and cursor-based pagination.\n * Does NOT handle orWhere — use buildAndExecuteQuery for that.\n */\nexport function applyQueryOptions<T>(\n q: Query,\n options: QueryOptions<T>,\n): Query {\n if (options.where) {\n options.where.forEach(([field, operator, value]) => {\n q = q.where(String(field), operator, value);\n });\n }\n\n if (options.orderBy) {\n options.orderBy.forEach((o) => {\n q = q.orderBy(String(o.field), o.direction ?? \"asc\");\n });\n }\n\n if (options.limit) {\n q = q.limit(options.limit);\n }\n\n if (options.offset) {\n q = q.offset(options.offset);\n }\n\n if (options.select && options.select.length > 0) {\n q = q.select(...options.select.map((f) => String(f)));\n }\n\n if (options.startAt) {\n q = Array.isArray(options.startAt)\n ? q.startAt(...options.startAt)\n : q.startAt(options.startAt);\n }\n\n if (options.startAfter) {\n q = Array.isArray(options.startAfter)\n ? q.startAfter(...options.startAfter)\n : q.startAfter(options.startAfter);\n }\n\n if (options.endAt) {\n q = Array.isArray(options.endAt)\n ? q.endAt(...options.endAt)\n : q.endAt(options.endAt);\n }\n\n if (options.endBefore) {\n q = Array.isArray(options.endBefore)\n ? q.endBefore(...options.endBefore)\n : q.endBefore(options.endBefore);\n }\n\n return q;\n}\n","import type { DocumentSnapshot, Query } from \"firebase-admin/firestore\";\nimport { buildAndExecuteQuery } from \"./query-builder\";\nimport { maybeNormalize } from \"./shared/date-config\";\nimport type { QueryOptions } from \"./shared/types\";\nimport { applyQueryOptions } from \"./shared/utils\";\n\nexport { applyQueryOptions };\n\n/**\n * Pagination result with data and cursor information\n * @template T - Data model type\n */\nexport interface PaginationResult<T> {\n /** Array of documents for the current page */\n data: T[];\n /** Cursor to the next page (undefined if no more pages) */\n nextCursor?: DocumentSnapshot;\n /** Cursor to the previous page (undefined if on first page) */\n prevCursor?: DocumentSnapshot;\n /** Whether there are more pages after this one */\n hasNextPage: boolean;\n /** Whether there are pages before this one */\n hasPrevPage: boolean;\n /** Total number of items in current page */\n pageSize: number;\n}\n\n/**\n * Pagination options for cursor-based pagination\n * @template T - Data model type\n */\nexport interface PaginationOptions<T> extends Omit<QueryOptions<T>, \"limit\"> {\n /** Number of items per page */\n pageSize: number;\n /** Cursor to start after (for next page) */\n cursor?: DocumentSnapshot;\n /** Direction of pagination */\n direction?: \"next\" | \"prev\";\n}\n\n/**\n * Executes a paginated query and returns results with pagination info.\n * Uses the advanced query builder that handles OR conditions and automatic splitting.\n *\n * @template T - Data model type\n * @param baseQuery - Base Firestore query\n * @param options - Pagination options\n * @returns Pagination result with data and cursor information\n *\n * @example\n * ```typescript\n * // Basic pagination\n * const firstPage = await executePaginatedQuery(collectionRef, {\n * pageSize: 10\n * });\n * console.log(firstPage.data); // Array of 10 items\n * console.log(firstPage.hasNextPage); // true if more pages exist\n *\n * // Get next page using cursor\n * if (firstPage.hasNextPage) {\n * const secondPage = await executePaginatedQuery(collectionRef, {\n * pageSize: 10,\n * cursor: firstPage.nextCursor,\n * direction: \"next\"\n * });\n * }\n *\n * // Pagination with filters and sorting\n * const filteredPage = await executePaginatedQuery(collectionRef, {\n * pageSize: 20,\n * where: [[\"status\", \"==\", \"active\"]],\n * orderBy: [[\"createdAt\", \"desc\"]],\n * select: [\"title\", \"status\", \"createdAt\"]\n * });\n *\n * // Pagination with OR conditions\n * const orPage = await executePaginatedQuery(collectionRef, {\n * pageSize: 10,\n * orWhere: [\n * [\"status\", \"==\", \"published\"],\n * [\"status\", \"==\", \"featured\"]\n * ]\n * });\n *\n * // Go to previous page\n * const prevPage = await executePaginatedQuery(collectionRef, {\n * pageSize: 10,\n * cursor: currentPage.prevCursor,\n * direction: \"prev\"\n * });\n * ```\n */\nexport async function executePaginatedQuery<T>(\n baseQuery: Query,\n options: PaginationOptions<T>,\n): Promise<PaginationResult<T>> {\n // Prepare options with cursor-based pagination\n const queryOptions: QueryOptions<T> = {\n ...options,\n limit: options.pageSize + 1, // Fetch one extra to check if there's a next page\n };\n\n // Apply cursor\n if (options.cursor) {\n if (options.direction === \"prev\") {\n queryOptions.endBefore = options.cursor;\n } else {\n queryOptions.startAfter = options.cursor;\n }\n }\n\n // Use the advanced query builder (handles OR and auto-splitting)\n const snapshot = await buildAndExecuteQuery(baseQuery, queryOptions);\n const docs = snapshot.docs;\n\n // Check if there are more pages\n const hasMore = docs.length > options.pageSize;\n const actualDocs = hasMore ? docs.slice(0, options.pageSize) : docs;\n\n const data = actualDocs.map((doc) =>\n maybeNormalize({\n ...doc.data(),\n docId: doc.id,\n }),\n ) as T[];\n\n const isPrev = options.direction === \"prev\";\n\n return {\n data,\n // When going \"prev\": nextCursor always points to last doc of the page (to go forward\n // again), prevCursor only set when there are even earlier docs (hasMore).\n // When going \"next\" (default): same logic as before.\n nextCursor: isPrev\n ? actualDocs.length > 0\n ? actualDocs[actualDocs.length - 1]\n : undefined\n : hasMore\n ? actualDocs[actualDocs.length - 1]\n : undefined,\n prevCursor: isPrev ? (hasMore ? actualDocs[0] : undefined) : actualDocs[0],\n hasNextPage: isPrev ? !!options.cursor : hasMore,\n hasPrevPage: isPrev ? hasMore : !!options.cursor,\n pageSize: data.length,\n };\n}\n\n/**\n * Creates an async generator for iterating through all pages.\n * Useful for processing large datasets without loading everything into memory.\n *\n * @template T - Data model type\n * @param baseQuery - Base Firestore query\n * @param options - Pagination options (without cursor)\n * @yields Pagination results for each page\n *\n * @example\n * ```typescript\n * // Basic iteration through all pages\n * const pageIterator = createPaginationIterator(query, { pageSize: 100 });\n * for await (const page of pageIterator) {\n * console.log(`Processing ${page.data.length} items`);\n * for (const item of page.data) {\n * await processItem(item);\n * }\n * }\n *\n * // With filters and sorting\n * const filteredIterator = createPaginationIterator(query, {\n * pageSize: 50,\n * where: [[\"status\", \"==\", \"pending\"]],\n * orderBy: [[\"createdAt\", \"asc\"]]\n * });\n *\n * let totalProcessed = 0;\n * for await (const page of filteredIterator) {\n * totalProcessed += page.data.length;\n * console.log(`Processed ${totalProcessed} items so far`);\n * }\n *\n * // Export all data to CSV\n * const allData: User[] = [];\n * for await (const page of createPaginationIterator(usersQuery, { pageSize: 500 })) {\n * allData.push(...page.data);\n * }\n * exportToCsv(allData);\n *\n * // Early exit if condition met\n * for await (const page of createPaginationIterator(query, { pageSize: 100 })) {\n * const found = page.data.find(item => item.id === targetId);\n * if (found) {\n * console.log(\"Found target item!\");\n * break; // Stop iteration early\n * }\n * }\n * ```\n */\nexport async function* createPaginationIterator<T>(\n baseQuery: Query,\n options: Omit<PaginationOptions<T>, \"cursor\" | \"direction\">,\n): AsyncGenerator<PaginationResult<T>, void, unknown> {\n let cursor: DocumentSnapshot | undefined;\n let hasMore = true;\n\n while (hasMore) {\n const result = await executePaginatedQuery<T>(baseQuery, {\n ...options,\n cursor,\n direction: \"next\",\n });\n\n yield result;\n\n hasMore = result.hasNextPage;\n cursor = result.nextCursor;\n }\n}\n","/**\n * Diff helper for the history module.\n *\n * Computes a top-level shallow diff between two snapshots of the same\n * document. Returns an empty changes object when nothing relevant changed.\n *\n * Meta fields, system keys (docId / pathKey / createdKey / updatedKey) and\n * any field listed in `exclude` are filtered out. When `include` is set, only\n * the listed fields are considered.\n */\n\nimport { Timestamp } from \"firebase-admin/firestore\";\nimport type {\n HistoryFieldChange,\n HistoryValueType,\n} from \"./types\";\n\nexport interface DiffOptions {\n include?: string[];\n exclude?: string[];\n /** Field names that hold meta info (auto-excluded from diff). */\n metaFields?: string[];\n /** System keys auto-excluded (docId, pathKey, createdKey, updatedKey). */\n systemKeys?: string[];\n}\n\nexport function valueType(v: unknown): HistoryValueType {\n if (v === null) return \"null\";\n if (v === undefined) return \"undefined\";\n if (v instanceof Timestamp) return \"timestamp\";\n if (v instanceof Date) return \"date\";\n if (Array.isArray(v)) return \"array\";\n const t = typeof v;\n if (t === \"string\" || t === \"number\" || t === \"boolean\") return t;\n return \"object\";\n}\n\n/** Cheap structural equality good enough for change detection. */\nexport function valuesEqual(a: unknown, b: unknown): boolean {\n if (a === b) return true;\n if (a === null || b === null || a === undefined || b === undefined) {\n return a === b;\n }\n\n if (a instanceof Timestamp && b instanceof Timestamp) {\n return a.isEqual(b);\n }\n if (a instanceof Date && b instanceof Date) {\n return a.getTime() === b.getTime();\n }\n\n if (Array.isArray(a) && Array.isArray(b)) {\n if (a.length !== b.length) return false;\n for (let i = 0; i < a.length; i++) {\n if (!valuesEqual(a[i], b[i])) return false;\n }\n return true;\n }\n\n if (typeof a === \"object\" && typeof b === \"object\") {\n try {\n return JSON.stringify(a) === JSON.stringify(b);\n } catch {\n return false;\n }\n }\n\n return false;\n}\n\n/**\n * Compute a flat top-level diff. Nested objects are compared as a whole — they\n * appear in the diff if changed but are NOT decomposed key by key.\n */\nexport function computeDiff<T extends Record<string, unknown>>(\n before: T | null | undefined,\n after: T | null | undefined,\n opts: DiffOptions = {},\n): Record<string, HistoryFieldChange> {\n const excludeSet = new Set<string>([\n ...(opts.exclude ?? []),\n ...(opts.metaFields ?? []),\n ...(opts.systemKeys ?? []),\n ]);\n const includeSet = opts.include ? new Set<string>(opts.include) : null;\n\n const beforeObj = (before ?? {}) as Record<string, unknown>;\n const afterObj = (after ?? {}) as Record<string, unknown>;\n\n const keys = new Set<string>([\n ...Object.keys(beforeObj),\n ...Object.keys(afterObj),\n ]);\n\n const changes: Record<string, HistoryFieldChange> = {};\n for (const key of keys) {\n if (excludeSet.has(key)) continue;\n if (includeSet && !includeSet.has(key)) continue;\n\n const oldValue = beforeObj[key];\n const newValue = afterObj[key];\n if (valuesEqual(oldValue, newValue)) continue;\n\n changes[key] = {\n oldValue: oldValue === undefined ? null : oldValue,\n newValue: newValue === undefined ? null : newValue,\n type: { old: valueType(oldValue), new: valueType(newValue) },\n };\n }\n\n return changes;\n}\n","/**\n * v1 ↔ v2 normalisation. The reader returns a unified {@link HistoryEntry}\n * shape regardless of which schema version a Firestore document was written\n * with.\n *\n * v2 doc → pass-through.\n * v1 doc (single field per doc) → wrapped into a 1-field unified entry.\n * Consecutive v1 docs that share the same `historySetAt` timestamp\n * (within a small tolerance) are merged into a single entry, mimicking\n * the original \"one update -> N field docs\" intent.\n */\n\nimport { Timestamp } from \"firebase-admin/firestore\";\nimport type {\n HistoryEntry,\n HistoryFieldChange,\n HistoryMeta,\n HistoryValueType,\n V1HistoryDoc,\n V2HistoryDoc,\n} from \"./types\";\nimport { valueType } from \"./diff\";\n\n/** Default tolerance (ms) used to group v1 docs from the same update. */\nexport const DEFAULT_GROUP_TOLERANCE_MS = 5;\n\ntype AnyHistoryDoc = (V1HistoryDoc | V2HistoryDoc) & Record<string, unknown>;\n\nfunction isV2(doc: AnyHistoryDoc): doc is V2HistoryDoc & Record<string, unknown> {\n return doc.schemaVersion === 2;\n}\n\nfunction legacyTypeToHistoryType(t: unknown): HistoryValueType {\n if (typeof t !== \"string\") return \"object\";\n switch (t) {\n case \"string\":\n case \"number\":\n case \"boolean\":\n case \"object\":\n case \"array\":\n case \"timestamp\":\n case \"date\":\n case \"null\":\n case \"undefined\":\n return t;\n default:\n return \"object\";\n }\n}\n\nfunction v2ToEntry(doc: V2HistoryDoc): HistoryEntry {\n return {\n historyDocId: doc.historyDocId,\n historyToObjectId: doc.historyToObjectId,\n historySetAt: doc.historySetAt,\n schemaVersion: 2,\n operation: doc.operation,\n meta: doc.meta ?? {},\n changes: doc.changes ?? {},\n };\n}\n\nfunction v1MetaOf(doc: V1HistoryDoc & Record<string, unknown>): HistoryMeta {\n const meta: HistoryMeta = {};\n if (doc.historyUserId !== undefined) meta.userId = doc.historyUserId ?? null;\n if (doc.historyUserEmail !== undefined)\n meta.userEmail = doc.historyUserEmail ?? null;\n\n const extra = doc.extraHistoryDetails ?? null;\n if (extra) {\n if (extra.reason !== undefined) meta.reason = extra.reason ?? null;\n if (extra.comment !== undefined) meta.comment = extra.comment ?? null;\n }\n\n const extras: Record<string, unknown> = {};\n let anyExtra = false;\n if (doc.historyDetails && typeof doc.historyDetails === \"object\") {\n for (const [k, v] of Object.entries(doc.historyDetails)) {\n extras[k] = v;\n anyExtra = true;\n }\n }\n if (doc.extraContentKeys && typeof doc.extraContentKeys === \"object\") {\n for (const [k, v] of Object.entries(doc.extraContentKeys)) {\n extras[`content.${k}`] = v;\n anyExtra = true;\n }\n }\n if (anyExtra) meta.extras = extras;\n return meta;\n}\n\nfunction v1FieldChange(doc: V1HistoryDoc): HistoryFieldChange {\n const oldValue = doc.changes?.oldValue ?? null;\n const newValue = doc.changes?.newValue ?? null;\n const declaredOld = doc.types?.oldValue;\n const declaredNew = doc.types?.newValue;\n return {\n oldValue,\n newValue,\n type: {\n old: declaredOld\n ? legacyTypeToHistoryType(declaredOld)\n : valueType(oldValue),\n new: declaredNew\n ? legacyTypeToHistoryType(declaredNew)\n : valueType(newValue),\n },\n };\n}\n\nfunction v1ToEntry(doc: V1HistoryDoc): HistoryEntry {\n const change = v1FieldChange(doc);\n const meta = v1MetaOf(doc as V1HistoryDoc & Record<string, unknown>);\n return {\n historyDocId: doc.historyDocId,\n historyToObjectId: doc.historyToObjectId,\n historySetAt: doc.historySetAt,\n schemaVersion: 1,\n operation: \"update\",\n meta,\n changes: { [doc.field]: change },\n };\n}\n\nfunction tsClose(a: Timestamp, b: Timestamp, toleranceMs: number): boolean {\n return Math.abs(a.toMillis() - b.toMillis()) <= toleranceMs;\n}\n\nfunction sameAuthor(a: HistoryMeta, b: HistoryMeta): boolean {\n return (a.userId ?? null) === (b.userId ?? null);\n}\n\n/**\n * Normalise a list of raw Firestore docs into unified {@link HistoryEntry}.\n * The input list MUST be sorted by `historySetAt` (asc or desc — the function\n * preserves order). v1 docs sharing the same timestamp + author are merged.\n */\nexport function normalizeHistoryDocs(\n docs: AnyHistoryDoc[],\n opts: { groupToleranceMs?: number } = {},\n): HistoryEntry[] {\n const tol = opts.groupToleranceMs ?? DEFAULT_GROUP_TOLERANCE_MS;\n const out: HistoryEntry[] = [];\n\n for (const doc of docs) {\n if (isV2(doc)) {\n out.push(v2ToEntry(doc));\n continue;\n }\n\n const v1 = doc as V1HistoryDoc;\n const entry = v1ToEntry(v1);\n\n const last = out[out.length - 1];\n if (\n last &&\n last.schemaVersion === 1 &&\n tsClose(last.historySetAt, entry.historySetAt, tol) &&\n sameAuthor(last.meta, entry.meta)\n ) {\n // Merge into the previous v1 entry (same logical update).\n Object.assign(last.changes, entry.changes);\n // Keep earliest historyDocId (stable id of the group).\n } else {\n out.push(entry);\n }\n }\n\n return out;\n}\n","/**\n * Write helpers for history entries.\n *\n * Builds a {@link V2HistoryDoc} from a diff + meta payload and writes it to\n * the entity's history subcollection. Used by {@link createHistoryTriggers}\n * and by the optional `repo.history.recordManual(...)` API.\n */\n\nimport {\n Timestamp,\n type CollectionReference,\n} from \"firebase-admin/firestore\";\nimport { randomUUID } from \"node:crypto\";\nimport type {\n HistoryConfigForModel,\n HistoryFieldChange,\n HistoryMeta,\n HistoryOperation,\n V2HistoryDoc,\n} from \"./types\";\n\nexport interface BuildEntryParams<T> {\n entityId: string;\n operation: HistoryOperation;\n changes: Record<string, HistoryFieldChange>;\n meta: HistoryMeta;\n config: HistoryConfigForModel<T>;\n ttlOverride?: { days: number };\n}\n\n/** Soft size guard — leave ~300 KiB headroom under Firestore's 1 MiB limit. */\nconst MAX_DOC_BYTES = 700_000;\n\nexport function buildHistoryEntry<T>(\n params: BuildEntryParams<T>,\n): V2HistoryDoc {\n const ttl = params.ttlOverride ?? params.config.ttl;\n const id = randomUUID();\n const entry: V2HistoryDoc = {\n schemaVersion: 2,\n historyDocId: id,\n historyToObjectId: params.entityId,\n historySetAt: Timestamp.now(),\n operation: params.operation,\n meta: params.meta,\n changes: params.changes,\n };\n if (ttl) {\n entry.expiresAt = Timestamp.fromMillis(\n Date.now() + ttl.days * 24 * 60 * 60 * 1000,\n );\n }\n\n // Soft size guard — if the JSON projection of `changes` is too large,\n // truncate large fields and mark the doc.\n const sizeOf = (obj: unknown): number => {\n try {\n return Buffer.byteLength(\n JSON.stringify(obj, (_k, v) => {\n if (v instanceof Timestamp) return v.toMillis();\n return v;\n }),\n \"utf8\",\n );\n } catch {\n return 0;\n }\n };\n\n if (sizeOf(entry.changes) > MAX_DOC_BYTES) {\n const truncated: Record<string, HistoryFieldChange> = {};\n for (const [k, change] of Object.entries(entry.changes)) {\n const oldSize = sizeOf(change.oldValue);\n const newSize = sizeOf(change.newValue);\n truncated[k] = {\n oldValue:\n oldSize > 50_000 ? \"[truncated]\" : change.oldValue,\n newValue:\n newSize > 50_000 ? \"[truncated]\" : change.newValue,\n type: change.type,\n };\n }\n entry.changes = truncated;\n entry._truncated = true;\n }\n\n return entry;\n}\n\nexport interface WriteEntryResult {\n written: boolean;\n entry?: V2HistoryDoc;\n reason?: string;\n}\n\n/**\n * Write a single history entry to the given subcollection reference.\n * Returns `{ written: false }` when the entry was dropped by `onBeforeWrite`.\n */\nexport async function writeHistoryEntry<T>(\n historyRef: CollectionReference,\n entry: V2HistoryDoc,\n config: HistoryConfigForModel<T>,\n ctx: { repoName: string; docId: string; before: T | null; after: T | null },\n): Promise<WriteEntryResult> {\n let toWrite: V2HistoryDoc | null = entry;\n if (config.onBeforeWrite) {\n toWrite = await config.onBeforeWrite(entry, ctx);\n }\n if (!toWrite) return { written: false, reason: \"dropped-by-onBeforeWrite\" };\n\n await historyRef.doc(toWrite.historyDocId).set(toWrite);\n return { written: true, entry: toWrite };\n}\n\n/**\n * Extract meta values from a Firestore document snapshot using the\n * declared meta config. Missing fields become `null`.\n */\nexport function extractMeta<T>(\n source: Record<string, unknown> | null | undefined,\n config: HistoryConfigForModel<T>,\n): HistoryMeta {\n const src = source ?? {};\n const meta: HistoryMeta = {};\n const m = config.meta;\n if (!m) return meta;\n\n const pickStr = (key?: string): string | null | undefined => {\n if (!key) return undefined;\n const v = src[key];\n if (v === undefined) return null;\n return v === null ? null : String(v);\n };\n\n const userId = pickStr(m.userId);\n if (userId !== undefined) meta.userId = userId;\n const userEmail = pickStr(m.userEmail);\n if (userEmail !== undefined) meta.userEmail = userEmail;\n const reason = pickStr(m.reason);\n if (reason !== undefined) meta.reason = reason;\n const comment = pickStr(m.comment);\n if (comment !== undefined) meta.comment = comment;\n\n if (m.extras && m.extras.length > 0) {\n const extras: Record<string, unknown> = {};\n let any = false;\n for (const k of m.extras) {\n if (k in src) {\n extras[k] = src[k];\n any = true;\n }\n }\n if (any) meta.extras = extras;\n }\n\n return meta;\n}\n\n/**\n * Returns all field names that should be excluded from the diff because\n * they're declared as meta fields (so we don't log them as their own change).\n */\nexport function metaFieldsOf<T>(config: HistoryConfigForModel<T>): string[] {\n const m = config.meta;\n if (!m) return [];\n const list: string[] = [];\n if (m.userId) list.push(m.userId);\n if (m.userEmail) list.push(m.userEmail);\n if (m.reason) list.push(m.reason);\n if (m.comment) list.push(m.comment);\n if (m.extras) list.push(...m.extras);\n return list;\n}\n","/**\n * `repo.history.*` read API.\n *\n * - `list(docId, opts)` → unified, paginated, normalised entries (v1 + v2).\n * - `raw(docId, opts)` → raw Firestore docs (no normalisation).\n * - `byField(docId, field, opts)` / `byOperation(docId, op, opts)` →\n * convenience wrappers.\n * - `recordManual(docId, payload)` → bypass the trigger and write a v2 entry\n * synchronously (use sparingly; prefer trigger-based capture).\n */\n\nimport {\n Timestamp,\n type CollectionReference,\n type DocumentReference,\n} from \"firebase-admin/firestore\";\nimport { computeDiff } from \"./diff\";\nimport { normalizeHistoryDocs } from \"./normalize\";\nimport {\n buildHistoryEntry,\n extractMeta,\n metaFieldsOf,\n writeHistoryEntry,\n} from \"./write\";\nimport type {\n HistoryConfigForModel,\n HistoryEntry,\n HistoryListOptions,\n HistoryMeta,\n HistoryOperation,\n HistoryRawListOptions,\n V1HistoryDoc,\n V2HistoryDoc,\n} from \"./types\";\n\nconst DEFAULT_SUBCOLLECTION = \"history\";\nconst DEFAULT_LIMIT = 50;\n\nfunction getHistoryRef(\n documentRef: (...args: any[]) => DocumentReference,\n subcollection: string,\n args: any[],\n): CollectionReference {\n const docRef = documentRef(...args);\n return docRef.collection(subcollection);\n}\n\nfunction getDocId(args: any[]): string {\n return String(args[args.length - 1] ?? \"\");\n}\n\n/**\n * Build the `repo.history` API for a given configured repository.\n * Returns `null` when history is not enabled — the factory then skips\n * exposing the namespace.\n */\nexport function createHistoryMethods<T>(\n documentRef: (...args: any[]) => DocumentReference,\n systemKeys: string[],\n repoName: string,\n config: HistoryConfigForModel<T> & { enabled: boolean },\n) {\n if (!config?.enabled) return null;\n\n const subcollection = config.subcollection ?? DEFAULT_SUBCOLLECTION;\n\n async function raw(\n ...args: any[]\n ): Promise<Array<{ id: string; data: V1HistoryDoc | V2HistoryDoc }>> {\n let opts: HistoryRawListOptions = {};\n let pathArgs = args;\n const last = args[args.length - 1];\n if (\n last !== null &&\n typeof last === \"object\" &&\n !(last instanceof Timestamp) &&\n (\"limit\" in last || \"cursor\" in last || \"direction\" in last)\n ) {\n opts = last as HistoryRawListOptions;\n pathArgs = args.slice(0, -1);\n }\n\n const ref = getHistoryRef(documentRef, subcollection, pathArgs);\n const direction = opts.direction ?? \"desc\";\n let q = ref.orderBy(\"historySetAt\", direction);\n if (opts.cursor) q = q.startAfter(opts.cursor);\n if (opts.limit && opts.limit > 0) q = q.limit(opts.limit);\n\n const snap = await q.get();\n return snap.docs.map((d) => ({\n id: d.id,\n data: d.data() as V1HistoryDoc | V2HistoryDoc,\n }));\n }\n\n async function list(\n ...args: any[]\n ): Promise<HistoryEntry<T>[]> {\n let opts: HistoryListOptions<T> = {};\n let pathArgs = args;\n const last = args[args.length - 1];\n if (\n last !== null &&\n typeof last === \"object\" &&\n !(last instanceof Timestamp) &&\n (\"limit\" in last ||\n \"cursor\" in last ||\n \"direction\" in last ||\n \"fields\" in last ||\n \"operations\" in last)\n ) {\n opts = last as HistoryListOptions<T>;\n pathArgs = args.slice(0, -1);\n }\n\n const limit = opts.limit ?? DEFAULT_LIMIT;\n // Read a bit more from Firestore because v1 entries get merged afterwards.\n // Cap at limit * 8 to avoid pathological reads.\n const fetchLimit = Math.max(limit, Math.min(limit * 8, 500));\n\n const rawDocs = await raw(...pathArgs, {\n limit: fetchLimit,\n cursor: opts.cursor,\n direction: opts.direction ?? \"desc\",\n });\n\n let entries = normalizeHistoryDocs(\n rawDocs.map((d) => d.data) as any[],\n ) as HistoryEntry<T>[];\n\n if (opts.fields && opts.fields.length > 0) {\n const set = new Set<string>(opts.fields as string[]);\n entries = entries.filter((e) =>\n Object.keys(e.changes).some((k) => set.has(k)),\n );\n }\n if (opts.operations && opts.operations.length > 0) {\n const set = new Set<HistoryOperation>(opts.operations);\n entries = entries.filter((e) => set.has(e.operation));\n }\n\n return entries.slice(0, limit);\n }\n\n async function byField(\n ...args: any[]\n ): Promise<HistoryEntry<T>[]> {\n const last = args[args.length - 1];\n let opts: HistoryListOptions<T> = {};\n let field: keyof T & string;\n let pathArgs: any[];\n if (last !== null && typeof last === \"object\" && !(last instanceof Timestamp)) {\n opts = last as HistoryListOptions<T>;\n field = args[args.length - 2] as keyof T & string;\n pathArgs = args.slice(0, -2);\n } else {\n field = last as keyof T & string;\n pathArgs = args.slice(0, -1);\n }\n return list(...pathArgs, { ...opts, fields: [field] });\n }\n\n async function byOperation(\n ...args: any[]\n ): Promise<HistoryEntry<T>[]> {\n const last = args[args.length - 1];\n let opts: HistoryListOptions<T> = {};\n let op: HistoryOperation;\n let pathArgs: any[];\n if (last !== null && typeof last === \"object\" && !(last instanceof Timestamp)) {\n opts = last as HistoryListOptions<T>;\n op = args[args.length - 2] as HistoryOperation;\n pathArgs = args.slice(0, -2);\n } else {\n op = last as HistoryOperation;\n pathArgs = args.slice(0, -1);\n }\n return list(...pathArgs, { ...opts, operations: [op] });\n }\n\n /**\n * Manually record a history entry. Bypasses the trigger and lets the caller\n * pass an explicit before/after pair plus meta (useful for synchronous flows\n * that need richer context than what the trigger can extract).\n */\n async function recordManual(\n ...args: any[]\n ): Promise<HistoryEntry<T> | null> {\n const payload = args[args.length - 1] as {\n operation: HistoryOperation;\n before?: T | null;\n after?: T | null;\n meta?: HistoryMeta;\n };\n const pathArgs = args.slice(0, -1);\n const entityId = getDocId(pathArgs);\n\n const changes = computeDiff(\n (payload.before ?? {}) as Record<string, unknown>,\n (payload.after ?? {}) as Record<string, unknown>,\n {\n include: config.include as string[] | undefined,\n exclude: config.exclude as string[] | undefined,\n metaFields: metaFieldsOf(config),\n systemKeys,\n },\n );\n if (\n payload.operation === \"update\" &&\n Object.keys(changes).length === 0\n ) {\n return null;\n }\n\n const fallbackMeta = extractMeta(\n (payload.after ?? payload.before ?? null) as Record<string, unknown> | null,\n config,\n );\n const meta: HistoryMeta = { ...fallbackMeta, ...(payload.meta ?? {}) };\n\n const entry = buildHistoryEntry({\n entityId,\n operation: payload.operation,\n changes,\n meta,\n config,\n });\n\n const ref = getHistoryRef(documentRef, subcollection, pathArgs);\n const result = await writeHistoryEntry(ref, entry, config, {\n repoName,\n docId: entityId,\n before: payload.before ?? null,\n after: payload.after ?? null,\n });\n if (!result.written || !result.entry) return null;\n\n return {\n historyDocId: result.entry.historyDocId,\n historyToObjectId: result.entry.historyToObjectId,\n historySetAt: result.entry.historySetAt,\n schemaVersion: 2,\n operation: result.entry.operation,\n meta: result.entry.meta,\n changes: result.entry.changes,\n } as HistoryEntry<T>;\n }\n\n return { list, raw, byField, byOperation, recordManual };\n}\n\nexport type HistoryMethods<T> = NonNullable<\n ReturnType<typeof createHistoryMethods<T>>\n>;\n","import type { Query } from \"firebase-admin/firestore\";\nimport type { QueryOptions } from \"../shared/types\";\nimport { applyQueryOptions } from \"../shared/utils\";\n\n/**\n * Creates aggregate methods for server-side computations.\n * These operations are executed on the Firestore server for optimal performance.\n *\n * @param collectionRef - Firestore query reference\n * @returns Object containing aggregate methods (count, sum, average)\n *\n * @example\n * ```typescript\n * // COUNT - Count all documents\n * const totalUsers = await repos.users.aggregate.count();\n *\n * // Count with filter\n * const activeUsers = await repos.users.aggregate.count({\n * where: [[\"isActive\", \"==\", true]]\n * });\n *\n * // Count with complex filters\n * const premiumActiveUsers = await repos.users.aggregate.count({\n * where: [\n * [\"isActive\", \"==\", true],\n * [\"subscription\", \"==\", \"premium\"]\n * ]\n * });\n *\n * // SUM - Sum of a numeric field\n * const totalRevenue = await repos.orders.aggregate.sum(\"amount\");\n *\n * // Sum with filter\n * const monthlyRevenue = await repos.orders.aggregate.sum(\"amount\", {\n * where: [\n * [\"createdAt\", \">=\", startOfMonth],\n * [\"createdAt\", \"<=\", endOfMonth]\n * ]\n * });\n *\n * // AVERAGE - Average of a numeric field\n * const avgOrderValue = await repos.orders.aggregate.average(\"amount\");\n *\n * // Average with filter\n * const avgPremiumOrder = await repos.orders.aggregate.average(\"amount\", {\n * where: [[\"customerType\", \"==\", \"premium\"]]\n * });\n *\n * // Returns null if no matching documents\n * const avgEmpty = await repos.orders.aggregate.average(\"amount\", {\n * where: [[\"status\", \"==\", \"nonexistent\"]]\n * }); // null\n *\n * // Combine multiple aggregations\n * const [total, sum, avg] = await Promise.all([\n * repos.orders.aggregate.count(),\n * repos.orders.aggregate.sum(\"amount\"),\n * repos.orders.aggregate.average(\"amount\")\n * ]);\n * console.log(`${total} orders, $${sum} total, $${avg} average`);\n * ```\n */\nexport function createAggregateMethods(collectionRef: Query) {\n return {\n // Count documents matching query options\n count: async (options: QueryOptions = {}): Promise<number> => {\n let q: Query = collectionRef as any;\n q = applyQueryOptions(q, options);\n const snapshot = await q.count().get();\n return snapshot.data().count;\n },\n\n // Sum of a numeric field\n sum: async (field: string, options: QueryOptions = {}): Promise<number> => {\n let q: Query = collectionRef as any;\n q = applyQueryOptions(q, options);\n const snapshot = await q.get();\n\n let total = 0;\n snapshot.forEach((doc) => {\n const value = doc.data()[field];\n if (typeof value === \"number\") {\n total += value;\n }\n });\n\n return total;\n },\n\n // Average of a numeric field\n average: async (\n field: string,\n options: QueryOptions = {},\n ): Promise<number | null> => {\n let q: Query = collectionRef as any;\n q = applyQueryOptions(q, options);\n const snapshot = await q.get();\n\n if (snapshot.empty) return null;\n\n let total = 0;\n let count = 0;\n\n snapshot.forEach((doc) => {\n const value = doc.data()[field];\n if (typeof value === \"number\") {\n total += value;\n count++;\n }\n });\n\n return count > 0 ? total / count : null;\n },\n };\n}\n","import type { Firestore, WriteBatch } from \"firebase-admin/firestore\";\n\n/**\n * Creates batch operation methods for atomic writes (max 500 operations).\n * All operations in a batch either succeed or fail together.\n *\n * @param db - Firestore database instance\n * @param documentRef - Function to create document references\n * @param documentKey - The field name used as document ID\n * @param pathKey - Optional field name to store the document path\n * @param createdKey - Optional field name for creation timestamp\n * @param updatedKey - Optional field name for update timestamp\n * @returns Object containing batch creation method\n *\n * @example\n * ```typescript\n * // Create a batch for atomic operations\n * const batch = repos.users.batch.create();\n *\n * // SET - Add multiple documents\n * batch.set(\"user-1\", { name: \"Alice\", email: \"alice@example.com\" });\n * batch.set(\"user-2\", { name: \"Bob\", email: \"bob@example.com\" });\n * batch.set(\"user-3\", { name: \"Charlie\", email: \"charlie@example.com\" });\n *\n * // For subcollections (e.g., posts/{postId}/comments/{commentId}):\n * const commentBatch = repos.comments.batch.create();\n * commentBatch.set(\"post-1\", \"comment-1\", { content: \"First comment\" });\n * commentBatch.set(\"post-1\", \"comment-2\", { content: \"Second comment\" });\n *\n * // UPDATE - Update existing documents in batch\n * batch.update(\"user-1\", { name: \"Alice Updated\" });\n * batch.update(\"user-2\", { age: 30 });\n *\n * // DELETE - Delete documents in batch\n * batch.delete(\"user-3\");\n *\n * // COMMIT - Execute all operations atomically\n * await batch.commit();\n *\n * // With merge option (default: true)\n * batch.set(\"user-4\", { name: \"David\" }, { merge: false }); // Overwrites entirely\n *\n * // Full example with mixed operations\n * const orderBatch = repos.orders.batch.create();\n * orderBatch.set(\"order-new\", { status: \"pending\", total: 99.99 });\n * orderBatch.update(\"order-old\", { status: \"completed\" });\n * orderBatch.delete(\"order-cancelled\");\n * await orderBatch.commit(); // All or nothing\n * ```\n */\nexport function createBatchMethods(\n db: Firestore,\n documentRef: (...args: any[]) => any,\n documentKey: string,\n pathKey?: string,\n createdKey?: string,\n updatedKey?: string,\n) {\n const now = () => new Date();\n\n return {\n create: () => {\n const batch: WriteBatch = db.batch();\n return {\n batch,\n set: (...args: any[]) => {\n const lastArg = args[args.length - 1];\n const hasOptions =\n typeof lastArg === \"object\" &&\n lastArg !== null &&\n \"merge\" in lastArg;\n\n const data = hasOptions\n ? args[args.length - 2]\n : args[args.length - 1];\n const pathArgs = hasOptions ? args.slice(0, -2) : args.slice(0, -1);\n const mergeOption = hasOptions ? lastArg : { merge: true };\n\n const docRef = documentRef(...pathArgs);\n\n // Auto-populate documentKey, pathKey, createdKey and updatedKey\n const enrichedData = { ...data };\n // Use the last pathArg as documentKey (for subcollections, first args are parent IDs)\n const docIdValue = pathArgs[pathArgs.length - 1];\n if (documentKey && docIdValue) {\n enrichedData[documentKey] = docIdValue;\n }\n if (pathKey) {\n enrichedData[pathKey] = docRef.path;\n }\n if (createdKey) {\n enrichedData[createdKey] = now();\n }\n if (updatedKey) {\n enrichedData[updatedKey] = now();\n }\n\n batch.set(docRef, enrichedData, mergeOption);\n },\n update: (...args: any[]) => {\n const data = args.pop();\n const pathArgs = args;\n const docRef = documentRef(...pathArgs);\n\n // Auto-set updatedKey\n const enrichedData = { ...data };\n if (updatedKey) {\n enrichedData[updatedKey] = now();\n }\n\n batch.update(docRef, enrichedData);\n },\n delete: (...args: any[]) => {\n const docRef = documentRef(...args);\n batch.delete(docRef);\n },\n commit: async () => {\n await batch.commit();\n },\n };\n },\n };\n}\n","import type { DocumentReference, Firestore } from \"firebase-admin/firestore\";\n\n/**\n * Creates bulk operation methods using BulkWriter for large-scale operations.\n * Automatically handles batching (flushes every 500 operations) and provides\n * better performance for large datasets than regular batches.\n *\n * @param db - Firestore database instance\n * @param createdKey - Optional field name for creation timestamp\n * @param updatedKey - Optional field name for update timestamp\n * @returns Object containing bulk write methods\n *\n * @example\n * ```typescript\n * // BULK SET - Create/update thousands of documents efficiently\n * // Prepare items with document references\n * const items = users.map(user => ({\n * docRef: db.collection(\"users\").doc(user.id),\n * data: { name: user.name, email: user.email },\n * merge: true // Optional, defaults to true\n * }));\n *\n * await repos.users.bulk.set(items);\n *\n * // BULK UPDATE - Update many documents\n * const updates = [\n * { docRef: db.collection(\"users\").doc(\"user-1\"), data: { status: \"active\" } },\n * { docRef: db.collection(\"users\").doc(\"user-2\"), data: { status: \"active\" } },\n * // ... thousands more\n * ];\n *\n * await repos.users.bulk.update(updates);\n *\n * // BULK DELETE - Delete many documents\n * const docsToDelete = [\n * db.collection(\"users\").doc(\"user-1\"),\n * db.collection(\"users\").doc(\"user-2\"),\n * // ... thousands more\n * ];\n *\n * await repos.users.bulk.delete(docsToDelete);\n *\n * // Practical example: Migrate data\n * const allUsers = await repos.users.query.getAll();\n * const bulkItems = allUsers.map(user => ({\n * docRef: db.collection(\"users\").doc(user.docId),\n * data: { ...user, migrated: true, version: 2 }\n * }));\n * await repos.users.bulk.set(bulkItems);\n *\n * // Note: Unlike batch, bulk operations are NOT atomic.\n * // Each write is independent - some may succeed while others fail.\n * // Use batch for atomic operations (max 500), bulk for large datasets.\n * ```\n */\nexport function createBulkMethods(\n db: Firestore,\n createdKey?: string,\n updatedKey?: string,\n) {\n const now = () => new Date();\n\n return {\n // Set multiple documents with automatic batching (500 ops per flush)\n set: async (\n items: Array<{\n docRef: DocumentReference;\n data: any;\n merge?: boolean;\n }>,\n ) => {\n const bulkWriter = db.bulkWriter();\n let pendingOps = 0;\n\n for (const item of items) {\n if (!item) continue;\n const { docRef, data, merge = true } = item;\n\n // Auto-set createdKey and updatedKey\n const enrichedData = { ...data };\n if (createdKey) {\n enrichedData[createdKey] = now();\n }\n if (updatedKey) {\n enrichedData[updatedKey] = now();\n }\n\n bulkWriter.set(docRef, enrichedData, { merge });\n pendingOps++;\n\n if (pendingOps >= 500) {\n await bulkWriter.flush();\n pendingOps = 0;\n }\n }\n\n await bulkWriter.close();\n },\n\n // Update multiple documents with automatic batching\n update: async (items: Array<{ docRef: DocumentReference; data: any }>) => {\n const bulkWriter = db.bulkWriter();\n let pendingOps = 0;\n\n for (const item of items) {\n if (!item) continue;\n const { docRef, data } = item;\n\n // Auto-set updatedKey\n const enrichedData = { ...data };\n if (updatedKey) {\n enrichedData[updatedKey] = now();\n }\n\n bulkWriter.update(docRef, enrichedData);\n pendingOps++;\n\n if (pendingOps >= 500) {\n await bulkWriter.flush();\n pendingOps = 0;\n }\n }\n\n await bulkWriter.close();\n },\n\n // Delete multiple documents with automatic batching\n delete: async (docRefs: DocumentReference[]) => {\n const bulkWriter = db.bulkWriter();\n let pendingOps = 0;\n\n for (const docRef of docRefs) {\n if (!docRef) continue;\n bulkWriter.delete(docRef);\n pendingOps++;\n\n if (pendingOps >= 500) {\n await bulkWriter.flush();\n pendingOps = 0;\n }\n }\n\n await bulkWriter.close();\n },\n };\n}\n","import type { CollectionReference } from \"firebase-admin/firestore\";\nimport { maybeNormalize } from \"../shared/date-config\";\n\n/**\n * Creates CRUD methods (create, set, update, delete).\n *\n * @template T - The document type\n * @param actualCollection - The collection reference (null for collection groups)\n * @param documentRef - Function to create document references\n * @param documentKey - The field name used as document ID\n * @param pathKey - Optional field name to store the document path\n * @param createdKey - Optional field name for creation timestamp\n * @param updatedKey - Optional field name for update timestamp\n * @returns Object containing CRUD methods\n *\n * @example\n * ```typescript\n * // CREATE - Add a new document\n * // Auto-generates docId if not provided, sets createdAt/updatedAt\n * const newUser = await repos.users.create({\n * name: \"John Doe\",\n * email: \"john@example.com\",\n * age: 28\n * });\n * console.log(newUser.docId); // Auto-generated ID\n *\n * // Create with custom docId\n * const customUser = await repos.users.create({\n * docId: \"custom-id-123\",\n * name: \"Jane Doe\",\n * email: \"jane@example.com\"\n * });\n *\n * // SET - Create or replace a document by ID\n * // For regular collections:\n * const user = await repos.users.set(\"user-123\", {\n * name: \"Updated Name\",\n * email: \"new@example.com\"\n * });\n *\n * // For subcollections (e.g., posts/{postId}/comments/{commentId}):\n * const comment = await repos.comments.set(\"post-123\", \"comment-456\", {\n * content: \"Great post!\",\n * likes: 0\n * });\n *\n * // Set with merge option (default: true)\n * await repos.users.set(\"user-123\", { name: \"Only Name\" }, { merge: true });\n *\n * // UPDATE - Partially update an existing document\n * const updatedUser = await repos.users.update(\"user-123\", {\n * name: \"New Name\"\n * });\n *\n * // Update subcollection document:\n * await repos.comments.update(\"post-123\", \"comment-456\", {\n * likes: 10\n * });\n *\n * // DELETE - Remove a document\n * await repos.users.delete(\"user-123\");\n *\n * // Delete subcollection document:\n * await repos.comments.delete(\"post-123\", \"comment-456\");\n * ```\n */\nexport function createCrudMethods<T>(\n actualCollection: CollectionReference | null,\n documentRef: (...args: any[]) => any,\n documentKey: string,\n pathKey?: string,\n createdKey?: string,\n updatedKey?: string,\n) {\n const now = () => new Date();\n\n // Create - adds a new document, optionally with a provided document key\n const create = async (data: any): Promise<T> => {\n if (!actualCollection) {\n throw new Error(\n \"Cannot use create() on collection groups. Use set() with a specific document ID instead.\",\n );\n }\n\n let docRef;\n let docId: string;\n\n // Auto-set createdKey and updatedKey\n const enrichedData = { ...data };\n if (createdKey) {\n enrichedData[createdKey] = now();\n }\n if (updatedKey) {\n enrichedData[updatedKey] = now();\n }\n\n // If documentKey is provided in data, use set() with that ID\n if (data[documentKey]) {\n docId = data[documentKey];\n docRef = actualCollection.doc(docId);\n // Also set pathKey if defined\n const dataWithPath = pathKey\n ? { ...enrichedData, [pathKey]: docRef.path }\n : enrichedData;\n await docRef.set(dataWithPath);\n } else {\n // Otherwise, use add() to auto-generate ID\n docRef = await actualCollection.add(enrichedData);\n docId = docRef.id;\n // Update the document to include the documentKey and optionally pathKey\n const updates: Record<string, string> = { [documentKey]: docId };\n if (pathKey) {\n updates[pathKey] = docRef.path;\n }\n await docRef.update(updates);\n }\n\n const createdDoc = await docRef.get();\n return maybeNormalize(createdDoc.data()) as T;\n };\n\n // Set - creates or replaces a document\n const set = async (...args: any[]): Promise<T> => {\n const lastArg = args[args.length - 1];\n const hasOptions =\n typeof lastArg === \"object\" && lastArg !== null && \"merge\" in lastArg;\n\n const data = hasOptions ? args[args.length - 2] : args[args.length - 1];\n const pathArgs = hasOptions ? args.slice(0, -2) : args.slice(0, -1);\n const mergeOption = hasOptions ? lastArg : { merge: true };\n\n const enrichedData = { ...data };\n\n // Auto-set updatedKey\n if (updatedKey) {\n enrichedData[updatedKey] = now();\n }\n\n const docRef = documentRef(...pathArgs);\n\n // Inject documentKey (last segment of the path args) and pathKey — same\n // behaviour as create() and batch.set() so the fields are always present.\n const docIdValue = pathArgs[pathArgs.length - 1];\n if (documentKey && docIdValue != null) {\n enrichedData[documentKey] = docIdValue;\n }\n if (pathKey) {\n enrichedData[pathKey] = docRef.path;\n }\n\n await docRef.set(enrichedData, mergeOption);\n\n const setDocument = await docRef.get();\n return maybeNormalize(setDocument.data()) as T;\n };\n\n // Update - updates a document and returns the merged object\n const update = async (...args: any[]): Promise<T> => {\n const data = args.pop();\n const pathArgs = args;\n\n // Auto-set updatedKey\n const enrichedData = { ...data };\n if (updatedKey) {\n enrichedData[updatedKey] = now();\n }\n\n const docRef = documentRef(...pathArgs);\n await docRef.update(enrichedData);\n\n const updatedDoc = await docRef.get();\n return maybeNormalize(updatedDoc.data()) as T;\n };\n\n // Delete - removes a document\n const deleteMethod = async (...args: any[]): Promise<void> => {\n const docRef = documentRef(...args);\n await docRef.delete();\n };\n\n return {\n create,\n set,\n update,\n delete: deleteMethod,\n };\n}\n","import type {\n CollectionReference,\n DocumentReference,\n DocumentSnapshot,\n Query,\n QuerySnapshot,\n} from \"firebase-admin/firestore\";\nimport { maybeNormalize } from \"../shared/date-config\";\nimport type { GetOptions } from \"../shared/types\";\nimport { capitalize, chunkArray } from \"../shared/utils\";\n\n/**\n * Creates get.by* methods for foreign keys.\n * These methods return a single document or null.\n *\n * @template T - The document type\n * @param collectionRef - Firestore query reference\n * @param foreignKeys - Array of field names to generate get methods for\n * @param actualCollection - The actual collection reference (null for collection groups)\n * @param documentRef - Function to create document references\n * @param documentKey - The field name used as document ID\n * @returns Object containing generated get methods\n *\n * @example\n * ```typescript\n * // Generated methods based on foreignKeys: [\"docId\", \"email\", \"slug\"]\n *\n * // Basic usage - get user by docId\n * const user = await repos.users.get.byDocId(\"user-123\");\n *\n * // Get user by email\n * const userByEmail = await repos.users.get.byEmail(\"john@example.com\");\n *\n * // With select - only return specific fields\n * const partialUser = await repos.users.get.byDocId(\"user-123\", {\n * select: [\"name\", \"email\"]\n * });\n *\n * // With returnDoc - get both data and Firestore DocumentSnapshot\n * const { data, doc } = await repos.users.get.byDocId(\"user-123\", {\n * returnDoc: true\n * });\n * console.log(\"Document path:\", doc.ref.path);\n *\n * // Get multiple documents by list of values\n * const users = await repos.users.get.byList(\"docId\", [\"user-1\", \"user-2\", \"user-3\"]);\n *\n * // Get by list with array-contains-any operator\n * const usersWithTags = await repos.users.get.byList(\n * \"tags\",\n * [\"admin\", \"moderator\"],\n * \"array-contains-any\"\n * );\n * ```\n */\nexport function createGetMethods<T>(\n collectionRef: Query,\n foreignKeys: readonly string[],\n actualCollection: CollectionReference | null,\n documentRef: (...args: any[]) => DocumentReference,\n documentKey: string,\n) {\n const getMethods: any = {};\n\n // get.byList - retrieve multiple documents by list of values\n getMethods.byList = async (\n key: string,\n values: any[],\n operator: \"in\" | \"array-contains-any\" = \"in\",\n options: GetOptions = {},\n ): Promise<T[] | { data: T; doc: DocumentSnapshot }[]> => {\n if (values.length === 0) return [];\n\n const results: (T | { data: T; doc: DocumentSnapshot })[] = [];\n const chunks = chunkArray(values, 30); // Firestore limits 'in' to 30 elements\n\n for (const chunk of chunks) {\n let q: Query = collectionRef as any;\n q = q.where(key, operator, chunk);\n\n // Apply select if specified\n if (options.select && options.select.length > 0) {\n q = q.select(...options.select.map((f) => String(f)));\n }\n\n const snapshot: QuerySnapshot = await q.get();\n\n snapshot.forEach((doc) => {\n const data = maybeNormalize(doc.data()) as T;\n results.push(options.returnDoc ? { data, doc } : data);\n });\n }\n\n return results as T[] | { data: T; doc: DocumentSnapshot }[];\n };\n\n // Generate get.by* methods for each foreign key\n foreignKeys.forEach((foreignKey: string) => {\n const methodName = `by${capitalize(String(foreignKey))}`;\n getMethods[methodName] = async (\n value: string,\n options: GetOptions | boolean = {},\n ): Promise<T | { data: T; doc: DocumentSnapshot } | null> => {\n // Handle legacy boolean returnDoc parameter\n const opts: GetOptions =\n typeof options === \"boolean\" ? { returnDoc: options } : options;\n\n // Special case: if foreignKey is the documentKey, use direct document reference\n if (String(foreignKey) === documentKey) {\n const docRef = documentRef(value);\n const doc = await docRef.get();\n if (!doc.exists) return null;\n const data = maybeNormalize(doc.data()) as T;\n return opts.returnDoc ? { data, doc } : data;\n }\n\n // For other keys, query by field value\n let q: Query = collectionRef as any;\n q = q.where(String(foreignKey), \"==\", value).limit(1);\n\n // Apply select if specified\n if (opts.select && opts.select.length > 0) {\n q = q.select(...opts.select.map((f) => String(f)));\n }\n\n const snapshot: QuerySnapshot = await q.get();\n if (snapshot.empty) return null;\n const doc = snapshot.docs[0];\n if (!doc) return null;\n const data = maybeNormalize(doc.data()) as T;\n return opts.returnDoc ? { data, doc } : data;\n };\n });\n\n return getMethods;\n}\n","import type { Query } from \"firebase-admin/firestore\";\nimport {\n createPaginationIterator,\n executePaginatedQuery,\n type PaginationOptions,\n type PaginationResult,\n} from \"../pagination\";\nimport { buildAndExecuteQuery } from \"../query-builder\";\nimport { maybeNormalize } from \"../shared/date-config\";\nimport type {\n QueryOptions,\n RelationConfig,\n WhereClause,\n} from \"../shared/types\";\nimport { applyQueryOptions, capitalize } from \"../shared/utils\";\n\n/**\n * Include configuration for a relation with optional select\n */\nexport interface IncludeConfig {\n /** The relation key to include */\n relation: string;\n /** Fields to select from the related documents (Firestore select) */\n select?: string[];\n}\n\n/**\n * Options for pagination with include support\n */\nexport interface PaginationWithIncludeOptions<\n T,\n TRelationKeys = string,\n> extends PaginationOptions<T> {\n /** Relations to include in results - can be relation keys or IncludeConfig objects */\n include?: (TRelationKeys | IncludeConfig)[];\n}\n\n/**\n * Creates query.by* methods for query keys.\n * These methods return arrays of documents matching a query condition.\n *\n * @template T - The document type\n * @param collectionRef - Firestore query reference\n * @param queryKeys - Array of field names to generate query methods for\n * @param relationalKeys - Optional relation configuration for includes\n * @param allRepositories - Optional map of all repositories for relation resolution\n * @returns Object containing generated query methods\n *\n * @example\n * ```typescript\n * // Generated methods based on queryKeys: [\"status\", \"categoryId\"]\n * // Basic usage - get all posts with status \"published\"\n * const publishedPosts = await repos.posts.query.byStatus(\"published\");\n *\n * // With options - filter, sort, limit and select\n * const recentPosts = await repos.posts.query.byStatus(\"published\", {\n * orderBy: [[\"createdAt\", \"desc\"]],\n * limit: 10,\n * select: [\"title\", \"createdAt\"]\n * });\n *\n * // Generic query.by with full options\n * const filteredPosts = await repos.posts.query.by({\n * where: [[\"views\", \">=\", 1000]],\n * orWhere: [\n * [\"status\", \"==\", \"published\"],\n * [\"status\", \"==\", \"featured\"]\n * ],\n * orderBy: [[\"views\", \"desc\"]],\n * limit: 20\n * });\n *\n * // Pagination with include (relation population)\n * const paginatedPosts = await repos.posts.query.paginate({\n * pageSize: 10,\n * orderBy: [[\"createdAt\", \"desc\"]],\n * include: [\"userId\", { relation: \"categoryId\", select: [\"name\"] }]\n * });\n *\n * // Iterate through all pages\n * for await (const page of repos.posts.query.paginateAll({ pageSize: 50 })) {\n * console.log(`Processing ${page.data.length} posts`);\n * }\n * ```\n */\nexport function createQueryMethods<T>(\n collectionRef: Query,\n queryKeys: readonly string[],\n relationalKeys?: Record<string, RelationConfig>,\n allRepositories?: Record<string, any>,\n) {\n const queryMethods: any = {};\n\n /**\n * Resolve included relations for a list of documents (parallel per document,\n * parallel per relation). Stores results by field key to avoid repo-name collisions.\n */\n const populateDocuments = async (\n documents: T[],\n includeConfigs: (string | IncludeConfig)[],\n ): Promise<(T & { populated: Record<string, any> })[]> => {\n if (!relationalKeys || !allRepositories || includeConfigs.length === 0) {\n return documents as any;\n }\n\n const normalizedConfigs: { key: string; select?: string[] }[] =\n includeConfigs.map((cfg) =>\n typeof cfg === \"string\"\n ? { key: cfg }\n : { key: cfg.relation, select: cfg.select },\n );\n\n return Promise.all(\n documents.map(async (doc) => {\n const entries = await Promise.all(\n normalizedConfigs.map(async ({ key, select }) => {\n const relation = relationalKeys[key];\n if (!relation) return [key, undefined] as const;\n\n const targetRepo = allRepositories[relation.repo];\n if (!targetRepo) return [key, undefined] as const;\n\n const fieldValue = (doc as any)[key];\n if (fieldValue === undefined || fieldValue === null) {\n return [key, relation.type === \"one\" ? null : []] as const;\n }\n\n const opts = select ? { select } : undefined;\n\n try {\n if (relation.type === \"one\") {\n const method = `by${capitalize(relation.key)}`;\n const result =\n typeof targetRepo.get?.[method] === \"function\"\n ? await targetRepo.get[method](fieldValue, opts)\n : null;\n return [key, result] as const;\n } else {\n const method = `by${capitalize(relation.key)}`;\n const result =\n typeof targetRepo.query?.[method] === \"function\"\n ? await targetRepo.query[method](fieldValue, opts)\n : [];\n return [key, result] as const;\n }\n } catch (err) {\n console.error(`[include] Error populating \"${key}\":`, err);\n return [key, relation.type === \"one\" ? null : []] as const;\n }\n }),\n );\n\n const populated: Record<string, any> = {};\n for (const [k, v] of entries) {\n if (k !== undefined) populated[k] = v;\n }\n return { ...doc, populated };\n }),\n );\n };\n\n // Generate query.by* methods — inject queryKey condition into options so\n // orWhere and other advanced options are all handled by buildAndExecuteQuery.\n queryKeys.forEach((queryKey: string) => {\n const methodName = `by${capitalize(queryKey)}`;\n queryMethods[methodName] = async (\n value: any,\n options: QueryOptions<T> = {},\n ): Promise<T[]> => {\n const mergedOptions: QueryOptions<T> = {\n ...options,\n where: [\n [queryKey, \"==\", value] as unknown as WhereClause<T>,\n ...(options.where ?? []),\n ],\n };\n const snapshot = await buildAndExecuteQuery<T>(\n collectionRef,\n mergedOptions,\n );\n return snapshot.docs.map((doc) => maybeNormalize(doc.data()) as T);\n };\n });\n\n // Generic query.by — full orWhere support via buildAndExecuteQuery\n queryMethods.by = async (options: QueryOptions<T>): Promise<T[]> => {\n const snapshot = await buildAndExecuteQuery<T>(collectionRef, options);\n return snapshot.docs.map((doc) => maybeNormalize(doc.data()) as T);\n };\n\n // getAll — full orWhere support via buildAndExecuteQuery\n queryMethods.getAll = async (options: QueryOptions<T> = {}): Promise<T[]> => {\n const snapshot = await buildAndExecuteQuery<T>(collectionRef, options);\n return snapshot.docs.map((doc) => maybeNormalize(doc.data()) as T);\n };\n\n // onSnapshot — real-time listener (orWhere not supported by Firestore SDK real-time)\n queryMethods.onSnapshot = (\n options: QueryOptions<T>,\n onNext: (data: T[]) => void,\n onError?: (error: Error) => void,\n ): (() => void) => {\n const q = applyQueryOptions(collectionRef, options);\n return q.onSnapshot((snapshot) => {\n onNext(snapshot.docs.map((doc) => maybeNormalize(doc.data()) as T));\n }, onError);\n };\n\n // Paginate — includes relation resolution after each page\n queryMethods.paginate = async (\n options: PaginationWithIncludeOptions<T, string>,\n ): Promise<\n | PaginationResult<T>\n | PaginationResult<T & { populated: Record<string, any> }>\n > => {\n const { include, ...paginationOptions } = options;\n const result = await executePaginatedQuery<T>(\n collectionRef,\n paginationOptions,\n );\n\n if (include && include.length > 0) {\n const populatedData = await populateDocuments(result.data, include);\n return { ...result, data: populatedData };\n }\n\n return result;\n };\n\n queryMethods.paginateAll = async function* (\n options: Omit<\n PaginationWithIncludeOptions<T, string>,\n \"cursor\" | \"direction\"\n >,\n ): AsyncGenerator<\n | PaginationResult<T>\n | PaginationResult<T & { populated: Record<string, any> }>,\n void,\n unknown\n > {\n const { include, ...paginationOptions } = options;\n for await (const page of createPaginationIterator<T>(\n collectionRef,\n paginationOptions,\n )) {\n if (include && include.length > 0) {\n const populatedData = await populateDocuments(page.data, include);\n yield { ...page, data: populatedData };\n } else {\n yield page;\n }\n }\n };\n\n return queryMethods;\n}\n","import type { RelationConfig, RepositoryConfig } from \"../shared/types\";\nimport { capitalize } from \"../shared/utils\";\n\n/**\n * Options for populate with select support.\n * Two formats:\n * - Single relation: { relation: \"userId\", select: [\"name\", \"email\"] }\n * - Multiple relations: { relations: [\"userId\", \"editorId\"], select: { userId: [\"name\"] } }\n */\nexport type PopulateOptions<TRelationKey = string> =\n | {\n relation: TRelationKey;\n select?: string[];\n }\n | {\n relations: TRelationKey | TRelationKey[];\n select?: Partial<Record<string, string[]>>;\n };\n\n/**\n * Creates populate methods for resolving relations between repositories.\n * Results are keyed by the **field name** (relation key) — not the repo name —\n * to avoid collisions when two fields point to the same repository.\n *\n * @template TConfig - Repository configuration type\n * @param config - Repository configuration with relational keys\n * @param allRepositories - Map of all repositories for relation resolution\n * @returns Object containing the populate method\n *\n * @example\n * ```typescript\n * // Assume relations configured as:\n * // posts.userId -> users.docId (one-to-one)\n * // posts.categoryId -> categories.docId (one-to-one)\n * // users.docId -> posts.userId (one-to-many)\n *\n * // POPULATE SINGLE RELATION - Get post with its author\n * const post = await repos.posts.get.byDocId(\"post-123\");\n * const postWithAuthor = await repos.posts.populate(post, \"userId\");\n * console.log(postWithAuthor.populated.userId); // User object\n *\n * // POPULATE WITH SELECT - Only fetch specific fields\n * const postWithPartialAuthor = await repos.posts.populate(post, {\n * relation: \"userId\",\n * select: [\"name\", \"email\", \"avatar\"]\n * });\n * console.log(postWithPartialAuthor.populated.userId.name);\n *\n * // POPULATE MULTIPLE RELATIONS - Get post with author and category\n * const postWithRelations = await repos.posts.populate(post, [\"userId\", \"categoryId\"]);\n * console.log(postWithRelations.populated.userId); // User object\n * console.log(postWithRelations.populated.categoryId); // Category object\n *\n * // POPULATE MULTIPLE WITH DIFFERENT SELECTS\n * const postWithCustomSelects = await repos.posts.populate(post, {\n * relations: [\"userId\", \"categoryId\"],\n * select: {\n * userId: [\"name\", \"avatar\"],\n * categoryId: [\"name\", \"slug\"]\n * }\n * });\n *\n * // POPULATE ONE-TO-MANY - Get user with all their posts\n * const user = await repos.users.get.byDocId(\"user-123\");\n * const userWithPosts = await repos.users.populate(user, \"docId\");\n * console.log(userWithPosts.populated.docId); // Array of Post objects\n *\n * // With select on one-to-many\n * const userWithPartialPosts = await repos.users.populate(user, {\n * relation: \"docId\",\n * select: [\"title\", \"status\", \"createdAt\"]\n * });\n *\n * // Chained population (nested relations)\n * const post = await repos.posts.get.byDocId(\"post-123\");\n * const postWithAuthor = await repos.posts.populate(post, \"userId\");\n * // If you need author's posts too:\n * const authorWithPosts = await repos.users.populate(\n * postWithAuthor.populated.userId,\n * \"docId\"\n * );\n * ```\n *\n * @internal\n */\nexport function createPopulateMethods<\n TConfig extends RepositoryConfig<\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any\n >,\n>(\n config: TConfig,\n allRepositories: Record<string, any>,\n): {\n populate: <\n K extends keyof NonNullable<TConfig[\"relationalKeys\"]>,\n TDoc extends Pick<TConfig[\"type\"], K>,\n >(\n document: TDoc,\n relationKeyOrOptions: K | K[] | PopulateOptions<K>,\n ) => Promise<TDoc & { populated: Record<string, any> }>;\n} {\n return {\n populate: async (document: any, relationKeyOrOptions: any) => {\n if (!config.relationalKeys) {\n return { ...document, populated: {} };\n }\n\n // Parse options into a list of keys + per-key select map\n let keys: string[];\n let selectMap: Record<string, string[]> = {};\n\n if (\n typeof relationKeyOrOptions === \"object\" &&\n !Array.isArray(relationKeyOrOptions)\n ) {\n if (\"relation\" in relationKeyOrOptions) {\n const opts = relationKeyOrOptions as {\n relation: string;\n select?: string[];\n };\n keys = [opts.relation];\n if (opts.select) selectMap[opts.relation] = opts.select;\n } else if (\"relations\" in relationKeyOrOptions) {\n const opts = relationKeyOrOptions as {\n relations: string | string[];\n select?: Record<string, string[]>;\n };\n keys = Array.isArray(opts.relations)\n ? opts.relations\n : [opts.relations];\n selectMap = opts.select ?? {};\n } else {\n keys = [];\n }\n } else {\n keys = Array.isArray(relationKeyOrOptions)\n ? relationKeyOrOptions\n : [relationKeyOrOptions];\n }\n\n // Resolve all relations in parallel\n const entries = await Promise.all(\n keys.map(async (key) => {\n const relation: RelationConfig | undefined =\n config.relationalKeys?.[key as string];\n if (!relation) {\n console.warn(`[populate] Relation \"${key}\" not found in config`);\n return [key, undefined] as const;\n }\n\n const targetRepo = allRepositories[relation.repo];\n if (!targetRepo) {\n console.warn(\n `[populate] Repository \"${relation.repo}\" not found in mapping`,\n );\n return [key, undefined] as const;\n }\n\n const fieldValue = document[key];\n if (fieldValue === undefined || fieldValue === null) {\n return [key, relation.type === \"one\" ? null : []] as const;\n }\n\n const selectFields = selectMap[key];\n const opts = selectFields ? { select: selectFields } : undefined;\n\n try {\n if (relation.type === \"one\") {\n const method = `by${capitalize(relation.key)}`;\n const result =\n typeof targetRepo.get?.[method] === \"function\"\n ? await targetRepo.get[method](fieldValue, opts)\n : null;\n return [key, result] as const;\n } else {\n const method = `by${capitalize(relation.key)}`;\n const result =\n typeof targetRepo.query?.[method] === \"function\"\n ? await targetRepo.query[method](fieldValue, opts)\n : [];\n return [key, result] as const;\n }\n } catch (err) {\n console.error(`[populate] Error populating \"${key}\":`, err);\n return [key, relation.type === \"one\" ? null : []] as const;\n }\n }),\n );\n\n const populated: Record<string, any> = {};\n for (const [k, v] of entries) {\n if (v !== undefined) populated[k] = v;\n }\n\n return { ...document, populated };\n },\n };\n}\n","import type { Firestore } from \"firebase-admin/firestore\";\nimport { maybeNormalize } from \"../shared/date-config\";\n\n/**\n * Creates transaction operation methods for atomic read-write operations.\n * Transactions ensure consistency when reading and writing data atomically.\n *\n * @param db - Firestore database instance\n * @param documentRef - Function to create document references\n * @returns Object containing the transaction run method\n *\n * @example\n * ```typescript\n * // Basic transaction - transfer points between users\n * const result = await repos.users.transaction.run(async (tx) => {\n * // Read both users\n * const sender = await tx.get(\"sender-id\");\n * const receiver = await tx.get(\"receiver-id\");\n *\n * if (!sender || sender.points < 100) {\n * throw new Error(\"Insufficient points\");\n * }\n *\n * // Update both atomically\n * tx.update(\"sender-id\", { points: sender.points - 100 });\n * tx.update(\"receiver-id\", { points: (receiver?.points || 0) + 100 });\n *\n * return { transferred: 100 };\n * });\n *\n * // Transaction with subcollections\n * await repos.comments.transaction.run(async (tx) => {\n * // Get comment from subcollection (postId, commentId)\n * const comment = await tx.get(\"post-123\", \"comment-456\");\n *\n * // Update the comment\n * tx.update(\"post-123\", \"comment-456\", {\n * likes: (comment?.likes || 0) + 1\n * });\n * });\n *\n * // Transaction with set and delete\n * await repos.orders.transaction.run(async (tx) => {\n * const order = await tx.get(\"order-id\");\n *\n * // Create archive entry\n * tx.set(\"archived-order-id\", {\n * ...order,\n * archivedAt: new Date()\n * });\n *\n * // Delete original\n * tx.delete(\"order-id\");\n * });\n *\n * // Access raw Firestore transaction for advanced use\n * await repos.users.transaction.run(async (tx) => {\n * // Use raw transaction for cross-collection operations\n * const rawTx = tx.raw;\n * const otherDoc = await rawTx.get(db.collection(\"other\").doc(\"id\"));\n * // ...\n * });\n *\n * // Transaction with merge option\n * await repos.users.transaction.run(async (tx) => {\n * tx.set(\"user-id\", { lastLogin: new Date() }, { merge: true });\n * });\n * ```\n */\nexport function createTransactionMethods(\n db: Firestore,\n documentRef: (...args: any[]) => any,\n) {\n return {\n run: async <R>(\n updateFunction: (transaction: any) => Promise<R>,\n ): Promise<R> => {\n return db.runTransaction(async (rawTransaction) => {\n const typedTransaction = {\n // Type-safe get method\n get: async (...args: any[]) => {\n const docRef = documentRef(...args);\n const docSnap = (await rawTransaction.get(docRef)) as any;\n if (!docSnap.exists) return null;\n return maybeNormalize({ ...docSnap.data(), docId: docSnap.id }) as any;\n },\n\n // Type-safe set method\n set: (...args: any[]) => {\n const options = args[args.length - 1];\n const hasOptions =\n typeof options === \"object\" &&\n options !== null &&\n \"merge\" in options;\n\n const data = hasOptions\n ? args[args.length - 2]\n : args[args.length - 1];\n const pathArgs = hasOptions ? args.slice(0, -2) : args.slice(0, -1);\n const mergeOption = hasOptions ? options : { merge: true };\n\n const docRef = documentRef(...pathArgs);\n rawTransaction.set(docRef, data, mergeOption);\n },\n\n // Type-safe update method\n update: (...args: any[]) => {\n const data = args[args.length - 1];\n const pathArgs = args.slice(0, -1);\n const docRef = documentRef(...pathArgs);\n rawTransaction.update(docRef, data);\n },\n\n // Delete method\n delete: (...args: any[]) => {\n const docRef = documentRef(...args);\n rawTransaction.delete(docRef);\n },\n\n // Access to raw transaction\n raw: rawTransaction,\n };\n\n return updateFunction(typedTransaction);\n });\n },\n };\n}\n","import type {\n CollectionReference,\n Firestore,\n Query,\n} from \"firebase-admin/firestore\";\nimport { createHistoryMethods, type HistoryMethods } from \"../history/read\";\nimport { createAggregateMethods } from \"../methods/aggregate\";\nimport { createBatchMethods } from \"../methods/batch\";\nimport { createBulkMethods } from \"../methods/bulk\";\nimport { createCrudMethods } from \"../methods/crud\";\nimport { createGetMethods } from \"../methods/get\";\nimport { createQueryMethods } from \"../methods/query\";\nimport { createPopulateMethods } from \"../methods/relations\";\nimport { createTransactionMethods } from \"../methods/transaction\";\nimport type { RepositoryConfig } from \"../shared/types\";\nimport type { ConfiguredRepository } from \"./types\";\n\n/**\n * Extract parent-key parameter names from a refCb function.\n * For `(db, postId, docId) => …` this returns `[\"postId\"]` (everything\n * between the first param – the Firestore `db` – and the last param – the\n * document's own ID).\n * Returns an empty array when the function has ≤ 2 params (db + docId).\n * @internal\n */\nfunction extractParentKeys(refCb: unknown): string[] {\n if (typeof refCb !== \"function\") return [];\n const src = refCb.toString();\n const match = src.match(/^\\s*(?:function\\s*\\w*\\s*)?\\(([^)]*)\\)/);\n if (!match?.[1]) return [];\n const params = match[1]\n .split(\",\")\n .map((p) => p.trim().replace(/\\s*[:=].*$/, \"\").trim())\n .filter(Boolean);\n // (db, docId) → 0 parents; (db, parentId, docId) → 1 parent; etc.\n if (params.length <= 2) return [];\n return params.slice(1, -1);\n}\n\n/**\n * Creates a configured repository instance with all methods\n */\nexport function createRepository<\n T extends RepositoryConfig<any, any, any, any, any, any, any, any, any, any, any>,\n>(\n db: Firestore,\n config: T,\n allRepositories: Record<string, any> = {},\n): ConfiguredRepository<T> {\n // Create collection reference\n const collectionRef: CollectionReference | Query = config.isGroup\n ? db.collectionGroup(config.path)\n : db.collection(config.path);\n\n // Keep actual collection for create operations\n const actualCollection = config.isGroup ? null : db.collection(config.path);\n\n // Create document reference function\n const documentRef = (...args: any[]) => (config.refCb as any)(db, ...args);\n\n // Create all method groups\n const getMethods = createGetMethods(\n collectionRef as Query,\n config.foreignKeys,\n actualCollection,\n documentRef,\n config.documentKey as string,\n );\n const queryMethods = createQueryMethods(\n collectionRef as Query,\n config.queryKeys,\n config.relationalKeys as Record<string, any> | undefined,\n allRepositories,\n );\n const aggregateMethods = createAggregateMethods(collectionRef as Query);\n const crudMethods = createCrudMethods(\n actualCollection,\n documentRef,\n config.documentKey as string,\n config.pathKey as string | undefined,\n config.createdKey as string | undefined,\n config.updatedKey as string | undefined,\n );\n const batchMethods = createBatchMethods(\n db,\n documentRef,\n config.documentKey as string,\n config.pathKey as string | undefined,\n config.createdKey as string | undefined,\n config.updatedKey as string | undefined,\n );\n const transactionMethods = createTransactionMethods(db, documentRef);\n const bulkMethods = createBulkMethods(\n db,\n config.createdKey as string | undefined,\n config.updatedKey as string | undefined,\n );\n const populateMethods = createPopulateMethods(config, allRepositories);\n\n // History namespace (opt-in via config.history.enabled)\n const historyConfig = (config as any).history as\n | { enabled: boolean; [k: string]: any }\n | undefined;\n const history: HistoryMethods<any> | null =\n historyConfig?.enabled\n ? (createHistoryMethods(\n documentRef,\n [\n config.documentKey as string,\n config.pathKey as string | undefined,\n config.createdKey as string | undefined,\n config.updatedKey as string | undefined,\n ].filter((k): k is string => typeof k === \"string\"),\n (config as any).path ?? \"(unknown)\",\n historyConfig as any,\n ) as HistoryMethods<any>)\n : null;\n\n return {\n ref: collectionRef,\n documentRef,\n get: getMethods,\n query: queryMethods,\n aggregate: aggregateMethods,\n ...crudMethods,\n batch: batchMethods,\n transaction: transactionMethods,\n bulk: bulkMethods,\n ...populateMethods,\n ...(history ? { history } : {}),\n // Pass through the Zod schema if one was attached via createRepositoryConfig(schema)\n schema: (config as any).schema,\n // Pass through relational keys built by buildRepositoryRelations\n relationalKeys: (config as any).relationalKeys,\n // Auto-managed keys that should never be accepted in user-provided payloads\n _systemKeys: [\n config.documentKey as string,\n config.pathKey as string | undefined,\n config.createdKey as string | undefined,\n config.updatedKey as string | undefined,\n ].filter((k): k is string => typeof k === \"string\"),\n // Expose pathKey name so server handlers can extract path args from documents\n _pathKey: (config.pathKey as string | undefined) ?? null,\n // Whether this is a collectionGroup repository\n _isGroup: !!config.isGroup,\n // Parent key field names auto-detected from refCb signature\n _parentKeys: config.isGroup\n ? extractParentKeys(config.refCb)\n : [],\n // Expose createdKey so server handlers can inject it when using set() for creates\n _createdKey: (config.createdKey as string | undefined) ?? null,\n } as unknown as ConfiguredRepository<T>;\n}\n","/**\n * Minimal zero-dependency HTTP router for Firebase Functions.\n * Compatible with any Express-like (req, res) handler.\n *\n * Supports:\n * - Named path parameters (e.g. \"/repos/:name/:id\")\n * - GET, POST, DELETE methods\n * - Global middleware (before each route)\n * - 404 / error fallbacks\n *\n * @example\n * ```typescript\n * import { MiniRouter } from \"@lpdjs/firestore-repo-service/servers/admin\";\n *\n * // Create router\n * const router = new MiniRouter();\n *\n * // Add global middleware (executed before every route)\n * router.use(async (req, res, next) => {\n * console.log(`${req.method} ${req.url}`);\n * await next();\n * });\n *\n * // Auth middleware\n * router.use((req, res, next) => {\n * if (!req.headers?.authorization) {\n * res.status(401).send(\"Unauthorized\");\n * return;\n * }\n * next();\n * });\n *\n * // Define routes with path parameters\n * router.get(\"/users\", async (req, res) => {\n * res.json({ users: await getAllUsers() });\n * });\n *\n * router.get(\"/users/:id\", async (req, res) => {\n * const user = await getUser(req.params.id); // Access path params\n * if (!user) {\n * res.status(404).send(\"User not found\");\n * return;\n * }\n * res.json(user);\n * });\n *\n * router.post(\"/users\", async (req, res) => {\n * const user = await createUser(req.body);\n * res.status(201).json(user);\n * });\n *\n * router.delete(\"/users/:id\", async (req, res) => {\n * await deleteUser(req.params.id);\n * res.status(204).end();\n * });\n *\n * // Custom 404 handler\n * router.onNotFound((req, res) => {\n * res.status(404).json({ error: \"Route not found\", path: req.url });\n * });\n *\n * // Custom error handler\n * router.onError((err, req, res) => {\n * console.error(\"Error:\", err);\n * res.status(500).json({ error: \"Internal server error\" });\n * });\n *\n * // Use with Firebase Functions\n * export const api = onRequest(async (req, res) => {\n * await router.handle(req, res);\n * });\n * ```\n */\n\nexport type AnyReq = {\n method?: string;\n url?: string;\n /** Express originalUrl — preserved before any router stripping, contains the full path including the Firebase Functions prefix */\n originalUrl?: string;\n path?: string;\n headers?: Record<string, string | string[] | undefined>;\n body?: unknown;\n query?: Record<string, string | string[] | undefined>;\n};\n\nexport type AnyRes = {\n status: (code: number) => AnyRes;\n set: (key: string, value: string) => AnyRes;\n send: (body: string) => void;\n json: (body: unknown) => void;\n end: () => void;\n};\n\nexport type RouteParams = Record<string, string>;\n\nexport type RouteHandler = (\n req: AnyReq & { params: RouteParams },\n res: AnyRes,\n) => void | Promise<void>;\n\nexport type Middleware = (\n req: AnyReq & { params: RouteParams },\n res: AnyRes,\n next: () => void | Promise<void>,\n) => void | Promise<void>;\n\n// ---------------------------------------------------------------------------\n// Route matching\n// ---------------------------------------------------------------------------\n\ninterface CompiledRoute {\n method: string;\n pattern: RegExp;\n paramNames: string[];\n handler: RouteHandler;\n}\n\nfunction compilePath(path: string): { pattern: RegExp; paramNames: string[] } {\n const paramNames: string[] = [];\n const src = path\n .replace(/[.*+?^${}()|[\\]\\\\]/g, (c) => (c === \":\" ? c : `\\\\${c}`))\n .replace(/:([a-zA-Z_][a-zA-Z0-9_]*)/g, (_match, name: string) => {\n paramNames.push(name);\n return \"([^/]+)\";\n });\n\n return { pattern: new RegExp(`^${src}$`), paramNames };\n}\n\nfunction extractPath(req: AnyReq): string {\n const raw = req.path ?? req.url ?? \"/\";\n const idx = raw.indexOf(\"?\");\n return idx === -1 ? raw : raw.slice(0, idx);\n}\n\n// ---------------------------------------------------------------------------\n// Router class\n// ---------------------------------------------------------------------------\n\nexport class MiniRouter {\n private routes: CompiledRoute[] = [];\n private middlewares: Middleware[] = [];\n private notFoundHandler: RouteHandler = (_req, res) => {\n res.status(404).send(\"Not Found\");\n };\n private errorHandler: (err: unknown, req: AnyReq, res: AnyRes) => void = (\n err,\n _req,\n res,\n ) => {\n console.error(\"[MiniRouter]\", err);\n res.status(500).send(\"Internal Server Error\");\n };\n\n // ── Route registration ────────────────────────────────────────────────────\n\n use(middleware: Middleware): this {\n this.middlewares.push(middleware);\n return this;\n }\n\n get(path: string, handler: RouteHandler): this {\n return this.addRoute(\"GET\", path, handler);\n }\n\n post(path: string, handler: RouteHandler): this {\n return this.addRoute(\"POST\", path, handler);\n }\n\n put(path: string, handler: RouteHandler): this {\n return this.addRoute(\"PUT\", path, handler);\n }\n\n patch(path: string, handler: RouteHandler): this {\n return this.addRoute(\"PATCH\", path, handler);\n }\n\n delete(path: string, handler: RouteHandler): this {\n return this.addRoute(\"DELETE\", path, handler);\n }\n\n onNotFound(handler: RouteHandler): this {\n this.notFoundHandler = handler;\n return this;\n }\n\n onError(handler: (err: unknown, req: AnyReq, res: AnyRes) => void): this {\n this.errorHandler = handler;\n return this;\n }\n\n private addRoute(method: string, path: string, handler: RouteHandler): this {\n const { pattern, paramNames } = compilePath(path);\n this.routes.push({\n method: method.toUpperCase(),\n pattern,\n paramNames,\n handler,\n });\n return this;\n }\n\n // ── Dispatch ──────────────────────────────────────────────────────────────\n\n async handle(req: AnyReq, res: AnyRes): Promise<void> {\n const method = (req.method ?? \"GET\").toUpperCase();\n const path = extractPath(req);\n\n // Find matching route\n let matchedRoute: CompiledRoute | null = null;\n let params: RouteParams = {};\n\n for (const route of this.routes) {\n if (route.method !== method) continue;\n const m = path.match(route.pattern);\n if (m) {\n matchedRoute = route;\n params = {};\n route.paramNames.forEach((name, i) => {\n params[name] = decodeURIComponent(m[i + 1] ?? \"\");\n });\n break;\n }\n }\n\n const enrichedReq = Object.assign(req, { params });\n\n // Run middleware chain → then handler\n const handler = matchedRoute ? matchedRoute.handler : this.notFoundHandler;\n\n try {\n await this.runMiddlewareChain(enrichedReq, res, handler);\n } catch (err) {\n this.errorHandler(err, req, res);\n }\n }\n\n private async runMiddlewareChain(\n req: AnyReq & { params: RouteParams },\n res: AnyRes,\n finalHandler: RouteHandler,\n ): Promise<void> {\n let index = 0;\n\n const next = async (): Promise<void> => {\n if (index < this.middlewares.length) {\n const mw = this.middlewares[index++]!;\n await mw(req, res, next);\n } else {\n await finalHandler(req, res);\n }\n };\n\n await next();\n }\n}\n","import { z } from \"zod\";\nimport {\n getTypeName,\n getInnerType,\n getShape,\n} from \"../shared/zod-compat\";\nimport { SYNC_VERSION_COLUMN } from \"./constants\";\nimport type { SqlColumn, SqlDialect, LogicalType } from \"./types\";\n\nconst WRAPPER_TYPES = new Set([\"ZodOptional\", \"ZodNullable\", \"ZodDefault\"]);\n\nfunction unwrap(schema: z.ZodType): { inner: z.ZodType; nullable: boolean } {\n let current = schema;\n let nullable = false;\n\n for (;;) {\n const name = getTypeName(current);\n if (!WRAPPER_TYPES.has(name)) break;\n if (name === \"ZodOptional\" || name === \"ZodNullable\") nullable = true;\n const inner = getInnerType(current);\n if (!inner) break;\n current = inner;\n }\n\n return { inner: current, nullable };\n}\n\nconst LOGICAL_MAP: Record<string, LogicalType> = {\n ZodString: \"string\",\n ZodNumber: \"number\",\n ZodBigInt: \"bigint\",\n ZodBoolean: \"boolean\",\n ZodDate: \"timestamp\",\n ZodEnum: \"string\",\n ZodNativeEnum: \"string\",\n ZodLiteral: \"string\",\n};\n\nexport function zodTypeToLogical(schema: z.ZodType): LogicalType {\n const { inner } = unwrap(schema);\n return LOGICAL_MAP[getTypeName(inner)] ?? \"json\";\n}\n\nexport interface ZodSchemaToColumnsOptions {\n primaryKey?: string;\n exclude?: string[];\n columnMap?: Record<string, string>;\n}\n\n/**\n * Recursively flatten a Zod object schema into flat SQL columns.\n * Nested objects produce `parent_child` column names.\n * Arrays and non-object complex types become JSON columns.\n */\nfunction flattenSchema(\n shape: Record<string, z.ZodType>,\n dialect: SqlDialect,\n prefix: string,\n parentNullable: boolean,\n excludeSet: Set<string>,\n columnMap: Record<string, string>,\n primaryKey: string | undefined,\n columns: SqlColumn[],\n): void {\n for (const [field, fieldSchema] of Object.entries(shape)) {\n const fullKey = prefix ? `${prefix}__${field}` : field;\n\n // Exclude check on the original (dotless) path and the flattened key\n if (excludeSet.has(field) || excludeSet.has(fullKey)) continue;\n\n const { inner, nullable } = unwrap(fieldSchema);\n const typeName = getTypeName(inner);\n const isNullable = parentNullable || nullable;\n\n // Nested object → recurse to flatten\n if (typeName === \"ZodObject\") {\n const nestedShape = getShape(inner as z.ZodObject<any>);\n flattenSchema(\n nestedShape,\n dialect,\n fullKey,\n isNullable,\n excludeSet,\n columnMap,\n primaryKey,\n columns,\n );\n continue;\n }\n\n // Arrays and other complex types → JSON\n const logical = LOGICAL_MAP[typeName] ?? \"json\";\n const isPK = fullKey === primaryKey || field === primaryKey;\n const colName = columnMap[fullKey] ?? columnMap[field] ?? fullKey;\n\n columns.push({\n name: colName,\n sqlType: dialect.mapType(logical),\n nullable: isPK ? false : isNullable,\n isPrimaryKey: isPK,\n });\n }\n}\n\n/**\n * Convert a Zod object schema into an array of {@link SqlColumn} definitions\n * suitable for SQL table creation.\n *\n * Nested ZodObject fields are recursively flattened into separate columns\n * with underscore-separated names (e.g. `address.street` → `address_street`).\n * Arrays become JSON columns.\n */\nexport function zodSchemaToColumns(\n schema: z.ZodObject<any>,\n dialect: SqlDialect,\n options: ZodSchemaToColumnsOptions = {},\n): SqlColumn[] {\n const { primaryKey, exclude = [], columnMap = {} } = options;\n const excludeSet = new Set(exclude);\n const shape = getShape(schema);\n const columns: SqlColumn[] = [];\n\n flattenSchema(shape, dialect, \"\", false, excludeSet, columnMap, primaryKey, columns);\n\n // Internal version column used by the worker to discard out-of-order\n // PubSub deliveries (added unconditionally — never excluded).\n if (!columns.some((c) => c.name === SYNC_VERSION_COLUMN)) {\n columns.push({\n name: SYNC_VERSION_COLUMN,\n sqlType: dialect.mapType(\"bigint\"),\n nullable: true,\n isPrimaryKey: false,\n description: \"Monotonic publish version (Date.now() ms). Internal.\",\n });\n }\n\n return columns;\n}\n","/**\n * Internal constants shared between the worker, queue, schema mapper and\n * SQL adapters.\n */\n\n/**\n * Name of the SQL column that stores the publish-time `version` of each\n * sync event. Used by the worker to discard out-of-order PubSub deliveries\n * (the MERGE only updates rows when the incoming version is strictly\n * greater than the stored one).\n *\n * Two underscores prefix avoids collisions with user-defined fields.\n */\nexport const SYNC_VERSION_COLUMN = \"__sync_version\";\n","import type { RepoSyncConfig } from \"./types\";\n\n/**\n * Convert a single Firestore value into a SQL-safe primitive.\n *\n * Complex types (arrays, GeoPoints, binary) become JSON strings.\n * Primitives pass through unchanged.\n * Objects are NOT stringified here — they are flattened by serializeDocument.\n */\nexport function serializeValue(value: unknown): unknown {\n if (value === null || value === undefined) return null;\n\n // Firestore Timestamp (duck-typed: has .toDate())\n if (\n typeof value === \"object\" &&\n typeof (value as Record<string, unknown>).toDate === \"function\"\n ) {\n return ((value as { toDate(): Date }).toDate()).toISOString();\n }\n\n if (value instanceof Date) return value.toISOString();\n\n if (Buffer.isBuffer(value)) return value.toString(\"base64\");\n\n if (value instanceof Uint8Array) {\n return Buffer.from(value).toString(\"base64\");\n }\n\n // Firestore GeoPoint (duck-typed: has latitude & longitude)\n if (\n typeof value === \"object\" &&\n \"latitude\" in (value as object) &&\n \"longitude\" in (value as object)\n ) {\n const geo = value as { latitude: number; longitude: number };\n return JSON.stringify({ lat: geo.latitude, lng: geo.longitude });\n }\n\n // Arrays → JSON (native JSON column in BigQuery)\n if (Array.isArray(value)) {\n return JSON.stringify(value.map(serializeValue));\n }\n\n // string | number | boolean — pass through\n // Plain objects are handled by flattenObject in serializeDocument\n return value;\n}\n\n/**\n * Recursively flatten a nested object into a flat key-value map\n * using underscore-separated keys: `{ address: { street: \"x\" } }` → `{ address_street: \"x\" }`.\n * Arrays and non-plain-object values are serialized as leaves.\n */\nfunction flattenObject(\n obj: Record<string, unknown>,\n prefix: string,\n result: Record<string, unknown>,\n): void {\n for (const [key, value] of Object.entries(obj)) {\n const flatKey = prefix ? `${prefix}__${key}` : key;\n\n if (\n value !== null &&\n value !== undefined &&\n typeof value === \"object\" &&\n !Array.isArray(value) &&\n !(value instanceof Date) &&\n !Buffer.isBuffer(value) &&\n !(value instanceof Uint8Array) &&\n // Not a Firestore Timestamp\n typeof (value as Record<string, unknown>).toDate !== \"function\" &&\n // Not a GeoPoint\n !(\"latitude\" in (value as object) && \"longitude\" in (value as object))\n ) {\n // Plain object → recurse\n flattenObject(value as Record<string, unknown>, flatKey, result);\n } else {\n result[flatKey] = serializeValue(value);\n }\n }\n}\n\n/**\n * Serialize a full Firestore document into a flat object of SQL-safe values.\n *\n * Nested objects are flattened into underscore-separated column names\n * (e.g. `address.street` → `address_street`). Arrays become JSON strings.\n * Applies optional field exclusions and column renames from `options`.\n */\nexport function serializeDocument(\n doc: Record<string, unknown>,\n options?: Pick<RepoSyncConfig, \"exclude\" | \"columnMap\">,\n): Record<string, unknown> {\n const exclude = new Set(options?.exclude);\n const columnMap = options?.columnMap ?? {};\n\n // First flatten the document\n const flat: Record<string, unknown> = {};\n flattenObject(doc, \"\", flat);\n\n // Then apply excludes and column renames\n const result: Record<string, unknown> = {};\n for (const [flatKey, value] of Object.entries(flat)) {\n if (exclude.has(flatKey)) continue;\n // Also check top-level prefix for excludes (e.g. exclude \"address\" removes all address_* cols)\n const topLevel = flatKey.split(\"__\")[0]!;\n if (topLevel !== flatKey && exclude.has(topLevel)) continue;\n const column =\n columnMap[flatKey] ??\n (flatKey.includes(\"__\")\n ? columnMap[flatKey.split(\"__\").pop()!]\n : undefined) ??\n flatKey;\n result[column] = value;\n }\n\n return result;\n}\n","/**\n * Sync Admin — optional HTTP endpoint for inspecting and managing the\n * Firestore → SQL sync pipeline.\n *\n * Features (gated by `featuresFlag`):\n * - **healthCheck** — compare expected Zod-derived columns vs actual SQL columns\n * - **manualSync** — force re-sync all documents in a Firestore collection\n * - **viewQueue** — inspect pending items in the per-repo SyncQueue\n *\n * @example\n * ```typescript\n * const sync = createFirestoreSync(repos, {\n * // …deps, adapter, etc.\n * admin: {\n * auth: { type: \"basic\", username: \"admin\", password: \"secret\" },\n * featuresFlag: { healthCheck: true, manualSync: true, viewQueue: true },\n * },\n * });\n *\n * export const adminsync = onRequest(sync.adminHandler!);\n * ```\n */\n\nimport { z } from \"zod\";\nimport type { AnyReq, AnyRes, RouteParams } from \"../servers/admin/router\";\nimport { MiniRouter } from \"../servers/admin/router\";\nimport type { SyncQueue } from \"./queue\";\nimport { zodSchemaToColumns } from \"./schema-mapper\";\nimport { serializeDocument } from \"./serializer\";\nimport type {\n adminsyncConfig,\n PubSubClientDep,\n RepoSyncConfig,\n SqlAdapter,\n SyncEvent,\n} from \"./types\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\ntype Req = AnyReq & { params: RouteParams };\n\ninterface RepoInfo {\n name: string;\n schema: z.ZodObject<any> | null;\n documentKey: string;\n tableName: string;\n isGroup: boolean;\n repoCfg: RepoSyncConfig<string> | undefined;\n repo: any;\n}\n\n// ---------------------------------------------------------------------------\n// Link-base resolution (emulator vs production)\n// ---------------------------------------------------------------------------\n\n/**\n * Compute the link base for all HTML links.\n *\n * In the Firebase emulator `FUNCTIONS_EMULATOR=true`, functions are served at\n * `http://localhost:5001/{project}/{region}/{functionTarget}/…`\n * and the browser needs the full prefix for navigation to work.\n *\n * In production, the Firebase proxy strips the prefix so `basePath` is enough.\n */\nfunction getLinkBase(req: any, base: string): string {\n if (process.env[\"FUNCTIONS_EMULATOR\"] === \"true\") {\n const project =\n process.env[\"GCLOUD_PROJECT\"] ??\n process.env[\"GOOGLE_CLOUD_PROJECT\"] ??\n \"demo-project\";\n const region = process.env[\"FUNCTION_REGION\"] ?? \"us-central1\";\n // FUNCTION_TARGET uses dots (e.g. \"sync.functions.adminsync\") but the\n // emulator URL uses hyphens (\"sync-functions-adminsync\").\n const target = (process.env[\"FUNCTION_TARGET\"] ?? \"\").replace(/\\./g, \"-\");\n return `/${project}/${region}/${target}${base}`;\n }\n\n // Cloud Functions v2: K_SERVICE = function name = URL path prefix.\n // Only add it when accessed via cloudfunctions.net (not custom domains).\n // Cloud Run (Gen 2) lowercases service names, but K_SERVICE may still\n // carry the original mixed-case export name — normalise to lowercase\n // so that generated links match the canonical URL.\n const service = process.env[\"K_SERVICE\"];\n const host: string = req.hostname ?? req.headers?.[\"host\"] ?? \"\";\n if (service && host.includes(\"cloudfunctions.net\")) {\n return `/${service.toLowerCase()}${base}`;\n }\n\n return base;\n}\n\n// ---------------------------------------------------------------------------\n// HTML helpers\n// ---------------------------------------------------------------------------\n\nfunction page(title: string, linkBase: string, body: string): string {\n return `<!DOCTYPE html>\n<html lang=\"en\"><head>\n<meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width,initial-scale=1\">\n<title>${title} — Sync Admin</title>\n<style>\n *{box-sizing:border-box;margin:0;padding:0}\n body{font-family:system-ui,-apple-system,sans-serif;background:#f5f5f5;color:#1a1a1a;padding:2rem}\n a{color:#0969da;text-decoration:none}a:hover{text-decoration:underline}\n h1{margin-bottom:1rem}h2{margin:1.5rem 0 .75rem}\n table{border-collapse:collapse;width:100%;margin-bottom:1rem}\n th,td{text-align:left;padding:.5rem .75rem;border:1px solid #d0d7de}\n th{background:#f6f8fa;font-weight:600}\n tr:nth-child(even){background:#fafbfc}\n .badge{display:inline-block;padding:.15rem .5rem;border-radius:1rem;font-size:.8rem;font-weight:600}\n .badge-ok{background:#dafbe1;color:#1a7f37}\n .badge-warn{background:#fff8c5;color:#9a6700}\n .badge-err{background:#ffebe9;color:#cf222e}\n .btn{display:inline-block;padding:.4rem 1rem;border:1px solid #d0d7de;border-radius:.375rem;\n background:#fff;cursor:pointer;font-size:.85rem;text-decoration:none;color:#1a1a1a}\n .btn:hover{background:#f3f4f6}.btn-primary{background:#0969da;color:#fff;border-color:#0969da}\n .btn-primary:hover{background:#0860ca}\n nav{margin-bottom:1.5rem}nav a{margin-right:1rem}\n .card{background:#fff;border:1px solid #d0d7de;border-radius:.5rem;padding:1.25rem;margin-bottom:1rem}\n pre{background:#f6f8fa;padding:1rem;border-radius:.375rem;overflow-x:auto;font-size:.85rem}\n .muted{color:#656d76;font-size:.85rem}\n</style>\n</head><body>\n<nav><a href=\"${linkBase}/\">← Dashboard</a></nav>\n<h1>${title}</h1>\n${body}\n</body></html>`;\n}\n\nfunction sendHtml(res: AnyRes, html: string, status = 200): void {\n res.status(status).set(\"Content-Type\", \"text/html; charset=utf-8\").send(html);\n}\n\nfunction sendJson(res: AnyRes, data: unknown, status = 200): void {\n res\n .status(status)\n .set(\"Content-Type\", \"application/json\")\n .send(JSON.stringify(data, null, 2));\n}\n\nfunction isJsonRequest(req: AnyReq): boolean {\n const accept = (req.headers?.[\"accept\"] ?? \"\") as string;\n return accept.includes(\"application/json\");\n}\n\n// ---------------------------------------------------------------------------\n// Factory\n// ---------------------------------------------------------------------------\n\n/**\n * Create the sync admin HTTP handler.\n *\n * @param repoMapping - The configured repository mapping\n * @param adapter - The SQL adapter (e.g. BigQueryAdapter)\n * @param queues - Live queue map from the worker\n * @param handleMessage - Direct SyncEvent processor from the worker\n * @param config - Admin-specific config (auth, basePath, features)\n * @param repoConfigs - Per-repo sync config (tableName, exclude, columnMap…)\n * @param pubsub - PubSub client (needed for configCheck)\n * @param topicPrefix - PubSub topic prefix (needed for configCheck)\n */\nexport function createadminsyncServer(\n repoMapping: Record<string, any>,\n adapter: SqlAdapter,\n queues: Map<string, SyncQueue>,\n handleMessage: (event: SyncEvent) => Promise<void>,\n config: adminsyncConfig,\n repoConfigs: Record<string, RepoSyncConfig<string> | undefined>,\n pubsub?: PubSubClientDep,\n topicPrefix?: string,\n): (req: any, res: any) => Promise<void> {\n const basePath = (config.basePath ?? \"/\").replace(/\\/$/, \"\") || \"\";\n const features = config.featuresFlag ?? {};\n\n // Pre-compute repo info\n const repoInfos: RepoInfo[] = [];\n for (const [name, repo] of Object.entries(repoMapping)) {\n const repoCfg = repoConfigs[name];\n repoInfos.push({\n name,\n schema: (repo as any).schema ?? null,\n documentKey:\n (repo as any)._systemKeys?.[0] ?? (repo as any).documentKey ?? \"docId\",\n tableName: repoCfg?.tableName ?? name,\n isGroup: !!(repo as any)._isGroup,\n repoCfg,\n repo,\n });\n }\n\n const router = new MiniRouter();\n\n // -- Auth middleware -----------------------------------------------------\n if (config.auth) {\n if (typeof config.auth === \"function\") {\n router.use(config.auth as any);\n } else {\n const realm = config.auth.realm ?? \"Sync Admin\";\n const expected =\n \"Basic \" +\n Buffer.from(`${config.auth.username}:${config.auth.password}`).toString(\n \"base64\",\n );\n router.use((req, res, next) => {\n const authorization = (req as any).headers?.[\"authorization\"] ?? \"\";\n if (authorization !== expected) {\n res\n .status(401)\n .set(\"WWW-Authenticate\", `Basic realm=\"${realm}\"`)\n .set(\"Content-Type\", \"text/plain\")\n .send(\"Unauthorized\");\n return;\n }\n next();\n });\n }\n }\n\n // -- Dashboard ----------------------------------------------------------\n router.get(`${basePath}/`, (req, res) => {\n const lb = getLinkBase(req, basePath);\n const rows = repoInfos\n .map((r) => {\n const links: string[] = [];\n if (features.healthCheck)\n links.push(`<a class=\"btn\" href=\"${lb}/${r.name}/health\">Health</a>`);\n if (features.manualSync)\n links.push(\n `<a class=\"btn btn-primary\" href=\"${lb}/${r.name}/force-sync\">Force Sync</a>`,\n );\n return `<tr>\n <td><strong>${r.name}</strong></td>\n <td>${r.tableName}</td>\n <td>${r.isGroup ? '<span class=\"badge badge-warn\">group</span>' : '<span class=\"badge badge-ok\">collection</span>'}</td>\n <td>${r.schema ? \"✓\" : \"✗\"}</td>\n <td>${links.join(\" \")}</td>\n </tr>`;\n })\n .join(\"\\n\");\n\n const queueLink = features.viewQueue\n ? `<p><a class=\"btn\" href=\"${lb}/queues\">View Queues</a></p>`\n : \"\";\n\n const configCheckLink = features.configCheck\n ? `<p style=\"margin-top:.5rem\"><a class=\"btn\" href=\"${lb}/config-check\">⚙ Config Check</a></p>`\n : \"\";\n\n const html = page(\n \"Sync Dashboard\",\n lb,\n `<div class=\"card\">\n <table>\n <thead><tr><th>Repository</th><th>Table</th><th>Type</th><th>Schema</th><th>Actions</th></tr></thead>\n <tbody>${rows}</tbody>\n </table>\n ${queueLink}\n ${configCheckLink}\n </div>`,\n );\n sendHtml(res, html);\n });\n router.get(`${basePath}`, (req, res) => {\n const lb = getLinkBase(req, basePath);\n res.status(302).set(\"Location\", `${lb}/`).send(\"\");\n });\n\n // -- Health Check -------------------------------------------------------\n if (features.healthCheck) {\n router.get(`${basePath}/:repoName/health`, async (req: Req, res) => {\n const lb = getLinkBase(req, basePath);\n const info = repoInfos.find((r) => r.name === req.params.repoName);\n if (!info) {\n sendHtml(\n res,\n page(\"Not Found\", lb, `<p>Unknown repo: ${req.params.repoName}</p>`),\n 404,\n );\n return;\n }\n if (!info.schema) {\n sendHtml(\n res,\n page(\n \"Health Check\",\n lb,\n `<p class=\"badge badge-warn\">No Zod schema attached to \"${info.name}\"</p>`,\n ),\n );\n return;\n }\n\n const expectedCols = zodSchemaToColumns(info.schema, adapter.dialect, {\n primaryKey: info.documentKey,\n exclude: info.repoCfg?.exclude,\n columnMap: info.repoCfg?.columnMap as\n | Record<string, string>\n | undefined,\n });\n\n let actualCols: string[] = [];\n let tableExists = false;\n let error: string | null = null;\n try {\n tableExists = await adapter.tableExists(info.tableName);\n if (tableExists) {\n actualCols = await adapter.getTableColumns(info.tableName);\n }\n } catch (e: any) {\n error = e?.message ?? String(e);\n }\n\n const actualSet = new Set(actualCols);\n const expectedSet = new Set(expectedCols.map((c) => c.name));\n\n const missing = expectedCols.filter((c) => !actualSet.has(c.name));\n const extra = actualCols.filter((c) => !expectedSet.has(c));\n const matched = expectedCols.filter((c) => actualSet.has(c.name));\n\n const isHealthy = tableExists && missing.length === 0 && !error;\n\n if (isJsonRequest(req)) {\n sendJson(res, {\n repo: info.name,\n table: info.tableName,\n tableExists,\n healthy: isHealthy,\n error,\n columns: {\n expected: expectedCols.map((c) => ({\n name: c.name,\n type: c.sqlType,\n nullable: c.nullable,\n isPrimaryKey: c.isPrimaryKey,\n })),\n actual: actualCols,\n matched: matched.map((c) => c.name),\n missing: missing.map((c) => ({\n name: c.name,\n type: c.sqlType,\n })),\n extra,\n },\n });\n return;\n }\n\n const statusBadge = isHealthy\n ? '<span class=\"badge badge-ok\">Healthy</span>'\n : '<span class=\"badge badge-err\">Unhealthy</span>';\n\n const colRows = expectedCols\n .map((c) => {\n const status = actualSet.has(c.name)\n ? '<span class=\"badge badge-ok\">OK</span>'\n : '<span class=\"badge badge-err\">MISSING</span>';\n return `<tr><td>${c.name}</td><td>${c.sqlType}</td><td>${c.nullable ? \"Yes\" : \"No\"}</td><td>${c.isPrimaryKey ? \"✓\" : \"\"}</td><td>${status}</td></tr>`;\n })\n .join(\"\\n\");\n\n const extraRows = extra\n .map(\n (c) =>\n `<tr><td>${c}</td><td colspan=\"3\" class=\"muted\">not in schema</td><td><span class=\"badge badge-warn\">EXTRA</span></td></tr>`,\n )\n .join(\"\\n\");\n\n const html = page(\n `Health: ${info.name}`,\n lb,\n `<div class=\"card\">\n <p>Table: <code>${info.tableName}</code> ${!tableExists ? '<span class=\"badge badge-err\">NOT FOUND</span>' : statusBadge}</p>\n ${error ? `<p class=\"badge badge-err\">Error: ${error}</p>` : \"\"}\n <h2>Columns</h2>\n <table>\n <thead><tr><th>Column</th><th>SQL Type</th><th>Nullable</th><th>PK</th><th>Status</th></tr></thead>\n <tbody>${colRows}${extraRows}</tbody>\n </table>\n </div>`,\n );\n sendHtml(res, html);\n });\n }\n\n // -- Force Sync ---------------------------------------------------------\n if (features.manualSync) {\n // GET — confirmation page\n router.get(`${basePath}/:repoName/force-sync`, (req: Req, res) => {\n const lb = getLinkBase(req, basePath);\n const info = repoInfos.find((r) => r.name === req.params.repoName);\n if (!info) {\n sendHtml(\n res,\n page(\"Not Found\", lb, `<p>Unknown repo: ${req.params.repoName}</p>`),\n 404,\n );\n return;\n }\n\n const html = page(\n `Force Sync: ${info.name}`,\n lb,\n `<div class=\"card\">\n <p>This will read <strong>all</strong> documents from the <code>${info.name}</code> Firestore collection\n and upsert them into the <code>${info.tableName}</code> SQL table.</p>\n <p class=\"muted\" style=\"margin:.75rem 0\">This may take a while for large collections.</p>\n <form method=\"POST\" action=\"${lb}/${info.name}/force-sync\">\n <button type=\"submit\" class=\"btn btn-primary\">Start Force Sync</button>\n </form>\n </div>`,\n );\n sendHtml(res, html);\n });\n\n // POST — execute\n router.post(`${basePath}/:repoName/force-sync`, async (req: Req, res) => {\n const lb = getLinkBase(req, basePath);\n const info = repoInfos.find((r) => r.name === req.params.repoName);\n if (!info) {\n sendJson(res, { error: `Unknown repo: ${req.params.repoName}` }, 404);\n return;\n }\n\n // Use the repository's collectionGroup or collection query\n const collRef = info.repo.ref;\n if (!collRef) {\n sendJson(\n res,\n { error: `No collection reference for \"${info.name}\"` },\n 400,\n );\n return;\n }\n\n let synced = 0;\n let errors = 0;\n const errorSamples: string[] = [];\n const batchSize = 500;\n const query = collRef.limit(batchSize);\n let lastDoc: any = null;\n\n try {\n // eslint-disable-next-line no-constant-condition\n while (true) {\n const paginatedQuery = lastDoc ? query.startAfter(lastDoc) : query;\n const snapshot = await paginatedQuery.get();\n if (snapshot.empty) break;\n\n for (const doc of snapshot.docs) {\n const data = doc.data() as Record<string, unknown>;\n const docId = String(data[info.documentKey] ?? doc.id);\n const serialized = serializeDocument(data, {\n exclude: info.repoCfg?.exclude,\n columnMap: info.repoCfg?.columnMap,\n });\n\n try {\n await handleMessage({\n operation: \"UPSERT\",\n repoName: info.name,\n docId,\n data: serialized,\n timestamp: new Date().toISOString(),\n });\n synced++;\n } catch (e: any) {\n errors++;\n const msg = e?.message ?? String(e);\n console.error(\n `[ForceSync:${info.name}] doc=${docId} failed:`,\n e,\n );\n if (errorSamples.length < 5) errorSamples.push(`${docId}: ${msg}`);\n }\n }\n\n lastDoc = snapshot.docs[snapshot.docs.length - 1];\n if (snapshot.docs.length < batchSize) break;\n }\n\n // Flush the queue for this repo\n const queue = queues.get(info.name);\n if (queue) await queue.flush();\n } catch (e: any) {\n if (isJsonRequest(req)) {\n sendJson(\n res,\n { error: e?.message ?? String(e), synced, errors },\n 500,\n );\n return;\n }\n sendHtml(\n res,\n page(\n `Force Sync: ${info.name}`,\n lb,\n `<div class=\"card\">\n <p class=\"badge badge-err\">Error: ${e?.message ?? String(e)}</p>\n <p>Synced ${synced} docs before failure (${errors} errors).</p>\n </div>`,\n ),\n 500,\n );\n return;\n }\n\n if (isJsonRequest(req)) {\n sendJson(res, {\n repo: info.name,\n table: info.tableName,\n synced,\n errors,\n ...(errorSamples.length > 0 && { errorSamples }),\n });\n return;\n }\n\n const errorBlock =\n errorSamples.length > 0\n ? `<details style=\"margin-top:1rem\"><summary>First ${errorSamples.length} error(s)</summary>\n <pre style=\"white-space:pre-wrap\">${errorSamples\n .map((s) => s.replace(/[<>&]/g, (c) => `&#${c.charCodeAt(0)};`))\n .join(\"\\n\\n\")}</pre></details>`\n : \"\";\n\n const html = page(\n `Force Sync: ${info.name}`,\n lb,\n `<div class=\"card\">\n <p class=\"badge ${errors > 0 ? \"badge-warn\" : \"badge-ok\"}\">${errors > 0 ? \"Completed with errors\" : \"Complete\"}</p>\n <p>Synced <strong>${synced}</strong> documents to <code>${info.tableName}</code>.</p>\n ${errors > 0 ? `<p class=\"badge badge-warn\">${errors} error(s)</p>` : \"\"}\n ${errorBlock}\n </div>`,\n );\n sendHtml(res, html);\n });\n }\n\n // -- View Queues --------------------------------------------------------\n if (features.viewQueue) {\n router.get(`${basePath}/queues`, (req, res) => {\n const lb = getLinkBase(req, basePath);\n const queueData: Array<{\n repo: string;\n table: string;\n pending: number;\n }> = [];\n\n for (const info of repoInfos) {\n const q = queues.get(info.name);\n queueData.push({\n repo: info.name,\n table: info.tableName,\n pending: q ? q.size : 0,\n });\n }\n\n if (isJsonRequest(req)) {\n sendJson(res, { queues: queueData });\n return;\n }\n\n const rows = queueData\n .map(\n (q) =>\n `<tr><td>${q.repo}</td><td>${q.table}</td><td>${q.pending === 0 ? '<span class=\"badge badge-ok\">0</span>' : `<span class=\"badge badge-warn\">${q.pending}</span>`}</td></tr>`,\n )\n .join(\"\\n\");\n\n const html = page(\n \"Sync Queues\",\n lb,\n `<div class=\"card\">\n <table>\n <thead><tr><th>Repository</th><th>Table</th><th>Pending</th></tr></thead>\n <tbody>${rows}</tbody>\n </table>\n </div>`,\n );\n sendHtml(res, html);\n });\n }\n\n // -- Config Check -------------------------------------------------------\n if (features.configCheck) {\n router.get(`${basePath}/config-check`, async (req, res) => {\n const lb = getLinkBase(req, basePath);\n const project =\n process.env[\"GCLOUD_PROJECT\"] ??\n process.env[\"GOOGLE_CLOUD_PROJECT\"] ??\n process.env[\"GCP_PROJECT\"] ??\n \"unknown\";\n const consoleBase = `https://console.cloud.google.com`;\n const tPrefix = topicPrefix ?? \"firestore-sync\";\n\n interface CheckResult {\n name: string;\n category: \"bigquery\" | \"pubsub\" | \"firestore\";\n status: \"ok\" | \"error\" | \"warn\";\n message: string;\n fix?: { gcloud?: string; console?: string; hint?: string };\n }\n\n const checks: CheckResult[] = [];\n\n // --- BigQuery checks ---\n // 1. General BQ connectivity (try listing tables via a simple exists check)\n try {\n await adapter.tableExists(\"__nonexistent_health_check__\");\n checks.push({\n name: \"BigQuery API\",\n category: \"bigquery\",\n status: \"ok\",\n message: \"BigQuery API is reachable\",\n });\n } catch (e: any) {\n const msg = e?.message ?? String(e);\n const msgLower = msg.toLowerCase();\n const isApiDisabled =\n msgLower.includes(\"disabled\") ||\n msgLower.includes(\"has not been used\") ||\n msgLower.includes(\"accessnotconfigured\");\n const isPermission =\n msgLower.includes(\"permission\") ||\n msg.includes(\"403\") ||\n msgLower.includes(\"access denied\");\n const isProjectNotFound =\n msgLower.includes(\"project\") && msgLower.includes(\"not found\");\n const isNotFound =\n msgLower.includes(\"not found\") || msg.includes(\"404\");\n\n if (isApiDisabled) {\n checks.push({\n name: \"BigQuery API\",\n category: \"bigquery\",\n status: \"error\",\n message: \"BigQuery API is not enabled\",\n fix: {\n gcloud: `gcloud services enable bigquery.googleapis.com --project=${project}`,\n console: `${consoleBase}/apis/library/bigquery.googleapis.com?project=${project}`,\n },\n });\n } else if (isProjectNotFound) {\n checks.push({\n name: \"BigQuery Project\",\n category: \"bigquery\",\n status: \"error\",\n message: msg,\n fix: {\n hint:\n \"The GCP project does not exist or the credentials don't have access to it. \" +\n \"In the Firebase emulator, GCLOUD_PROJECT may override the configured projectId. \" +\n \"Ensure you pass the correct projectId to the BigQuery constructor and have valid credentials.\",\n console: `${consoleBase}/home/dashboard`,\n },\n });\n } else if (isPermission) {\n checks.push({\n name: \"BigQuery API\",\n category: \"bigquery\",\n status: \"error\",\n message: `Permission denied: ${msg}`,\n fix: {\n hint: \"Grant the service account BigQuery Data Editor + BigQuery Job User roles\",\n gcloud: [\n `SA=$(gcloud run services describe YOUR_SERVICE --region=YOUR_REGION --format=\"value(spec.template.spec.serviceAccountName)\" --project=${project})`,\n `gcloud projects add-iam-policy-binding ${project} --member=\"serviceAccount:$SA\" --role=\"roles/bigquery.dataEditor\"`,\n `gcloud projects add-iam-policy-binding ${project} --member=\"serviceAccount:$SA\" --role=\"roles/bigquery.jobUser\"`,\n ].join(\"\\n\"),\n console: `${consoleBase}/iam-admin/iam?project=${project}`,\n },\n });\n } else if (isNotFound) {\n checks.push({\n name: \"BigQuery Dataset\",\n category: \"bigquery\",\n status: \"error\",\n message: `Dataset not found: ${msg}`,\n fix: {\n hint: \"Create the dataset first\",\n gcloud: `bq mk --dataset ${project}:YOUR_DATASET_ID`,\n console: `${consoleBase}/bigquery?project=${project}`,\n },\n });\n } else {\n checks.push({\n name: \"BigQuery API\",\n category: \"bigquery\",\n status: \"ok\",\n message:\n \"BigQuery API is reachable (table lookup returned expected error)\",\n });\n }\n }\n\n // 2. Per-repo table existence\n for (const info of repoInfos) {\n try {\n const exists = await adapter.tableExists(info.tableName);\n checks.push({\n name: `Table: ${info.tableName}`,\n category: \"bigquery\",\n status: exists ? \"ok\" : \"warn\",\n message: exists\n ? `Table \\`${info.tableName}\\` exists`\n : `Table \\`${info.tableName}\\` does not exist yet`,\n ...(!exists && {\n fix: {\n hint: \"Table will be auto-created on first sync if autoMigrate is enabled. Or create it manually.\",\n },\n }),\n });\n } catch (e: any) {\n checks.push({\n name: `Table: ${info.tableName}`,\n category: \"bigquery\",\n status: \"error\",\n message: e?.message ?? String(e),\n });\n }\n }\n\n // --- Pub/Sub checks ---\n if (pubsub) {\n for (const info of repoInfos) {\n const topicName = `${tPrefix}-${info.name}`;\n try {\n // Try to get topic metadata — succeeds if it exists\n const topic = (pubsub as any).topic(topicName);\n if (typeof topic.exists === \"function\") {\n const [exists] = await topic.exists();\n checks.push({\n name: `Topic: ${topicName}`,\n category: \"pubsub\",\n status: exists ? \"ok\" : \"error\",\n message: exists\n ? `Topic \\`${topicName}\\` exists`\n : `Topic \\`${topicName}\\` does not exist`,\n ...(!exists && {\n fix: {\n gcloud: `gcloud pubsub topics create ${topicName} --project=${project}`,\n console: `${consoleBase}/cloudpubsub/topic/list?project=${project}`,\n },\n }),\n });\n } else {\n // Minimal PubSub client — can't check existence, try publishing a no-op\n checks.push({\n name: `Topic: ${topicName}`,\n category: \"pubsub\",\n status: \"warn\",\n message:\n \"Cannot verify topic existence (PubSub client doesn't expose .exists())\",\n fix: {\n gcloud: `gcloud pubsub topics create ${topicName} --project=${project}`,\n console: `${consoleBase}/cloudpubsub/topic/list?project=${project}`,\n hint: \"Ensure the topic exists. It is auto-created by the Firebase emulator but must exist in production.\",\n },\n });\n }\n } catch (e: any) {\n const msg = e?.message ?? String(e);\n const isApiDisabled =\n msg.includes(\"disabled\") || msg.includes(\"has not been used\");\n checks.push({\n name: isApiDisabled ? \"Pub/Sub API\" : `Topic: ${topicName}`,\n category: \"pubsub\",\n status: \"error\",\n message: isApiDisabled ? \"Pub/Sub API is not enabled\" : msg,\n fix: isApiDisabled\n ? {\n gcloud: `gcloud services enable pubsub.googleapis.com --project=${project}`,\n console: `${consoleBase}/apis/library/pubsub.googleapis.com?project=${project}`,\n }\n : {\n gcloud: `gcloud pubsub topics create ${topicName} --project=${project}`,\n console: `${consoleBase}/cloudpubsub/topic/list?project=${project}`,\n },\n });\n // If the API itself is disabled, skip remaining topic checks\n if (isApiDisabled) break;\n }\n }\n } else {\n checks.push({\n name: \"Pub/Sub Client\",\n category: \"pubsub\",\n status: \"warn\",\n message: \"PubSub client not available for config check\",\n });\n }\n\n // --- JSON response ---\n if (isJsonRequest(req)) {\n const allOk = checks.every((c) => c.status === \"ok\");\n sendJson(res, { project, healthy: allOk, checks });\n return;\n }\n\n // --- HTML response ---\n const statusIcon = (s: string) =>\n s === \"ok\"\n ? '<span class=\"badge badge-ok\">OK</span>'\n : s === \"warn\"\n ? '<span class=\"badge badge-warn\">WARN</span>'\n : '<span class=\"badge badge-err\">ERROR</span>';\n\n const grouped = {\n bigquery: checks.filter((c) => c.category === \"bigquery\"),\n pubsub: checks.filter((c) => c.category === \"pubsub\"),\n firestore: checks.filter((c) => c.category === \"firestore\"),\n };\n\n const renderSection = (title: string, items: CheckResult[]) => {\n if (items.length === 0) return \"\";\n const rows = items\n .map((c) => {\n let fixHtml = \"\";\n if (c.fix) {\n const parts: string[] = [];\n if (c.fix.hint) parts.push(`<p class=\"muted\">${c.fix.hint}</p>`);\n if (c.fix.gcloud) parts.push(`<pre>$ ${c.fix.gcloud}</pre>`);\n if (c.fix.console)\n parts.push(\n `<p><a href=\"${c.fix.console}\" target=\"_blank\">Open GCP Console →</a></p>`,\n );\n fixHtml = `<div style=\"margin-top:.5rem\">${parts.join(\"\")}</div>`;\n }\n return `<tr>\n <td>${statusIcon(c.status)}</td>\n <td><strong>${c.name}</strong><br><span class=\"muted\">${c.message}</span>${fixHtml}</td>\n </tr>`;\n })\n .join(\"\\n\");\n return `<h2>${title}</h2>\n <table><thead><tr><th style=\"width:80px\">Status</th><th>Check</th></tr></thead>\n <tbody>${rows}</tbody></table>`;\n };\n\n const allOk = checks.every((c) => c.status === \"ok\");\n const overallBadge = allOk\n ? '<span class=\"badge badge-ok\">All checks passed</span>'\n : '<span class=\"badge badge-warn\">Some issues found</span>';\n\n const html = page(\n \"Config Check\",\n lb,\n `<div class=\"card\">\n <p>Project: <code>${project}</code> ${overallBadge}</p>\n ${renderSection(\"BigQuery\", grouped.bigquery)}\n ${renderSection(\"Pub/Sub\", grouped.pubsub)}\n ${renderSection(\"Firestore\", grouped.firestore)}\n </div>`,\n );\n sendHtml(res, html);\n });\n }\n\n // -- Request handler ----------------------------------------------------\n return async (req: any, res: any): Promise<void> => {\n await router.handle(req, res);\n };\n}\n","/**\n * Firestore Cloud Function triggers that publish {@link SyncEvent}s to\n * Google Cloud PubSub.\n *\n * Dependencies (`firebase-functions`, `@google-cloud/pubsub`) are injected\n * via the `deps` config property — no lazy loading or module resolution issues.\n *\n * Out-of-order delivery is handled at the application level: every event\n * carries a `version` (publish-time `Date.now()` in ms) which is propagated\n * to SQL as the `__sync_version` column. The worker's MERGE only updates a\n * row when the incoming `version` is strictly greater than the stored one —\n * so a stale event delivered after a newer one is silently skipped.\n *\n * @example\n * ```typescript\n * import { createSyncTriggers } from \"@lpdjs/firestore-repo-service/sync\";\n * import * as firestoreTriggers from \"firebase-functions/v2/firestore\";\n * import { PubSub } from \"@google-cloud/pubsub\";\n *\n * const triggers = createSyncTriggers(repos, {\n * deps: { firestoreTriggers, pubsub: new PubSub() },\n * topicPrefix: \"my-sync\",\n * repos: { users: { exclude: [\"password\"] } },\n * });\n *\n * export const { users_onCreate, users_onUpdate, users_onDelete } = triggers;\n * ```\n */\n\nimport { serializeDocument } from \"./serializer\";\nimport type { RepoSyncConfig, SyncEvent, SyncTriggersConfig } from \"./types\";\n\nconst DEFAULT_TOPIC_PREFIX = \"firestore-sync\";\n\n/**\n * Derive the Firestore document path pattern for a trigger.\n * Returns `null` when the collection path cannot be determined.\n */\nfunction buildDocumentPath(repoName: string, repo: any): string | null {\n const collectionPath: string | undefined =\n (repo as any).ref?.path ?? undefined;\n\n if (!collectionPath) {\n console.warn(\n `[SyncTriggers] Cannot determine collection path for \"${repoName}\". Skipping.`,\n );\n return null;\n }\n\n return `${collectionPath}/{docId}`;\n}\n\n/**\n * Create Firestore Cloud Functions (v2) triggers that publish\n * {@link SyncEvent}s to PubSub for each repository in `repoMapping`.\n *\n * For each non-group repository, three triggers are created:\n * - `{repoName}_onCreate` → publishes an `INSERT` event\n * - `{repoName}_onUpdate` → publishes an `UPSERT` event\n * - `{repoName}_onDelete` → publishes a `DELETE` event\n *\n * Each event carries a monotonic `version` (`Date.now()` in ms) used by\n * the worker to discard out-of-order PubSub deliveries.\n */\nexport function createSyncTriggers<M extends Record<string, any>>(\n repoMapping: M,\n config: SyncTriggersConfig<NoInfer<M>>,\n): Record<string, any> {\n const { onDocumentCreated, onDocumentUpdated, onDocumentDeleted } =\n config.deps.firestoreTriggers;\n const pubsub = config.deps.pubsub;\n\n const topicPrefix = config?.topicPrefix ?? DEFAULT_TOPIC_PREFIX;\n const triggers: Record<string, any> = {};\n\n // Cache topic clients so the publisher reuses the same batching state\n // for a given topic across invocations.\n const topicCache = new Map<string, any>();\n function getTopic(topicName: string): any {\n let t = topicCache.get(topicName);\n if (t) return t;\n t = (pubsub as any).topic(topicName);\n topicCache.set(topicName, t);\n return t;\n }\n\n async function publish(\n topicName: string,\n syncEvent: SyncEvent,\n ): Promise<void> {\n const topic = getTopic(topicName);\n await topic.publishMessage({ json: syncEvent });\n }\n\n for (const [repoName, repo] of Object.entries(repoMapping) as [\n string,\n any,\n ][]) {\n const repoCfg = (\n config?.repos as Record<string, RepoSyncConfig<string>> | undefined\n )?.[repoName];\n\n let documentPath: string | null;\n\n if ((repo as any)._isGroup) {\n if (!repoCfg?.triggerPath) {\n console.warn(\n `[SyncTriggers] Skipping collection-group repo \"${repoName}\". ` +\n \"Provide a triggerPath in the sync repos config for group collections.\",\n );\n continue;\n }\n documentPath = repoCfg.triggerPath;\n } else {\n documentPath = repoCfg?.triggerPath ?? buildDocumentPath(repoName, repo);\n }\n if (!documentPath) continue;\n\n const documentKey: string = (repo as any)._systemKeys?.[0] ?? \"docId\";\n const topicName = `${topicPrefix}-${repoName}`;\n\n triggers[`${repoName}_onCreate`] = onDocumentCreated(\n documentPath,\n async (event: any) => {\n const snap = event.data;\n if (!snap) return;\n\n const data = snap.data() as Record<string, unknown> | undefined;\n if (!data) return;\n\n const docId = String(data[documentKey] ?? snap.id);\n const serialized = serializeDocument(data, {\n exclude: repoCfg?.exclude,\n columnMap: repoCfg?.columnMap,\n });\n\n const syncEvent: SyncEvent = {\n operation: \"INSERT\",\n repoName,\n docId,\n data: serialized,\n timestamp: new Date().toISOString(),\n version: Date.now(),\n };\n\n await publish(topicName, syncEvent);\n },\n );\n\n triggers[`${repoName}_onUpdate`] = onDocumentUpdated(\n documentPath,\n async (event: any) => {\n const snap = event.data?.after;\n if (!snap) return;\n\n const data = snap.data() as Record<string, unknown> | undefined;\n if (!data) return;\n\n const docId = String(data[documentKey] ?? snap.id);\n const serialized = serializeDocument(data, {\n exclude: repoCfg?.exclude,\n columnMap: repoCfg?.columnMap,\n });\n\n const syncEvent: SyncEvent = {\n operation: \"UPSERT\",\n repoName,\n docId,\n data: serialized,\n timestamp: new Date().toISOString(),\n version: Date.now(),\n };\n\n await publish(topicName, syncEvent);\n },\n );\n\n triggers[`${repoName}_onDelete`] = onDocumentDeleted(\n documentPath,\n async (event: any) => {\n const snap = event.data;\n if (!snap) return;\n\n const data = snap.data() as Record<string, unknown> | undefined;\n const docId = String(data?.[documentKey] ?? snap.id);\n\n const syncEvent: SyncEvent = {\n operation: \"DELETE\",\n repoName,\n docId,\n data: null,\n timestamp: new Date().toISOString(),\n version: Date.now(),\n };\n\n await publish(topicName, syncEvent);\n },\n );\n }\n\n return triggers;\n}\n","/**\n * Per-repo in-memory batch buffer.\n *\n * Accumulates {@link SyncEvent}s and flushes them in batches to a\n * {@link SqlAdapter}. On flush failure the events are re-published\n * to PubSub for retry (if a PubSub re-publisher is provided).\n */\n\nimport { SYNC_VERSION_COLUMN } from \"./constants\";\nimport type { SqlAdapter, SyncEvent } from \"./types\";\n\nexport interface SyncQueueOptions {\n /** SQL adapter to flush data to */\n adapter: SqlAdapter;\n /** SQL table name */\n tableName: string;\n /** Primary key column name */\n primaryKey: string;\n /** Max rows per flush (default: 100) */\n batchSize?: number;\n /** Auto-flush interval in ms (default: 5_000). 0 = manual only. */\n flushIntervalMs?: number;\n /** Called on flush failure with the failed events. Typically re-publishes to PubSub. */\n onFlushError?: (events: SyncEvent[], error: unknown) => Promise<void>;\n}\n\n/**\n * In-memory buffer that batches sync events per-repo and flushes them\n * to a SQL adapter.\n */\nexport class SyncQueue {\n private buffer: SyncEvent[] = [];\n private flushing = false;\n private timer: ReturnType<typeof setInterval> | null = null;\n\n private readonly adapter: SqlAdapter;\n private readonly tableName: string;\n private readonly primaryKey: string;\n private readonly batchSize: number;\n private readonly onFlushError?: SyncQueueOptions[\"onFlushError\"];\n\n constructor(opts: SyncQueueOptions) {\n this.adapter = opts.adapter;\n this.tableName = opts.tableName;\n this.primaryKey = opts.primaryKey;\n this.batchSize = opts.batchSize ?? 100;\n this.onFlushError = opts.onFlushError;\n\n const interval = opts.flushIntervalMs ?? 5_000;\n if (interval > 0) {\n this.timer = setInterval(() => void this.flush(), interval);\n // Allow the Node process to exit even if the timer is running\n if (typeof this.timer === \"object\" && \"unref\" in this.timer) {\n this.timer.unref();\n }\n }\n }\n\n /** Number of events waiting in the buffer. */\n get size(): number {\n return this.buffer.length;\n }\n\n /** Push one or more events into the buffer. Triggers auto-flush if batchSize reached. */\n enqueue(...events: SyncEvent[]): void {\n this.buffer.push(...events);\n if (this.buffer.length >= this.batchSize) {\n void this.flush();\n }\n }\n\n /**\n * Flush all buffered events to the SQL adapter.\n * Upserts and deletes are batched separately.\n */\n async flush(): Promise<void> {\n if (this.flushing || this.buffer.length === 0) return;\n this.flushing = true;\n\n // Drain the buffer atomically\n const batch = this.buffer.splice(0, this.batchSize);\n\n try {\n const upsertsById = new Map<string, Record<string, unknown>>();\n const deleteIds: string[] = [];\n\n for (const evt of batch) {\n if (evt.operation === \"DELETE\") {\n deleteIds.push(evt.docId);\n // A delete supersedes any pending upsert in the same batch.\n upsertsById.delete(evt.docId);\n } else if (evt.data) {\n // Multiple updates to the same doc within a single batch would\n // make BigQuery MERGE error out (\"UPDATE/MERGE must match at\n // most one source row for each target row\"). Keep only the row\n // with the highest __sync_version per docId.\n const existing = upsertsById.get(evt.docId);\n if (!existing) {\n upsertsById.set(evt.docId, evt.data);\n } else {\n const a = Number(existing[SYNC_VERSION_COLUMN] ?? 0);\n const b = Number(evt.data[SYNC_VERSION_COLUMN] ?? 0);\n if (b >= a) upsertsById.set(evt.docId, evt.data);\n }\n }\n }\n\n const upserts = Array.from(upsertsById.values());\n\n if (upserts.length > 0) {\n await this.adapter.upsertRows(this.tableName, upserts, this.primaryKey);\n }\n if (deleteIds.length > 0) {\n await this.adapter.deleteRows(\n this.tableName,\n this.primaryKey,\n deleteIds,\n );\n }\n } catch (err) {\n if (this.onFlushError) {\n await this.onFlushError(batch, err).catch((handlerErr) => {\n console.error(\n `[SyncQueue] Flush error for ${this.tableName}:`,\n err,\n );\n console.error(\n `[SyncQueue] Error handler also failed:`,\n handlerErr,\n );\n });\n } else {\n // Re-insert at the front so we retry next flush\n this.buffer.unshift(...batch);\n console.error(`[SyncQueue] Flush failed for ${this.tableName}:`, err);\n }\n } finally {\n this.flushing = false;\n }\n }\n\n /** Stop the auto-flush timer and flush remaining events. */\n async shutdown(): Promise<void> {\n if (this.timer) {\n clearInterval(this.timer);\n this.timer = null;\n }\n await this.flush();\n }\n}\n","/**\n * PubSub worker — creates a Cloud Function that receives {@link SyncEvent}\n * messages from PubSub, routes them to per-repo {@link SyncQueue}s, and\n * flushes batches to the configured {@link SqlAdapter}.\n *\n * Dependencies (`firebase-functions`, `@google-cloud/pubsub`) are injected\n * via the `deps` config property.\n */\n\nimport { z } from \"zod\";\nimport { SYNC_VERSION_COLUMN } from \"./constants\";\nimport { SyncQueue } from \"./queue\";\nimport { zodSchemaToColumns } from \"./schema-mapper\";\nimport type {\n RepoSyncConfig,\n SqlAdapter,\n SyncEvent,\n SyncWorkerConfig,\n} from \"./types\";\n\n// ---------------------------------------------------------------------------\n// Migration tracking\n// ---------------------------------------------------------------------------\n\n/** Set of repo names that have already been migrated in this process lifetime. */\nconst migratedRepos = new Set<string>();\n\nasync function ensureMigrated(\n repoName: string,\n adapter: SqlAdapter,\n schema: z.ZodObject<any>,\n tableName: string,\n primaryKey: string,\n exclude?: string[],\n columnMap?: Record<string, string>,\n): Promise<void> {\n if (migratedRepos.has(repoName)) return;\n\n const columns = zodSchemaToColumns(schema, adapter.dialect, {\n primaryKey,\n exclude,\n columnMap,\n });\n\n const exists = await adapter.tableExists(tableName);\n if (!exists) {\n await adapter.createTable({ tableName, columns });\n } else {\n const existing = new Set(await adapter.getTableColumns(tableName));\n const newCols = columns.filter((c) => !existing.has(c.name));\n if (newCols.length > 0) {\n await adapter.addColumns(tableName, newCols);\n }\n }\n\n migratedRepos.add(repoName);\n}\n\n// ---------------------------------------------------------------------------\n// Worker factory\n// ---------------------------------------------------------------------------\n\n/**\n * Create a PubSub-triggered Cloud Function that syncs Firestore changes\n * to a SQL database.\n *\n * Returns an object with:\n * - `createHandler` — creates a Cloud Function for a PubSub topic\n * - `handleMessage` — process a SyncEvent directly (for testing)\n * - `queues` — internal SyncQueue map (for testing / manual flush)\n * - `shutdown()` — flush all queues and stop timers\n */\nexport function createSyncWorker<M extends Record<string, any>>(\n repoMapping: M,\n config: SyncWorkerConfig<NoInfer<M>>,\n) {\n const {\n deps,\n adapter,\n batchSize = 100,\n flushIntervalMs = 5_000,\n autoMigrate = false,\n topicPrefix = \"firestore-sync\",\n workerOptions,\n repos: repoConfigs = {} as Record<\n string,\n RepoSyncConfig<string> | undefined\n >,\n } = config;\n\n // Build per-repo queues lazily\n const queues = new Map<string, SyncQueue>();\n\n function getQueue(repoName: string, primaryKey: string): SyncQueue {\n let q = queues.get(repoName);\n if (q) return q;\n\n const repoCfg = repoConfigs[repoName];\n const tableName = repoCfg?.tableName ?? repoName;\n\n // On flush failure → log error + re-publish to PubSub dead-letter\n const onFlushError = async (\n events: SyncEvent[],\n error: unknown,\n ): Promise<void> => {\n console.error(\n `[SyncWorker] Flush failed for \"${repoName}\" (${events.length} events):`,\n error,\n );\n try {\n const dlTopicName = `${topicPrefix}-${repoName}-dlq`;\n const dlTopic = deps.pubsub.topic(dlTopicName);\n const [exists] = await dlTopic.exists();\n if (!exists) {\n await dlTopic.create();\n console.info(`[SyncWorker] Created DLQ topic \"${dlTopicName}\"`);\n }\n for (const evt of events) {\n await dlTopic.publishMessage({ json: evt });\n }\n } catch (dlErr) {\n console.error(\n `[SyncWorker] Dead-letter publish also failed for ${repoName}:`,\n dlErr,\n );\n }\n };\n\n q = new SyncQueue({\n adapter,\n tableName,\n primaryKey,\n batchSize,\n flushIntervalMs,\n onFlushError,\n });\n queues.set(repoName, q);\n return q;\n }\n\n // Message handler (works with or without Cloud Functions wrapper)\n async function handleMessage(syncEvent: SyncEvent): Promise<void> {\n const { repoName } = syncEvent;\n const repo = (repoMapping as Record<string, any>)[repoName];\n if (!repo) {\n console.warn(`[SyncWorker] Unknown repo \"${repoName}\", skipping event`);\n return;\n }\n\n const documentKey: string =\n (repo as any)._systemKeys?.[0] ?? (repo as any).documentKey ?? \"docId\";\n\n const repoCfg = repoConfigs[repoName];\n const columnMap = repoCfg?.columnMap as Record<string, string> | undefined;\n // The primaryKey for BigQuery must use the mapped column name (e.g. docId → user_id)\n const primaryKey = columnMap?.[documentKey] ?? documentKey;\n\n if (autoMigrate) {\n const schema: z.ZodObject<any> | undefined =\n (repo as any).schema ?? undefined;\n if (schema) {\n const tableName = repoCfg?.tableName ?? repoName;\n await ensureMigrated(\n repoName,\n adapter,\n schema,\n tableName,\n documentKey,\n repoCfg?.exclude,\n columnMap,\n );\n }\n }\n\n const queue = getQueue(repoName, primaryKey);\n\n // Stamp the row with the publish version so the SQL adapter can skip\n // stale (out-of-order) updates. Force-sync events without a version\n // fall back to the wall clock — still monotonic per-process.\n if (syncEvent.data) {\n syncEvent.data[SYNC_VERSION_COLUMN] = syncEvent.version ?? Date.now();\n }\n\n queue.enqueue(syncEvent);\n }\n\n // Cloud Function v2 PubSub handler (sync — deps are already available)\n function createHandler(topicName: string) {\n const handlerFn = async (event: any) => {\n const data: SyncEvent = event.data?.message?.json ?? event.data?.json;\n if (!data) {\n console.warn(\"[SyncWorker] Received empty PubSub message\");\n return;\n }\n await handleMessage(data);\n // Flush so data is persisted before the Cloud Function container shuts down.\n // Force-sync (admin) handles its own flush after the batch loop.\n const q = queues.get(data.repoName);\n if (q) await q.flush();\n };\n\n if (workerOptions) {\n return deps.pubsubHandler.onMessagePublished(\n { topic: topicName, ...workerOptions },\n handlerFn,\n );\n }\n return deps.pubsubHandler.onMessagePublished(topicName, handlerFn);\n }\n\n return {\n /** Process a SyncEvent directly (for testing or custom PubSub integration). */\n handleMessage,\n /** Create a Cloud Function handler for a specific PubSub topic. */\n createHandler,\n /** Internal queue map (for testing). */\n queues,\n /** Flush all queues and stop timers. */\n async shutdown(): Promise<void> {\n const promises: Promise<void>[] = [];\n for (const q of queues.values()) {\n promises.push(q.shutdown());\n }\n await Promise.all(promises);\n },\n };\n}\n","/**\n * Unified wrapper — combines triggers + worker into a single call.\n *\n * @example\n * ```typescript\n * import * as firestoreTriggers from \"firebase-functions/v2/firestore\";\n * import * as pubsubHandler from \"firebase-functions/v2/pubsub\";\n * import { PubSub } from \"@google-cloud/pubsub\";\n *\n * const sync = createFirestoreSync(repos, {\n * deps: { firestoreTriggers, pubsubHandler, pubsub: new PubSub() },\n * adapter,\n * topicPrefix: \"firestore-sync\",\n * autoMigrate: true,\n * admin: {\n * auth: { type: \"basic\", username: \"admin\", password: \"secret\" },\n * featuresFlag: { healthCheck: true, manualSync: true, viewQueue: true },\n * },\n * repos: {\n * users: { exclude: [\"documentPath\"], columnMap: { docId: \"user_id\" } },\n * posts: { columnMap: { docId: \"post_id\" } },\n * },\n * });\n *\n * // Triggers + PubSub handlers\n * export const { users_onCreate, users_onUpdate, users_onDelete, sync_users } = sync.functions;\n *\n * // Admin endpoint — wrap with onRequest yourself\n * export const adminsync = onRequest(sync.adminHandler!);\n *\n * // Or pass onRequest in admin config to auto-add to sync.functions:\n * // admin: { onRequest, ... } → export const { adminsync } = sync.functions;\n * ```\n */\n\nimport { createadminsyncServer } from \"./admin\";\nimport type { SyncQueue } from \"./queue\";\nimport { createSyncTriggers } from \"./triggers\";\nimport type { FirestoreSyncConfig, OrFactory, RepoSyncConfig, SyncEvent } from \"./types\";\nimport { createSyncWorker } from \"./worker\";\n\nconst DEFAULT_TOPIC_PREFIX = \"firestore-sync\";\n\n/**\n * Wraps a value-or-factory into a lazy proxy that only instantiates\n * when a property is first accessed. If the value is already an instance,\n * returns it as-is (zero overhead).\n */\nfunction lazyProxy<T extends object>(v: OrFactory<T>): T {\n if (typeof v !== \"function\") return v;\n const factory = v as () => T;\n let instance: T | undefined;\n return new Proxy({} as T, {\n get(_, prop) {\n if (!instance) instance = factory();\n return (instance as any)[prop];\n },\n has(_, prop) {\n if (!instance) instance = factory();\n return prop in (instance as object);\n },\n });\n}\n\nexport function createFirestoreSync<M extends Record<string, any>>(\n repoMapping: M,\n config: FirestoreSyncConfig<NoInfer<M>>,\n) {\n const {\n deps,\n adapter: rawAdapter,\n topicPrefix = DEFAULT_TOPIC_PREFIX,\n batchSize,\n flushIntervalMs,\n autoMigrate,\n admin: adminConfig,\n workerOptions,\n repos: repoConfigs,\n } = config;\n\n // Resolve lazy deps — instances are returned as-is, factories are wrapped\n // in a proxy that defers construction until the first property access.\n const pubsub = lazyProxy(deps.pubsub);\n const adapter = lazyProxy(rawAdapter);\n\n // Create triggers (Firestore → PubSub)\n const triggers = createSyncTriggers(repoMapping, {\n deps: { firestoreTriggers: deps.firestoreTriggers, pubsub },\n topicPrefix,\n repos: repoConfigs,\n });\n\n // Create worker (PubSub → SQL)\n const worker = createSyncWorker(repoMapping, {\n deps: { pubsubHandler: deps.pubsubHandler, pubsub },\n adapter,\n batchSize,\n flushIntervalMs,\n autoMigrate,\n topicPrefix,\n workerOptions,\n repos: repoConfigs,\n });\n\n // Auto-create a PubSub handler per repo\n const handlers: Record<string, any> = {};\n for (const repoName of Object.keys(repoMapping)) {\n handlers[`sync_${repoName}`] = worker.createHandler(\n `${topicPrefix}-${repoName}`,\n );\n }\n\n // Optional admin endpoint\n let adminHandler: ((req: any, res: any) => Promise<void>) | null = null;\n if (adminConfig) {\n adminHandler = createadminsyncServer(\n repoMapping,\n adapter,\n worker.queues as Map<string, SyncQueue>,\n worker.handleMessage as (event: SyncEvent) => Promise<void>,\n adminConfig,\n (repoConfigs ?? {}) as Record<string, RepoSyncConfig<string> | undefined>,\n pubsub,\n topicPrefix,\n );\n // If onRequest is provided, wrap it as a Cloud Function automatically.\n // Otherwise expose the raw handler so the user can wrap it.\n handlers[\"adminsync\"] = adminConfig.onRequest\n ? adminConfig.httpsOptions\n ? adminConfig.onRequest(adminConfig.httpsOptions, adminHandler)\n : adminConfig.onRequest(adminHandler)\n : adminHandler;\n }\n\n const result = {\n /** All Cloud Functions (triggers + handlers + optional admin) — spread into exports */\n functions: { ...triggers, ...handlers } as Record<string, any>,\n /**\n * Raw admin HTTP handler — wrap with `onRequest()` yourself if you\n * didn't pass `onRequest` in the admin config.\n * @example\n * ```ts\n * export const adminsync = onRequest(sync.adminHandler!);\n * ```\n */\n adminHandler: adminHandler as\n | ((req: any, res: any) => Promise<void>)\n | null,\n /** Process a SyncEvent directly (for testing) */\n handleMessage: worker.handleMessage as (event: SyncEvent) => Promise<void>,\n /** Internal queue map (for testing) */\n queues: worker.queues as Map<string, SyncQueue>,\n /** Flush all queues and stop timers */\n shutdown: worker.shutdown as () => Promise<void>,\n };\n\n // Hide non-function properties from Firebase's recursive discovery.\n // Only `functions` is enumerable — the rest is accessible but invisible to Object.keys().\n for (const key of [\n \"adminHandler\",\n \"handleMessage\",\n \"queues\",\n \"shutdown\",\n ] as const) {\n Object.defineProperty(result, key, { enumerable: false });\n }\n\n return result;\n}\n","/**\n * HTTP route handlers for the admin ORM server.\n * Each handler corresponds to a URL pattern registered in the router.\n *\n * Routes:\n * GET / → dashboard GET /:repoName → document list (paginated)\n * GET /:repoName/create → create form\n * POST /:repoName/create → submit create\n * GET /:repoName/:id/edit → edit form (pre-filled)\n * POST /:repoName/:id/edit → submit update\n * POST /:repoName/:id/delete → delete document\n */\n\nimport { z } from \"zod\";\nimport type { ConfiguredRepository } from \"../../repositories/types\";\nimport type { RepositoryConfig } from \"../../shared/types\";\nimport {\n getEnumValues,\n getInnerType,\n getLiteralValue,\n getNativeEnumValues,\n getShape,\n getTypeName,\n} from \"../../shared/zod-compat\";\nimport { renderForm, zodToFields, type FieldDescriptor } from \"./form-gen\";\nimport type {\n ColumnMeta,\n FilterState,\n RelationalFieldMeta,\n WhereOp,\n} from \"./renderer\";\nimport { renderDashboard, renderFormPage, renderList, renderPage } from \"./renderer\";\nimport type { AnyReq, AnyRes, RouteParams } from \"./router\";\nimport { isMissingIndexError, toQueryError } from \"./index-url\";\n\n// ---------------------------------------------------------------------------\n// Registry type\n// ---------------------------------------------------------------------------\n\nexport interface AdminRepoEntry {\n name: string;\n path: string;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n repo: ConfiguredRepository<\n RepositoryConfig<any, any, any, any, any, any, any, any, any, any, any>\n >;\n schema: z.ZodObject<any>;\n /** document key field name (default: \"docId\") */\n documentKey?: string;\n /** Field name that stores the full Firestore document path (e.g. \"documentPath\") */\n pathKey?: string;\n /** Whether this repo is a collection group (subcollection) */\n isGroup?: boolean;\n /** Parent key field names needed to build a subcollection document ref (auto-detected from refCb) */\n parentKeys?: string[];\n /** Field name for the creation timestamp (auto-set on create) */\n createdKey?: string;\n /** List of columns to display in the table (defaults to schema keys) */\n listColumns?: string[];\n /** Page size for list view (default: 25) */\n pageSize?: number;\n /** Fields exposed in the filter bar (defaults to all schema keys) */\n filterableFields?: string[];\n /** Fields shown in the edit form (defaults to all schema fields if unset) */\n mutableFields?: string[];\n /** Fields shown in the create form (defaults to all schema fields if unset) */\n createFields?: string[];\n /** Whether delete is allowed (default: false) */\n allowDelete?: boolean;\n /**\n * Fields that link to another repository.\n * Populated automatically from the repo's relationalKeys.\n */\n relationalMeta?: RelationalFieldMeta[];\n}\n\nexport type RepoRegistry = Record<string, AdminRepoEntry>;\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nconst _idChars =\n \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\";\n\n/** Generate a random 20-char alphanumeric ID matching Firestore's native format. */\nfunction generateFirestoreId(): string {\n let id = \"\";\n for (let i = 0; i < 20; i++) {\n id += _idChars.charAt(Math.floor(Math.random() * _idChars.length));\n }\n return id;\n}\n\n/**\n * Extract Firestore document path args from a document's stored path.\n * e.g. \"posts/abc/comments/xyz\" → [\"abc\", \"xyz\"] (the doc-ID segments).\n * Returns `undefined` when no usable path is available.\n */\nfunction extractPathArgs(\n doc: Record<string, unknown>,\n pathKey?: string,\n): string[] | undefined {\n if (!pathKey) return undefined;\n const fullPath = doc[pathKey];\n if (typeof fullPath !== \"string\" || !fullPath) return undefined;\n const segments = fullPath.split(\"/\").filter(Boolean);\n // Doc IDs are at odd indices: col/id/col/id/...\n const args: string[] = [];\n for (let i = 1; i < segments.length; i += 2) {\n args.push(segments[i]!);\n }\n return args.length > 0 ? args : undefined;\n}\n\n/**\n * Fetch a single document by its documentKey, with fallback to query\n * for collection-group repos where direct documentRef may fail.\n */\nasync function fetchDocById(\n entry: AdminRepoEntry,\n docId: string,\n): Promise<Record<string, unknown> | null> {\n const docKey = entry.documentKey ?? \"docId\";\n const getMethod =\n `by${docKey.charAt(0).toUpperCase()}${docKey.slice(1)}` as keyof typeof entry.repo.get;\n\n // Try direct get first\n if (typeof entry.repo.get[getMethod] === \"function\") {\n try {\n const doc = (await (entry.repo.get[getMethod] as Function)(\n docId,\n )) as Record<string, unknown> | null;\n if (doc) return doc;\n } catch {\n // Direct ref may fail for subcollections — fall through to query\n }\n }\n\n // Fallback: query-based lookup (works for collectionGroup)\n const results = await entry.repo.query.by({\n where: [[docKey, \"==\", docId]],\n limit: 1,\n });\n return (results[0] as Record<string, unknown>) ?? null;\n}\n\n/**\n * Build a `flash` payload (with optional \"Create Index\" CTA) from a Firestore\n * error raised while loading a single document. Returns `undefined` if the\n * error is not interesting enough to render as a structured alert.\n */\nfunction flashFromDocFetchError(\n entry: AdminRepoEntry,\n docId: string,\n err: unknown,\n): { type: \"warning\" | \"error\"; message: string; action?: { href: string; label: string; external?: boolean } } {\n const docKey = entry.documentKey ?? \"docId\";\n const qe = toQueryError(err, {\n ref: entry.repo.ref,\n path: entry.path,\n isGroup: !!entry.isGroup,\n filters: [{ field: docKey, op: \"==\", value: docId }],\n });\n if (qe.type === \"index\") {\n return {\n type: \"warning\",\n message:\n \"Loading this document requires a composite index that does not exist yet.\",\n ...(qe.indexUrl\n ? {\n action: {\n href: qe.indexUrl,\n label: \"Create Index →\",\n external: true,\n },\n }\n : {}),\n };\n }\n return {\n type: \"error\",\n message: qe.message,\n };\n}\n\nfunction sendHtml(res: AnyRes, html: string, status = 200): void {\n res.status(status).set(\"Content-Type\", \"text/html; charset=utf-8\").send(html);\n}\n\nfunction redirect(res: AnyRes, to: string): void {\n res.status(302).set(\"Location\", to).send(\"\");\n}\n\n/**\n * Parse a flat form body (from `application/x-www-form-urlencoded`) into a\n * typed object using the Zod schema as guide.\n * Handles: dot-notation nested fields (e.g. address.street), JSON textarea\n * values, booleans (checkbox), numbers.\n */\nfunction parseFormBody(\n raw: Record<string, string | string[] | undefined>,\n schema: z.ZodObject<any>,\n): Record<string, unknown> {\n const shape = schema.shape;\n const result: Record<string, unknown> = {};\n\n for (const [key, zodField] of Object.entries(shape)) {\n const tn = resolveTypeName(zodField as z.ZodType);\n\n // ── ZodObject: prefer dot-notation sub-keys over raw JSON textarea ──────\n if (tn === \"ZodObject\") {\n // Check for explicit null marker first\n if (raw[key + \"__isnull\"] === \"1\") {\n result[key] = null;\n continue;\n }\n const subRaw: Record<string, string | string[] | undefined> = {};\n let hasDotKeys = false;\n for (const [k, v] of Object.entries(raw)) {\n if (k.startsWith(`${key}.`)) {\n subRaw[k.slice(key.length + 1)] = v;\n hasDotKeys = true;\n }\n }\n if (hasDotKeys) {\n // Unwrap to the inner ZodObject schema and recurse\n let innerSchema: z.ZodType = zodField as z.ZodType;\n while (true) {\n const itn = getTypeName(innerSchema);\n if (\n itn === \"ZodOptional\" ||\n itn === \"ZodNullable\" ||\n itn === \"ZodDefault\"\n ) {\n innerSchema = getInnerType(innerSchema)!;\n } else break;\n }\n result[key] = parseFormBody(subRaw, innerSchema as z.ZodObject<any>);\n continue;\n }\n // Fallback: try to JSON-parse the textarea value\n const rawVal = raw[key];\n const strVal = Array.isArray(rawVal) ? rawVal[rawVal.length - 1] : rawVal;\n if (strVal) {\n try {\n result[key] = JSON.parse(strVal);\n } catch {\n result[key] = strVal;\n }\n }\n continue;\n }\n\n // ── All other types ─────────────────────────────────────────────────────\n const rawVal = raw[key];\n const strVal = Array.isArray(rawVal) ? rawVal[rawVal.length - 1] : rawVal;\n // Nullable field explicitly set to null via the toggle\n if (raw[key + \"__isnull\"] === \"1\") {\n result[key] = null;\n continue;\n }\n if (strVal === undefined || strVal === \"\") {\n // Checkbox unchecked → false; everything else → omit\n if (tn === \"ZodBoolean\") result[key] = false;\n continue;\n }\n\n switch (tn) {\n case \"ZodBoolean\":\n if (strVal === \"__null__\") {\n result[key] = null;\n } else {\n result[key] = strVal === \"true\" || strVal === \"on\" || strVal === \"1\";\n }\n break;\n case \"ZodNumber\":\n case \"ZodBigInt\":\n result[key] = Number(strVal);\n break;\n case \"ZodDate\":\n result[key] = new Date(strVal);\n break;\n case \"ZodArray\":\n try {\n result[key] = JSON.parse(strVal);\n } catch {\n result[key] = strVal;\n }\n break;\n default:\n // Try JSON for inline JSON textareas, fall back to string\n if (strVal.startsWith(\"{\") || strVal.startsWith(\"[\")) {\n try {\n result[key] = JSON.parse(strVal);\n break;\n } catch {\n /* fall through */\n }\n }\n result[key] = strVal;\n }\n }\n\n return result;\n}\n\n/**\n * Convert any date-like value to the \"yyyy-MM-ddThh:mm\" string required by\n * `<input type=\"datetime-local\">`.\n * Handles: native Date, Firestore Timestamp ({_seconds, _nanoseconds}),\n * Firestore Timestamp with .toDate(), ISO strings, unix numbers.\n */\nfunction toDatetimeLocal(val: unknown): string | null {\n let date: Date | null = null;\n\n if (val instanceof Date) {\n date = val;\n } else if (\n typeof val === \"object\" &&\n val !== null &&\n typeof (val as any).toDate === \"function\"\n ) {\n // Firestore Timestamp SDK object\n date = (val as any).toDate() as Date;\n } else if (\n typeof val === \"object\" &&\n val !== null &&\n \"_seconds\" in val &&\n \"_nanoseconds\" in val\n ) {\n // Plain serialized Firestore Timestamp { _seconds, _nanoseconds }\n date = new Date(\n (val as any)._seconds * 1000 +\n Math.floor((val as any)._nanoseconds / 1_000_000),\n );\n } else if (typeof val === \"string\" || typeof val === \"number\") {\n const d = new Date(val as string | number);\n if (!isNaN(d.getTime())) date = d;\n }\n\n if (!date || isNaN(date.getTime())) return null;\n\n // Format as local time yyyy-MM-ddThh:mm (what datetime-local expects)\n const pad = (n: number) => String(n).padStart(2, \"0\");\n return (\n `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}` +\n `T${pad(date.getHours())}:${pad(date.getMinutes())}`\n );\n}\n\n/** Resolve the innermost Zod type name (unwrapping Optional/Nullable/Default) */\nfunction resolveTypeName(schema: z.ZodType): string {\n let s: z.ZodType = schema;\n // eslint-disable-next-line no-constant-condition\n while (true) {\n const tn = getTypeName(s);\n if (tn === \"ZodOptional\" || tn === \"ZodNullable\" || tn === \"ZodDefault\") {\n s = getInnerType(s)!;\n } else {\n return tn;\n }\n }\n}\n\n/** Resolve the innermost Zod schema (unwrapping Optional/Nullable/Default) */\nfunction resolveInnerSchema(schema: z.ZodType): z.ZodType {\n let s: z.ZodType = schema;\n // eslint-disable-next-line no-constant-condition\n while (true) {\n const tn = getTypeName(s);\n if (tn === \"ZodOptional\" || tn === \"ZodNullable\" || tn === \"ZodDefault\") {\n s = getInnerType(s)!;\n } else {\n return s;\n }\n }\n}\n\n/** True if the schema is wrapped in ZodOptional or ZodNullable (recursively). */\nfunction isFieldNullable(schema: z.ZodType): boolean {\n let s: z.ZodType = schema;\n // eslint-disable-next-line no-constant-condition\n while (true) {\n const tn = getTypeName(s);\n if (tn === \"ZodOptional\" || tn === \"ZodNullable\") return true;\n if (tn === \"ZodDefault\") {\n s = getInnerType(s)!;\n continue;\n }\n return false;\n }\n}\n\n/** Extract enum values from a (possibly wrapped) ZodEnum / ZodNativeEnum / ZodLiteral. Returns undefined if not an enum. */\nfunction extractEnumValues(schema: z.ZodType): readonly string[] | undefined {\n const inner = resolveInnerSchema(schema);\n const tn = getTypeName(inner);\n if (tn === \"ZodEnum\") {\n const v = getEnumValues(inner);\n return v.length > 0 ? v : undefined;\n }\n if (tn === \"ZodNativeEnum\") {\n const obj = getNativeEnumValues(inner);\n const vals = Object.values(obj).filter(\n (v) => typeof v === \"string\",\n ) as string[];\n return vals.length > 0 ? vals : undefined;\n }\n if (tn === \"ZodLiteral\") {\n const v = getLiteralValue(inner);\n return typeof v === \"string\" ? [v] : undefined;\n }\n return undefined;\n}\n\n/**\n * Prefill a Zod schema fields with existing document values.\n * For ZodObject fields, recurses into nested sub-fields using dot-notation keys\n * so that individual sub-inputs (e.g. address.street) are properly pre-filled.\n */\nfunction prefillFromDoc(\n doc: Record<string, unknown>,\n schema: z.ZodObject<any>,\n prefix = \"\",\n): Record<string, string> {\n const result: Record<string, string> = {};\n for (const key of Object.keys(schema.shape)) {\n const fullKey = prefix ? `${prefix}.${key}` : key;\n const val = doc[key];\n // Sentinel \"__null__\" tells renderField to pre-check the null toggle\n if (val === null) {\n result[fullKey] = \"__null__\";\n continue;\n }\n if (val === undefined) continue;\n\n // Unwrap Optional/Nullable/Default to check inner type\n let innerSchema: z.ZodType = schema.shape[key] as z.ZodType;\n while (true) {\n const itn = getTypeName(innerSchema);\n if (\n itn === \"ZodOptional\" ||\n itn === \"ZodNullable\" ||\n itn === \"ZodDefault\"\n ) {\n innerSchema = getInnerType(innerSchema)!;\n } else break;\n }\n const innerTn = getTypeName(innerSchema);\n\n if (\n innerTn === \"ZodObject\" &&\n typeof val === \"object\" &&\n val !== null &&\n !Array.isArray(val)\n ) {\n // Recursively flatten nested object fields with dot-notation\n const nested = prefillFromDoc(\n val as Record<string, unknown>,\n innerSchema as z.ZodObject<any>,\n fullKey,\n );\n Object.assign(result, nested);\n } else if (innerTn === \"ZodDate\") {\n // Convert Date / Firestore Timestamp → datetime-local string\n const dtLocal = toDatetimeLocal(val);\n if (dtLocal !== null) result[fullKey] = dtLocal;\n } else if (\n typeof val === \"object\" &&\n val !== null &&\n !Array.isArray(val) &&\n (\"_seconds\" in val || typeof (val as any).toDate === \"function\")\n ) {\n // Untyped Timestamp-like value: try datetime-local, fall back to JSON\n const dtLocal = toDatetimeLocal(val);\n result[fullKey] = dtLocal ?? JSON.stringify(val, null, 2);\n } else if (typeof val === \"object\") {\n result[fullKey] = JSON.stringify(val, null, 2);\n } else {\n result[fullKey] = String(val);\n }\n }\n return result;\n}\n\n/**\n * Recursively apply prefilled string values to a tree of FieldDescriptors.\n * Handles dot-notation keys for nested objects (e.g. \"address.street\").\n */\nfunction applyPrefill(\n fields: FieldDescriptor[],\n prefilled: Record<string, string>,\n): FieldDescriptor[] {\n return fields.map((f) => ({\n ...f,\n defaultValue: prefilled[f.name] ?? f.defaultValue,\n nested: f.nested ? applyPrefill(f.nested, prefilled) : undefined,\n }));\n}\n\n// ---------------------------------------------------------------------------\n// Filter helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Extract active filters from URL query params.\n * Params: fv_{field} = value, fo_{field} = operator (default ==)\n */\nfunction parseFilters(\n query: Record<string, string>,\n validFields: Set<string>,\n): FilterState[] {\n const validOps = new Set<string>([\n \"==\",\n \"!=\",\n \"<\",\n \"<=\",\n \">\",\n \">=\",\n \"in\",\n \"not-in\",\n \"array-contains\",\n \"array-contains-any\",\n ]);\n const filters: FilterState[] = [];\n for (const [k, v] of Object.entries(query)) {\n if (!k.startsWith(\"fv_\")) continue;\n const field = k.slice(3);\n if (!validFields.has(field)) continue;\n const value = (v ?? \"\").trim();\n if (!value) continue;\n const opRaw = query[`fo_${field}`] ?? \"==\";\n const op = validOps.has(opRaw) ? (opRaw as WhereOp) : \"==\";\n filters.push({ field, op, value });\n }\n return filters;\n}\n\n/**\n * Convert FilterState[] to the where-clause tuples expected by the query engine.\n * Coerces string values to boolean/number when unambiguous.\n */\nfunction filtersToWhere(filters: FilterState[]): [string, WhereOp, unknown][] {\n const NULL_SENTINEL = \"__null__\";\n const coerce = (v: string): unknown => {\n if (v === NULL_SENTINEL) return null;\n if (v === \"true\") return true;\n if (v === \"false\") return false;\n if (v !== \"\" && !isNaN(Number(v))) return Number(v);\n return v;\n };\n return filters.map((f) => {\n if (f.op === \"array-contains-any\" || f.op === \"in\" || f.op === \"not-in\") {\n // CSV list → array, each element coerced (drop empty / null sentinels —\n // Firestore rejects null inside `in`/`not-in`).\n const arr = f.value\n .split(\",\")\n .map((s) => s.trim())\n .filter((s) => s !== \"\" && s !== NULL_SENTINEL)\n .map((s) => coerce(s));\n return [f.field, f.op, arr];\n }\n return [f.field, f.op, coerce(f.value)];\n });\n}\n\n/** Build ColumnMeta for displayable columns, recursing into ZodObject sub-fields (dot-notation). */\nfunction buildColumnMeta(\n columns: string[],\n schema: z.ZodObject<any>,\n prefix = \"\",\n): ColumnMeta[] {\n const result: ColumnMeta[] = [];\n for (const col of columns) {\n const fullName = prefix ? `${prefix}.${col}` : col;\n const field = schema.shape[col] as z.ZodType | undefined;\n if (!field) {\n result.push({ name: fullName, zodType: \"ZodString\" });\n continue;\n }\n const zodType = resolveTypeName(field);\n if (zodType === \"ZodObject\") {\n // Unwrap wrappers to reach the inner ZodObject\n let inner: z.ZodType = field;\n while (true) {\n const itn = getTypeName(inner);\n if (\n itn === \"ZodOptional\" ||\n itn === \"ZodNullable\" ||\n itn === \"ZodDefault\"\n ) {\n inner = getInnerType(inner)!;\n } else break;\n }\n const subShape = getShape(inner);\n result.push(\n ...buildColumnMeta(\n Object.keys(subShape),\n inner as z.ZodObject<any>,\n fullName,\n ),\n );\n } else {\n result.push({\n name: fullName,\n zodType,\n nullable: isFieldNullable(field),\n enumValues: extractEnumValues(field),\n });\n }\n }\n return result;\n}\n\n// ---------------------------------------------------------------------------\n// Handler factory\n// ---------------------------------------------------------------------------\n\n/**\n * Resolve the ZodType at a dot-notation path (e.g. \"address.city\") within a schema.\n * Returns null if the path cannot be resolved.\n */\nfunction resolveZodAtPath(\n schema: z.ZodObject<any>,\n path: string,\n): z.ZodType | null {\n const parts = path.split(\".\");\n let s: z.ZodType = schema as z.ZodType;\n for (const part of parts) {\n // Unwrap Optional / Nullable / Default wrappers\n while (true) {\n const itn = getTypeName(s);\n if (\n itn === \"ZodOptional\" ||\n itn === \"ZodNullable\" ||\n itn === \"ZodDefault\"\n ) {\n s = getInnerType(s)!;\n } else break;\n }\n const shape = getShape(s);\n if (!(part in shape)) return null;\n s = shape[part]!;\n }\n return s;\n}\n\n/**\n * Returns a Zod schema restricted to `fields` when defined.\n * Supports dot-notation paths (e.g. \"address.city\") by building partial\n * nested sub-schemas — useful for edit/create forms.\n * Falls back to the full schema if fields is undefined/empty.\n */\nfunction getMutableSchema(\n schema: z.ZodObject<any>,\n fields: string[] | undefined,\n): z.ZodObject<any> {\n if (!fields || fields.length === 0) return schema;\n\n const topLevel: string[] = [];\n // parent key → list of sub-field names requested\n const dotGroups = new Map<string, string[]>();\n\n for (const f of fields) {\n const dot = f.indexOf(\".\");\n if (dot === -1) {\n topLevel.push(f);\n } else {\n const parent = f.slice(0, dot);\n const child = f.slice(dot + 1);\n if (!dotGroups.has(parent)) dotGroups.set(parent, []);\n dotGroups.get(parent)!.push(child);\n }\n }\n\n const picked: Record<string, z.ZodType> = {};\n\n // Direct top-level fields\n for (const f of topLevel) {\n if (f in schema.shape) picked[f] = schema.shape[f]!;\n }\n\n // Partial nested objects for dot-notation entries\n for (const [parent, subFields] of dotGroups) {\n if (!(parent in schema.shape)) continue;\n // Unwrap to the inner ZodObject\n let inner: z.ZodType = schema.shape[parent] as z.ZodType;\n while (true) {\n const itn = getTypeName(inner);\n if (\n itn === \"ZodOptional\" ||\n itn === \"ZodNullable\" ||\n itn === \"ZodDefault\"\n ) {\n inner = getInnerType(inner)!;\n } else break;\n }\n if (getTypeName(inner) !== \"ZodObject\") {\n // Not an object — include as-is\n picked[parent] = schema.shape[parent]!;\n continue;\n }\n // Recurse: build a partial sub-schema for the requested sub-fields\n picked[parent] = getMutableSchema(inner as z.ZodObject<any>, subFields);\n }\n\n return z.object(picked);\n}\n/**\n * Compute the link base for all UI links.\n *\n * ── Emulator (FUNCTIONS_EMULATOR=true) ──────────────────────────────────────\n * Firebase emulator exposes functions at:\n * http://localhost:5001/{GCLOUD_PROJECT}/{FUNCTION_REGION}/{FUNCTION_TARGET}/...\n * env vars set by the emulator:\n * GCLOUD_PROJECT / GOOGLE_CLOUD_PROJECT → project id\n * FUNCTION_REGION → region (default: us-central1)\n * FUNCTION_TARGET → function export name (e.g. \"admin\")\n *\n * ── Production ──────────────────────────────────────────────────────────────\n * Firebase proxy strips the prefix before reaching the handler, so links\n * are relative to \"/\" and `staticBasePath` is used as-is.\n */\nfunction getLinkBase(req: AnyReq, staticBasePath: string): string {\n const base = staticBasePath === \"/\" ? \"\" : staticBasePath.replace(/\\/$/, \"\");\n\n if (process.env[\"FUNCTIONS_EMULATOR\"] === \"true\") {\n const project =\n process.env[\"GCLOUD_PROJECT\"] ??\n process.env[\"GOOGLE_CLOUD_PROJECT\"] ??\n \"demo-project\";\n const region = process.env[\"FUNCTION_REGION\"] ?? \"us-central1\";\n // FUNCTION_TARGET uses dots (e.g. \"sync.functions.adminsync\") but the\n // emulator URL uses hyphens (\"sync-functions-adminsync\").\n const target = (process.env[\"FUNCTION_TARGET\"] ?? \"\").replace(/\\./g, \"-\");\n return `/${project}/${region}/${target}${base}`;\n }\n\n // Cloud Functions v2: K_SERVICE = function name = URL path prefix.\n // Only add it when accessed via cloudfunctions.net (not custom domains).\n // Cloud Run (Gen 2) lowercases service names, but K_SERVICE may still\n // carry the original mixed-case export name — normalise to lowercase\n // so that generated links match the canonical URL.\n const service = process.env[\"K_SERVICE\"];\n const host: string =\n (req as any).hostname ?? (req.headers as any)?.[\"host\"] ?? \"\";\n if (service && host.includes(\"cloudfunctions.net\")) {\n return `/${service.toLowerCase()}${base}`;\n }\n\n return base;\n}\n\nexport function createAdminHandlers(registry: RepoRegistry, basePath: string) {\n // ── Dashboard ─────────────────────────────────────────────────────────────\n const handleDashboard = (\n req: AnyReq & { params: RouteParams },\n res: AnyRes,\n ): void => {\n const lb = getLinkBase(req, basePath);\n const repos = Object.values(registry).map((e) => ({\n name: e.name,\n path: e.path,\n }));\n sendHtml(res, renderDashboard(repos, lb));\n };\n\n // ── List documents ────────────────────────────────────────────────────────\n const handleList = async (\n req: AnyReq & { params: RouteParams },\n res: AnyRes,\n ): Promise<void> => {\n const repoName = req.params[\"repoName\"];\n if (!repoName) {\n sendHtml(res, \"Bad request\", 400);\n return;\n }\n const entry = registry[repoName];\n if (!entry) {\n sendHtml(res, \"Repository not found\", 404);\n return;\n }\n\n const pageSize = entry.pageSize ?? 25;\n const query = (req.query ?? {}) as Record<string, string>;\n const cursorStr = query[\"cursor\"];\n const dir = query[\"dir\"] === \"prev\" ? \"prev\" : \"next\";\n\n // Sort\n const sortField = query[\"ob\"] ?? \"\";\n const sortDir = (query[\"od\"] === \"desc\" ? \"desc\" : \"asc\") as \"asc\" | \"desc\";\n const sortState = sortField\n ? { field: sortField, dir: sortDir }\n : undefined;\n\n // Rows per page (query ?ps= overrides config, capped at 200)\n const psRaw = parseInt(query[\"ps\"] ?? \"\");\n const currentPageSize =\n Number.isFinite(psRaw) && psRaw > 0 ? Math.min(psRaw, 200) : pageSize;\n\n const allColumns = entry.listColumns ?? Object.keys(entry.schema.shape);\n const docKey = entry.documentKey ?? \"docId\";\n const columns = [docKey, ...allColumns.filter((c: string) => c !== docKey)];\n // Restrict filterable columns to filterableFields when defined.\n // Dot-notation paths (e.g. \"address.city\") are passed through directly;\n // top-level keys expand to sub-fields via buildColumnMeta as before.\n const filterableColumns: string[] = entry.filterableFields\n ? (() => {\n const out: string[] = [];\n for (const f of entry.filterableFields!) {\n if (f.includes(\".\")) {\n out.push(f); // direct dot-notation path\n } else if (allColumns.includes(f)) {\n out.push(f); // regular top-level key\n }\n }\n return out;\n })()\n : allColumns;\n // For dot-notation entries, resolve the correct ZodType; for top-level\n // keys, delegate to the existing buildColumnMeta (handles ZodObject expansion).\n const columnMeta: import(\"./renderer\").ColumnMeta[] = (() => {\n const out: import(\"./renderer\").ColumnMeta[] = [];\n for (const col of filterableColumns) {\n if (col.includes(\".\")) {\n const resolved = resolveZodAtPath(entry.schema, col);\n out.push({\n name: col,\n zodType: resolved ? resolveTypeName(resolved) : \"ZodString\",\n nullable: resolved ? isFieldNullable(resolved) : false,\n enumValues: resolved ? extractEnumValues(resolved) : undefined,\n });\n } else {\n out.push(...buildColumnMeta([col], entry.schema));\n }\n }\n return out;\n })();\n\n // Parse and validate filters from query params\n // validFields built from columnMeta so dot-notation fields (address.city) are accepted\n const validFields = new Set(columnMeta.map((c) => c.name));\n const activeFilters = parseFilters(query, validFields);\n const whereFilters = filtersToWhere(activeFilters);\n\n // Attempt to rehydrate cursor\n let cursorSnapshot:\n | import(\"firebase-admin/firestore\").DocumentSnapshot\n | undefined;\n if (cursorStr) {\n try {\n const colRef = entry.repo.ref as any;\n if (typeof colRef.doc === \"function\") {\n cursorSnapshot = await colRef.doc(cursorStr).get();\n }\n } catch {\n /* ignore */\n }\n }\n\n const [result, totalCount] = await Promise.all([\n entry.repo.query\n .paginate({\n pageSize: currentPageSize,\n cursor: cursorSnapshot,\n // direction + where + orderBy are supported at runtime but not in the strict typed interface\n ...{ direction: dir },\n ...(whereFilters.length > 0 ? { where: whereFilters } : {}),\n ...(sortState\n ? {\n orderBy: [\n { field: sortState.field as any, direction: sortState.dir },\n ],\n }\n : {}),\n })\n .catch(\n (err: unknown) =>\n ({\n queryError: toQueryError(err, {\n ref: entry.repo.ref,\n path: entry.path,\n isGroup: !!entry.isGroup,\n filters: activeFilters,\n sort: sortState,\n }),\n }) as const,\n ),\n entry.repo.aggregate\n .count(\n (whereFilters.length > 0\n ? { where: whereFilters as any }\n : {}) as any,\n )\n .catch(() => undefined as number | undefined),\n ]);\n\n // Discriminate between success and error results\n const isError = \"queryError\" in result;\n const docs = isError ? [] : (result.data as Record<string, unknown>[]);\n const nextCursorId = isError ? \"\" : (result.nextCursor?.id ?? \"\");\n const prevCursorId = isError ? \"\" : (result.prevCursor?.id ?? \"\");\n const queryError = isError ? result.queryError : undefined;\n const lb = getLinkBase(req, basePath);\n\n sendHtml(\n res,\n renderList(\n entry.name,\n docs,\n columns,\n lb,\n {\n hasPrev: isError ? false : result.hasPrevPage,\n hasNext: isError ? false : result.hasNextPage,\n prevCursor: prevCursorId,\n nextCursor: nextCursorId,\n },\n undefined,\n columnMeta,\n activeFilters,\n entry.allowDelete ?? false,\n entry.relationalMeta,\n sortState,\n currentPageSize,\n queryError,\n entry.isGroup,\n totalCount,\n entry.mutableFields,\n entry.schema,\n ),\n );\n };\n\n // ── Create form ───────────────────────────────────────────────────────────\n const handleCreateForm = (\n req: AnyReq & { params: RouteParams },\n res: AnyRes,\n ): void => {\n const repoName = req.params[\"repoName\"];\n if (!repoName) {\n sendHtml(res, \"Bad request\", 400);\n return;\n }\n const entry = registry[repoName];\n if (!entry) {\n sendHtml(res, \"Repository not found\", 404);\n return;\n }\n\n const lb = getLinkBase(req, basePath);\n const createSchema = getMutableSchema(entry.schema, entry.createFields);\n const fields = zodToFields(createSchema);\n const actionUrl = `${lb}/${entry.name}/create`;\n const formHtml = renderForm(fields, actionUrl, \"POST\", \"Create document\");\n\n sendHtml(res, renderFormPage(entry.name, formHtml, \"create\", null, lb));\n };\n\n // ── Create submit ─────────────────────────────────────────────────────────\n const handleCreateSubmit = async (\n req: AnyReq & { params: RouteParams },\n res: AnyRes,\n ): Promise<void> => {\n const repoName = req.params[\"repoName\"];\n if (!repoName) {\n sendHtml(res, \"Bad request\", 400);\n return;\n }\n const entry = registry[repoName];\n if (!entry) {\n sendHtml(res, \"Repository not found\", 404);\n return;\n }\n\n const lb = getLinkBase(req, basePath);\n const rawBody =\n (req.body as Record<string, string | string[] | undefined>) ?? {};\n const parsed = parseFormBody(rawBody, entry.schema);\n const createSchema = getMutableSchema(entry.schema, entry.createFields);\n const validation = createSchema.safeParse(parsed);\n\n if (!validation.success) {\n const fields = zodToFields(createSchema);\n const actionUrl = `${lb}/${entry.name}/create`;\n const formHtml = renderForm(fields, actionUrl, \"POST\", \"Create document\");\n const errorMsg = validation.error.issues\n .map((e) => `${e.path.join(\".\")}: ${e.message}`)\n .join(\", \");\n sendHtml(\n res,\n renderFormPage(entry.name, formHtml, \"create\", null, lb, {\n type: \"error\",\n message: `Validation error: ${errorMsg}`,\n }),\n 422,\n );\n return;\n }\n\n try {\n if (entry.isGroup && entry.parentKeys && entry.parentKeys.length > 0) {\n // Collection-group repos cannot use create(); use set() with parent path args.\n const data: Record<string, any> = { ...validation.data };\n // set() doesn't auto-set createdKey, so inject it here\n if (entry.createdKey) {\n data[entry.createdKey] = new Date();\n }\n const missingKeys = entry.parentKeys.filter((k) => !data[k]);\n if (missingKeys.length > 0) {\n throw new Error(\n `Missing parent key(s) for subcollection create: ${missingKeys.join(\", \")}`,\n );\n }\n const parentIds = entry.parentKeys.map((k) => data[k] as string);\n const docKey = entry.documentKey ?? \"docId\";\n const docId = data[docKey] || generateFirestoreId();\n await entry.repo.set(...parentIds, docId, data);\n } else {\n await entry.repo.create(validation.data);\n }\n redirect(res, `${lb}/${entry.name}?flash=created`);\n } catch (err) {\n const createSchema2 = getMutableSchema(entry.schema, entry.createFields);\n const fields = zodToFields(createSchema2);\n const actionUrl = `${lb}/${entry.name}/create`;\n const formHtml = renderForm(fields, actionUrl, \"POST\", \"Create document\");\n sendHtml(\n res,\n renderFormPage(entry.name, formHtml, \"create\", null, lb, {\n type: \"error\",\n message: `Save error: ${(err as Error).message}`,\n }),\n 500,\n );\n }\n };\n\n // ── Edit form ─────────────────────────────────────────────────────────────\n const handleEditForm = async (\n req: AnyReq & { params: RouteParams },\n res: AnyRes,\n ): Promise<void> => {\n const repoName = req.params[\"repoName\"];\n const docId = req.params[\"id\"];\n if (!repoName || !docId) {\n sendHtml(res, \"Bad request\", 400);\n return;\n }\n const entry = registry[repoName];\n if (!entry) {\n sendHtml(res, \"Repository not found\", 404);\n return;\n }\n\n const lb = getLinkBase(req, basePath);\n\n let doc: Record<string, unknown> | null = null;\n try {\n doc = await fetchDocById(entry, docId);\n } catch (err) {\n const flash = flashFromDocFetchError(entry, docId, err);\n const status = isMissingIndexError(err) ? 424 : 500;\n sendHtml(\n res,\n renderPage(\"\", {\n title: `Edit ${entry.name} / ${docId}`,\n basePath: lb,\n breadcrumb: [\n { label: \"Repositories\", href: lb },\n { label: entry.name, href: `${lb}/${entry.name}` },\n { label: `Edit ${docId}` },\n ],\n flash,\n }),\n status,\n );\n return;\n }\n\n if (!doc) {\n sendHtml(res, \"Document not found\", 404);\n return;\n }\n\n const prefilled = prefillFromDoc(doc, entry.schema);\n const mutableSchema = getMutableSchema(entry.schema, entry.mutableFields);\n const fields = applyPrefill(zodToFields(mutableSchema), prefilled);\n\n const actionUrl = `${lb}/${entry.name}/${encodeURIComponent(docId)}/edit`;\n const formHtml = renderForm(fields, actionUrl, \"POST\", \"Save changes\");\n\n sendHtml(res, renderFormPage(entry.name, formHtml, \"edit\", docId, lb));\n };\n\n // ── Edit submit ───────────────────────────────────────────────────────────\n const handleEditSubmit = async (\n req: AnyReq & { params: RouteParams },\n res: AnyRes,\n ): Promise<void> => {\n const repoName = req.params[\"repoName\"];\n const docId = req.params[\"id\"];\n if (!repoName || !docId) {\n sendHtml(res, \"Bad request\", 400);\n return;\n }\n const entry = registry[repoName];\n if (!entry) {\n sendHtml(res, \"Repository not found\", 404);\n return;\n }\n const lb = getLinkBase(req, basePath);\n const rawBody =\n (req.body as Record<string, string | string[] | undefined>) ?? {};\n const parsed = parseFormBody(rawBody, entry.schema);\n\n // Partial validation for updates (restricted to mutableFields)\n const mutableSchema = getMutableSchema(entry.schema, entry.mutableFields);\n const partialSchema = mutableSchema.partial();\n const validation = partialSchema.safeParse(parsed);\n\n if (!validation.success) {\n const prefilled = Object.fromEntries(\n Object.entries(rawBody).map(([k, v]) => [\n k,\n Array.isArray(v) ? v.join(\",\") : (v ?? \"\"),\n ]),\n );\n const fields = applyPrefill(zodToFields(mutableSchema), prefilled);\n const actionUrl = `${lb}/${entry.name}/${encodeURIComponent(docId)}/edit`;\n const formHtml = renderForm(fields, actionUrl, \"POST\", \"Save changes\");\n const errorMsg = validation.error.issues\n .map((e) => `${e.path.join(\".\")}: ${e.message}`)\n .join(\", \");\n sendHtml(\n res,\n renderFormPage(entry.name, formHtml, \"edit\", docId, lb, {\n type: \"error\",\n message: `Validation error: ${errorMsg}`,\n }),\n 422,\n );\n return;\n }\n\n try {\n // Fetch document to extract path args for subcollection repos\n const doc = await fetchDocById(entry, docId);\n const pathArgs = (doc && extractPathArgs(doc, entry.pathKey)) ?? [docId];\n await entry.repo.update(...pathArgs, validation.data);\n redirect(res, `${lb}/${entry.name}?flash=updated`);\n } catch (err) {\n const mutableSchema2 = getMutableSchema(\n entry.schema,\n entry.mutableFields,\n );\n const fields = zodToFields(mutableSchema2);\n const actionUrl = `${lb}/${entry.name}/${encodeURIComponent(docId)}/edit`;\n const formHtml = renderForm(fields, actionUrl, \"POST\", \"Save changes\");\n const flash = isMissingIndexError(err)\n ? flashFromDocFetchError(entry, docId, err)\n : { type: \"error\" as const, message: `Save error: ${(err as Error).message}` };\n const status = isMissingIndexError(err) ? 424 : 500;\n sendHtml(\n res,\n renderFormPage(entry.name, formHtml, \"edit\", docId, lb, flash),\n status,\n );\n }\n };\n\n // ── Delete ────────────────────────────────────────────────────────────────\n const handleDelete = async (\n req: AnyReq & { params: RouteParams },\n res: AnyRes,\n ): Promise<void> => {\n const repoName = req.params[\"repoName\"];\n const docId = req.params[\"id\"];\n if (!repoName || !docId) {\n sendHtml(res, \"Bad request\", 400);\n return;\n }\n const entry = registry[repoName];\n if (!entry) {\n sendHtml(res, \"Repository not found\", 404);\n return;\n }\n if (!entry.allowDelete) {\n sendHtml(res, \"Delete is not allowed for this repository\", 403);\n return;\n }\n const lb = getLinkBase(req, basePath);\n try {\n // Fetch document to extract path args for subcollection repos\n const doc = await fetchDocById(entry, docId);\n const pathArgs = (doc && extractPathArgs(doc, entry.pathKey)) ?? [docId];\n await entry.repo.delete(...pathArgs);\n redirect(res, `${lb}/${entry.name}?flash=deleted`);\n } catch (err) {\n const flash = isMissingIndexError(err)\n ? flashFromDocFetchError(entry, docId, err)\n : { type: \"error\" as const, message: `Delete error: ${(err as Error).message}` };\n const status = isMissingIndexError(err) ? 424 : 500;\n sendHtml(\n res,\n renderPage(\"\", {\n title: `Delete ${entry.name} / ${docId}`,\n basePath: lb,\n breadcrumb: [\n { label: \"Repositories\", href: lb },\n { label: entry.name, href: `${lb}/${entry.name}` },\n { label: `Delete ${docId}` },\n ],\n flash,\n }),\n status,\n );\n }\n };\n\n // ── Relation right-panel preview (HTML fragment, no shell) ───────────────\n const handlePanel = async (\n req: AnyReq & { params: RouteParams },\n res: AnyRes,\n ): Promise<void> => {\n const repoName = req.params[\"repoName\"];\n if (!repoName) {\n sendHtml(res, \"Bad request\", 400);\n return;\n }\n const entry = registry[repoName];\n if (!entry) {\n sendHtml(res, \"Repository not found\", 404);\n return;\n }\n const lb = getLinkBase(req, basePath);\n const query = (req as any).query as Record<string, string> | undefined;\n const type = query?.[\"type\"] === \"many\" ? \"many\" : \"one\";\n const ps = Math.max(1, Math.min(100, Number(query?.[\"ps\"] ?? 25) || 25));\n const allColumns = entry.listColumns ?? Object.keys(getShape(entry.schema));\n\n // Lazy import the panel components — they're only used by this route.\n const { PanelOne, PanelMany } = await import(\"./components/right-panel\");\n const { renderToString } = await import(\"hono/jsx/dom/server\");\n\n if (type === \"one\") {\n const id = String(query?.[\"id\"] ?? \"\");\n if (!id) {\n sendHtml(res, \"<div class='p-6 text-error'>Missing id parameter.</div>\", 400);\n return;\n }\n try {\n const doc = await fetchDocById(entry, id);\n const html = renderToString(\n PanelOne({\n doc,\n repoName: entry.name,\n basePath: lb,\n schema: entry.schema,\n columns: allColumns,\n }) as any,\n );\n sendHtml(res, html);\n } catch (err) {\n sendHtml(\n res,\n `<div class='p-6 text-error text-sm'>Error: ${(err as Error).message}</div>`,\n 500,\n );\n }\n return;\n }\n\n // many\n const fk = String(query?.[\"fk\"] ?? \"\");\n const fv = String(query?.[\"fv\"] ?? \"\");\n if (!fk || !fv) {\n sendHtml(res, \"<div class='p-6 text-error'>Missing fk/fv parameters.</div>\", 400);\n return;\n }\n const cursorStr = query?.[\"cursor\"] ?? \"\";\n const dir = query?.[\"dir\"] === \"prev\" ? \"prev\" : \"next\";\n let cursorSnapshot:\n | import(\"firebase-admin/firestore\").DocumentSnapshot\n | undefined;\n if (cursorStr) {\n try {\n const colRef = entry.repo.ref as any;\n if (typeof colRef.doc === \"function\") {\n cursorSnapshot = await colRef.doc(cursorStr).get();\n }\n } catch {\n /* ignore */\n }\n }\n try {\n const result = await entry.repo.query.paginate({\n pageSize: ps,\n cursor: cursorSnapshot,\n ...{ direction: dir },\n ...{ where: [[fk, \"==\", coerceFilterValue(fv)]] },\n } as any);\n const html = renderToString(\n PanelMany({\n docs: result.data as Record<string, unknown>[],\n repoName: entry.name,\n basePath: lb,\n fk,\n fv,\n columns: allColumns,\n schema: entry.schema,\n pagination: {\n hasPrev: result.hasPrevPage,\n hasNext: result.hasNextPage,\n prevCursor: result.prevCursor?.id ?? \"\",\n nextCursor: result.nextCursor?.id ?? \"\",\n pageSize: ps,\n },\n }) as any,\n );\n sendHtml(res, html);\n } catch (err) {\n sendHtml(\n res,\n `<div class='p-6 text-error text-sm'>Error: ${(err as Error).message}</div>`,\n 500,\n );\n }\n };\n\n // ── Bulk operations ──────────────────────────────────────────────────────\n /** Build DocumentReferences for a list of docIds, handling subcollections via fetchDocById. */\n const resolveRefs = async (\n entry: AdminRepoEntry,\n ids: string[],\n ): Promise<import(\"firebase-admin/firestore\").DocumentReference[]> => {\n const refs: import(\"firebase-admin/firestore\").DocumentReference[] = [];\n for (const id of ids) {\n let pathArgs: string[] | undefined;\n if (entry.isGroup || entry.parentKeys?.length) {\n const doc = await fetchDocById(entry, id);\n pathArgs = doc ? extractPathArgs(doc, entry.pathKey) : undefined;\n }\n if (!pathArgs) pathArgs = [id];\n try {\n const ref = (entry.repo as any).documentRef(...pathArgs);\n if (ref) refs.push(ref);\n } catch {\n /* ignore */\n }\n }\n return refs;\n };\n\n /** Resolve all docIds matching a set of filters by streaming the query in pages. */\n const resolveAllIds = async (\n entry: AdminRepoEntry,\n filters: FilterState[],\n ): Promise<string[]> => {\n const where = filtersToWhere(filters);\n const docKey = entry.documentKey ?? \"docId\";\n const ids: string[] = [];\n let cursor: import(\"firebase-admin/firestore\").DocumentSnapshot | undefined;\n // Stream in pages of 500\n // eslint-disable-next-line no-constant-condition\n while (true) {\n const page: any = await entry.repo.query.paginate({\n pageSize: 500,\n cursor,\n ...{ direction: \"next\" },\n ...(where.length > 0 ? { where } : {}),\n } as any);\n for (const d of page.data as Record<string, unknown>[]) {\n const id = String(d[docKey] ?? d[\"id\"] ?? \"\");\n if (id) ids.push(id);\n }\n if (!page.hasNextPage || !page.nextCursor) break;\n cursor = page.nextCursor;\n }\n return ids;\n };\n\n const handleBulkDelete = async (\n req: AnyReq & { params: RouteParams },\n res: AnyRes,\n ): Promise<void> => {\n const repoName = req.params[\"repoName\"];\n if (!repoName) {\n sendJson(res, { error: \"Bad request\" }, 400);\n return;\n }\n const entry = registry[repoName];\n if (!entry) {\n sendJson(res, { error: \"Repository not found\" }, 404);\n return;\n }\n if (!entry.allowDelete) {\n sendJson(res, { error: \"Delete is not allowed for this repository\" }, 403);\n return;\n }\n const body = ((req as any).body ?? {}) as {\n ids?: unknown;\n selectAll?: unknown;\n filters?: unknown;\n };\n try {\n const ids = await collectTargetIds(entry, body);\n if (ids.length === 0) {\n sendJson(res, { deleted: 0 });\n return;\n }\n const refs = await resolveRefs(entry, ids);\n // Chunk to 500 per Firestore batched-write limit\n for (let i = 0; i < refs.length; i += 500) {\n await entry.repo.bulk.delete(refs.slice(i, i + 500));\n }\n sendJson(res, { deleted: refs.length });\n } catch (err) {\n sendJson(res, { error: (err as Error).message }, 500);\n }\n };\n\n const handleBulkUpdate = async (\n req: AnyReq & { params: RouteParams },\n res: AnyRes,\n ): Promise<void> => {\n const repoName = req.params[\"repoName\"];\n if (!repoName) {\n sendJson(res, { error: \"Bad request\" }, 400);\n return;\n }\n const entry = registry[repoName];\n if (!entry) {\n sendJson(res, { error: \"Repository not found\" }, 404);\n return;\n }\n const body = ((req as any).body ?? {}) as {\n ids?: unknown;\n selectAll?: unknown;\n filters?: unknown;\n field?: unknown;\n value?: unknown;\n };\n const field = String(body.field ?? \"\");\n if (!field) {\n sendJson(res, { error: \"Missing 'field'\" }, 400);\n return;\n }\n // SECURITY: Strict allow-list of fields\n if (!entry.mutableFields || !entry.mutableFields.includes(field)) {\n sendJson(res, { error: `Field '${field}' is not bulk-updatable` }, 403);\n return;\n }\n // Parse value through the field's Zod schema for validation/coercion\n const fieldSchema = (entry.schema as any).shape?.[field] as\n | z.ZodType\n | undefined;\n let parsedValue: unknown = body.value;\n if (fieldSchema) {\n const parsed = fieldSchema.safeParse(body.value);\n if (!parsed.success) {\n sendJson(\n res,\n { error: `Invalid value for '${field}': ${parsed.error.message}` },\n 400,\n );\n return;\n }\n parsedValue = parsed.data;\n }\n try {\n const ids = await collectTargetIds(entry, body);\n if (ids.length === 0) {\n sendJson(res, { updated: 0 });\n return;\n }\n const refs = await resolveRefs(entry, ids);\n const items = refs.map((docRef) => ({\n docRef,\n data: { [field]: parsedValue } as any,\n }));\n for (let i = 0; i < items.length; i += 500) {\n await entry.repo.bulk.update(items.slice(i, i + 500));\n }\n sendJson(res, { updated: items.length });\n } catch (err) {\n sendJson(res, { error: (err as Error).message }, 500);\n }\n };\n\n /** Shared logic: extract target IDs from a request body (`ids[]` OR `selectAll + filters`). */\n async function collectTargetIds(\n entry: AdminRepoEntry,\n body: { ids?: unknown; selectAll?: unknown; filters?: unknown },\n ): Promise<string[]> {\n if (body.selectAll) {\n const filters = sanitizeFilters(body.filters, entry);\n return await resolveAllIds(entry, filters);\n }\n if (Array.isArray(body.ids)) {\n return body.ids.filter((x): x is string => typeof x === \"string\" && !!x);\n }\n return [];\n }\n\n function sanitizeFilters(\n raw: unknown,\n entry: AdminRepoEntry,\n ): FilterState[] {\n if (!Array.isArray(raw)) return [];\n const validFields = new Set(\n (entry.filterableFields ?? Object.keys(getShape(entry.schema))).map((s) =>\n String(s),\n ),\n );\n const validOps = new Set([\n \"==\",\n \"!=\",\n \"<\",\n \"<=\",\n \">\",\n \">=\",\n \"in\",\n \"not-in\",\n \"array-contains\",\n \"array-contains-any\",\n ]);\n const out: FilterState[] = [];\n for (const f of raw) {\n if (\n f &&\n typeof f === \"object\" &&\n typeof (f as any).field === \"string\" &&\n validFields.has((f as any).field) &&\n typeof (f as any).value === \"string\" &&\n validOps.has(String((f as any).op))\n ) {\n out.push({\n field: (f as any).field,\n op: (f as any).op,\n value: (f as any).value,\n });\n }\n }\n return out;\n }\n\n return {\n handleDashboard,\n handleList,\n handleCreateForm,\n handleCreateSubmit,\n handleEditForm,\n handleEditSubmit,\n handleDelete,\n handlePanel,\n handleBulkDelete,\n handleBulkUpdate,\n };\n}\n\nfunction sendJson(res: AnyRes, payload: unknown, status = 200): void {\n res\n .status(status)\n .set(\"Content-Type\", \"application/json; charset=utf-8\")\n .send(JSON.stringify(payload));\n}\n\n/** Coerce a string filter value to the most likely runtime type for a Firestore where clause. */\nfunction coerceFilterValue(v: string): unknown {\n if (v === \"true\") return true;\n if (v === \"false\") return false;\n if (v !== \"\" && !isNaN(Number(v))) return Number(v);\n return v;\n}\n","/**\n * Zod-to-HTML form generator.\n * Inspects a Zod schema's `_def` to produce typed HTML `<input>` / `<select>`\n * elements — no extra dependencies needed.\n *\n * Supported Zod types:\n * ZodString, ZodNumber, ZodBoolean, ZodDate, ZodEnum,\n * ZodOptional, ZodNullable, ZodDefault, ZodObject, ZodArray, ZodLiteral\n *\n * For ZodObject fields, nested sections are rendered with indentation.\n * For ZodArray and unknown types, a `<textarea>` with JSON hint is used.\n *\n * @example\n * ```typescript\n * import { zodToFields, renderForm } from \"@lpdjs/firestore-repo-service/servers/admin\";\n *\n * // Convert Zod schema to field descriptors\n * const schema = z.object({\n * name: z.string(),\n * email: z.string().email(),\n * age: z.number().optional(),\n * role: z.enum([\"admin\", \"user\"]),\n * isActive: z.boolean().default(true),\n * address: z.object({\n * street: z.string(),\n * city: z.string(),\n * }),\n * });\n *\n * const fields = zodToFields(schema);\n * // Returns:\n * // [\n * // { name: \"name\", type: \"text\", required: true, ... },\n * // { name: \"email\", type: \"text\", required: true, hint: \"email\", ... },\n * // { name: \"age\", type: \"number\", required: false, ... },\n * // { name: \"role\", type: \"select\", options: [\"admin\", \"user\"], ... },\n * // { name: \"isActive\", type: \"checkbox\", defaultValue: true, ... },\n * // { name: \"address\", nested: [...], ... },\n * // ]\n *\n * // Render form HTML\n * const html = renderForm(fields, \"create\", {\n * name: \"John\",\n * email: \"john@example.com\",\n * });\n *\n * // Render single field\n * const fieldHtml = renderField(fields[0], { name: \"Jane\" });\n * ```\n */\n\nimport type { z } from \"zod\";\nimport {\n getArrayElementType,\n getDefaultValue,\n getEnumValues,\n getInnerType,\n getLiteralValue,\n getNativeEnumValues,\n getShape,\n getStringChecks,\n getTypeName,\n} from \"../../shared/zod-compat\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface FieldDescriptor {\n name: string;\n label: string;\n type:\n | \"text\"\n | \"number\"\n | \"checkbox\"\n | \"datetime-local\"\n | \"select\"\n | \"textarea\";\n required: boolean;\n nullable: boolean;\n options?: string[]; // for select\n defaultValue?: unknown;\n nested?: FieldDescriptor[]; // for objects\n hint?: string;\n /** For array fields: the element input type */\n arrayElementType?:\n | \"text\"\n | \"number\"\n | \"checkbox\"\n | \"select\"\n | \"datetime-local\"\n | \"object\";\n /** For enum arrays: the allowed values */\n arrayElementOptions?: string[];\n /** For object arrays: the field descriptors for one element */\n arrayElementFields?: FieldDescriptor[];\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/** Convert camelCase / snake_case to \"Human Label\" */\nfunction toLabel(name: string): string {\n return name\n .replace(/([A-Z])/g, \" $1\")\n .replace(/_/g, \" \")\n .replace(/^\\s/, \"\")\n .replace(/^./, (c) => c.toUpperCase());\n}\n\n/** Unwrap ZodOptional / ZodNullable / ZodDefault to the inner schema */\nfunction unwrap(schema: z.ZodType): {\n inner: z.ZodType;\n required: boolean;\n nullable: boolean;\n defaultValue: unknown;\n} {\n let inner: z.ZodType = schema;\n let required = true;\n let nullable = false;\n let defaultValue: unknown = undefined;\n\n // eslint-disable-next-line no-constant-condition\n while (true) {\n const tn = getTypeName(inner);\n if (tn === \"ZodOptional\") {\n required = false;\n inner = getInnerType(inner)!;\n } else if (tn === \"ZodNullable\") {\n required = false;\n nullable = true;\n inner = getInnerType(inner)!;\n } else if (tn === \"ZodDefault\") {\n required = false;\n defaultValue = getDefaultValue(inner);\n inner = getInnerType(inner)!;\n } else {\n break;\n }\n }\n\n return { inner, required, nullable, defaultValue };\n}\n\n// ---------------------------------------------------------------------------\n// Core introspection\n// ---------------------------------------------------------------------------\n\nexport function zodToFields(\n schema: z.ZodType,\n namePrefix = \"\",\n): FieldDescriptor[] {\n const tn = getTypeName(schema);\n\n if (tn === \"ZodObject\") {\n const shape: Record<string, z.ZodType> = getShape(schema);\n return Object.entries(shape).map(([fieldName, fieldSchema]) =>\n zodFieldToDescriptor(\n namePrefix ? `${namePrefix}.${fieldName}` : fieldName,\n fieldName,\n fieldSchema,\n ),\n );\n }\n\n // If the root schema is not an object, treat it as a single field\n return [\n zodFieldToDescriptor(namePrefix || \"value\", namePrefix || \"value\", schema),\n ];\n}\n\nfunction zodFieldToDescriptor(\n name: string,\n rawName: string,\n schema: z.ZodType,\n): FieldDescriptor {\n const { inner, required, nullable, defaultValue } = unwrap(schema);\n const tn = getTypeName(inner);\n const label = toLabel(rawName.split(\".\").pop() ?? rawName);\n\n switch (tn) {\n case \"ZodString\": {\n const checks = getStringChecks(inner);\n const isEmail = checks.includes(\"email\");\n const isUrl = checks.includes(\"url\");\n return {\n name,\n label,\n type: \"text\",\n required,\n nullable,\n defaultValue,\n hint: isEmail ? \"email\" : isUrl ? \"url\" : undefined,\n };\n }\n\n case \"ZodNumber\":\n case \"ZodBigInt\":\n return { name, label, type: \"number\", required, nullable, defaultValue };\n\n case \"ZodBoolean\":\n return {\n name,\n label,\n type: \"checkbox\",\n required,\n nullable,\n defaultValue,\n };\n\n case \"ZodDate\":\n case \"ZodCoerce\":\n return {\n name,\n label,\n type: \"datetime-local\",\n required,\n nullable,\n defaultValue,\n };\n\n case \"ZodEnum\": {\n const values = getEnumValues(inner);\n return {\n name,\n label,\n type: \"select\",\n required,\n nullable,\n defaultValue,\n options: values,\n };\n }\n\n case \"ZodNativeEnum\": {\n const enumObj = getNativeEnumValues(inner);\n const values = Object.values(enumObj).filter(\n (v) => typeof v === \"string\",\n ) as string[];\n return {\n name,\n label,\n type: \"select\",\n required,\n nullable,\n defaultValue,\n options: values,\n };\n }\n\n case \"ZodLiteral\": {\n const value = String(getLiteralValue(inner) ?? \"\");\n return {\n name,\n label,\n type: \"select\",\n required,\n nullable,\n defaultValue,\n options: [value],\n };\n }\n\n case \"ZodObject\": {\n const nested = zodToFields(inner, name);\n return {\n name,\n label,\n type: \"textarea\",\n required,\n nullable,\n defaultValue,\n nested,\n hint: \"JSON object\",\n };\n }\n\n case \"ZodArray\": {\n const elSchema = getArrayElementType(inner);\n if (!elSchema) {\n return {\n name,\n label,\n type: \"textarea\",\n required,\n nullable,\n defaultValue,\n hint: \"JSON array\",\n };\n }\n const { inner: elInner } = unwrap(elSchema);\n const elTn = getTypeName(elInner);\n\n let arrayElementType: FieldDescriptor[\"arrayElementType\"];\n let arrayElementOptions: string[] | undefined;\n let arrayElementFields: FieldDescriptor[] | undefined;\n\n switch (elTn) {\n case \"ZodString\":\n arrayElementType = \"text\";\n break;\n case \"ZodNumber\":\n case \"ZodBigInt\":\n arrayElementType = \"number\";\n break;\n case \"ZodBoolean\":\n arrayElementType = \"checkbox\";\n break;\n case \"ZodDate\":\n arrayElementType = \"datetime-local\";\n break;\n case \"ZodEnum\":\n arrayElementType = \"select\";\n arrayElementOptions = getEnumValues(elInner);\n break;\n case \"ZodNativeEnum\":\n arrayElementType = \"select\";\n arrayElementOptions = Object.values(\n getNativeEnumValues(elInner),\n ).filter((v) => typeof v === \"string\") as string[];\n break;\n case \"ZodObject\":\n arrayElementType = \"object\";\n arrayElementFields = zodToFields(elInner);\n break;\n default:\n // Unknown element type → JSON textarea fallback\n return {\n name,\n label,\n type: \"textarea\",\n required,\n nullable,\n defaultValue,\n hint: \"JSON array\",\n };\n }\n\n return {\n name,\n label,\n type: \"textarea\",\n required,\n nullable,\n defaultValue,\n arrayElementType,\n arrayElementOptions,\n arrayElementFields,\n };\n }\n\n default:\n return {\n name,\n label,\n type: \"textarea\",\n required,\n nullable,\n defaultValue,\n hint: \"JSON\",\n };\n }\n}\n\n// ---------------------------------------------------------------------------\n// HTML generation — DaisyUI + Tailwind classes\n// ---------------------------------------------------------------------------\n\nexport function renderField(field: FieldDescriptor, depth = 0): string {\n const indent = depth > 0 ? `ml-${depth * 4}` : \"\";\n const id = `field_${field.name.replace(/\\./g, \"__\")}`;\n const nameAttr = field.name;\n const requiredAttr = field.required ? \" required\" : \"\";\n // \"__null__\" is the sentinel value used when a nullable field is set to null\n const isNullValue = field.defaultValue === \"__null__\";\n const defaultStr =\n !isNullValue && field.defaultValue != null\n ? String(field.defaultValue)\n : \"\";\n\n // Null toggle — rendered inline to the right of the input for nullable non-checkbox fields\n const nullToggle =\n field.nullable && field.type !== \"checkbox\"\n ? `<span class=\"flex items-center gap-1 shrink-0\">\n <input type=\"hidden\" id=\"${id}__isnull\" name=\"${nameAttr}__isnull\" value=\"${isNullValue ? \"1\" : \"\"}\">\n <label class=\"flex items-center gap-1 cursor-pointer select-none text-xs text-base-content/40 hover:text-base-content/70 border border-base-300 rounded px-2 py-1\">\n <input type=\"checkbox\" class=\"checkbox checkbox-xs\" ${isNullValue ? \"checked\" : \"\"}\n onchange=\"(function(cb){\n var inp = document.getElementById('${id}');\n var h = document.getElementById('${id}__isnull');\n if (cb.checked) { inp.disabled=true; inp.style.opacity='0.35'; h.value='1'; }\n else { inp.disabled=false; inp.style.opacity=''; h.value=''; }\n })(this)\">\n <span>null</span>\n </label>\n </span>`\n : \"\";\n\n let input: string;\n\n switch (field.type) {\n case \"checkbox\":\n // Nullable boolean → 3-state select (null / true / false)\n if (field.nullable) {\n const sel3 = isNullValue\n ? \"__null__\"\n : defaultStr === \"true\"\n ? \"true\"\n : defaultStr === \"false\"\n ? \"false\"\n : \"__null__\";\n return `\n <div class=\"form-control mb-3 ${indent}\">\n <label for=\"${id}\" class=\"label pb-1\">\n <span class=\"label-text font-medium\">\n ${e(field.label)}\n <span class=\"text-base-content/40 text-xs ml-1\">(nullable)</span>\n </span>\n </label>\n <select id=\"${id}\" name=\"${nameAttr}\" class=\"select select-bordered select-sm w-full\">\n <option value=\"__null__\"${sel3 === \"__null__\" ? \" selected\" : \"\"}>— null —</option>\n <option value=\"true\"${sel3 === \"true\" ? \" selected\" : \"\"}>✓ true</option>\n <option value=\"false\"${sel3 === \"false\" ? \" selected\" : \"\"}>✗ false</option>\n </select>\n </div>`;\n }\n return `\n <div class=\"form-control ${indent}\">\n <label class=\"label cursor-pointer justify-start gap-3\">\n <input type=\"checkbox\" id=\"${id}\" name=\"${nameAttr}\" value=\"true\"${\n defaultStr === \"true\" ? \" checked\" : \"\"\n } class=\"checkbox checkbox-primary checkbox-sm\">\n <span class=\"label-text font-medium\">\n ${e(field.label)}${field.required ? ` <span class=\"text-error\">*</span>` : \"\"}\n </span>\n </label>\n </div>`;\n\n case \"select\":\n input = `<select id=\"${id}\" name=\"${nameAttr}\"${requiredAttr}${isNullValue ? ' disabled style=\"opacity:0.35\"' : \"\"} class=\"select select-bordered select-sm w-full\">\n ${field.required && !field.nullable ? \"\" : `<option value=\"\">— optional —</option>`}\n ${(field.options ?? []).map((o) => `<option value=\"${e(o)}\"${defaultStr === o ? \" selected\" : \"\"}>${e(o)}</option>`).join(\"\\n \")}\n </select>`;\n break;\n\n case \"textarea\":\n if (field.arrayElementType) {\n return renderArrayField(field, depth);\n }\n if (field.nested && field.nested.length > 0) {\n const subFields = field.nested\n .map((f) => renderField(f, depth + 1))\n .join(\"\\n\");\n return `\n <fieldset class=\"fieldset border border-base-300 rounded-box p-3 mb-3 ${indent}\">\n <legend class=\"fieldset-legend text-xs font-semibold text-base-content/60 px-1\">\n ${e(field.label)}${field.required ? ` <span class=\"text-error\">*</span>` : \"\"}\n </legend>\n ${subFields}\n </fieldset>`;\n }\n input = `<textarea id=\"${id}\" name=\"${nameAttr}\"${requiredAttr} rows=\"3\"${isNullValue ? ' disabled style=\"opacity:0.35\"' : \"\"}\n data-json\n class=\"textarea textarea-bordered textarea-sm w-full font-mono text-xs\"\n placeholder=\"${e(field.hint ?? \"JSON\")}\">${e(defaultStr)}</textarea>`;\n break;\n\n default:\n input = `<input type=\"${field.type}\" id=\"${id}\" name=\"${nameAttr}\"${requiredAttr}${isNullValue ? ' disabled style=\"opacity:0.35\"' : \"\"}\n value=\"${e(defaultStr)}\"\n class=\"input input-bordered input-sm w-full\"${\n field.hint === \"email\"\n ? ' autocomplete=\"email\"'\n : field.hint === \"url\"\n ? ' autocomplete=\"url\"'\n : \"\"\n }>`;\n }\n\n return `\n <div class=\"form-control mb-3 ${indent}\">\n <label for=\"${id}\" class=\"label pb-1\">\n <span class=\"label-text font-medium\">\n ${e(field.label)}${field.required ? ` <span class=\"text-error\">*</span>` : \"\"}\n ${field.hint ? `<span class=\"text-base-content/40 text-xs ml-1\">(${e(field.hint)})</span>` : \"\"}\n </span>\n </label>\n <div class=\"flex items-center gap-2\">\n <div class=\"flex-1 min-w-0\">${input}</div>\n ${nullToggle}\n </div>\n </div>`;\n}\n\n/** Minimal HTML escape */\nfunction e(s: string): string {\n return s\n .replace(/&/g, \"&\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\")\n .replace(/\"/g, \""\")\n .replace(/'/g, \"'\");\n}\n\n// ---------------------------------------------------------------------------\n// Array field rendering\n// ---------------------------------------------------------------------------\n\nfunction renderArrayField(field: FieldDescriptor, depth: number): string {\n const indent = depth > 0 ? `ml-${depth * 4}` : \"\";\n const id = `field_${field.name.replace(/\\./g, \"__\")}`;\n const isNullValue = field.defaultValue === \"__null__\";\n const isObject = field.arrayElementType === \"object\";\n\n // Parse existing value (JSON string → array)\n let items: unknown[] = [];\n if (\n field.defaultValue != null &&\n field.defaultValue !== \"\" &&\n field.defaultValue !== \"__null__\"\n ) {\n try {\n items = JSON.parse(String(field.defaultValue));\n } catch {\n /* ignore */\n }\n }\n if (!Array.isArray(items)) items = [];\n\n const itemsHtml = isObject\n ? items\n .map((item) =>\n renderObjectItem(field, (item as Record<string, unknown>) ?? {}),\n )\n .join(\"\\n\")\n : items.map((item) => renderPrimitiveItem(field, item)).join(\"\\n\");\n\n const templateHtml = isObject\n ? renderObjectItem(field, {})\n : renderPrimitiveItem(field, \"\");\n\n // Null toggle for nullable array fields\n const nullToggle =\n field.nullable\n ? `<span class=\"flex items-center gap-1 mt-2\">\n <input type=\"hidden\" id=\"${id}__isnull\" name=\"${e(field.name)}__isnull\" value=\"${isNullValue ? \"1\" : \"\"}\">\n <label class=\"flex items-center gap-1 cursor-pointer select-none text-xs text-base-content/40 hover:text-base-content/70 border border-base-300 rounded px-2 py-1\">\n <input type=\"checkbox\" class=\"checkbox checkbox-xs\" ${isNullValue ? \"checked\" : \"\"}\n onchange=\"(function(cb){\n var fs = cb.closest('[data-frs-array]');\n var h = document.getElementById('${id}__isnull');\n var hidden = document.getElementById('${id}');\n if (cb.checked) { fs.querySelector('[data-frs-array-items]').style.opacity='0.35'; h.value='1'; hidden.disabled=true; }\n else { fs.querySelector('[data-frs-array-items]').style.opacity=''; h.value=''; hidden.disabled=false; }\n })(this)\">\n <span>null</span>\n </label>\n </span>`\n : \"\";\n\n return `\n <fieldset class=\"fieldset border border-base-300 rounded-box p-3 mb-3 ${indent}\"\n data-frs-array=\"${e(field.name)}\" data-frs-array-type=\"${e(field.arrayElementType ?? \"text\")}\">\n <legend class=\"fieldset-legend text-xs font-semibold text-base-content/60 px-1\">\n ${e(field.label)}${field.required ? ` <span class=\"text-error\">*</span>` : \"\"}\n </legend>\n <input type=\"hidden\" id=\"${id}\" name=\"${e(field.name)}\" value=\"${e(JSON.stringify(items))}\"${isNullValue ? \" disabled\" : \"\"}>\n <div data-frs-array-items${isNullValue ? ' style=\"opacity:0.35\"' : \"\"}>\n ${itemsHtml}\n </div>\n <template data-frs-array-tpl>${templateHtml}</template>\n <button type=\"button\" class=\"btn btn-xs btn-outline mt-1\" data-frs-array-add>+ Add</button>\n ${nullToggle}\n </fieldset>`;\n}\n\nfunction renderPrimitiveItem(\n field: FieldDescriptor,\n value: unknown,\n): string {\n const strVal = value != null ? String(value) : \"\";\n let inputHtml: string;\n\n switch (field.arrayElementType) {\n case \"select\":\n inputHtml = `<select data-frs-val class=\"select select-bordered select-sm flex-1\">\n <option value=\"\">—</option>\n ${(field.arrayElementOptions ?? []).map((o) => `<option value=\"${e(o)}\"${strVal === o ? \" selected\" : \"\"}>${e(o)}</option>`).join(\"\")}\n </select>`;\n break;\n case \"checkbox\":\n inputHtml = `<label class=\"flex items-center gap-2 flex-1 cursor-pointer\">\n <input type=\"checkbox\" data-frs-val class=\"checkbox checkbox-sm checkbox-primary\"${strVal === \"true\" ? \" checked\" : \"\"}>\n <span class=\"text-sm\">true</span>\n </label>`;\n break;\n case \"number\":\n inputHtml = `<input type=\"number\" data-frs-val value=\"${e(strVal)}\" class=\"input input-bordered input-sm flex-1\">`;\n break;\n case \"datetime-local\":\n inputHtml = `<input type=\"datetime-local\" data-frs-val value=\"${e(strVal)}\" class=\"input input-bordered input-sm flex-1\">`;\n break;\n default:\n inputHtml = `<input type=\"text\" data-frs-val value=\"${e(strVal)}\" class=\"input input-bordered input-sm flex-1\">`;\n }\n\n return `<div class=\"flex items-center gap-2 mb-2\" data-frs-array-item>\n ${inputHtml}\n <button type=\"button\" class=\"btn btn-xs btn-ghost text-error\" data-frs-array-rm>×</button>\n </div>`;\n}\n\nfunction renderObjectItem(\n field: FieldDescriptor,\n obj: Record<string, unknown>,\n): string {\n const elFields = field.arrayElementFields ?? [];\n\n const fieldsHtml = elFields\n .map((f) => {\n const val = obj[f.name];\n const strVal =\n val == null\n ? \"\"\n : typeof val === \"object\"\n ? JSON.stringify(val)\n : String(val);\n\n switch (f.type) {\n case \"checkbox\":\n return `<div class=\"form-control mb-2\">\n <label class=\"label cursor-pointer justify-start gap-3\">\n <input type=\"checkbox\" data-frs-key=\"${e(f.name)}\" class=\"checkbox checkbox-sm checkbox-primary\"${strVal === \"true\" ? \" checked\" : \"\"}>\n <span class=\"label-text text-sm\">${e(f.label)}</span>\n </label>\n </div>`;\n case \"select\":\n return `<div class=\"form-control mb-2\">\n <label class=\"label pb-1\"><span class=\"label-text text-sm\">${e(f.label)}</span></label>\n <select data-frs-key=\"${e(f.name)}\" class=\"select select-bordered select-sm w-full\">\n ${f.required ? \"\" : `<option value=\"\">—</option>`}\n ${(f.options ?? []).map((o) => `<option value=\"${e(o)}\"${strVal === o ? \" selected\" : \"\"}>${e(o)}</option>`).join(\"\")}\n </select>\n </div>`;\n case \"number\":\n return `<div class=\"form-control mb-2\">\n <label class=\"label pb-1\"><span class=\"label-text text-sm\">${e(f.label)}</span></label>\n <input type=\"number\" data-frs-key=\"${e(f.name)}\" value=\"${e(strVal)}\" class=\"input input-bordered input-sm w-full\">\n </div>`;\n case \"datetime-local\":\n return `<div class=\"form-control mb-2\">\n <label class=\"label pb-1\"><span class=\"label-text text-sm\">${e(f.label)}</span></label>\n <input type=\"datetime-local\" data-frs-key=\"${e(f.name)}\" value=\"${e(strVal)}\" class=\"input input-bordered input-sm w-full\">\n </div>`;\n case \"textarea\":\n return `<div class=\"form-control mb-2\">\n <label class=\"label pb-1\"><span class=\"label-text text-sm\">${e(f.label)}</span></label>\n <textarea data-frs-key=\"${e(f.name)}\" rows=\"2\" class=\"textarea textarea-bordered textarea-sm w-full font-mono text-xs\" placeholder=\"JSON\">${e(strVal)}</textarea>\n </div>`;\n default:\n return `<div class=\"form-control mb-2\">\n <label class=\"label pb-1\"><span class=\"label-text text-sm\">${e(f.label)}</span></label>\n <input type=\"text\" data-frs-key=\"${e(f.name)}\" value=\"${e(strVal)}\" class=\"input input-bordered input-sm w-full\">\n </div>`;\n }\n })\n .join(\"\\n\");\n\n return `<div class=\"border border-base-200 rounded p-3 mb-2\" data-frs-array-item>\n <div class=\"flex justify-end mb-1\">\n <button type=\"button\" class=\"btn btn-xs btn-ghost text-error\" data-frs-array-rm>×</button>\n </div>\n ${fieldsHtml}\n </div>`;\n}\n\n// ---------------------------------------------------------------------------\n// Full form render\n// ---------------------------------------------------------------------------\n\nexport function renderForm(\n fields: FieldDescriptor[],\n action: string,\n method: \"GET\" | \"POST\",\n submitLabel = \"Save\",\n): string {\n const fieldsHtml = fields.map((f) => renderField(f)).join(\"\\n\");\n return `\n <form action=\"${e(action)}\" method=\"${method}\" novalidate data-frs-form>\n ${fieldsHtml}\n <div class=\"flex gap-2 mt-4 pt-4 border-t border-base-200\">\n <button type=\"submit\" class=\"btn btn-primary btn-sm\">${e(submitLabel)}</button>\n <button type=\"button\" class=\"btn btn-ghost btn-sm\" onclick=\"history.back()\">Cancel</button>\n </div>\n </form>`;\n}\n","export { CellValue } from \"./cell-value\";\nexport { ClientScript } from \"./client-script\";\nexport { renderDashboardJsx } from \"./dashboard\";\nexport { FilterBar } from \"./filter-bar\";\nexport { renderFormPageJsx } from \"./form\";\nexport { renderListJsx } from \"./list\";\nexport { PageShell, renderHtml, renderPageJsx } from \"./shell\";\nexport type {\n ColumnMeta,\n FilterState,\n PageOptions,\n QueryError,\n RelationalFieldMeta,\n SortState,\n WhereOp,\n} from \"./types\";\n","// ── Shared helpers ──────────────────────────────────────────────────────────\nfunction frsGetBasePath() {\n var root = document.querySelector(\"[data-frs-panel-root]\");\n var bp = root && root.getAttribute(\"data-frs-base-path\");\n if (typeof bp === \"string\") return bp.replace(/\\/$/, \"\");\n return window.location.pathname.replace(/\\/[^/]*\\/?$/, \"\");\n}\n\n// ── Right panel (relations preview) ─────────────────────────────────────────\n(function () {\n function panelEls() {\n return {\n root: document.querySelector(\"[data-frs-panel-root]\"),\n backdrop: document.querySelector(\"[data-frs-panel-backdrop]\"),\n panel: document.querySelector(\"[data-frs-panel]\"),\n title: document.querySelector(\"[data-frs-panel-title]\"),\n body: document.querySelector(\"[data-frs-panel-body]\"),\n };\n }\n function openPanel(label) {\n var els = panelEls();\n if (!els.root || !els.panel) return;\n els.root.classList.remove(\"hidden\");\n els.root.setAttribute(\"aria-hidden\", \"false\");\n requestAnimationFrame(function () {\n if (els.backdrop) els.backdrop.style.opacity = \"1\";\n if (els.panel) {\n els.panel.classList.remove(\"translate-x-full\");\n els.panel.style.transform = \"translateX(0)\";\n els.panel.style.translate = \"0 0\";\n }\n });\n if (els.title) els.title.textContent = label || \"Relation\";\n if (els.body) {\n els.body.innerHTML =\n '<div class=\"flex items-center justify-center py-12 text-base-content/40\"><span class=\"loading loading-spinner loading-md\"></span></div>';\n }\n }\n function closePanel() {\n var els = panelEls();\n if (!els.root || !els.panel) return;\n if (els.backdrop) els.backdrop.style.opacity = \"0\";\n if (els.panel) {\n els.panel.style.transform = \"translateX(100%)\";\n els.panel.style.translate = \"100% 0\";\n els.panel.classList.add(\"translate-x-full\");\n }\n setTimeout(function () {\n els.root.classList.add(\"hidden\");\n els.root.setAttribute(\"aria-hidden\", \"true\");\n }, 200);\n }\n function getBasePath() {\n return frsGetBasePath();\n }\n function fetchPanel(url, label) {\n openPanel(label);\n fetch(url, { credentials: \"same-origin\" })\n .then(function (r) {\n return r.text();\n })\n .then(function (html) {\n var els = panelEls();\n if (els.body) els.body.innerHTML = html;\n })\n .catch(function (err) {\n var els = panelEls();\n if (els.body) {\n els.body.innerHTML =\n '<div class=\"p-6 text-error text-sm\">Error: ' +\n (err && err.message ? err.message : String(err)) +\n \"</div>\";\n }\n });\n }\n document.addEventListener(\"click\", function (e) {\n var trigger = e.target.closest(\"[data-frs-relation]\");\n if (trigger) {\n e.preventDefault();\n var type = trigger.getAttribute(\"data-frs-rel-type\");\n var repo = trigger.getAttribute(\"data-frs-rel-repo\");\n var fk = trigger.getAttribute(\"data-frs-rel-fk\");\n var val = trigger.getAttribute(\"data-frs-rel-val\");\n var label = trigger.getAttribute(\"data-frs-rel-label\") || \"Relation\";\n var bp = getBasePath();\n var url;\n if (type === \"one\") {\n url =\n bp +\n \"/\" +\n encodeURIComponent(repo) +\n \"/_panel?type=one&id=\" +\n encodeURIComponent(val);\n } else {\n url =\n bp +\n \"/\" +\n encodeURIComponent(repo) +\n \"/_panel?type=many&fk=\" +\n encodeURIComponent(fk) +\n \"&fv=\" +\n encodeURIComponent(val);\n }\n fetchPanel(url, repo + \" · \" + label);\n return;\n }\n if (e.target.closest(\"[data-frs-panel-close]\")) {\n closePanel();\n return;\n }\n if (e.target.closest(\"[data-frs-panel-backdrop]\")) {\n closePanel();\n return;\n }\n var pageBtn = e.target.closest(\"[data-frs-panel-page]\");\n if (pageBtn) {\n // Recompute URL by inspecting the current open panel context — encoded in the body's first anchor \"Full view →\"\n // Simpler: rebuild via the previous URL stored in data-attr.\n var fullViewLink = document.querySelector(\n \"[data-frs-panel-body] a.btn-outline[href]\",\n );\n if (!fullViewLink) return;\n var dir = pageBtn.getAttribute(\"data-frs-panel-page\");\n var cursor = pageBtn.getAttribute(\"data-cursor\") || \"\";\n var fullViewUrl = new URL(fullViewLink.href, window.location.href);\n var repo = fullViewUrl.pathname.split(\"/\").filter(Boolean).pop();\n var bp = fullViewUrl.pathname.replace(/\\/[^/]+\\/?$/, \"\");\n var fk = \"\";\n var fv = \"\";\n fullViewUrl.searchParams.forEach(function (v, k) {\n if (k.indexOf(\"fv_\") === 0) {\n fk = k.slice(3);\n fv = v;\n }\n });\n var url =\n bp +\n \"/\" +\n encodeURIComponent(repo) +\n \"/_panel?type=many&fk=\" +\n encodeURIComponent(fk) +\n \"&fv=\" +\n encodeURIComponent(fv) +\n \"&cursor=\" +\n encodeURIComponent(cursor) +\n \"&dir=\" +\n encodeURIComponent(dir);\n fetchPanel(url, repo);\n }\n });\n document.addEventListener(\"keydown\", function (e) {\n if (e.key === \"Escape\") closePanel();\n });\n})();\n\n// ── Bulk selection + actions ────────────────────────────────────────────────\n(function () {\n var state = {\n selectAllAcrossQuery: false,\n // Keep a Set of selected ids on the current page (cleared on navigation).\n selected: new Set(),\n };\n\n function bar() {\n return document.querySelector(\"[data-frs-bulk-bar]\");\n }\n function summarize() {\n var b = bar();\n if (!b) return;\n var total = parseInt(b.getAttribute(\"data-frs-total\") || \"0\", 10);\n var summary = b.querySelector(\"[data-frs-bulk-summary]\");\n var selectAllBtn = b.querySelector(\"[data-frs-bulk-select-all]\");\n var allActive = b.querySelector(\"[data-frs-bulk-all-active]\");\n var pageSize = parseInt(b.getAttribute(\"data-frs-page-size\") || \"0\", 10);\n var n = state.selected.size;\n if (state.selectAllAcrossQuery) {\n if (allActive) allActive.classList.remove(\"hidden\");\n if (selectAllBtn) selectAllBtn.classList.add(\"hidden\");\n if (summary) summary.textContent = \"\";\n b.classList.remove(\"hidden\");\n return;\n }\n if (n === 0) {\n b.classList.add(\"hidden\");\n if (selectAllBtn) selectAllBtn.classList.add(\"hidden\");\n if (allActive) allActive.classList.add(\"hidden\");\n return;\n }\n b.classList.remove(\"hidden\");\n if (allActive) allActive.classList.add(\"hidden\");\n if (summary) {\n summary.textContent =\n n + \" selected\" + (pageSize ? \" on this page\" : \"\");\n }\n if (selectAllBtn && total > n) {\n selectAllBtn.classList.remove(\"hidden\");\n } else if (selectAllBtn) {\n selectAllBtn.classList.add(\"hidden\");\n }\n }\n function syncHeader() {\n var head = document.querySelector(\"[data-frs-select-page]\");\n if (!head) return;\n var rows = document.querySelectorAll(\"[data-frs-select-row]\");\n var checked = 0;\n rows.forEach(function (r) {\n if (r.checked) checked++;\n });\n head.indeterminate = checked > 0 && checked < rows.length;\n head.checked = rows.length > 0 && checked === rows.length;\n }\n document.addEventListener(\"change\", function (e) {\n if (e.target.matches(\"[data-frs-select-row]\")) {\n var id = e.target.value;\n if (e.target.checked) state.selected.add(id);\n else state.selected.delete(id);\n state.selectAllAcrossQuery = false;\n syncHeader();\n summarize();\n } else if (e.target.matches(\"[data-frs-select-page]\")) {\n var rows = document.querySelectorAll(\"[data-frs-select-row]\");\n rows.forEach(function (r) {\n r.checked = e.target.checked;\n if (e.target.checked) state.selected.add(r.value);\n else state.selected.delete(r.value);\n });\n state.selectAllAcrossQuery = false;\n summarize();\n }\n });\n document.addEventListener(\"click\", function (e) {\n var sa = e.target.closest(\"[data-frs-bulk-select-all]\");\n if (sa) {\n state.selectAllAcrossQuery = true;\n summarize();\n return;\n }\n var clear = e.target.closest(\"[data-frs-bulk-clear]\");\n if (clear) {\n state.selectAllAcrossQuery = false;\n state.selected.clear();\n document\n .querySelectorAll(\"[data-frs-select-row]\")\n .forEach(function (r) {\n r.checked = false;\n });\n syncHeader();\n summarize();\n return;\n }\n var actBtn = e.target.closest(\"[data-frs-bulk-action]\");\n if (actBtn) {\n var action = actBtn.getAttribute(\"data-frs-bulk-action\");\n if (action === \"delete\") doBulkDelete();\n else if (action === \"update\") openBulkUpdateModal();\n }\n });\n\n function buildPayload() {\n var b = bar();\n if (!b) return null;\n if (state.selectAllAcrossQuery) {\n var filters = [];\n try {\n filters = JSON.parse(b.getAttribute(\"data-frs-filters\") || \"[]\");\n } catch (_) {}\n return { selectAll: true, filters: filters };\n }\n return { ids: Array.from(state.selected) };\n }\n\n function repoEndpoint(action) {\n var b = bar();\n if (!b) return null;\n var repo = b.getAttribute(\"data-frs-repo\");\n var bp = frsGetBasePath();\n return bp + \"/\" + encodeURIComponent(repo) + \"/_bulk/\" + action;\n }\n\n function doBulkDelete() {\n var payload = buildPayload();\n if (!payload) return;\n var n = state.selectAllAcrossQuery\n ? \"all matching\"\n : payload.ids.length + \"\";\n if (!confirm(\"Delete \" + n + \" documents? This cannot be undone.\")) return;\n var url = repoEndpoint(\"delete\");\n if (!url) return;\n fetch(url, {\n method: \"POST\",\n credentials: \"same-origin\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(payload),\n })\n .then(function (r) {\n return r.json().then(function (j) {\n return { ok: r.ok, body: j };\n });\n })\n .then(function (res) {\n if (!res.ok) {\n alert(\"Bulk delete failed: \" + (res.body && res.body.error));\n return;\n }\n window.location.reload();\n })\n .catch(function (err) {\n alert(\"Bulk delete failed: \" + err.message);\n });\n }\n\n function openBulkUpdateModal() {\n var b = bar();\n var dialog = document.getElementById(\"frs-bulk-update-modal\");\n if (!b || !dialog) return;\n var fields = [];\n try {\n fields = JSON.parse(b.getAttribute(\"data-frs-fields\") || \"[]\");\n } catch (_) {}\n if (fields.length === 0) return;\n var summary = dialog.querySelector(\n \"[data-frs-bulk-update-summary]\",\n );\n if (summary) {\n summary.textContent = state.selectAllAcrossQuery\n ? \"Update one field on all matching documents.\"\n : \"Update one field on \" +\n state.selected.size +\n \" selected document\" +\n (state.selected.size !== 1 ? \"s\" : \"\") +\n \".\";\n }\n var select = dialog.querySelector(\"[data-frs-bulk-field-select]\");\n var valueContainer = dialog.querySelector(\n \"[data-frs-bulk-value-container]\",\n );\n var renderValueInput = function () {\n if (!valueContainer || !select) return;\n var name = select.value;\n var meta = fields.filter(function (f) {\n return f.name === name;\n })[0];\n if (!meta) {\n valueContainer.innerHTML = \"\";\n return;\n }\n var inputHtml = \"\";\n var label =\n '<div class=\"label\"><span class=\"label-text text-xs uppercase tracking-wide\">Value</span></div>';\n if (meta.type === \"boolean\") {\n inputHtml =\n '<select name=\"value\" class=\"select select-bordered select-sm w-full\">' +\n '<option value=\"true\">true</option><option value=\"false\">false</option>' +\n \"</select>\";\n } else if (\n (meta.type === \"enum\" || meta.type === \"literal\") &&\n meta.enumValues &&\n meta.enumValues.length\n ) {\n inputHtml =\n '<select name=\"value\" class=\"select select-bordered select-sm w-full\">';\n meta.enumValues.forEach(function (v) {\n inputHtml +=\n '<option value=\"' + escapeAttr(v) + '\">' + escapeHtml(v) + \"</option>\";\n });\n inputHtml += \"</select>\";\n } else if (meta.type === \"number\" || meta.type === \"bigint\") {\n inputHtml =\n '<input type=\"number\" step=\"any\" name=\"value\" class=\"input input-bordered input-sm w-full\" />';\n } else {\n inputHtml =\n '<input type=\"text\" name=\"value\" class=\"input input-bordered input-sm w-full\" />';\n }\n valueContainer.innerHTML =\n '<label class=\"form-control w-full\">' + label + inputHtml + \"</label>\";\n };\n if (select) {\n select.value = \"\";\n select.onchange = renderValueInput;\n }\n if (valueContainer) valueContainer.innerHTML = \"\";\n var form = dialog.querySelector(\"[data-frs-bulk-update-form]\");\n if (form) {\n form.onsubmit = function (e) {\n e.preventDefault();\n if (!select || !select.value) return;\n var meta = fields.filter(function (f) {\n return f.name === select.value;\n })[0];\n if (!meta) return;\n var input = valueContainer.querySelector(\n 'input[name=\"value\"], select[name=\"value\"]',\n );\n if (!input) return;\n var raw = input.value;\n var typed;\n if (meta.type === \"boolean\") typed = raw === \"true\";\n else if (meta.type === \"number\") typed = raw === \"\" ? null : Number(raw);\n else if (meta.type === \"bigint\") typed = raw === \"\" ? null : Number(raw);\n else typed = raw;\n var payload = buildPayload();\n if (!payload) return;\n payload.field = select.value;\n payload.value = typed;\n var url = repoEndpoint(\"update\");\n if (!url) return;\n fetch(url, {\n method: \"POST\",\n credentials: \"same-origin\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(payload),\n })\n .then(function (r) {\n return r.json().then(function (j) {\n return { ok: r.ok, body: j };\n });\n })\n .then(function (res) {\n if (!res.ok) {\n alert(\"Bulk update failed: \" + (res.body && res.body.error));\n return;\n }\n dialog.close();\n window.location.reload();\n })\n .catch(function (err) {\n alert(\"Bulk update failed: \" + err.message);\n });\n };\n }\n var cancel = dialog.querySelector(\"[data-frs-bulk-update-cancel]\");\n if (cancel)\n cancel.onclick = function () {\n dialog.close();\n };\n if (typeof dialog.showModal === \"function\") dialog.showModal();\n else dialog.setAttribute(\"open\", \"\");\n }\n\n function escapeHtml(s) {\n return String(s).replace(/[&<>\"']/g, function (c) {\n return (\n { \"&\": \"&\", \"<\": \"<\", \">\": \">\", '\"': \""\", \"'\": \"'\" }[\n c\n ] || c\n );\n });\n }\n function escapeAttr(s) {\n return escapeHtml(s);\n }\n})();\n\n// ── Theme switcher ──────────────────────────────────────────────────────────\n(function () {\n function syncThemeUI() {\n var current =\n document.documentElement.getAttribute(\"data-theme\") || \"corporate\";\n var label = document.querySelector(\"[data-frs-theme-current]\");\n if (label) label.textContent = current;\n document.querySelectorAll(\"[data-frs-theme-check]\").forEach(function (el) {\n el.classList.toggle(\n \"hidden\",\n el.getAttribute(\"data-frs-theme-check\") !== current,\n );\n });\n }\n document.addEventListener(\"DOMContentLoaded\", syncThemeUI);\n document.addEventListener(\"click\", function (e) {\n var btn = e.target.closest(\"[data-frs-theme]\");\n if (!btn) return;\n var theme = btn.getAttribute(\"data-frs-theme\");\n if (!theme) return;\n document.documentElement.setAttribute(\"data-theme\", theme);\n try {\n localStorage.setItem(\"frs-admin-theme\", theme);\n } catch (_) {}\n syncThemeUI();\n // Close the dropdown by blurring focus (DaisyUI dropdown closes on focusout)\n if (document.activeElement && document.activeElement.blur) {\n document.activeElement.blur();\n }\n });\n})();\n\n// ── Form validation + array serialization ───────────────────────────────────\ndocument.addEventListener(\"submit\", function (e) {\n var form = e.target;\n if (!form.hasAttribute(\"data-frs-form\")) return;\n\n // 1. Validate JSON textareas\n var valid = true;\n form.querySelectorAll(\"textarea[data-json]\").forEach(function (ta) {\n var v = ta.value.trim();\n if (!v) return;\n try {\n JSON.parse(v);\n } catch (err) {\n valid = false;\n e.preventDefault();\n alert('Invalid JSON in field \"' + ta.name + '\":\\n' + err.message);\n }\n });\n if (!valid) return;\n\n // 2. Serialize array fields into hidden inputs\n form.querySelectorAll(\"[data-frs-array]\").forEach(function (fieldset) {\n var hidden = fieldset.querySelector(\"input[type=hidden][name]\");\n if (!hidden || hidden.disabled) return;\n\n var type = fieldset.getAttribute(\"data-frs-array-type\");\n var items = fieldset.querySelectorAll(\"[data-frs-array-item]\");\n var arr = [];\n\n if (type === \"object\") {\n items.forEach(function (item) {\n var obj = {};\n item.querySelectorAll(\"[data-frs-key]\").forEach(function (inp) {\n var key = inp.getAttribute(\"data-frs-key\");\n if (inp.type === \"checkbox\") {\n obj[key] = inp.checked;\n } else if (inp.type === \"number\") {\n obj[key] = inp.value === \"\" ? null : Number(inp.value);\n } else if (inp.tagName === \"TEXTAREA\") {\n var v = inp.value.trim();\n if (v) {\n try {\n obj[key] = JSON.parse(v);\n } catch (_) {\n obj[key] = v;\n }\n } else {\n obj[key] = null;\n }\n } else {\n obj[key] = inp.value;\n }\n });\n arr.push(obj);\n });\n } else {\n items.forEach(function (item) {\n var inp = item.querySelector(\"[data-frs-val]\");\n if (!inp) return;\n if (type === \"checkbox\") {\n arr.push(inp.checked);\n } else if (type === \"number\") {\n if (inp.value !== \"\") arr.push(Number(inp.value));\n } else {\n if (inp.value !== \"\") arr.push(inp.value);\n }\n });\n }\n\n hidden.value = JSON.stringify(arr);\n });\n});\n\n// ── Array add / remove buttons ──────────────────────────────────────────────\ndocument.addEventListener(\"click\", function (e) {\n // Add item\n var addBtn = e.target.closest(\"[data-frs-array-add]\");\n if (addBtn) {\n var fieldset = addBtn.closest(\"[data-frs-array]\");\n if (!fieldset) return;\n var tpl = fieldset.querySelector(\"template[data-frs-array-tpl]\");\n var container = fieldset.querySelector(\"[data-frs-array-items]\");\n if (!tpl || !container) return;\n var clone = tpl.content.cloneNode(true);\n container.appendChild(clone);\n var last = container.lastElementChild;\n if (last) {\n var firstInp = last.querySelector(\"input,select,textarea\");\n if (firstInp) firstInp.focus();\n }\n return;\n }\n\n // Remove item\n var rmBtn = e.target.closest(\"[data-frs-array-rm]\");\n if (rmBtn) {\n var item = rmBtn.closest(\"[data-frs-array-item]\");\n if (item) item.remove();\n }\n});\n\n// ── Table enhancements ──────────────────────────────────────────────────────\ndocument.addEventListener(\"DOMContentLoaded\", function () {\n document.querySelectorAll(\"table[data-frs-table]\").forEach(initTable);\n});\n\nfunction initTable(table) {\n tagOriginalIndices(table);\n applySavedColumnOrder(table);\n initColumnResize(table);\n initColumnVisibility(table);\n initColumnReorder(table);\n}\n\n// ── Tag original column indices ─────────────────────────────────────────────\nfunction tagOriginalIndices(table) {\n var ths = Array.from(table.querySelectorAll(\"thead th\"));\n var dataCount = countDataColumns(table, ths);\n for (var i = 0; i < dataCount; i++) {\n ths[i].setAttribute(\"data-orig-col\", String(i));\n }\n table.querySelectorAll(\"tbody tr\").forEach(function (row) {\n var tds = Array.from(row.querySelectorAll(\"td\"));\n for (var j = 0; j < dataCount && j < tds.length; j++) {\n tds[j].setAttribute(\"data-orig-col\", String(j));\n }\n });\n}\n\nfunction countDataColumns(table, ths) {\n var explicit = table.getAttribute(\"data-frs-colcount\");\n if (explicit) return parseInt(explicit, 10);\n var count = 0;\n for (var i = 0; i < ths.length; i++) {\n if (ths[i].querySelector(\"a[href]\")) count++;\n else break;\n }\n return count || Math.max(0, ths.length - 1);\n}\n\n// ── Apply saved column order ────────────────────────────────────────────────\nfunction applySavedColumnOrder(table) {\n var repo = table.getAttribute(\"data-frs-repo\") || \"default\";\n var saved;\n try {\n saved = JSON.parse(localStorage.getItem(\"frs_colorder_\" + repo));\n } catch (_) {\n return;\n }\n if (!saved || !Array.isArray(saved) || saved.length === 0) return;\n reorderColumns(table, saved);\n}\n\n// ── Reorder columns by orig-index array ─────────────────────────────────────\nfunction reorderColumns(table, order) {\n var headRow = table.querySelector(\"thead tr\");\n if (!headRow) return;\n reorderRow(headRow, order);\n table.querySelectorAll(\"tbody tr\").forEach(function (row) {\n reorderRow(row, order);\n });\n}\n\nfunction reorderRow(row, order) {\n var cells = Array.from(row.children);\n var dataCells = cells.filter(function (c) {\n return c.hasAttribute(\"data-orig-col\");\n });\n var tailCells = cells.filter(function (c) {\n return !c.hasAttribute(\"data-orig-col\");\n });\n var cellMap = {};\n dataCells.forEach(function (c) {\n cellMap[c.getAttribute(\"data-orig-col\")] = c;\n });\n while (row.firstChild) row.removeChild(row.firstChild);\n order.forEach(function (origIdx) {\n if (cellMap[origIdx]) row.appendChild(cellMap[origIdx]);\n });\n dataCells.forEach(function (c) {\n if (!row.contains(c)) row.appendChild(c);\n });\n tailCells.forEach(function (c) {\n row.appendChild(c);\n });\n}\n\n// ── Column resize ───────────────────────────────────────────────────────────\nfunction initColumnResize(table) {\n var ths = Array.from(table.querySelectorAll(\"thead th\"));\n ths.forEach(function (th, i) {\n if (i === ths.length - 1) return;\n th.style.position = \"relative\";\n var handle = document.createElement(\"div\");\n handle.style.cssText =\n \"position:absolute;right:0;top:0;bottom:0;width:5px;cursor:col-resize;z-index:10;\";\n handle.addEventListener(\"mousedown\", function (e) {\n e.preventDefault();\n e.stopPropagation();\n var startX = e.clientX,\n startW = th.offsetWidth;\n var line = document.createElement(\"div\");\n line.style.cssText =\n \"position:fixed;top:0;bottom:0;width:2px;background:oklch(0.585 0.233 277.117);opacity:0.5;pointer-events:none;z-index:9999;\";\n line.style.left = e.clientX + \"px\";\n document.body.appendChild(line);\n function onMove(ev) {\n var newW = Math.max(40, startW + ev.clientX - startX);\n th.style.width = newW + \"px\";\n th.style.minWidth = newW + \"px\";\n line.style.left = ev.clientX + \"px\";\n }\n function onUp() {\n document.body.removeChild(line);\n document.removeEventListener(\"mousemove\", onMove);\n document.removeEventListener(\"mouseup\", onUp);\n }\n document.addEventListener(\"mousemove\", onMove);\n document.addEventListener(\"mouseup\", onUp);\n });\n th.appendChild(handle);\n });\n}\n\n// ── Column visibility (Columns dropdown with checkboxes) ────────────────────\nfunction initColumnVisibility(table) {\n var dataThs = Array.from(table.querySelectorAll(\"thead th[data-orig-col]\"));\n if (dataThs.length === 0) return;\n\n var wrap = table.closest(\"[data-frs-table-wrap]\");\n var toolbar =\n (wrap &&\n (wrap.parentElement\n ? wrap.parentElement.querySelector(\"[data-frs-toolbar]\")\n : null)) ||\n (wrap && wrap.previousElementSibling);\n if (!toolbar) return;\n\n var repo = table.getAttribute(\"data-frs-repo\") || \"default\";\n var storageKey = \"frs_cols_\" + repo;\n var savedState = {};\n try {\n savedState = JSON.parse(localStorage.getItem(storageKey) || \"{}\");\n } catch (_) {}\n\n function saveState(origIdx, visible) {\n savedState[origIdx] = visible;\n try {\n localStorage.setItem(storageKey, JSON.stringify(savedState));\n } catch (_) {}\n }\n\n function setColVisible(origIdx, visible) {\n var th = table.querySelector('thead th[data-orig-col=\"' + origIdx + '\"]');\n if (th) th.style.display = visible ? \"\" : \"none\";\n table\n .querySelectorAll('tbody td[data-orig-col=\"' + origIdx + '\"]')\n .forEach(function (td) {\n td.style.display = visible ? \"\" : \"none\";\n });\n }\n\n var cols = dataThs.map(function (th) {\n var origIdx = parseInt(th.getAttribute(\"data-orig-col\"), 10);\n return {\n origIndex: origIdx,\n label: th.textContent.replace(/\\s+/g, \" \").trim(),\n };\n });\n\n // Build dropdown\n var dropdown = document.createElement(\"div\");\n dropdown.className = \"dropdown dropdown-end\";\n\n var btn = document.createElement(\"button\");\n btn.type = \"button\";\n btn.tabIndex = 0;\n btn.className = \"btn btn-sm btn-outline gap-1\";\n btn.innerHTML =\n '<svg xmlns=\"http://www.w3.org/2000/svg\" class=\"size-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\">' +\n '<path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 4v16M15 4v16M4 9h16M4 15h16\"/>' +\n \"</svg> Columns\";\n dropdown.appendChild(btn);\n\n var menu = document.createElement(\"ul\");\n menu.tabIndex = 0;\n menu.className =\n \"dropdown-content menu bg-base-100 rounded-box z-50 p-2 shadow-lg border border-base-300 w-56 max-h-80 overflow-y-auto flex-nowrap\";\n\n cols.forEach(function (col) {\n var li = document.createElement(\"li\");\n var label = document.createElement(\"label\");\n label.className =\n \"flex items-center gap-2 cursor-pointer px-2 py-1.5 rounded hover:bg-base-200\";\n\n var cb = document.createElement(\"input\");\n cb.type = \"checkbox\";\n cb.className = \"checkbox checkbox-xs checkbox-primary\";\n var isVisible = savedState[col.origIndex] !== false;\n cb.checked = isVisible;\n\n var span = document.createElement(\"span\");\n span.className = \"text-sm select-none\";\n span.textContent = col.label || \"Column \" + (col.origIndex + 1);\n\n label.appendChild(cb);\n label.appendChild(span);\n li.appendChild(label);\n\n if (!isVisible) setColVisible(col.origIndex, false);\n\n cb.addEventListener(\"change\", function (e) {\n var visible = e.target.checked;\n setColVisible(col.origIndex, visible);\n saveState(col.origIndex, visible);\n });\n\n menu.appendChild(li);\n });\n\n dropdown.appendChild(menu);\n toolbar.appendChild(dropdown);\n}\n\n// ── Column reorder (drag grip handles on headers) ───────────────────────────\nfunction initColumnReorder(table) {\n var repo = table.getAttribute(\"data-frs-repo\") || \"default\";\n var orderKey = \"frs_colorder_\" + repo;\n var dragSrcTh = null;\n var allDataThs = Array.from(\n table.querySelectorAll(\"thead th[data-orig-col]\"),\n );\n if (allDataThs.length < 2) return;\n\n allDataThs.forEach(function (th) {\n // Prepend a drag grip\n var grip = document.createElement(\"span\");\n grip.draggable = true;\n grip.textContent = \"\\u2807\";\n grip.style.cssText =\n \"cursor:grab;opacity:0.18;margin-right:4px;font-size:14px;vertical-align:middle;user-select:none;display:inline-block;\";\n grip.addEventListener(\"mouseenter\", function () {\n grip.style.opacity = \"0.5\";\n });\n grip.addEventListener(\"mouseleave\", function () {\n grip.style.opacity = \"0.18\";\n });\n th.insertBefore(grip, th.firstChild);\n\n // Drag starts from the grip only\n grip.addEventListener(\"dragstart\", function (e) {\n dragSrcTh = th;\n th.style.opacity = \"0.35\";\n e.dataTransfer.effectAllowed = \"move\";\n e.dataTransfer.setData(\"text/plain\", \"col\");\n try {\n e.dataTransfer.setDragImage(th, 20, 16);\n } catch (_) {}\n });\n\n grip.addEventListener(\"dragend\", function () {\n if (dragSrcTh) dragSrcTh.style.opacity = \"\";\n dragSrcTh = null;\n allDataThs.forEach(function (t) {\n t.style.boxShadow = \"\";\n });\n });\n\n // Drop target is the full <th>\n th.addEventListener(\"dragover\", function (e) {\n if (!dragSrcTh || dragSrcTh === th) return;\n e.preventDefault();\n e.dataTransfer.dropEffect = \"move\";\n allDataThs.forEach(function (t) {\n t.style.boxShadow = \"\";\n });\n var rect = th.getBoundingClientRect();\n var midX = rect.left + rect.width / 2;\n if (e.clientX < midX) {\n th.style.boxShadow = \"inset 3px 0 0 oklch(0.585 0.233 277.117)\";\n } else {\n th.style.boxShadow = \"inset -3px 0 0 oklch(0.585 0.233 277.117)\";\n }\n });\n\n th.addEventListener(\"dragleave\", function () {\n th.style.boxShadow = \"\";\n });\n\n th.addEventListener(\"drop\", function (e) {\n e.preventDefault();\n if (!dragSrcTh || dragSrcTh === th) return;\n allDataThs.forEach(function (t) {\n t.style.boxShadow = \"\";\n });\n\n var headRow = th.parentNode;\n var rect = th.getBoundingClientRect();\n var midX = rect.left + rect.width / 2;\n if (e.clientX < midX) {\n headRow.insertBefore(dragSrcTh, th);\n } else {\n headRow.insertBefore(dragSrcTh, th.nextElementSibling);\n }\n\n // Read new order from the reordered thead\n var newOrder = Array.from(\n table.querySelectorAll(\"thead th[data-orig-col]\"),\n ).map(function (t) {\n return parseInt(t.getAttribute(\"data-orig-col\"), 10);\n });\n\n // Apply the same order to all tbody rows\n table.querySelectorAll(\"tbody tr\").forEach(function (row) {\n reorderRow(row, newOrder);\n });\n\n // Persist\n try {\n localStorage.setItem(orderKey, JSON.stringify(newOrder));\n } catch (_) {}\n });\n });\n}\n","import JS from \"./client-script.raw.js\";\n\nexport function ClientScript() {\n // dangerouslySetInnerHTML is required here: JSX would escape < > & inside\n // a <script> text child, breaking the JavaScript at runtime.\n return <script dangerouslySetInnerHTML={{ __html: JS }} />;\n}\n","import type { Child, FC, PropsWithChildren } from \"hono/jsx\";\nimport { renderToString } from \"hono/jsx/dom/server\";\nimport { ClientScript } from \"./client-script\";\nimport { RightPanel } from \"./right-panel\";\nimport type { PageOptions } from \"./types\";\n\n/** Render a JSX element to a complete HTML string (includes <!DOCTYPE html>) */\nexport function renderHtml(element: Child): string {\n return \"<!DOCTYPE html>\" + renderToString(element);\n}\n\n/** Available themes (DaisyUI 5). Order matters — first is the default. */\nconst THEMES = [\"corporate\", \"silk\", \"dark\"] as const;\n\nconst ThemeSwitcher: FC = () => (\n <div class=\"dropdown dropdown-end\" data-frs-theme-switcher>\n <button\n type=\"button\"\n tabIndex={0}\n class=\"btn btn-sm btn-ghost text-neutral-content gap-1.5\"\n aria-label=\"Switch theme\"\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n class=\"size-4\"\n >\n <circle cx=\"12\" cy=\"12\" r=\"4\" />\n <path d=\"M12 2v2M12 20v2M4.93 4.93l1.41 1.41M17.66 17.66l1.41 1.41M2 12h2M20 12h2M4.93 19.07l1.41-1.41M17.66 6.34l1.41-1.41\" />\n </svg>\n <span class=\"text-xs hidden sm:inline\" data-frs-theme-current>\n Theme\n </span>\n </button>\n <ul\n tabIndex={0}\n class=\"dropdown-content menu menu-sm bg-base-100 text-base-content rounded-box z-50 mt-2 w-40 p-1 shadow-lg border border-base-300\"\n >\n {THEMES.map((t) => (\n <li key={t}>\n <button\n type=\"button\"\n data-frs-theme={t}\n class=\"capitalize justify-between\"\n >\n <span>{t}</span>\n <span class=\"hidden text-primary\" data-frs-theme-check={t}>\n ✓\n </span>\n </button>\n </li>\n ))}\n </ul>\n </div>\n);\n\nexport const PageShell: FC<PropsWithChildren<{ opts: PageOptions }>> = ({\n opts,\n children,\n}) => {\n const { title, breadcrumb, flash, basePath = \"/\" } = opts;\n\n return (\n <html lang=\"en\" data-theme=\"corporate\">\n <head>\n <meta charset=\"UTF-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n <title>{title} — FRS Admin</title>\n {/* Early theme hydration — runs before paint to avoid flash of unstyled theme */}\n <script\n dangerouslySetInnerHTML={{\n __html:\n \"(function(){try{var t=localStorage.getItem('frs-admin-theme');if(t){document.documentElement.setAttribute('data-theme',t);}}catch(_){}})();\",\n }}\n />\n <link\n href=\"https://cdn.jsdelivr.net/npm/daisyui@5/themes.css\"\n rel=\"stylesheet\"\n type=\"text/css\"\n />\n <link\n href=\"https://cdn.jsdelivr.net/npm/daisyui@5/daisyui.css\"\n rel=\"stylesheet\"\n type=\"text/css\"\n />\n <script src=\"https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4\" />\n </head>\n <body class=\"bg-base-200/50 min-h-screen flex flex-col\">\n {/* Navbar */}\n <div class=\"navbar bg-neutral text-neutral-content shadow-sm sticky top-0 z-50 px-6\">\n <div class=\"flex-1\">\n <a\n href={basePath}\n class=\"font-bold text-lg tracking-tight hover:opacity-80 transition-opacity\"\n >\n FRS Admin\n </a>\n </div>\n <div class=\"flex-none\">\n <ThemeSwitcher />\n </div>\n </div>\n\n <main class=\"px-6 py-8 w-full flex-1\">\n {/* Breadcrumbs */}\n {breadcrumb && breadcrumb.length > 0 && (\n <div class=\"text-sm breadcrumbs mb-4\">\n <ul>\n {breadcrumb.map((c, i) =>\n c.href ? (\n <li key={i}>\n <a href={c.href}>{c.label}</a>\n </li>\n ) : (\n <li key={i} class=\"text-base-content/60\">\n {c.label}\n </li>\n ),\n )}\n </ul>\n </div>\n )}\n\n <h1 class=\"text-2xl font-bold mb-6\">{title}</h1>\n\n {/* Flash message */}\n {flash && (\n <div\n role=\"alert\"\n class={`alert ${\n flash.type === \"success\"\n ? \"alert-success\"\n : flash.type === \"warning\"\n ? \"alert-warning\"\n : \"alert-error\"\n } mb-6`}\n >\n <span class=\"flex-1\">{flash.message}</span>\n {flash.action && (\n <a\n href={flash.action.href}\n {...(flash.action.external\n ? { target: \"_blank\", rel: \"noopener noreferrer\" }\n : {})}\n class=\"btn btn-sm btn-outline\"\n >\n {flash.action.label}\n </a>\n )}\n </div>\n )}\n\n {children}\n </main>\n\n <RightPanel basePath={basePath} />\n <ClientScript />\n </body>\n </html>\n );\n};\n\n/** Wrap a raw HTML string in the page shell (backward compat). */\nexport function renderPageJsx(content: string, opts: PageOptions): string {\n return renderHtml(\n <PageShell opts={opts}>\n <div dangerouslySetInnerHTML={{ __html: content }} />\n </PageShell>,\n );\n}\n","import { PageShell, renderHtml } from \"./shell\";\n\nexport function renderDashboardJsx(\n repos: { name: string; path: string }[],\n basePath: string,\n): string {\n return renderHtml(\n <PageShell opts={{ title: \"Repositories\", basePath }}>\n {repos.length === 0 ? (\n <div class=\"text-center py-20 text-base-content/50\">\n <p class=\"text-lg font-medium mb-1\">No repositories configured</p>\n <p class=\"text-sm\">\n Add a repository to your FRS config to get started.\n </p>\n </div>\n ) : (\n <div class=\"grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-4\">\n {repos.map((r) => (\n <a\n key={r.name}\n href={`${basePath}/${r.name}`}\n class=\"card bg-base-100 border border-base-300 hover:shadow-md no-underline transition-shadow\"\n >\n <div class=\"card-body p-5\">\n <h2 class=\"card-title text-sm font-semibold\">{r.name}</h2>\n <p class=\"text-xs text-base-content/50 font-mono\">{r.path}</p>\n </div>\n </a>\n ))}\n </div>\n )}\n </PageShell>,\n );\n}\n","import type { ColumnMeta, FilterState, WhereOp } from \"./types\";\n\n// ---------------------------------------------------------------------------\n// Operator definitions per Zod type\n// ---------------------------------------------------------------------------\n\ntype OpDef = { value: WhereOp; label: string };\n\nconst OPS_TEXT: OpDef[] = [\n { value: \"==\", label: \"=\" },\n { value: \"!=\", label: \"≠\" },\n { value: \"in\", label: \"in\" },\n { value: \"not-in\", label: \"not in\" },\n];\nconst OPS_NUMERIC: OpDef[] = [\n { value: \"==\", label: \"=\" },\n { value: \"!=\", label: \"≠\" },\n { value: \"<\", label: \"<\" },\n { value: \"<=\", label: \"≤\" },\n { value: \">\", label: \">\" },\n { value: \">=\", label: \"≥\" },\n { value: \"in\", label: \"in\" },\n { value: \"not-in\", label: \"not in\" },\n];\nconst OPS_ARRAY: OpDef[] = [\n { value: \"array-contains\", label: \"contains\" },\n { value: \"array-contains-any\", label: \"contains any\" },\n];\n\nfunction opsForType(zodType: string): OpDef[] {\n switch (zodType) {\n case \"ZodNumber\":\n case \"ZodBigInt\":\n case \"ZodDate\":\n return OPS_NUMERIC;\n case \"ZodBoolean\":\n return OPS_TEXT;\n case \"ZodArray\":\n return OPS_ARRAY;\n default:\n return OPS_TEXT;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Value input per type\n// ---------------------------------------------------------------------------\n\nconst NULL_SENTINEL = \"__null__\";\n\n/**\n * Inline JS toggle that sets the sibling input's value to \"__null__\" / restores it.\n * Keeps the input enabled so it stays in the form payload (disabled inputs are NOT\n * submitted, which would silently drop the filter). Swaps number/date inputs to\n * text temporarily because they reject the sentinel value.\n */\nfunction nullToggleScript(inputId: string): string {\n return `(function(cb){var i=document.getElementById('${inputId}');if(!i)return;if(cb.checked){i.dataset._prev=i.value;if(i.tagName==='SELECT'){var o=i.querySelector('option[value=\"${NULL_SENTINEL}\"]');if(!o){o=document.createElement('option');o.value='${NULL_SENTINEL}';o.textContent='∅ null';o.dataset._auto='1';i.appendChild(o);}o.selected=true;}else{if(i.type==='number'||i.type==='datetime-local'){i.dataset._type=i.type;i.type='text';}i.value='${NULL_SENTINEL}';i.readOnly=true;}i.style.opacity='0.55';}else{i.style.opacity='';if(i.tagName==='SELECT'){var o2=i.querySelector('option[value=\"${NULL_SENTINEL}\"][data-_auto=\"1\"]');if(o2)o2.remove();var prev=i.dataset._prev||'';for(var k=0;k<i.options.length;k++)i.options[k].selected=(i.options[k].value===prev);}else{if(i.dataset._type){i.type=i.dataset._type;delete i.dataset._type;}i.readOnly=false;i.value=(i.dataset._prev&&i.dataset._prev!=='${NULL_SENTINEL}')?i.dataset._prev:'';}}})(this)`;\n}\n\n/** Inline JS that syncs a list of enum checkboxes into a CSV hidden input. */\nfunction enumChecklistScript(hiddenId: string, group: string): string {\n return `(function(){var h=document.getElementById('${hiddenId}');var boxes=document.querySelectorAll('input[data-enum-group=\"${group}\"]');h.value=Array.from(boxes).filter(function(b){return b.checked;}).map(function(b){return b.value;}).join(',');})()`;\n}\n\nfunction NullToggle({\n inputId,\n active,\n}: {\n inputId: string;\n active: boolean;\n}) {\n return (\n <label\n class=\"flex items-center gap-1 cursor-pointer select-none text-xs text-base-content/60 hover:text-base-content border border-base-300 rounded-md px-1.5 py-1 shrink-0 leading-none h-8\"\n title=\"Filter where field IS NULL\"\n >\n <input\n type=\"checkbox\"\n class=\"checkbox checkbox-xs\"\n checked={active}\n onchange={nullToggleScript(inputId)}\n />\n <span>∅</span>\n </label>\n );\n}\n\nfunction FilterValueInput({\n col,\n active,\n}: {\n col: ColumnMeta;\n active?: FilterState;\n}) {\n const val = active?.value ?? \"\";\n const isNull = val === NULL_SENTINEL;\n const inputId = `fv_input_${col.name.replace(/\\./g, \"__\")}`;\n const op = active?.op;\n const isMultiOp = op === \"in\" || op === \"not-in\";\n\n // ── Enum / Literal columns ────────────────────────────────────────────────\n if (col.enumValues && col.enumValues.length > 0) {\n if (isMultiOp) {\n // Multi-select via checkbox group + hidden CSV input\n const selected = new Set(\n val\n .split(\",\")\n .map((s) => s.trim())\n .filter(Boolean),\n );\n const group = `eg_${col.name.replace(/\\./g, \"__\")}`;\n return (\n <div class=\"flex flex-wrap items-center gap-1 w-full\">\n <input\n type=\"hidden\"\n id={inputId}\n name={`fv_${col.name}`}\n value={val}\n />\n {col.enumValues.map((v) => (\n <label\n key={v}\n class=\"flex items-center gap-1 text-xs border border-base-300 rounded px-2 cursor-pointer hover:bg-base-200\"\n >\n <input\n type=\"checkbox\"\n class=\"checkbox checkbox-xs\"\n value={v}\n checked={selected.has(v)}\n data-enum-group={group}\n onchange={enumChecklistScript(inputId, group)}\n />\n <span>{v}</span>\n </label>\n ))}\n </div>\n );\n }\n // Single-select for ==, !=, etc.\n return (\n <div class=\"flex items-center gap-1 w-full\">\n <select\n id={inputId}\n name={`fv_${col.name}`}\n class=\"select select-sm select-bordered w-full\"\n style={isNull ? \"opacity:0.55\" : undefined}\n >\n <option value=\"\" selected={val === \"\" && !isNull}>\n —\n </option>\n {col.enumValues.map((v) => (\n <option key={v} value={v} selected={val === v}>\n {v}\n </option>\n ))}\n {col.nullable && (\n <option value={NULL_SENTINEL} data-_auto=\"1\" selected={isNull}>\n ∅ null\n </option>\n )}\n </select>\n {col.nullable && <NullToggle inputId={inputId} active={isNull} />}\n </div>\n );\n }\n\n // ── Boolean ────────────────────────────────────────────────────────────────\n if (col.zodType === \"ZodBoolean\") {\n return (\n <div class=\"flex items-center gap-1 w-full\">\n <select\n id={inputId}\n name={`fv_${col.name}`}\n class=\"select select-sm select-bordered w-full\"\n style={isNull ? \"opacity:0.55\" : undefined}\n >\n <option value=\"\" selected={val === \"\" && !isNull}>\n —\n </option>\n <option value=\"true\" selected={val === \"true\"}>\n true\n </option>\n <option value=\"false\" selected={val === \"false\"}>\n false\n </option>\n {col.nullable && (\n <option value={NULL_SENTINEL} data-_auto=\"1\" selected={isNull}>\n ∅ null\n </option>\n )}\n </select>\n {col.nullable && <NullToggle inputId={inputId} active={isNull} />}\n </div>\n );\n }\n\n // ── Array (no nullable toggle: array-contains semantics differ) ───────────\n if (col.zodType === \"ZodArray\") {\n const isAny = active?.op === \"array-contains-any\";\n return (\n <input\n id={inputId}\n type=\"text\"\n name={`fv_${col.name}`}\n value={val}\n placeholder={isAny ? \"val1, val2, …\" : \"value\"}\n class=\"input input-sm input-bordered w-full\"\n />\n );\n }\n\n // ── Numeric ────────────────────────────────────────────────────────────────\n if (col.zodType === \"ZodNumber\" || col.zodType === \"ZodBigInt\") {\n return (\n <div class=\"flex items-center gap-1 w-full\">\n <input\n id={inputId}\n type={isNull ? \"text\" : \"number\"}\n name={`fv_${col.name}`}\n value={val}\n placeholder=\"value\"\n class=\"input input-sm input-bordered w-full\"\n readOnly={isNull}\n style={isNull ? \"opacity:0.55\" : undefined}\n data-_type={isNull ? \"number\" : undefined}\n />\n {col.nullable && <NullToggle inputId={inputId} active={isNull} />}\n </div>\n );\n }\n\n // ── Date ───────────────────────────────────────────────────────────────────\n if (col.zodType === \"ZodDate\") {\n return (\n <div class=\"flex items-center gap-1 w-full\">\n <input\n id={inputId}\n type={isNull ? \"text\" : \"datetime-local\"}\n name={`fv_${col.name}`}\n value={val}\n class=\"input input-sm input-bordered w-full\"\n readOnly={isNull}\n style={isNull ? \"opacity:0.55\" : undefined}\n data-_type={isNull ? \"datetime-local\" : undefined}\n />\n {col.nullable && <NullToggle inputId={inputId} active={isNull} />}\n </div>\n );\n }\n\n // ── Default text ───────────────────────────────────────────────────────────\n return (\n <div class=\"flex items-center gap-1 w-full\">\n <input\n id={inputId}\n type=\"text\"\n name={`fv_${col.name}`}\n value={val}\n placeholder=\"value\"\n class=\"input input-sm input-bordered w-full\"\n readOnly={isNull}\n style={isNull ? \"opacity:0.55\" : undefined}\n />\n {col.nullable && <NullToggle inputId={inputId} active={isNull} />}\n </div>\n );\n}\n\n// ---------------------------------------------------------------------------\n// FilterBar\n// ---------------------------------------------------------------------------\n\nexport function FilterBar({\n action,\n columnMeta,\n activeFilters,\n isGroup,\n}: {\n /** Form action URL (list page URL, without query params) */\n action: string;\n columnMeta: ColumnMeta[];\n activeFilters: FilterState[];\n /** Whether this repo is a collection group (subcollection) */\n isGroup?: boolean;\n}) {\n const activeMap = Object.fromEntries(activeFilters.map((f) => [f.field, f]));\n const hasActive = activeFilters.length > 0;\n const needsIndexHint = activeFilters.length >= 2 || (isGroup && hasActive);\n\n // Columns that can be filtered (exclude pure-object columns)\n const filterable = columnMeta.filter(\n (c) => c.zodType !== \"ZodObject\" && c.zodType !== \"ZodRecord\",\n );\n\n return (\n <details\n class=\"collapse collapse-arrow bg-base-100 border border-base-300 rounded-box mb-6 shadow-sm\"\n open={hasActive ? true : undefined}\n >\n <summary class=\"collapse-title text-sm font-medium py-2 min-h-0\">\n Filters\n {hasActive && (\n <span class=\"badge badge-primary badge-sm ml-2\">\n {activeFilters.length} active\n </span>\n )}\n </summary>\n <div class=\"collapse-content pb-4 pt-2\">\n <form method=\"get\" action={action}>\n <div class=\"grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-4\">\n {filterable.map((col) => {\n const ops = opsForType(col.zodType);\n const active = activeMap[col.name];\n const currentOp: WhereOp = active?.op ?? ops[0]!.value;\n return (\n <div key={col.name} class=\"flex flex-col gap-1.5\">\n <label class=\"text-xs font-semibold text-base-content/60 uppercase tracking-wide\">\n {col.name}\n </label>\n <div class=\"flex gap-1.5\">\n {ops.length > 1 ? (\n <select\n name={`fo_${col.name}`}\n class=\"select select-sm select-bordered w-20 shrink-0\"\n >\n {ops.map((o) => (\n <option\n key={o.value}\n value={o.value}\n selected={o.value === currentOp}\n >\n {o.label}\n </option>\n ))}\n </select>\n ) : (\n // Single op → hidden input, no select to clutter UI\n <input\n type=\"hidden\"\n name={`fo_${col.name}`}\n value={ops[0]!.value}\n />\n )}\n <FilterValueInput col={col} active={active} />\n </div>\n </div>\n );\n })}\n </div>\n\n <div class=\"flex flex-wrap gap-2 mt-4 pt-3 border-t border-base-200 items-center\">\n <button type=\"submit\" class=\"btn btn-sm btn-primary\">\n Apply\n </button>\n {hasActive && (\n <a href={action} class=\"btn btn-sm btn-ghost\">\n Clear\n </a>\n )}\n {needsIndexHint && (\n <span class=\"text-xs text-warning ml-auto flex items-center gap-1\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n class=\"h-4 w-4\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n stroke-width=\"2\"\n d=\"M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z\"\n />\n </svg>\n {isGroup\n ? \"Collection group queries require a composite index\"\n : \"Multiple filters may require a composite index\"}\n </span>\n )}\n </div>\n </form>\n </div>\n </details>\n );\n}\n","import { PageShell, renderHtml } from \"./shell\";\nimport type { PageOptions } from \"./types\";\n\nexport function renderFormPageJsx(\n repoName: string,\n formHtml: string,\n mode: \"create\" | \"edit\",\n docId: string | null,\n basePath: string,\n flash?: PageOptions[\"flash\"],\n): string {\n const title =\n mode === \"create\"\n ? `Create ${repoName}`\n : `Edit ${repoName} / ${docId ?? \"\"}`;\n\n const crumbs =\n mode === \"create\"\n ? [\n { label: \"Repositories\", href: basePath },\n { label: repoName, href: `${basePath}/${repoName}` },\n { label: \"New document\" },\n ]\n : [\n { label: \"Repositories\", href: basePath },\n { label: repoName, href: `${basePath}/${repoName}` },\n { label: `Edit ${docId ?? \"\"}` },\n ];\n\n return renderHtml(\n <PageShell opts={{ title, breadcrumb: crumbs, basePath, flash }}>\n <div class=\"card bg-base-100 border border-base-300\">\n <div class=\"card-body p-6\">\n <div dangerouslySetInnerHTML={{ __html: formHtml }} />\n </div>\n </div>\n </PageShell>,\n );\n}\n","import type { z } from \"zod\";\nimport { CellValue } from \"./cell-value\";\nimport { FilterBar } from \"./filter-bar\";\nimport { PageShell, renderHtml } from \"./shell\";\nimport type { ExpectedType } from \"./type-check\";\nimport { expectedTypeOf, mismatchMessage, resolveAtPath } from \"./type-check\";\nimport type {\n ColumnMeta,\n FilterState,\n PageOptions,\n QueryError,\n RelationalFieldMeta,\n SortState,\n} from \"./types\";\n\n/** Shared helper — gather filter params into URLSearchParams. */\nfunction baseParams(\n filters: FilterState[],\n sort?: SortState,\n pageSize?: number,\n): URLSearchParams {\n const p = new URLSearchParams();\n for (const f of filters) {\n p.set(`fv_${f.field}`, f.value);\n p.set(`fo_${f.field}`, f.op);\n }\n if (sort) {\n p.set(\"ob\", sort.field);\n p.set(\"od\", sort.dir);\n }\n if (pageSize) p.set(\"ps\", String(pageSize));\n return p;\n}\n\n/**\n * Build a query-string for pagination (preserves filters, sort, page-size).\n */\nfunction paginationHref(\n filters: FilterState[],\n cursor: string,\n dir: \"prev\" | \"next\",\n sort?: SortState,\n pageSize?: number,\n): string {\n const p = baseParams(filters, sort, pageSize);\n p.set(\"cursor\", cursor);\n p.set(\"dir\", dir);\n return `?${p.toString()}`;\n}\n\n/**\n * Build a query-string that toggles / cycles the sort on a column.\n * Clears the cursor so the user starts from page 1 of the new order.\n */\nfunction sortHref(\n col: string,\n current: SortState | undefined,\n filters: FilterState[],\n pageSize?: number,\n): string {\n const p = baseParams(filters, undefined, pageSize);\n if (current?.field === col) {\n if (current.dir === \"asc\") {\n p.set(\"ob\", col);\n p.set(\"od\", \"desc\");\n }\n // desc → no ob/od (back to default order)\n } else {\n p.set(\"ob\", col);\n p.set(\"od\", \"asc\");\n }\n return `?${p.toString()}`;\n}\n\n/** Build a query-string that changes page size (clears cursor). */\nfunction pageSizeHref(\n newPs: number,\n filters: FilterState[],\n sort?: SortState,\n): string {\n const p = baseParams(filters, sort, newPs);\n return `?${p.toString()}`;\n}\n\nexport function renderListJsx(\n repoName: string,\n docs: Record<string, unknown>[],\n columns: string[],\n basePath: string,\n pagination: {\n hasPrev: boolean;\n hasNext: boolean;\n prevCursor: string;\n nextCursor: string;\n },\n flash?: PageOptions[\"flash\"],\n columnMeta: ColumnMeta[] = [],\n activeFilters: FilterState[] = [],\n allowDelete = false,\n relationalMeta: RelationalFieldMeta[] = [],\n sortState?: SortState,\n currentPageSize?: number,\n queryError?: QueryError,\n isGroup?: boolean,\n totalCount?: number,\n mutableFields?: string[],\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n schema?: z.ZodObject<any>,\n): string {\n const listUrl = `${basePath}/${repoName}`;\n const createUrl = `${listUrl}/create`;\n\n // Build expected-type map for type-mismatch indicator\n const expectedTypes: Record<string, ExpectedType> = {};\n if (schema) {\n for (const c of columns) {\n expectedTypes[c] = expectedTypeOf(resolveAtPath(schema, c));\n }\n }\n\n // Bulk capability: scalar mutable fields (excluding object/array/date/unknown)\n const scalarMutable = (mutableFields ?? []).filter((f) => {\n const t = expectedTypes[f] ?? expectedTypeOf(resolveAtPath(schema, f));\n return (\n t === \"string\" ||\n t === \"number\" ||\n t === \"bigint\" ||\n t === \"boolean\" ||\n t === \"enum\" ||\n t === \"literal\"\n );\n });\n const canBulkUpdate = scalarMutable.length > 0;\n const canBulkDelete = allowDelete;\n const showSelection = canBulkDelete || canBulkUpdate;\n\n // Bulk-update field metadata: gives the client what it needs to render the right input type\n const bulkFieldsMeta = scalarMutable.map((f) => {\n const sub = resolveAtPath(schema, f);\n const t = expectedTypeOf(sub);\n const meta = columnMeta.find((m) => m.name === f);\n return {\n name: f,\n type: t,\n enumValues: meta?.enumValues ?? null,\n nullable: meta?.nullable ?? false,\n };\n });\n\n return renderHtml(\n <PageShell\n opts={{\n title: repoName,\n breadcrumb: [\n { label: \"Repositories\", href: basePath },\n { label: repoName },\n ],\n basePath,\n flash,\n }}\n >\n {/* Filter panel */}\n {columnMeta.length > 0 && (\n <FilterBar\n action={listUrl}\n columnMeta={columnMeta}\n activeFilters={activeFilters}\n isGroup={isGroup}\n />\n )}\n\n {/* Query error alert (missing index or generic) */}\n {queryError && (\n <div\n role=\"alert\"\n class={`alert ${queryError.type === \"index\" ? \"alert-warning\" : \"alert-error\"} mb-6 shadow-sm`}\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n class=\"h-6 w-6 shrink-0 stroke-current\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n >\n {queryError.type === \"index\" ? (\n <path\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n stroke-width=\"2\"\n d=\"M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z\"\n />\n ) : (\n <path\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n stroke-width=\"2\"\n d=\"M10 14l2-2m0 0l2-2m-2 2l-2-2m2 2l2 2m7-2a9 9 0 11-18 0 9 9 0 0118 0z\"\n />\n )}\n </svg>\n <div class=\"flex-1\">\n <h3 class=\"font-bold\">\n {queryError.type === \"index\"\n ? \"Composite index required\"\n : \"Query failed\"}\n </h3>\n <div class=\"text-sm\">{queryError.message}</div>\n </div>\n {queryError.indexUrl && (\n <a\n href={queryError.indexUrl}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n class=\"btn btn-sm btn-outline\"\n >\n Create Index →\n </a>\n )}\n </div>\n )}\n\n {/* Toolbar */}\n <div class=\"flex flex-wrap justify-between items-center mb-4 gap-3\" data-frs-toolbar>\n <div class=\"flex items-center gap-3\">\n <span class=\"text-sm text-base-content/60\">\n {docs.length}\n {typeof totalCount === \"number\" && (\n <>\n {\" \"}of <span class=\"font-semibold text-base-content/80\">{totalCount}</span>\n </>\n )}\n {\" \"}document{(typeof totalCount === \"number\" ? totalCount : docs.length) !== 1 && \"s\"}\n </span>\n {/* Rows-per-page */}\n <div class=\"flex items-center gap-1.5 text-sm text-base-content/60\">\n <span>Rows</span>\n <div class=\"join\">\n {[10, 25, 50, 100].map((ps) => (\n <a\n key={ps}\n href={pageSizeHref(ps, activeFilters, sortState)}\n class={`join-item btn btn-xs ${currentPageSize === ps ? \"btn-active btn-primary\" : \"btn-outline\"}`}\n >\n {ps}\n </a>\n ))}\n </div>\n </div>\n </div>\n <a href={createUrl} class=\"btn btn-primary btn-sm\">\n + New\n </a>\n </div>\n\n {/* Bulk action bar (hidden until at least one row is selected) */}\n {showSelection && (\n <div\n class=\"hidden mb-3 alert alert-info py-2 px-3\"\n data-frs-bulk-bar\n data-frs-repo={repoName}\n data-frs-total={typeof totalCount === \"number\" ? String(totalCount) : \"\"}\n data-frs-page-size={String(currentPageSize ?? docs.length)}\n data-frs-allow-delete={canBulkDelete ? \"1\" : \"0\"}\n data-frs-allow-update={canBulkUpdate ? \"1\" : \"0\"}\n data-frs-fields={JSON.stringify(bulkFieldsMeta)}\n data-frs-filters={JSON.stringify(activeFilters)}\n >\n <div class=\"flex-1 text-sm\">\n <span data-frs-bulk-summary>0 selected</span>\n {typeof totalCount === \"number\" && totalCount > docs.length && (\n <button\n type=\"button\"\n class=\"ml-3 link link-primary text-sm hidden\"\n data-frs-bulk-select-all\n >\n Select all {totalCount} matching documents\n </button>\n )}\n <span class=\"hidden ml-3 italic\" data-frs-bulk-all-active>\n All {totalCount ?? \"?\"} matching documents are selected.{\" \"}\n <button\n type=\"button\"\n class=\"link\"\n data-frs-bulk-clear\n >\n Clear selection\n </button>\n </span>\n </div>\n <div class=\"flex gap-2\">\n {canBulkUpdate && (\n <button\n type=\"button\"\n class=\"btn btn-sm btn-outline\"\n data-frs-bulk-action=\"update\"\n >\n Update field…\n </button>\n )}\n {canBulkDelete && (\n <button\n type=\"button\"\n class=\"btn btn-sm btn-error btn-outline\"\n data-frs-bulk-action=\"delete\"\n >\n Delete\n </button>\n )}\n </div>\n </div>\n )}\n\n {/* Table */}\n <div\n class=\"overflow-x-auto rounded-box border border-base-300 bg-base-100\"\n data-frs-table-wrap\n >\n <table\n class=\"table table-sm w-full\"\n data-frs-table\n data-frs-repo={repoName}\n data-frs-colcount={columns.length}\n >\n <thead>\n <tr class=\"bg-base-200/50\">\n {showSelection && (\n <th class=\"w-8\">\n <input\n type=\"checkbox\"\n class=\"checkbox checkbox-xs checkbox-primary\"\n data-frs-select-page\n aria-label=\"Select all on this page\"\n />\n </th>\n )}\n {[...columns].map((c, i) => {\n const isSorted = sortState?.field === c;\n const arrow = isSorted\n ? sortState!.dir === \"asc\"\n ? \" ▲\"\n : \" ▼\"\n : \"\";\n return (\n <th\n key={i}\n class=\"text-xs font-semibold text-base-content/60 uppercase tracking-wide\"\n >\n <a\n href={sortHref(\n c,\n sortState,\n activeFilters,\n currentPageSize,\n )}\n class={`hover:text-base-content inline-flex items-center gap-0.5${isSorted ? \" text-primary font-bold\" : \"\"}`}\n >\n {c}\n {arrow}\n </a>\n </th>\n );\n })}\n {relationalMeta.map((m, i) => (\n <th\n key={`rel-${i}`}\n class=\"text-xs font-semibold text-base-content/60 uppercase tracking-wide\"\n >\n {m.column}\n </th>\n ))}\n <th class=\"text-xs font-semibold text-base-content/60 uppercase tracking-wide text-right\">\n Actions\n </th>\n </tr>\n </thead>\n <tbody>\n {docs.length === 0 ? (\n <tr>\n <td\n colspan={\n columns.length +\n relationalMeta.length +\n 1 +\n (showSelection ? 1 : 0)\n }\n class=\"text-center py-16 text-base-content/40\"\n >\n No documents found\n </td>\n </tr>\n ) : (\n docs.map((doc, rowIdx) => {\n const id = String(doc[\"docId\"] ?? doc[\"id\"] ?? \"\");\n const editUrl = `${basePath}/${repoName}/${encodeURIComponent(id)}/edit`;\n const deleteUrl = `${basePath}/${repoName}/${encodeURIComponent(id)}/delete`;\n return (\n <tr key={rowIdx} class=\"hover\" data-frs-row-id={id}>\n {showSelection && (\n <td class=\"align-middle py-2\">\n <input\n type=\"checkbox\"\n class=\"checkbox checkbox-xs checkbox-primary\"\n data-frs-select-row\n value={id}\n aria-label={`Select ${id}`}\n />\n </td>\n )}\n {columns.map((c, ci) => {\n const val = doc[c];\n const expected = expectedTypes[c];\n const mismatch = expected\n ? mismatchMessage(expected, val)\n : null;\n return (\n <td key={ci} class=\"align-top py-2\">\n <CellValue val={val} mismatch={mismatch} />\n </td>\n );\n })}\n {relationalMeta.map((m, mi) => {\n const rawVal = doc[m.key];\n if (rawVal == null || rawVal === \"\") {\n return <td key={`rel-${mi}`} class=\"py-2\" />;\n }\n const fallbackHref =\n m.type === \"one\"\n ? `${basePath}/${m.targetRepo}/${encodeURIComponent(String(rawVal))}/edit`\n : `${basePath}/${m.targetRepo}?fv_${m.targetKey}=${encodeURIComponent(String(rawVal))}`;\n return (\n <td key={`rel-${mi}`} class=\"align-middle py-2\">\n <a\n href={fallbackHref}\n class=\"btn btn-xs btn-ghost btn-outline\"\n data-frs-relation\n data-frs-rel-type={m.type}\n data-frs-rel-repo={m.targetRepo}\n data-frs-rel-fk={m.targetKey}\n data-frs-rel-val={String(rawVal)}\n data-frs-rel-label={m.column}\n >\n {m.column}\n </a>\n </td>\n );\n })}\n <td class=\"align-middle text-right whitespace-nowrap py-2\">\n <div class=\"flex gap-1 justify-end\">\n <a\n href={editUrl}\n class=\"btn btn-xs btn-outline\"\n >\n Edit\n </a>\n {allowDelete && (\n <form\n method=\"post\"\n action={deleteUrl}\n onsubmit=\"return confirm('Delete this document?')\"\n >\n <button\n type=\"submit\"\n class=\"btn btn-xs btn-error btn-outline\"\n >\n Delete\n </button>\n </form>\n )}\n </div>\n </td>\n </tr>\n );\n })\n )}\n </tbody>\n </table>\n </div>\n\n {/* Pagination */}\n {(pagination.hasPrev || pagination.hasNext) && (\n <div class=\"flex flex-col items-center mt-6 gap-2\">\n <div class=\"flex justify-center items-center gap-2\">\n {pagination.hasPrev ? (\n <a\n href={paginationHref(\n activeFilters,\n pagination.prevCursor,\n \"prev\",\n sortState,\n currentPageSize,\n )}\n class=\"btn btn-sm btn-outline\"\n >\n ← Previous\n </a>\n ) : (\n <button class=\"btn btn-sm btn-outline\" disabled>\n ← Previous\n </button>\n )}\n {pagination.hasNext ? (\n <a\n href={paginationHref(\n activeFilters,\n pagination.nextCursor,\n \"next\",\n sortState,\n currentPageSize,\n )}\n class=\"btn btn-sm btn-outline\"\n >\n Next →\n </a>\n ) : (\n <button class=\"btn btn-sm btn-outline\" disabled>\n Next →\n </button>\n )}\n </div>\n {typeof totalCount === \"number\" && (\n <div class=\"text-xs text-base-content/50\">\n {totalCount} total document{totalCount !== 1 ? \"s\" : \"\"}\n {activeFilters.length > 0 ? \" matching filters\" : \"\"}\n </div>\n )}\n </div>\n )}\n\n {/* Bulk update modal — controlled client-side */}\n {showSelection && canBulkUpdate && (\n <dialog id=\"frs-bulk-update-modal\" class=\"modal\">\n <div class=\"modal-box\">\n <h3 class=\"font-bold text-lg mb-3\">Bulk update field</h3>\n <p class=\"text-sm text-base-content/60 mb-4\" data-frs-bulk-update-summary>\n Update one field on the selected documents.\n </p>\n <form method=\"dialog\" data-frs-bulk-update-form>\n <label class=\"form-control w-full mb-3\">\n <div class=\"label\">\n <span class=\"label-text text-xs uppercase tracking-wide\">\n Field\n </span>\n </div>\n <select\n class=\"select select-bordered select-sm w-full\"\n name=\"field\"\n required\n data-frs-bulk-field-select\n >\n <option value=\"\">— Select a field —</option>\n {scalarMutable.map((f) => (\n <option key={f} value={f}>\n {f}\n </option>\n ))}\n </select>\n </label>\n <div class=\"mb-4\" data-frs-bulk-value-container>\n {/* Value input injected by client script based on field type */}\n </div>\n <div class=\"modal-action\">\n <button\n type=\"button\"\n class=\"btn btn-sm btn-ghost\"\n data-frs-bulk-update-cancel\n >\n Cancel\n </button>\n <button\n type=\"submit\"\n class=\"btn btn-sm btn-primary\"\n data-frs-bulk-update-submit\n >\n Apply\n </button>\n </div>\n </form>\n </div>\n <form method=\"dialog\" class=\"modal-backdrop\">\n <button>close</button>\n </form>\n </dialog>\n )}\n </PageShell>,\n );\n}\n","/**\n * Admin UI renderer — HTML generation functions for the admin interface.\n * All HTML generation is done via JSX in components.tsx.\n * This file preserves the original public API for backward compatibility.\n *\n * @example\n * ```typescript\n * import {\n * renderPage,\n * renderDashboard,\n * renderList,\n * renderFormPage,\n * ClientScript,\n * CSS,\n * } from \"@lpdjs/firestore-repo-service/servers/admin\";\n *\n * // Render a complete page with shell\n * const html = renderPage(\"<h1>Content</h1>\", {\n * title: \"My Admin\",\n * basePath: \"/admin\",\n * });\n *\n * // Render dashboard listing all repositories\n * const dashboard = renderDashboard(\n * [\n * { name: \"users\", path: \"users\", docCount: 150 },\n * { name: \"posts\", path: \"posts\", docCount: 42 },\n * ],\n * \"/admin\"\n * );\n *\n * // Render document list with pagination\n * const list = renderList(\n * \"users\",\n * [{ docId: \"1\", name: \"John\" }, { docId: \"2\", name: \"Jane\" }],\n * [\"docId\", \"name\"],\n * \"/admin\",\n * { hasPrev: false, hasNext: true, prevCursor: \"\", nextCursor: \"abc123\" },\n * { type: \"success\", message: \"User created!\" }, // Optional flash\n * [{ key: \"name\", label: \"Name\" }], // Column metadata\n * [{ field: \"name\", op: \"==\", value: \"John\" }], // Active filters\n * true, // Allow delete\n * [{ key: \"docId\", column: \"Posts\", targetRepo: \"posts\", targetKey: \"userId\", type: \"many\" }],\n * { field: \"name\", direction: \"asc\" }, // Sort state\n * 25, // Current page size\n * );\n *\n * // Render create/edit form page\n * const form = renderFormPage(\n * \"users\",\n * \"<form>...</form>\",\n * \"edit\",\n * \"user-123\",\n * \"/admin\",\n * { type: \"error\", message: \"Validation failed\" }\n * );\n * ```\n */\n\nexport { ClientScript } from \"./components\";\nexport type {\n ColumnMeta,\n FilterState,\n PageOptions,\n QueryError,\n RelationalFieldMeta,\n SortState,\n WhereOp,\n} from \"./components\";\n\n/** @deprecated Styles come from DaisyUI CDN — no inline CSS needed */\nexport const CSS = \"\";\n\nimport type {\n ColumnMeta,\n FilterState,\n PageOptions,\n QueryError,\n RelationalFieldMeta,\n SortState,\n} from \"./components\";\nimport {\n renderDashboardJsx,\n renderFormPageJsx,\n renderListJsx,\n renderPageJsx,\n} from \"./components\";\nimport type { z } from \"zod\";\n\nexport function renderPage(content: string, opts: PageOptions): string {\n return renderPageJsx(content, opts);\n}\n\nexport function renderDashboard(\n repos: { name: string; path: string; docCount?: number }[],\n basePath: string,\n): string {\n return renderDashboardJsx(repos, basePath);\n}\n\nexport function renderList(\n repoName: string,\n docs: Record<string, unknown>[],\n columns: string[],\n basePath: string,\n pagination: {\n hasPrev: boolean;\n hasNext: boolean;\n prevCursor: string;\n nextCursor: string;\n },\n flash?: PageOptions[\"flash\"],\n columnMeta?: ColumnMeta[],\n activeFilters?: FilterState[],\n allowDelete?: boolean,\n relationalMeta?: RelationalFieldMeta[],\n sortState?: SortState,\n currentPageSize?: number,\n queryError?: QueryError,\n isGroup?: boolean,\n totalCount?: number,\n mutableFields?: string[],\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n schema?: z.ZodObject<any>,\n): string {\n return renderListJsx(\n repoName,\n docs,\n columns,\n basePath,\n pagination,\n flash,\n columnMeta,\n activeFilters,\n allowDelete,\n relationalMeta,\n sortState,\n currentPageSize,\n queryError,\n isGroup,\n totalCount,\n mutableFields,\n schema,\n );\n}\n\nexport function renderFormPage(\n repoName: string,\n formHtml: string,\n mode: \"create\" | \"edit\",\n docId: string | null,\n basePath: string,\n flash?: PageOptions[\"flash\"],\n): string {\n return renderFormPageJsx(repoName, formHtml, mode, docId, basePath, flash);\n}\n","/**\n * Generates a Firebase Console URL to create a composite index OR a\n * single-field index exemption.\n *\n * When Firestore throws FAILED_PRECONDITION (code 9) for missing indexes,\n * the error message sometimes includes a creation link (regular collections)\n * but often does NOT include it (collection groups). This utility builds the\n * link from the query context so the admin UI can always present it.\n *\n * Two URL shapes are produced depending on the query:\n *\n * - **Composite index** (≥ 2 indexed fields, or any COLLECTION-scope multi-field\n * query). Encoded as a JSON `create_composite=` parameter under\n * `/v1/r/project/{p}/firestore/indexes`.\n *\n * - **Single-field exemption** (exactly one indexed field on a COLLECTION_GROUP\n * query — Firestore disables single-field collection-group indexes by\n * default and requires an explicit exemption). Encoded as a base64\n * protobuf `create_exemption=` parameter under\n * `/project/{p}/firestore/databases/-default-/indexes/automatic`.\n */\n\nimport type {\n FilterState,\n QueryError,\n SortState,\n WhereOp,\n} from \"./components/types\";\n\n// ── Types ────────────────────────────────────────────────────────────────────\n\ninterface IndexField {\n fieldPath: string;\n order?: \"ASCENDING\" | \"DESCENDING\";\n arrayConfig?: \"CONTAINS\";\n}\n\n// ── Helpers ──────────────────────────────────────────────────────────────────\n\nconst RANGE_OPS = new Set<WhereOp>([\"<\", \"<=\", \">\", \">=\", \"!=\"]);\nconst ARRAY_OPS = new Set<WhereOp>([\"array-contains\", \"array-contains-any\"]);\n\nfunction toIndexOrder(dir?: \"asc\" | \"desc\"): \"ASCENDING\" | \"DESCENDING\" {\n return dir === \"desc\" ? \"DESCENDING\" : \"ASCENDING\";\n}\n\n/**\n * Extract the collection ID (last path segment) from a Firestore path.\n * e.g. \"posts/{postId}/comments\" → \"comments\"\n */\nexport function collectionIdFromPath(path: string): string {\n const segments = path.split(\"/\").filter(Boolean);\n return segments[segments.length - 1] ?? path;\n}\n\n// ── Main ─────────────────────────────────────────────────────────────────────\n\n/**\n * Build a Firebase Console URL that pre-fills the composite-index creation form.\n *\n * @param projectId - GCP project ID (e.g. \"firestore-repo-services\")\n * @param collectionId - Firestore collection ID (e.g. \"posts\", \"comments\")\n * @param isGroup - Whether this is a collection group query\n * @param filters - Active filter states from the admin UI\n * @param sort - Active sort state (optional)\n * @returns - Full HTTPS URL to the Firebase Console index wizard\n */\nexport function buildIndexUrl(\n projectId: string,\n collectionId: string,\n isGroup: boolean,\n filters: FilterState[],\n sort?: SortState,\n): string {\n const fields: IndexField[] = [];\n const seen = new Set<string>();\n\n // 1. Equality filters first (order doesn't matter for equality)\n for (const f of filters) {\n if (f.op === \"==\" || f.op === \"in\" || f.op === \"not-in\") {\n if (seen.has(f.field)) continue;\n seen.add(f.field);\n fields.push({ fieldPath: f.field, order: \"ASCENDING\" });\n }\n }\n\n // 2. Array operators\n for (const f of filters) {\n if (ARRAY_OPS.has(f.op)) {\n if (seen.has(f.field)) continue;\n seen.add(f.field);\n fields.push({ fieldPath: f.field, arrayConfig: \"CONTAINS\" });\n }\n }\n\n // 3. Range / inequality filters\n for (const f of filters) {\n if (RANGE_OPS.has(f.op)) {\n if (seen.has(f.field)) continue;\n seen.add(f.field);\n // Use the sort direction if the range field matches the orderBy field\n const dir =\n sort?.field === f.field ? toIndexOrder(sort.dir) : \"ASCENDING\";\n fields.push({ fieldPath: f.field, order: dir });\n }\n }\n\n // 4. OrderBy fields not already covered by filters\n if (sort && !seen.has(sort.field)) {\n fields.push({ fieldPath: sort.field, order: toIndexOrder(sort.dir) });\n }\n\n // ── Single-field collection-group exemption ──────────────────────────────\n // Firestore disables single-field collection-group indexes by default; you\n // must create an explicit \"field exemption\". The Firebase Console wizard\n // for that uses a totally different URL (`create_exemption=`) with its own\n // protobuf shape — see buildExemptionUrl below.\n if (fields.length === 1 && isGroup) {\n return buildExemptionUrl(projectId, collectionId, fields[0]!);\n }\n\n // ── Composite index ──────────────────────────────────────────────────────\n // Firebase Console encodes composite indexes as a base64 protobuf payload\n // under `create_composite=`. Every composite index implicitly ends with\n // `__name__` as a tie-breaker, so we always append it (matches what the\n // Console itself produces).\n const lastDir =\n sort && fields.some((f) => f.fieldPath === sort.field)\n ? toIndexOrder(sort.dir)\n : \"ASCENDING\";\n fields.push({ fieldPath: \"__name__\", order: lastDir });\n\n return buildCompositeUrl(projectId, collectionId, isGroup, fields);\n}\n\n/**\n * Build a Firebase Console URL that pre-fills the composite index creation\n * form for either a regular collection or a collection-group query.\n *\n * The URL uses a base64-encoded protobuf payload (the same shape the Console\n * itself produces when you click \"Add index\" in the UI). Schema:\n *\n * message CompositeIndex {\n * string resource_path = 1; // projects/.../collectionGroups/{cg}/indexes/_\n * int32 query_scope = 2; // 1 = COLLECTION, 2 = COLLECTION_GROUP\n * repeated IndexField fields = 3;\n * }\n */\nexport function buildCompositeUrl(\n projectId: string,\n collectionId: string,\n isGroup: boolean,\n fields: IndexField[],\n databaseId: string = \"(default)\",\n): string {\n const resource = `projects/${projectId}/databases/${databaseId}/collectionGroups/${collectionId}/indexes/_`;\n\n const payload: number[] = [\n ...pbString(1, resource),\n ...pbInt(2, isGroup ? 2 : 1),\n ];\n for (const f of fields) {\n payload.push(...pbMessage(3, encodeIndexField(f)));\n }\n\n const urlDbId = databaseId === \"(default)\" ? \"-default-\" : databaseId;\n const encoded = encodeURIComponent(toBase64(payload));\n return `https://console.firebase.google.com/project/${projectId}/firestore/databases/${urlDbId}/indexes?create_composite=${encoded}`;\n}\n\n/**\n * Try to extract an index-creation URL from a Firestore error message.\n * Returns `undefined` if no URL is found.\n */\nexport function extractIndexUrl(message: string): string | undefined {\n const match = message.match(\n /https:\\/\\/console\\.firebase\\.google\\.com[^\\s)\"]*/,\n );\n return match?.[0];\n}\n\n// ── Single-field exemption URL (collection-group) ────────────────────────────\n\n/**\n * Minimal protobuf encoder for the field-exemption payload used by the\n * Firebase Console URL `?create_exemption=…`.\n *\n * Wire format (subset):\n * tag = (field_number << 3) | wire_type\n * wire types: 0 = varint, 2 = length-delimited\n *\n * Schema we encode (reverse-engineered from real Firebase Console URLs):\n * message FieldExemption {\n * string resource_path = 1; // projects/.../fields/{field}\n * int32 query_scope = 2; // 1 = COLLECTION, 2 = COLLECTION_GROUP\n * IndexConfig index = 3;\n * }\n * message IndexConfig {\n * string field_path = 1;\n * int32 order = 2; // 1 = ASCENDING, 2 = DESCENDING\n * int32 array_config = 3; // 1 = CONTAINS (mutually exclusive with order)\n * }\n */\nfunction pbVarint(n: number): number[] {\n const out: number[] = [];\n let v = n >>> 0;\n while (v >= 0x80) {\n out.push((v & 0x7f) | 0x80);\n v >>>= 7;\n }\n out.push(v & 0x7f);\n return out;\n}\n\nfunction pbTag(fieldNumber: number, wireType: 0 | 2): number {\n return (fieldNumber << 3) | wireType;\n}\n\nfunction pbString(fieldNumber: number, value: string): number[] {\n const bytes = Array.from(new TextEncoder().encode(value));\n return [pbTag(fieldNumber, 2), ...pbVarint(bytes.length), ...bytes];\n}\n\nfunction pbInt(fieldNumber: number, value: number): number[] {\n return [pbTag(fieldNumber, 0), ...pbVarint(value)];\n}\n\nfunction pbMessage(fieldNumber: number, payload: number[]): number[] {\n return [pbTag(fieldNumber, 2), ...pbVarint(payload.length), ...payload];\n}\n\n/** Encode an IndexField submessage: { field_path:1, order:2 OR array_config:3 } */\nfunction encodeIndexField(f: IndexField): number[] {\n const out: number[] = [...pbString(1, f.fieldPath)];\n if (f.arrayConfig === \"CONTAINS\") {\n out.push(...pbInt(3, 1));\n } else {\n out.push(...pbInt(2, f.order === \"DESCENDING\" ? 2 : 1));\n }\n return out;\n}\n\nfunction toBase64(bytes: number[]): string {\n // Standard base64 (no padding) — matches what Firebase Console produces.\n // Use Buffer when available (Node), otherwise fall back to btoa.\n const bin = String.fromCharCode(...bytes);\n let b64: string;\n if (typeof Buffer !== \"undefined\") {\n b64 = Buffer.from(bytes).toString(\"base64\");\n } else if (typeof btoa !== \"undefined\") {\n b64 = btoa(bin);\n } else {\n throw new Error(\"No base64 encoder available\");\n }\n return b64.replace(/=+$/, \"\");\n}\n\n/**\n * Build a Firebase Console URL that pre-fills the single-field index\n * exemption form for a collection-group query.\n */\nexport function buildExemptionUrl(\n projectId: string,\n collectionId: string,\n field: IndexField,\n databaseId: string = \"(default)\",\n): string {\n const resource = `projects/${projectId}/databases/${databaseId}/collectionGroups/${collectionId}/fields/${field.fieldPath}`;\n\n const payload: number[] = [\n ...pbString(1, resource),\n ...pbInt(2, 2), // COLLECTION_GROUP\n ...pbMessage(3, encodeIndexField(field)),\n ];\n\n // Database ID for the URL path: \"(default)\" → \"-default-\",\n // any other ID is used as-is (Firebase Console uses the bare ID).\n const urlDbId = databaseId === \"(default)\" ? \"-default-\" : databaseId;\n\n // create_exemption is base64 (URL-safe characters only — `+` and `/` are\n // valid in query string values per RFC, and Firebase accepts them, but we\n // URL-encode just to be safe).\n const encoded = encodeURIComponent(toBase64(payload));\n return `https://console.firebase.google.com/project/${projectId}/firestore/databases/${urlDbId}/indexes/automatic?create_exemption=${encoded}`;\n}\n\n// ── Project ID extraction ────────────────────────────────────────────────────\n\n/**\n * Robustly extract the GCP project ID from a Firestore reference.\n * Falls back through several known locations across firebase-admin versions\n * and finally to standard environment variables.\n */\nexport function extractProjectId(ref: unknown): string | undefined {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const r = ref as any;\n const candidates: unknown[] = [\n r?.firestore?.projectId,\n r?.firestore?.app?.options?.projectId,\n r?.firestore?._settings?.projectId,\n r?.firestore?.databaseId?.projectId,\n r?._firestore?.projectId,\n ];\n for (const c of candidates) {\n if (typeof c === \"string\" && c.length > 0) return c;\n }\n const env =\n process.env[\"GCLOUD_PROJECT\"] ||\n process.env[\"GOOGLE_CLOUD_PROJECT\"] ||\n process.env[\"FIREBASE_PROJECT_ID\"];\n return env || undefined;\n}\n\n// ── Centralized error → QueryError conversion ────────────────────────────────\n\n/**\n * Context required to build a fallback index URL when Firestore does not\n * include one in its error (typical for collection-group queries).\n */\nexport interface QueryErrorContext {\n /** Repository ref (CollectionReference / Query) used to extract project id */\n ref: unknown;\n /** Firestore collection path of the repo (e.g. \"posts/{postId}/comments\") */\n path: string;\n /** Whether the repo is a collection-group */\n isGroup: boolean;\n /** Active where filters at the time of the failed query */\n filters: FilterState[];\n /** Active orderBy state at the time of the failed query (if any) */\n sort?: SortState;\n}\n\n/**\n * Detect whether an unknown error thrown by Firestore is a missing-index\n * (`FAILED_PRECONDITION` / code 9) error.\n */\nexport function isMissingIndexError(err: unknown): boolean {\n const fe = err as { code?: number; message?: string } | null | undefined;\n if (!fe) return false;\n if (fe.code === 9) return true;\n return typeof fe.message === \"string\"\n ? fe.message.includes(\"requires an index\")\n : false;\n}\n\n/**\n * Convert a Firestore error into a typed `QueryError` with a guaranteed\n * `indexUrl` for missing-index cases (extracted from the message when\n * present, otherwise rebuilt from the query context — necessary for\n * collection-group queries where the SDK omits the link).\n *\n * Returns `null` when `err` is falsy.\n */\nexport function toQueryError(\n err: unknown,\n ctx: QueryErrorContext,\n): QueryError {\n const fe = (err ?? {}) as { code?: number; message?: string };\n const isIndex = isMissingIndexError(err);\n\n let indexUrl: string | undefined;\n if (isIndex) {\n indexUrl = fe.message ? extractIndexUrl(fe.message) : undefined;\n if (!indexUrl) {\n const projectId = extractProjectId(ctx.ref);\n if (projectId) {\n const colId = collectionIdFromPath(ctx.path);\n indexUrl = buildIndexUrl(\n projectId,\n colId,\n ctx.isGroup,\n ctx.filters,\n ctx.sort,\n );\n }\n }\n }\n\n return {\n type: isIndex ? \"index\" : \"error\",\n message: isIndex\n ? \"This query requires a composite index that does not exist yet.\"\n : (fe.message ?? \"Query failed\"),\n indexUrl,\n };\n}\n","/**\n * @module servers/admin\n *\n * Creates a static ORM admin interface served as a Firebase HTTPS function.\n *\n * Features:\n * - Dashboard listing all registered repositories\n * - Document list with cursor-based pagination\n * - Create / Edit / Delete forms generated from Zod schemas\n * - Forms map **exactly** to the repository model type\n * - Zero JavaScript framework — plain HTML + inline CSS + vanilla JS\n * - Body parsing for `application/x-www-form-urlencoded` (default HTML forms)\n * and `application/json` (API clients)\n *\n * @example\n * ```ts\n * import * as functions from \"firebase-functions\";\n * import { z } from \"zod\";\n * import { createAdminServer } from \"@lpdjs/firestore-repo-service/servers/admin\";\n *\n * const postSchema = z.object({\n * title: z.string().min(1),\n * content: z.string(),\n * status: z.enum([\"draft\", \"published\"]),\n * authorId: z.string(),\n * });\n *\n * export const adminApp = functions.https.onRequest(\n * createAdminServer({\n * basePath: \"/admin\",\n * repos: {\n * posts: { repo: repos.posts, schema: postSchema, path: \"posts\" },\n * },\n * })\n * );\n * ```\n */\n\nimport type { z } from \"zod\";\nimport type { HttpsOptions } from \"firebase-functions/v2/https\";\nimport type { ConfiguredRepository } from \"../../repositories/types\";\nimport type { FieldPath, RepositoryConfig } from \"../../shared/types\";\nimport type { FieldRole } from \"../crud/types\";\nimport type { HttpRequest, HttpResponse } from \"../http-types\";\nimport type { AdminRepoEntry, RepoRegistry } from \"./handlers\";\nimport { createAdminHandlers } from \"./handlers\";\nimport type { RelationalFieldMeta } from \"./renderer\";\nimport { type Middleware, MiniRouter } from \"./router\";\n\n// ---------------------------------------------------------------------------\n// Public option types\n// ---------------------------------------------------------------------------\n\n/**\n * Extracts the model type `T` from a `ConfiguredRepository`.\n * Two-step inference so it survives intersection types\n * (e.g. `RepositoryConfig<...> & { schema: ZodObject }` produced by\n * `createRepositoryConfig(schema)`).\n * @internal\n */\ntype RepoModelType<TRepo> =\n TRepo extends ConfiguredRepository<infer C>\n ? C extends RepositoryConfig<\n infer T,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any\n >\n ? T\n : never\n : never;\n\n/**\n * Configuration for a single repository in the admin server.\n *\n * @template TRepo - The `ConfiguredRepository` type; used to derive typed field names.\n *\n * If the repository was created with `createRepositoryConfig(schema)(config)`,\n * the `schema` field is optional — it is auto-detected from the repo.\n * Otherwise, pass `schema` explicitly.\n *\n * @example\n * ```ts\n * posts: {\n * repo: repos.posts,\n * fieldsConfig: {\n * title: [\"create\", \"mutable\", \"filterable\"],\n * content: [\"create\", \"mutable\"],\n * status: [\"create\", \"filterable\"],\n * },\n * allowDelete: true,\n * }\n * ```\n */\nexport interface AdminRepoConfig<\n TRepo extends ConfiguredRepository<any> = ConfiguredRepository<any>,\n> {\n /** The configured repository instance. Drives type inference for all other fields. */\n repo: TRepo;\n /**\n * Zod schema — optional when the repo was created with `createRepositoryConfig(schema)`.\n * Pass explicitly for repos created with the legacy `createRepositoryConfig<T>()` form.\n */\n schema?: z.ZodObject<any>;\n /** Firestore collection path (for display only) */\n path: string;\n /** Key used to identify documents (default: \"docId\") */\n documentKey?: string;\n /** Columns to display in the list view (default: all schema keys) */\n listColumns?: string[];\n /** Number of documents per page in the list view (default: 25) */\n pageSize?: number;\n /**\n * Per-field role configuration.\n * Each key is a model field (with autocomplete); the value is an array of roles.\n *\n * Roles:\n * - `\"create\"` — field is shown in the create form\n * - `\"mutable\"` — field is shown in the edit form\n * - `\"filterable\"` — field is shown in the filter bar\n *\n * If omitted, all schema fields are shown in all contexts.\n *\n * @example\n * ```ts\n * fieldsConfig: {\n * title: [\"create\", \"mutable\", \"filterable\"],\n * content: [\"create\", \"mutable\"],\n * status: [\"create\", \"filterable\"],\n * }\n * ```\n */\n fieldsConfig?: Partial<Record<FieldPath<RepoModelType<TRepo>>, readonly FieldRole[]>>;\n /**\n * Whether to show the delete button in the list view.\n * Default: false — delete is disabled unless explicitly set to true.\n */\n allowDelete?: boolean;\n /**\n * Relational action columns appended to the list table.\n * Each entry adds a dedicated button that navigates to the linked repository.\n *\n * - **type \"one\"** (e.g. `userId` on a post) → button links to the target\n * document edit page: `/{targetRepo}/{value}/edit`\n * - **type \"many\"** (e.g. `docId` on a user) → button links to the target\n * repo list filtered by value: `/{targetRepo}?fv_{targetKey}={value}`\n *\n * @example\n * ```ts\n * users: {\n * repo: repos.users,\n * relationalFields: [\n * { key: \"docId\", column: \"Posts\" }, // many → list of posts by this user\n * ]\n * }\n * posts: {\n * repo: repos.posts,\n * relationalFields: [\n * { key: \"userId\", column: \"Author\" }, // one → edit page of the user\n * ]\n * }\n * ```\n */\n relationalFields?: {\n key: keyof RepoModelType<TRepo> & string;\n column: string;\n }[];\n}\n\n/**\n * HTTP Basic Auth configuration.\n * The browser will show a native login dialog.\n */\nexport interface BasicAuthConfig {\n type: \"basic\";\n /** Realm displayed in the browser login dialog */\n realm?: string;\n username: string;\n password: string;\n}\n\n/**\n * Options for `createAdminServer`.\n *\n * Made generic so TypeScript can infer the model type of each repo entry\n * and provide autocomplete + type-checking on `fieldsConfig`.\n *\n * @template TRepos - Shape of the repos map (inferred automatically at the call site)\n */\nexport interface AdminServerOptions<\n TRepos extends Record<string, ConfiguredRepository<any>> = Record<\n string,\n ConfiguredRepository<any>\n >,\n> {\n /**\n * Base URL path of the function (e.g. \"/admin\").\n * Must match the path where the Firebase Function is mounted.\n * Default: \"/\"\n */\n basePath?: string;\n\n /**\n * Repository entries keyed by a display name.\n * TypeScript infers the model type from each `repo` field,\n * so `fieldsConfig` keys are typed to that model's field paths.\n *\n * @example\n * ```ts\n * repos: {\n * posts: {\n * repo: repos.posts,\n * fieldsConfig: {\n * title: [\"create\", \"mutable\", \"filterable\"],\n * content: [\"create\", \"mutable\"],\n * status: [\"create\", \"filterable\"],\n * },\n * },\n * }\n * ```\n */\n repos: { [K in keyof TRepos]: AdminRepoConfig<TRepos[K]> };\n\n /** Whether to parse URL-encoded bodies. Default: true. */\n parseBody?: boolean;\n\n /**\n * Authentication guard executed before every request.\n * - Pass a `BasicAuthConfig` to enable HTTP Basic Auth.\n * - Pass a `Middleware` function for custom auth logic.\n */\n auth?: BasicAuthConfig | Middleware;\n\n /**\n * Additional middleware functions executed after auth, before route handlers.\n */\n middleware?: Middleware[];\n\n /**\n * Options forwarded to `onRequest()` from `firebase-functions/v2/https`.\n * Stored on the returned handler as `.httpsOptions` for easy access.\n *\n * @example\n * ```ts\n * const handler = createAdminServer({ httpsOptions: { invoker: \"public\" }, ... });\n * export const admin = onRequest(handler.httpsOptions!, handler);\n * ```\n */\n httpsOptions?: HttpsOptions;\n}\n// ---------------------------------------------------------------------------\n\n/** Eagerly reads the raw request body as a string */\nasync function readRawBody(req: HttpRequest): Promise<string> {\n if (typeof (req as any).rawBody === \"string\")\n return (req as any).rawBody as string;\n if (Buffer.isBuffer((req as any).rawBody))\n return ((req as any).rawBody as Buffer).toString(\"utf8\");\n // Firebase Functions v2 / Cloud Run: body may already be parsed\n return \"\";\n}\n\nfunction parseUrlEncoded(body: string): Record<string, string | string[]> {\n const result: Record<string, string | string[]> = {};\n if (!body) return result;\n for (const pair of body.split(\"&\")) {\n const idx = pair.indexOf(\"=\");\n if (idx === -1) continue;\n const key = decodeURIComponent(pair.slice(0, idx).replace(/\\+/g, \" \"));\n const val = decodeURIComponent(pair.slice(idx + 1).replace(/\\+/g, \" \"));\n const existing = result[key];\n if (existing === undefined) {\n result[key] = val;\n } else if (Array.isArray(existing)) {\n existing.push(val);\n } else {\n result[key] = [existing, val];\n }\n }\n return result;\n}\n\n// ---------------------------------------------------------------------------\n// Factory\n// ---------------------------------------------------------------------------\n\n/**\n * Creates an Express-compatible request handler for the admin ORM UI.\n * Generates a complete admin interface with dashboard, lists, and CRUD forms.\n *\n * @template TRepos - Shape of the repos map (inferred automatically)\n * @param options - Admin server configuration\n * @returns Express-compatible request handler for Firebase Functions\n *\n * @example\n * ```typescript\n * // Basic admin server\n * import { onRequest } from \"firebase-functions/https\";\n * import { createAdminServer } from \"@lpdjs/firestore-repo-service/servers/admin\";\n *\n * export const admin = onRequest(\n * createAdminServer({\n * basePath: \"/admin\",\n * repos: {\n * users: {\n * repo: repos.users,\n * path: \"users\",\n * },\n * posts: {\n * repo: repos.posts,\n * path: \"posts\",\n * },\n * },\n * })\n * );\n *\n * // With HTTP Basic Auth\n * export const admin = onRequest(\n * createAdminServer({\n * basePath: \"/admin\",\n * auth: {\n * type: \"basic\",\n * realm: \"Admin Area\",\n * username: \"admin\",\n * password: process.env.ADMIN_PASSWORD!,\n * },\n * repos: { ... },\n * })\n * );\n *\n * // With custom auth middleware\n * export const admin = onRequest(\n * createAdminServer({\n * auth: async (req, res, next) => {\n * const token = req.headers?.authorization?.replace(\"Bearer \", \"\");\n * if (!token || !(await verifyToken(token))) {\n * res.status(401).send(\"Unauthorized\");\n * return;\n * }\n * next();\n * },\n * repos: { ... },\n * })\n * );\n *\n * // Full configuration with all options\n * export const admin = onRequest(\n * createAdminServer({\n * basePath: \"/admin\",\n * parseBody: true, // Parse URL-encoded bodies\n * auth: { type: \"basic\", username: \"admin\", password: \"secret\" },\n * middleware: [loggingMiddleware], // Additional middleware\n * repos: {\n * posts: {\n * repo: repos.posts,\n * path: \"posts\",\n * documentKey: \"docId\", // Field used as document ID\n * listColumns: [\"title\", \"status\", \"createdAt\"], // Columns in list\n * pageSize: 25, // Items per page in list\n * fieldsConfig: {\n * title: [\"create\", \"mutable\", \"filterable\"],\n * content: [\"create\", \"mutable\"],\n * status: [\"create\", \"mutable\", \"filterable\"],\n * userId: [\"filterable\"],\n * },\n * allowDelete: true, // Enable delete button\n * relationalFields: [ // Relation navigation buttons\n * { key: \"userId\", column: \"Author\" }, // Link to user\n * { key: \"docId\", column: \"Comments\" }, // Link to comments list\n * ],\n * },\n * users: {\n * repo: repos.users,\n * path: \"users\",\n * fieldsConfig: {\n * name: [\"create\", \"mutable\"],\n * email: [\"create\", \"mutable\", \"filterable\"],\n * isActive: [\"mutable\", \"filterable\"],\n * },\n * allowDelete: false,\n * relationalFields: [\n * { key: \"docId\", column: \"Posts\" },\n * ],\n * },\n * },\n * })\n * );\n *\n * // Routes generated automatically:\n * // GET /admin/ → Dashboard (list of repos)\n * // GET /admin/:repo → Document list with pagination\n * // GET /admin/:repo/create → Create form\n * // POST /admin/:repo/create → Submit create\n * // GET /admin/:repo/:id/edit → Edit form\n * // POST /admin/:repo/:id/edit → Submit edit\n * // POST /admin/:repo/:id/delete → Delete document\n * ```\n */\nexport function createAdminServer<\n TRepos extends Record<string, ConfiguredRepository<any>>,\n>(\n options: AdminServerOptions<TRepos>,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n): ((req: any, res: any) => Promise<void>) & { httpsOptions?: HttpsOptions } {\n const {\n basePath = \"/\",\n repos,\n parseBody = true,\n auth,\n middleware: extraMiddleware = [],\n httpsOptions,\n } = options;\n\n // Normalise basePath: no trailing slash\n const base = basePath === \"/\" ? \"\" : basePath.replace(/\\/$/, \"\");\n\n // Build the registry\n const registry: RepoRegistry = {};\n for (const [name, cfg] of Object.entries(repos)) {\n // Schema resolution: explicit cfg.schema > embedded in repo (createRepositoryConfig(schema))\n const resolvedSchema = cfg.schema ?? (cfg.repo as any).schema ?? null;\n if (!resolvedSchema) {\n throw new Error(\n `[createAdminServer] Repository \"${name}\" has no Zod schema. ` +\n `Either use createRepositoryConfig(schema)(config) or pass schema: explicitly.`,\n );\n }\n // Resolve fieldsConfig → separate arrays for runtime\n let filterableFields: string[] | undefined;\n let mutableFields: string[] | undefined;\n let createFields: string[] | undefined;\n if (cfg.fieldsConfig) {\n const fc = cfg.fieldsConfig as Record<string, readonly string[]>;\n filterableFields = [];\n mutableFields = [];\n createFields = [];\n for (const [field, roles] of Object.entries(fc)) {\n for (const role of roles) {\n if (role === \"filterable\") filterableFields.push(field);\n else if (role === \"mutable\") mutableFields.push(field);\n else if (role === \"create\") createFields.push(field);\n }\n }\n if (filterableFields.length === 0) filterableFields = undefined;\n if (mutableFields.length === 0) mutableFields = undefined;\n if (createFields.length === 0) createFields = undefined;\n }\n\n // For collection-group repos, ensure parentKeys are included in createFields\n // so the form/validation allows the user to provide them.\n const parentKeys = (() => {\n const pk = (cfg.repo as any)._parentKeys as string[] | undefined;\n return pk && pk.length > 0 ? pk : undefined;\n })();\n if (parentKeys && createFields) {\n for (const pk of parentKeys) {\n if (!createFields.includes(pk)) createFields.push(pk);\n }\n }\n\n const entry: AdminRepoEntry = {\n name,\n path: cfg.path,\n repo: cfg.repo,\n schema: resolvedSchema,\n documentKey: cfg.documentKey ?? \"docId\",\n pathKey: (cfg.repo as any)._pathKey ?? undefined,\n isGroup: !!(cfg.repo as any)._isGroup,\n parentKeys,\n createdKey: (cfg.repo as any)._createdKey ?? undefined,\n listColumns: cfg.listColumns,\n pageSize: cfg.pageSize,\n filterableFields,\n mutableFields,\n createFields,\n allowDelete: cfg.allowDelete ?? false,\n relationalMeta: (() => {\n if (!cfg.relationalFields || cfg.relationalFields.length === 0)\n return undefined;\n const repoRelKeys = (cfg.repo as any).relationalKeys ?? {};\n const meta: RelationalFieldMeta[] = [];\n for (const entry of cfg.relationalFields) {\n const rel = repoRelKeys[entry.key];\n if (rel) {\n meta.push({\n key: entry.key,\n column: entry.column,\n targetRepo: String(rel.repo),\n targetKey: String(rel.key),\n type: rel.type as \"one\" | \"many\",\n });\n }\n }\n return meta.length > 0 ? meta : undefined;\n })(),\n };\n registry[name] = entry;\n }\n\n const handlers = createAdminHandlers(registry, base);\n\n // ── Router ─────────────────────────────────────────────────────────────\n const router = new MiniRouter();\n\n // ── 1. Body-parsing middleware ──────────────────────────────────────────\n if (parseBody) {\n router.use(async (req, _res, next) => {\n const r = req as unknown as HttpRequest;\n const contentType = String(r.headers?.[\"content-type\"] ?? \"\");\n if (contentType.includes(\"application/x-www-form-urlencoded\")) {\n const raw = await readRawBody(r);\n (req as any).body = parseUrlEncoded(raw);\n } else if (\n contentType.includes(\"application/json\") &&\n typeof r.body === \"string\"\n ) {\n try {\n (req as any).body = JSON.parse(r.body as string);\n } catch {\n /* keep as string */\n }\n }\n await next();\n });\n }\n\n // ── 2. Auth middleware ──────────────────────────────────────────────────\n if (auth) {\n if (typeof auth === \"function\") {\n // Custom middleware\n router.use(auth);\n } else {\n // HTTP Basic Auth\n const realm = auth.realm ?? \"Admin\";\n const expected =\n \"Basic \" +\n Buffer.from(`${auth.username}:${auth.password}`).toString(\"base64\");\n router.use((req, res, next) => {\n const authorization = (req as any).headers?.[\"authorization\"] ?? \"\";\n if (authorization !== expected) {\n res\n .status(401)\n .set(\"WWW-Authenticate\", `Basic realm=\"${realm}\"`)\n .set(\"Content-Type\", \"text/plain\")\n .send(\"Unauthorized\");\n return;\n }\n next();\n });\n }\n }\n\n // ── 3. Extra user middleware ────────────────────────────────────────────\n for (const mw of extraMiddleware) {\n router.use(mw);\n }\n\n // ── 4. Routes ─────────────────────────────────────────────────────────────\n router.get(`${base}/`, handlers.handleDashboard);\n router.get(`${base}`, handlers.handleDashboard);\n\n // Specific routes (with literal \"_panel\" / \"_bulk\" segments) MUST come before\n // the generic \":repoName/:id/...\" routes so they take precedence.\n router.get(`${base}/:repoName/_panel`, handlers.handlePanel as any);\n router.post(`${base}/:repoName/_bulk/delete`, handlers.handleBulkDelete as any);\n router.post(`${base}/:repoName/_bulk/update`, handlers.handleBulkUpdate as any);\n\n router.get(`${base}/:repoName`, handlers.handleList);\n\n router.get(`${base}/:repoName/create`, handlers.handleCreateForm);\n router.post(`${base}/:repoName/create`, handlers.handleCreateSubmit as any);\n\n router.get(`${base}/:repoName/:id/edit`, handlers.handleEditForm as any);\n router.post(`${base}/:repoName/:id/edit`, handlers.handleEditSubmit as any);\n\n router.post(`${base}/:repoName/:id/delete`, handlers.handleDelete as any);\n\n // ── Request handler ─────────────────────────────────────────────────────\n const handler = async (req: HttpRequest, res: HttpResponse): Promise<void> => {\n await router.handle(req as any, res as any);\n };\n if (httpsOptions) (handler as any).httpsOptions = httpsOptions;\n return handler as ((req: any, res: any) => Promise<void>) & { httpsOptions?: HttpsOptions };\n}\n\n// Re-exports for convenience\nexport type { AdminRepoEntry, RepoRegistry } from \"./handlers\";\nexport { MiniRouter } from \"./router\";\nexport type { Middleware, RouteHandler } from \"./router\";\n","/**\n * HTTP route handlers for the CRUD API server.\n *\n * Routes:\n * GET /:repoName → list documents (paginated)\n * GET /:repoName/:id → get single document\n * POST /:repoName → create document\n * PUT /:repoName/:id → update document (full)\n * PATCH /:repoName/:id → update document (partial)\n * DELETE /:repoName/:id → delete document\n */\n\nimport { z } from \"zod\";\nimport {\n coerceToDate,\n getDateHandling,\n maybeNormalize,\n} from \"../../shared/date-config\";\nimport {\n isMissingIndexError,\n toQueryError,\n type QueryErrorContext,\n} from \"../admin/index-url\";\nimport type {\n ApiResponse,\n CrudRepoEntry,\n CrudRepoRegistry,\n ListResponseData,\n QueryRequestBody,\n} from \"./types\";\n\n// ---------------------------------------------------------------------------\n// Response helpers\n// ---------------------------------------------------------------------------\n\nfunction sendJson<T>(res: any, data: ApiResponse<T>, status = 200): void {\n const payload = maybeNormalize(data);\n res\n .status(status)\n .set(\"Content-Type\", \"application/json; charset=utf-8\")\n .send(JSON.stringify(payload));\n}\n\nfunction sendSuccess<T>(\n res: any,\n data: T,\n meta?: ApiResponse[\"meta\"],\n status = 200,\n): void {\n sendJson(res, { success: true, data, meta }, status);\n}\n\nfunction sendError(res: any, error: string, status = 400): void {\n sendJson(res, { success: false, error }, status);\n}\n\n/**\n * Send a structured error response. When the underlying Firestore error is a\n * missing-index (`FAILED_PRECONDITION` / code 9), include `errorType: \"index\"`\n * and an `indexUrl` pointing to the Firebase Console index-creation wizard —\n * crucial for collection-group queries where the SDK omits the link.\n */\nfunction sendQueryError(\n res: any,\n err: unknown,\n ctx: QueryErrorContext,\n fallbackMessage: string,\n verbose: boolean,\n): void {\n const qe = toQueryError(err, ctx);\n const isIndex = qe.type === \"index\";\n const status = isIndex ? 424 : 500;\n const message = isIndex\n ? qe.message\n : verbose && err instanceof Error\n ? err.message\n : fallbackMessage;\n const payload: ApiResponse = { success: false, error: message };\n if (isIndex) {\n payload.errorType = \"index\";\n if (qe.indexUrl) payload.indexUrl = qe.indexUrl;\n }\n sendJson(res, payload, status);\n}\n\n// ---------------------------------------------------------------------------\n// ID generation\n// ---------------------------------------------------------------------------\n\nconst _idChars =\n \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\";\n\n/** Generate a random 20-char alphanumeric ID matching Firestore's native format. */\nfunction generateFirestoreId(): string {\n let id = \"\";\n for (let i = 0; i < 20; i++) {\n id += _idChars.charAt(Math.floor(Math.random() * _idChars.length));\n }\n return id;\n}\n\n// ---------------------------------------------------------------------------\n// Zod schema helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Recursively wrap z.date() with z.preprocess(coerceToDate) so that ISO strings,\n * Firestore Timestamps and {_seconds,_nanoseconds} payloads are accepted as input.\n * Only invoked when global date handling mode is \"normalize\".\n */\nfunction wrapDateSchemas(schema: z.ZodType): z.ZodType {\n const def = (schema as any)._def ?? (schema as any).def;\n if (!def) return schema;\n const typeName = def.typeName ?? def.type;\n\n if (typeName === \"ZodDate\" || typeName === \"date\") {\n return z.preprocess((v) => coerceToDate(v) ?? v, schema as z.ZodDate);\n }\n if (typeName === \"ZodObject\" || typeName === \"object\") {\n const shape = (schema as z.ZodObject<any>).shape;\n const wrapped: Record<string, z.ZodType> = {};\n for (const [k, v] of Object.entries(shape)) {\n wrapped[k] = wrapDateSchemas(v as z.ZodType);\n }\n return z.object(wrapped);\n }\n if (typeName === \"ZodArray\" || typeName === \"array\") {\n const inner = def.element ?? def.type;\n if (inner) return z.array(wrapDateSchemas(inner));\n }\n if (typeName === \"ZodOptional\" || typeName === \"optional\") {\n const inner = def.innerType;\n if (inner) return wrapDateSchemas(inner).optional();\n }\n if (typeName === \"ZodNullable\" || typeName === \"nullable\") {\n const inner = def.innerType;\n if (inner) return wrapDateSchemas(inner).nullable();\n }\n if (typeName === \"ZodDefault\" || typeName === \"default\") {\n const inner = def.innerType;\n const dflt = def.defaultValue;\n if (inner) {\n const wrapped = wrapDateSchemas(inner);\n return typeof dflt === \"function\"\n ? wrapped.default(dflt())\n : wrapped.default(dflt);\n }\n }\n return schema;\n}\n\n/**\n * Pick only specified fields from a Zod schema, always excluding system-managed keys.\n *\n * - `fields` undefined or empty → all schema fields minus systemKeys\n * - `fields` with values → only those fields, minus systemKeys\n */\nfunction pickSchemaFields(\n schema: z.ZodObject<any>,\n fields: string[] | undefined,\n systemKeys: string[] = [],\n): z.ZodObject<any> {\n const shape = schema.shape;\n const picked: Record<string, z.ZodType> = {};\n\n const source = fields && fields.length > 0 ? fields : Object.keys(shape);\n\n for (const field of source) {\n if (systemKeys.includes(field)) continue;\n const topLevel = field.split(\".\")[0];\n if (topLevel && shape[topLevel]) {\n picked[topLevel] = shape[topLevel]!;\n }\n }\n\n return z.object(picked);\n}\n\n/**\n * Validate data against schema and return parsed result or error.\n */\nfunction validateData(\n schema: z.ZodObject<any>,\n data: unknown,\n fields: string[] | undefined,\n partial = false,\n systemKeys: string[] = [],\n):\n | { success: true; data: Record<string, unknown> }\n | { success: false; error: string } {\n try {\n const targetSchema = pickSchemaFields(schema, fields, systemKeys);\n const partialSchema = partial ? targetSchema.partial() : targetSchema;\n const finalSchema =\n getDateHandling() === \"normalize\"\n ? (wrapDateSchemas(partialSchema) as z.ZodObject<any>)\n : partialSchema;\n const parsed = finalSchema.parse(data);\n return { success: true, data: parsed as Record<string, unknown> };\n } catch (err) {\n if (err instanceof z.ZodError) {\n const messages = err.issues.map(\n (e) => `${e.path.join(\".\")}: ${e.message}`,\n );\n return {\n success: false,\n error: `Validation failed: ${messages.join(\", \")}`,\n };\n }\n return { success: false, error: \"Validation failed\" };\n }\n}\n\n// ---------------------------------------------------------------------------\n// Filter parsing\n// ---------------------------------------------------------------------------\n\ntype WhereOp =\n | \"==\"\n | \"!=\"\n | \"<\"\n | \"<=\"\n | \">\"\n | \">=\"\n | \"in\"\n | \"not-in\"\n | \"array-contains\"\n | \"array-contains-any\";\n\ninterface ParsedFilter {\n field: string;\n op: WhereOp;\n value: unknown;\n}\n\n/**\n * Parse query params into filter conditions.\n * Supports:\n * - field=value → field == value\n * - field__op=value → field op value (e.g., status__ne=draft → status != draft)\n * - field__in=a,b,c → field in [a, b, c]\n */\nfunction parseFilters(\n query: Record<string, string | string[] | undefined>,\n filterableFields: string[] | undefined,\n): ParsedFilter[] {\n const filters: ParsedFilter[] = [];\n const allowedFields = filterableFields ? new Set(filterableFields) : null;\n\n const opMap: Record<string, WhereOp> = {\n eq: \"==\",\n ne: \"!=\",\n lt: \"<\",\n lte: \"<=\",\n gt: \">\",\n gte: \">=\",\n in: \"in\",\n nin: \"not-in\",\n contains: \"array-contains\",\n containsAny: \"array-contains-any\",\n };\n\n for (const [key, rawVal] of Object.entries(query)) {\n if (rawVal === undefined) continue;\n\n // Skip pagination/meta params\n if (\n [\"cursor\", \"limit\", \"pageSize\", \"orderBy\", \"orderDir\", \"select\"].includes(\n key,\n )\n )\n continue;\n\n const val = Array.isArray(rawVal) ? rawVal[0] : rawVal;\n if (val === undefined || val === \"\") continue;\n\n // Parse field__op format\n const match = key.match(/^(\\w+)__(\\w+)$/);\n let field: string;\n let op: WhereOp = \"==\";\n\n if (match && match[1] && match[2]) {\n field = match[1];\n const opKey = match[2];\n if (opMap[opKey]) {\n op = opMap[opKey];\n } else {\n continue; // Unknown operator, skip\n }\n } else if (!match) {\n field = key;\n } else {\n continue; // Invalid match\n }\n\n // Check if field is filterable\n if (allowedFields && !allowedFields.has(field)) continue;\n\n // Parse value\n let parsedVal: unknown = val;\n\n // Handle \"in\" and \"not-in\" operators (comma-separated)\n if (op === \"in\" || op === \"not-in\" || op === \"array-contains-any\") {\n parsedVal = val.split(\",\").map((v) => parseValue(v.trim()));\n } else {\n parsedVal = parseValue(val);\n }\n\n filters.push({ field, op, value: parsedVal });\n }\n\n return filters;\n}\n\n/**\n * Parse a string value into appropriate type.\n */\nfunction parseValue(val: string): unknown {\n // Boolean\n if (val === \"true\") return true;\n if (val === \"false\") return false;\n if (val === \"null\") return null;\n\n // Number\n const num = Number(val);\n if (!isNaN(num) && val !== \"\") return num;\n\n // String\n return val;\n}\n\n// ---------------------------------------------------------------------------\n// Cursor serialization helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Serialize a Firestore DocumentSnapshot to a JSON-safe cursor object.\n */\nfunction serializeCursor(\n snapshot: import(\"firebase-admin/firestore\").DocumentSnapshot | undefined,\n): Record<string, unknown> | null {\n if (!snapshot) return null;\n return { docId: snapshot.id };\n}\n\n/**\n * Deserialize a cursor object back to a DocumentSnapshot.\n * Fetches the document from Firestore to get the actual snapshot.\n */\nasync function deserializeCursor(\n entry: CrudRepoEntry,\n cursor: unknown,\n): Promise<import(\"firebase-admin/firestore\").DocumentSnapshot | undefined> {\n if (!cursor || typeof cursor !== \"object\") return undefined;\n const docId = (cursor as Record<string, unknown>).docId;\n if (typeof docId !== \"string\") return undefined;\n\n try {\n // Get the collection reference from the repo\n const colRef = entry.repo\n .ref as import(\"firebase-admin/firestore\").CollectionReference;\n if (typeof colRef.doc !== \"function\") return undefined;\n const snapshot = await colRef.doc(docId).get();\n return snapshot.exists ? snapshot : undefined;\n } catch {\n return undefined;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Handlers factory\n// ---------------------------------------------------------------------------\n\nexport function createCrudHandlers(\n registry: CrudRepoRegistry,\n basePath: string,\n verbose: boolean,\n) {\n // ── Helper to get repo entry ────────────────────────────────────────────\n function getRepoEntry(\n repoName: string | undefined,\n res: any,\n ): CrudRepoEntry | null {\n if (!repoName || !registry[repoName]) {\n sendError(res, `Repository \"${repoName}\" not found`, 404);\n return null;\n }\n return registry[repoName];\n }\n\n /**\n * Extract Firestore document path args from a document's stored path.\n * e.g. \"posts/abc/comments/xyz\" → [\"abc\", \"xyz\"] (the doc-ID segments).\n */\n function extractPathArgs(\n doc: Record<string, unknown>,\n pathKey?: string,\n ): string[] | undefined {\n if (!pathKey) return undefined;\n const fullPath = doc[pathKey];\n if (typeof fullPath !== \"string\" || !fullPath) return undefined;\n const segments = fullPath.split(\"/\").filter(Boolean);\n const args: string[] = [];\n for (let i = 1; i < segments.length; i += 2) {\n args.push(segments[i]!);\n }\n return args.length > 0 ? args : undefined;\n }\n\n /**\n * Fetch a single document by its documentKey, with fallback to query\n * for collection-group repos where direct documentRef may fail.\n */\n async function fetchDocById(\n entry: CrudRepoEntry,\n docId: string,\n ): Promise<Record<string, unknown> | null> {\n const getterName = `by${entry.documentKey.charAt(0).toUpperCase()}${entry.documentKey.slice(1)}`;\n const getter = (entry.repo.get as any)[getterName];\n\n if (typeof getter === \"function\") {\n try {\n const doc = (await getter(docId)) as Record<string, unknown> | null;\n if (doc) return doc;\n } catch {\n // Direct ref may fail for subcollections — fall through to query\n }\n }\n\n const results = await entry.repo.query.by({\n where: [[entry.documentKey, \"==\", docId]],\n limit: 1,\n });\n return (results[0] as Record<string, unknown>) ?? null;\n }\n\n // ── LIST: GET /:repoName ────────────────────────────────────────────────\n async function handleList(req: any, res: any): Promise<void> {\n const params = req.params || {};\n const entry = getRepoEntry(params.repoName, res);\n if (!entry) return;\n\n // Captured for error handling (so the catch can build an index URL)\n let ctxFilters: { field: string; op: any; value: string }[] = [];\n let ctxSort: { field: string; dir: \"asc\" | \"desc\" } | undefined;\n\n try {\n const query = req.query ?? {};\n const pageSize = Math.min(\n Number(query.pageSize) || entry.pageSize,\n 100, // Max page size\n );\n const cursor = query.cursor as string | undefined;\n const direction =\n (query.direction as string)?.toLowerCase() === \"prev\" ? \"prev\" : \"next\";\n const orderBy = query.orderBy as string | undefined;\n const orderDir =\n (query.orderDir as string)?.toLowerCase() === \"desc\" ? \"desc\" : \"asc\";\n const selectStr = query.select as string | undefined;\n const select = selectStr\n ? selectStr.split(\",\").map((s) => s.trim())\n : undefined;\n\n // Parse includes (relation population)\n let includes:\n | (string | { relation: string; select?: string[] })[]\n | undefined;\n if (entry.allowedIncludes && query.includes) {\n const rawIncludes =\n typeof query.includes === \"string\"\n ? query.includes.split(\",\").map((s: string) => s.trim())\n : Array.isArray(query.includes)\n ? query.includes\n : [];\n includes = rawIncludes.filter(\n (inc: string) =>\n typeof inc === \"string\" && entry.allowedIncludes!.includes(inc),\n );\n if (includes?.length === 0) includes = undefined;\n }\n\n // Parse filters\n const filters = parseFilters(query, entry.filterableFields);\n ctxFilters = filters.map((f) => ({\n field: f.field,\n op: f.op,\n value: String(f.value ?? \"\"),\n }));\n if (orderBy) ctxSort = { field: orderBy, dir: orderDir };\n\n // Build query options\n const queryOptions: any = {\n pageSize,\n direction,\n };\n\n if (cursor) {\n try {\n const cursorObj =\n typeof cursor === \"string\" ? JSON.parse(cursor) : cursor;\n queryOptions.cursor = await deserializeCursor(entry, cursorObj);\n } catch {\n // Invalid cursor, ignore\n }\n }\n\n if (orderBy) {\n queryOptions.orderBy = [{ field: orderBy, direction: orderDir }];\n }\n\n if (filters.length > 0) {\n queryOptions.where = filters.map((f) => [f.field, f.op, f.value]);\n }\n\n if (select) {\n queryOptions.select = select as any;\n }\n\n if (includes) {\n queryOptions.include = includes as any;\n }\n\n // Execute query\n const result = await entry.repo.query.paginate(queryOptions);\n\n const responseData: ListResponseData = {\n items: result.data,\n hasNextPage: result.hasNextPage,\n hasPrevPage: result.hasPrevPage,\n nextCursor: serializeCursor(result.nextCursor),\n prevCursor: serializeCursor(result.prevCursor),\n };\n\n sendSuccess(res, responseData, {\n pageSize,\n hasMore: result.hasNextPage,\n });\n } catch (err) {\n sendQueryError(\n res,\n err,\n {\n ref: entry.repo.ref,\n path: entry.path,\n isGroup: !!entry.isGroup,\n filters: ctxFilters,\n sort: ctxSort,\n },\n \"Failed to fetch documents\",\n verbose,\n );\n }\n }\n\n // ── QUERY: POST /:repoName/query ────────────────────────────────────────\n // Advanced query endpoint supporting OR conditions, array filters, etc.\n async function handleQuery(req: any, res: any): Promise<void> {\n const params = req.params || {};\n const entry = getRepoEntry(params.repoName, res);\n if (!entry) return;\n\n // Captured for error handling (so the catch can build an index URL)\n let ctxFilters: { field: string; op: any; value: string }[] = [];\n let ctxSort: { field: string; dir: \"asc\" | \"desc\" } | undefined;\n\n try {\n const body: QueryRequestBody = req.body ?? {};\n const pageSize = Math.min(body.pageSize || entry.pageSize, 100);\n const direction = body.direction === \"prev\" ? \"prev\" : \"next\";\n\n // Capture context for index URL fallback\n if (body.where) {\n ctxFilters = body.where.map((w) => ({\n field: String(w[0]),\n op: w[1] as any,\n value: String(w[2] ?? \"\"),\n }));\n }\n if (body.orderBy && body.orderBy[0]) {\n ctxSort = {\n field: body.orderBy[0].field,\n dir: body.orderBy[0].direction === \"desc\" ? \"desc\" : \"asc\",\n };\n }\n\n // Build query options\n const queryOptions: any = {\n pageSize,\n direction,\n };\n\n // Cursor\n if (body.cursor) {\n try {\n const cursorObj =\n typeof body.cursor === \"string\"\n ? JSON.parse(body.cursor)\n : body.cursor;\n queryOptions.cursor = await deserializeCursor(entry, cursorObj);\n } catch {\n // Invalid cursor, ignore\n }\n }\n\n // Includes (relation population)\n if (entry.allowedIncludes && body.includes && body.includes.length > 0) {\n const validIncludes = body.includes.filter((inc) => {\n if (typeof inc === \"string\") {\n return entry.allowedIncludes!.includes(inc);\n }\n if (\n typeof inc === \"object\" &&\n inc !== null &&\n \"relation\" in inc &&\n typeof inc.relation === \"string\"\n ) {\n return entry.allowedIncludes!.includes(inc.relation);\n }\n return false;\n });\n if (validIncludes.length > 0) {\n queryOptions.include = validIncludes as any;\n }\n }\n\n // Where conditions (AND)\n if (body.where && body.where.length > 0) {\n // Validate filterable fields if configured\n if (entry.filterableFields) {\n const allowed = new Set(entry.filterableFields);\n const invalid = body.where.filter((w) => !allowed.has(w[0]));\n if (invalid.length > 0) {\n sendError(\n res,\n `Fields not filterable: ${invalid.map((w) => w[0]).join(\", \")}`,\n 400,\n );\n return;\n }\n }\n queryOptions.where = body.where;\n }\n\n // OR where conditions (simple)\n if (body.orWhere && body.orWhere.length > 0) {\n if (entry.filterableFields) {\n const allowed = new Set(entry.filterableFields);\n const invalid = body.orWhere.filter((w) => !allowed.has(w[0]));\n if (invalid.length > 0) {\n sendError(\n res,\n `Fields not filterable: ${invalid.map((w) => w[0]).join(\", \")}`,\n 400,\n );\n return;\n }\n }\n queryOptions.orWhere = body.orWhere;\n }\n\n // OR where groups (advanced)\n if (body.orWhereGroups && body.orWhereGroups.length > 0) {\n if (entry.filterableFields) {\n const allowed = new Set(entry.filterableFields);\n for (const group of body.orWhereGroups) {\n const invalid = group.filter((w) => !allowed.has(w[0]));\n if (invalid.length > 0) {\n sendError(\n res,\n `Fields not filterable: ${invalid.map((w) => w[0]).join(\", \")}`,\n 400,\n );\n return;\n }\n }\n }\n queryOptions.orWhereGroups = body.orWhereGroups;\n }\n\n // Order by\n if (body.orderBy && body.orderBy.length > 0) {\n queryOptions.orderBy = body.orderBy;\n }\n\n // Select\n if (body.select && body.select.length > 0) {\n queryOptions.select = body.select;\n }\n\n // Execute query\n const result = await entry.repo.query.paginate(queryOptions);\n\n const responseData: ListResponseData = {\n items: result.data,\n hasNextPage: result.hasNextPage,\n hasPrevPage: result.hasPrevPage,\n nextCursor: serializeCursor(result.nextCursor),\n prevCursor: serializeCursor(result.prevCursor),\n };\n\n sendSuccess(res, responseData, {\n pageSize,\n hasMore: result.hasNextPage,\n });\n } catch (err) {\n sendQueryError(\n res,\n err,\n {\n ref: entry.repo.ref,\n path: entry.path,\n isGroup: !!entry.isGroup,\n filters: ctxFilters,\n sort: ctxSort,\n },\n \"Failed to query documents\",\n verbose,\n );\n }\n }\n\n // ── GET: GET /:repoName/:id ─────────────────────────────────────────────\n async function handleGet(req: any, res: any): Promise<void> {\n const params = req.params || {};\n const entry = getRepoEntry(params.repoName, res);\n if (!entry) return;\n\n const id = params.id;\n if (!id) {\n sendError(res, \"Document ID required\", 400);\n return;\n }\n\n try {\n const doc = await fetchDocById(entry, id);\n\n if (!doc) {\n sendError(res, \"Document not found\", 404);\n return;\n }\n\n sendSuccess(res, doc);\n } catch (err) {\n sendQueryError(\n res,\n err,\n {\n ref: entry.repo.ref,\n path: entry.path,\n isGroup: !!entry.isGroup,\n filters: [{ field: entry.documentKey, op: \"==\", value: id }],\n },\n \"Failed to fetch document\",\n verbose,\n );\n }\n }\n\n // ── CREATE: POST /:repoName ─────────────────────────────────────────────\n async function handleCreate(req: any, res: any): Promise<void> {\n const params = req.params || {};\n const entry = getRepoEntry(params.repoName, res);\n if (!entry) return;\n\n try {\n const body = req.body ?? {};\n\n // Validate against schema\n const validation = validateData(\n entry.schema,\n body,\n entry.createFields,\n false,\n entry.systemKeys,\n );\n if (!validation.success) {\n sendError(res, validation.error, 400);\n return;\n }\n\n // Custom validation\n if (entry.validate) {\n const customError = await entry.validate(validation.data, \"create\");\n if (customError) {\n sendError(res, customError, 400);\n return;\n }\n }\n\n // Create document\n let created: any;\n if (entry.isGroup && entry.parentKeys && entry.parentKeys.length > 0) {\n // Collection-group repos cannot use create(); use set() with parent path args.\n const data: Record<string, any> = { ...validation.data };\n // set() doesn't auto-set createdKey, so inject it here\n if (entry.createdKey) {\n data[entry.createdKey] = new Date();\n }\n const missingKeys = entry.parentKeys.filter((k) => !data[k]);\n if (missingKeys.length > 0) {\n sendError(\n res,\n `Missing parent key(s) for subcollection create: ${missingKeys.join(\", \")}`,\n 400,\n );\n return;\n }\n const parentIds = entry.parentKeys.map((k) => data[k] as string);\n const docId =\n data[entry.documentKey] || generateFirestoreId();\n created = await entry.repo.set(...parentIds, docId, data);\n } else {\n created = await entry.repo.create(validation.data as any);\n }\n\n sendSuccess(res, created, undefined, 201);\n } catch (err) {\n const message =\n verbose && err instanceof Error\n ? err.message\n : \"Failed to create document\";\n sendError(res, message, 500);\n }\n }\n\n // ── UPDATE: PUT/PATCH /:repoName/:id ────────────────────────────────────\n async function handleUpdate(\n req: any,\n res: any,\n partial: boolean,\n ): Promise<void> {\n const params = req.params || {};\n const entry = getRepoEntry(params.repoName, res);\n if (!entry) return;\n\n const id = params.id;\n if (!id) {\n sendError(res, \"Document ID required\", 400);\n return;\n }\n\n try {\n const body = req.body ?? {};\n\n // Validate against schema\n const validation = validateData(\n entry.schema,\n body,\n entry.mutableFields,\n partial,\n entry.systemKeys,\n );\n if (!validation.success) {\n sendError(res, validation.error, 400);\n return;\n }\n\n // Custom validation\n if (entry.validate) {\n const customError = await entry.validate(validation.data, \"update\");\n if (customError) {\n sendError(res, customError, 400);\n return;\n }\n }\n\n // Update document — fetch first to get path args for subcollections\n const existingDoc = await fetchDocById(entry, id);\n const pathArgs =\n (existingDoc && extractPathArgs(existingDoc, entry.pathKey)) ?? [id];\n const updated = await entry.repo.update(\n ...pathArgs,\n validation.data as any,\n );\n\n sendSuccess(res, updated);\n } catch (err) {\n const message =\n verbose && err instanceof Error\n ? err.message\n : \"Failed to update document\";\n sendError(res, message, 500);\n }\n }\n\n // ── DELETE: DELETE /:repoName/:id ───────────────────────────────────────\n async function handleDelete(req: any, res: any): Promise<void> {\n const params = req.params || {};\n const entry = getRepoEntry(params.repoName, res);\n if (!entry) return;\n\n if (!entry.allowDelete) {\n sendError(res, \"Delete not allowed for this repository\", 403);\n return;\n }\n\n const id = params.id;\n if (!id) {\n sendError(res, \"Document ID required\", 400);\n return;\n }\n\n try {\n // Fetch first to get path args for subcollections\n const doc = await fetchDocById(entry, id);\n const pathArgs =\n (doc && extractPathArgs(doc, entry.pathKey)) ?? [id];\n await entry.repo.delete(...pathArgs);\n sendSuccess(res, { deleted: true });\n } catch (err) {\n const message =\n verbose && err instanceof Error\n ? err.message\n : \"Failed to delete document\";\n sendError(res, message, 500);\n }\n }\n\n // ── OPTIONS: for CORS preflight ─────────────────────────────────────────\n function handleOptions(req: any, res: any): void {\n res\n .status(204)\n .set(\n \"Access-Control-Allow-Methods\",\n \"GET, POST, PUT, PATCH, DELETE, OPTIONS\",\n )\n .set(\"Access-Control-Allow-Headers\", \"Content-Type, Authorization\")\n .set(\"Access-Control-Max-Age\", \"86400\")\n .send(\"\");\n }\n\n return {\n handleList,\n handleQuery,\n handleGet,\n handleCreate,\n handleUpdate,\n handleDelete,\n handleOptions,\n };\n}\n","/**\n * OpenAPI 3.1 specification generator for the CRUD server.\n *\n * Introspects each `CrudRepoEntry` and uses Zod 4's native `z.toJSONSchema()`\n * to produce a fully typed OpenAPI document ready for Scalar UI or codegen.\n *\n * @module servers/crud/openapi\n */\n\nimport { z } from \"zod\";\nimport type { CrudRepoEntry, CrudRepoRegistry, OpenAPISpecOptions } from \"./types\";\n\nexport type { OpenAPISpecOptions };\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/** Minimal subset of an OpenAPI 3.1 document we produce. */\nexport interface OpenAPIDocument {\n openapi: \"3.1.0\";\n info: OpenAPIInfo;\n servers?: { url: string; description?: string }[];\n paths: Record<string, Record<string, OpenAPIOperation>>;\n components: {\n schemas: Record<string, Record<string, unknown>>;\n securitySchemes?: Record<string, Record<string, unknown>>;\n };\n security?: Record<string, string[]>[];\n tags?: { name: string; description?: string }[];\n}\n\nexport interface OpenAPIInfo {\n title: string;\n version: string;\n description?: string;\n}\n\ninterface OpenAPIOperation {\n operationId: string;\n summary: string;\n tags: string[];\n parameters?: Record<string, unknown>[];\n requestBody?: Record<string, unknown>;\n responses: Record<string, Record<string, unknown>>;\n security?: Record<string, string[]>[];\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Convert a Zod schema to a JSON Schema object suitable for OpenAPI 3.1.\n *\n * Uses `unrepresentable: \"any\"` so that types Zod can't natively serialize\n * (e.g. `z.date()`, `z.bigint()`, custom classes — common with Firestore\n * Timestamps stored as `Date`) don't throw and collapse the whole schema to\n * a bare `{ type: \"object\" }`. We additionally override a few well-known\n * cases to a sensible OpenAPI representation.\n */\nfunction zodToJsonSchema(schema: z.ZodType): Record<string, unknown> {\n try {\n return z.toJSONSchema(schema, {\n target: \"openapi-3.1\",\n unrepresentable: \"any\",\n override: (ctx) => {\n const def: any = (ctx.zodSchema as any)?._zod?.def;\n if (!def) return;\n if (def.type === \"date\") {\n (ctx.jsonSchema as any).type = \"string\";\n (ctx.jsonSchema as any).format = \"date-time\";\n } else if (def.type === \"bigint\") {\n (ctx.jsonSchema as any).type = \"string\";\n (ctx.jsonSchema as any).format = \"int64\";\n }\n },\n }) as Record<string, unknown>;\n } catch (err) {\n if (typeof console !== \"undefined\" && console.warn) {\n console.warn(\n \"[generateOpenAPISpec] Failed to convert Zod schema to JSON Schema; falling back to {type:object}.\",\n err,\n );\n }\n return { type: \"object\" };\n }\n}\n\n/** Wraps a JSON Schema in a `#/components/schemas/<name>` $ref. */\nfunction schemaRef(name: string): Record<string, unknown> {\n return { $ref: `#/components/schemas/${name}` };\n}\n\n/** Standard error response schema. */\nfunction errorResponse(description: string): Record<string, unknown> {\n return {\n description,\n content: {\n \"application/json\": {\n schema: schemaRef(\"ErrorResponse\"),\n },\n },\n };\n}\n\n/** Standard success response wrapping data. */\nfunction successResponse(\n description: string,\n dataSchema: Record<string, unknown>,\n): Record<string, unknown> {\n return {\n description,\n content: {\n \"application/json\": {\n schema: {\n type: \"object\",\n properties: {\n success: { type: \"boolean\", enum: [true] },\n data: dataSchema,\n },\n required: [\"success\", \"data\"],\n },\n },\n },\n };\n}\n\n/** Build list response with pagination metadata. */\nfunction listResponse(\n itemSchema: Record<string, unknown>,\n): Record<string, unknown> {\n return {\n description: \"Paginated list of documents\",\n content: {\n \"application/json\": {\n schema: {\n type: \"object\",\n properties: {\n success: { type: \"boolean\", enum: [true] },\n data: {\n type: \"object\",\n properties: {\n items: { type: \"array\", items: itemSchema },\n nextCursor: {\n oneOf: [{ type: \"object\" }, { type: \"null\" }],\n },\n prevCursor: {\n oneOf: [{ type: \"object\" }, { type: \"null\" }],\n },\n hasNextPage: { type: \"boolean\" },\n hasPrevPage: { type: \"boolean\" },\n },\n required: [\"items\", \"hasNextPage\", \"hasPrevPage\"],\n },\n meta: {\n type: \"object\",\n properties: {\n pageSize: { type: \"integer\" },\n hasMore: { type: \"boolean\" },\n cursor: {\n oneOf: [{ type: \"string\" }, { type: \"null\" }],\n },\n },\n },\n },\n required: [\"success\", \"data\"],\n },\n },\n },\n };\n}\n\n// ---------------------------------------------------------------------------\n// Pagination / filter query parameters (shared across list endpoints)\n// ---------------------------------------------------------------------------\n\nfunction paginationParams(entry: CrudRepoEntry): Record<string, unknown>[] {\n return [\n {\n name: \"pageSize\",\n in: \"query\",\n schema: { type: \"integer\", default: entry.pageSize, maximum: 100 },\n description: \"Number of items per page\",\n },\n {\n name: \"cursor\",\n in: \"query\",\n schema: { type: \"string\" },\n description: \"Base64 pagination cursor\",\n },\n {\n name: \"orderBy\",\n in: \"query\",\n schema: { type: \"string\" },\n description: \"Field name to order by\",\n },\n {\n name: \"orderDir\",\n in: \"query\",\n schema: { type: \"string\", enum: [\"asc\", \"desc\"] },\n description: \"Order direction\",\n },\n {\n name: \"select\",\n in: \"query\",\n schema: { type: \"string\" },\n description: \"Comma-separated list of fields to return\",\n },\n ];\n}\n\nfunction filterParams(entry: CrudRepoEntry): Record<string, unknown>[] {\n const fields = entry.filterableFields ?? Object.keys(entry.schema.shape);\n const ops = [\"eq\", \"ne\", \"lt\", \"lte\", \"gt\", \"gte\", \"in\", \"nin\", \"contains\"];\n\n const params: Record<string, unknown>[] = [];\n for (const field of fields) {\n // Direct equality filter: ?field=value\n params.push({\n name: field,\n in: \"query\",\n schema: { type: \"string\" },\n description: `Filter by ${field} (equality)`,\n });\n // Operator filters: ?field__op=value\n for (const op of ops) {\n params.push({\n name: `${field}__${op}`,\n in: \"query\",\n schema: { type: \"string\" },\n description: `Filter ${field} with operator ${op}`,\n });\n }\n }\n return params;\n}\n\n// ---------------------------------------------------------------------------\n// Query body schema (POST /query)\n// ---------------------------------------------------------------------------\n\nfunction queryBodySchema(): Record<string, unknown> {\n return {\n type: \"object\",\n properties: {\n where: {\n type: \"array\",\n items: {\n type: \"array\",\n items: {},\n minItems: 3,\n maxItems: 3,\n },\n description: \"AND conditions: [field, operator, value][]\",\n },\n orWhere: {\n type: \"array\",\n items: {\n type: \"array\",\n items: {},\n minItems: 3,\n maxItems: 3,\n },\n description: \"Simple OR conditions (each independently OR'd)\",\n },\n orWhereGroups: {\n type: \"array\",\n items: {\n type: \"array\",\n items: {\n type: \"array\",\n items: {},\n minItems: 3,\n maxItems: 3,\n },\n },\n description: \"Advanced OR groups (AND within, OR across groups)\",\n },\n orderBy: {\n type: \"array\",\n items: {\n type: \"object\",\n properties: {\n field: { type: \"string\" },\n direction: { type: \"string\", enum: [\"asc\", \"desc\"] },\n },\n required: [\"field\"],\n },\n },\n select: {\n type: \"array\",\n items: { type: \"string\" },\n description: \"Fields to select (projection)\",\n },\n pageSize: {\n type: \"integer\",\n maximum: 100,\n description: \"Number of items per page\",\n },\n cursor: {\n oneOf: [{ type: \"string\" }, { type: \"object\" }],\n description: \"Pagination cursor\",\n },\n direction: {\n type: \"string\",\n enum: [\"next\", \"prev\"],\n description: \"Pagination direction\",\n },\n includes: {\n type: \"array\",\n items: {\n oneOf: [\n { type: \"string\" },\n {\n type: \"object\",\n properties: {\n relation: { type: \"string\" },\n select: { type: \"array\", items: { type: \"string\" } },\n },\n required: [\"relation\"],\n },\n ],\n },\n description: \"Relations to include (populate)\",\n },\n },\n };\n}\n\n// ---------------------------------------------------------------------------\n// Path generation per repo entry\n// ---------------------------------------------------------------------------\n\nfunction buildPathsForEntry(\n entry: CrudRepoEntry,\n base: string,\n modelSchemaName: string,\n createSchemaName: string | null,\n updateSchemaName: string | null,\n): Record<string, Record<string, OpenAPIOperation>> {\n const paths: Record<string, Record<string, OpenAPIOperation>> = {};\n const tag = entry.name;\n const collectionPath = `${base}/${entry.name}`;\n const documentPath = `${collectionPath}/{${entry.documentKey}}`;\n\n const idParam = {\n name: entry.documentKey,\n in: \"path\",\n required: true,\n schema: { type: \"string\" },\n description: `Unique document identifier`,\n };\n\n // ── GET /:repo → list ──────────────────────────────────────────────\n paths[collectionPath] = {\n get: {\n operationId: `list${capitalize(entry.name)}`,\n summary: `List ${entry.name} (paginated)`,\n tags: [tag],\n parameters: [...paginationParams(entry), ...filterParams(entry)],\n responses: {\n \"200\": listResponse(schemaRef(modelSchemaName)),\n \"500\": errorResponse(\"Internal server error\"),\n },\n },\n // ── POST /:repo → create ────────────────────────────────────────\n post: {\n operationId: `create${capitalize(entry.name)}`,\n summary: `Create a ${singularize(entry.name)}`,\n tags: [tag],\n requestBody: {\n required: true,\n content: {\n \"application/json\": {\n schema: schemaRef(createSchemaName ?? modelSchemaName),\n },\n },\n },\n responses: {\n \"201\": successResponse(\"Document created\", schemaRef(modelSchemaName)),\n \"400\": errorResponse(\"Validation error\"),\n \"500\": errorResponse(\"Internal server error\"),\n },\n },\n };\n\n // ── POST /:repo/query → advanced query ────────────────────────────\n paths[`${collectionPath}/query`] = {\n post: {\n operationId: `query${capitalize(entry.name)}`,\n summary: `Query ${entry.name} with advanced filters`,\n tags: [tag],\n requestBody: {\n required: true,\n content: {\n \"application/json\": {\n schema: schemaRef(\"QueryRequestBody\"),\n },\n },\n },\n responses: {\n \"200\": listResponse(schemaRef(modelSchemaName)),\n \"400\": errorResponse(\"Invalid query\"),\n \"500\": errorResponse(\"Internal server error\"),\n },\n },\n };\n\n // ── Single-document paths ────────────────────────────────────────\n const docOps: Record<string, OpenAPIOperation> = {};\n\n // GET /:repo/:id\n docOps.get = {\n operationId: `get${capitalize(singularize(entry.name))}`,\n summary: `Get a single ${singularize(entry.name)}`,\n tags: [tag],\n parameters: [idParam],\n responses: {\n \"200\": successResponse(\"Document found\", schemaRef(modelSchemaName)),\n \"404\": errorResponse(\"Document not found\"),\n \"500\": errorResponse(\"Internal server error\"),\n },\n };\n\n // PUT /:repo/:id (full update)\n docOps.put = {\n operationId: `update${capitalize(singularize(entry.name))}`,\n summary: `Update a ${singularize(entry.name)} (full replace)`,\n tags: [tag],\n parameters: [idParam],\n requestBody: {\n required: true,\n content: {\n \"application/json\": {\n schema: schemaRef(updateSchemaName ?? modelSchemaName),\n },\n },\n },\n responses: {\n \"200\": successResponse(\"Document updated\", schemaRef(modelSchemaName)),\n \"400\": errorResponse(\"Validation error\"),\n \"404\": errorResponse(\"Document not found\"),\n \"500\": errorResponse(\"Internal server error\"),\n },\n };\n\n // PATCH /:repo/:id (partial update)\n docOps.patch = {\n operationId: `patch${capitalize(singularize(entry.name))}`,\n summary: `Partially update a ${singularize(entry.name)}`,\n tags: [tag],\n parameters: [idParam],\n requestBody: {\n required: true,\n content: {\n \"application/json\": {\n schema: {\n allOf: [schemaRef(updateSchemaName ?? modelSchemaName)],\n description: \"All fields are optional for partial updates\",\n },\n },\n },\n },\n responses: {\n \"200\": successResponse(\"Document patched\", schemaRef(modelSchemaName)),\n \"400\": errorResponse(\"Validation error\"),\n \"404\": errorResponse(\"Document not found\"),\n \"500\": errorResponse(\"Internal server error\"),\n },\n };\n\n // DELETE /:repo/:id (only if allowDelete)\n if (entry.allowDelete) {\n docOps.delete = {\n operationId: `delete${capitalize(singularize(entry.name))}`,\n summary: `Delete a ${singularize(entry.name)}`,\n tags: [tag],\n parameters: [idParam],\n responses: {\n \"200\": successResponse(\"Document deleted\", {\n type: \"object\",\n properties: { id: { type: \"string\" } },\n }),\n \"404\": errorResponse(\"Document not found\"),\n \"500\": errorResponse(\"Internal server error\"),\n },\n };\n }\n\n paths[documentPath] = docOps;\n\n return paths;\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Generate a full OpenAPI 3.1 specification from a `CrudRepoRegistry`.\n *\n * Uses Zod 4's native `z.toJSONSchema()` to convert each repo's schema\n * into a JSON Schema component, then assembles paths for the standard\n * CRUD endpoints.\n *\n * @example\n * ```ts\n * import { generateOpenAPISpec } from \"@lpdjs/firestore-repo-service/servers/crud\";\n *\n * const spec = generateOpenAPISpec(registry, \"/api\", {\n * title: \"My API\",\n * version: \"1.0.0\",\n * servers: [{ url: \"https://my-api.example.com\" }],\n * auth: \"bearer\",\n * });\n *\n * // Write to file\n * fs.writeFileSync(\"openapi.json\", JSON.stringify(spec, null, 2));\n * ```\n */\nexport function generateOpenAPISpec(\n registry: CrudRepoRegistry,\n basePath: string,\n options: OpenAPISpecOptions = {},\n): OpenAPIDocument {\n const {\n title = \"CRUD API\",\n version = \"1.0.0\",\n description,\n servers,\n auth = false,\n } = options;\n\n const base = basePath === \"/\" ? \"\" : basePath.replace(/\\/$/, \"\");\n\n // ── Components: schemas ───────────────────────────────────────────\n const schemas: Record<string, Record<string, unknown>> = {};\n const allPaths: Record<string, Record<string, OpenAPIOperation>> = {};\n const tags: { name: string; description?: string }[] = [];\n\n // Shared schemas\n schemas[\"ErrorResponse\"] = {\n type: \"object\",\n properties: {\n success: { type: \"boolean\", enum: [false] },\n error: { type: \"string\" },\n },\n required: [\"success\", \"error\"],\n };\n\n schemas[\"QueryRequestBody\"] = queryBodySchema();\n\n // Per-repo schemas & paths\n for (const [name, entry] of Object.entries(registry)) {\n const modelName = capitalize(singularize(name));\n const createName = `${modelName}Create`;\n const updateName = `${modelName}Update`;\n\n // Full model schema\n schemas[modelName] = zodToJsonSchema(entry.schema);\n\n // Helper: build a filtered shape (respects systemKeys + field list)\n const buildShape = (\n fieldList: string[] | undefined,\n ): Record<string, z.ZodType> => {\n const source =\n fieldList && fieldList.length > 0\n ? fieldList\n : Object.keys(entry.schema.shape);\n const shape: Record<string, z.ZodType> = {};\n for (const f of source) {\n const top = f.split(\".\")[0];\n if (top && entry.schema.shape[top] && !entry.systemKeys.includes(top)) {\n shape[top] = entry.schema.shape[top];\n }\n }\n return shape;\n };\n\n // Create schema\n let createSchemaName: string | null = null;\n const createShape = buildShape(entry.createFields);\n if (Object.keys(createShape).length > 0) {\n schemas[createName] = zodToJsonSchema(z.object(createShape));\n createSchemaName = createName;\n }\n\n // Update schema\n let updateSchemaName: string | null = null;\n const updateShape = buildShape(entry.mutableFields);\n if (Object.keys(updateShape).length > 0) {\n schemas[updateName] = zodToJsonSchema(z.object(updateShape));\n updateSchemaName = updateName;\n }\n\n // Build paths\n const entryPaths = buildPathsForEntry(\n entry,\n base,\n modelName,\n createSchemaName,\n updateSchemaName,\n );\n Object.assign(allPaths, entryPaths);\n\n // Tag\n tags.push({\n name,\n description: `Operations on ${name} (collection: ${entry.path})`,\n });\n }\n\n // ── Security ──────────────────────────────────────────────────────\n const securitySchemes: Record<string, Record<string, unknown>> = {};\n let security: Record<string, string[]>[] | undefined;\n\n if (auth === \"basic\") {\n securitySchemes[\"basicAuth\"] = {\n type: \"http\",\n scheme: \"basic\",\n };\n security = [{ basicAuth: [] }];\n } else if (auth === \"bearer\") {\n securitySchemes[\"bearerAuth\"] = {\n type: \"http\",\n scheme: \"bearer\",\n bearerFormat: \"JWT\",\n };\n security = [{ bearerAuth: [] }];\n }\n\n // ── Assemble ──────────────────────────────────────────────────────\n const doc: OpenAPIDocument = {\n openapi: \"3.1.0\",\n info: {\n title,\n version,\n ...(description ? { description } : {}),\n },\n ...(servers && servers.length > 0 ? { servers } : {}),\n paths: allPaths,\n components: {\n schemas,\n ...(Object.keys(securitySchemes).length > 0 ? { securitySchemes } : {}),\n },\n ...(security ? { security } : {}),\n tags,\n };\n\n return doc;\n}\n\n// ---------------------------------------------------------------------------\n// Utility\n// ---------------------------------------------------------------------------\n\nfunction capitalize(s: string): string {\n return s.charAt(0).toUpperCase() + s.slice(1);\n}\n\n/** Naive singularize: strip trailing 's' for display. */\nfunction singularize(s: string): string {\n if (s.endsWith(\"ies\")) return s.slice(0, -3) + \"y\";\n if (s.endsWith(\"ses\") || s.endsWith(\"xes\") || s.endsWith(\"zes\"))\n return s.slice(0, -2);\n if (s.endsWith(\"s\") && !s.endsWith(\"ss\")) return s.slice(0, -1);\n return s;\n}\n","/**\n * @module servers/crud\n *\n * Creates a REST API server for CRUD operations on Firestore repositories.\n *\n * Features:\n * - RESTful endpoints for List, Get, Create, Update, Delete\n * - Request validation using Zod schemas\n * - Cursor-based pagination\n * - Query filtering with operators (eq, ne, lt, gt, in, etc.)\n * - Field selection\n * - CORS support\n * - Configurable auth (Basic Auth or custom middleware)\n *\n * @example\n * ```ts\n * import * as functions from \"firebase-functions\";\n * import { z } from \"zod\";\n * import { createCrudServer } from \"@lpdjs/firestore-repo-service/servers/crud\";\n *\n * const postSchema = z.object({\n * title: z.string().min(1),\n * content: z.string(),\n * status: z.enum([\"draft\", \"published\"]),\n * authorId: z.string(),\n * });\n *\n * export const api = functions.https.onRequest(\n * createCrudServer({\n * basePath: \"/api\",\n * repos: {\n * posts: {\n * repo: repos.posts,\n * schema: postSchema,\n * path: \"posts\",\n * fieldsConfig: {\n * status: [\"filterable\"],\n * authorId: [\"filterable\"],\n * },\n * allowDelete: true,\n * },\n * },\n * })\n * );\n * ```\n *\n * ## API Endpoints\n *\n * | Method | Path | Description |\n * |--------|-------------------|--------------------------|\n * | GET | /:repo | List documents (paginated) |\n * | GET | /:repo/:id | Get single document |\n * | POST | /:repo | Create document |\n * | PUT | /:repo/:id | Update document (full) |\n * | PATCH | /:repo/:id | Update document (partial)|\n * | DELETE | /:repo/:id | Delete document |\n *\n * ## Query Parameters (GET list)\n *\n * | Param | Description |\n * |------------|------------------------------------------|\n * | pageSize | Number of items per page (max 100) |\n * | cursor | Base64 pagination cursor |\n * | orderBy | Field to order by |\n * | orderDir | Order direction (asc/desc) |\n * | select | Comma-separated fields to return |\n * | field | Filter by field (field=value) |\n * | field__op | Filter with operator (field__gt=10) |\n *\n * ## Filter Operators\n *\n * | Suffix | Firestore Op | Example |\n * |-------------|-------------------|-----------------------|\n * | (none) | == | status=active |\n * | __eq | == | status__eq=active |\n * | __ne | != | status__ne=draft |\n * | __lt | < | age__lt=18 |\n * | __lte | <= | age__lte=18 |\n * | __gt | > | age__gt=18 |\n * | __gte | >= | age__gte=18 |\n * | __in | in | status__in=a,b,c |\n * | __nin | not-in | status__nin=x,y |\n * | __contains | array-contains | tags__contains=news |\n */\n\nimport { MiniRouter } from \"../admin/router\";\nimport type { HttpsOptions } from \"firebase-functions/v2/https\";\nimport type { HttpRequest, HttpResponse } from \"../http-types\";\nimport type { ConfiguredRepository } from \"../../repositories/types\";\nimport { createCrudHandlers } from \"./handlers\";\nimport { generateOpenAPISpec, type OpenAPIDocument } from \"./openapi\";\nimport type {\n CrudRepoEntry,\n CrudRepoRegistry,\n CrudServerOptions,\n} from \"./types\";\n\n// ---------------------------------------------------------------------------\n// Scalar API docs HTML template\n// ---------------------------------------------------------------------------\n\n/** Returns a self-contained HTML page using Scalar to render the spec. */\nfunction scalarDocsHtml(title: string, specUrl: string): string {\n return `<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"utf-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n <title>${title}</title>\n</head>\n<body>\n <script id=\"api-reference\" data-url=\"${specUrl}\"></script>\n <script src=\"https://cdn.jsdelivr.net/npm/@scalar/api-reference\"></script>\n</body>\n</html>`;\n}\n\n/**\n * Compute the URL prefix for links / spec URLs.\n * In the Firebase emulator the /{project}/{region}/{functionTarget} prefix\n * is visible in URLs but stripped before the handler receives `req.url`.\n * In production Firebase proxy strips it automatically.\n */\nfunction getLinkBase(req: any, staticBasePath: string): string {\n const base = staticBasePath === \"/\" ? \"\" : staticBasePath.replace(/\\/$/, \"\");\n\n if (process.env[\"FUNCTIONS_EMULATOR\"] === \"true\") {\n const project =\n process.env[\"GCLOUD_PROJECT\"] ??\n process.env[\"GOOGLE_CLOUD_PROJECT\"] ??\n \"demo-project\";\n const region = process.env[\"FUNCTION_REGION\"] ?? \"us-central1\";\n const target = process.env[\"FUNCTION_TARGET\"] ?? \"\";\n return `/${project}/${region}/${target}${base}`;\n }\n\n // Cloud Functions v2: K_SERVICE = function name = URL path prefix.\n // Only add it when accessed via cloudfunctions.net (not custom domains).\n // Cloud Run (Gen 2) lowercases service names, but K_SERVICE may still\n // carry the original mixed-case export name — normalise to lowercase\n // so that generated links match the canonical URL.\n const service = process.env[\"K_SERVICE\"];\n const host: string = req?.hostname ?? req?.headers?.[\"host\"] ?? \"\";\n if (service && host.includes(\"cloudfunctions.net\")) {\n return `/${service.toLowerCase()}${base}`;\n }\n\n return base;\n}\n\n// ---------------------------------------------------------------------------\n// Body parser\n// ---------------------------------------------------------------------------\n\n/** Eagerly reads the raw request body as a string */\nasync function readRawBody(req: HttpRequest): Promise<string> {\n if (typeof (req as any).rawBody === \"string\")\n return (req as any).rawBody as string;\n if (Buffer.isBuffer((req as any).rawBody))\n return ((req as any).rawBody as Buffer).toString(\"utf8\");\n return \"\";\n}\n\n// ---------------------------------------------------------------------------\n// Factory\n// ---------------------------------------------------------------------------\n\n/**\n * Creates an Express-compatible request handler for a REST CRUD API.\n *\n * @template TRepos - Shape of the repos map (inferred automatically)\n * @param options - CRUD server configuration\n * @returns Express-compatible request handler for Firebase Functions\n *\n * @example\n * ```typescript\n * // Basic CRUD server\n * import { onRequest } from \"firebase-functions/https\";\n * import { createCrudServer } from \"@lpdjs/firestore-repo-service/servers/crud\";\n *\n * export const api = onRequest(\n * createCrudServer({\n * basePath: \"/api\",\n * repos: {\n * users: {\n * repo: repos.users,\n * path: \"users\",\n * fieldsConfig: {\n * name: [\"create\", \"mutable\"],\n * email: [\"create\", \"mutable\", \"filterable\"],\n * isActive: [\"filterable\"],\n * },\n * allowDelete: false,\n * },\n * posts: {\n * repo: repos.posts,\n * path: \"posts\",\n * fieldsConfig: {\n * status: [\"filterable\"],\n * userId: [\"filterable\"],\n * },\n * allowDelete: true,\n * },\n * },\n * })\n * );\n *\n * // With authentication\n * export const api = onRequest(\n * createCrudServer({\n * basePath: \"/api\",\n * auth: {\n * type: \"basic\",\n * username: \"api\",\n * password: process.env.API_PASSWORD!,\n * },\n * repos: { ... },\n * })\n * );\n *\n * // With custom auth middleware\n * export const api = onRequest(\n * createCrudServer({\n * auth: async (req, res, next) => {\n * const token = req.headers?.authorization?.replace(\"Bearer \", \"\");\n * if (!token || !(await verifyToken(token))) {\n * res.status(401).json({ success: false, error: \"Unauthorized\" });\n * return;\n * }\n * next();\n * },\n * repos: { ... },\n * })\n * );\n *\n * // With custom validation\n * export const api = onRequest(\n * createCrudServer({\n * repos: {\n * posts: {\n * repo: repos.posts,\n * path: \"posts\",\n * validate: async (data, operation) => {\n * if (operation === \"create\" && !data.title) {\n * return \"Title is required\";\n * }\n * return undefined;\n * },\n * },\n * },\n * })\n * );\n * ```\n */\nexport function createCrudServer<\n TRepos extends Record<string, ConfiguredRepository<any>>,\n>(\n options: CrudServerOptions<TRepos>,\n): ((req: any, res: any) => Promise<void>) & { spec: () => OpenAPIDocument; httpsOptions?: HttpsOptions } {\n const {\n basePath = \"/\",\n repos,\n parseBody = true,\n auth,\n middleware: extraMiddleware = [],\n verbose = false,\n httpsOptions,\n } = options;\n\n // Normalise basePath: no trailing slash\n const base = basePath === \"/\" ? \"\" : basePath.replace(/\\/$/, \"\");\n\n // Build the registry\n const registry: CrudRepoRegistry = {};\n for (const [name, cfg] of Object.entries(repos)) {\n // Schema resolution: explicit cfg.schema > embedded in repo (createRepositoryConfig(schema))\n const resolvedSchema = cfg.schema ?? (cfg.repo as any).schema ?? null;\n if (!resolvedSchema) {\n throw new Error(\n `[createCrudServer] Repository \"${name}\" has no Zod schema. ` +\n `Either use createRepositoryConfig(schema)(config) or pass schema: explicitly.`,\n );\n }\n\n // Resolve fieldsConfig → separate arrays for runtime\n let filterableFields: string[] | undefined;\n let mutableFields: string[] | undefined;\n let createFields: string[] | undefined;\n if (cfg.fieldsConfig) {\n const fc = cfg.fieldsConfig as Record<string, readonly string[]>;\n filterableFields = [];\n mutableFields = [];\n createFields = [];\n for (const [field, roles] of Object.entries(fc)) {\n for (const role of roles) {\n if (role === \"filterable\") filterableFields.push(field);\n else if (role === \"mutable\") mutableFields.push(field);\n else if (role === \"create\") createFields.push(field);\n }\n }\n if (filterableFields.length === 0) filterableFields = undefined;\n if (mutableFields.length === 0) mutableFields = undefined;\n if (createFields.length === 0) createFields = undefined;\n }\n\n // For collection-group repos, ensure parentKeys are included in createFields\n // so the validation accepts them in the request body.\n const parentKeys = (() => {\n const pk = (cfg.repo as any)._parentKeys as string[] | undefined;\n return pk && pk.length > 0 ? pk : undefined;\n })();\n if (parentKeys && createFields) {\n for (const pk of parentKeys) {\n if (!createFields.includes(pk)) createFields.push(pk);\n }\n }\n\n const entry: CrudRepoEntry = {\n name,\n path: cfg.path,\n repo: cfg.repo,\n schema: resolvedSchema,\n systemKeys: (cfg.repo as any)._systemKeys ?? [cfg.documentKey ?? \"docId\"],\n documentKey: cfg.documentKey ?? \"docId\",\n pathKey: (cfg.repo as any)._pathKey ?? undefined,\n isGroup: !!(cfg.repo as any)._isGroup,\n parentKeys,\n createdKey: (cfg.repo as any)._createdKey ?? undefined,\n pageSize: cfg.pageSize ?? 25,\n filterableFields,\n mutableFields,\n createFields,\n allowDelete: cfg.allowDelete ?? false,\n allowedIncludes: cfg.allowedIncludes as string[] | undefined,\n validate: cfg.validate as CrudRepoEntry[\"validate\"],\n };\n\n registry[name] = entry;\n }\n\n const handlers = createCrudHandlers(registry, base, verbose);\n\n // ── OpenAPI spec (cached) ─────────────────────────────────────────────\n const openapi = options.openapi;\n const openapiOpts = openapi && typeof openapi === \"object\" ? openapi : {};\n let _specCache: OpenAPIDocument | null = null;\n function getSpec(): OpenAPIDocument {\n if (!_specCache) {\n const authType =\n auth && typeof auth !== \"function\"\n ? (\"basic\" as const)\n : auth\n ? (\"bearer\" as const)\n : false;\n _specCache = generateOpenAPISpec(registry, base, {\n ...openapiOpts,\n auth: openapiOpts.auth ?? authType,\n });\n }\n return _specCache;\n }\n\n // ── Router ─────────────────────────────────────────────────────────────\n const router = new MiniRouter();\n\n // ── CORS middleware ─────────────────────────────────────────────────────\n router.use((req, res, next) => {\n res.set(\"Access-Control-Allow-Origin\", \"*\");\n res.set(\"Access-Control-Allow-Credentials\", \"true\");\n next();\n });\n\n // ── 1. Body-parsing middleware ──────────────────────────────────────────\n if (parseBody) {\n router.use(async (req, _res, next) => {\n const r = req as unknown as HttpRequest;\n const contentType = String(r.headers?.[\"content-type\"] ?? \"\");\n if (contentType.includes(\"application/json\")) {\n if (typeof r.body === \"string\") {\n try {\n (req as any).body = JSON.parse(r.body);\n } catch {\n /* keep as string */\n }\n } else if (Buffer.isBuffer((req as any).rawBody)) {\n try {\n const raw = await readRawBody(r);\n (req as any).body = JSON.parse(raw);\n } catch {\n /* keep as is */\n }\n }\n }\n await next();\n });\n }\n\n // ── 2. Auth middleware ──────────────────────────────────────────────────\n if (auth) {\n if (typeof auth === \"function\") {\n // Custom middleware\n router.use(auth);\n } else {\n // HTTP Basic Auth\n const realm = auth.realm ?? \"API\";\n const expected =\n \"Basic \" +\n Buffer.from(`${auth.username}:${auth.password}`).toString(\"base64\");\n router.use((req, res, next) => {\n const authorization = (req as any).headers?.[\"authorization\"] ?? \"\";\n if (authorization !== expected) {\n res\n .status(401)\n .set(\"WWW-Authenticate\", `Basic realm=\"${realm}\"`)\n .set(\"Content-Type\", \"application/json\")\n .send(JSON.stringify({ success: false, error: \"Unauthorized\" }));\n return;\n }\n next();\n });\n }\n }\n\n // ── 3. Extra user middleware ────────────────────────────────────────────\n for (const mw of extraMiddleware) {\n router.use(mw);\n }\n\n // ── 4. Routes ─────────────────────────────────────────────────────────────\n\n // ── OpenAPI spec & docs endpoints (before auth so they're public) ────\n if (openapi !== false) {\n const specPath = `${base}/__spec.json`;\n const docsPath = `${base}/__docs`;\n\n router.get(specPath, (_req: any, res: any) => {\n const spec = getSpec();\n res\n .status(200)\n .set(\"Content-Type\", \"application/json; charset=utf-8\")\n .send(JSON.stringify(spec, null, 2));\n });\n\n router.get(docsPath, (req: any, res: any) => {\n // Rebuild spec URL with the correct prefix for the current context\n // (emulator, Cloud Functions URL, or custom domain).\n const specUrl = getLinkBase(req, base) + \"/__spec.json\";\n const html = scalarDocsHtml(openapiOpts.title ?? \"CRUD API\", specUrl);\n res\n .status(200)\n .set(\"Content-Type\", \"text/html; charset=utf-8\")\n .send(html);\n });\n }\n\n // OPTIONS for CORS preflight\n router.use((req, res, next) => {\n if (req.method === \"OPTIONS\") {\n handlers.handleOptions(req, res);\n return;\n }\n next();\n });\n\n // List: GET /:repoName\n router.get(`${base}/:repoName`, handlers.handleList);\n\n // Query: POST /:repoName/query (advanced filtering with body)\n router.post(`${base}/:repoName/query`, handlers.handleQuery);\n\n // Get: GET /:repoName/:id\n router.get(`${base}/:repoName/:id`, handlers.handleGet);\n\n // Create: POST /:repoName\n router.post(`${base}/:repoName`, handlers.handleCreate);\n\n // Update (full): PUT /:repoName/:id\n router.put(`${base}/:repoName/:id`, (req: any, res: any) =>\n handlers.handleUpdate(req, res, false),\n );\n\n // Update (partial): PATCH /:repoName/:id\n router.patch(`${base}/:repoName/:id`, (req: any, res: any) =>\n handlers.handleUpdate(req, res, true),\n );\n\n // Delete: DELETE /:repoName/:id\n router.delete(`${base}/:repoName/:id`, handlers.handleDelete);\n\n // ── Request handler ─────────────────────────────────────────────────────\n const handler = async (\n req: HttpRequest,\n res: HttpResponse,\n ): Promise<void> => {\n await router.handle(req as any, res as any);\n };\n\n // Attach spec getter so users can call server.spec() programmatically\n (handler as any).spec = getSpec;\n if (httpsOptions) (handler as any).httpsOptions = httpsOptions;\n\n return handler as ((req: any, res: any) => Promise<void>) & {\n /** Return the generated OpenAPI 3.1 document. */\n spec: () => OpenAPIDocument;\n /** Options to forward to `onRequest()` from firebase-functions. */\n httpsOptions?: HttpsOptions;\n };\n}\n\n// Re-exports for convenience\nexport { generateOpenAPISpec } from \"./openapi\";\nexport type { OpenAPIDocument, OpenAPISpecOptions } from \"./openapi\";\nexport type {\n ApiResponse,\n BasicAuthConfig,\n CrudRepoConfig,\n CrudRepoEntry,\n CrudRepoRegistry,\n CrudServerOptions,\n FieldRole,\n ListResponseData,\n Middleware,\n QueryRequestBody,\n RepoFieldPath,\n RepoRelationKeys,\n UserFieldPath,\n} from \"./types\";\n","/**\n * @module servers/create-servers\n *\n * Unified factory that pre-binds a repository mapping to all server builders\n * (admin UI, CRUD REST API, Firestore→SQL sync admin).\n *\n * The goal is purely DX: instead of repeating `repo: repos.posts` for each\n * entry — and losing strong inference on `keyof Model` paths because the key\n * `\"posts\"` is decoupled from the value `repos.posts` — the bound builders\n * derive the repo (and thus the model type) from the registry key:\n *\n * ```ts\n * const servers = createServers(repos, { onRequest });\n *\n * export const admin = servers.admin({\n * basePath: \"/admin\",\n * repos: {\n * posts: { path: \"posts\", fieldsConfig: { title: [\"create\"] } },\n * // ^ typed against repos.posts model\n * },\n * });\n *\n * export const api = servers.crud({\n * basePath: \"/api\",\n * repos: {\n * posts: { path: \"posts\", allowDelete: true },\n * },\n * });\n *\n * export const { functions } = servers.sync({\n * deps: { firestoreTriggers, pubsubHandler, pubsub },\n * adapter,\n * admin: { auth: { type: \"basic\", username: \"admin\", password: \"secret\" } },\n * });\n * ```\n *\n * When `onRequest` is provided to `createServers`, the admin and CRUD\n * builders return a ready-to-export Cloud Function (wrapped with the\n * caller-provided `onRequest`). Otherwise they return the raw handler.\n */\n\nimport type { HttpsOptions, onRequest as OnRequestFn } from \"firebase-functions/v2/https\";\nimport type { ConfiguredRepository } from \"../repositories/types\";\nimport type { FirestoreSyncConfig } from \"../sync/types\";\nimport { createFirestoreSync } from \"../sync/create-sync\";\nimport {\n type AdminRepoConfig,\n type AdminServerOptions,\n createAdminServer,\n} from \"./admin/index\";\nimport { createCrudServer } from \"./crud/index\";\nimport type { CrudRepoConfig, CrudServerOptions } from \"./crud/types\";\n\n// ---------------------------------------------------------------------------\n// Bound option types\n// ---------------------------------------------------------------------------\n\n/** Per-repo admin config with `repo` omitted (auto-bound from the registry key). */\nexport type BoundAdminRepoConfig<TRepo extends ConfiguredRepository<any>> = Omit<\n AdminRepoConfig<TRepo>,\n \"repo\"\n>;\n\n/** Per-repo CRUD config with `repo` omitted (auto-bound from the registry key). */\nexport type BoundCrudRepoConfig<TRepo extends ConfiguredRepository<any>> = Omit<\n CrudRepoConfig<TRepo>,\n \"repo\"\n>;\n\n/**\n * Admin server options for the bound builder.\n * `repos` becomes a partial record so callers can expose a subset of the\n * underlying registry, and each entry omits `repo` (injected from the key).\n */\nexport interface BoundAdminServerOptions<\n TRepos extends Record<string, ConfiguredRepository<any>>,\n> extends Omit<AdminServerOptions<TRepos>, \"repos\"> {\n repos: { [K in keyof TRepos]?: BoundAdminRepoConfig<TRepos[K]> };\n}\n\n/** CRUD server options for the bound builder. */\nexport interface BoundCrudServerOptions<\n TRepos extends Record<string, ConfiguredRepository<any>>,\n> extends Omit<CrudServerOptions<TRepos>, \"repos\"> {\n repos: { [K in keyof TRepos]?: BoundCrudRepoConfig<TRepos[K]> };\n}\n\n/**\n * Sync config for the bound builder — identical to `FirestoreSyncConfig`\n * but the top-level `repoMapping` argument is supplied by `createServers`.\n */\nexport type BoundFirestoreSyncConfig<TRepos extends Record<string, any>> =\n FirestoreSyncConfig<TRepos>;\n\n// ---------------------------------------------------------------------------\n// Shared deps\n// ---------------------------------------------------------------------------\n\n/** Optional dependencies shared across every server. */\nexport interface CreateServersDeps {\n /**\n * `onRequest` from `firebase-functions/v2/https`. When provided, the\n * admin/CRUD builders return a ready-to-export Cloud Function instead of\n * the raw handler. Also forwarded to the sync admin (so the bundled\n * `adminsync` Cloud Function is generated automatically).\n */\n onRequest?: typeof OnRequestFn;\n /**\n * Default `httpsOptions` applied to every server. Per-server options\n * override these defaults.\n */\n httpsOptions?: HttpsOptions;\n}\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\ntype RawHandler = ((req: any, res: any) => any) & {\n httpsOptions?: HttpsOptions;\n};\n\nfunction maybeWrap<H extends RawHandler>(\n handler: H,\n deps: CreateServersDeps,\n): H | ReturnType<typeof OnRequestFn> {\n if (!deps.onRequest) return handler;\n const opts = handler.httpsOptions ?? deps.httpsOptions;\n return opts ? deps.onRequest(opts, handler) : deps.onRequest(handler);\n}\n\nfunction injectRepos<\n TRepos extends Record<string, ConfiguredRepository<any>>,\n TBoundCfg,\n>(\n repos: TRepos,\n bound: { [K in keyof TRepos]?: TBoundCfg },\n serverName: string,\n): Record<string, TBoundCfg & { repo: ConfiguredRepository<any> }> {\n const out: Record<string, any> = {};\n for (const [name, cfg] of Object.entries(bound)) {\n if (!cfg) continue;\n const repo = repos[name as keyof TRepos];\n if (!repo) {\n throw new Error(\n `[createServers.${serverName}] Unknown repo \"${name}\" — not present in the registry passed to createServers().`,\n );\n }\n out[name] = { ...(cfg as object), repo } as any;\n }\n return out;\n}\n\n// ---------------------------------------------------------------------------\n// Factory\n// ---------------------------------------------------------------------------\n\n/**\n * Pre-binds a repository mapping to all server builders.\n *\n * @template TRepos - Repository registry; inferred at the call site.\n * @param repos - The repository mapping (e.g. result of `createRepositoryMapping`).\n * @param deps - Optional shared deps (notably `onRequest` for auto-wrapping).\n *\n * @example\n * ```ts\n * import { onRequest } from \"firebase-functions/v2/https\";\n * import { createServers } from \"@lpdjs/firestore-repo-service/servers\";\n *\n * const servers = createServers(repos, { onRequest });\n *\n * export const admin = servers.admin({\n * basePath: \"/admin\",\n * repos: {\n * posts: { path: \"posts\", allowDelete: true },\n * users: { path: \"users\" },\n * },\n * });\n * ```\n */\nexport function createServers<\n TRepos extends Record<string, ConfiguredRepository<any>>,\n>(repos: TRepos, deps: CreateServersDeps = {}) {\n return {\n /**\n * Build the admin UI handler with `repo` auto-injected from each registry key.\n * Returns a Cloud Function when `onRequest` was passed to `createServers`,\n * otherwise the raw HTTP handler.\n */\n admin(options: BoundAdminServerOptions<TRepos>) {\n const fullRepos = injectRepos<TRepos, BoundAdminRepoConfig<any>>(\n repos,\n options.repos,\n \"admin\",\n );\n const handler = createAdminServer({\n ...options,\n repos: fullRepos as AdminServerOptions<TRepos>[\"repos\"],\n httpsOptions: options.httpsOptions ?? deps.httpsOptions,\n });\n return maybeWrap(handler, deps);\n },\n\n /**\n * Build the CRUD REST API handler with `repo` auto-injected from each\n * registry key. Returns a Cloud Function when `onRequest` was passed to\n * `createServers`, otherwise the raw HTTP handler (which still exposes\n * `.spec()` and `.httpsOptions` on the raw form).\n */\n crud(options: BoundCrudServerOptions<TRepos>) {\n const fullRepos = injectRepos<TRepos, BoundCrudRepoConfig<any>>(\n repos,\n options.repos,\n \"crud\",\n );\n const handler = createCrudServer({\n ...options,\n repos: fullRepos as CrudServerOptions<TRepos>[\"repos\"],\n httpsOptions: options.httpsOptions ?? deps.httpsOptions,\n });\n return maybeWrap(handler, deps);\n },\n\n /**\n * Build the Firestore→SQL sync pipeline using the bound registry.\n * Forwards the shared `onRequest` to the sync admin config so the\n * bundled `adminsync` Cloud Function is auto-generated.\n */\n sync(config: BoundFirestoreSyncConfig<TRepos>) {\n const merged: BoundFirestoreSyncConfig<TRepos> = { ...config };\n if (deps.onRequest && merged.admin && !merged.admin.onRequest) {\n merged.admin = {\n ...merged.admin,\n onRequest: deps.onRequest as any,\n httpsOptions: merged.admin.httpsOptions ?? deps.httpsOptions,\n };\n }\n return createFirestoreSync(repos, merged);\n },\n };\n}\n","/* eslint-disable @typescript-eslint/no-empty-object-type */\n\nimport type { Firestore } from \"firebase-admin/firestore\";\nimport type { z } from \"zod\";\n\n// ============================================\n// Re-exports from modules\n// ============================================\n\n// Shared types\nexport type {\n ExtractDocumentRefSignature,\n ExtractUpdateSignature,\n FieldPath,\n GetOptions,\n GetResult,\n QueryOptions,\n RelationalKeys,\n RelationConfig,\n RepositoryConfig,\n WhereClause,\n} from \"./shared/types\";\n\n// Pagination\nexport {\n applyQueryOptions as applyPaginationQueryOptions,\n createPaginationIterator,\n executePaginatedQuery,\n} from \"./pagination\";\nexport type { PaginationOptions, PaginationResult } from \"./pagination\";\n\n// Query pagination with include\nexport type {\n IncludeConfig,\n PaginationWithIncludeOptions,\n} from \"./methods/query\";\n\n// Populate options\nexport type { PopulateOptions } from \"./methods/relations\";\n\n// Query builder\nexport { buildAndExecuteQuery } from \"./query-builder\";\n\n// Repository types\nexport type {\n ConfiguredRepository,\n GenerateGetMethods,\n GenerateQueryMethods,\n IncludeConfigTyped,\n PaginationWithIncludeOptionsTyped,\n PopulateOptionsTyped,\n} from \"./repositories/types\";\n\n// Date handling (global)\nexport {\n coerceToDate,\n getDateHandling,\n normalizeTimestamps,\n setDateHandling,\n} from \"./shared/date-config\";\nexport type { DateHandlingMode } from \"./shared/date-config\";\n\n// ============================================\n// Imports for internal use\n// ============================================\n\nimport { createRepository } from \"./repositories/factory\";\nimport type { ConfiguredRepository } from \"./repositories/types\";\nimport type { RelationConfig, RepositoryConfig } from \"./shared/types\";\n\n// ============================================\n// Repository Configuration Helper\n// ============================================\n\n/**\n * Helper to create a typed repository configuration with literal type preservation.\n * Uses currying pattern to allow type parameter inference.\n *\n * **IMPORTANT:** A Zod schema is required. The model type is automatically\n * inferred from the schema via `z.infer<TSchema>`.\n *\n * @template TSchema - Zod schema that defines the model structure\n * @param schema - The Zod schema for validation and type inference\n * @returns Builder function that accepts repository configuration\n *\n * @example\n * ```typescript\n * const userSchema = z.object({\n * docId: z.string(),\n * email: z.string().email(),\n * name: z.string(),\n * isActive: z.boolean(),\n * });\n *\n * const postSchema = z.object({\n * docId: z.string(),\n * userId: z.string(),\n * title: z.string(),\n * content: z.string(),\n * status: z.enum([\"draft\", \"published\"]),\n * });\n *\n * const mapping = {\n * users: createRepositoryConfig(userSchema)({\n * path: \"users\",\n * isGroup: false,\n * foreignKeys: [\"docId\", \"email\"] as const,\n * queryKeys: [\"isActive\"] as const,\n * documentKey: \"docId\",\n * refCb: (db, docId: string) => db.collection(\"users\").doc(docId),\n * }),\n * posts: createRepositoryConfig(postSchema)({\n * path: \"posts\",\n * isGroup: false,\n * foreignKeys: [\"docId\", \"userId\"] as const,\n * queryKeys: [\"status\"] as const,\n * documentKey: \"docId\",\n * refCb: (db, docId: string) => db.collection(\"posts\").doc(docId),\n * }),\n * };\n *\n * const repos = createRepositoryMapping(db, mapping);\n * ```\n */\nexport function createRepositoryConfig<TSchema extends z.ZodObject<any>>(\n schema: TSchema,\n): <\n const TForeignKeys extends readonly (keyof z.infer<TSchema>)[],\n const TQueryKeys extends readonly (keyof z.infer<TSchema>)[],\n const TIsGroup extends boolean,\n const TDocumentKey extends keyof z.infer<TSchema>,\n const TPathKey extends keyof z.infer<TSchema> | undefined = undefined,\n const TCreatedKey extends keyof z.infer<TSchema> | undefined = undefined,\n const TUpdatedKey extends keyof z.infer<TSchema> | undefined = undefined,\n const THistoryEnabled extends boolean = false,\n TRefCb = undefined,\n>(config: {\n path: string;\n isGroup: TIsGroup;\n foreignKeys: TForeignKeys;\n queryKeys: TQueryKeys;\n documentKey: TDocumentKey;\n pathKey?: TPathKey;\n createdKey?: TCreatedKey;\n updatedKey?: TUpdatedKey;\n refCb: TRefCb;\n /**\n * Optional change-history configuration. Set `enabled: true` to expose\n * `repo.history.*` and have `createHistoryTriggers(...)` register a trigger\n * for this repo.\n */\n history?: import(\"./history/types\").HistoryConfigForModel<\n z.infer<TSchema>\n > & { enabled: THistoryEnabled };\n}) => RepositoryConfig<\n z.infer<TSchema>,\n TForeignKeys,\n TQueryKeys,\n TIsGroup,\n TRefCb,\n {},\n TDocumentKey,\n TPathKey,\n TCreatedKey,\n TUpdatedKey,\n THistoryEnabled\n> & { schema: TSchema } {\n return (config: any): any => ({\n ...config,\n schema,\n type: null as any,\n documentRef: null as any,\n update: null as any,\n });\n}\n\n/**\n * Helper type to resolve a single relation configuration\n * Extracts the target model type from the mapping\n */\ntype ResolveRelation<TMapping, TRelationConfig> = TRelationConfig extends {\n repo: infer R;\n key: infer FK;\n type: infer RT;\n}\n ? R extends keyof TMapping\n ? TMapping[R] extends { type: infer TTarget }\n ? RelationConfig<R & string, FK & string, RT & (\"one\" | \"many\"), TTarget>\n : never\n : never\n : never;\n\n/**\n * Helper to add relations to a repository mapping with full type validation\n * Validates that repo names and foreign keys exist in the mapping\n * @template TMapping - The complete repository mapping for validation\n * @template TRelations - Relations configuration with strict typing\n * @param mapping - The base repository mapping\n * @param relations - Relations configuration for each repository\n * @returns Updated mapping with relations and full type safety\n * @example\n * ```typescript\n * const mapping = {\n * users: createRepositoryConfig<UserModel>()({ ... }),\n * posts: createRepositoryConfig<PostModel>()({ ... }),\n * };\n *\n * const mappingWithRelations = buildRepositoryRelations(mapping, {\n * posts: {\n * userId: { repo: \"users\", key: \"docId\", type: \"one\" as const }\n * }\n * });\n *\n * const repos = createRepositoryMapping(db, mappingWithRelations);\n * ```\n */\nexport function buildRepositoryRelations<\n TMapping extends Record<string, any>,\n const TRelations extends {\n [K in keyof TMapping]?: TMapping[K] extends RepositoryConfig<\n infer T,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any\n >\n ? {\n [RK in keyof T]?: {\n [R in keyof TMapping]: TMapping[R] extends RepositoryConfig<\n infer TTargetModel,\n infer TForeignKeys,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any\n >\n ? {\n repo: R;\n key: TForeignKeys[number];\n type: \"one\" | \"many\";\n }\n : never;\n }[keyof TMapping];\n }\n : never;\n },\n>(\n mapping: TMapping,\n relations: TRelations,\n): {\n [K in keyof TMapping]: K extends keyof TRelations\n ? TMapping[K] extends RepositoryConfig<\n infer T,\n infer TForeignKeys,\n infer TQueryKeys,\n infer TIsGroup,\n infer TRefCb,\n any,\n infer TDocumentKey,\n infer TPathKey,\n infer TCreatedKey,\n infer TUpdatedKey,\n infer THistoryEnabled\n >\n ? RepositoryConfig<\n T,\n TForeignKeys,\n TQueryKeys,\n TIsGroup,\n TRefCb,\n {\n [RK in keyof TRelations[K]]: ResolveRelation<\n TMapping,\n TRelations[K][RK]\n >;\n },\n TDocumentKey,\n TPathKey,\n TCreatedKey,\n TUpdatedKey,\n THistoryEnabled\n >\n : TMapping[K]\n : TMapping[K];\n} {\n const result: any = { ...mapping };\n\n for (const repoKey in relations) {\n if (relations[repoKey]) {\n result[repoKey] = {\n ...mapping[repoKey],\n relationalKeys: relations[repoKey],\n };\n }\n }\n\n return result as any;\n}\n\n// ============================================\n// Repository Mapping Class\n// ============================================\n\n/**\n * Repository mapping class that manages Firestore repositories with type safety\n * @template T - Record of repository configurations\n */\nexport class RepositoryMapping<T extends Record<string, any>> {\n private db: Firestore;\n private repositoryCache = new Map<string, any>();\n private mapping: T;\n private allRepositories: Record<string, any> = {};\n\n /**\n * Creates a new RepositoryMapping instance\n * @param db - Firestore instance from firebase-admin\n * @param mapping - Repository configuration mapping\n */\n constructor(db: Firestore, mapping: T) {\n this.db = db;\n this.mapping = mapping;\n // Pre-initialize all repositories to allow cross-references\n this.initializeRepositories();\n }\n\n /**\n * Initialize all repositories in two passes to handle circular dependencies\n * @private\n */\n private initializeRepositories() {\n // Pass 1: Create all repositories without populate methods\n for (const key of Object.keys(this.mapping)) {\n this.allRepositories[key] = createRepository(\n this.db,\n this.mapping[key],\n {},\n );\n }\n\n // Pass 2: Update all repositories with complete allRepositories map\n for (const key of Object.keys(this.mapping)) {\n this.allRepositories[key] = createRepository(\n this.db,\n this.mapping[key],\n this.allRepositories,\n );\n }\n }\n\n /**\n * Gets a repository (already initialized)\n * @template K - Repository key\n * @param key - Repository identifier\n * @returns Configured repository instance\n */\n getRepository<K extends keyof T>(key: K): ConfiguredRepository<T[K]> {\n return this.allRepositories[key as string];\n }\n}\n\n// ============================================\n// Repository Mapping Factory\n// ============================================\n\n/**\n * Helper function to create a RepositoryMapping instance with full typing\n * @template T - Record of repository configurations\n * @param db - Firestore instance from firebase-admin\n * @param mapping - Repository configurations\n * @returns RepositoryMapping instance with repository access via getters\n * @example\n * ```typescript\n * import * as admin from 'firebase-admin';\n *\n * admin.initializeApp();\n * const db = admin.firestore();\n *\n * const repos = createRepositoryMapping(db, {\n * users: createRepositoryConfig<UserModel>()({\n * path: \"users\",\n * isGroup: false,\n * foreignKeys: [\"docId\", \"email\"] as const,\n * queryKeys: [\"isActive\"] as const,\n * refCb: (db, docId: string) => db.collection(\"users\").doc(docId),\n * }),\n * });\n *\n * // Access repositories directly\n * const user = await repos.users.get.byDocId(\"123\");\n * ```\n */\nexport function createRepositoryMapping<T extends Record<string, any>>(\n db: Firestore,\n mapping: T,\n): { [K in keyof T]: ConfiguredRepository<T[K]> } {\n const instance = new RepositoryMapping(db, mapping);\n\n const mappingKeys = Object.keys(mapping);\n\n // Proxy exposes only the mapping keys as own properties,\n // hiding internal class fields (db, repositoryCache, etc.)\n return new Proxy(instance, {\n get(target, prop) {\n if (typeof prop === \"string\" && prop in mapping) {\n return target.getRepository(prop as keyof T);\n }\n return (target as any)[prop];\n },\n ownKeys() {\n return mappingKeys;\n },\n getOwnPropertyDescriptor(_target, prop) {\n if (typeof prop === \"string\" && prop in mapping) {\n return { configurable: true, enumerable: true, writable: false };\n }\n return undefined;\n },\n }) as any;\n}\n\n// ============================================\n// Servers (admin ORM & CRUD API)\n// ============================================\nexport {\n createServers,\n MiniRouter,\n} from \"./servers/index\";\nexport type {\n AdminRepoConfig,\n AdminRepoEntry,\n AdminServerOptions,\n ApiResponse,\n BasicAuthConfig,\n BoundAdminRepoConfig,\n BoundAdminServerOptions,\n BoundCrudRepoConfig,\n BoundCrudServerOptions,\n BoundFirestoreSyncConfig,\n CreateServersDeps,\n CrudRepoConfig,\n CrudServerOptions,\n FieldRole,\n ListResponseData,\n QueryRequestBody,\n RepoFieldPath,\n RepoRelationKeys,\n UserFieldPath,\n} from \"./servers/index\";\n"]}
|