@hot-updater/server 0.33.2 → 0.34.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/_virtual/_rolldown/runtime.cjs +0 -2
- package/dist/adapters/drizzle.cjs +195 -2
- package/dist/adapters/drizzle.d.cts +7 -4
- package/dist/adapters/drizzle.d.mts +7 -4
- package/dist/adapters/drizzle.mjs +194 -2
- package/dist/adapters/drizzleLazyDB.cjs +53 -0
- package/dist/adapters/drizzleLazyDB.mjs +53 -0
- package/dist/adapters/kysely.cjs +154 -3
- package/dist/adapters/kysely.d.cts +18 -10
- package/dist/adapters/kysely.d.mts +18 -10
- package/dist/adapters/kysely.mjs +153 -3
- package/dist/adapters/mongodb.cjs +183 -2
- package/dist/adapters/mongodb.d.cts +5 -4
- package/dist/adapters/mongodb.d.mts +5 -4
- package/dist/adapters/mongodb.mjs +183 -2
- package/dist/adapters/prisma.cjs +200 -2
- package/dist/adapters/prisma.d.cts +9 -4
- package/dist/adapters/prisma.d.mts +9 -4
- package/dist/adapters/prisma.mjs +199 -2
- package/dist/db/bundleRows.cjs +82 -0
- package/dist/db/bundleRows.d.cts +33 -0
- package/dist/db/bundleRows.d.mts +33 -0
- package/dist/db/bundleRows.mjs +79 -0
- package/dist/db/fixedMigrator.cjs +136 -0
- package/dist/db/fixedMigrator.mjs +135 -0
- package/dist/db/index.cjs +17 -15
- package/dist/db/index.d.cts +3 -3
- package/dist/db/index.d.mts +3 -3
- package/dist/db/index.mjs +17 -15
- package/dist/db/pluginCore.cjs +13 -5
- package/dist/db/pluginCore.mjs +13 -5
- package/dist/db/schema/mongodb.cjs +17 -0
- package/dist/db/schema/mongodb.mjs +17 -0
- package/dist/db/schema/registry.cjs +23 -0
- package/dist/db/schema/registry.mjs +18 -0
- package/dist/db/schema/sql.cjs +84 -0
- package/dist/db/schema/sql.mjs +78 -0
- package/dist/db/schema/sqlMigrations.cjs +74 -0
- package/dist/db/schema/sqlMigrations.mjs +73 -0
- package/dist/db/schema/sqlOperations.cjs +27 -0
- package/dist/db/schema/sqlOperations.mjs +26 -0
- package/dist/db/schemaEnhancements.cjs +1 -152
- package/dist/db/schemaEnhancements.mjs +1 -149
- package/dist/db/schemaGenerators.cjs +222 -0
- package/dist/db/schemaGenerators.mjs +220 -0
- package/dist/db/schemaReadiness.cjs +23 -0
- package/dist/db/schemaReadiness.d.cts +8 -0
- package/dist/db/schemaReadiness.d.mts +8 -0
- package/dist/db/schemaReadiness.mjs +22 -0
- package/dist/db/types.cjs +10 -2
- package/dist/db/types.d.cts +58 -14
- package/dist/db/types.d.mts +58 -14
- package/dist/db/types.mjs +9 -1
- package/dist/index.cjs +2 -2
- package/dist/index.d.cts +3 -2
- package/dist/index.d.mts +3 -2
- package/dist/index.mjs +2 -2
- package/dist/{packages/server/package.cjs → package.cjs} +1 -1
- package/dist/{packages/server/package.mjs → package.mjs} +1 -1
- package/dist/runtime.cjs +9 -2
- package/dist/runtime.mjs +9 -2
- package/dist/schema/dsl.cjs +86 -0
- package/dist/schema/dsl.mjs +73 -0
- package/dist/schema/index.cjs +13 -0
- package/dist/schema/index.mjs +13 -0
- package/dist/schema/settings.cjs +9 -0
- package/dist/schema/settings.mjs +9 -0
- package/dist/schema/types.cjs +6 -0
- package/dist/schema/types.mjs +5 -0
- package/dist/schema/v0_21_0.cjs +33 -18
- package/dist/schema/v0_21_0.mjs +32 -18
- package/dist/schema/v0_29_0.cjs +40 -20
- package/dist/schema/v0_29_0.mjs +39 -20
- package/dist/schema/v0_31_0.cjs +77 -43
- package/dist/schema/v0_31_0.mjs +75 -43
- package/dist/version.cjs +1 -1
- package/dist/version.mjs +1 -1
- package/package.json +30 -16
- package/src/adapters/drizzle.spec.ts +75 -0
- package/src/adapters/drizzle.ts +328 -12
- package/src/adapters/drizzleLazyDB.ts +151 -0
- package/src/adapters/kysely.spec.ts +107 -0
- package/src/adapters/kysely.ts +349 -14
- package/src/adapters/mongodb.ts +298 -15
- package/src/adapters/prisma.ts +337 -12
- package/src/db/bundleRows.ts +140 -0
- package/src/db/fixedMigrator.spec.ts +89 -0
- package/src/db/fixedMigrator.ts +288 -0
- package/src/db/hotUpdaterSchema.ts +6 -0
- package/src/db/index.spec.ts +976 -13
- package/src/db/index.ts +37 -36
- package/src/db/pluginCore.spec.ts +17 -11
- package/src/db/pluginCore.ts +15 -6
- package/src/db/schema/definitions.ts +1 -0
- package/src/db/schema/mongodb.ts +26 -0
- package/src/db/schema/registry.ts +55 -0
- package/src/db/schema/sql.ts +200 -0
- package/src/db/schema/sqlMigrations.ts +219 -0
- package/src/db/schema/sqlOperations.ts +62 -0
- package/src/db/schema/types.ts +1 -0
- package/src/db/schemaEnhancements.ts +0 -405
- package/src/db/schemaGenerators.ts +382 -0
- package/src/db/schemaReadiness.ts +33 -0
- package/src/db/types.ts +69 -25
- package/src/runtime.spec.ts +70 -0
- package/src/runtime.ts +14 -2
- package/src/schema/dsl-all-versions.spec.ts +26 -0
- package/src/schema/dsl.ts +148 -0
- package/src/schema/index.ts +16 -0
- package/src/schema/settings.ts +15 -0
- package/src/schema/types.ts +73 -0
- package/src/schema/v0_21_0.ts +48 -18
- package/src/schema/v0_29_0.ts +58 -22
- package/src/schema/v0_31_0.spec.ts +73 -0
- package/src/schema/v0_31_0.ts +116 -54
- package/dist/_virtual/_rolldown/runtime.mjs +0 -6
- package/dist/calculatePagination.cjs +0 -25
- package/dist/calculatePagination.mjs +0 -25
- package/dist/db/ormCore.cjs +0 -577
- package/dist/db/ormCore.d.cts +0 -110
- package/dist/db/ormCore.d.mts +0 -110
- package/dist/db/ormCore.mjs +0 -575
- package/dist/node_modules/.pnpm/@noble_hashes@1.8.0/node_modules/@noble/hashes/_u64.cjs +0 -112
- package/dist/node_modules/.pnpm/@noble_hashes@1.8.0/node_modules/@noble/hashes/_u64.mjs +0 -108
- package/dist/node_modules/.pnpm/@noble_hashes@1.8.0/node_modules/@noble/hashes/cryptoNode.cjs +0 -22
- package/dist/node_modules/.pnpm/@noble_hashes@1.8.0/node_modules/@noble/hashes/cryptoNode.mjs +0 -18
- package/dist/node_modules/.pnpm/@noble_hashes@1.8.0/node_modules/@noble/hashes/sha3.cjs +0 -219
- package/dist/node_modules/.pnpm/@noble_hashes@1.8.0/node_modules/@noble/hashes/sha3.mjs +0 -214
- package/dist/node_modules/.pnpm/@noble_hashes@1.8.0/node_modules/@noble/hashes/utils.cjs +0 -275
- package/dist/node_modules/.pnpm/@noble_hashes@1.8.0/node_modules/@noble/hashes/utils.mjs +0 -270
- package/dist/node_modules/.pnpm/@paralleldrive_cuid2@2.3.1/node_modules/@paralleldrive/cuid2/index.cjs +0 -17
- package/dist/node_modules/.pnpm/@paralleldrive_cuid2@2.3.1/node_modules/@paralleldrive/cuid2/index.mjs +0 -13
- package/dist/node_modules/.pnpm/@paralleldrive_cuid2@2.3.1/node_modules/@paralleldrive/cuid2/src/index.cjs +0 -69
- package/dist/node_modules/.pnpm/@paralleldrive_cuid2@2.3.1/node_modules/@paralleldrive/cuid2/src/index.mjs +0 -65
- package/dist/node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare_workers-types@4.20260611.1_@electric-sql_pglite@0.4.1_@l_601a3995dfc55b0b7fac93cbe1e76579/node_modules/drizzle-orm/column.cjs +0 -52
- package/dist/node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare_workers-types@4.20260611.1_@electric-sql_pglite@0.4.1_@l_601a3995dfc55b0b7fac93cbe1e76579/node_modules/drizzle-orm/column.mjs +0 -52
- package/dist/node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare_workers-types@4.20260611.1_@electric-sql_pglite@0.4.1_@l_601a3995dfc55b0b7fac93cbe1e76579/node_modules/drizzle-orm/entity.cjs +0 -16
- package/dist/node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare_workers-types@4.20260611.1_@electric-sql_pglite@0.4.1_@l_601a3995dfc55b0b7fac93cbe1e76579/node_modules/drizzle-orm/entity.mjs +0 -15
- package/dist/node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare_workers-types@4.20260611.1_@electric-sql_pglite@0.4.1_@l_601a3995dfc55b0b7fac93cbe1e76579/node_modules/drizzle-orm/pg-core/columns/enum.cjs +0 -7
- package/dist/node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare_workers-types@4.20260611.1_@electric-sql_pglite@0.4.1_@l_601a3995dfc55b0b7fac93cbe1e76579/node_modules/drizzle-orm/pg-core/columns/enum.mjs +0 -7
- package/dist/node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare_workers-types@4.20260611.1_@electric-sql_pglite@0.4.1_@l_601a3995dfc55b0b7fac93cbe1e76579/node_modules/drizzle-orm/sql/expressions/conditions.cjs +0 -92
- package/dist/node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare_workers-types@4.20260611.1_@electric-sql_pglite@0.4.1_@l_601a3995dfc55b0b7fac93cbe1e76579/node_modules/drizzle-orm/sql/expressions/conditions.mjs +0 -78
- package/dist/node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare_workers-types@4.20260611.1_@electric-sql_pglite@0.4.1_@l_601a3995dfc55b0b7fac93cbe1e76579/node_modules/drizzle-orm/sql/expressions/select.cjs +0 -11
- package/dist/node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare_workers-types@4.20260611.1_@electric-sql_pglite@0.4.1_@l_601a3995dfc55b0b7fac93cbe1e76579/node_modules/drizzle-orm/sql/expressions/select.mjs +0 -10
- package/dist/node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare_workers-types@4.20260611.1_@electric-sql_pglite@0.4.1_@l_601a3995dfc55b0b7fac93cbe1e76579/node_modules/drizzle-orm/sql/sql.cjs +0 -383
- package/dist/node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare_workers-types@4.20260611.1_@electric-sql_pglite@0.4.1_@l_601a3995dfc55b0b7fac93cbe1e76579/node_modules/drizzle-orm/sql/sql.mjs +0 -366
- package/dist/node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare_workers-types@4.20260611.1_@electric-sql_pglite@0.4.1_@l_601a3995dfc55b0b7fac93cbe1e76579/node_modules/drizzle-orm/subquery.cjs +0 -17
- package/dist/node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare_workers-types@4.20260611.1_@electric-sql_pglite@0.4.1_@l_601a3995dfc55b0b7fac93cbe1e76579/node_modules/drizzle-orm/subquery.mjs +0 -17
- package/dist/node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare_workers-types@4.20260611.1_@electric-sql_pglite@0.4.1_@l_601a3995dfc55b0b7fac93cbe1e76579/node_modules/drizzle-orm/table.cjs +0 -60
- package/dist/node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare_workers-types@4.20260611.1_@electric-sql_pglite@0.4.1_@l_601a3995dfc55b0b7fac93cbe1e76579/node_modules/drizzle-orm/table.mjs +0 -59
- package/dist/node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare_workers-types@4.20260611.1_@electric-sql_pglite@0.4.1_@l_601a3995dfc55b0b7fac93cbe1e76579/node_modules/drizzle-orm/table.utils.cjs +0 -4
- package/dist/node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare_workers-types@4.20260611.1_@electric-sql_pglite@0.4.1_@l_601a3995dfc55b0b7fac93cbe1e76579/node_modules/drizzle-orm/table.utils.mjs +0 -4
- package/dist/node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare_workers-types@4.20260611.1_@electric-sql_pglite@0.4.1_@l_601a3995dfc55b0b7fac93cbe1e76579/node_modules/drizzle-orm/tracing.cjs +0 -6
- package/dist/node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare_workers-types@4.20260611.1_@electric-sql_pglite@0.4.1_@l_601a3995dfc55b0b7fac93cbe1e76579/node_modules/drizzle-orm/tracing.mjs +0 -6
- package/dist/node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare_workers-types@4.20260611.1_@electric-sql_pglite@0.4.1_@l_601a3995dfc55b0b7fac93cbe1e76579/node_modules/drizzle-orm/view-common.cjs +0 -4
- package/dist/node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare_workers-types@4.20260611.1_@electric-sql_pglite@0.4.1_@l_601a3995dfc55b0b7fac93cbe1e76579/node_modules/drizzle-orm/view-common.mjs +0 -4
- package/dist/node_modules/.pnpm/fumadb@0.2.2_mongodb@6.20.0_@aws-sdk_credential-providers@3.1066.0_socks@2.8.9__prisma@_ee79457f0e32f18f0beb5c2db02e4f73/node_modules/fumadb/dist/adapters/drizzle/index.cjs +0 -383
- package/dist/node_modules/.pnpm/fumadb@0.2.2_mongodb@6.20.0_@aws-sdk_credential-providers@3.1066.0_socks@2.8.9__prisma@_ee79457f0e32f18f0beb5c2db02e4f73/node_modules/fumadb/dist/adapters/drizzle/index.d.cts +0 -12
- package/dist/node_modules/.pnpm/fumadb@0.2.2_mongodb@6.20.0_@aws-sdk_credential-providers@3.1066.0_socks@2.8.9__prisma@_ee79457f0e32f18f0beb5c2db02e4f73/node_modules/fumadb/dist/adapters/drizzle/index.d.mts +0 -12
- package/dist/node_modules/.pnpm/fumadb@0.2.2_mongodb@6.20.0_@aws-sdk_credential-providers@3.1066.0_socks@2.8.9__prisma@_ee79457f0e32f18f0beb5c2db02e4f73/node_modules/fumadb/dist/adapters/drizzle/index.mjs +0 -383
- package/dist/node_modules/.pnpm/fumadb@0.2.2_mongodb@6.20.0_@aws-sdk_credential-providers@3.1066.0_socks@2.8.9__prisma@_ee79457f0e32f18f0beb5c2db02e4f73/node_modules/fumadb/dist/adapters/kysely/index.cjs +0 -4
- package/dist/node_modules/.pnpm/fumadb@0.2.2_mongodb@6.20.0_@aws-sdk_credential-providers@3.1066.0_socks@2.8.9__prisma@_ee79457f0e32f18f0beb5c2db02e4f73/node_modules/fumadb/dist/adapters/kysely/index.mjs +0 -5
- package/dist/node_modules/.pnpm/fumadb@0.2.2_mongodb@6.20.0_@aws-sdk_credential-providers@3.1066.0_socks@2.8.9__prisma@_ee79457f0e32f18f0beb5c2db02e4f73/node_modules/fumadb/dist/adapters/prisma/index.cjs +0 -339
- package/dist/node_modules/.pnpm/fumadb@0.2.2_mongodb@6.20.0_@aws-sdk_credential-providers@3.1066.0_socks@2.8.9__prisma@_ee79457f0e32f18f0beb5c2db02e4f73/node_modules/fumadb/dist/adapters/prisma/index.d.cts +0 -70
- package/dist/node_modules/.pnpm/fumadb@0.2.2_mongodb@6.20.0_@aws-sdk_credential-providers@3.1066.0_socks@2.8.9__prisma@_ee79457f0e32f18f0beb5c2db02e4f73/node_modules/fumadb/dist/adapters/prisma/index.d.mts +0 -70
- package/dist/node_modules/.pnpm/fumadb@0.2.2_mongodb@6.20.0_@aws-sdk_credential-providers@3.1066.0_socks@2.8.9__prisma@_ee79457f0e32f18f0beb5c2db02e4f73/node_modules/fumadb/dist/adapters/prisma/index.mjs +0 -339
- package/dist/node_modules/.pnpm/fumadb@0.2.2_mongodb@6.20.0_@aws-sdk_credential-providers@3.1066.0_socks@2.8.9__prisma@_ee79457f0e32f18f0beb5c2db02e4f73/node_modules/fumadb/dist/chunk-7PZK4ONR.cjs +0 -57
- package/dist/node_modules/.pnpm/fumadb@0.2.2_mongodb@6.20.0_@aws-sdk_credential-providers@3.1066.0_socks@2.8.9__prisma@_ee79457f0e32f18f0beb5c2db02e4f73/node_modules/fumadb/dist/chunk-7PZK4ONR.mjs +0 -56
- package/dist/node_modules/.pnpm/fumadb@0.2.2_mongodb@6.20.0_@aws-sdk_credential-providers@3.1066.0_socks@2.8.9__prisma@_ee79457f0e32f18f0beb5c2db02e4f73/node_modules/fumadb/dist/chunk-C6OTUURW.cjs +0 -330
- package/dist/node_modules/.pnpm/fumadb@0.2.2_mongodb@6.20.0_@aws-sdk_credential-providers@3.1066.0_socks@2.8.9__prisma@_ee79457f0e32f18f0beb5c2db02e4f73/node_modules/fumadb/dist/chunk-C6OTUURW.mjs +0 -326
- package/dist/node_modules/.pnpm/fumadb@0.2.2_mongodb@6.20.0_@aws-sdk_credential-providers@3.1066.0_socks@2.8.9__prisma@_ee79457f0e32f18f0beb5c2db02e4f73/node_modules/fumadb/dist/chunk-CHTIKPQU.cjs +0 -166
- package/dist/node_modules/.pnpm/fumadb@0.2.2_mongodb@6.20.0_@aws-sdk_credential-providers@3.1066.0_socks@2.8.9__prisma@_ee79457f0e32f18f0beb5c2db02e4f73/node_modules/fumadb/dist/chunk-CHTIKPQU.mjs +0 -163
- package/dist/node_modules/.pnpm/fumadb@0.2.2_mongodb@6.20.0_@aws-sdk_credential-providers@3.1066.0_socks@2.8.9__prisma@_ee79457f0e32f18f0beb5c2db02e4f73/node_modules/fumadb/dist/chunk-GUE4GMNC.cjs +0 -14
- package/dist/node_modules/.pnpm/fumadb@0.2.2_mongodb@6.20.0_@aws-sdk_credential-providers@3.1066.0_socks@2.8.9__prisma@_ee79457f0e32f18f0beb5c2db02e4f73/node_modules/fumadb/dist/chunk-GUE4GMNC.mjs +0 -13
- package/dist/node_modules/.pnpm/fumadb@0.2.2_mongodb@6.20.0_@aws-sdk_credential-providers@3.1066.0_socks@2.8.9__prisma@_ee79457f0e32f18f0beb5c2db02e4f73/node_modules/fumadb/dist/chunk-LHHP6UVP.cjs +0 -24
- package/dist/node_modules/.pnpm/fumadb@0.2.2_mongodb@6.20.0_@aws-sdk_credential-providers@3.1066.0_socks@2.8.9__prisma@_ee79457f0e32f18f0beb5c2db02e4f73/node_modules/fumadb/dist/chunk-LHHP6UVP.mjs +0 -24
- package/dist/node_modules/.pnpm/fumadb@0.2.2_mongodb@6.20.0_@aws-sdk_credential-providers@3.1066.0_socks@2.8.9__prisma@_ee79457f0e32f18f0beb5c2db02e4f73/node_modules/fumadb/dist/chunk-LVCPMTAT.cjs +0 -1190
- package/dist/node_modules/.pnpm/fumadb@0.2.2_mongodb@6.20.0_@aws-sdk_credential-providers@3.1066.0_socks@2.8.9__prisma@_ee79457f0e32f18f0beb5c2db02e4f73/node_modules/fumadb/dist/chunk-LVCPMTAT.mjs +0 -1189
- package/dist/node_modules/.pnpm/fumadb@0.2.2_mongodb@6.20.0_@aws-sdk_credential-providers@3.1066.0_socks@2.8.9__prisma@_ee79457f0e32f18f0beb5c2db02e4f73/node_modules/fumadb/dist/chunk-PK2W2SQ7.cjs +0 -197
- package/dist/node_modules/.pnpm/fumadb@0.2.2_mongodb@6.20.0_@aws-sdk_credential-providers@3.1066.0_socks@2.8.9__prisma@_ee79457f0e32f18f0beb5c2db02e4f73/node_modules/fumadb/dist/chunk-PK2W2SQ7.mjs +0 -197
- package/dist/node_modules/.pnpm/fumadb@0.2.2_mongodb@6.20.0_@aws-sdk_credential-providers@3.1066.0_socks@2.8.9__prisma@_ee79457f0e32f18f0beb5c2db02e4f73/node_modules/fumadb/dist/chunk-ZEQMAIFI.cjs +0 -410
- package/dist/node_modules/.pnpm/fumadb@0.2.2_mongodb@6.20.0_@aws-sdk_credential-providers@3.1066.0_socks@2.8.9__prisma@_ee79457f0e32f18f0beb5c2db02e4f73/node_modules/fumadb/dist/chunk-ZEQMAIFI.mjs +0 -400
- package/dist/node_modules/.pnpm/fumadb@0.2.2_mongodb@6.20.0_@aws-sdk_credential-providers@3.1066.0_socks@2.8.9__prisma@_ee79457f0e32f18f0beb5c2db02e4f73/node_modules/fumadb/dist/chunk-ZOCGSAWS.cjs +0 -213
- package/dist/node_modules/.pnpm/fumadb@0.2.2_mongodb@6.20.0_@aws-sdk_credential-providers@3.1066.0_socks@2.8.9__prisma@_ee79457f0e32f18f0beb5c2db02e4f73/node_modules/fumadb/dist/chunk-ZOCGSAWS.mjs +0 -212
- package/dist/node_modules/.pnpm/fumadb@0.2.2_mongodb@6.20.0_@aws-sdk_credential-providers@3.1066.0_socks@2.8.9__prisma@_ee79457f0e32f18f0beb5c2db02e4f73/node_modules/fumadb/dist/create-tg0451Y_.d.cts +0 -285
- package/dist/node_modules/.pnpm/fumadb@0.2.2_mongodb@6.20.0_@aws-sdk_credential-providers@3.1066.0_socks@2.8.9__prisma@_ee79457f0e32f18f0beb5c2db02e4f73/node_modules/fumadb/dist/create-tg0451Y_.d.mts +0 -285
- package/dist/node_modules/.pnpm/fumadb@0.2.2_mongodb@6.20.0_@aws-sdk_credential-providers@3.1066.0_socks@2.8.9__prisma@_ee79457f0e32f18f0beb5c2db02e4f73/node_modules/fumadb/dist/index-CMqePMTF.d.cts +0 -45
- package/dist/node_modules/.pnpm/fumadb@0.2.2_mongodb@6.20.0_@aws-sdk_credential-providers@3.1066.0_socks@2.8.9__prisma@_ee79457f0e32f18f0beb5c2db02e4f73/node_modules/fumadb/dist/index-CMqePMTF.d.mts +0 -45
- package/dist/node_modules/.pnpm/fumadb@0.2.2_mongodb@6.20.0_@aws-sdk_credential-providers@3.1066.0_socks@2.8.9__prisma@_ee79457f0e32f18f0beb5c2db02e4f73/node_modules/fumadb/dist/index.cjs +0 -69
- package/dist/node_modules/.pnpm/fumadb@0.2.2_mongodb@6.20.0_@aws-sdk_credential-providers@3.1066.0_socks@2.8.9__prisma@_ee79457f0e32f18f0beb5c2db02e4f73/node_modules/fumadb/dist/index.d.cts +0 -49
- package/dist/node_modules/.pnpm/fumadb@0.2.2_mongodb@6.20.0_@aws-sdk_credential-providers@3.1066.0_socks@2.8.9__prisma@_ee79457f0e32f18f0beb5c2db02e4f73/node_modules/fumadb/dist/index.d.mts +0 -49
- package/dist/node_modules/.pnpm/fumadb@0.2.2_mongodb@6.20.0_@aws-sdk_credential-providers@3.1066.0_socks@2.8.9__prisma@_ee79457f0e32f18f0beb5c2db02e4f73/node_modules/fumadb/dist/index.mjs +0 -67
- package/dist/node_modules/.pnpm/fumadb@0.2.2_mongodb@6.20.0_@aws-sdk_credential-providers@3.1066.0_socks@2.8.9__prisma@_ee79457f0e32f18f0beb5c2db02e4f73/node_modules/fumadb/dist/query/index.d.cts +0 -156
- package/dist/node_modules/.pnpm/fumadb@0.2.2_mongodb@6.20.0_@aws-sdk_credential-providers@3.1066.0_socks@2.8.9__prisma@_ee79457f0e32f18f0beb5c2db02e4f73/node_modules/fumadb/dist/query/index.d.mts +0 -156
- package/dist/node_modules/.pnpm/fumadb@0.2.2_mongodb@6.20.0_@aws-sdk_credential-providers@3.1066.0_socks@2.8.9__prisma@_ee79457f0e32f18f0beb5c2db02e4f73/node_modules/fumadb/dist/schema/index.cjs +0 -1
- package/dist/node_modules/.pnpm/fumadb@0.2.2_mongodb@6.20.0_@aws-sdk_credential-providers@3.1066.0_socks@2.8.9__prisma@_ee79457f0e32f18f0beb5c2db02e4f73/node_modules/fumadb/dist/schema/index.mjs +0 -2
- package/src/db/ormCore.ts +0 -1059
- package/src/db/ormUpdateCheck.bench.ts +0 -262
package/src/db/index.spec.ts
CHANGED
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
} from "@hot-updater/test-utils";
|
|
13
13
|
import { Kysely } from "kysely";
|
|
14
14
|
import { PGliteDialect } from "kysely-pglite-dialect";
|
|
15
|
+
import type { MongoClient } from "mongodb";
|
|
15
16
|
import {
|
|
16
17
|
afterAll,
|
|
17
18
|
afterEach,
|
|
@@ -23,9 +24,19 @@ import {
|
|
|
23
24
|
vi,
|
|
24
25
|
} from "vitest";
|
|
25
26
|
|
|
27
|
+
import { drizzleAdapter } from "../adapters/drizzle";
|
|
26
28
|
import { kyselyAdapter } from "../adapters/kysely";
|
|
29
|
+
import { mongoAdapter } from "../adapters/mongodb";
|
|
30
|
+
import { prismaAdapter } from "../adapters/prisma";
|
|
31
|
+
import { bundleToRow } from "./bundleRows";
|
|
32
|
+
import {
|
|
33
|
+
createSchemaMigrationSql,
|
|
34
|
+
createTableSql,
|
|
35
|
+
hotUpdaterSchemaVersions,
|
|
36
|
+
} from "./hotUpdaterSchema";
|
|
27
37
|
import { createHotUpdater } from "./index";
|
|
28
|
-
import
|
|
38
|
+
import { generateDrizzleSchema } from "./schemaGenerators";
|
|
39
|
+
import type { DatabasePluginFactory, ORMProvider } from "./types";
|
|
29
40
|
|
|
30
41
|
const RAW_PRISMA_SCHEMA = `model bundles {
|
|
31
42
|
id String @id
|
|
@@ -168,25 +179,74 @@ function createSchemaOnlyAdapter({
|
|
|
168
179
|
name: string;
|
|
169
180
|
provider: ORMProvider;
|
|
170
181
|
path: string;
|
|
171
|
-
}):
|
|
172
|
-
|
|
182
|
+
}): DatabasePluginFactory {
|
|
183
|
+
const factory: DatabasePluginFactory = () => ({
|
|
173
184
|
name,
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
throw new Error("Schema-only adapter cannot create ORM");
|
|
177
|
-
},
|
|
178
|
-
async getSchemaVersion() {
|
|
179
|
-
return undefined;
|
|
185
|
+
async getBundleById() {
|
|
186
|
+
return null;
|
|
180
187
|
},
|
|
181
|
-
|
|
188
|
+
async getBundles() {
|
|
182
189
|
return {
|
|
183
|
-
|
|
184
|
-
|
|
190
|
+
data: [],
|
|
191
|
+
pagination: {
|
|
192
|
+
currentPage: 1,
|
|
193
|
+
hasNextPage: false,
|
|
194
|
+
hasPreviousPage: false,
|
|
195
|
+
total: 0,
|
|
196
|
+
totalPages: 0,
|
|
197
|
+
},
|
|
185
198
|
};
|
|
186
199
|
},
|
|
200
|
+
async getChannels() {
|
|
201
|
+
return [];
|
|
202
|
+
},
|
|
203
|
+
async appendBundle() {},
|
|
204
|
+
async updateBundle() {},
|
|
205
|
+
async deleteBundle() {},
|
|
206
|
+
async commitBundle() {},
|
|
207
|
+
});
|
|
208
|
+
factory.adapterName = name;
|
|
209
|
+
factory.provider = provider;
|
|
210
|
+
factory.generateSchema = (_version, schemaName = name) => {
|
|
211
|
+
return {
|
|
212
|
+
code,
|
|
213
|
+
path: path || schemaName,
|
|
214
|
+
};
|
|
187
215
|
};
|
|
216
|
+
return factory;
|
|
188
217
|
}
|
|
189
218
|
|
|
219
|
+
const transactionBundle: Bundle = {
|
|
220
|
+
id: "00000000-0000-0000-0000-000000000777",
|
|
221
|
+
platform: "ios",
|
|
222
|
+
shouldForceUpdate: false,
|
|
223
|
+
enabled: true,
|
|
224
|
+
fileHash: "transaction-hash",
|
|
225
|
+
gitCommitHash: null,
|
|
226
|
+
message: "transaction bundle",
|
|
227
|
+
channel: "production",
|
|
228
|
+
storageUri: "s3://test-bucket/transaction.zip",
|
|
229
|
+
targetAppVersion: "1.0.0",
|
|
230
|
+
fingerprintHash: null,
|
|
231
|
+
};
|
|
232
|
+
|
|
233
|
+
const appVersionFastPathBundle: Bundle = {
|
|
234
|
+
...transactionBundle,
|
|
235
|
+
id: "00000000-0000-0000-0000-000000000778",
|
|
236
|
+
fileHash: "app-version-fast-path-hash",
|
|
237
|
+
message: "app version fast path bundle",
|
|
238
|
+
targetAppVersion: "1.0.0",
|
|
239
|
+
};
|
|
240
|
+
|
|
241
|
+
const fingerprintFastPathBundle: Bundle = {
|
|
242
|
+
...transactionBundle,
|
|
243
|
+
id: "00000000-0000-0000-0000-000000000779",
|
|
244
|
+
fileHash: "fingerprint-fast-path-hash",
|
|
245
|
+
fingerprintHash: "fingerprint-fast-path",
|
|
246
|
+
message: "fingerprint fast path bundle",
|
|
247
|
+
targetAppVersion: null,
|
|
248
|
+
};
|
|
249
|
+
|
|
190
250
|
describe("server/db hotUpdater getUpdateInfo (PGlite + Kysely)", async () => {
|
|
191
251
|
const db = new PGlite();
|
|
192
252
|
|
|
@@ -268,8 +328,18 @@ describe("server/db hotUpdater getUpdateInfo (PGlite + Kysely)", async () => {
|
|
|
268
328
|
}),
|
|
269
329
|
});
|
|
270
330
|
|
|
331
|
+
it("uses the default generated schema artifact path for Drizzle", () => {
|
|
332
|
+
const adapter = drizzleAdapter({
|
|
333
|
+
db: { _: { fullSchema: {} } },
|
|
334
|
+
provider: "sqlite",
|
|
335
|
+
});
|
|
336
|
+
|
|
337
|
+
expect(adapter.generateSchema?.("latest").path).toBe(
|
|
338
|
+
"hot-updater-schema.ts",
|
|
339
|
+
);
|
|
340
|
+
});
|
|
341
|
+
|
|
271
342
|
beforeAll(async () => {
|
|
272
|
-
// Initialize FumaDB schema to latest (creates tables under the hood)
|
|
273
343
|
const migrator = hotUpdater.createMigrator();
|
|
274
344
|
const result = await migrator.migrateToLatest({
|
|
275
345
|
mode: "from-schema",
|
|
@@ -316,6 +386,7 @@ describe("server/db hotUpdater getUpdateInfo (PGlite + Kysely)", async () => {
|
|
|
316
386
|
|
|
317
387
|
expect(code).toContain('channel String @default("production")');
|
|
318
388
|
expect(code).toContain('metadata Json @default("{}")');
|
|
389
|
+
expect(code).toContain('value String @default("0.31.0")');
|
|
319
390
|
expect(code).toContain(
|
|
320
391
|
'patches bundle_patches[] @relation("bundle_patches_bundles_patches")',
|
|
321
392
|
);
|
|
@@ -329,6 +400,7 @@ describe("server/db hotUpdater getUpdateInfo (PGlite + Kysely)", async () => {
|
|
|
329
400
|
'baseBundle bundles @relation("bundle_patches_bundles_baseForPatches"',
|
|
330
401
|
);
|
|
331
402
|
expect(code).toContain('@@index([channel], map: "bundles_channel_idx")');
|
|
403
|
+
expect(code).not.toContain("bundles_platform_idx");
|
|
332
404
|
expect(code).toContain(
|
|
333
405
|
'@@index([bundle_id], map: "bundle_patches_bundle_id_idx")',
|
|
334
406
|
);
|
|
@@ -341,6 +413,14 @@ describe("server/db hotUpdater getUpdateInfo (PGlite + Kysely)", async () => {
|
|
|
341
413
|
expect(code).not.toContain('metadata Json @default("{}")');
|
|
342
414
|
});
|
|
343
415
|
|
|
416
|
+
it("generates ORM schema from the requested version snapshot", () => {
|
|
417
|
+
const code = prismaSchemaHotUpdater.generateSchema("0.21.0").code;
|
|
418
|
+
|
|
419
|
+
expect(code).toContain('value String @default("0.21.0")');
|
|
420
|
+
expect(code).not.toContain("rollout_cohort_count");
|
|
421
|
+
expect(code).not.toContain("bundle_patches");
|
|
422
|
+
});
|
|
423
|
+
|
|
344
424
|
it("includes foreign keys and indexes in Drizzle output", () => {
|
|
345
425
|
const code = drizzleSchemaHotUpdater.generateSchema("latest").code;
|
|
346
426
|
const bundlesBlock = code.match(
|
|
@@ -361,6 +441,7 @@ describe("server/db hotUpdater getUpdateInfo (PGlite + Kysely)", async () => {
|
|
|
361
441
|
expect(bundlesBlock).toContain(
|
|
362
442
|
'index("bundles_channel_idx").on(table.channel)',
|
|
363
443
|
);
|
|
444
|
+
expect(bundlesBlock).not.toContain("bundles_platform_idx");
|
|
364
445
|
expect(bundlesBlock).toContain(
|
|
365
446
|
'index("bundles_target_app_version_idx").on(table.target_app_version)',
|
|
366
447
|
);
|
|
@@ -373,10 +454,65 @@ describe("server/db hotUpdater getUpdateInfo (PGlite + Kysely)", async () => {
|
|
|
373
454
|
expect(bundlePatchesBlock).not.toContain(
|
|
374
455
|
'index("bundles_target_app_version_idx").on(table.target_app_version)',
|
|
375
456
|
);
|
|
457
|
+
const generatedCode = generateDrizzleSchema("postgresql");
|
|
458
|
+
expect(generatedCode).toContain(
|
|
459
|
+
'id: varchar("id", { length: 255 }).primaryKey().notNull()',
|
|
460
|
+
);
|
|
461
|
+
expect(generatedCode).toContain(
|
|
462
|
+
'version: varchar("version", { length: 255 }).notNull().default("0.31.0")',
|
|
463
|
+
);
|
|
464
|
+
expect(generatedCode).not.toContain('key: varchar("key"');
|
|
465
|
+
expect(generatedCode).not.toContain('value: text("value"');
|
|
376
466
|
});
|
|
377
467
|
});
|
|
378
468
|
|
|
379
469
|
describe("migrator enhancements", () => {
|
|
470
|
+
it("derives incremental migrations from versioned schemas", () => {
|
|
471
|
+
expect(hotUpdaterSchemaVersions.map((schema) => schema.version)).toEqual([
|
|
472
|
+
"0.21.0",
|
|
473
|
+
"0.29.0",
|
|
474
|
+
"0.31.0",
|
|
475
|
+
]);
|
|
476
|
+
|
|
477
|
+
const v029Sql = createSchemaMigrationSql(
|
|
478
|
+
"0.21.0",
|
|
479
|
+
"0.29.0",
|
|
480
|
+
"postgresql",
|
|
481
|
+
).join("\n");
|
|
482
|
+
const v031Sql = createSchemaMigrationSql(
|
|
483
|
+
"0.29.0",
|
|
484
|
+
"0.31.0",
|
|
485
|
+
"postgresql",
|
|
486
|
+
).join("\n");
|
|
487
|
+
|
|
488
|
+
expect(v029Sql).toContain(
|
|
489
|
+
"alter table bundles add column rollout_cohort_count",
|
|
490
|
+
);
|
|
491
|
+
expect(v029Sql).not.toContain("bundle_patches");
|
|
492
|
+
expect(v031Sql).toContain(
|
|
493
|
+
"alter table bundles add column manifest_storage_uri",
|
|
494
|
+
);
|
|
495
|
+
expect(v031Sql).toContain("create table if not exists bundle_patches");
|
|
496
|
+
expect(v031Sql).toContain(
|
|
497
|
+
"add constraint bundle_patches_bundle_id_fk foreign key",
|
|
498
|
+
);
|
|
499
|
+
});
|
|
500
|
+
|
|
501
|
+
it("omits MySQL defaults for text and JSON columns", () => {
|
|
502
|
+
const sql = createTableSql("mysql").join("\n");
|
|
503
|
+
|
|
504
|
+
expect(sql).toContain("channel text not null");
|
|
505
|
+
expect(sql).not.toContain("channel text not null default");
|
|
506
|
+
expect(sql).toContain("metadata json not null");
|
|
507
|
+
expect(sql).not.toContain("metadata json not null default");
|
|
508
|
+
expect(sql).toContain("`key` varchar(255) primary key");
|
|
509
|
+
expect(sql).not.toContain("\nkey varchar(255) primary key");
|
|
510
|
+
expect(sql).toContain(
|
|
511
|
+
"create index bundle_patches_bundle_id_idx on bundle_patches(bundle_id)",
|
|
512
|
+
);
|
|
513
|
+
expect(sql).not.toContain("bundle_id(255)");
|
|
514
|
+
});
|
|
515
|
+
|
|
380
516
|
it("adds custom indexes and constraints to generated SQL", async () => {
|
|
381
517
|
const migrationDb = new PGlite();
|
|
382
518
|
const migrationKysely = new Kysely({
|
|
@@ -401,14 +537,841 @@ describe("server/db hotUpdater getUpdateInfo (PGlite + Kysely)", async () => {
|
|
|
401
537
|
expect(sql).toContain(
|
|
402
538
|
"add constraint check_version_or_fingerprint check",
|
|
403
539
|
);
|
|
540
|
+
expect(sql).toContain(
|
|
541
|
+
"add constraint bundle_patches_bundle_id_fk foreign key",
|
|
542
|
+
);
|
|
404
543
|
expect(sql).toContain(
|
|
405
544
|
"create index bundle_patches_bundle_id_idx on bundle_patches",
|
|
406
545
|
);
|
|
546
|
+
expect(sql).toContain("insert into private_hot_updater_settings");
|
|
547
|
+
expect(result.operations).not.toContainEqual(
|
|
548
|
+
expect.objectContaining({
|
|
549
|
+
sql: expect.stringContaining(
|
|
550
|
+
"insert into private_hot_updater_settings",
|
|
551
|
+
),
|
|
552
|
+
}),
|
|
553
|
+
);
|
|
554
|
+
} finally {
|
|
555
|
+
await migrationKysely.destroy();
|
|
556
|
+
await migrationDb.close();
|
|
557
|
+
}
|
|
558
|
+
});
|
|
559
|
+
|
|
560
|
+
it("migrates existing 0.21.0 Kysely schemas incrementally", async () => {
|
|
561
|
+
const migrationDb = new PGlite();
|
|
562
|
+
const migrationKysely = new Kysely({
|
|
563
|
+
dialect: new PGliteDialect(migrationDb),
|
|
564
|
+
});
|
|
565
|
+
const migrationHotUpdater = createHotUpdater({
|
|
566
|
+
database: kyselyAdapter({
|
|
567
|
+
db: migrationKysely,
|
|
568
|
+
provider: "postgresql",
|
|
569
|
+
}),
|
|
570
|
+
});
|
|
571
|
+
|
|
572
|
+
try {
|
|
573
|
+
await migrationDb.exec(`
|
|
574
|
+
create table bundles (
|
|
575
|
+
id uuid primary key,
|
|
576
|
+
platform text not null,
|
|
577
|
+
should_force_update boolean not null,
|
|
578
|
+
enabled boolean not null,
|
|
579
|
+
file_hash text not null,
|
|
580
|
+
git_commit_hash text,
|
|
581
|
+
message text,
|
|
582
|
+
channel text not null default 'production',
|
|
583
|
+
storage_uri text not null,
|
|
584
|
+
target_app_version text,
|
|
585
|
+
fingerprint_hash text,
|
|
586
|
+
metadata json not null default '{}'::json
|
|
587
|
+
);
|
|
588
|
+
create table private_hot_updater_settings (
|
|
589
|
+
key varchar(255) primary key,
|
|
590
|
+
value text not null
|
|
591
|
+
);
|
|
592
|
+
insert into private_hot_updater_settings (key, value)
|
|
593
|
+
values ('version', '0.21.0');
|
|
594
|
+
`);
|
|
595
|
+
|
|
596
|
+
const migrator = migrationHotUpdater.createMigrator();
|
|
597
|
+
const result = await migrator.migrateToLatest({
|
|
598
|
+
mode: "from-schema",
|
|
599
|
+
updateSettings: true,
|
|
600
|
+
});
|
|
601
|
+
const sql = result.getSQL?.() ?? "";
|
|
602
|
+
|
|
603
|
+
expect(sql).toContain(
|
|
604
|
+
"alter table bundles add column rollout_cohort_count",
|
|
605
|
+
);
|
|
606
|
+
expect(sql).toContain(
|
|
607
|
+
"alter table bundles add column manifest_storage_uri",
|
|
608
|
+
);
|
|
609
|
+
expect(sql).toContain("create table if not exists bundle_patches");
|
|
610
|
+
expect(sql).not.toContain("create table if not exists bundles");
|
|
611
|
+
|
|
612
|
+
await result.execute();
|
|
613
|
+
|
|
614
|
+
const version = await migrationDb.query<{ value: string }>(
|
|
615
|
+
"select value from private_hot_updater_settings where key = 'version'",
|
|
616
|
+
);
|
|
617
|
+
expect(version.rows[0]?.value).toBe("0.31.0");
|
|
618
|
+
await migrationDb.query(
|
|
619
|
+
"select rollout_cohort_count, target_cohorts, manifest_storage_uri from bundles limit 0",
|
|
620
|
+
);
|
|
621
|
+
await migrationDb.query("select * from bundle_patches limit 0");
|
|
622
|
+
} finally {
|
|
623
|
+
await migrationKysely.destroy();
|
|
624
|
+
await migrationDb.close();
|
|
625
|
+
}
|
|
626
|
+
});
|
|
627
|
+
|
|
628
|
+
it("honors soft relation mode by omitting SQL foreign keys", async () => {
|
|
629
|
+
const migrationDb = new PGlite();
|
|
630
|
+
const migrationKysely = new Kysely({
|
|
631
|
+
dialect: new PGliteDialect(migrationDb),
|
|
632
|
+
});
|
|
633
|
+
const migrationHotUpdater = createHotUpdater({
|
|
634
|
+
database: kyselyAdapter({
|
|
635
|
+
db: migrationKysely,
|
|
636
|
+
provider: "postgresql",
|
|
637
|
+
relationMode: "fumadb",
|
|
638
|
+
}),
|
|
639
|
+
});
|
|
640
|
+
|
|
641
|
+
try {
|
|
642
|
+
const migrator = migrationHotUpdater.createMigrator();
|
|
643
|
+
const result = await migrator.migrateToLatest({
|
|
644
|
+
mode: "from-schema",
|
|
645
|
+
updateSettings: false,
|
|
646
|
+
});
|
|
647
|
+
const sql = result.getSQL?.() ?? "";
|
|
648
|
+
|
|
649
|
+
expect(sql).not.toContain("add constraint bundle_patches_bundle_id_fk");
|
|
650
|
+
expect(result.operations).not.toContainEqual(
|
|
651
|
+
expect.objectContaining({
|
|
652
|
+
sql: expect.stringContaining("bundle_patches_bundle_id_fk"),
|
|
653
|
+
}),
|
|
654
|
+
);
|
|
655
|
+
} finally {
|
|
656
|
+
await migrationKysely.destroy();
|
|
657
|
+
await migrationDb.close();
|
|
658
|
+
}
|
|
659
|
+
});
|
|
660
|
+
|
|
661
|
+
it("omits unsupported SQLite alter constraint statements", async () => {
|
|
662
|
+
const migrationDb = new PGlite();
|
|
663
|
+
const migrationKysely = new Kysely({
|
|
664
|
+
dialect: new PGliteDialect(migrationDb),
|
|
665
|
+
});
|
|
666
|
+
const migrationHotUpdater = createHotUpdater({
|
|
667
|
+
database: kyselyAdapter({
|
|
668
|
+
db: migrationKysely,
|
|
669
|
+
provider: "sqlite",
|
|
670
|
+
}),
|
|
671
|
+
});
|
|
672
|
+
|
|
673
|
+
try {
|
|
674
|
+
const migrator = migrationHotUpdater.createMigrator();
|
|
675
|
+
const result = await migrator.migrateToLatest({
|
|
676
|
+
mode: "from-schema",
|
|
677
|
+
updateSettings: false,
|
|
678
|
+
});
|
|
679
|
+
const sql = result.getSQL?.() ?? "";
|
|
680
|
+
|
|
681
|
+
expect(sql).not.toContain("alter table bundles add constraint");
|
|
682
|
+
expect(sql).not.toContain("alter table bundle_patches add constraint");
|
|
683
|
+
expect(result.operations).not.toContainEqual(
|
|
684
|
+
expect.objectContaining({
|
|
685
|
+
sql: expect.stringContaining("add constraint"),
|
|
686
|
+
}),
|
|
687
|
+
);
|
|
688
|
+
} finally {
|
|
689
|
+
await migrationKysely.destroy();
|
|
690
|
+
await migrationDb.close();
|
|
691
|
+
}
|
|
692
|
+
});
|
|
693
|
+
|
|
694
|
+
it("creates MongoDB indexes for runtime query fields", async () => {
|
|
695
|
+
const collection = {
|
|
696
|
+
findOne: vi.fn(async () => null),
|
|
697
|
+
};
|
|
698
|
+
const client = {
|
|
699
|
+
db: () => ({
|
|
700
|
+
collection: () => collection,
|
|
701
|
+
}),
|
|
702
|
+
} as unknown as MongoClient;
|
|
703
|
+
const mongoHotUpdater = createHotUpdater({
|
|
704
|
+
database: mongoAdapter({ client }),
|
|
705
|
+
});
|
|
706
|
+
const result = await mongoHotUpdater
|
|
707
|
+
.createMigrator()
|
|
708
|
+
.migrateToLatest({ mode: "from-schema" });
|
|
709
|
+
|
|
710
|
+
expect(result.operations).toEqual(
|
|
711
|
+
expect.arrayContaining([
|
|
712
|
+
expect.objectContaining({
|
|
713
|
+
sql: "create index bundles_id_idx on bundles(id)",
|
|
714
|
+
}),
|
|
715
|
+
expect.objectContaining({
|
|
716
|
+
sql: "create index bundles_target_app_version_idx on bundles(target_app_version)",
|
|
717
|
+
}),
|
|
718
|
+
expect.objectContaining({
|
|
719
|
+
sql: "create index bundles_fingerprint_hash_idx on bundles(fingerprint_hash)",
|
|
720
|
+
}),
|
|
721
|
+
expect.objectContaining({
|
|
722
|
+
sql: "create index bundles_platform_idx on bundles(platform)",
|
|
723
|
+
}),
|
|
724
|
+
expect.objectContaining({
|
|
725
|
+
sql: "create index bundle_patches_base_bundle_id_idx on bundle_patches(base_bundle_id)",
|
|
726
|
+
}),
|
|
727
|
+
]),
|
|
728
|
+
);
|
|
729
|
+
});
|
|
730
|
+
|
|
731
|
+
it("rejects from-database migrations explicitly", async () => {
|
|
732
|
+
const migrationDb = new PGlite();
|
|
733
|
+
const migrationKysely = new Kysely({
|
|
734
|
+
dialect: new PGliteDialect(migrationDb),
|
|
735
|
+
});
|
|
736
|
+
const migrationHotUpdater = createHotUpdater({
|
|
737
|
+
database: kyselyAdapter({
|
|
738
|
+
db: migrationKysely,
|
|
739
|
+
provider: "postgresql",
|
|
740
|
+
}),
|
|
741
|
+
});
|
|
742
|
+
|
|
743
|
+
try {
|
|
744
|
+
await expect(
|
|
745
|
+
migrationHotUpdater.createMigrator().migrateToLatest({
|
|
746
|
+
mode: "from-database",
|
|
747
|
+
}),
|
|
748
|
+
).rejects.toThrow(
|
|
749
|
+
"Hot Updater migrations support only mode: 'from-schema'.",
|
|
750
|
+
);
|
|
751
|
+
} finally {
|
|
752
|
+
await migrationKysely.destroy();
|
|
753
|
+
await migrationDb.close();
|
|
754
|
+
}
|
|
755
|
+
});
|
|
756
|
+
|
|
757
|
+
it("rejects runtime access when a Kysely schema is not initialized", async () => {
|
|
758
|
+
const migrationDb = new PGlite();
|
|
759
|
+
const migrationKysely = new Kysely({
|
|
760
|
+
dialect: new PGliteDialect(migrationDb),
|
|
761
|
+
});
|
|
762
|
+
const migrationHotUpdater = createHotUpdater({
|
|
763
|
+
database: kyselyAdapter({
|
|
764
|
+
db: migrationKysely,
|
|
765
|
+
provider: "postgresql",
|
|
766
|
+
}),
|
|
767
|
+
});
|
|
768
|
+
|
|
769
|
+
try {
|
|
770
|
+
await expect(
|
|
771
|
+
migrationHotUpdater.getBundles({ limit: 10 }),
|
|
772
|
+
).rejects.toThrow(
|
|
773
|
+
"Hot Updater database schema is not initialized for kysely.",
|
|
774
|
+
);
|
|
775
|
+
} finally {
|
|
776
|
+
await migrationKysely.destroy();
|
|
777
|
+
await migrationDb.close();
|
|
778
|
+
}
|
|
779
|
+
});
|
|
780
|
+
|
|
781
|
+
it("rejects runtime access when a Kysely schema is stale", async () => {
|
|
782
|
+
const migrationDb = new PGlite();
|
|
783
|
+
const migrationKysely = new Kysely({
|
|
784
|
+
dialect: new PGliteDialect(migrationDb),
|
|
785
|
+
});
|
|
786
|
+
const migrationHotUpdater = createHotUpdater({
|
|
787
|
+
database: kyselyAdapter({
|
|
788
|
+
db: migrationKysely,
|
|
789
|
+
provider: "postgresql",
|
|
790
|
+
}),
|
|
791
|
+
});
|
|
792
|
+
|
|
793
|
+
try {
|
|
794
|
+
await migrationDb.exec(`
|
|
795
|
+
create table private_hot_updater_settings (
|
|
796
|
+
key varchar(255) primary key,
|
|
797
|
+
value text not null
|
|
798
|
+
);
|
|
799
|
+
insert into private_hot_updater_settings (key, value)
|
|
800
|
+
values ('version', '0.21.0');
|
|
801
|
+
`);
|
|
802
|
+
|
|
803
|
+
await expect(migrationHotUpdater.getChannels()).rejects.toThrow(
|
|
804
|
+
"Hot Updater database schema version 0.21.0 is not supported by kysely.",
|
|
805
|
+
);
|
|
407
806
|
} finally {
|
|
408
807
|
await migrationKysely.destroy();
|
|
409
808
|
await migrationDb.close();
|
|
410
809
|
}
|
|
411
810
|
});
|
|
811
|
+
|
|
812
|
+
it("rejects runtime access when a MongoDB schema is stale", async () => {
|
|
813
|
+
const settings = {
|
|
814
|
+
findOne: vi.fn(async () => ({ key: "version", value: "0.21.0" })),
|
|
815
|
+
};
|
|
816
|
+
const bundles = {
|
|
817
|
+
countDocuments: vi.fn(async () => 0),
|
|
818
|
+
find: vi.fn(),
|
|
819
|
+
findOne: vi.fn(),
|
|
820
|
+
};
|
|
821
|
+
const patches = {
|
|
822
|
+
find: vi.fn(),
|
|
823
|
+
};
|
|
824
|
+
const client = {
|
|
825
|
+
db: () => ({
|
|
826
|
+
collection: (name: string) => {
|
|
827
|
+
if (name === "private_hot_updater_settings") return settings;
|
|
828
|
+
if (name === "bundle_patches") return patches;
|
|
829
|
+
return bundles;
|
|
830
|
+
},
|
|
831
|
+
}),
|
|
832
|
+
} as unknown as MongoClient;
|
|
833
|
+
const mongoHotUpdater = createHotUpdater({
|
|
834
|
+
database: mongoAdapter({ client }),
|
|
835
|
+
});
|
|
836
|
+
|
|
837
|
+
await expect(mongoHotUpdater.getBundles({ limit: 10 })).rejects.toThrow(
|
|
838
|
+
"Hot Updater database schema version 0.21.0 is not supported by mongodb.",
|
|
839
|
+
);
|
|
840
|
+
expect(bundles.countDocuments).not.toHaveBeenCalled();
|
|
841
|
+
});
|
|
842
|
+
});
|
|
843
|
+
|
|
844
|
+
describe("adapter filters", () => {
|
|
845
|
+
it("returns an empty Kysely page for empty set filters", async () => {
|
|
846
|
+
const byId = await hotUpdater.getBundles({
|
|
847
|
+
limit: 10,
|
|
848
|
+
where: { id: { in: [] } },
|
|
849
|
+
});
|
|
850
|
+
const byTargetAppVersion = await hotUpdater.getBundles({
|
|
851
|
+
limit: 10,
|
|
852
|
+
where: { targetAppVersionIn: [] },
|
|
853
|
+
});
|
|
854
|
+
|
|
855
|
+
expect(byId.data).toEqual([]);
|
|
856
|
+
expect(byId.pagination.total).toBe(0);
|
|
857
|
+
expect(byTargetAppVersion.data).toEqual([]);
|
|
858
|
+
expect(byTargetAppVersion.pagination.total).toBe(0);
|
|
859
|
+
});
|
|
860
|
+
|
|
861
|
+
it("combines Prisma targetAppVersion filters without overwriting", async () => {
|
|
862
|
+
const bundles = {
|
|
863
|
+
count: vi.fn(async () => 0),
|
|
864
|
+
createMany: vi.fn(),
|
|
865
|
+
deleteMany: vi.fn(),
|
|
866
|
+
findFirst: vi.fn(),
|
|
867
|
+
findMany: vi.fn(async () => []),
|
|
868
|
+
upsert: vi.fn(),
|
|
869
|
+
};
|
|
870
|
+
const patches = {
|
|
871
|
+
count: vi.fn(),
|
|
872
|
+
createMany: vi.fn(),
|
|
873
|
+
deleteMany: vi.fn(),
|
|
874
|
+
findFirst: vi.fn(),
|
|
875
|
+
findMany: vi.fn(async () => []),
|
|
876
|
+
upsert: vi.fn(),
|
|
877
|
+
};
|
|
878
|
+
const plugin = prismaAdapter({
|
|
879
|
+
prisma: { bundles, bundle_patches: patches },
|
|
880
|
+
provider: "postgresql",
|
|
881
|
+
})();
|
|
882
|
+
|
|
883
|
+
await plugin.getBundles({
|
|
884
|
+
limit: 10,
|
|
885
|
+
where: {
|
|
886
|
+
targetAppVersion: "1.0.x",
|
|
887
|
+
targetAppVersionNotNull: true,
|
|
888
|
+
},
|
|
889
|
+
});
|
|
890
|
+
|
|
891
|
+
expect(bundles.findMany).toHaveBeenCalledWith(
|
|
892
|
+
expect.objectContaining({
|
|
893
|
+
where: expect.objectContaining({
|
|
894
|
+
AND: [
|
|
895
|
+
{ target_app_version: "1.0.x" },
|
|
896
|
+
{ target_app_version: { not: null } },
|
|
897
|
+
],
|
|
898
|
+
}),
|
|
899
|
+
}),
|
|
900
|
+
);
|
|
901
|
+
});
|
|
902
|
+
|
|
903
|
+
it("combines MongoDB targetAppVersion filters without overwriting", async () => {
|
|
904
|
+
const toArray = vi.fn(async () => []);
|
|
905
|
+
const limit = vi.fn(() => ({ toArray }));
|
|
906
|
+
const skip = vi.fn(() => ({ limit }));
|
|
907
|
+
const sort = vi.fn(() => ({ skip }));
|
|
908
|
+
const bundles = {
|
|
909
|
+
countDocuments: vi.fn(async () => 0),
|
|
910
|
+
distinct: vi.fn(),
|
|
911
|
+
find: vi.fn(() => ({ sort })),
|
|
912
|
+
findOne: vi.fn(),
|
|
913
|
+
};
|
|
914
|
+
const patches = {
|
|
915
|
+
deleteMany: vi.fn(),
|
|
916
|
+
find: vi.fn(() => ({
|
|
917
|
+
sort: vi.fn(() => ({ toArray: vi.fn(async () => []) })),
|
|
918
|
+
})),
|
|
919
|
+
insertMany: vi.fn(),
|
|
920
|
+
};
|
|
921
|
+
const client = {
|
|
922
|
+
db: () => ({
|
|
923
|
+
collection: (name: string) =>
|
|
924
|
+
name === "bundle_patches" ? patches : bundles,
|
|
925
|
+
}),
|
|
926
|
+
} as unknown as MongoClient;
|
|
927
|
+
const plugin = mongoAdapter({ client })();
|
|
928
|
+
|
|
929
|
+
await plugin.getBundles({
|
|
930
|
+
limit: 10,
|
|
931
|
+
where: {
|
|
932
|
+
targetAppVersion: "1.0.x",
|
|
933
|
+
targetAppVersionNotNull: true,
|
|
934
|
+
},
|
|
935
|
+
});
|
|
936
|
+
|
|
937
|
+
expect(bundles.countDocuments).toHaveBeenCalledWith({
|
|
938
|
+
$and: [
|
|
939
|
+
{ target_app_version: "1.0.x" },
|
|
940
|
+
{ target_app_version: { $exists: true, $nin: [null, ""] } },
|
|
941
|
+
],
|
|
942
|
+
});
|
|
943
|
+
});
|
|
944
|
+
|
|
945
|
+
it("uses Prisma update-check queries without generic list pagination", async () => {
|
|
946
|
+
const appVersionRow = bundleToRow(appVersionFastPathBundle);
|
|
947
|
+
const fingerprintRow = bundleToRow(fingerprintFastPathBundle);
|
|
948
|
+
const bundles = {
|
|
949
|
+
count: vi.fn(async () => {
|
|
950
|
+
throw new Error("unexpected generic Prisma count");
|
|
951
|
+
}),
|
|
952
|
+
createMany: vi.fn(),
|
|
953
|
+
deleteMany: vi.fn(),
|
|
954
|
+
findFirst: vi.fn(),
|
|
955
|
+
findMany: vi
|
|
956
|
+
.fn()
|
|
957
|
+
.mockResolvedValueOnce([
|
|
958
|
+
{ target_app_version: appVersionRow.target_app_version },
|
|
959
|
+
])
|
|
960
|
+
.mockResolvedValueOnce([appVersionRow])
|
|
961
|
+
.mockResolvedValueOnce([fingerprintRow]),
|
|
962
|
+
upsert: vi.fn(),
|
|
963
|
+
};
|
|
964
|
+
const patches = {
|
|
965
|
+
count: vi.fn(),
|
|
966
|
+
createMany: vi.fn(),
|
|
967
|
+
deleteMany: vi.fn(),
|
|
968
|
+
findFirst: vi.fn(),
|
|
969
|
+
findMany: vi.fn(async () => []),
|
|
970
|
+
upsert: vi.fn(),
|
|
971
|
+
};
|
|
972
|
+
const plugin = prismaAdapter({
|
|
973
|
+
prisma: { bundles, bundle_patches: patches },
|
|
974
|
+
provider: "postgresql",
|
|
975
|
+
})();
|
|
976
|
+
|
|
977
|
+
await expect(
|
|
978
|
+
plugin.getUpdateInfo?.({
|
|
979
|
+
_updateStrategy: "appVersion",
|
|
980
|
+
appVersion: "1.0.0",
|
|
981
|
+
bundleId: NIL_UUID,
|
|
982
|
+
platform: "ios",
|
|
983
|
+
}),
|
|
984
|
+
).resolves.toMatchObject({
|
|
985
|
+
id: appVersionFastPathBundle.id,
|
|
986
|
+
status: "UPDATE",
|
|
987
|
+
});
|
|
988
|
+
await expect(
|
|
989
|
+
plugin.getUpdateInfo?.({
|
|
990
|
+
_updateStrategy: "fingerprint",
|
|
991
|
+
bundleId: NIL_UUID,
|
|
992
|
+
fingerprintHash: "fingerprint-fast-path",
|
|
993
|
+
platform: "ios",
|
|
994
|
+
}),
|
|
995
|
+
).resolves.toMatchObject({
|
|
996
|
+
id: fingerprintFastPathBundle.id,
|
|
997
|
+
status: "UPDATE",
|
|
998
|
+
});
|
|
999
|
+
|
|
1000
|
+
expect(bundles.count).not.toHaveBeenCalled();
|
|
1001
|
+
expect(bundles.findMany).toHaveBeenNthCalledWith(
|
|
1002
|
+
1,
|
|
1003
|
+
expect.objectContaining({
|
|
1004
|
+
select: { target_app_version: true },
|
|
1005
|
+
where: expect.objectContaining({
|
|
1006
|
+
channel: "production",
|
|
1007
|
+
id: { gte: NIL_UUID },
|
|
1008
|
+
}),
|
|
1009
|
+
}),
|
|
1010
|
+
);
|
|
1011
|
+
expect(bundles.findMany).toHaveBeenNthCalledWith(
|
|
1012
|
+
2,
|
|
1013
|
+
expect.objectContaining({
|
|
1014
|
+
where: expect.objectContaining({
|
|
1015
|
+
target_app_version: { in: ["1.0.0"] },
|
|
1016
|
+
}),
|
|
1017
|
+
}),
|
|
1018
|
+
);
|
|
1019
|
+
expect(bundles.findMany).toHaveBeenNthCalledWith(
|
|
1020
|
+
3,
|
|
1021
|
+
expect.objectContaining({
|
|
1022
|
+
where: expect.objectContaining({
|
|
1023
|
+
fingerprint_hash: "fingerprint-fast-path",
|
|
1024
|
+
}),
|
|
1025
|
+
}),
|
|
1026
|
+
);
|
|
1027
|
+
expect(patches.findMany).toHaveBeenCalledTimes(2);
|
|
1028
|
+
});
|
|
1029
|
+
|
|
1030
|
+
it("uses Drizzle update-check queries without generic list pagination", async () => {
|
|
1031
|
+
const appVersionRow = bundleToRow(appVersionFastPathBundle);
|
|
1032
|
+
const fingerprintRow = bundleToRow(fingerprintFastPathBundle);
|
|
1033
|
+
const tables = {
|
|
1034
|
+
bundle_patches: {
|
|
1035
|
+
bundle_id: "bundle_id",
|
|
1036
|
+
id: "patch_id",
|
|
1037
|
+
order_index: "order_index",
|
|
1038
|
+
},
|
|
1039
|
+
bundles: {
|
|
1040
|
+
channel: "channel",
|
|
1041
|
+
enabled: "enabled",
|
|
1042
|
+
fingerprint_hash: "fingerprint_hash",
|
|
1043
|
+
id: "id",
|
|
1044
|
+
platform: "platform",
|
|
1045
|
+
target_app_version: "target_app_version",
|
|
1046
|
+
},
|
|
1047
|
+
};
|
|
1048
|
+
const bundleFindMany = vi
|
|
1049
|
+
.fn()
|
|
1050
|
+
.mockResolvedValueOnce([
|
|
1051
|
+
{ target_app_version: appVersionRow.target_app_version },
|
|
1052
|
+
])
|
|
1053
|
+
.mockResolvedValueOnce([appVersionRow])
|
|
1054
|
+
.mockResolvedValueOnce([fingerprintRow]);
|
|
1055
|
+
const patchFindMany = vi.fn(async () => []);
|
|
1056
|
+
const db = {
|
|
1057
|
+
_: { fullSchema: tables },
|
|
1058
|
+
$count: vi.fn(async () => {
|
|
1059
|
+
throw new Error("unexpected generic Drizzle count");
|
|
1060
|
+
}),
|
|
1061
|
+
delete: vi.fn(() => ({
|
|
1062
|
+
where: vi.fn(async () => undefined),
|
|
1063
|
+
})),
|
|
1064
|
+
insert: vi.fn(),
|
|
1065
|
+
query: {
|
|
1066
|
+
bundle_patches: {
|
|
1067
|
+
findMany: patchFindMany,
|
|
1068
|
+
},
|
|
1069
|
+
bundles: {
|
|
1070
|
+
findFirst: vi.fn(),
|
|
1071
|
+
findMany: bundleFindMany,
|
|
1072
|
+
},
|
|
1073
|
+
},
|
|
1074
|
+
select: vi.fn(),
|
|
1075
|
+
update: vi.fn(),
|
|
1076
|
+
};
|
|
1077
|
+
const plugin = drizzleAdapter({
|
|
1078
|
+
db,
|
|
1079
|
+
provider: "postgresql",
|
|
1080
|
+
})();
|
|
1081
|
+
|
|
1082
|
+
await expect(
|
|
1083
|
+
plugin.getUpdateInfo?.({
|
|
1084
|
+
_updateStrategy: "appVersion",
|
|
1085
|
+
appVersion: "1.0.0",
|
|
1086
|
+
bundleId: NIL_UUID,
|
|
1087
|
+
platform: "ios",
|
|
1088
|
+
}),
|
|
1089
|
+
).resolves.toMatchObject({
|
|
1090
|
+
id: appVersionFastPathBundle.id,
|
|
1091
|
+
status: "UPDATE",
|
|
1092
|
+
});
|
|
1093
|
+
await expect(
|
|
1094
|
+
plugin.getUpdateInfo?.({
|
|
1095
|
+
_updateStrategy: "fingerprint",
|
|
1096
|
+
bundleId: NIL_UUID,
|
|
1097
|
+
fingerprintHash: "fingerprint-fast-path",
|
|
1098
|
+
platform: "ios",
|
|
1099
|
+
}),
|
|
1100
|
+
).resolves.toMatchObject({
|
|
1101
|
+
id: fingerprintFastPathBundle.id,
|
|
1102
|
+
status: "UPDATE",
|
|
1103
|
+
});
|
|
1104
|
+
|
|
1105
|
+
expect(db.$count).not.toHaveBeenCalled();
|
|
1106
|
+
expect(bundleFindMany).toHaveBeenNthCalledWith(
|
|
1107
|
+
1,
|
|
1108
|
+
expect.objectContaining({
|
|
1109
|
+
columns: { target_app_version: true },
|
|
1110
|
+
}),
|
|
1111
|
+
);
|
|
1112
|
+
const appVersionWhere = JSON.stringify(bundleFindMany.mock.calls[0]?.[0]);
|
|
1113
|
+
const fingerprintWhere = JSON.stringify(
|
|
1114
|
+
bundleFindMany.mock.calls[2]?.[0],
|
|
1115
|
+
);
|
|
1116
|
+
expect(appVersionWhere).toContain("production");
|
|
1117
|
+
expect(appVersionWhere).toContain(NIL_UUID);
|
|
1118
|
+
expect(fingerprintWhere).toContain("production");
|
|
1119
|
+
expect(fingerprintWhere).toContain(NIL_UUID);
|
|
1120
|
+
expect(fingerprintWhere).toContain("fingerprint-fast-path");
|
|
1121
|
+
expect(bundleFindMany).toHaveBeenCalledTimes(3);
|
|
1122
|
+
expect(patchFindMany).toHaveBeenCalledTimes(2);
|
|
1123
|
+
});
|
|
1124
|
+
|
|
1125
|
+
it("uses MongoDB update-check queries without generic list pagination", async () => {
|
|
1126
|
+
const appVersionRow = bundleToRow(appVersionFastPathBundle);
|
|
1127
|
+
const fingerprintRow = bundleToRow(fingerprintFastPathBundle);
|
|
1128
|
+
const projectToArray = vi.fn(async () => [
|
|
1129
|
+
{ target_app_version: appVersionRow.target_app_version },
|
|
1130
|
+
]);
|
|
1131
|
+
const sortToArray = vi
|
|
1132
|
+
.fn()
|
|
1133
|
+
.mockResolvedValueOnce([appVersionRow])
|
|
1134
|
+
.mockResolvedValueOnce([fingerprintRow]);
|
|
1135
|
+
const project = vi.fn(() => ({ toArray: projectToArray }));
|
|
1136
|
+
const sort = vi.fn(() => ({ toArray: sortToArray }));
|
|
1137
|
+
const bundles = {
|
|
1138
|
+
countDocuments: vi.fn(async () => {
|
|
1139
|
+
throw new Error("unexpected generic MongoDB count");
|
|
1140
|
+
}),
|
|
1141
|
+
deleteMany: vi.fn(),
|
|
1142
|
+
distinct: vi.fn(),
|
|
1143
|
+
find: vi.fn((filter: Record<string, unknown>) => {
|
|
1144
|
+
const targetAppVersion = filter["target_app_version"];
|
|
1145
|
+
if (
|
|
1146
|
+
typeof targetAppVersion === "object" &&
|
|
1147
|
+
targetAppVersion !== null &&
|
|
1148
|
+
"$exists" in targetAppVersion
|
|
1149
|
+
) {
|
|
1150
|
+
return { project };
|
|
1151
|
+
}
|
|
1152
|
+
return { sort };
|
|
1153
|
+
}),
|
|
1154
|
+
findOne: vi.fn(),
|
|
1155
|
+
updateOne: vi.fn(),
|
|
1156
|
+
};
|
|
1157
|
+
const patches = {
|
|
1158
|
+
deleteMany: vi.fn(),
|
|
1159
|
+
find: vi.fn(() => ({
|
|
1160
|
+
sort: vi.fn(() => ({ toArray: vi.fn(async () => []) })),
|
|
1161
|
+
})),
|
|
1162
|
+
insertMany: vi.fn(),
|
|
1163
|
+
};
|
|
1164
|
+
const client = {
|
|
1165
|
+
db: () => ({
|
|
1166
|
+
collection: (name: string) =>
|
|
1167
|
+
name === "bundle_patches" ? patches : bundles,
|
|
1168
|
+
}),
|
|
1169
|
+
} as unknown as MongoClient;
|
|
1170
|
+
const plugin = mongoAdapter({ client })();
|
|
1171
|
+
|
|
1172
|
+
await expect(
|
|
1173
|
+
plugin.getUpdateInfo?.({
|
|
1174
|
+
_updateStrategy: "appVersion",
|
|
1175
|
+
appVersion: "1.0.0",
|
|
1176
|
+
bundleId: NIL_UUID,
|
|
1177
|
+
platform: "ios",
|
|
1178
|
+
}),
|
|
1179
|
+
).resolves.toMatchObject({
|
|
1180
|
+
id: appVersionFastPathBundle.id,
|
|
1181
|
+
status: "UPDATE",
|
|
1182
|
+
});
|
|
1183
|
+
await expect(
|
|
1184
|
+
plugin.getUpdateInfo?.({
|
|
1185
|
+
_updateStrategy: "fingerprint",
|
|
1186
|
+
bundleId: NIL_UUID,
|
|
1187
|
+
fingerprintHash: "fingerprint-fast-path",
|
|
1188
|
+
platform: "ios",
|
|
1189
|
+
}),
|
|
1190
|
+
).resolves.toMatchObject({
|
|
1191
|
+
id: fingerprintFastPathBundle.id,
|
|
1192
|
+
status: "UPDATE",
|
|
1193
|
+
});
|
|
1194
|
+
|
|
1195
|
+
expect(bundles.countDocuments).not.toHaveBeenCalled();
|
|
1196
|
+
expect(bundles.find).toHaveBeenNthCalledWith(
|
|
1197
|
+
1,
|
|
1198
|
+
expect.objectContaining({
|
|
1199
|
+
channel: "production",
|
|
1200
|
+
id: { $gte: NIL_UUID },
|
|
1201
|
+
target_app_version: { $exists: true, $nin: [null, ""] },
|
|
1202
|
+
}),
|
|
1203
|
+
);
|
|
1204
|
+
expect(bundles.find).toHaveBeenNthCalledWith(
|
|
1205
|
+
2,
|
|
1206
|
+
expect.objectContaining({
|
|
1207
|
+
target_app_version: { $in: ["1.0.0"] },
|
|
1208
|
+
}),
|
|
1209
|
+
);
|
|
1210
|
+
expect(bundles.find).toHaveBeenNthCalledWith(
|
|
1211
|
+
3,
|
|
1212
|
+
expect.objectContaining({
|
|
1213
|
+
fingerprint_hash: "fingerprint-fast-path",
|
|
1214
|
+
}),
|
|
1215
|
+
);
|
|
1216
|
+
expect(patches.find).toHaveBeenCalledTimes(2);
|
|
1217
|
+
});
|
|
1218
|
+
|
|
1219
|
+
it("commits Prisma bundle changes inside a transaction when available", async () => {
|
|
1220
|
+
const rootBundles = {
|
|
1221
|
+
count: vi.fn(),
|
|
1222
|
+
createMany: vi.fn(),
|
|
1223
|
+
deleteMany: vi.fn(),
|
|
1224
|
+
findFirst: vi.fn(),
|
|
1225
|
+
findMany: vi.fn(),
|
|
1226
|
+
upsert: vi.fn(),
|
|
1227
|
+
};
|
|
1228
|
+
const rootPatches = {
|
|
1229
|
+
count: vi.fn(),
|
|
1230
|
+
createMany: vi.fn(),
|
|
1231
|
+
deleteMany: vi.fn(),
|
|
1232
|
+
findFirst: vi.fn(),
|
|
1233
|
+
findMany: vi.fn(),
|
|
1234
|
+
upsert: vi.fn(),
|
|
1235
|
+
};
|
|
1236
|
+
const txBundles = {
|
|
1237
|
+
...rootBundles,
|
|
1238
|
+
upsert: vi.fn(async () => undefined),
|
|
1239
|
+
};
|
|
1240
|
+
const txPatches = {
|
|
1241
|
+
...rootPatches,
|
|
1242
|
+
deleteMany: vi.fn(async () => undefined),
|
|
1243
|
+
};
|
|
1244
|
+
const $transaction = vi.fn(
|
|
1245
|
+
async (operation: (tx: Record<string, unknown>) => Promise<unknown>) =>
|
|
1246
|
+
operation({
|
|
1247
|
+
bundle_patches: txPatches,
|
|
1248
|
+
bundles: txBundles,
|
|
1249
|
+
}),
|
|
1250
|
+
);
|
|
1251
|
+
const plugin = prismaAdapter({
|
|
1252
|
+
prisma: {
|
|
1253
|
+
$transaction,
|
|
1254
|
+
bundle_patches: rootPatches,
|
|
1255
|
+
bundles: rootBundles,
|
|
1256
|
+
},
|
|
1257
|
+
provider: "postgresql",
|
|
1258
|
+
})();
|
|
1259
|
+
|
|
1260
|
+
await plugin.appendBundle(transactionBundle);
|
|
1261
|
+
await plugin.commitBundle();
|
|
1262
|
+
|
|
1263
|
+
expect($transaction).toHaveBeenCalledTimes(1);
|
|
1264
|
+
expect(txBundles.upsert).toHaveBeenCalledTimes(1);
|
|
1265
|
+
expect(rootBundles.upsert).not.toHaveBeenCalled();
|
|
1266
|
+
});
|
|
1267
|
+
|
|
1268
|
+
it("commits Drizzle bundle changes inside a transaction when available", async () => {
|
|
1269
|
+
const tables = {
|
|
1270
|
+
bundle_patches: {
|
|
1271
|
+
bundle_id: "bundle_id",
|
|
1272
|
+
id: "patch_id",
|
|
1273
|
+
order_index: "order_index",
|
|
1274
|
+
},
|
|
1275
|
+
bundles: {
|
|
1276
|
+
id: "id",
|
|
1277
|
+
},
|
|
1278
|
+
};
|
|
1279
|
+
const rootInsert = vi.fn(() => ({
|
|
1280
|
+
values: vi.fn(() => ({ execute: vi.fn(async () => undefined) })),
|
|
1281
|
+
}));
|
|
1282
|
+
const txInsert = vi.fn(() => ({
|
|
1283
|
+
values: vi.fn(() => ({ execute: vi.fn(async () => undefined) })),
|
|
1284
|
+
}));
|
|
1285
|
+
const createDb = (insert: typeof rootInsert) => ({
|
|
1286
|
+
_: { fullSchema: tables },
|
|
1287
|
+
$count: vi.fn(),
|
|
1288
|
+
delete: vi.fn(() => ({
|
|
1289
|
+
where: vi.fn(async () => undefined),
|
|
1290
|
+
})),
|
|
1291
|
+
insert,
|
|
1292
|
+
query: {
|
|
1293
|
+
bundle_patches: {
|
|
1294
|
+
findMany: vi.fn(),
|
|
1295
|
+
},
|
|
1296
|
+
bundles: {
|
|
1297
|
+
findFirst: vi.fn(async () => undefined),
|
|
1298
|
+
findMany: vi.fn(),
|
|
1299
|
+
},
|
|
1300
|
+
},
|
|
1301
|
+
select: vi.fn(),
|
|
1302
|
+
update: vi.fn(() => ({
|
|
1303
|
+
set: vi.fn(() => ({
|
|
1304
|
+
where: vi.fn(async () => undefined),
|
|
1305
|
+
})),
|
|
1306
|
+
})),
|
|
1307
|
+
});
|
|
1308
|
+
const txDb = createDb(txInsert);
|
|
1309
|
+
const transaction = vi.fn(
|
|
1310
|
+
async (operation: (tx: typeof txDb) => Promise<unknown>) =>
|
|
1311
|
+
operation(txDb),
|
|
1312
|
+
);
|
|
1313
|
+
const db = {
|
|
1314
|
+
...createDb(rootInsert),
|
|
1315
|
+
transaction,
|
|
1316
|
+
};
|
|
1317
|
+
const plugin = drizzleAdapter({
|
|
1318
|
+
db,
|
|
1319
|
+
provider: "postgresql",
|
|
1320
|
+
})();
|
|
1321
|
+
|
|
1322
|
+
await plugin.appendBundle(transactionBundle);
|
|
1323
|
+
await plugin.commitBundle();
|
|
1324
|
+
|
|
1325
|
+
expect(transaction).toHaveBeenCalledTimes(1);
|
|
1326
|
+
expect(txInsert).toHaveBeenCalledTimes(1);
|
|
1327
|
+
expect(rootInsert).not.toHaveBeenCalled();
|
|
1328
|
+
});
|
|
1329
|
+
|
|
1330
|
+
it("commits MongoDB bundle changes inside a session transaction when available", async () => {
|
|
1331
|
+
const session = {
|
|
1332
|
+
endSession: vi.fn(async () => undefined),
|
|
1333
|
+
withTransaction: vi.fn(async (operation: () => Promise<void>) =>
|
|
1334
|
+
operation(),
|
|
1335
|
+
),
|
|
1336
|
+
};
|
|
1337
|
+
const bundles = {
|
|
1338
|
+
countDocuments: vi.fn(),
|
|
1339
|
+
deleteMany: vi.fn(),
|
|
1340
|
+
distinct: vi.fn(),
|
|
1341
|
+
find: vi.fn(),
|
|
1342
|
+
findOne: vi.fn(),
|
|
1343
|
+
updateOne: vi.fn(async () => undefined),
|
|
1344
|
+
};
|
|
1345
|
+
const patches = {
|
|
1346
|
+
deleteMany: vi.fn(async () => undefined),
|
|
1347
|
+
find: vi.fn(),
|
|
1348
|
+
insertMany: vi.fn(),
|
|
1349
|
+
};
|
|
1350
|
+
const client = {
|
|
1351
|
+
db: () => ({
|
|
1352
|
+
collection: (name: string) =>
|
|
1353
|
+
name === "bundle_patches" ? patches : bundles,
|
|
1354
|
+
}),
|
|
1355
|
+
startSession: vi.fn(() => session),
|
|
1356
|
+
} as unknown as MongoClient;
|
|
1357
|
+
const plugin = mongoAdapter({ client })();
|
|
1358
|
+
|
|
1359
|
+
await plugin.appendBundle(transactionBundle);
|
|
1360
|
+
await plugin.commitBundle();
|
|
1361
|
+
|
|
1362
|
+
expect(client.startSession).toHaveBeenCalledTimes(1);
|
|
1363
|
+
expect(session.withTransaction).toHaveBeenCalledTimes(1);
|
|
1364
|
+
expect(bundles.updateOne).toHaveBeenCalledWith(
|
|
1365
|
+
{ id: transactionBundle.id },
|
|
1366
|
+
expect.any(Object),
|
|
1367
|
+
expect.objectContaining({ session, upsert: true }),
|
|
1368
|
+
);
|
|
1369
|
+
expect(patches.deleteMany).toHaveBeenCalledWith(
|
|
1370
|
+
{ bundle_id: transactionBundle.id },
|
|
1371
|
+
{ session },
|
|
1372
|
+
);
|
|
1373
|
+
expect(session.endSession).toHaveBeenCalledTimes(1);
|
|
1374
|
+
});
|
|
412
1375
|
});
|
|
413
1376
|
|
|
414
1377
|
describe("bundle validation", () => {
|