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