@tailor-platform/erp-kit 0.1.2 → 0.2.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/CHANGELOG.md +6 -0
- package/README.md +81 -12
- package/dist/cli.js +1070 -450
- package/package.json +11 -8
- package/schemas/module/model.yml +5 -0
- package/skills/{app-compose-1-requirement-analysis → erp-kit-app-1-requirements}/SKILL.md +2 -2
- package/skills/{app-compose-2-requirements-breakdown → erp-kit-app-2-breakdown}/SKILL.md +3 -3
- package/skills/{app-compose-3-doc-review → erp-kit-app-3-doc-review}/SKILL.md +2 -2
- package/skills/{app-compose-4-design-mock → erp-kit-app-4-design}/SKILL.md +3 -3
- package/skills/{app-compose-5-design-mock-review → erp-kit-app-5-design-review}/SKILL.md +4 -4
- package/skills/{app-compose-6-implementation-spec → erp-kit-app-6-impl-spec}/SKILL.md +3 -3
- package/skills/{mock-scenario → erp-kit-mock-scenario}/SKILL.md +1 -1
- package/skills/{1-module-docs → erp-kit-module-1-docs}/SKILL.md +2 -2
- package/skills/{2-module-feature-breakdown → erp-kit-module-2-feature-breakdown}/SKILL.md +13 -9
- package/skills/erp-kit-module-2-feature-breakdown/references/naming.md +59 -0
- package/skills/{3-module-doc-review → erp-kit-module-3-doc-review}/SKILL.md +83 -25
- package/skills/erp-kit-module-4-tdd/SKILL.md +94 -0
- package/skills/erp-kit-module-4-tdd/references/cross-module-dependency.md +133 -0
- package/skills/{4-module-tdd-implementation → erp-kit-module-4-tdd}/references/db-relations.md +5 -1
- package/skills/{4-module-tdd-implementation → erp-kit-module-4-tdd}/references/exports.md +1 -1
- package/skills/erp-kit-module-4-tdd/references/generated-code.md +32 -0
- package/skills/{5-module-implementation-review → erp-kit-module-5-impl-review}/SKILL.md +46 -44
- package/skills/erp-kit-module-5-impl-review/references/commands.md +62 -0
- package/skills/erp-kit-module-5-impl-review/references/errors.md +10 -0
- package/skills/{5-module-implementation-review → erp-kit-module-5-impl-review}/references/testing.md +1 -1
- package/skills/erp-kit-module-shared/SKILL.md +16 -0
- package/skills/erp-kit-module-shared/references/commands.md +203 -0
- package/skills/erp-kit-module-shared/references/errors.md +35 -0
- package/skills/erp-kit-module-shared/references/queries.md +168 -0
- package/skills/erp-kit-module-shared/references/structure.md +36 -0
- package/skills/{3-module-doc-review → erp-kit-module-shared}/references/testing.md +4 -3
- package/skills/erp-kit-update/SKILL.md +64 -0
- package/src/cli.doc.test.ts +65 -0
- package/src/cli.ts +3 -35
- package/src/commands/app/index.ts +3 -3
- package/src/commands/check.test.ts +1 -1
- package/src/commands/check.ts +2 -2
- package/src/commands/index.ts +73 -0
- package/src/commands/init.test.ts +22 -5
- package/src/commands/init.ts +25 -16
- package/src/commands/license.ts +193 -0
- package/src/commands/mock/index.ts +2 -2
- package/src/commands/mock/start.ts +1 -1
- package/src/commands/mock/validate.test.ts +1 -1
- package/src/commands/module/generate.ts +35 -0
- package/src/commands/module/index.ts +6 -4
- package/src/commands/module/list.test.ts +7 -12
- package/src/commands/module/list.ts +1 -1
- package/src/commands/scaffold-templates.ts +65 -0
- package/src/commands/scaffold.test.ts +92 -2
- package/src/commands/scaffold.ts +22 -2
- package/src/commands/sync-check.test.ts +60 -1
- package/src/commands/sync-check.ts +35 -2
- package/src/generator/generate-code.test.ts +200 -0
- package/src/generator/generate-code.ts +260 -0
- package/src/generator/parse-command-doc.test.ts +159 -0
- package/src/generator/parse-command-doc.ts +116 -0
- package/src/integration.test.ts +2 -2
- package/src/module.ts +6 -6
- package/src/modules/item-management/README.md +38 -0
- package/src/modules/item-management/command/activateItem.generated.ts +6 -0
- package/src/modules/item-management/command/activateItem.test.ts +76 -0
- package/src/modules/item-management/command/activateItem.ts +42 -0
- package/src/modules/item-management/command/assignItemToTaxonomy.generated.ts +6 -0
- package/src/modules/item-management/command/assignItemToTaxonomy.test.ts +88 -0
- package/src/modules/item-management/command/assignItemToTaxonomy.ts +63 -0
- package/src/modules/item-management/command/createItem.generated.ts +6 -0
- package/src/modules/item-management/command/createItem.test.ts +152 -0
- package/src/modules/item-management/command/createItem.ts +72 -0
- package/src/modules/item-management/command/createTaxonomyNode.generated.ts +6 -0
- package/src/modules/item-management/command/createTaxonomyNode.test.ts +126 -0
- package/src/modules/item-management/command/createTaxonomyNode.ts +70 -0
- package/src/modules/item-management/command/deactivateItem.generated.ts +6 -0
- package/src/modules/item-management/command/deactivateItem.test.ts +76 -0
- package/src/modules/item-management/command/deactivateItem.ts +42 -0
- package/src/modules/item-management/command/deleteItem.generated.ts +6 -0
- package/src/modules/item-management/command/deleteItem.test.ts +61 -0
- package/src/modules/item-management/command/deleteItem.ts +38 -0
- package/src/modules/item-management/command/deleteTaxonomyNode.generated.ts +6 -0
- package/src/modules/item-management/command/deleteTaxonomyNode.test.ts +73 -0
- package/src/modules/item-management/command/deleteTaxonomyNode.ts +50 -0
- package/src/modules/item-management/command/moveTaxonomyNode.generated.ts +6 -0
- package/src/modules/item-management/command/moveTaxonomyNode.test.ts +136 -0
- package/src/modules/item-management/command/moveTaxonomyNode.ts +85 -0
- package/src/modules/item-management/command/reactivateItem.generated.ts +6 -0
- package/src/modules/item-management/command/reactivateItem.test.ts +76 -0
- package/src/modules/item-management/command/reactivateItem.ts +42 -0
- package/src/modules/item-management/command/removeItemFromTaxonomy.generated.ts +6 -0
- package/src/modules/item-management/command/removeItemFromTaxonomy.test.ts +43 -0
- package/src/modules/item-management/command/removeItemFromTaxonomy.ts +30 -0
- package/src/modules/item-management/command/updateItem.generated.ts +6 -0
- package/src/modules/item-management/command/updateItem.test.ts +178 -0
- package/src/modules/item-management/command/updateItem.ts +103 -0
- package/src/modules/item-management/command/updateTaxonomyNode.generated.ts +6 -0
- package/src/modules/item-management/command/updateTaxonomyNode.test.ts +88 -0
- package/src/modules/item-management/command/updateTaxonomyNode.ts +62 -0
- package/src/modules/item-management/db/item.ts +47 -0
- package/src/modules/item-management/db/itemTaxonomyAssignment.ts +49 -0
- package/src/modules/item-management/db/taxonomyNode.ts +34 -0
- package/src/modules/item-management/docs/commands/ActivateItem.md +32 -0
- package/src/modules/item-management/docs/commands/AssignItemToTaxonomy.md +38 -0
- package/src/modules/item-management/docs/commands/CreateItem.md +44 -0
- package/src/modules/item-management/docs/commands/CreateTaxonomyNode.md +44 -0
- package/src/modules/item-management/docs/commands/DeactivateItem.md +34 -0
- package/src/modules/item-management/docs/commands/DeleteItem.md +35 -0
- package/src/modules/item-management/docs/commands/DeleteTaxonomyNode.md +39 -0
- package/src/modules/item-management/docs/commands/MoveTaxonomyNode.md +45 -0
- package/src/modules/item-management/docs/commands/ReactivateItem.md +34 -0
- package/src/modules/item-management/docs/commands/RemoveItemFromTaxonomy.md +30 -0
- package/src/modules/item-management/docs/commands/UpdateItem.md +55 -0
- package/src/modules/item-management/docs/commands/UpdateTaxonomyNode.md +36 -0
- package/src/modules/item-management/docs/features/item-lifecycle.md +60 -0
- package/src/modules/item-management/docs/features/item-taxonomy.md +65 -0
- package/src/modules/item-management/docs/models/ItemTaxonomyAssignment.md +36 -0
- package/src/modules/item-management/docs/models/TaxonomyNode.md +47 -0
- package/src/modules/item-management/docs/models/item.md +59 -0
- package/src/modules/item-management/docs/queries/CalculateNodeDepth.md +36 -0
- package/src/modules/item-management/docs/queries/CalculateSubtreeDepth.md +40 -0
- package/src/modules/item-management/docs/queries/DetectCircularReference.md +41 -0
- package/src/modules/item-management/docs/queries/GetItem.md +38 -0
- package/src/modules/item-management/docs/queries/GetItemTaxonomyAssignment.md +29 -0
- package/src/modules/item-management/docs/queries/GetTaxonomyNode.md +35 -0
- package/src/modules/item-management/docs/queries/GetTaxonomyNodeAssignments.md +29 -0
- package/src/modules/item-management/docs/queries/GetTaxonomyNodeChildren.md +29 -0
- package/src/modules/item-management/generated/enums.ts +9 -0
- package/src/modules/item-management/generated/kysely-tailordb.ts +62 -0
- package/src/modules/item-management/index.ts +53 -0
- package/src/modules/item-management/lib/_db_deps.ts +13 -0
- package/src/modules/item-management/lib/errors.generated.ts +117 -0
- package/src/modules/item-management/lib/permissions.generated.ts +17 -0
- package/src/modules/item-management/lib/types.ts +19 -0
- package/src/modules/item-management/module.ts +97 -0
- package/src/modules/item-management/query/calculateNodeDepth.generated.ts +5 -0
- package/src/modules/item-management/query/calculateNodeDepth.test.ts +56 -0
- package/src/modules/item-management/query/calculateNodeDepth.ts +28 -0
- package/src/modules/item-management/query/calculateSubtreeDepth.generated.ts +5 -0
- package/src/modules/item-management/query/calculateSubtreeDepth.test.ts +75 -0
- package/src/modules/item-management/query/calculateSubtreeDepth.ts +29 -0
- package/src/modules/item-management/query/detectCircularReference.generated.ts +5 -0
- package/src/modules/item-management/query/detectCircularReference.test.ts +61 -0
- package/src/modules/item-management/query/detectCircularReference.ts +32 -0
- package/src/modules/item-management/query/getItem.generated.ts +5 -0
- package/src/modules/item-management/query/getItem.test.ts +67 -0
- package/src/modules/item-management/query/getItem.ts +20 -0
- package/src/modules/item-management/query/getItemTaxonomyAssignment.generated.ts +5 -0
- package/src/modules/item-management/query/getItemTaxonomyAssignment.test.ts +25 -0
- package/src/modules/item-management/query/getItemTaxonomyAssignment.ts +18 -0
- package/src/modules/item-management/query/getTaxonomyNode.generated.ts +5 -0
- package/src/modules/item-management/query/getTaxonomyNode.test.ts +47 -0
- package/src/modules/item-management/query/getTaxonomyNode.ts +18 -0
- package/src/modules/item-management/query/getTaxonomyNodeAssignments.generated.ts +5 -0
- package/src/modules/item-management/query/getTaxonomyNodeAssignments.test.ts +25 -0
- package/src/modules/item-management/query/getTaxonomyNodeAssignments.ts +16 -0
- package/src/modules/item-management/query/getTaxonomyNodeChildren.generated.ts +5 -0
- package/src/modules/item-management/query/getTaxonomyNodeChildren.test.ts +34 -0
- package/src/modules/item-management/query/getTaxonomyNodeChildren.ts +16 -0
- package/src/modules/item-management/tailor.config.ts +11 -0
- package/src/modules/item-management/testing/fixtures.ts +81 -0
- package/src/modules/primitives/command/activateCategory.generated.ts +6 -0
- package/src/modules/primitives/command/activateCategory.test.ts +11 -29
- package/src/modules/primitives/command/activateCategory.ts +27 -34
- package/src/modules/primitives/command/activateCurrency.generated.ts +6 -0
- package/src/modules/primitives/command/activateCurrency.test.ts +11 -29
- package/src/modules/primitives/command/activateCurrency.ts +27 -34
- package/src/modules/primitives/command/activateUnit.generated.ts +6 -0
- package/src/modules/primitives/command/activateUnit.test.ts +11 -15
- package/src/modules/primitives/command/activateUnit.ts +27 -34
- package/src/modules/primitives/command/createCategory.generated.ts +6 -0
- package/src/modules/primitives/command/createCategory.test.ts +27 -39
- package/src/modules/primitives/command/createCategory.ts +53 -62
- package/src/modules/primitives/command/createCurrency.generated.ts +6 -0
- package/src/modules/primitives/command/createCurrency.test.ts +78 -71
- package/src/modules/primitives/command/createCurrency.ts +43 -48
- package/src/modules/primitives/command/createExchangeRate.generated.ts +6 -0
- package/src/modules/primitives/command/createExchangeRate.test.ts +101 -100
- package/src/modules/primitives/command/createExchangeRate.ts +50 -59
- package/src/modules/primitives/command/createUnit.generated.ts +6 -0
- package/src/modules/primitives/command/createUnit.test.ts +92 -95
- package/src/modules/primitives/command/createUnit.ts +54 -57
- package/src/modules/primitives/command/deactivateCategory.generated.ts +6 -0
- package/src/modules/primitives/command/deactivateCategory.test.ts +27 -28
- package/src/modules/primitives/command/deactivateCategory.ts +43 -50
- package/src/modules/primitives/command/deactivateCurrency.generated.ts +6 -0
- package/src/modules/primitives/command/deactivateCurrency.test.ts +23 -38
- package/src/modules/primitives/command/deactivateCurrency.ts +31 -38
- package/src/modules/primitives/command/deactivateUnit.generated.ts +6 -0
- package/src/modules/primitives/command/deactivateUnit.test.ts +27 -23
- package/src/modules/primitives/command/deactivateUnit.ts +39 -49
- package/src/modules/primitives/command/setBaseCurrency.generated.ts +6 -0
- package/src/modules/primitives/command/setBaseCurrency.test.ts +40 -33
- package/src/modules/primitives/command/setBaseCurrency.ts +43 -50
- package/src/modules/primitives/command/setReferenceUnit.generated.ts +6 -0
- package/src/modules/primitives/command/setReferenceUnit.test.ts +39 -35
- package/src/modules/primitives/command/setReferenceUnit.ts +46 -59
- package/src/modules/primitives/db/unit.ts +13 -3
- package/src/modules/primitives/docs/commands/ActivateCategory.md +1 -2
- package/src/modules/primitives/docs/commands/ActivateCurrency.md +1 -2
- package/src/modules/primitives/docs/commands/ActivateUnit.md +1 -2
- package/src/modules/primitives/docs/commands/CreateCategory.md +1 -4
- package/src/modules/primitives/docs/commands/CreateCurrency.md +3 -4
- package/src/modules/primitives/docs/commands/CreateExchangeRate.md +4 -5
- package/src/modules/primitives/docs/commands/CreateUnit.md +5 -5
- package/src/modules/primitives/docs/commands/DeactivateCategory.md +2 -3
- package/src/modules/primitives/docs/commands/DeactivateCurrency.md +2 -3
- package/src/modules/primitives/docs/commands/DeactivateUnit.md +2 -3
- package/src/modules/primitives/docs/commands/SetBaseCurrency.md +2 -3
- package/src/modules/primitives/docs/commands/SetReferenceUnit.md +2 -3
- package/src/modules/primitives/docs/queries/ConvertAmount.md +3 -5
- package/src/modules/primitives/docs/queries/ConvertQuantity.md +3 -5
- package/src/modules/primitives/docs/queries/GetBaseCurrency.md +32 -0
- package/src/modules/primitives/docs/queries/GetCurrency.md +36 -0
- package/src/modules/primitives/docs/queries/GetUnit.md +36 -0
- package/src/modules/primitives/docs/queries/GetUoMCategory.md +36 -0
- package/src/modules/primitives/docs/queries/ListUnitsByCategory.md +26 -0
- package/src/modules/primitives/generated/kysely-tailordb.ts +24 -45
- package/src/modules/primitives/index.ts +15 -4
- package/src/modules/primitives/lib/errors.generated.ts +112 -0
- package/src/modules/primitives/{permissions.ts → lib/permissions.generated.ts} +9 -8
- package/src/modules/primitives/module.ts +37 -27
- package/src/modules/primitives/query/convertAmount.generated.ts +5 -0
- package/src/modules/primitives/query/convertAmount.test.ts +2 -2
- package/src/modules/primitives/query/convertAmount.ts +27 -28
- package/src/modules/primitives/query/convertQuantity.generated.ts +5 -0
- package/src/modules/primitives/query/convertQuantity.test.ts +6 -2
- package/src/modules/primitives/query/convertQuantity.ts +49 -57
- package/src/modules/primitives/query/getBaseCurrency.generated.ts +5 -0
- package/src/modules/primitives/query/getBaseCurrency.test.ts +28 -0
- package/src/modules/primitives/query/getBaseCurrency.ts +16 -0
- package/src/modules/primitives/query/getCurrency.generated.ts +5 -0
- package/src/modules/primitives/query/getCurrency.test.ts +47 -0
- package/src/modules/primitives/query/getCurrency.ts +18 -0
- package/src/modules/primitives/query/getUnit.generated.ts +5 -0
- package/src/modules/primitives/query/getUnit.test.ts +47 -0
- package/src/modules/primitives/query/getUnit.ts +18 -0
- package/src/modules/primitives/query/getUoMCategory.generated.ts +5 -0
- package/src/modules/primitives/query/getUoMCategory.test.ts +47 -0
- package/src/modules/primitives/query/getUoMCategory.ts +18 -0
- package/src/modules/primitives/query/listUnitsByCategory.generated.ts +5 -0
- package/src/modules/primitives/query/listUnitsByCategory.ts +16 -0
- package/src/modules/primitives/tailor.config.ts +3 -3
- package/src/modules/shared/defineCommand.test.ts +23 -10
- package/src/modules/shared/defineCommand.ts +23 -10
- package/src/modules/shared/internal.ts +1 -0
- package/src/modules/shared/requirePermission.test.ts +22 -21
- package/src/modules/shared/requirePermission.ts +8 -2
- package/src/modules/shared/result.ts +12 -0
- package/src/modules/testing/index.ts +36 -11
- package/src/modules/user-management/command/activateUser.generated.ts +6 -0
- package/src/modules/user-management/command/activateUser.test.ts +27 -27
- package/src/modules/user-management/command/activateUser.ts +40 -48
- package/src/modules/user-management/command/assignPermissionToRole.generated.ts +6 -0
- package/src/modules/user-management/command/assignPermissionToRole.test.ts +42 -43
- package/src/modules/user-management/command/assignPermissionToRole.ts +59 -62
- package/src/modules/user-management/command/assignRoleToUser.generated.ts +6 -0
- package/src/modules/user-management/command/assignRoleToUser.test.ts +70 -63
- package/src/modules/user-management/command/assignRoleToUser.ts +63 -66
- package/src/modules/user-management/command/createPermission.generated.ts +6 -0
- package/src/modules/user-management/command/createPermission.test.ts +45 -38
- package/src/modules/user-management/command/createPermission.ts +42 -46
- package/src/modules/user-management/command/createRole.generated.ts +6 -0
- package/src/modules/user-management/command/createRole.test.ts +30 -29
- package/src/modules/user-management/command/createRole.ts +33 -33
- package/src/modules/user-management/command/createUser.generated.ts +6 -0
- package/src/modules/user-management/command/createUser.test.ts +64 -42
- package/src/modules/user-management/command/createUser.ts +54 -56
- package/src/modules/user-management/command/deactivateUser.generated.ts +6 -0
- package/src/modules/user-management/command/deactivateUser.test.ts +27 -27
- package/src/modules/user-management/command/deactivateUser.ts +40 -48
- package/src/modules/user-management/command/logAuditEvent.generated.ts +6 -0
- package/src/modules/user-management/command/logAuditEvent.test.ts +50 -42
- package/src/modules/user-management/command/logAuditEvent.ts +25 -28
- package/src/modules/user-management/command/reactivateUser.generated.ts +6 -0
- package/src/modules/user-management/command/reactivateUser.test.ts +31 -27
- package/src/modules/user-management/command/reactivateUser.ts +40 -48
- package/src/modules/user-management/command/revokePermissionFromRole.generated.ts +6 -0
- package/src/modules/user-management/command/revokePermissionFromRole.test.ts +52 -51
- package/src/modules/user-management/command/revokePermissionFromRole.ts +60 -57
- package/src/modules/user-management/command/revokeRoleFromUser.generated.ts +6 -0
- package/src/modules/user-management/command/revokeRoleFromUser.test.ts +53 -48
- package/src/modules/user-management/command/revokeRoleFromUser.ts +58 -57
- package/src/modules/user-management/docs/commands/CreatePermission.md +2 -2
- package/src/modules/user-management/docs/commands/CreateRole.md +1 -1
- package/src/modules/user-management/generated/enums.ts +11 -11
- package/src/modules/user-management/generated/kysely-tailordb.ts +27 -56
- package/src/modules/user-management/index.ts +2 -2
- package/src/modules/user-management/lib/errors.generated.ts +67 -0
- package/src/modules/user-management/{permissions.ts → lib/permissions.generated.ts} +8 -7
- package/src/modules/user-management/module.ts +22 -22
- package/src/modules/user-management/tailor.config.ts +3 -3
- package/src/schemas.ts +1 -1
- package/skills/1-module-docs/references/structure.md +0 -22
- package/skills/2-module-feature-breakdown/references/commands.md +0 -48
- package/skills/2-module-feature-breakdown/references/structure.md +0 -22
- package/skills/3-module-doc-review/references/commands.md +0 -54
- package/skills/3-module-doc-review/references/models.md +0 -29
- package/skills/4-module-tdd-implementation/SKILL.md +0 -74
- package/skills/4-module-tdd-implementation/references/commands.md +0 -45
- package/skills/4-module-tdd-implementation/references/errors.md +0 -7
- package/skills/4-module-tdd-implementation/references/models.md +0 -30
- package/skills/4-module-tdd-implementation/references/structure.md +0 -22
- package/skills/4-module-tdd-implementation/references/testing.md +0 -37
- package/skills/5-module-implementation-review/references/commands.md +0 -45
- package/skills/5-module-implementation-review/references/errors.md +0 -7
- package/skills/5-module-implementation-review/references/exports.md +0 -8
- package/skills/5-module-implementation-review/references/models.md +0 -30
- package/src/modules/primitives/lib/errors.ts +0 -138
- package/src/modules/user-management/lib/errors.ts +0 -81
- /package/skills/{app-compose-1-requirement-analysis → erp-kit-app-1-requirements}/references/structure.md +0 -0
- /package/skills/{app-compose-2-requirements-breakdown → erp-kit-app-2-breakdown}/references/screen-detailview.md +0 -0
- /package/skills/{app-compose-2-requirements-breakdown → erp-kit-app-2-breakdown}/references/screen-form.md +0 -0
- /package/skills/{app-compose-2-requirements-breakdown → erp-kit-app-2-breakdown}/references/screen-listview.md +0 -0
- /package/skills/{app-compose-2-requirements-breakdown → erp-kit-app-2-breakdown}/references/structure.md +0 -0
- /package/skills/{app-compose-3-doc-review → erp-kit-app-3-doc-review}/references/structure.md +0 -0
- /package/skills/{app-compose-4-design-mock → erp-kit-app-4-design}/references/component.md +0 -0
- /package/skills/{app-compose-4-design-mock → erp-kit-app-4-design}/references/screen-detailview.md +0 -0
- /package/skills/{app-compose-4-design-mock → erp-kit-app-4-design}/references/screen-form.md +0 -0
- /package/skills/{app-compose-4-design-mock → erp-kit-app-4-design}/references/screen-listview.md +0 -0
- /package/skills/{app-compose-4-design-mock → erp-kit-app-4-design}/references/structure.md +0 -0
- /package/skills/{app-compose-5-design-mock-review → erp-kit-app-5-design-review}/references/component.md +0 -0
- /package/skills/{app-compose-5-design-mock-review → erp-kit-app-5-design-review}/references/screen-detailview.md +0 -0
- /package/skills/{app-compose-5-design-mock-review → erp-kit-app-5-design-review}/references/screen-form.md +0 -0
- /package/skills/{app-compose-5-design-mock-review → erp-kit-app-5-design-review}/references/screen-listview.md +0 -0
- /package/skills/{app-compose-6-implementation-spec → erp-kit-app-6-impl-spec}/references/auth.md +0 -0
- /package/skills/{app-compose-6-implementation-spec → erp-kit-app-6-impl-spec}/references/structure.md +0 -0
- /package/skills/{2-module-feature-breakdown → erp-kit-module-4-tdd}/references/models.md +0 -0
|
@@ -1,40 +1,28 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
type
|
|
5
|
-
type
|
|
6
|
-
type
|
|
7
|
-
type
|
|
8
|
-
type
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
type Generated<T> =
|
|
14
|
-
T extends ColumnType<infer S, infer I, infer U>
|
|
15
|
-
? ColumnType<S, I | undefined, U>
|
|
16
|
-
: ColumnType<T, T | undefined, T>;
|
|
2
|
+
createGetDB,
|
|
3
|
+
type Generated,
|
|
4
|
+
type Timestamp,
|
|
5
|
+
type NamespaceDB,
|
|
6
|
+
type NamespaceInsertable,
|
|
7
|
+
type NamespaceSelectable,
|
|
8
|
+
type NamespaceTable,
|
|
9
|
+
type NamespaceTableName,
|
|
10
|
+
type NamespaceTransaction,
|
|
11
|
+
type NamespaceUpdateable,
|
|
12
|
+
} from "@tailor-platform/sdk/kysely";
|
|
17
13
|
|
|
18
14
|
export interface Namespace {
|
|
19
15
|
"main-db": {
|
|
20
16
|
AuditEvent: {
|
|
21
17
|
id: Generated<string>;
|
|
22
|
-
eventType:
|
|
23
|
-
| "USER_CREATED"
|
|
24
|
-
| "USER_ACTIVATED"
|
|
25
|
-
| "USER_DEACTIVATED"
|
|
26
|
-
| "USER_REACTIVATED"
|
|
27
|
-
| "ROLE_ASSIGNED"
|
|
28
|
-
| "ROLE_REVOKED"
|
|
29
|
-
| "PERMISSION_ASSIGNED"
|
|
30
|
-
| "PERMISSION_REVOKED";
|
|
18
|
+
eventType: "USER_CREATED" | "USER_ACTIVATED" | "USER_DEACTIVATED" | "USER_REACTIVATED" | "ROLE_ASSIGNED" | "ROLE_REVOKED" | "PERMISSION_ASSIGNED" | "PERMISSION_REVOKED";
|
|
31
19
|
actorId: string;
|
|
32
20
|
targetId: string | null;
|
|
33
21
|
targetType: string | null;
|
|
34
22
|
payload: string | null;
|
|
35
23
|
createdAt: Generated<Timestamp>;
|
|
36
24
|
updatedAt: Timestamp | null;
|
|
37
|
-
}
|
|
25
|
+
}
|
|
38
26
|
|
|
39
27
|
Permission: {
|
|
40
28
|
id: Generated<string>;
|
|
@@ -42,7 +30,7 @@ export interface Namespace {
|
|
|
42
30
|
description: string | null;
|
|
43
31
|
createdAt: Generated<Timestamp>;
|
|
44
32
|
updatedAt: Timestamp | null;
|
|
45
|
-
}
|
|
33
|
+
}
|
|
46
34
|
|
|
47
35
|
Role: {
|
|
48
36
|
id: Generated<string>;
|
|
@@ -50,7 +38,7 @@ export interface Namespace {
|
|
|
50
38
|
description: string | null;
|
|
51
39
|
createdAt: Generated<Timestamp>;
|
|
52
40
|
updatedAt: Timestamp | null;
|
|
53
|
-
}
|
|
41
|
+
}
|
|
54
42
|
|
|
55
43
|
RolePermission: {
|
|
56
44
|
id: Generated<string>;
|
|
@@ -58,7 +46,7 @@ export interface Namespace {
|
|
|
58
46
|
permissionId: string;
|
|
59
47
|
createdAt: Generated<Timestamp>;
|
|
60
48
|
updatedAt: Timestamp | null;
|
|
61
|
-
}
|
|
49
|
+
}
|
|
62
50
|
|
|
63
51
|
User: {
|
|
64
52
|
id: Generated<string>;
|
|
@@ -68,7 +56,7 @@ export interface Namespace {
|
|
|
68
56
|
permissions: string[] | null;
|
|
69
57
|
createdAt: Generated<Timestamp>;
|
|
70
58
|
updatedAt: Timestamp | null;
|
|
71
|
-
}
|
|
59
|
+
}
|
|
72
60
|
|
|
73
61
|
UserRole: {
|
|
74
62
|
id: Generated<string>;
|
|
@@ -76,37 +64,20 @@ export interface Namespace {
|
|
|
76
64
|
roleId: string;
|
|
77
65
|
createdAt: Generated<Timestamp>;
|
|
78
66
|
updatedAt: Timestamp | null;
|
|
79
|
-
}
|
|
80
|
-
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
81
69
|
}
|
|
82
70
|
|
|
83
|
-
export
|
|
84
|
-
namespace: N,
|
|
85
|
-
kyselyConfig?: Omit<KyselyConfig, "dialect">,
|
|
86
|
-
): Kysely<Namespace[N]> {
|
|
87
|
-
const client = new tailordb.Client({ namespace });
|
|
88
|
-
return new Kysely<Namespace[N]>({
|
|
89
|
-
dialect: new TailordbDialect(client),
|
|
90
|
-
...kyselyConfig,
|
|
91
|
-
});
|
|
92
|
-
}
|
|
71
|
+
export const getDB = createGetDB<Namespace>();
|
|
93
72
|
|
|
94
|
-
export type DB<N extends keyof Namespace = keyof Namespace> =
|
|
73
|
+
export type DB<N extends keyof Namespace = keyof Namespace> = NamespaceDB<Namespace, N>;
|
|
95
74
|
|
|
96
75
|
export type Transaction<K extends keyof Namespace | DB = keyof Namespace> =
|
|
97
|
-
|
|
98
|
-
? KyselyTransaction<Namespace[N]>
|
|
99
|
-
: K extends keyof Namespace
|
|
100
|
-
? KyselyTransaction<Namespace[K]>
|
|
101
|
-
: never;
|
|
76
|
+
NamespaceTransaction<Namespace, K>;
|
|
102
77
|
|
|
103
|
-
type TableName =
|
|
104
|
-
|
|
105
|
-
}[keyof Namespace];
|
|
106
|
-
export type Table<T extends TableName> = {
|
|
107
|
-
[N in keyof Namespace]: T extends keyof Namespace[N] ? Namespace[N][T] : never;
|
|
108
|
-
}[keyof Namespace];
|
|
78
|
+
type TableName = NamespaceTableName<Namespace>;
|
|
79
|
+
export type Table<T extends TableName> = NamespaceTable<Namespace, T>;
|
|
109
80
|
|
|
110
|
-
export type Insertable<T extends
|
|
111
|
-
export type Selectable<T extends
|
|
112
|
-
export type Updateable<T extends
|
|
81
|
+
export type Insertable<T extends TableName> = NamespaceInsertable<Namespace, T>;
|
|
82
|
+
export type Selectable<T extends TableName> = NamespaceSelectable<Namespace, T>;
|
|
83
|
+
export type Updateable<T extends TableName> = NamespaceUpdateable<Namespace, T>;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { defineModule } from "./module";
|
|
2
|
-
export { permissions, own, all } from "./permissions";
|
|
2
|
+
export { permissions, own, all } from "./lib/permissions.generated";
|
|
3
3
|
|
|
4
4
|
// generated types
|
|
5
5
|
export { AuditEventEventType, UserStatus } from "./generated/enums";
|
|
@@ -19,7 +19,7 @@ export {
|
|
|
19
19
|
DuplicateRoleNameError,
|
|
20
20
|
AssignmentNotFoundError,
|
|
21
21
|
InvalidEventTypeError,
|
|
22
|
-
} from "./lib/errors";
|
|
22
|
+
} from "./lib/errors.generated";
|
|
23
23
|
|
|
24
24
|
// input types
|
|
25
25
|
export { type ActivateUserInput } from "./command/activateUser";
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
// @generated — do not edit
|
|
2
|
+
import { createDomainError } from "../../shared/internal";
|
|
3
|
+
|
|
4
|
+
export const UserNotFoundError = createDomainError(
|
|
5
|
+
"UserNotFoundError", "USER_NOT_FOUND",
|
|
6
|
+
(identifier: string) => `User ID does not exist in the system - return not found error with the provided ID: ${identifier}`,
|
|
7
|
+
);
|
|
8
|
+
|
|
9
|
+
export const InvalidStatusTransitionError = createDomainError(
|
|
10
|
+
"InvalidStatusTransitionError", "INVALID_STATUS_TRANSITION",
|
|
11
|
+
(identifier: string) => `User is not in PENDING status (already ACTIVE or INACTIVE) - return error with current status and valid transitions: ${identifier}`,
|
|
12
|
+
);
|
|
13
|
+
|
|
14
|
+
export const RoleNotFoundError = createDomainError(
|
|
15
|
+
"RoleNotFoundError", "ROLE_NOT_FOUND",
|
|
16
|
+
(identifier: string) => `Role ID does not exist in the system - return not found error with the provided role ID: ${identifier}`,
|
|
17
|
+
);
|
|
18
|
+
|
|
19
|
+
export const PermissionNotFoundError = createDomainError(
|
|
20
|
+
"PermissionNotFoundError", "PERMISSION_NOT_FOUND",
|
|
21
|
+
(identifier: string) => `Permission ID does not exist in the system - return not found error with the provided permission ID: ${identifier}`,
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
export const UserNotActiveError = createDomainError(
|
|
25
|
+
"UserNotActiveError", "USER_NOT_ACTIVE",
|
|
26
|
+
(identifier: string) => `User is in PENDING or INACTIVE status - return error indicating only ACTIVE users can receive role assignments: ${identifier}`,
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
export const InvalidPermissionKeyFormatError = createDomainError(
|
|
30
|
+
"InvalidPermissionKeyFormatError", "INVALID_PERMISSION_KEY_FORMAT",
|
|
31
|
+
(identifier: string) => `Key does not match resource:action pattern: ${identifier}`,
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
export const DuplicatePermissionKeyError = createDomainError(
|
|
35
|
+
"DuplicatePermissionKeyError", "DUPLICATE_PERMISSION_KEY",
|
|
36
|
+
(identifier: string) => `Permission with the same key already exists: ${identifier}`,
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
export const MissingRequiredFieldError = createDomainError(
|
|
40
|
+
"MissingRequiredFieldError", "MISSING_REQUIRED_FIELD",
|
|
41
|
+
(identifier: string) => `Role name not provided - return validation error indicating name is required: ${identifier}`,
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
export const DuplicateRoleNameError = createDomainError(
|
|
45
|
+
"DuplicateRoleNameError", "DUPLICATE_ROLE_NAME",
|
|
46
|
+
(identifier: string) => `Role with the same name already exists: ${identifier}`,
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
export const UserAlreadyExistsError = createDomainError(
|
|
50
|
+
"UserAlreadyExistsError", "USER_ALREADY_EXISTS",
|
|
51
|
+
(identifier: string) => `Email address is already registered in the system - return conflict error with message indicating email is taken: ${identifier}`,
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
export const InvalidEmailError = createDomainError(
|
|
55
|
+
"InvalidEmailError", "INVALID_EMAIL",
|
|
56
|
+
(identifier: string) => `Email does not follow valid email format - return validation error with format requirements: ${identifier}`,
|
|
57
|
+
);
|
|
58
|
+
|
|
59
|
+
export const InvalidEventTypeError = createDomainError(
|
|
60
|
+
"InvalidEventTypeError", "INVALID_EVENT_TYPE",
|
|
61
|
+
(identifier: string) => `Event type is not one of the recognized types - return validation error with list of valid event types: ${identifier}`,
|
|
62
|
+
);
|
|
63
|
+
|
|
64
|
+
export const AssignmentNotFoundError = createDomainError(
|
|
65
|
+
"AssignmentNotFoundError", "ASSIGNMENT_NOT_FOUND",
|
|
66
|
+
(identifier: string) => `Role does not have this permission assigned - return not found error indicating the association does not exist: ${identifier}`,
|
|
67
|
+
);
|
|
@@ -1,15 +1,16 @@
|
|
|
1
|
-
|
|
1
|
+
// @generated — do not edit
|
|
2
|
+
import { definePermissions } from "../../shared/internal";
|
|
2
3
|
|
|
3
4
|
export const { permissions, own, all } = definePermissions("user-management", [
|
|
4
|
-
"createUser",
|
|
5
5
|
"activateUser",
|
|
6
|
-
"
|
|
7
|
-
"
|
|
6
|
+
"assignPermissionToRole",
|
|
7
|
+
"assignRoleToUser",
|
|
8
8
|
"createPermission",
|
|
9
9
|
"createRole",
|
|
10
|
-
"
|
|
10
|
+
"createUser",
|
|
11
|
+
"deactivateUser",
|
|
12
|
+
"logAuditEvent",
|
|
13
|
+
"reactivateUser",
|
|
11
14
|
"revokePermissionFromRole",
|
|
12
|
-
"assignRoleToUser",
|
|
13
15
|
"revokeRoleFromUser",
|
|
14
|
-
"logAuditEvent",
|
|
15
16
|
] as const);
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import { type TailorAnyDBField } from "@tailor-platform/sdk";
|
|
2
2
|
import { type EmptyFields, type FieldsToInsertable } from "../shared/internal";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import { activateUser } from "./command/activateUser";
|
|
7
|
-
import { deactivateUser } from "./command/deactivateUser";
|
|
8
|
-
import { reactivateUser } from "./command/reactivateUser";
|
|
9
|
-
import { assignPermissionToRole } from "./command/assignPermissionToRole";
|
|
10
|
-
import { revokePermissionFromRole } from "./command/revokePermissionFromRole";
|
|
11
|
-
import { assignRoleToUser } from "./command/assignRoleToUser";
|
|
12
|
-
import { revokeRoleFromUser } from "./command/revokeRoleFromUser";
|
|
13
|
-
import { logAuditEvent } from "./command/logAuditEvent";
|
|
3
|
+
import { createUser } from "./command/createUser.generated";
|
|
4
|
+
import { createRole } from "./command/createRole.generated";
|
|
5
|
+
import { createPermission } from "./command/createPermission.generated";
|
|
6
|
+
import { activateUser } from "./command/activateUser.generated";
|
|
7
|
+
import { deactivateUser } from "./command/deactivateUser.generated";
|
|
8
|
+
import { reactivateUser } from "./command/reactivateUser.generated";
|
|
9
|
+
import { assignPermissionToRole } from "./command/assignPermissionToRole.generated";
|
|
10
|
+
import { revokePermissionFromRole } from "./command/revokePermissionFromRole.generated";
|
|
11
|
+
import { assignRoleToUser } from "./command/assignRoleToUser.generated";
|
|
12
|
+
import { revokeRoleFromUser } from "./command/revokeRoleFromUser.generated";
|
|
13
|
+
import { logAuditEvent } from "./command/logAuditEvent.generated";
|
|
14
14
|
import { createAuditEventType, CreateAuditEventTypeParams } from "./db/auditEvent";
|
|
15
15
|
import { createPermissionType, CreatePermissionTypeParams } from "./db/permission";
|
|
16
16
|
import { createRoleType, CreateRoleTypeParams } from "./db/role";
|
|
@@ -61,17 +61,17 @@ export const defineModule = <
|
|
|
61
61
|
db: { user, permission, role, userRole, rolePermission, auditEvent },
|
|
62
62
|
executors: { rolePermissionCreated, rolePermissionDeleted },
|
|
63
63
|
commands: {
|
|
64
|
-
createUser:
|
|
65
|
-
createRole:
|
|
66
|
-
createPermission:
|
|
67
|
-
activateUser,
|
|
68
|
-
deactivateUser,
|
|
69
|
-
reactivateUser,
|
|
70
|
-
assignPermissionToRole,
|
|
71
|
-
revokePermissionFromRole,
|
|
72
|
-
assignRoleToUser,
|
|
73
|
-
revokeRoleFromUser,
|
|
74
|
-
logAuditEvent,
|
|
64
|
+
createUser: createUser<FieldsToInsertable<UF>>(),
|
|
65
|
+
createRole: createRole<FieldsToInsertable<RF>>(),
|
|
66
|
+
createPermission: createPermission<FieldsToInsertable<PF>>(),
|
|
67
|
+
activateUser: activateUser(),
|
|
68
|
+
deactivateUser: deactivateUser(),
|
|
69
|
+
reactivateUser: reactivateUser(),
|
|
70
|
+
assignPermissionToRole: assignPermissionToRole(),
|
|
71
|
+
revokePermissionFromRole: revokePermissionFromRole(),
|
|
72
|
+
assignRoleToUser: assignRoleToUser(),
|
|
73
|
+
revokeRoleFromUser: revokeRoleFromUser(),
|
|
74
|
+
logAuditEvent: logAuditEvent(),
|
|
75
75
|
},
|
|
76
76
|
};
|
|
77
77
|
};
|
|
@@ -2,10 +2,10 @@ import { defineConfig, defineGenerators } from "@tailor-platform/sdk";
|
|
|
2
2
|
|
|
3
3
|
export default defineConfig({
|
|
4
4
|
name: "user-management",
|
|
5
|
-
db: { "main-db": { files: [`./
|
|
5
|
+
db: { "main-db": { files: [`./db/*.ts`] } },
|
|
6
6
|
});
|
|
7
7
|
|
|
8
8
|
export const generators = defineGenerators(
|
|
9
|
-
["@tailor-platform/kysely-type", { distPath: `./
|
|
10
|
-
["@tailor-platform/enum-constants", { distPath: "./
|
|
9
|
+
["@tailor-platform/kysely-type", { distPath: `./generated/kysely-tailordb.ts` }],
|
|
10
|
+
["@tailor-platform/enum-constants", { distPath: "./generated/enums.ts" }],
|
|
11
11
|
);
|
package/src/schemas.ts
CHANGED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
# Module Directory Structure
|
|
2
|
-
|
|
3
|
-
```
|
|
4
|
-
src/
|
|
5
|
-
├── db/ # Database models (one file per model)
|
|
6
|
-
├── executor/ # Async executors (record triggers, job functions)
|
|
7
|
-
├── command/ # Domain commands + tests (*.test.ts co-located)
|
|
8
|
-
├── lib/ # Internal shared code (errors.ts, types.ts)
|
|
9
|
-
├── testing/ # Test fixtures and helpers
|
|
10
|
-
├── generated/ # Auto-generated code (do not edit)
|
|
11
|
-
├── index.ts # Public exports
|
|
12
|
-
└── module.ts # Module definition
|
|
13
|
-
```
|
|
14
|
-
|
|
15
|
-
## Rules
|
|
16
|
-
|
|
17
|
-
- `db/`: Only documentable model definitions, no helpers
|
|
18
|
-
- `executor/`: Async executors as factory functions (see executors.md)
|
|
19
|
-
- `command/`: Domain commands + co-located tests, no utilities
|
|
20
|
-
- `lib/`: Internal errors and types (not documented)
|
|
21
|
-
- `testing/`: Fixtures for tests only
|
|
22
|
-
- Run `pnpm generate` after modifying `db/` models
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
# Command Implementation
|
|
2
|
-
|
|
3
|
-
## defineCommand Pattern
|
|
4
|
-
|
|
5
|
-
Commands that don't need custom fields use `defineCommand` directly:
|
|
6
|
-
|
|
7
|
-
```typescript
|
|
8
|
-
export const myCommand = defineCommand(permissions.myCommand, async (db: DB, input: Input) => { ... });
|
|
9
|
-
```
|
|
10
|
-
|
|
11
|
-
## Factory Function Pattern (custom fields)
|
|
12
|
-
|
|
13
|
-
Commands that insert into a table with user-extensible fields use a `makeCreateX<CF>()` factory:
|
|
14
|
-
|
|
15
|
-
- Export only `makeCreateX` — no default instance
|
|
16
|
-
- Generic `CF extends Record<string, unknown>` for custom fields
|
|
17
|
-
- Input type: `CreateXInput & CF`
|
|
18
|
-
- Destructure known fields, rest-spread custom fields into `.values()` before known fields
|
|
19
|
-
- Cast custom fields: `...(customFields as Record<string, unknown>)`
|
|
20
|
-
- `module.ts` wires with `makeCreateX<FieldsToInsertable<F>>()`
|
|
21
|
-
|
|
22
|
-
## Implementation Considerations
|
|
23
|
-
|
|
24
|
-
- **Validation**: Check referenced entities exist before operating
|
|
25
|
-
- **Idempotency**: For assign/revoke, return existing instead of throwing
|
|
26
|
-
- **Return format**: Wrap in object `{ entity }` not just `entity`
|
|
27
|
-
|
|
28
|
-
## Conventions
|
|
29
|
-
|
|
30
|
-
- Input types: exported interfaces (`export interface MyFunctionInput`)
|
|
31
|
-
- Use `.executeTakeFirst()` for single results
|
|
32
|
-
- Include JSDoc: `/** Function: name \n Description */`
|
|
33
|
-
|
|
34
|
-
## State Transitions
|
|
35
|
-
|
|
36
|
-
For commands that transition between statuses, accept `from?: string[]` with a default:
|
|
37
|
-
|
|
38
|
-
```typescript
|
|
39
|
-
from?: string[]; // Default: ["ACTIVE"]
|
|
40
|
-
|
|
41
|
-
const validFromStatuses = input.from ?? ["ACTIVE"];
|
|
42
|
-
if (!validFromStatuses.includes(user.status)) {
|
|
43
|
-
throw new InvalidStatusTransitionError(user.status, targetStatus);
|
|
44
|
-
}
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
- Default `from` contains the base valid source status
|
|
48
|
-
- Parent modules can override to allow transitions from additional statuses
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
# Module Directory Structure
|
|
2
|
-
|
|
3
|
-
```
|
|
4
|
-
src/
|
|
5
|
-
├── db/ # Database models (one file per model)
|
|
6
|
-
├── executor/ # Async executors (record triggers, job functions)
|
|
7
|
-
├── command/ # Domain commands + tests (*.test.ts co-located)
|
|
8
|
-
├── lib/ # Internal shared code (errors.ts, types.ts)
|
|
9
|
-
├── testing/ # Test fixtures and helpers
|
|
10
|
-
├── generated/ # Auto-generated code (do not edit)
|
|
11
|
-
├── index.ts # Public exports
|
|
12
|
-
└── module.ts # Module definition
|
|
13
|
-
```
|
|
14
|
-
|
|
15
|
-
## Rules
|
|
16
|
-
|
|
17
|
-
- `db/`: Only documentable model definitions, no helpers
|
|
18
|
-
- `executor/`: Async executors as factory functions (see executors.md)
|
|
19
|
-
- `command/`: Domain commands + co-located tests, no utilities
|
|
20
|
-
- `lib/`: Internal errors and types (not documented)
|
|
21
|
-
- `testing/`: Fixtures for tests only
|
|
22
|
-
- Run `pnpm generate` after modifying `db/` models
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
paths:
|
|
3
|
-
- "packages/erp-kit/src/modules/*/command/*.ts"
|
|
4
|
-
- "!packages/erp-kit/src/modules/*/command/*.test.ts"
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
# Command Implementation
|
|
8
|
-
|
|
9
|
-
## defineCommand Pattern
|
|
10
|
-
|
|
11
|
-
Commands that don't need custom fields use `defineCommand` directly:
|
|
12
|
-
|
|
13
|
-
```typescript
|
|
14
|
-
export const myCommand = defineCommand(permissions.myCommand, async (db: DB, input: Input) => { ... });
|
|
15
|
-
```
|
|
16
|
-
|
|
17
|
-
## Factory Function Pattern (custom fields)
|
|
18
|
-
|
|
19
|
-
Commands that insert into a table with user-extensible fields use a `makeCreateX<CF>()` factory:
|
|
20
|
-
|
|
21
|
-
- Export only `makeCreateX` — no default instance
|
|
22
|
-
- Generic `CF extends Record<string, unknown>` for custom fields
|
|
23
|
-
- Input type: `CreateXInput & CF`
|
|
24
|
-
- Destructure known fields, rest-spread custom fields into `.values()` before known fields
|
|
25
|
-
- Cast custom fields: `...(customFields as Record<string, unknown>)`
|
|
26
|
-
- `module.ts` wires with `makeCreateX<FieldsToInsertable<F>>()`
|
|
27
|
-
|
|
28
|
-
## Implementation Considerations
|
|
29
|
-
|
|
30
|
-
- **Validation**: Check referenced entities exist before operating
|
|
31
|
-
- **Idempotency**: For assign/revoke, return existing instead of throwing
|
|
32
|
-
- **Return format**: Wrap in object `{ entity }` not just `entity`
|
|
33
|
-
|
|
34
|
-
## Conventions
|
|
35
|
-
|
|
36
|
-
- Input types: exported interfaces (`export interface MyFunctionInput`)
|
|
37
|
-
- Use `.executeTakeFirst()` for single results
|
|
38
|
-
- Include JSDoc: `/** Function: name \n Description */`
|
|
39
|
-
|
|
40
|
-
## State Transitions
|
|
41
|
-
|
|
42
|
-
For commands that transition between statuses, accept `from?: string[]` with a default:
|
|
43
|
-
|
|
44
|
-
```typescript
|
|
45
|
-
from?: string[]; // Default: ["ACTIVE"]
|
|
46
|
-
|
|
47
|
-
const validFromStatuses = input.from ?? ["ACTIVE"];
|
|
48
|
-
if (!validFromStatuses.includes(user.status)) {
|
|
49
|
-
throw new InvalidStatusTransitionError(user.status, targetStatus);
|
|
50
|
-
}
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
- Default `from` contains the base valid source status
|
|
54
|
-
- Parent modules can override to allow transitions from additional statuses
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
# Database Models
|
|
2
|
-
|
|
3
|
-
## Factory Function Pattern
|
|
4
|
-
|
|
5
|
-
Each model is a `createXType<const F>(params)` factory:
|
|
6
|
-
|
|
7
|
-
- Params interface generic: `F extends Record<string, TailorAnyDBField>`
|
|
8
|
-
- `fields?: F` — optional custom fields from parent modules
|
|
9
|
-
- Spread as `...(params.fields ?? {}) as F` to preserve type information
|
|
10
|
-
- Include `...db.fields.timestamps()`
|
|
11
|
-
- Use `.description()` for field docs
|
|
12
|
-
- Apply permissions at model level
|
|
13
|
-
- Export a default instance: `export const x = createXType({})`
|
|
14
|
-
|
|
15
|
-
## Stateful Model Enums
|
|
16
|
-
|
|
17
|
-
Status enums are tied to the module's state machine. Base module defines core statuses; parent callers can only **extend, not replace**.
|
|
18
|
-
|
|
19
|
-
```typescript
|
|
20
|
-
// Good: extension only
|
|
21
|
-
const BASE_STATUSES = ["PENDING", "ACTIVE", "INACTIVE"] as const;
|
|
22
|
-
const statuses = [...BASE_STATUSES, ...(params.additionalStatuses ?? [])];
|
|
23
|
-
|
|
24
|
-
// Bad: allows replacement
|
|
25
|
-
const statuses = params.statuses ?? ["PENDING", "ACTIVE", "INACTIVE"];
|
|
26
|
-
```
|
|
27
|
-
|
|
28
|
-
- Name parameter `additionalX` to signal extension-only
|
|
29
|
-
- Parent modules handle their additional status transitions
|
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: 4-module-tdd-implementation
|
|
3
|
-
description: Use when implementing features in any module under modules/. Triggers on TDD workflow, domain command implementation, adding new database models, creating test fixtures, or implementing business logic commands.
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# TDD Implementation for Module Development
|
|
7
|
-
|
|
8
|
-
Guide for implementing features in modules using Test-Driven Development.
|
|
9
|
-
|
|
10
|
-
## When to Use
|
|
11
|
-
|
|
12
|
-
- Implementing new domain commands in any module
|
|
13
|
-
- Adding database models with `@tailor-platform/sdk`
|
|
14
|
-
- Creating tests with `@tailor-platform/erp-kit` testing utilities
|
|
15
|
-
- Implementing business logic (CRUD, state transitions, relationships)
|
|
16
|
-
|
|
17
|
-
## Workflow
|
|
18
|
-
|
|
19
|
-
```
|
|
20
|
-
MODELS → ERRORS → FIXTURES → TESTS → IMPLEMENT → EXPORT → VERIFY
|
|
21
|
-
```
|
|
22
|
-
|
|
23
|
-
## Step-by-Step
|
|
24
|
-
|
|
25
|
-
### 1. Database Models (`src/db/`)
|
|
26
|
-
|
|
27
|
-
**Read [models rules](references/models.md) and [db-relations rules](references/db-relations.md) before writing any model.**
|
|
28
|
-
|
|
29
|
-
Key patterns: factory function, `db.fields.timestamps()`, `.description()` on fields, `.relation()` for foreign keys.
|
|
30
|
-
|
|
31
|
-
### 2. Error Classes (`src/lib/errors.ts`)
|
|
32
|
-
|
|
33
|
-
**Read [errors rules](references/errors.md) before defining errors.**
|
|
34
|
-
|
|
35
|
-
Key patterns: `name` as const = class name, `code` as const = SCREAMING_SNAKE_CASE.
|
|
36
|
-
|
|
37
|
-
### 3. Test Fixtures (`src/testing/fixtures.ts`)
|
|
38
|
-
|
|
39
|
-
**Read [testing rules](references/testing.md) before writing fixtures or tests.**
|
|
40
|
-
|
|
41
|
-
### 4. Write Tests First (`src/command/*.test.ts`)
|
|
42
|
-
|
|
43
|
-
Same reference: [testing rules](references/testing.md).
|
|
44
|
-
|
|
45
|
-
Key patterns: `createMockDb<DB>()`, fixed IDs `"entity-1"`, cover all doc branches.
|
|
46
|
-
|
|
47
|
-
### 5. Implement Commands (`src/command/*.ts`)
|
|
48
|
-
|
|
49
|
-
**Read [commands rules](references/commands.md) before implementing.**
|
|
50
|
-
|
|
51
|
-
Key patterns: dual function (`_fn` internal + `fn<T>` public), validate → query → mutate.
|
|
52
|
-
|
|
53
|
-
### 6. Export (`src/index.ts`)
|
|
54
|
-
|
|
55
|
-
**Read [exports rules](references/exports.md) for export order.**
|
|
56
|
-
|
|
57
|
-
### 7. Verify
|
|
58
|
-
|
|
59
|
-
```bash
|
|
60
|
-
pnpm generate # Regenerate types if models changed
|
|
61
|
-
pnpm lint # Check code style
|
|
62
|
-
pnpm typecheck # Verify TypeScript types
|
|
63
|
-
pnpm test # Run all tests
|
|
64
|
-
```
|
|
65
|
-
|
|
66
|
-
## References
|
|
67
|
-
|
|
68
|
-
- [Module structure](references/structure.md)
|
|
69
|
-
- [Model patterns](references/models.md)
|
|
70
|
-
- [Database relations](references/db-relations.md)
|
|
71
|
-
- [Command patterns](references/commands.md)
|
|
72
|
-
- [Error patterns](references/errors.md)
|
|
73
|
-
- [Testing patterns](references/testing.md)
|
|
74
|
-
- [Export order](references/exports.md)
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
# Command Implementation
|
|
2
|
-
|
|
3
|
-
## Dual Function Pattern
|
|
4
|
-
|
|
5
|
-
Two functions per operation: internal `_fn` and public `fn`.
|
|
6
|
-
|
|
7
|
-
**Internal function (`_myFunction`):**
|
|
8
|
-
|
|
9
|
-
- Takes concrete `DB` type from `generated/kysely-tailordb`
|
|
10
|
-
- Return type uses `Schema` from `lib/types`: `Promise<{ entity: Entity<Schema> }>`
|
|
11
|
-
- Contains actual implementation
|
|
12
|
-
|
|
13
|
-
**Public function (`myFunction`):**
|
|
14
|
-
|
|
15
|
-
- Generic signature: `<T extends { Entity: object }>(db: Kysely<T>, ...)`
|
|
16
|
-
- Return type uses generic `T`: `Promise<{ entity: Entity<T> }>`
|
|
17
|
-
- Delegates to internal with type casting: `_fn(db as unknown as DB, ...) as unknown as Result`
|
|
18
|
-
|
|
19
|
-
## Implementation Considerations
|
|
20
|
-
|
|
21
|
-
- **Validation**: Check referenced entities exist before operating
|
|
22
|
-
- **Idempotency**: For assign/revoke, return existing instead of throwing
|
|
23
|
-
- **Return format**: Wrap in object `{ entity }` not just `entity`
|
|
24
|
-
|
|
25
|
-
## Conventions
|
|
26
|
-
|
|
27
|
-
- Input types: exported interfaces (`export interface MyFunctionInput`)
|
|
28
|
-
- Use `.executeTakeFirst()` for single results
|
|
29
|
-
- Include JSDoc: `/** Function: name \n Description */`
|
|
30
|
-
|
|
31
|
-
## State Transitions
|
|
32
|
-
|
|
33
|
-
For commands that transition between statuses, accept `from?: string[]` with a default:
|
|
34
|
-
|
|
35
|
-
```typescript
|
|
36
|
-
from?: string[]; // Default: ["ACTIVE"]
|
|
37
|
-
|
|
38
|
-
const validFromStatuses = input.from ?? ["ACTIVE"];
|
|
39
|
-
if (!validFromStatuses.includes(user.status)) {
|
|
40
|
-
throw new InvalidStatusTransitionError(user.status, targetStatus);
|
|
41
|
-
}
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
- Default `from` contains the base valid source status
|
|
45
|
-
- Parent modules can override to allow transitions from additional statuses
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
# Database Models
|
|
2
|
-
|
|
3
|
-
## Factory Function Pattern
|
|
4
|
-
|
|
5
|
-
```typescript
|
|
6
|
-
export function createEntityType(params: {
|
|
7
|
-
fields?: Record<string, unknown>;
|
|
8
|
-
additionalStatuses?: string[];
|
|
9
|
-
});
|
|
10
|
-
```
|
|
11
|
-
|
|
12
|
-
- Include `...db.fields.timestamps()`
|
|
13
|
-
- Use `.description()` for field docs
|
|
14
|
-
- Apply permissions at model level
|
|
15
|
-
|
|
16
|
-
## Stateful Model Enums
|
|
17
|
-
|
|
18
|
-
Status enums are tied to the module's state machine. Base module defines core statuses; parent callers can only **extend, not replace**.
|
|
19
|
-
|
|
20
|
-
```typescript
|
|
21
|
-
// Good: extension only
|
|
22
|
-
const BASE_STATUSES = ["PENDING", "ACTIVE", "INACTIVE"] as const;
|
|
23
|
-
const statuses = [...BASE_STATUSES, ...(params.additionalStatuses ?? [])];
|
|
24
|
-
|
|
25
|
-
// Bad: allows replacement
|
|
26
|
-
const statuses = params.statuses ?? ["PENDING", "ACTIVE", "INACTIVE"];
|
|
27
|
-
```
|
|
28
|
-
|
|
29
|
-
- Name parameter `additionalX` to signal extension-only
|
|
30
|
-
- Parent modules handle their additional status transitions
|