@tailor-platform/erp-kit 0.1.0 → 0.1.2

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.
Files changed (102) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/LICENSE +21 -0
  3. package/README.md +77 -50
  4. package/dist/cli.js +693 -553
  5. package/package.json +4 -2
  6. package/schemas/module/command.yml +1 -0
  7. package/schemas/module/model.yml +9 -0
  8. package/schemas/module/query.yml +53 -0
  9. package/skills/1-module-docs/SKILL.md +4 -0
  10. package/{rules/module-development → skills/1-module-docs/references}/structure.md +2 -7
  11. package/skills/2-module-feature-breakdown/SKILL.md +6 -0
  12. package/{rules/module-development → skills/2-module-feature-breakdown/references}/commands.md +0 -6
  13. package/{rules/module-development → skills/2-module-feature-breakdown/references}/models.md +0 -5
  14. package/skills/2-module-feature-breakdown/references/structure.md +22 -0
  15. package/skills/3-module-doc-review/SKILL.md +6 -0
  16. package/skills/3-module-doc-review/references/commands.md +54 -0
  17. package/skills/3-module-doc-review/references/models.md +29 -0
  18. package/{rules/module-development → skills/3-module-doc-review/references}/testing.md +0 -6
  19. package/skills/4-module-tdd-implementation/SKILL.md +24 -6
  20. package/skills/4-module-tdd-implementation/references/commands.md +45 -0
  21. package/{rules/sdk-best-practices → skills/4-module-tdd-implementation/references}/db-relations.md +0 -5
  22. package/{rules/module-development → skills/4-module-tdd-implementation/references}/errors.md +0 -5
  23. package/{rules/module-development → skills/4-module-tdd-implementation/references}/exports.md +0 -5
  24. package/skills/4-module-tdd-implementation/references/models.md +30 -0
  25. package/skills/4-module-tdd-implementation/references/structure.md +22 -0
  26. package/skills/4-module-tdd-implementation/references/testing.md +37 -0
  27. package/skills/5-module-implementation-review/SKILL.md +8 -0
  28. package/skills/5-module-implementation-review/references/commands.md +45 -0
  29. package/skills/5-module-implementation-review/references/errors.md +7 -0
  30. package/skills/5-module-implementation-review/references/exports.md +8 -0
  31. package/skills/5-module-implementation-review/references/models.md +30 -0
  32. package/skills/5-module-implementation-review/references/testing.md +29 -0
  33. package/skills/app-compose-1-requirement-analysis/SKILL.md +4 -0
  34. package/{rules/app-compose → skills/app-compose-1-requirement-analysis/references}/structure.md +0 -5
  35. package/skills/app-compose-2-requirements-breakdown/SKILL.md +7 -0
  36. package/{rules/app-compose/frontend → skills/app-compose-2-requirements-breakdown/references}/screen-detailview.md +0 -6
  37. package/{rules/app-compose/frontend → skills/app-compose-2-requirements-breakdown/references}/screen-form.md +0 -6
  38. package/{rules/app-compose/frontend → skills/app-compose-2-requirements-breakdown/references}/screen-listview.md +0 -6
  39. package/skills/app-compose-2-requirements-breakdown/references/structure.md +27 -0
  40. package/skills/app-compose-3-doc-review/SKILL.md +4 -0
  41. package/skills/app-compose-3-doc-review/references/structure.md +27 -0
  42. package/skills/app-compose-4-design-mock/SKILL.md +8 -0
  43. package/{rules/app-compose/frontend → skills/app-compose-4-design-mock/references}/component.md +0 -5
  44. package/skills/app-compose-4-design-mock/references/screen-detailview.md +106 -0
  45. package/skills/app-compose-4-design-mock/references/screen-form.md +139 -0
  46. package/skills/app-compose-4-design-mock/references/screen-listview.md +153 -0
  47. package/skills/app-compose-4-design-mock/references/structure.md +27 -0
  48. package/skills/app-compose-5-design-mock-review/SKILL.md +7 -0
  49. package/skills/app-compose-5-design-mock-review/references/component.md +50 -0
  50. package/skills/app-compose-5-design-mock-review/references/screen-detailview.md +106 -0
  51. package/skills/app-compose-5-design-mock-review/references/screen-form.md +139 -0
  52. package/skills/app-compose-5-design-mock-review/references/screen-listview.md +153 -0
  53. package/skills/app-compose-6-implementation-spec/SKILL.md +5 -0
  54. package/{rules/app-compose/backend → skills/app-compose-6-implementation-spec/references}/auth.md +0 -6
  55. package/skills/app-compose-6-implementation-spec/references/structure.md +27 -0
  56. package/src/cli.ts +8 -90
  57. package/src/commands/app/index.ts +74 -0
  58. package/src/commands/check.test.ts +2 -1
  59. package/src/commands/check.ts +1 -0
  60. package/src/commands/init.test.ts +30 -19
  61. package/src/commands/init.ts +76 -43
  62. package/src/commands/module/index.ts +85 -0
  63. package/src/commands/module/list.test.ts +62 -0
  64. package/src/commands/module/list.ts +64 -0
  65. package/src/commands/scaffold.test.ts +5 -0
  66. package/src/commands/scaffold.ts +2 -1
  67. package/src/commands/sync-check.test.ts +28 -0
  68. package/src/commands/sync-check.ts +6 -0
  69. package/src/integration.test.ts +6 -8
  70. package/src/module.ts +4 -3
  71. package/src/modules/primitives/docs/models/Currency.md +4 -0
  72. package/src/modules/primitives/docs/models/ExchangeRate.md +4 -1
  73. package/src/modules/primitives/docs/models/Unit.md +4 -1
  74. package/src/modules/primitives/docs/models/UoMCategory.md +2 -0
  75. package/src/modules/primitives/index.ts +2 -2
  76. package/src/modules/primitives/module.ts +5 -3
  77. package/src/modules/primitives/permissions.ts +0 -2
  78. package/src/modules/primitives/{command → query}/convertAmount.test.ts +2 -19
  79. package/src/modules/primitives/query/convertAmount.ts +122 -0
  80. package/src/modules/primitives/{command → query}/convertQuantity.test.ts +2 -13
  81. package/src/modules/primitives/{command → query}/convertQuantity.ts +4 -6
  82. package/src/modules/shared/defineQuery.test.ts +28 -0
  83. package/src/modules/shared/defineQuery.ts +16 -0
  84. package/src/modules/shared/internal.ts +2 -1
  85. package/src/modules/shared/types.ts +8 -0
  86. package/src/modules/user-management/docs/models/AuditEvent.md +2 -0
  87. package/src/modules/user-management/docs/models/Permission.md +2 -0
  88. package/src/modules/user-management/docs/models/Role.md +2 -0
  89. package/src/modules/user-management/docs/models/RolePermission.md +2 -0
  90. package/src/modules/user-management/docs/models/User.md +2 -0
  91. package/src/modules/user-management/docs/models/UserRole.md +2 -0
  92. package/src/schemas.ts +1 -0
  93. package/rules/app-compose/frontend/auth.md +0 -55
  94. package/rules/app-compose/frontend/page.md +0 -86
  95. package/rules/module-development/cross-module-type-injection.md +0 -28
  96. package/rules/module-development/dependency-modules.md +0 -24
  97. package/rules/module-development/executors.md +0 -67
  98. package/rules/module-development/sync-vs-async-operations.md +0 -83
  99. package/rules/sdk-best-practices/sdk-docs.md +0 -14
  100. package/src/modules/primitives/command/convertAmount.ts +0 -126
  101. /package/src/modules/primitives/docs/{commands → queries}/ConvertAmount.md +0 -0
  102. /package/src/modules/primitives/docs/{commands → queries}/ConvertQuantity.md +0 -0
