joist-codegen 2.3.0-next.5 → 2.3.0-next.51
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/build/EntityDbMetadata.cjs +608 -0
- package/build/EntityDbMetadata.cjs.map +1 -0
- package/build/EntityDbMetadata.d.cts +274 -0
- package/build/EntityDbMetadata.d.cts.map +1 -0
- package/build/EntityDbMetadata.d.mts +274 -0
- package/build/EntityDbMetadata.d.mts.map +1 -0
- package/build/EntityDbMetadata.js +485 -661
- package/build/EntityDbMetadata.js.map +1 -1
- package/build/_virtual/_rolldown/runtime.cjs +23 -0
- package/build/_virtual/_rolldown/runtime.js +5 -0
- package/build/assignTags.cjs +45 -0
- package/build/assignTags.cjs.map +1 -0
- package/build/{assignTags.d.ts → assignTags.d.cts} +8 -4
- package/build/assignTags.d.cts.map +1 -0
- package/build/assignTags.d.mts +16 -0
- package/build/assignTags.d.mts.map +1 -0
- package/build/assignTags.js +37 -59
- package/build/assignTags.js.map +1 -1
- package/build/codemods/Codemod.cjs +2 -0
- package/build/codemods/Codemod.d.cts +17 -0
- package/build/codemods/Codemod.d.cts.map +1 -0
- package/build/codemods/Codemod.d.mts +17 -0
- package/build/codemods/Codemod.d.mts.map +1 -0
- package/build/codemods/Codemod.js +2 -3
- package/build/codemods/JscodeshiftMod.cjs +42 -0
- package/build/codemods/JscodeshiftMod.cjs.map +1 -0
- package/build/codemods/JscodeshiftMod.d.cts +14 -0
- package/build/codemods/JscodeshiftMod.d.cts.map +1 -0
- package/build/codemods/JscodeshiftMod.d.mts +14 -0
- package/build/codemods/JscodeshiftMod.d.mts.map +1 -0
- package/build/codemods/JscodeshiftMod.js +33 -33
- package/build/codemods/JscodeshiftMod.js.map +1 -1
- package/build/codemods/codemod_0001-rename_has_async_property.cjs +30 -0
- package/build/codemods/codemod_0001-rename_has_async_property.cjs.map +1 -0
- package/build/codemods/codemod_0001-rename_has_async_property.d.cts +9 -0
- package/build/codemods/codemod_0001-rename_has_async_property.d.cts.map +1 -0
- package/build/codemods/codemod_0001-rename_has_async_property.d.mts +9 -0
- package/build/codemods/codemod_0001-rename_has_async_property.d.mts.map +1 -0
- package/build/codemods/codemod_0001-rename_has_async_property.js +21 -25
- package/build/codemods/codemod_0001-rename_has_async_property.js.map +1 -1
- package/build/codemods/codemod_0002-rename_async_query_fields.cjs +50 -0
- package/build/codemods/codemod_0002-rename_async_query_fields.cjs.map +1 -0
- package/build/codemods/codemod_0002-rename_async_query_fields.d.cts +9 -0
- package/build/codemods/codemod_0002-rename_async_query_fields.d.cts.map +1 -0
- package/build/codemods/codemod_0002-rename_async_query_fields.d.mts +9 -0
- package/build/codemods/codemod_0002-rename_async_query_fields.d.mts.map +1 -0
- package/build/codemods/codemod_0002-rename_async_query_fields.js +38 -52
- package/build/codemods/codemod_0002-rename_async_query_fields.js.map +1 -1
- package/build/codemods/codemod_0003-rename_find_paginated.cjs +25 -0
- package/build/codemods/codemod_0003-rename_find_paginated.cjs.map +1 -0
- package/build/codemods/codemod_0003-rename_find_paginated.d.cts +9 -0
- package/build/codemods/codemod_0003-rename_find_paginated.d.cts.map +1 -0
- package/build/codemods/codemod_0003-rename_find_paginated.d.mts +9 -0
- package/build/codemods/codemod_0003-rename_find_paginated.d.mts.map +1 -0
- package/build/codemods/codemod_0003-rename_find_paginated.js +17 -26
- package/build/codemods/codemod_0003-rename_find_paginated.js.map +1 -1
- package/build/codemods/index.cjs +49 -0
- package/build/codemods/index.cjs.map +1 -0
- package/build/codemods/index.d.cts +12 -0
- package/build/codemods/index.d.cts.map +1 -0
- package/build/codemods/index.d.mts +12 -0
- package/build/codemods/index.d.mts.map +1 -0
- package/build/codemods/index.js +34 -42
- package/build/codemods/index.js.map +1 -1
- package/build/config.cjs +377 -0
- package/build/config.cjs.map +1 -0
- package/build/config.d.cts +181 -0
- package/build/config.d.cts.map +1 -0
- package/build/config.d.mts +181 -0
- package/build/config.d.mts.map +1 -0
- package/build/config.js +309 -347
- package/build/config.js.map +1 -1
- package/build/docs/cache.cjs +62 -0
- package/build/docs/cache.cjs.map +1 -0
- package/build/docs/cache.d.cts +17 -0
- package/build/docs/cache.d.cts.map +1 -0
- package/build/docs/cache.d.mts +17 -0
- package/build/docs/cache.d.mts.map +1 -0
- package/build/docs/cache.js +52 -53
- package/build/docs/cache.js.map +1 -1
- package/build/docs/generate-metadata-docs.cjs +32 -0
- package/build/docs/generate-metadata-docs.cjs.map +1 -0
- package/build/docs/generate-metadata-docs.d.cts +9 -0
- package/build/docs/generate-metadata-docs.d.cts.map +1 -0
- package/build/docs/generate-metadata-docs.d.mts +9 -0
- package/build/docs/generate-metadata-docs.d.mts.map +1 -0
- package/build/docs/generate-metadata-docs.js +19 -24
- package/build/docs/generate-metadata-docs.js.map +1 -1
- package/build/docs/index.cjs +90 -0
- package/build/docs/index.cjs.map +1 -0
- package/build/docs/index.d.cts +16 -0
- package/build/docs/index.d.cts.map +1 -0
- package/build/docs/index.d.mts +16 -0
- package/build/docs/index.d.mts.map +1 -0
- package/build/docs/index.js +75 -80
- package/build/docs/index.js.map +1 -1
- package/build/docs/markdown.cjs +181 -0
- package/build/docs/markdown.cjs.map +1 -0
- package/build/docs/{markdown.d.ts → markdown.d.cts} +14 -12
- package/build/docs/markdown.d.cts.map +1 -0
- package/build/docs/markdown.d.mts +32 -0
- package/build/docs/markdown.d.mts.map +1 -0
- package/build/docs/markdown.js +152 -220
- package/build/docs/markdown.js.map +1 -1
- package/build/docs/parsing.cjs +117 -0
- package/build/docs/parsing.cjs.map +1 -0
- package/build/docs/parsing.d.cts +48 -0
- package/build/docs/parsing.d.cts.map +1 -0
- package/build/docs/parsing.d.mts +48 -0
- package/build/docs/parsing.d.mts.map +1 -0
- package/build/docs/parsing.js +89 -88
- package/build/docs/parsing.js.map +1 -1
- package/build/findEntityScopes.cjs +119 -0
- package/build/findEntityScopes.cjs.map +1 -0
- package/build/findEntityScopes.d.cts +14 -0
- package/build/findEntityScopes.d.cts.map +1 -0
- package/build/findEntityScopes.d.mts +14 -0
- package/build/findEntityScopes.d.mts.map +1 -0
- package/build/findEntityScopes.js +83 -111
- package/build/findEntityScopes.js.map +1 -1
- package/build/foreignKeyOrdering.cjs +52 -0
- package/build/foreignKeyOrdering.cjs.map +1 -0
- package/build/foreignKeyOrdering.d.cts +8 -0
- package/build/foreignKeyOrdering.d.cts.map +1 -0
- package/build/foreignKeyOrdering.d.mts +8 -0
- package/build/foreignKeyOrdering.d.mts.map +1 -0
- package/build/foreignKeyOrdering.js +46 -55
- package/build/foreignKeyOrdering.js.map +1 -1
- package/build/generate.cjs +127 -0
- package/build/generate.cjs.map +1 -0
- package/build/generate.d.cts +17 -0
- package/build/generate.d.cts.map +1 -0
- package/build/generate.d.mts +17 -0
- package/build/generate.d.mts.map +1 -0
- package/build/generate.js +110 -124
- package/build/generate.js.map +1 -1
- package/build/generateEntitiesFile.cjs +46 -0
- package/build/generateEntitiesFile.cjs.map +1 -0
- package/build/generateEntitiesFile.d.cts +11 -0
- package/build/generateEntitiesFile.d.cts.map +1 -0
- package/build/generateEntitiesFile.d.mts +11 -0
- package/build/generateEntitiesFile.d.mts.map +1 -0
- package/build/generateEntitiesFile.js +28 -25
- package/build/generateEntitiesFile.js.map +1 -1
- package/build/generateEntityCodegenFile.cjs +936 -0
- package/build/generateEntityCodegenFile.cjs.map +1 -0
- package/build/generateEntityCodegenFile.d.cts +16 -0
- package/build/generateEntityCodegenFile.d.cts.map +1 -0
- package/build/generateEntityCodegenFile.d.mts +16 -0
- package/build/generateEntityCodegenFile.d.mts.map +1 -0
- package/build/generateEntityCodegenFile.js +718 -826
- package/build/generateEntityCodegenFile.js.map +1 -1
- package/build/generateEntityFile.cjs +23 -0
- package/build/generateEntityFile.cjs.map +1 -0
- package/build/generateEntityFile.d.cts +9 -0
- package/build/generateEntityFile.d.cts.map +1 -0
- package/build/generateEntityFile.d.mts +9 -0
- package/build/generateEntityFile.d.mts.map +1 -0
- package/build/generateEntityFile.js +11 -8
- package/build/generateEntityFile.js.map +1 -1
- package/build/generateEntityTestFile.cjs +25 -0
- package/build/generateEntityTestFile.cjs.map +1 -0
- package/build/generateEntityTestFile.d.cts +9 -0
- package/build/generateEntityTestFile.d.cts.map +1 -0
- package/build/generateEntityTestFile.d.mts +9 -0
- package/build/generateEntityTestFile.d.mts.map +1 -0
- package/build/generateEntityTestFile.js +10 -7
- package/build/generateEntityTestFile.js.map +1 -1
- package/build/generateEnumFile.cjs +73 -0
- package/build/generateEnumFile.cjs.map +1 -0
- package/build/generateEnumFile.d.cts +9 -0
- package/build/generateEnumFile.d.cts.map +1 -0
- package/build/generateEnumFile.d.mts +9 -0
- package/build/generateEnumFile.d.mts.map +1 -0
- package/build/generateEnumFile.js +33 -43
- package/build/generateEnumFile.js.map +1 -1
- package/build/generateFactoriesFiles.cjs +28 -0
- package/build/generateFactoriesFiles.cjs.map +1 -0
- package/build/generateFactoriesFiles.d.cts +7 -0
- package/build/generateFactoriesFiles.d.cts.map +1 -0
- package/build/generateFactoriesFiles.d.mts +7 -0
- package/build/generateFactoriesFiles.d.mts.map +1 -0
- package/build/generateFactoriesFiles.js +21 -16
- package/build/generateFactoriesFiles.js.map +1 -1
- package/build/generateFlushFunction.cjs +61 -0
- package/build/generateFlushFunction.cjs.map +1 -0
- package/build/{generateFlushFunction.d.ts → generateFlushFunction.d.cts} +8 -5
- package/build/generateFlushFunction.d.cts.map +1 -0
- package/build/generateFlushFunction.d.mts +23 -0
- package/build/generateFlushFunction.d.mts.map +1 -0
- package/build/generateFlushFunction.js +32 -78
- package/build/generateFlushFunction.js.map +1 -1
- package/build/generateMetadataFile.cjs +290 -0
- package/build/generateMetadataFile.cjs.map +1 -0
- package/build/generateMetadataFile.d.cts +8 -0
- package/build/generateMetadataFile.d.cts.map +1 -0
- package/build/generateMetadataFile.d.mts +8 -0
- package/build/generateMetadataFile.d.mts.map +1 -0
- package/build/generateMetadataFile.js +116 -140
- package/build/generateMetadataFile.js.map +1 -1
- package/build/generatePgEnumFile.cjs +21 -0
- package/build/generatePgEnumFile.cjs.map +1 -0
- package/build/generatePgEnumFile.d.cts +9 -0
- package/build/generatePgEnumFile.d.cts.map +1 -0
- package/build/generatePgEnumFile.d.mts +9 -0
- package/build/generatePgEnumFile.d.mts.map +1 -0
- package/build/generatePgEnumFile.js +12 -9
- package/build/generatePgEnumFile.js.map +1 -1
- package/build/index.cjs +135 -0
- package/build/index.cjs.map +1 -0
- package/build/index.d.cts +12 -0
- package/build/index.d.cts.map +1 -0
- package/build/index.d.mts +12 -0
- package/build/index.d.mts.map +1 -0
- package/build/index.js +108 -127
- package/build/index.js.map +1 -1
- package/build/inheritance.cjs +213 -0
- package/build/inheritance.cjs.map +1 -0
- package/build/inheritance.d.cts +12 -0
- package/build/inheritance.d.cts.map +1 -0
- package/build/inheritance.d.mts +12 -0
- package/build/inheritance.d.mts.map +1 -0
- package/build/inheritance.js +193 -247
- package/build/inheritance.js.map +1 -1
- package/build/installSkills.cjs +68 -0
- package/build/installSkills.cjs.map +1 -0
- package/build/installSkills.d.cts +16 -0
- package/build/installSkills.d.cts.map +1 -0
- package/build/installSkills.d.mts +16 -0
- package/build/installSkills.d.mts.map +1 -0
- package/build/installSkills.js +67 -0
- package/build/installSkills.js.map +1 -0
- package/build/keywords.cjs +7 -0
- package/build/keywords.cjs.map +1 -0
- package/build/keywords.d.cts +5 -0
- package/build/keywords.d.cts.map +1 -0
- package/build/keywords.d.mts +5 -0
- package/build/keywords.d.mts.map +1 -0
- package/build/keywords.js +5 -4
- package/build/keywords.js.map +1 -1
- package/build/loadMetadata.cjs +39 -0
- package/build/loadMetadata.cjs.map +1 -0
- package/build/loadMetadata.d.cts +31 -0
- package/build/loadMetadata.d.cts.map +1 -0
- package/build/loadMetadata.d.mts +31 -0
- package/build/loadMetadata.d.mts.map +1 -0
- package/build/loadMetadata.js +32 -39
- package/build/loadMetadata.js.map +1 -1
- package/build/logger.cjs +28 -0
- package/build/logger.cjs.map +1 -0
- package/build/logger.d.cts +13 -0
- package/build/logger.d.cts.map +1 -0
- package/build/logger.d.mts +13 -0
- package/build/logger.d.mts.map +1 -0
- package/build/logger.js +17 -16
- package/build/logger.js.map +1 -1
- package/build/scanEntityFiles.cjs +46 -0
- package/build/scanEntityFiles.cjs.map +1 -0
- package/build/scanEntityFiles.d.cts +8 -0
- package/build/scanEntityFiles.d.cts.map +1 -0
- package/build/scanEntityFiles.d.mts +8 -0
- package/build/scanEntityFiles.d.mts.map +1 -0
- package/build/scanEntityFiles.js +37 -42
- package/build/scanEntityFiles.js.map +1 -1
- package/build/sortForeignKeys.cjs +99 -0
- package/build/sortForeignKeys.cjs.map +1 -0
- package/build/{sortForeignKeys.d.ts → sortForeignKeys.d.cts} +8 -5
- package/build/sortForeignKeys.d.cts.map +1 -0
- package/build/sortForeignKeys.d.mts +35 -0
- package/build/sortForeignKeys.d.mts.map +1 -0
- package/build/sortForeignKeys.js +88 -117
- package/build/sortForeignKeys.js.map +1 -1
- package/build/symbols.cjs +226 -0
- package/build/symbols.cjs.map +1 -0
- package/build/symbols.d.cts +114 -0
- package/build/symbols.d.cts.map +1 -0
- package/build/symbols.d.mts +114 -0
- package/build/symbols.d.mts.map +1 -0
- package/build/symbols.js +115 -113
- package/build/symbols.js.map +1 -1
- package/build/tsdoc.cjs +22 -0
- package/build/tsdoc.cjs.map +1 -0
- package/build/tsdoc.d.cts +15 -0
- package/build/tsdoc.d.cts.map +1 -0
- package/build/tsdoc.d.mts +15 -0
- package/build/tsdoc.d.mts.map +1 -0
- package/build/tsdoc.js +18 -15
- package/build/tsdoc.js.map +1 -1
- package/build/utils.cjs +173 -0
- package/build/utils.cjs.map +1 -0
- package/build/utils.d.cts +34 -0
- package/build/utils.d.cts.map +1 -0
- package/build/utils.d.mts +34 -0
- package/build/utils.d.mts.map +1 -0
- package/build/utils.js +112 -166
- package/build/utils.js.map +1 -1
- package/build/write-json-schema.cjs +23 -0
- package/build/write-json-schema.cjs.map +1 -0
- package/build/write-json-schema.d.cts +1 -0
- package/build/write-json-schema.d.mts +1 -0
- package/build/write-json-schema.js +19 -13
- package/build/write-json-schema.js.map +1 -1
- package/package.json +37 -17
- package/skills/joist-docs/SKILL.md +133 -0
- package/skills/joist-em-basics/SKILL.md +114 -0
- package/skills/joist-partial-updates/SKILL.md +352 -0
- package/skills/joist-reactive-hints/SKILL.md +150 -0
- package/skills/joist-test-factories/SKILL.md +397 -0
- package/skills/joist-upsert/SKILL.md +95 -0
- package/build/EntityDbMetadata.d.ts +0 -269
- package/build/EntityDbMetadata.d.ts.map +0 -1
- package/build/EntityDbMetadata.test.d.ts +0 -2
- package/build/EntityDbMetadata.test.d.ts.map +0 -1
- package/build/EntityDbMetadata.test.js +0 -211
- package/build/EntityDbMetadata.test.js.map +0 -1
- package/build/assignTags.d.ts.map +0 -1
- package/build/codemods/Codemod.d.ts +0 -14
- package/build/codemods/Codemod.d.ts.map +0 -1
- package/build/codemods/Codemod.js.map +0 -1
- package/build/codemods/JscodeshiftMod.d.ts +0 -11
- package/build/codemods/JscodeshiftMod.d.ts.map +0 -1
- package/build/codemods/__tests__/codemod_0001-rename_has_async_property.test.d.ts +0 -2
- package/build/codemods/__tests__/codemod_0001-rename_has_async_property.test.d.ts.map +0 -1
- package/build/codemods/__tests__/codemod_0001-rename_has_async_property.test.js +0 -9
- package/build/codemods/__tests__/codemod_0001-rename_has_async_property.test.js.map +0 -1
- package/build/codemods/__tests__/codemod_0002-rename_async_query_fields.test.d.ts +0 -2
- package/build/codemods/__tests__/codemod_0002-rename_async_query_fields.test.d.ts.map +0 -1
- package/build/codemods/__tests__/codemod_0002-rename_async_query_fields.test.js +0 -9
- package/build/codemods/__tests__/codemod_0002-rename_async_query_fields.test.js.map +0 -1
- package/build/codemods/__tests__/codemod_0003-rename_find_paginated.test.d.ts +0 -2
- package/build/codemods/__tests__/codemod_0003-rename_find_paginated.test.d.ts.map +0 -1
- package/build/codemods/__tests__/codemod_0003-rename_find_paginated.test.js +0 -9
- package/build/codemods/__tests__/codemod_0003-rename_find_paginated.test.js.map +0 -1
- package/build/codemods/codemod_0001-rename_has_async_property.d.ts +0 -7
- package/build/codemods/codemod_0001-rename_has_async_property.d.ts.map +0 -1
- package/build/codemods/codemod_0002-rename_async_query_fields.d.ts +0 -7
- package/build/codemods/codemod_0002-rename_async_query_fields.d.ts.map +0 -1
- package/build/codemods/codemod_0003-rename_find_paginated.d.ts +0 -7
- package/build/codemods/codemod_0003-rename_find_paginated.d.ts.map +0 -1
- package/build/codemods/index.d.ts +0 -9
- package/build/codemods/index.d.ts.map +0 -1
- package/build/codemods/index.test.d.ts +0 -2
- package/build/codemods/index.test.d.ts.map +0 -1
- package/build/codemods/index.test.js +0 -24
- package/build/codemods/index.test.js.map +0 -1
- package/build/config.d.ts +0 -167
- package/build/config.d.ts.map +0 -1
- package/build/config.test.d.ts +0 -2
- package/build/config.test.d.ts.map +0 -1
- package/build/config.test.js +0 -78
- package/build/config.test.js.map +0 -1
- package/build/docs/cache.d.ts +0 -14
- package/build/docs/cache.d.ts.map +0 -1
- package/build/docs/cache.test.d.ts +0 -2
- package/build/docs/cache.test.d.ts.map +0 -1
- package/build/docs/cache.test.js +0 -47
- package/build/docs/cache.test.js.map +0 -1
- package/build/docs/generate-metadata-docs.d.ts +0 -6
- package/build/docs/generate-metadata-docs.d.ts.map +0 -1
- package/build/docs/index.d.ts +0 -9
- package/build/docs/index.d.ts.map +0 -1
- package/build/docs/index.test.d.ts +0 -2
- package/build/docs/index.test.d.ts.map +0 -1
- package/build/docs/index.test.js +0 -100
- package/build/docs/index.test.js.map +0 -1
- package/build/docs/markdown.d.ts.map +0 -1
- package/build/docs/markdown.test.d.ts +0 -2
- package/build/docs/markdown.test.d.ts.map +0 -1
- package/build/docs/markdown.test.js +0 -280
- package/build/docs/markdown.test.js.map +0 -1
- package/build/docs/parsing.d.ts +0 -42
- package/build/docs/parsing.d.ts.map +0 -1
- package/build/docs/parsing.test.d.ts +0 -2
- package/build/docs/parsing.test.d.ts.map +0 -1
- package/build/docs/parsing.test.js +0 -190
- package/build/docs/parsing.test.js.map +0 -1
- package/build/findEntityScopes.d.ts +0 -11
- package/build/findEntityScopes.d.ts.map +0 -1
- package/build/foreignKeyOrdering.d.ts +0 -3
- package/build/foreignKeyOrdering.d.ts.map +0 -1
- package/build/generate.d.ts +0 -12
- package/build/generate.d.ts.map +0 -1
- package/build/generateEntitiesFile.d.ts +0 -7
- package/build/generateEntitiesFile.d.ts.map +0 -1
- package/build/generateEntityCodegenFile.d.ts +0 -11
- package/build/generateEntityCodegenFile.d.ts.map +0 -1
- package/build/generateEntityFile.d.ts +0 -6
- package/build/generateEntityFile.d.ts.map +0 -1
- package/build/generateEntityTestFile.d.ts +0 -6
- package/build/generateEntityTestFile.d.ts.map +0 -1
- package/build/generateEnumFile.d.ts +0 -5
- package/build/generateEnumFile.d.ts.map +0 -1
- package/build/generateFactoriesFiles.d.ts +0 -4
- package/build/generateFactoriesFiles.d.ts.map +0 -1
- package/build/generateFlushFunction.d.ts.map +0 -1
- package/build/generateMetadataFile.d.ts +0 -5
- package/build/generateMetadataFile.d.ts.map +0 -1
- package/build/generatePgEnumFile.d.ts +0 -5
- package/build/generatePgEnumFile.d.ts.map +0 -1
- package/build/index.d.ts +0 -11
- package/build/index.d.ts.map +0 -1
- package/build/inheritance.d.ts +0 -10
- package/build/inheritance.d.ts.map +0 -1
- package/build/keywords.d.ts +0 -2
- package/build/keywords.d.ts.map +0 -1
- package/build/loadMetadata.d.ts +0 -26
- package/build/loadMetadata.d.ts.map +0 -1
- package/build/logger.d.ts +0 -10
- package/build/logger.d.ts.map +0 -1
- package/build/scanEntityFiles.d.ts +0 -5
- package/build/scanEntityFiles.d.ts.map +0 -1
- package/build/sortForeignKeys.d.ts.map +0 -1
- package/build/symbols.d.ts +0 -108
- package/build/symbols.d.ts.map +0 -1
- package/build/tsdoc.d.ts +0 -12
- package/build/tsdoc.d.ts.map +0 -1
- package/build/utils.d.ts +0 -31
- package/build/utils.d.ts.map +0 -1
- package/build/write-json-schema.d.ts +0 -2
- package/build/write-json-schema.d.ts.map +0 -1
|
@@ -1,58 +1,45 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
};
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
const pluralize_1 = __importDefault(require("pluralize"));
|
|
9
|
-
const ts_poet_1 = require("ts-poet");
|
|
10
|
-
const symbols_1 = require("./symbols");
|
|
1
|
+
import "./config.js";
|
|
2
|
+
import { EnumMetadata } from "./symbols.js";
|
|
3
|
+
import "./index.js";
|
|
4
|
+
import { pascalCase } from "change-case";
|
|
5
|
+
import pluralize from "pluralize";
|
|
6
|
+
import { code } from "ts-poet";
|
|
7
|
+
//#region src/generateEnumFile.ts
|
|
11
8
|
function generateEnumFile(config, enumData, enumName) {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
}
|
|
27
|
-
return `${primitive.fieldName}: ${primitive.fieldType};`;
|
|
28
|
-
}),
|
|
29
|
-
].join(" ");
|
|
30
|
-
return (0, ts_poet_1.code) `
|
|
9
|
+
const { rows, extraPrimitives } = enumData;
|
|
10
|
+
const detailsName = `${enumName}Details`;
|
|
11
|
+
const idType = enumData.idType === "uuid" ? "string" : "number";
|
|
12
|
+
const detailsDefinition = [
|
|
13
|
+
`id: ${idType};`,
|
|
14
|
+
`code: ${enumName};`,
|
|
15
|
+
"name: string;",
|
|
16
|
+
...extraPrimitives.map((primitive) => {
|
|
17
|
+
const allValues = rows.map((r) => r[primitive.columnName]);
|
|
18
|
+
if (new Set(allValues).size === allValues.length) return `${primitive.fieldName}: ${primitive.fieldType === "string" ? `"${allValues.join("\" | \"")}"` : allValues.join(" | ")};`;
|
|
19
|
+
return `${primitive.fieldName}: ${primitive.fieldType};`;
|
|
20
|
+
})
|
|
21
|
+
].join(" ");
|
|
22
|
+
return code`
|
|
31
23
|
export enum ${enumName} {
|
|
32
|
-
${rows.map((row) => `${
|
|
24
|
+
${rows.map((row) => `${pascalCase(row.code)} = '${row.code}'`).join(",\n")}
|
|
33
25
|
}
|
|
34
26
|
|
|
35
27
|
export type ${detailsName} = {${detailsDefinition}};
|
|
36
28
|
|
|
37
29
|
const details: Record<${enumName}, ${detailsName}> = {
|
|
38
|
-
${rows
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
.join(", ");
|
|
45
|
-
const id = enumData.idType === "uuid" ? `"${row.id}"` : row.id;
|
|
46
|
-
return `[${enumName}.${code}]: { id: ${id}, code: ${enumName}.${code}, name: '${safeName}', ${extras} }`;
|
|
47
|
-
})
|
|
48
|
-
.join(",")}
|
|
30
|
+
${rows.map((row) => {
|
|
31
|
+
const code = pascalCase(row.code);
|
|
32
|
+
const safeName = row.name.replace(/(["'])/g, "\\$1");
|
|
33
|
+
const extras = extraPrimitives.map((p) => `${p.fieldName}: ${JSON.stringify(row[p.columnName])}`).join(", ");
|
|
34
|
+
return `[${enumName}.${code}]: { id: ${enumData.idType === "uuid" ? `"${row.id}"` : row.id}, code: ${enumName}.${code}, name: '${safeName}', ${extras} }`;
|
|
35
|
+
}).join(",")}
|
|
49
36
|
};
|
|
50
37
|
|
|
51
38
|
export const ${detailsName} = {
|
|
52
|
-
${rows.map((row) => `${
|
|
39
|
+
${rows.map((row) => `${pascalCase(row.code)}: details[${enumName}.${pascalCase(row.code)}]`).join(",")}
|
|
53
40
|
};
|
|
54
41
|
|
|
55
|
-
export const ${(
|
|
42
|
+
export const ${pluralize(enumName)}: ${EnumMetadata}<${enumName}, ${detailsName}, ${idType}> = {
|
|
56
43
|
name: "${enumName}",
|
|
57
44
|
|
|
58
45
|
getByCode(code: ${enumName}): ${detailsName} {
|
|
@@ -77,4 +64,7 @@ function generateEnumFile(config, enumData, enumName) {
|
|
|
77
64
|
};
|
|
78
65
|
`;
|
|
79
66
|
}
|
|
67
|
+
//#endregion
|
|
68
|
+
export { generateEnumFile };
|
|
69
|
+
|
|
80
70
|
//# sourceMappingURL=generateEnumFile.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generateEnumFile.js","
|
|
1
|
+
{"version":3,"file":"generateEnumFile.js","names":[],"sources":["../src/generateEnumFile.ts"],"sourcesContent":["import { pascalCase } from \"change-case\";\nimport pluralize from \"pluralize\";\nimport { type Code, code } from \"ts-poet\";\n\nimport { type Config } from \"./config.ts\";\nimport { type EnumTableData } from \"./index.ts\";\nimport { EnumMetadata } from \"./symbols.ts\";\n\nexport function generateEnumFile(config: Config, enumData: EnumTableData, enumName: string): Code {\n const { rows, extraPrimitives } = enumData;\n const detailsName = `${enumName}Details`;\n const idType = enumData.idType === \"uuid\" ? \"string\" : \"number\";\n\n // Create the `const fooDetails = code -> literal` mapping\n const detailsDefinition = [\n `id: ${idType};`,\n `code: ${enumName};`,\n \"name: string;\",\n ...extraPrimitives.map((primitive) => {\n // If the extra primitive values are all unique, then allow the type be only that set of values. Otherwise, use `fieldType`\n const allValues = rows.map((r) => r[primitive.columnName]);\n const uniqueValues = new Set(allValues);\n if (uniqueValues.size === allValues.length) {\n return `${primitive.fieldName}: ${\n primitive.fieldType === \"string\" ? `\"${allValues.join('\" | \"')}\"` : allValues.join(\" | \")\n };`;\n }\n return `${primitive.fieldName}: ${primitive.fieldType};`;\n }),\n ].join(\" \");\n\n return code`\n export enum ${enumName} {\n ${rows.map((row) => `${pascalCase(row.code)} = '${row.code}'`).join(\",\\n\")}\n }\n\n export type ${detailsName} = {${detailsDefinition}};\n\n const details: Record<${enumName}, ${detailsName}> = {\n ${rows\n .map((row) => {\n const code = pascalCase(row.code);\n const safeName = row.name.replace(/([\"'])/g, \"\\\\$1\");\n const extras = extraPrimitives\n .map((p) => `${p.fieldName}: ${JSON.stringify((row as any)[p.columnName])}`)\n .join(\", \");\n const id = enumData.idType === \"uuid\" ? `\"${row.id}\"` : row.id;\n return `[${enumName}.${code}]: { id: ${id}, code: ${enumName}.${code}, name: '${safeName}', ${extras} }`;\n })\n .join(\",\")}\n };\n \n export const ${detailsName} = {\n ${rows.map((row) => `${pascalCase(row.code)}: details[${enumName}.${pascalCase(row.code)}]`).join(\",\")}\n };\n\n export const ${pluralize(enumName)}: ${EnumMetadata}<${enumName}, ${detailsName}, ${idType}> = {\n name: \"${enumName}\",\n\n getByCode(code: ${enumName}): ${detailsName} {\n return details[code];\n },\n\n findByCode(code: string): ${detailsName} | undefined {\n return details[code as ${enumName}];\n },\n\n findById(id: ${idType}): ${detailsName} | undefined {\n return Object.values(details).find(d => d.id === id);\n },\n\n getValues(): ReadonlyArray<${enumName}> {\n return Object.values(${enumName});\n },\n\n getDetails(): ReadonlyArray<${detailsName}> {\n return Object.values(details);\n },\n };\n `;\n}\n"],"mappings":";;;;;;;AAQA,SAAgB,iBAAiB,QAAgB,UAAyB,UAAwB;CAChG,MAAM,EAAE,MAAM,oBAAoB;CAClC,MAAM,cAAc,GAAG,SAAS;CAChC,MAAM,SAAS,SAAS,WAAW,SAAS,WAAW;CAGvD,MAAM,oBAAoB;EACxB,OAAO,OAAO;EACd,SAAS,SAAS;EAClB;EACA,GAAG,gBAAgB,KAAK,cAAc;GAEpC,MAAM,YAAY,KAAK,KAAK,MAAM,EAAE,UAAU,WAAW;GAEzD,IAAI,IADqB,IAAI,SACd,CAAC,CAAC,SAAS,UAAU,QAClC,OAAO,GAAG,UAAU,UAAU,IAC5B,UAAU,cAAc,WAAW,IAAI,UAAU,KAAK,SAAO,EAAE,KAAK,UAAU,KAAK,KAAK,EACzF;GAEH,OAAO,GAAG,UAAU,UAAU,IAAI,UAAU,UAAU;EACxD,CAAC;CACH,CAAC,CAAC,KAAK,GAAG;CAEV,OAAO,IAAI;kBACK,SAAS;QACnB,KAAK,KAAK,QAAQ,GAAG,WAAW,IAAI,IAAI,EAAE,MAAM,IAAI,KAAK,EAAE,CAAC,CAAC,KAAK,KAAK,EAAE;;;kBAG/D,YAAY,MAAM,kBAAkB;;4BAE1B,SAAS,IAAI,YAAY;QAC7C,KACC,KAAK,QAAQ;EACZ,MAAM,OAAO,WAAW,IAAI,IAAI;EAChC,MAAM,WAAW,IAAI,KAAK,QAAQ,WAAW,MAAM;EACnD,MAAM,SAAS,gBACZ,KAAK,MAAM,GAAG,EAAE,UAAU,IAAI,KAAK,UAAW,IAAY,EAAE,WAAW,GAAG,CAAC,CAC3E,KAAK,IAAI;EAEZ,OAAO,IAAI,SAAS,GAAG,KAAK,WADjB,SAAS,WAAW,SAAS,IAAI,IAAI,GAAG,KAAK,IAAI,GAClB,UAAU,SAAS,GAAG,KAAK,WAAW,SAAS,KAAK,OAAO;CACvG,CAAC,CAAC,CACD,KAAK,GAAG,EAAE;;;mBAGA,YAAY;QACvB,KAAK,KAAK,QAAQ,GAAG,WAAW,IAAI,IAAI,EAAE,YAAY,SAAS,GAAG,WAAW,IAAI,IAAI,EAAE,EAAE,CAAC,CAAC,KAAK,GAAG,EAAE;;;mBAG1F,UAAU,QAAQ,EAAE,IAAI,aAAa,GAAG,SAAS,IAAI,YAAY,IAAI,OAAO;eAChF,SAAS;;wBAEA,SAAS,KAAK,YAAY;;;;kCAIhB,YAAY;iCACb,SAAS;;;qBAGrB,OAAO,KAAK,YAAY;;;;mCAIV,SAAS;+BACb,SAAS;;;oCAGJ,YAAY;;;;;AAKhD"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
const require_symbols = require("./symbols.cjs");
|
|
3
|
+
require("./EntityDbMetadata.cjs");
|
|
4
|
+
let change_case = require("change-case");
|
|
5
|
+
let ts_poet = require("ts-poet");
|
|
6
|
+
//#region src/generateFactoriesFiles.ts
|
|
7
|
+
const EntityManager = (0, ts_poet.imp)("t:EntityManager@./entities.ts");
|
|
8
|
+
function generateFactoriesFiles(entities) {
|
|
9
|
+
return entities.map(({ entity }) => {
|
|
10
|
+
const name = (0, change_case.pascalCase)(entity.name);
|
|
11
|
+
const contents = ts_poet.code`
|
|
12
|
+
export function new${name}(
|
|
13
|
+
em: ${EntityManager},
|
|
14
|
+
opts: ${require_symbols.FactoryOpts}<${entity.type}> = {},
|
|
15
|
+
): ${require_symbols.DeepNew}<${entity.type}> {
|
|
16
|
+
return ${require_symbols.newTestInstance}(em, ${entity.typeSymbol}, opts, {});
|
|
17
|
+
}`;
|
|
18
|
+
return {
|
|
19
|
+
name: `./factories/new${entity.name}.ts`,
|
|
20
|
+
contents,
|
|
21
|
+
overwrite: false
|
|
22
|
+
};
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
//#endregion
|
|
26
|
+
exports.generateFactoriesFiles = generateFactoriesFiles;
|
|
27
|
+
|
|
28
|
+
//# sourceMappingURL=generateFactoriesFiles.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generateFactoriesFiles.cjs","names":["imp","pascalCase","FactoryOpts","DeepNew","newTestInstance"],"sources":["../src/generateFactoriesFiles.ts"],"sourcesContent":["import { pascalCase } from \"change-case\";\nimport { type CodegenFile, code, imp } from \"ts-poet\";\n\nimport { type EntityDbMetadata } from \"./EntityDbMetadata.ts\";\nimport { DeepNew, FactoryOpts, newTestInstance } from \"./symbols.ts\";\n\nconst EntityManager = imp(\"t:EntityManager@./entities.ts\");\n\nexport function generateFactoriesFiles(entities: EntityDbMetadata[]): CodegenFile[] {\n // One-time create an ./factories/newAuthor.ts for each entity\n return entities.map(({ entity }) => {\n const name = pascalCase(entity.name);\n const contents = code`\n export function new${name}(\n em: ${EntityManager},\n opts: ${FactoryOpts}<${entity.type}> = {},\n ): ${DeepNew}<${entity.type}> {\n return ${newTestInstance}(em, ${entity.typeSymbol}, opts, {});\n }`;\n return { name: `./factories/new${entity.name}.ts`, contents, overwrite: false };\n });\n}\n"],"mappings":";;;;;;AAMA,MAAM,iBAAA,GAAgBA,QAAAA,IAAAA,CAAI,+BAA+B;AAEzD,SAAgB,uBAAuB,UAA6C;CAElF,OAAO,SAAS,KAAK,EAAE,aAAa;EAClC,MAAM,QAAA,GAAOC,YAAAA,WAAAA,CAAW,OAAO,IAAI;EACnC,MAAM,WAAW,QAAA,IAAI;2BACE,KAAK;cAClB,cAAc;gBACZC,gBAAAA,YAAY,GAAG,OAAO,KAAK;WAChCC,gBAAAA,QAAQ,GAAG,OAAO,KAAK;iBACjBC,gBAAAA,gBAAgB,OAAO,OAAO,WAAW;;EAEtD,OAAO;GAAE,MAAM,kBAAkB,OAAO,KAAK;GAAM;GAAU,WAAW;EAAM;CAChF,CAAC;AACH"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { EntityDbMetadata } from "./EntityDbMetadata.cjs";
|
|
2
|
+
import { CodegenFile } from "ts-poet";
|
|
3
|
+
//#region src/generateFactoriesFiles.d.ts
|
|
4
|
+
declare function generateFactoriesFiles(entities: EntityDbMetadata[]): CodegenFile[];
|
|
5
|
+
//#endregion
|
|
6
|
+
export { generateFactoriesFiles };
|
|
7
|
+
//# sourceMappingURL=generateFactoriesFiles.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generateFactoriesFiles.d.cts","names":[],"sources":["../src/generateFactoriesFiles.ts"],"mappings":";;;iBAQgB,uBAAuB,UAAU,qBAAqB"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { EntityDbMetadata } from "./EntityDbMetadata.mjs";
|
|
2
|
+
import { CodegenFile } from "ts-poet";
|
|
3
|
+
//#region src/generateFactoriesFiles.d.ts
|
|
4
|
+
declare function generateFactoriesFiles(entities: EntityDbMetadata[]): CodegenFile[];
|
|
5
|
+
//#endregion
|
|
6
|
+
export { generateFactoriesFiles };
|
|
7
|
+
//# sourceMappingURL=generateFactoriesFiles.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generateFactoriesFiles.d.mts","names":[],"sources":["../src/generateFactoriesFiles.ts"],"mappings":";;;iBAQgB,uBAAuB,UAAU,qBAAqB"}
|
|
@@ -1,22 +1,27 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
const
|
|
7
|
-
const EntityManager = (0, ts_poet_1.imp)("t:EntityManager@./entities.ts");
|
|
1
|
+
import { DeepNew, FactoryOpts, newTestInstance } from "./symbols.js";
|
|
2
|
+
import "./EntityDbMetadata.js";
|
|
3
|
+
import { pascalCase } from "change-case";
|
|
4
|
+
import { code, imp } from "ts-poet";
|
|
5
|
+
//#region src/generateFactoriesFiles.ts
|
|
6
|
+
const EntityManager = imp("t:EntityManager@./entities.ts");
|
|
8
7
|
function generateFactoriesFiles(entities) {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
const contents = (0, ts_poet_1.code) `
|
|
8
|
+
return entities.map(({ entity }) => {
|
|
9
|
+
const name = pascalCase(entity.name);
|
|
10
|
+
const contents = code`
|
|
13
11
|
export function new${name}(
|
|
14
12
|
em: ${EntityManager},
|
|
15
|
-
opts: ${
|
|
16
|
-
): ${
|
|
17
|
-
return ${
|
|
13
|
+
opts: ${FactoryOpts}<${entity.type}> = {},
|
|
14
|
+
): ${DeepNew}<${entity.type}> {
|
|
15
|
+
return ${newTestInstance}(em, ${entity.typeSymbol}, opts, {});
|
|
18
16
|
}`;
|
|
19
|
-
|
|
20
|
-
|
|
17
|
+
return {
|
|
18
|
+
name: `./factories/new${entity.name}.ts`,
|
|
19
|
+
contents,
|
|
20
|
+
overwrite: false
|
|
21
|
+
};
|
|
22
|
+
});
|
|
21
23
|
}
|
|
24
|
+
//#endregion
|
|
25
|
+
export { generateFactoriesFiles };
|
|
26
|
+
|
|
22
27
|
//# sourceMappingURL=generateFactoriesFiles.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generateFactoriesFiles.js","
|
|
1
|
+
{"version":3,"file":"generateFactoriesFiles.js","names":[],"sources":["../src/generateFactoriesFiles.ts"],"sourcesContent":["import { pascalCase } from \"change-case\";\nimport { type CodegenFile, code, imp } from \"ts-poet\";\n\nimport { type EntityDbMetadata } from \"./EntityDbMetadata.ts\";\nimport { DeepNew, FactoryOpts, newTestInstance } from \"./symbols.ts\";\n\nconst EntityManager = imp(\"t:EntityManager@./entities.ts\");\n\nexport function generateFactoriesFiles(entities: EntityDbMetadata[]): CodegenFile[] {\n // One-time create an ./factories/newAuthor.ts for each entity\n return entities.map(({ entity }) => {\n const name = pascalCase(entity.name);\n const contents = code`\n export function new${name}(\n em: ${EntityManager},\n opts: ${FactoryOpts}<${entity.type}> = {},\n ): ${DeepNew}<${entity.type}> {\n return ${newTestInstance}(em, ${entity.typeSymbol}, opts, {});\n }`;\n return { name: `./factories/new${entity.name}.ts`, contents, overwrite: false };\n });\n}\n"],"mappings":";;;;;AAMA,MAAM,gBAAgB,IAAI,+BAA+B;AAEzD,SAAgB,uBAAuB,UAA6C;CAElF,OAAO,SAAS,KAAK,EAAE,aAAa;EAClC,MAAM,OAAO,WAAW,OAAO,IAAI;EACnC,MAAM,WAAW,IAAI;2BACE,KAAK;cAClB,cAAc;gBACZ,YAAY,GAAG,OAAO,KAAK;WAChC,QAAQ,GAAG,OAAO,KAAK;iBACjB,gBAAgB,OAAO,OAAO,WAAW;;EAEtD,OAAO;GAAE,MAAM,kBAAkB,OAAO,KAAK;GAAM;GAAU,WAAW;EAAM;CAChF,CAAC;AACH"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
require("./EntityDbMetadata.cjs");
|
|
3
|
+
require("pg");
|
|
4
|
+
//#region src/generateFlushFunction.ts
|
|
5
|
+
/** Creates a `flush_database` stored procedure to truncate all the tables between tests. */
|
|
6
|
+
async function createFlushFunction(client, db) {
|
|
7
|
+
const hasAnyNonDeferredFks = db.entities.some((e) => e.nonDeferredFks.length > 0 || e.nonDeferredManyToManyFks.length > 0);
|
|
8
|
+
if (db.entities.some((e) => e.primaryKey.columnType === "uuid") || hasAnyNonDeferredFks) await client.query(generateExplicitFlushFunction(db));
|
|
9
|
+
else await client.query(generateSequenceFlushFunction(db));
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Explicitly deletes every entity/m2m table in a deterministic order.
|
|
13
|
+
*
|
|
14
|
+
* We do this for schemas with non-deferred foreign keys (order matters)
|
|
15
|
+
* or schemas with UUID id columns.
|
|
16
|
+
*/
|
|
17
|
+
function generateExplicitFlushFunction(db) {
|
|
18
|
+
const deletes = [...db.joinTables, ...[...db.entities].sort((a, b) => {
|
|
19
|
+
const x = a.nonDeferredFkOrder;
|
|
20
|
+
const y = b.nonDeferredFkOrder;
|
|
21
|
+
if (x !== y) return y - x;
|
|
22
|
+
const i = a.baseClassName ? 1 : -1;
|
|
23
|
+
return (b.baseClassName ? 1 : -1) - i;
|
|
24
|
+
}).map((e) => e.tableName)].flatMap((t) => [`DELETE FROM "${t}";`, `ALTER SEQUENCE IF EXISTS "${t}_id_seq" RESTART WITH 1 INCREMENT BY 1;`]);
|
|
25
|
+
return `CREATE OR REPLACE FUNCTION flush_database() RETURNS void AS $$
|
|
26
|
+
BEGIN
|
|
27
|
+
${[...db.entities.filter((t) => t.nonDeferredFkOrder).flatMap((t) => t.manyToOnes.filter((m2o) => m2o.onDelete !== "SET NULL" && m2o.onDelete !== "CASCADE").filter((m2o) => db.entitiesByName[m2o.otherEntity.name].nonDeferredFkOrder > t.nonDeferredFkOrder).map((m2o) => `UPDATE ${t.tableName} SET "${m2o.columnName}" = NULL;`)), ...deletes].join("\n")}
|
|
28
|
+
END;
|
|
29
|
+
$$ LANGUAGE
|
|
30
|
+
'plpgsql'`;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* A cuter/shorter flush that only DELETEs from tables that were inserted into.
|
|
34
|
+
*
|
|
35
|
+
* The difference between this and the explicit-order function should only be
|
|
36
|
+
* noticeable on 100+ table schemas (specifically, on our production app with ~200 tables
|
|
37
|
+
* and ~5,000 tests, it gave an 8% speed-up vs. the "DELETE every table" approach).
|
|
38
|
+
*/
|
|
39
|
+
function generateSequenceFlushFunction(db) {
|
|
40
|
+
const stableTables = [...Object.values(db.enums).map((e) => e.table.name), ...db.otherTables];
|
|
41
|
+
return `CREATE OR REPLACE FUNCTION flush_database() RETURNS void AS $$
|
|
42
|
+
DECLARE seq RECORD;
|
|
43
|
+
BEGIN
|
|
44
|
+
FOR seq IN
|
|
45
|
+
SELECT sequencename AS name
|
|
46
|
+
FROM pg_sequences
|
|
47
|
+
WHERE schemaname = 'public' AND last_value IS NOT NULL AND sequencename LIKE '%_id_seq' ${stableTables.length === 0 ? "" : `AND sequencename NOT IN (${stableTables.map((t) => `'${t}_id_seq'`).join(", ")})`}
|
|
48
|
+
LOOP
|
|
49
|
+
EXECUTE format('DELETE FROM %I', regexp_replace(seq.name, '_id_seq$', ''));
|
|
50
|
+
EXECUTE format('ALTER SEQUENCE %I RESTART WITH 1', seq.name);
|
|
51
|
+
END LOOP;
|
|
52
|
+
END;
|
|
53
|
+
$$ LANGUAGE
|
|
54
|
+
'plpgsql'`;
|
|
55
|
+
}
|
|
56
|
+
//#endregion
|
|
57
|
+
exports.createFlushFunction = createFlushFunction;
|
|
58
|
+
exports.generateExplicitFlushFunction = generateExplicitFlushFunction;
|
|
59
|
+
exports.generateSequenceFlushFunction = generateSequenceFlushFunction;
|
|
60
|
+
|
|
61
|
+
//# sourceMappingURL=generateFlushFunction.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generateFlushFunction.cjs","names":[],"sources":["../src/generateFlushFunction.ts"],"sourcesContent":["import { type Client } from \"pg\";\n\nimport { type DbMetadata } from \"./EntityDbMetadata.ts\";\n\n/** Creates a `flush_database` stored procedure to truncate all the tables between tests. */\nexport async function createFlushFunction(client: Client, db: DbMetadata): Promise<void> {\n // We only check nonDeferredManyToManyFks here (and not other places) b/c we don't really count/track m2ms\n // as true FK dependencies -- they would a) always create cycles, and b) it's easiest enough for us to just\n // always have `flush_database` / `em.flush` delete from m2m tables first, to avoid FK delete constraints\n // errors when we delete from the main entity tables.\n //\n // ...but, because order matters for the m2m tables, then we have to use the `generateExplicitFlushFunction`\n // instead of the cuter `generateSequenceFlushFunction`.\n const hasAnyNonDeferredFks = db.entities.some(\n (e) => e.nonDeferredFks.length > 0 || e.nonDeferredManyToManyFks.length > 0,\n );\n const hasAnyNonSequenceIds = db.entities.some((e) => e.primaryKey.columnType === \"uuid\");\n if (hasAnyNonSequenceIds || hasAnyNonDeferredFks) {\n await client.query(generateExplicitFlushFunction(db));\n } else {\n await client.query(generateSequenceFlushFunction(db));\n }\n}\n\n/**\n * Explicitly deletes every entity/m2m table in a deterministic order.\n *\n * We do this for schemas with non-deferred foreign keys (order matters)\n * or schemas with UUID id columns.\n */\nexport function generateExplicitFlushFunction(db: DbMetadata): string {\n // Leave code/enum tables alone\n const tables = [\n ...db.joinTables,\n ...[...db.entities]\n .sort((a, b) => {\n // Flush books before authors if it has non-deferred FKs\n const x = a.nonDeferredFkOrder;\n const y = b.nonDeferredFkOrder;\n if (x !== y) {\n return y - x;\n }\n // Flush base tables before sub-tables.\n const i = a.baseClassName ? 1 : -1;\n const j = b.baseClassName ? 1 : -1;\n return j - i;\n })\n .map((e) => e.tableName),\n ];\n\n // Note that, for whatever reason, doing DELETEs + ALTER SEQUENCEs is dramatically faster than TRUNCATEs.\n // On even a 40-table schema, TRUNCATEs (either 1 per table or even a single TRUNCATE with all tables) takes\n // 100s of milliseconds, whereas DELETEs takes single-digit milliseconds and DELETEs + ALTER SEQUENCEs is\n // 10s of milliseconds.\n const deletes = tables.flatMap((t) => [\n `DELETE FROM \"${t}\";`,\n `ALTER SEQUENCE IF EXISTS \"${t}_id_seq\" RESTART WITH 1 INCREMENT BY 1;`,\n ]);\n\n // Create `SET NULLs` in schemas that don't have deferred FKs\n const setFksNulls = db.entities\n .filter((t) => t.nonDeferredFkOrder)\n .flatMap((t) =>\n t.manyToOnes\n // These FKs will auto-unset/delete the later row, so don't need explicit unsetting\n .filter((m2o) => m2o.onDelete !== \"SET NULL\" && m2o.onDelete !== \"CASCADE\")\n // Look for FKs to tables whose DELETEs come after us\n .filter((m2o) => db.entitiesByName[m2o.otherEntity.name].nonDeferredFkOrder > t.nonDeferredFkOrder)\n .map((m2o) => `UPDATE ${t.tableName} SET \"${m2o.columnName}\" = NULL;`),\n );\n\n const statements = [...setFksNulls, ...deletes].join(\"\\n\");\n\n return `CREATE OR REPLACE FUNCTION flush_database() RETURNS void AS $$\n BEGIN\n ${statements}\n END;\n $$ LANGUAGE\n 'plpgsql'`;\n}\n\n/**\n * A cuter/shorter flush that only DELETEs from tables that were inserted into.\n *\n * The difference between this and the explicit-order function should only be\n * noticeable on 100+ table schemas (specifically, on our production app with ~200 tables\n * and ~5,000 tests, it gave an 8% speed-up vs. the \"DELETE every table\" approach).\n */\nexport function generateSequenceFlushFunction(db: DbMetadata): string {\n const stableTables = [...Object.values(db.enums).map((e) => e.table.name), ...db.otherTables];\n const maybeSkipStable =\n stableTables.length === 0 ? \"\" : `AND sequencename NOT IN (${stableTables.map((t) => `'${t}_id_seq'`).join(\", \")})`;\n return `CREATE OR REPLACE FUNCTION flush_database() RETURNS void AS $$\n DECLARE seq RECORD;\n BEGIN\n FOR seq IN\n SELECT sequencename AS name\n FROM pg_sequences\n WHERE schemaname = 'public' AND last_value IS NOT NULL AND sequencename LIKE '%_id_seq' ${maybeSkipStable}\n LOOP\n EXECUTE format('DELETE FROM %I', regexp_replace(seq.name, '_id_seq$', ''));\n EXECUTE format('ALTER SEQUENCE %I RESTART WITH 1', seq.name);\n END LOOP;\n END;\n $$ LANGUAGE\n 'plpgsql'`;\n}\n"],"mappings":";;;;;AAKA,eAAsB,oBAAoB,QAAgB,IAA+B;CAQvF,MAAM,uBAAuB,GAAG,SAAS,MACtC,MAAM,EAAE,eAAe,SAAS,KAAK,EAAE,yBAAyB,SAAS,CAC5E;CAEA,IAD6B,GAAG,SAAS,MAAM,MAAM,EAAE,WAAW,eAAe,MAC1D,KAAK,sBAC1B,MAAM,OAAO,MAAM,8BAA8B,EAAE,CAAC;MAEpD,MAAM,OAAO,MAAM,8BAA8B,EAAE,CAAC;AAExD;;;;;;;AAQA,SAAgB,8BAA8B,IAAwB;CAwBpE,MAAM,UAAU,CArBd,GAAG,GAAG,YACN,GAAG,CAAC,GAAG,GAAG,QAAQ,CAAC,CAChB,MAAM,GAAG,MAAM;EAEd,MAAM,IAAI,EAAE;EACZ,MAAM,IAAI,EAAE;EACZ,IAAI,MAAM,GACR,OAAO,IAAI;EAGb,MAAM,IAAI,EAAE,gBAAgB,IAAI;EAEhC,QADU,EAAE,gBAAgB,IAAI,MACrB;CACb,CAAC,CAAC,CACD,KAAK,MAAM,EAAE,SAAS,CAON,CAAC,CAAC,SAAS,MAAM,CACpC,gBAAgB,EAAE,KAClB,6BAA6B,EAAE,wCACjC,CAAC;CAgBD,OAAO;;QAFY,CAAC,GAXA,GAAG,SACpB,QAAQ,MAAM,EAAE,kBAAkB,CAAC,CACnC,SAAS,MACR,EAAE,WAEC,QAAQ,QAAQ,IAAI,aAAa,cAAc,IAAI,aAAa,SAAS,CAAC,CAE1E,QAAQ,QAAQ,GAAG,eAAe,IAAI,YAAY,KAAK,CAAC,qBAAqB,EAAE,kBAAkB,CAAC,CAClG,KAAK,QAAQ,UAAU,EAAE,UAAU,QAAQ,IAAI,WAAW,UAAU,CAG1C,GAAG,GAAG,OAAO,CAAC,CAAC,KAAK,IAItC,EAAE;;;;AAInB;;;;;;;;AASA,SAAgB,8BAA8B,IAAwB;CACpE,MAAM,eAAe,CAAC,GAAG,OAAO,OAAO,GAAG,KAAK,CAAC,CAAC,KAAK,MAAM,EAAE,MAAM,IAAI,GAAG,GAAG,GAAG,WAAW;CAG5F,OAAO;;;;;;kGADL,aAAa,WAAW,IAAI,KAAK,4BAA4B,aAAa,KAAK,MAAM,IAAI,EAAE,SAAS,CAAC,CAAC,KAAK,IAAI,EAAE,GAOH;;;;;;;;AAQlH"}
|
|
@@ -1,14 +1,15 @@
|
|
|
1
|
+
import { DbMetadata } from "./EntityDbMetadata.cjs";
|
|
1
2
|
import { Client } from "pg";
|
|
2
|
-
|
|
3
|
+
//#region src/generateFlushFunction.d.ts
|
|
3
4
|
/** Creates a `flush_database` stored procedure to truncate all the tables between tests. */
|
|
4
|
-
|
|
5
|
+
declare function createFlushFunction(client: Client, db: DbMetadata): Promise<void>;
|
|
5
6
|
/**
|
|
6
7
|
* Explicitly deletes every entity/m2m table in a deterministic order.
|
|
7
8
|
*
|
|
8
9
|
* We do this for schemas with non-deferred foreign keys (order matters)
|
|
9
10
|
* or schemas with UUID id columns.
|
|
10
11
|
*/
|
|
11
|
-
|
|
12
|
+
declare function generateExplicitFlushFunction(db: DbMetadata): string;
|
|
12
13
|
/**
|
|
13
14
|
* A cuter/shorter flush that only DELETEs from tables that were inserted into.
|
|
14
15
|
*
|
|
@@ -16,5 +17,7 @@ export declare function generateExplicitFlushFunction(db: DbMetadata): string;
|
|
|
16
17
|
* noticeable on 100+ table schemas (specifically, on our production app with ~200 tables
|
|
17
18
|
* and ~5,000 tests, it gave an 8% speed-up vs. the "DELETE every table" approach).
|
|
18
19
|
*/
|
|
19
|
-
|
|
20
|
-
//#
|
|
20
|
+
declare function generateSequenceFlushFunction(db: DbMetadata): string;
|
|
21
|
+
//#endregion
|
|
22
|
+
export { createFlushFunction, generateExplicitFlushFunction, generateSequenceFlushFunction };
|
|
23
|
+
//# sourceMappingURL=generateFlushFunction.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generateFlushFunction.d.cts","names":[],"sources":["../src/generateFlushFunction.ts"],"mappings":";;;;iBAKsB,oBAAoB,QAAQ,QAAQ,IAAI,aAAa;;;;;;;iBAyB3D,8BAA8B,IAAI;;;;;;;;iBA0DlC,8BAA8B,IAAI"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { DbMetadata } from "./EntityDbMetadata.mjs";
|
|
2
|
+
import { Client } from "pg";
|
|
3
|
+
//#region src/generateFlushFunction.d.ts
|
|
4
|
+
/** Creates a `flush_database` stored procedure to truncate all the tables between tests. */
|
|
5
|
+
declare function createFlushFunction(client: Client, db: DbMetadata): Promise<void>;
|
|
6
|
+
/**
|
|
7
|
+
* Explicitly deletes every entity/m2m table in a deterministic order.
|
|
8
|
+
*
|
|
9
|
+
* We do this for schemas with non-deferred foreign keys (order matters)
|
|
10
|
+
* or schemas with UUID id columns.
|
|
11
|
+
*/
|
|
12
|
+
declare function generateExplicitFlushFunction(db: DbMetadata): string;
|
|
13
|
+
/**
|
|
14
|
+
* A cuter/shorter flush that only DELETEs from tables that were inserted into.
|
|
15
|
+
*
|
|
16
|
+
* The difference between this and the explicit-order function should only be
|
|
17
|
+
* noticeable on 100+ table schemas (specifically, on our production app with ~200 tables
|
|
18
|
+
* and ~5,000 tests, it gave an 8% speed-up vs. the "DELETE every table" approach).
|
|
19
|
+
*/
|
|
20
|
+
declare function generateSequenceFlushFunction(db: DbMetadata): string;
|
|
21
|
+
//#endregion
|
|
22
|
+
export { createFlushFunction, generateExplicitFlushFunction, generateSequenceFlushFunction };
|
|
23
|
+
//# sourceMappingURL=generateFlushFunction.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generateFlushFunction.d.mts","names":[],"sources":["../src/generateFlushFunction.ts"],"mappings":";;;;iBAKsB,oBAAoB,QAAQ,QAAQ,IAAI,aAAa;;;;;;;iBAyB3D,8BAA8B,IAAI;;;;;;;;iBA0DlC,8BAA8B,IAAI"}
|
|
@@ -1,98 +1,49 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
exports.generateExplicitFlushFunction = generateExplicitFlushFunction;
|
|
5
|
-
exports.generateSequenceFlushFunction = generateSequenceFlushFunction;
|
|
1
|
+
import "./EntityDbMetadata.js";
|
|
2
|
+
import "pg";
|
|
3
|
+
//#region src/generateFlushFunction.ts
|
|
6
4
|
/** Creates a `flush_database` stored procedure to truncate all the tables between tests. */
|
|
7
5
|
async function createFlushFunction(client, db) {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
// errors when we delete from the main entity tables.
|
|
12
|
-
//
|
|
13
|
-
// ...but, because order matters for the m2m tables, then we have to use the `generateExplicitFlushFunction`
|
|
14
|
-
// instead of the cuter `generateSequenceFlushFunction`.
|
|
15
|
-
const hasAnyNonDeferredFks = db.entities.some((e) => e.nonDeferredFks.length > 0 || e.nonDeferredManyToManyFks.length > 0);
|
|
16
|
-
const hasAnyNonSequenceIds = db.entities.some((e) => e.primaryKey.columnType === "uuid");
|
|
17
|
-
if (hasAnyNonSequenceIds || hasAnyNonDeferredFks) {
|
|
18
|
-
await client.query(generateExplicitFlushFunction(db));
|
|
19
|
-
}
|
|
20
|
-
else {
|
|
21
|
-
await client.query(generateSequenceFlushFunction(db));
|
|
22
|
-
}
|
|
6
|
+
const hasAnyNonDeferredFks = db.entities.some((e) => e.nonDeferredFks.length > 0 || e.nonDeferredManyToManyFks.length > 0);
|
|
7
|
+
if (db.entities.some((e) => e.primaryKey.columnType === "uuid") || hasAnyNonDeferredFks) await client.query(generateExplicitFlushFunction(db));
|
|
8
|
+
else await client.query(generateSequenceFlushFunction(db));
|
|
23
9
|
}
|
|
24
10
|
/**
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
11
|
+
* Explicitly deletes every entity/m2m table in a deterministic order.
|
|
12
|
+
*
|
|
13
|
+
* We do this for schemas with non-deferred foreign keys (order matters)
|
|
14
|
+
* or schemas with UUID id columns.
|
|
15
|
+
*/
|
|
30
16
|
function generateExplicitFlushFunction(db) {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
if (x !== y) {
|
|
40
|
-
return y - x;
|
|
41
|
-
}
|
|
42
|
-
// Flush base tables before sub-tables.
|
|
43
|
-
const i = a.baseClassName ? 1 : -1;
|
|
44
|
-
const j = b.baseClassName ? 1 : -1;
|
|
45
|
-
return j - i;
|
|
46
|
-
})
|
|
47
|
-
.map((e) => e.tableName),
|
|
48
|
-
];
|
|
49
|
-
// Note that, for whatever reason, doing DELETEs + ALTER SEQUENCEs is dramatically faster than TRUNCATEs.
|
|
50
|
-
// On even a 40-table schema, TRUNCATEs (either 1 per table or even a single TRUNCATE with all tables) takes
|
|
51
|
-
// 100s of milliseconds, whereas DELETEs takes single-digit milliseconds and DELETEs + ALTER SEQUENCEs is
|
|
52
|
-
// 10s of milliseconds.
|
|
53
|
-
const deletes = tables.flatMap((t) => [
|
|
54
|
-
`DELETE FROM "${t}";`,
|
|
55
|
-
`ALTER SEQUENCE IF EXISTS "${t}_id_seq" RESTART WITH 1 INCREMENT BY 1;`,
|
|
56
|
-
]);
|
|
57
|
-
// Create `SET NULLs` in schemas that don't have deferred FKs
|
|
58
|
-
const setFksNulls = db.entities
|
|
59
|
-
.filter((t) => t.nonDeferredFkOrder)
|
|
60
|
-
.flatMap((t) => t.manyToOnes
|
|
61
|
-
// These FKs will auto-unset/delete the later row, so don't need explicit unsetting
|
|
62
|
-
.filter((m2o) => m2o.onDelete !== "SET NULL" && m2o.onDelete !== "CASCADE")
|
|
63
|
-
// Look for FKs to tables whose DELETEs come after us
|
|
64
|
-
.filter((m2o) => db.entitiesByName[m2o.otherEntity.name].nonDeferredFkOrder > t.nonDeferredFkOrder)
|
|
65
|
-
.map((m2o) => `UPDATE ${t.tableName} SET "${m2o.columnName}" = NULL;`));
|
|
66
|
-
const statements = [...setFksNulls, ...deletes].join("\n");
|
|
67
|
-
return `CREATE OR REPLACE FUNCTION flush_database() RETURNS void AS $$
|
|
17
|
+
const deletes = [...db.joinTables, ...[...db.entities].sort((a, b) => {
|
|
18
|
+
const x = a.nonDeferredFkOrder;
|
|
19
|
+
const y = b.nonDeferredFkOrder;
|
|
20
|
+
if (x !== y) return y - x;
|
|
21
|
+
const i = a.baseClassName ? 1 : -1;
|
|
22
|
+
return (b.baseClassName ? 1 : -1) - i;
|
|
23
|
+
}).map((e) => e.tableName)].flatMap((t) => [`DELETE FROM "${t}";`, `ALTER SEQUENCE IF EXISTS "${t}_id_seq" RESTART WITH 1 INCREMENT BY 1;`]);
|
|
24
|
+
return `CREATE OR REPLACE FUNCTION flush_database() RETURNS void AS $$
|
|
68
25
|
BEGIN
|
|
69
|
-
${
|
|
26
|
+
${[...db.entities.filter((t) => t.nonDeferredFkOrder).flatMap((t) => t.manyToOnes.filter((m2o) => m2o.onDelete !== "SET NULL" && m2o.onDelete !== "CASCADE").filter((m2o) => db.entitiesByName[m2o.otherEntity.name].nonDeferredFkOrder > t.nonDeferredFkOrder).map((m2o) => `UPDATE ${t.tableName} SET "${m2o.columnName}" = NULL;`)), ...deletes].join("\n")}
|
|
70
27
|
END;
|
|
71
28
|
$$ LANGUAGE
|
|
72
29
|
'plpgsql'`;
|
|
73
30
|
}
|
|
74
31
|
/**
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
32
|
+
* A cuter/shorter flush that only DELETEs from tables that were inserted into.
|
|
33
|
+
*
|
|
34
|
+
* The difference between this and the explicit-order function should only be
|
|
35
|
+
* noticeable on 100+ table schemas (specifically, on our production app with ~200 tables
|
|
36
|
+
* and ~5,000 tests, it gave an 8% speed-up vs. the "DELETE every table" approach).
|
|
37
|
+
*/
|
|
81
38
|
function generateSequenceFlushFunction(db) {
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
...db.otherTables,
|
|
85
|
-
];
|
|
86
|
-
const maybeSkipStable = stableTables.length === 0
|
|
87
|
-
? ""
|
|
88
|
-
: `AND sequencename NOT IN (${stableTables.map((t) => `'${t}_id_seq'`).join(", ")})`;
|
|
89
|
-
return `CREATE OR REPLACE FUNCTION flush_database() RETURNS void AS $$
|
|
39
|
+
const stableTables = [...Object.values(db.enums).map((e) => e.table.name), ...db.otherTables];
|
|
40
|
+
return `CREATE OR REPLACE FUNCTION flush_database() RETURNS void AS $$
|
|
90
41
|
DECLARE seq RECORD;
|
|
91
42
|
BEGIN
|
|
92
43
|
FOR seq IN
|
|
93
44
|
SELECT sequencename AS name
|
|
94
45
|
FROM pg_sequences
|
|
95
|
-
WHERE schemaname = 'public' AND last_value IS NOT NULL AND sequencename LIKE '%_id_seq' ${
|
|
46
|
+
WHERE schemaname = 'public' AND last_value IS NOT NULL AND sequencename LIKE '%_id_seq' ${stableTables.length === 0 ? "" : `AND sequencename NOT IN (${stableTables.map((t) => `'${t}_id_seq'`).join(", ")})`}
|
|
96
47
|
LOOP
|
|
97
48
|
EXECUTE format('DELETE FROM %I', regexp_replace(seq.name, '_id_seq$', ''));
|
|
98
49
|
EXECUTE format('ALTER SEQUENCE %I RESTART WITH 1', seq.name);
|
|
@@ -101,4 +52,7 @@ function generateSequenceFlushFunction(db) {
|
|
|
101
52
|
$$ LANGUAGE
|
|
102
53
|
'plpgsql'`;
|
|
103
54
|
}
|
|
55
|
+
//#endregion
|
|
56
|
+
export { createFlushFunction, generateExplicitFlushFunction, generateSequenceFlushFunction };
|
|
57
|
+
|
|
104
58
|
//# sourceMappingURL=generateFlushFunction.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generateFlushFunction.js","
|
|
1
|
+
{"version":3,"file":"generateFlushFunction.js","names":[],"sources":["../src/generateFlushFunction.ts"],"sourcesContent":["import { type Client } from \"pg\";\n\nimport { type DbMetadata } from \"./EntityDbMetadata.ts\";\n\n/** Creates a `flush_database` stored procedure to truncate all the tables between tests. */\nexport async function createFlushFunction(client: Client, db: DbMetadata): Promise<void> {\n // We only check nonDeferredManyToManyFks here (and not other places) b/c we don't really count/track m2ms\n // as true FK dependencies -- they would a) always create cycles, and b) it's easiest enough for us to just\n // always have `flush_database` / `em.flush` delete from m2m tables first, to avoid FK delete constraints\n // errors when we delete from the main entity tables.\n //\n // ...but, because order matters for the m2m tables, then we have to use the `generateExplicitFlushFunction`\n // instead of the cuter `generateSequenceFlushFunction`.\n const hasAnyNonDeferredFks = db.entities.some(\n (e) => e.nonDeferredFks.length > 0 || e.nonDeferredManyToManyFks.length > 0,\n );\n const hasAnyNonSequenceIds = db.entities.some((e) => e.primaryKey.columnType === \"uuid\");\n if (hasAnyNonSequenceIds || hasAnyNonDeferredFks) {\n await client.query(generateExplicitFlushFunction(db));\n } else {\n await client.query(generateSequenceFlushFunction(db));\n }\n}\n\n/**\n * Explicitly deletes every entity/m2m table in a deterministic order.\n *\n * We do this for schemas with non-deferred foreign keys (order matters)\n * or schemas with UUID id columns.\n */\nexport function generateExplicitFlushFunction(db: DbMetadata): string {\n // Leave code/enum tables alone\n const tables = [\n ...db.joinTables,\n ...[...db.entities]\n .sort((a, b) => {\n // Flush books before authors if it has non-deferred FKs\n const x = a.nonDeferredFkOrder;\n const y = b.nonDeferredFkOrder;\n if (x !== y) {\n return y - x;\n }\n // Flush base tables before sub-tables.\n const i = a.baseClassName ? 1 : -1;\n const j = b.baseClassName ? 1 : -1;\n return j - i;\n })\n .map((e) => e.tableName),\n ];\n\n // Note that, for whatever reason, doing DELETEs + ALTER SEQUENCEs is dramatically faster than TRUNCATEs.\n // On even a 40-table schema, TRUNCATEs (either 1 per table or even a single TRUNCATE with all tables) takes\n // 100s of milliseconds, whereas DELETEs takes single-digit milliseconds and DELETEs + ALTER SEQUENCEs is\n // 10s of milliseconds.\n const deletes = tables.flatMap((t) => [\n `DELETE FROM \"${t}\";`,\n `ALTER SEQUENCE IF EXISTS \"${t}_id_seq\" RESTART WITH 1 INCREMENT BY 1;`,\n ]);\n\n // Create `SET NULLs` in schemas that don't have deferred FKs\n const setFksNulls = db.entities\n .filter((t) => t.nonDeferredFkOrder)\n .flatMap((t) =>\n t.manyToOnes\n // These FKs will auto-unset/delete the later row, so don't need explicit unsetting\n .filter((m2o) => m2o.onDelete !== \"SET NULL\" && m2o.onDelete !== \"CASCADE\")\n // Look for FKs to tables whose DELETEs come after us\n .filter((m2o) => db.entitiesByName[m2o.otherEntity.name].nonDeferredFkOrder > t.nonDeferredFkOrder)\n .map((m2o) => `UPDATE ${t.tableName} SET \"${m2o.columnName}\" = NULL;`),\n );\n\n const statements = [...setFksNulls, ...deletes].join(\"\\n\");\n\n return `CREATE OR REPLACE FUNCTION flush_database() RETURNS void AS $$\n BEGIN\n ${statements}\n END;\n $$ LANGUAGE\n 'plpgsql'`;\n}\n\n/**\n * A cuter/shorter flush that only DELETEs from tables that were inserted into.\n *\n * The difference between this and the explicit-order function should only be\n * noticeable on 100+ table schemas (specifically, on our production app with ~200 tables\n * and ~5,000 tests, it gave an 8% speed-up vs. the \"DELETE every table\" approach).\n */\nexport function generateSequenceFlushFunction(db: DbMetadata): string {\n const stableTables = [...Object.values(db.enums).map((e) => e.table.name), ...db.otherTables];\n const maybeSkipStable =\n stableTables.length === 0 ? \"\" : `AND sequencename NOT IN (${stableTables.map((t) => `'${t}_id_seq'`).join(\", \")})`;\n return `CREATE OR REPLACE FUNCTION flush_database() RETURNS void AS $$\n DECLARE seq RECORD;\n BEGIN\n FOR seq IN\n SELECT sequencename AS name\n FROM pg_sequences\n WHERE schemaname = 'public' AND last_value IS NOT NULL AND sequencename LIKE '%_id_seq' ${maybeSkipStable}\n LOOP\n EXECUTE format('DELETE FROM %I', regexp_replace(seq.name, '_id_seq$', ''));\n EXECUTE format('ALTER SEQUENCE %I RESTART WITH 1', seq.name);\n END LOOP;\n END;\n $$ LANGUAGE\n 'plpgsql'`;\n}\n"],"mappings":";;;;AAKA,eAAsB,oBAAoB,QAAgB,IAA+B;CAQvF,MAAM,uBAAuB,GAAG,SAAS,MACtC,MAAM,EAAE,eAAe,SAAS,KAAK,EAAE,yBAAyB,SAAS,CAC5E;CAEA,IAD6B,GAAG,SAAS,MAAM,MAAM,EAAE,WAAW,eAAe,MAC1D,KAAK,sBAC1B,MAAM,OAAO,MAAM,8BAA8B,EAAE,CAAC;MAEpD,MAAM,OAAO,MAAM,8BAA8B,EAAE,CAAC;AAExD;;;;;;;AAQA,SAAgB,8BAA8B,IAAwB;CAwBpE,MAAM,UAAU,CArBd,GAAG,GAAG,YACN,GAAG,CAAC,GAAG,GAAG,QAAQ,CAAC,CAChB,MAAM,GAAG,MAAM;EAEd,MAAM,IAAI,EAAE;EACZ,MAAM,IAAI,EAAE;EACZ,IAAI,MAAM,GACR,OAAO,IAAI;EAGb,MAAM,IAAI,EAAE,gBAAgB,IAAI;EAEhC,QADU,EAAE,gBAAgB,IAAI,MACrB;CACb,CAAC,CAAC,CACD,KAAK,MAAM,EAAE,SAAS,CAON,CAAC,CAAC,SAAS,MAAM,CACpC,gBAAgB,EAAE,KAClB,6BAA6B,EAAE,wCACjC,CAAC;CAgBD,OAAO;;QAFY,CAAC,GAXA,GAAG,SACpB,QAAQ,MAAM,EAAE,kBAAkB,CAAC,CACnC,SAAS,MACR,EAAE,WAEC,QAAQ,QAAQ,IAAI,aAAa,cAAc,IAAI,aAAa,SAAS,CAAC,CAE1E,QAAQ,QAAQ,GAAG,eAAe,IAAI,YAAY,KAAK,CAAC,qBAAqB,EAAE,kBAAkB,CAAC,CAClG,KAAK,QAAQ,UAAU,EAAE,UAAU,QAAQ,IAAI,WAAW,UAAU,CAG1C,GAAG,GAAG,OAAO,CAAC,CAAC,KAAK,IAItC,EAAE;;;;AAInB;;;;;;;;AASA,SAAgB,8BAA8B,IAAwB;CACpE,MAAM,eAAe,CAAC,GAAG,OAAO,OAAO,GAAG,KAAK,CAAC,CAAC,KAAK,MAAM,EAAE,MAAM,IAAI,GAAG,GAAG,GAAG,WAAW;CAG5F,OAAO;;;;;;kGADL,aAAa,WAAW,IAAI,KAAK,4BAA4B,aAAa,KAAK,MAAM,IAAI,EAAE,SAAS,CAAC,CAAC,KAAK,IAAI,EAAE,GAOH;;;;;;;;AAQlH"}
|