upgrading/app/upgrades/0.15-to-0.16/instructions.md
upgrading/app/upgrades/0.15-to-0.16/instructions.mdBrowse 76 files
2,824 tokens
11,293 bytes
Token encoding: o200k_base
Snapshot fac8604
← Back to SKILL.md
from: "0.15" to: "0.16" changes:
- id: extension-supabase-test-utils-export-removed
summary: |
@internal/extension-supabaseno longer exports the./test/utilssubpath (bootstrapSupabaseShim). The import typechecked (types shipped indist), but the subpath never worked from npm — the shim reads fixture.sqlfiles that were never published, so every call failed with ENOENT before touching a database. There is no working code to migrate: delete the import and whatever test setup calledbootstrapSupabaseShim. detection: glob: "**/*.{ts,mts,cts,js,mjs}" contains: - "extension-supabase/test/utils" anyMatch: true - id: identity-columns-need-explicit-default-under-strict-verify
summary: |
contract infernow emits@default(autoincrement())for a PostgresGENERATED ALWAYS AS IDENTITY/GENERATED BY DEFAULT AS IDENTITYcolumn (previously it emitted a bare column with no default, since Postgres reports nocolumn_defaultfor an identity column). Symmetrically,db verifyintrospecting a live identity column now resolves its default toautoincrement()too (previously it resolved to nothing). This only changesdb verify --strict— without--strict, an undeclared live default is tolerated either way. If you rundb verify --strictagainst a table with an identity column whose contract does not declare@default(autoincrement())(because it predates this fix), verify now reports that default as an unexpected extra. Re-runcontract inferfor the affected table, or add@default(autoincrement())by hand, to match what the database has always generated. - id: pluralize-back-relation-names-no-longer-double-pluralize
summary: |
contract infer's back-relation field name generation used a hand-rolled pluralization rule that appendedesto any table name already ending ins/x/z/ch/sh, doubling an already-plural table name (sessions->sessionses).contract infernow uses real inflection (thepluralizelibrary) and produces the correct name (sessionsstayssessions; a genuinely singularstatusstill becomesstatuses). This only affects a futurecontract inferrun — an already-generated.prismafile is untouched, so nothing breaks until you next re-run infer. If you do re-runcontract inferagainst a database with an already-plural table name, diff the regenerated.prismafile for any back-relation field whose name changed — that's a public field name your application code accesses via.include()/.select()/the generated TypeScript types, so update those call sites to the corrected name. - id: scalar-type-descriptors-channel-removed
summary: |
The scalar-type descriptor channel is retired in favour of the unified authoring type
namespace. Projects with custom control-stack setups that import
createPostgresScalarTypeDescriptors/createSqliteScalarTypeDescriptors, or that readscalarTypeDescriptorsfrom a control stack or contract-source context, must migrate: those exports are deleted, and scalar types are now zero-arg type-constructor contributions in the component'sauthoring.typenamespace — e.g.String: { kind: 'typeConstructor', output: { codecId: 'pg/text@1', nativeType: 'text' } }. Read the scalar type names viastack.scalarTypes, or the full name ->{ codecId, nativeType }map viacollectScalarTypeConstructors(stack.authoringContributions.type)from@internal/framework-components/authoring. Standard target setups (@internal/postgres,@internal/sqlite) supply the contributions themselves. detection: glob: "**/*.{ts,mts,cts}" contains: - "createPostgresScalarTypeDescriptors" - "createSqliteScalarTypeDescriptors" - "scalarTypeDescriptors" anyMatch: true - id: postgres-json-rebound-to-native-json
summary: |
On the postgres target the PSL
Jsonscalar re-binds frompg/jsonb@1/jsonbtopg/json@1/json; a new bareJsonbscalar carriespg/jsonb@1/jsonb. Postgres schemas that useJsonand mean jsonb storage (which every pre-0.16Jsonfield did) must switch those fields — andtypes {}aliases — toJsonb, then re-runprisma-next contract emit; withJsonbthe emittedcontract.jsonis byte-identical to the pre-0.16 output. A field left asJsonnow emits a nativejsoncolumn and a new storage hash, which against an existing jsonb database is a schema change. The legacy@db.Jsonattribute path is unchanged (Json @db.Jsonstill yieldspg/json@1/json), and sqlite/mongoJsonbindings are untouched. The TS builder surface (field.json(),jsonbColumn) is unchanged and stays jsonb. detection: glob: "**/*.prisma" contains: - "Json" anyMatch: true - id: default-generators-no-longer-set-storage
summary: |
@default(<generator>)no longer influences a column's storage — the type position is the only storage decider. Pre-0.16, a generator default on a bareStringfield re-picked the column's storage to a sized char:String @default(uuid())/@default(uuid(7))emittedsql/char@1/character(36),@default(cuid(2))character(24),@default(nanoid())character(21)(orcharacter(<size>)fornanoid(<size>)), and@default(ulid())character(26). From 0.16 such fields emit the target'sStringstorage (postgres:pg/text@1/text) with the same execution-time generator, so a re-emit produces a new storage hash — against an existing database created with the char storage this is a schema change. To keep the prior storage byte-identical, name it in the type position:Char(36) @default(uuid()),Char(24) @default(cuid(2)),Char(21) @default(nanoid())(orChar(<size>)for a sized nanoid),Char(26) @default(ulid())— or adopt nativeUuidforuuid()if auuid-typed column is preferred (that is a schema change too). Then re-runprisma-next contract emitand, if you accepted a storage change, plan/apply the matching migration. Generator applicability validation is unchanged (uuid()onIntstill fails withPSL_INVALID_DEFAULT_APPLICABILITY), and the TS builder presets (field.id.uuidv4String(),field.generated(uuidv4()), …) are untouched — they bundle theirchar(N)storage explicitly. detection: glob: "**/*.prisma" contains: - "@default(uuid(" - "@default(cuid(" - "@default(nanoid(" - "@default(ulid(" anyMatch: true