@@ -1,83 +0,0 @@
1
- ---
2
- paths:
3
- - "modules/*/src/"
4
- ---
5
-
6
- # Sync vs Async Operations
7
-
8
- ## Decision Criteria
9
-
10
- Choose synchronous or asynchronous execution based on:
11
-
12
- 1. **Number of affected records** - How many records need processing?
13
- 2. **Data growth trajectory** - Will the operation slow down as data grows?
14
-
15
- | Scenario | Approach | Implementation |
16
- | ----------------------------------- | ------------------ | --------------------------- |
17
- | Single record, bounded complexity | **Synchronous** | Inline in command |
18
- | Single record, unbounded complexity | **Consider async** | Evaluate growth |
19
- | Multiple records | **Asynchronous** | Executor with `jobFunction` |
20
-
21
- ## Growth Considerations
22
-
23
- Ask: "How does this operation scale as the system grows?"
24
-
25
- - **Bounded**: User status update (always 1 record, O(1))
26
- - **Bounded**: Single user permission recompute (limited by reasonable role/permission counts)
27
- - **Unbounded**: All users with role X (grows with user base, O(n))
28
- - **Unbounded**: All orders in date range (grows with transaction volume)
29
-
30
- When in doubt, monitor operation timing in production and migrate to async if latency increases.
31
-
32
- ## Rationale
33
-
34
- - **Synchronous**: Acceptable when operation time is predictable and bounded
35
- - **Asynchronous**: Required when operation time scales with data volume
36
-
37
- ## Pattern: Synchronous (Single Record)
38
-
39
- Commands that affect a single known record should execute the operation inline and return the result:
40
-
41
- ```typescript
42
- // In command - recompute immediately
43
- const updatedUser = await recomputeUserPermissions(db, input.userId);
44
- return { userRole, user: updatedUser, auditEvent };
45
- ```
46
-
47
- ## Pattern: Asynchronous (Multiple Records)
48
-
49
- Commands that affect an unknown number of records should delegate to an executor:
50
-
51
- ```typescript
52
- // Command just creates/deletes the record
53
- // Executor handles recomputation asynchronously
54
- ```
55
-
56
- Create executors with record triggers:
57
-
58
- - `recordCreatedTrigger` - React to inserts
59
- - `recordDeletedTrigger` - React to deletes
60
- - Use `kind: "jobFunction"` for extended execution
61
-
62
- ## Example: Permission Recomputation
63
-
64
- | Command | Affected | Approach |
65
- | ------------------------ | ----------------------- | --------------- |
66
- | assignRoleToUser | 1 user | Sync in command |
67
- | revokeRoleFromUser | 1 user | Sync in command |
68
- | assignPermissionToRole | N users (all with role) | Async executor |
69
- | revokePermissionFromRole | N users (all with role) | Async executor |
70
-
71
- ## Trade-offs
72
-
73
- **Synchronous:**
74
-
75
- - Immediate consistency
76
- - Simpler error handling
77
- - Blocks request until complete
78
-
79
- **Asynchronous:**
80
-
81
- - Eventual consistency
82
- - Non-blocking requests
83
- - Requires executor infrastructure
@@ -1,14 +0,0 @@
1
- ---
2
- paths:
3
- - "modules/*/src/db/*.ts"
4
- - "modules/*/src/executor/*.ts"
5
- - "modules/*/src/workflow/*.ts"
6
- ---
7
-
8
- # SDK Docs Reference
9
-
10
- Read the official Tailor SDK documentation for database models, executors:
11
-
12
- - [TailorDB Models](https://raw.githubusercontent.com/tailor-platform/sdk/refs/heads/main/packages/sdk/docs/services/tailordb.md)
13
- - [Executors](https://raw.githubusercontent.com/tailor-platform/sdk/refs/heads/main/packages/sdk/docs/services/executors.md)
14
- - [Workflow](https://raw.githubusercontent.com/tailor-platform/sdk/refs/heads/main/packages/sdk/docs/services/workflow.md)
@@ -1,126 +0,0 @@
1
- import { defineCommand } from "../../shared/internal";
2
- import { DB } from "../generated/kysely-tailordb";
3
- import {
4
- CurrencyNotFoundError,
5
- ExchangeRateNotFoundError,
6
- InactiveCurrencyError,
7
- } from "../lib/errors";
8
- import { permissions } from "../permissions";
9
-
10
- export interface ConvertAmountInput {
11
- amount: number;
12
- sourceCurrencyCode: string;
13
- targetCurrencyCode: string;
14
- conversionDate: string;
15
- }
16
-
17
- /**
18
- * Function: convertAmount
19
- *
20
- * Converts a monetary amount from one currency to another using the applicable
21
- * exchange rate for a given date. Currencies are identified by their ISO 4217
22
- * code (e.g., "USD", "EUR", "JPY"). The function looks up the most recent exchange
23
- * rate on or before the specified date. If no direct rate exists, it calculates
24
- * the inverse rate. Result is rounded to the target currency's decimal precision.
25
- */
26
- export const convertAmount = defineCommand(
27
- permissions.convertAmount,
28
- async (db: DB, input: ConvertAmountInput) => {
29
- // 1. Validate source currency exists
30
- const sourceCurrency = await db
31
- .selectFrom("Currency")
32
- .selectAll()
33
- .where("code", "=", input.sourceCurrencyCode)
34
- .executeTakeFirst();
35
-
36
- if (!sourceCurrency) {
37
- throw new CurrencyNotFoundError(input.sourceCurrencyCode);
38
- }
39
-
40
- // 2. Validate target currency exists
41
- const targetCurrency = await db
42
- .selectFrom("Currency")
43
- .selectAll()
44
- .where("code", "=", input.targetCurrencyCode)
45
- .executeTakeFirst();
46
-
47
- if (!targetCurrency) {
48
- throw new CurrencyNotFoundError(input.targetCurrencyCode);
49
- }
50
-
51
- // 3. Validate both currencies are active
52
- if (!sourceCurrency.isActive) {
53
- throw new InactiveCurrencyError(input.sourceCurrencyCode);
54
- }
55
-
56
- if (!targetCurrency.isActive) {
57
- throw new InactiveCurrencyError(input.targetCurrencyCode);
58
- }
59
-
60
- // 4. Same currency - return original amount
61
- if (sourceCurrency.id === targetCurrency.id) {
62
- return {
63
- convertedAmount: input.amount,
64
- exchangeRate: 1,
65
- sourceCurrency,
66
- targetCurrency,
67
- exchangeRateRecord: null,
68
- };
69
- }
70
-
71
- // 5. Find direct exchange rate (most recent on or before conversion date)
72
- const conversionDate = new Date(input.conversionDate);
73
- const directRate = await db
74
- .selectFrom("ExchangeRate")
75
- .selectAll()
76
- .where("sourceCurrencyId", "=", sourceCurrency.id)
77
- .where("targetCurrencyId", "=", targetCurrency.id)
78
- .where("effectiveDate", "<=", conversionDate)
79
- .orderBy("effectiveDate", "desc")
80
- .executeTakeFirst();
81
-
82
- let exchangeRate: number;
83
- let exchangeRateRecord = null;
84
-
85
- if (directRate) {
86
- exchangeRate = directRate.rate;
87
- exchangeRateRecord = directRate;
88
- } else {
89
- // 6. Try inverse rate
90
- const inverseRate = await db
91
- .selectFrom("ExchangeRate")
92
- .selectAll()
93
- .where("sourceCurrencyId", "=", targetCurrency.id)
94
- .where("targetCurrencyId", "=", sourceCurrency.id)
95
- .where("effectiveDate", "<=", conversionDate)
96
- .orderBy("effectiveDate", "desc")
97
- .executeTakeFirst();
98
-
99
- if (!inverseRate) {
100
- throw new ExchangeRateNotFoundError(
101
- input.sourceCurrencyCode,
102
- input.targetCurrencyCode,
103
- input.conversionDate,
104
- );
105
- }
106
-
107
- exchangeRate = 1 / inverseRate.rate;
108
- exchangeRateRecord = inverseRate;
109
- }
110
-
111
- // 7. Calculate converted amount
112
- const rawResult = input.amount * exchangeRate;
113
-
114
- // 8. Round to target currency's decimal places
115
- const roundingFactor = Math.pow(10, targetCurrency.decimalPlaces);
116
- const convertedAmount = Math.round(rawResult * roundingFactor) / roundingFactor;
117
-
118
- return {
119
- convertedAmount,
120
- exchangeRate,
121
- sourceCurrency,
122
- targetCurrency,
123
- exchangeRateRecord,
124
- };
125
- },
126
- );