@tailor-platform/create-sdk 1.19.0 → 1.21.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.
Files changed (149) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/dist/index.js +7 -2
  3. package/package.json +1 -1
  4. package/templates/executor/README.md +32 -0
  5. package/templates/{testing → executor}/eslint.config.js +0 -5
  6. package/templates/executor/package.json +30 -0
  7. package/templates/executor/src/db/auditLog.ts +24 -0
  8. package/templates/executor/src/db/notification.ts +27 -0
  9. package/templates/executor/src/db/user.ts +22 -0
  10. package/templates/executor/src/executor/dailyCleanup.ts +16 -0
  11. package/templates/executor/src/executor/externalWebhook.ts +18 -0
  12. package/templates/executor/src/executor/onDataProcessed.ts +26 -0
  13. package/templates/executor/src/executor/onIdpUserCreated.ts +19 -0
  14. package/templates/executor/src/executor/onIdpUserDeleted.ts +19 -0
  15. package/templates/executor/src/executor/onIdpUserUpdated.ts +19 -0
  16. package/templates/executor/src/executor/onTokenIssued.ts +19 -0
  17. package/templates/executor/src/executor/onTokenRefreshed.ts +19 -0
  18. package/templates/executor/src/executor/onTokenRevoked.ts +19 -0
  19. package/templates/executor/src/executor/onUserCreated.ts +23 -0
  20. package/templates/executor/src/executor/onUserDeleted.ts +22 -0
  21. package/templates/executor/src/executor/onUserUpdated.ts +22 -0
  22. package/templates/executor/src/executor/shared.test.ts +36 -0
  23. package/templates/executor/src/executor/shared.ts +13 -0
  24. package/templates/executor/src/generated/db.ts +59 -0
  25. package/templates/executor/src/resolver/processData.ts +22 -0
  26. package/templates/executor/src/workflow/cleanup.ts +13 -0
  27. package/templates/executor/tailor.config.ts +40 -0
  28. package/templates/executor/vitest.config.ts +15 -0
  29. package/templates/generators/.oxfmtrc.json +3 -0
  30. package/templates/generators/.oxlintrc.json +197 -0
  31. package/templates/generators/.prettierignore +1 -0
  32. package/templates/generators/.prettierrc +1 -0
  33. package/templates/generators/README.md +30 -0
  34. package/templates/generators/__dot__gitignore +3 -0
  35. package/templates/generators/eslint.config.js +24 -0
  36. package/templates/generators/package.json +30 -0
  37. package/templates/generators/src/db/category.ts +25 -0
  38. package/templates/generators/src/db/order.ts +38 -0
  39. package/templates/generators/src/db/product.ts +34 -0
  40. package/templates/generators/src/db/user.ts +26 -0
  41. package/templates/generators/src/generated/db.ts +68 -0
  42. package/templates/generators/src/generated/enums.ts +39 -0
  43. package/templates/generators/src/generated/files.ts +51 -0
  44. package/templates/generators/src/resolver/getProduct.test.ts +92 -0
  45. package/templates/generators/src/resolver/getProduct.ts +53 -0
  46. package/templates/generators/src/seed/data/Category.jsonl +0 -0
  47. package/templates/generators/src/seed/data/Category.schema.ts +23 -0
  48. package/templates/generators/src/seed/data/Order.jsonl +0 -0
  49. package/templates/generators/src/seed/data/Order.schema.ts +21 -0
  50. package/templates/generators/src/seed/data/Product.jsonl +0 -0
  51. package/templates/generators/src/seed/data/Product.schema.ts +23 -0
  52. package/templates/generators/src/seed/data/User.jsonl +0 -0
  53. package/templates/generators/src/seed/data/User.schema.ts +20 -0
  54. package/templates/generators/src/seed/exec.mjs +419 -0
  55. package/templates/generators/tailor.config.ts +36 -0
  56. package/templates/generators/tsconfig.json +16 -0
  57. package/templates/generators/vitest.config.ts +15 -0
  58. package/templates/hello-world/package.json +1 -1
  59. package/templates/inventory-management/package.json +1 -1
  60. package/templates/inventory-management/user-defined.d.ts +15 -0
  61. package/templates/multi-application/package.json +1 -1
  62. package/templates/resolver/.oxfmtrc.json +3 -0
  63. package/templates/resolver/.oxlintrc.json +197 -0
  64. package/templates/resolver/.prettierrc +1 -0
  65. package/templates/resolver/README.md +31 -0
  66. package/templates/resolver/__dot__gitignore +3 -0
  67. package/templates/resolver/eslint.config.js +24 -0
  68. package/templates/resolver/package.json +30 -0
  69. package/templates/resolver/src/resolver/add.test.ts +23 -0
  70. package/templates/{testing/src/resolver/mockTailordb.test.ts → resolver/src/resolver/queryUser.test.ts} +5 -6
  71. package/templates/{testing/src/resolver/mockTailordb.ts → resolver/src/resolver/queryUser.ts} +0 -5
  72. package/templates/resolver/src/resolver/showEnv.test.ts +14 -0
  73. package/templates/resolver/src/resolver/showEnv.ts +19 -0
  74. package/templates/resolver/src/resolver/showUserInfo.test.ts +37 -0
  75. package/templates/resolver/src/resolver/showUserInfo.ts +21 -0
  76. package/templates/{testing/src/resolver/wrapTailordb.test.ts → resolver/src/resolver/updateUser.test.ts} +3 -5
  77. package/templates/{testing/src/resolver/wrapTailordb.ts → resolver/src/resolver/updateUser.ts} +0 -5
  78. package/templates/resolver/tailor.config.ts +26 -0
  79. package/templates/resolver/tsconfig.json +16 -0
  80. package/templates/resolver/user-defined.d.ts +18 -0
  81. package/templates/resolver/vitest.config.ts +15 -0
  82. package/templates/static-web-site/.oxfmtrc.json +3 -0
  83. package/templates/static-web-site/.oxlintrc.json +197 -0
  84. package/templates/static-web-site/.prettierrc +1 -0
  85. package/templates/static-web-site/README.md +21 -0
  86. package/templates/static-web-site/__dot__gitignore +3 -0
  87. package/templates/static-web-site/eslint.config.js +24 -0
  88. package/templates/static-web-site/package.json +27 -0
  89. package/templates/static-web-site/public/callback.html +34 -0
  90. package/templates/static-web-site/public/index.html +55 -0
  91. package/templates/static-web-site/public/style.css +62 -0
  92. package/templates/static-web-site/src/db/user.ts +22 -0
  93. package/templates/static-web-site/tailor.config.ts +55 -0
  94. package/templates/static-web-site/tsconfig.json +16 -0
  95. package/templates/tailordb/.oxfmtrc.json +3 -0
  96. package/templates/tailordb/.oxlintrc.json +197 -0
  97. package/templates/tailordb/.prettierrc +1 -0
  98. package/templates/tailordb/README.md +29 -0
  99. package/templates/tailordb/__dot__gitignore +3 -0
  100. package/templates/tailordb/eslint.config.js +24 -0
  101. package/templates/tailordb/package.json +30 -0
  102. package/templates/tailordb/src/db/category.ts +15 -0
  103. package/templates/tailordb/src/db/comment.ts +26 -0
  104. package/templates/tailordb/src/db/permission.ts +43 -0
  105. package/templates/tailordb/src/db/task.test.ts +41 -0
  106. package/templates/tailordb/src/db/task.ts +58 -0
  107. package/templates/tailordb/src/db/user.ts +19 -0
  108. package/templates/tailordb/src/generated/db.ts +75 -0
  109. package/templates/tailordb/tailor.config.ts +26 -0
  110. package/templates/tailordb/tsconfig.json +16 -0
  111. package/templates/tailordb/user-defined.d.ts +15 -0
  112. package/templates/tailordb/vitest.config.ts +15 -0
  113. package/templates/workflow/.oxfmtrc.json +3 -0
  114. package/templates/workflow/.oxlintrc.json +197 -0
  115. package/templates/workflow/.prettierrc +1 -0
  116. package/templates/workflow/README.md +25 -0
  117. package/templates/workflow/__dot__gitignore +3 -0
  118. package/templates/{testing → workflow}/e2e/globalSetup.ts +5 -5
  119. package/templates/workflow/e2e/resolver.test.ts +90 -0
  120. package/templates/workflow/e2e/workflow.test.ts +31 -0
  121. package/templates/workflow/eslint.config.js +24 -0
  122. package/templates/{testing → workflow}/package.json +3 -2
  123. package/templates/workflow/src/db/order.ts +22 -0
  124. package/templates/workflow/src/db/user.ts +22 -0
  125. package/templates/workflow/src/generated/db.ts +48 -0
  126. package/templates/workflow/src/resolver/incrementAge.ts +40 -0
  127. package/templates/workflow/src/workflow/order-fulfillment.test.ts +148 -0
  128. package/templates/workflow/src/workflow/order-fulfillment.ts +69 -0
  129. package/templates/{testing/src/workflow/wrapTailordb.test.ts → workflow/src/workflow/sync-profile.test.ts} +1 -1
  130. package/templates/{testing → workflow}/tailor.config.ts +1 -1
  131. package/templates/workflow/tsconfig.json +16 -0
  132. package/templates/workflow/user-defined.d.ts +15 -0
  133. package/templates/testing/README.md +0 -130
  134. package/templates/testing/e2e/resolver.test.ts +0 -57
  135. package/templates/testing/e2e/workflow.test.ts +0 -47
  136. package/templates/testing/src/resolver/simple.test.ts +0 -14
  137. package/templates/testing/src/workflow/simple.test.ts +0 -88
  138. package/templates/testing/src/workflow/simple.ts +0 -36
  139. package/templates/testing/src/workflow/trigger.test.ts +0 -104
  140. /package/templates/{testing → executor}/.oxfmtrc.json +0 -0
  141. /package/templates/{testing → executor}/.oxlintrc.json +0 -0
  142. /package/templates/{testing → executor}/.prettierrc +0 -0
  143. /package/templates/{testing → executor}/__dot__gitignore +0 -0
  144. /package/templates/{testing → executor}/tsconfig.json +0 -0
  145. /package/templates/{testing → resolver}/src/db/user.ts +0 -0
  146. /package/templates/{testing → resolver}/src/generated/db.ts +0 -0
  147. /package/templates/{testing/src/resolver/simple.ts → resolver/src/resolver/add.ts} +0 -0
  148. /package/templates/{testing/src/workflow/wrapTailordb.ts → workflow/src/workflow/sync-profile.ts} +0 -0
  149. /package/templates/{testing → workflow}/vitest.config.ts +0 -0
@@ -0,0 +1,197 @@
1
+ {
2
+ "$schema": "./node_modules/oxlint/configuration_schema.json",
3
+ "plugins": ["typescript"],
4
+ "categories": {
5
+ "correctness": "off"
6
+ },
7
+ "env": {
8
+ "builtin": true
9
+ },
10
+ "ignorePatterns": [".tailor-sdk/", "src/generated/", "src/seed/"],
11
+ "rules": {
12
+ "constructor-super": "error",
13
+ "for-direction": "error",
14
+ "no-async-promise-executor": "error",
15
+ "no-case-declarations": "error",
16
+ "no-class-assign": "error",
17
+ "no-compare-neg-zero": "error",
18
+ "no-cond-assign": "error",
19
+ "no-const-assign": "error",
20
+ "no-constant-binary-expression": "error",
21
+ "no-constant-condition": "error",
22
+ "no-control-regex": "error",
23
+ "no-debugger": "error",
24
+ "no-delete-var": "error",
25
+ "no-dupe-class-members": "error",
26
+ "no-dupe-else-if": "error",
27
+ "no-dupe-keys": "error",
28
+ "no-duplicate-case": "error",
29
+ "no-empty": "error",
30
+ "no-empty-character-class": "error",
31
+ "no-empty-pattern": "error",
32
+ "no-empty-static-block": "error",
33
+ "no-ex-assign": "error",
34
+ "no-extra-boolean-cast": "error",
35
+ "no-fallthrough": "error",
36
+ "no-func-assign": "error",
37
+ "no-global-assign": "error",
38
+ "no-import-assign": "error",
39
+ "no-invalid-regexp": "error",
40
+ "no-irregular-whitespace": "error",
41
+ "no-loss-of-precision": "error",
42
+ "no-new-native-nonconstructor": "error",
43
+ "no-nonoctal-decimal-escape": "error",
44
+ "no-obj-calls": "error",
45
+ "no-prototype-builtins": "error",
46
+ "no-redeclare": "error",
47
+ "no-regex-spaces": "error",
48
+ "no-self-assign": "error",
49
+ "no-setter-return": "error",
50
+ "no-shadow-restricted-names": "error",
51
+ "no-sparse-arrays": "error",
52
+ "no-this-before-super": "error",
53
+ "no-unexpected-multiline": "error",
54
+ "no-unsafe-finally": "error",
55
+ "no-unsafe-negation": "error",
56
+ "no-unsafe-optional-chaining": "error",
57
+ "no-unused-labels": "error",
58
+ "no-unused-private-class-members": "error",
59
+ "no-unused-vars": "error",
60
+ "no-useless-backreference": "error",
61
+ "no-useless-catch": "error",
62
+ "no-useless-escape": "error",
63
+ "no-with": "error",
64
+ "require-yield": "error",
65
+ "use-isnan": "error",
66
+ "valid-typeof": "error",
67
+ "@typescript-eslint/await-thenable": "error",
68
+ "@typescript-eslint/ban-ts-comment": "error",
69
+ "no-array-constructor": "error",
70
+ "@typescript-eslint/no-array-delete": "error",
71
+ "@typescript-eslint/no-base-to-string": "error",
72
+ "@typescript-eslint/no-duplicate-enum-values": "error",
73
+ "@typescript-eslint/no-duplicate-type-constituents": "error",
74
+ "@typescript-eslint/no-empty-object-type": "error",
75
+ "@typescript-eslint/no-explicit-any": "error",
76
+ "@typescript-eslint/no-extra-non-null-assertion": "error",
77
+ "@typescript-eslint/no-floating-promises": "error",
78
+ "@typescript-eslint/no-for-in-array": "error",
79
+ "@typescript-eslint/no-implied-eval": "error",
80
+ "@typescript-eslint/no-misused-new": "error",
81
+ "@typescript-eslint/no-misused-promises": "error",
82
+ "@typescript-eslint/no-namespace": "error",
83
+ "@typescript-eslint/no-non-null-asserted-optional-chain": "error",
84
+ "@typescript-eslint/no-redundant-type-constituents": "error",
85
+ "@typescript-eslint/no-require-imports": "error",
86
+ "@typescript-eslint/no-this-alias": "error",
87
+ "@typescript-eslint/no-unnecessary-type-assertion": "error",
88
+ "@typescript-eslint/no-unnecessary-type-constraint": "error",
89
+ "@typescript-eslint/no-unsafe-argument": "error",
90
+ "@typescript-eslint/no-unsafe-assignment": "error",
91
+ "@typescript-eslint/no-unsafe-call": "error",
92
+ "@typescript-eslint/no-unsafe-declaration-merging": "error",
93
+ "@typescript-eslint/no-unsafe-enum-comparison": "error",
94
+ "@typescript-eslint/no-unsafe-function-type": "error",
95
+ "@typescript-eslint/no-unsafe-member-access": "error",
96
+ "@typescript-eslint/no-unsafe-return": "error",
97
+ "@typescript-eslint/no-unsafe-unary-minus": "error",
98
+ "no-unused-expressions": "error",
99
+ "@typescript-eslint/no-wrapper-object-types": "error",
100
+ "@typescript-eslint/only-throw-error": "error",
101
+ "@typescript-eslint/prefer-as-const": "error",
102
+ "@typescript-eslint/prefer-namespace-keyword": "error",
103
+ "@typescript-eslint/prefer-promise-reject-errors": "error",
104
+ "@typescript-eslint/require-await": "error",
105
+ "@typescript-eslint/restrict-plus-operands": "error",
106
+ "@typescript-eslint/restrict-template-expressions": "error",
107
+ "@typescript-eslint/triple-slash-reference": "error",
108
+ "@typescript-eslint/unbound-method": "error",
109
+ "@typescript-eslint/adjacent-overload-signatures": "error",
110
+ "@typescript-eslint/array-type": "error",
111
+ "@typescript-eslint/ban-tslint-comment": "error",
112
+ "@typescript-eslint/consistent-generic-constructors": "error",
113
+ "@typescript-eslint/consistent-indexed-object-style": "error",
114
+ "@typescript-eslint/consistent-type-definitions": "error",
115
+ "@typescript-eslint/no-confusing-non-null-assertion": "error",
116
+ "no-empty-function": "error",
117
+ "@typescript-eslint/no-inferrable-types": "error",
118
+ "@typescript-eslint/non-nullable-type-assertion-style": "error",
119
+ "@typescript-eslint/prefer-for-of": "error",
120
+ "@typescript-eslint/prefer-function-type": "error",
121
+ "@typescript-eslint/prefer-includes": "error",
122
+ "@typescript-eslint/prefer-nullish-coalescing": "error"
123
+ },
124
+ "overrides": [
125
+ {
126
+ "files": ["**/*.ts", "**/*.tsx", "**/*.mts", "**/*.cts"],
127
+ "rules": {
128
+ "constructor-super": "off",
129
+ "no-class-assign": "off",
130
+ "no-const-assign": "off",
131
+ "no-dupe-class-members": "off",
132
+ "no-dupe-keys": "off",
133
+ "no-func-assign": "off",
134
+ "no-import-assign": "off",
135
+ "no-new-native-nonconstructor": "off",
136
+ "no-obj-calls": "off",
137
+ "no-redeclare": "off",
138
+ "no-setter-return": "off",
139
+ "no-this-before-super": "off",
140
+ "no-unsafe-negation": "off",
141
+ "no-var": "error",
142
+ "no-with": "off",
143
+ "prefer-rest-params": "error",
144
+ "prefer-spread": "error"
145
+ }
146
+ },
147
+ {
148
+ "files": ["eslint.config.js"],
149
+ "rules": {
150
+ "@typescript-eslint/await-thenable": "off",
151
+ "@typescript-eslint/no-array-delete": "off",
152
+ "@typescript-eslint/no-base-to-string": "off",
153
+ "@typescript-eslint/no-confusing-void-expression": "off",
154
+ "@typescript-eslint/no-deprecated": "off",
155
+ "@typescript-eslint/no-duplicate-type-constituents": "off",
156
+ "@typescript-eslint/no-floating-promises": "off",
157
+ "@typescript-eslint/no-for-in-array": "off",
158
+ "@typescript-eslint/no-implied-eval": "off",
159
+ "@typescript-eslint/no-meaningless-void-operator": "off",
160
+ "@typescript-eslint/no-misused-promises": "off",
161
+ "@typescript-eslint/no-misused-spread": "off",
162
+ "@typescript-eslint/no-mixed-enums": "off",
163
+ "@typescript-eslint/no-redundant-type-constituents": "off",
164
+ "@typescript-eslint/no-unnecessary-boolean-literal-compare": "off",
165
+ "@typescript-eslint/no-unnecessary-template-expression": "off",
166
+ "@typescript-eslint/no-unnecessary-type-arguments": "off",
167
+ "@typescript-eslint/no-unnecessary-type-assertion": "off",
168
+ "@typescript-eslint/no-unsafe-argument": "off",
169
+ "@typescript-eslint/no-unsafe-assignment": "off",
170
+ "@typescript-eslint/no-unsafe-call": "off",
171
+ "@typescript-eslint/no-unsafe-enum-comparison": "off",
172
+ "@typescript-eslint/no-unsafe-member-access": "off",
173
+ "@typescript-eslint/no-unsafe-return": "off",
174
+ "@typescript-eslint/no-unsafe-type-assertion": "off",
175
+ "@typescript-eslint/no-unsafe-unary-minus": "off",
176
+ "@typescript-eslint/non-nullable-type-assertion-style": "off",
177
+ "@typescript-eslint/only-throw-error": "off",
178
+ "@typescript-eslint/prefer-includes": "off",
179
+ "@typescript-eslint/prefer-nullish-coalescing": "off",
180
+ "@typescript-eslint/prefer-promise-reject-errors": "off",
181
+ "@typescript-eslint/prefer-reduce-type-parameter": "off",
182
+ "@typescript-eslint/prefer-return-this-type": "off",
183
+ "@typescript-eslint/promise-function-async": "off",
184
+ "@typescript-eslint/related-getter-setter-pairs": "off",
185
+ "@typescript-eslint/require-array-sort-compare": "off",
186
+ "@typescript-eslint/require-await": "off",
187
+ "@typescript-eslint/restrict-plus-operands": "off",
188
+ "@typescript-eslint/restrict-template-expressions": "off",
189
+ "@typescript-eslint/return-await": "off",
190
+ "@typescript-eslint/strict-boolean-expressions": "off",
191
+ "@typescript-eslint/switch-exhaustiveness-check": "off",
192
+ "@typescript-eslint/unbound-method": "off",
193
+ "@typescript-eslint/use-unknown-in-catch-callback-variable": "off"
194
+ }
195
+ }
196
+ ]
197
+ }
@@ -0,0 +1 @@
1
+ src/seed/
@@ -0,0 +1 @@
1
+ {}
@@ -0,0 +1,30 @@
1
+ # Generators Template
2
+
3
+ Demonstrates all built-in generator plugins for the Tailor Platform SDK.
4
+
5
+ ## Plugins
6
+
7
+ - **kyselyTypePlugin** - Generates Kysely type definitions for type-safe database queries
8
+ - **enumConstantsPlugin** - Generates enum constant objects from `db.enum()` fields
9
+ - **fileUtilsPlugin** - Generates file upload/download utility functions
10
+ - **seedPlugin** - Generates seed data templates and execution script
11
+
12
+ ## Generated Files
13
+
14
+ - `src/generated/db.ts` - Kysely database types
15
+ - `src/generated/enums.ts` - Enum constants
16
+ - `src/generated/files.ts` - File operation utilities
17
+
18
+ ## Getting Started
19
+
20
+ ```bash
21
+ pnpm install
22
+ pnpm generate # Regenerate all generated files
23
+ pnpm deploy
24
+ ```
25
+
26
+ ## Testing
27
+
28
+ ```bash
29
+ pnpm test
30
+ ```
@@ -0,0 +1,3 @@
1
+ node_modules/
2
+ .tailor-sdk/
3
+ .eslintcache
@@ -0,0 +1,24 @@
1
+ import eslint from "@eslint/js";
2
+ import tseslint from "typescript-eslint";
3
+ import { defineConfig, globalIgnores } from "eslint/config";
4
+ import oxlint from "eslint-plugin-oxlint";
5
+
6
+ export default defineConfig([
7
+ globalIgnores([".tailor-sdk/", "src/generated/", "src/seed/"]),
8
+ eslint.configs.recommended,
9
+ tseslint.configs.recommendedTypeChecked,
10
+ tseslint.configs.stylisticTypeChecked,
11
+ {
12
+ languageOptions: {
13
+ parserOptions: {
14
+ projectService: true,
15
+ tsconfigRootDir: import.meta.dirname,
16
+ },
17
+ },
18
+ },
19
+ {
20
+ files: ["eslint.config.js"],
21
+ extends: [tseslint.configs.disableTypeChecked],
22
+ },
23
+ ...oxlint.buildFromOxlintConfigFile("./.oxlintrc.json"),
24
+ ]);
@@ -0,0 +1,30 @@
1
+ {
2
+ "name": "generators",
3
+ "private": true,
4
+ "type": "module",
5
+ "scripts": {
6
+ "generate": "tailor-sdk generate",
7
+ "deploy": "tailor-sdk apply",
8
+ "test": "vitest --project unit",
9
+ "test:unit": "vitest --project unit",
10
+ "format": "oxfmt --write .",
11
+ "format:check": "oxfmt --check .",
12
+ "lint": "oxlint --type-aware . && eslint --cache .",
13
+ "lint:fix": "oxlint --type-aware --fix . && eslint --cache --fix .",
14
+ "typecheck": "tsc --noEmit"
15
+ },
16
+ "devDependencies": {
17
+ "@eslint/js": "9.39.2",
18
+ "@tailor-platform/function-types": "0.8.0",
19
+ "@tailor-platform/sdk": "1.21.0",
20
+ "@types/node": "24.10.9",
21
+ "eslint": "9.39.2",
22
+ "eslint-plugin-oxlint": "1.39.0",
23
+ "oxfmt": "0.24.0",
24
+ "oxlint": "1.39.0",
25
+ "oxlint-tsgolint": "0.11.1",
26
+ "typescript": "5.9.3",
27
+ "typescript-eslint": "8.53.0",
28
+ "vitest": "4.0.17"
29
+ }
30
+ }
@@ -0,0 +1,25 @@
1
+ import { db } from "@tailor-platform/sdk";
2
+
3
+ export const category = db
4
+ .type("Category", {
5
+ name: db.string(),
6
+ slug: db.string().unique(),
7
+ parentCategoryId: db.uuid({ optional: true }).relation({
8
+ type: "n-1",
9
+ toward: { type: "self" },
10
+ backward: "children",
11
+ }),
12
+ })
13
+ .permission({
14
+ create: [[{ user: "_loggedIn" }, "=", true]],
15
+ read: [[{ user: "_loggedIn" }, "=", true]],
16
+ update: [[{ user: "_loggedIn" }, "=", true]],
17
+ delete: [[{ user: "_loggedIn" }, "=", true]],
18
+ })
19
+ .gqlPermission([
20
+ {
21
+ conditions: [[{ user: "_loggedIn" }, "=", true]],
22
+ actions: "all",
23
+ permit: true,
24
+ },
25
+ ]);
@@ -0,0 +1,38 @@
1
+ import { db } from "@tailor-platform/sdk";
2
+ import { product } from "./product";
3
+ import { user } from "./user";
4
+
5
+ export const order = db
6
+ .type("Order", {
7
+ productId: db.uuid().relation({
8
+ type: "n-1",
9
+ toward: { type: product },
10
+ }),
11
+ userId: db.uuid().relation({
12
+ type: "n-1",
13
+ toward: { type: user },
14
+ }),
15
+ quantity: db.int(),
16
+ totalPrice: db.float(),
17
+ status: db.enum([
18
+ { value: "PENDING", description: "Awaiting confirmation" },
19
+ { value: "CONFIRMED", description: "Order confirmed" },
20
+ { value: "SHIPPED", description: "In transit" },
21
+ { value: "DELIVERED", description: "Successfully delivered" },
22
+ { value: "CANCELLED", description: "Order cancelled" },
23
+ ]),
24
+ ...db.fields.timestamps(),
25
+ })
26
+ .permission({
27
+ create: [[{ user: "_loggedIn" }, "=", true]],
28
+ read: [[{ user: "_loggedIn" }, "=", true]],
29
+ update: [[{ user: "_loggedIn" }, "=", true]],
30
+ delete: [[{ user: "_loggedIn" }, "=", true]],
31
+ })
32
+ .gqlPermission([
33
+ {
34
+ conditions: [[{ user: "_loggedIn" }, "=", true]],
35
+ actions: "all",
36
+ permit: true,
37
+ },
38
+ ]);
@@ -0,0 +1,34 @@
1
+ import { db } from "@tailor-platform/sdk";
2
+ import { category } from "./category";
3
+
4
+ export const product = db
5
+ .type("Product", {
6
+ name: db.string(),
7
+ description: db.string({ optional: true }),
8
+ price: db.float(),
9
+ status: db.enum([
10
+ { value: "DRAFT", description: "Not yet published" },
11
+ { value: "ACTIVE", description: "Available for purchase" },
12
+ { value: "DISCONTINUED", description: "No longer sold" },
13
+ ]),
14
+ categoryId: db.uuid({ optional: true }).relation({
15
+ type: "n-1",
16
+ toward: { type: category },
17
+ }),
18
+ ...db.fields.timestamps(),
19
+ })
20
+ .files({ image: "Product image" })
21
+ .indexes({ fields: ["status", "categoryId"], unique: false })
22
+ .permission({
23
+ create: [[{ user: "_loggedIn" }, "=", true]],
24
+ read: [[{ user: "_loggedIn" }, "=", true]],
25
+ update: [[{ user: "_loggedIn" }, "=", true]],
26
+ delete: [[{ user: "_loggedIn" }, "=", true]],
27
+ })
28
+ .gqlPermission([
29
+ {
30
+ conditions: [[{ user: "_loggedIn" }, "=", true]],
31
+ actions: "all",
32
+ permit: true,
33
+ },
34
+ ]);
@@ -0,0 +1,26 @@
1
+ import { db } from "@tailor-platform/sdk";
2
+
3
+ export const user = db
4
+ .type("User", {
5
+ name: db.string(),
6
+ email: db.string().unique(),
7
+ role: db.enum([
8
+ { value: "ADMIN", description: "Administrator with full access" },
9
+ { value: "MEMBER", description: "Regular team member" },
10
+ { value: "VIEWER", description: "Read-only access" },
11
+ ]),
12
+ ...db.fields.timestamps(),
13
+ })
14
+ .permission({
15
+ create: [[{ user: "_loggedIn" }, "=", true]],
16
+ read: [[{ user: "_loggedIn" }, "=", true]],
17
+ update: [[{ user: "_loggedIn" }, "=", true]],
18
+ delete: [[{ user: "_loggedIn" }, "=", true]],
19
+ })
20
+ .gqlPermission([
21
+ {
22
+ conditions: [[{ user: "_loggedIn" }, "=", true]],
23
+ actions: "all",
24
+ permit: true,
25
+ },
26
+ ]);
@@ -0,0 +1,68 @@
1
+ import {
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";
13
+
14
+ export interface Namespace {
15
+ "main-db": {
16
+ Category: {
17
+ id: Generated<string>;
18
+ name: string;
19
+ slug: string;
20
+ parentCategoryId: string | null;
21
+ }
22
+
23
+ Order: {
24
+ id: Generated<string>;
25
+ productId: string;
26
+ userId: string;
27
+ quantity: number;
28
+ totalPrice: number;
29
+ status: "PENDING" | "CONFIRMED" | "SHIPPED" | "DELIVERED" | "CANCELLED";
30
+ createdAt: Generated<Timestamp>;
31
+ updatedAt: Timestamp | null;
32
+ }
33
+
34
+ Product: {
35
+ id: Generated<string>;
36
+ name: string;
37
+ description: string | null;
38
+ price: number;
39
+ status: "DRAFT" | "ACTIVE" | "DISCONTINUED";
40
+ categoryId: string | null;
41
+ createdAt: Generated<Timestamp>;
42
+ updatedAt: Timestamp | null;
43
+ }
44
+
45
+ User: {
46
+ id: Generated<string>;
47
+ name: string;
48
+ email: string;
49
+ role: "ADMIN" | "MEMBER" | "VIEWER";
50
+ createdAt: Generated<Timestamp>;
51
+ updatedAt: Timestamp | null;
52
+ }
53
+ }
54
+ }
55
+
56
+ export const getDB = createGetDB<Namespace>();
57
+
58
+ export type DB<N extends keyof Namespace = keyof Namespace> = NamespaceDB<Namespace, N>;
59
+
60
+ export type Transaction<K extends keyof Namespace | DB = keyof Namespace> =
61
+ NamespaceTransaction<Namespace, K>;
62
+
63
+ type TableName = NamespaceTableName<Namespace>;
64
+ export type Table<T extends TableName> = NamespaceTable<Namespace, T>;
65
+
66
+ export type Insertable<T extends TableName> = NamespaceInsertable<Namespace, T>;
67
+ export type Selectable<T extends TableName> = NamespaceSelectable<Namespace, T>;
68
+ export type Updateable<T extends TableName> = NamespaceUpdateable<Namespace, T>;
@@ -0,0 +1,39 @@
1
+ /**
2
+ * @property PENDING - Awaiting confirmation
3
+ * @property CONFIRMED - Order confirmed
4
+ * @property SHIPPED - In transit
5
+ * @property DELIVERED - Successfully delivered
6
+ * @property CANCELLED - Order cancelled
7
+ */
8
+ export const OrderStatus = {
9
+ "PENDING": "PENDING",
10
+ "CONFIRMED": "CONFIRMED",
11
+ "SHIPPED": "SHIPPED",
12
+ "DELIVERED": "DELIVERED",
13
+ "CANCELLED": "CANCELLED"
14
+ } as const;
15
+ export type OrderStatus = (typeof OrderStatus)[keyof typeof OrderStatus];
16
+
17
+ /**
18
+ * @property DRAFT - Not yet published
19
+ * @property ACTIVE - Available for purchase
20
+ * @property DISCONTINUED - No longer sold
21
+ */
22
+ export const ProductStatus = {
23
+ "DRAFT": "DRAFT",
24
+ "ACTIVE": "ACTIVE",
25
+ "DISCONTINUED": "DISCONTINUED"
26
+ } as const;
27
+ export type ProductStatus = (typeof ProductStatus)[keyof typeof ProductStatus];
28
+
29
+ /**
30
+ * @property ADMIN - Administrator with full access
31
+ * @property MEMBER - Regular team member
32
+ * @property VIEWER - Read-only access
33
+ */
34
+ export const UserRole = {
35
+ "ADMIN": "ADMIN",
36
+ "MEMBER": "MEMBER",
37
+ "VIEWER": "VIEWER"
38
+ } as const;
39
+ export type UserRole = (typeof UserRole)[keyof typeof UserRole];
@@ -0,0 +1,51 @@
1
+ export interface TypeWithFiles {
2
+ Product: {
3
+ fields: "image";
4
+ };
5
+ }
6
+
7
+ const namespaces: Record<keyof TypeWithFiles, string> = {
8
+ Product: "main-db",
9
+ };
10
+
11
+ export async function downloadFile<T extends keyof TypeWithFiles>(
12
+ type: T,
13
+ field: TypeWithFiles[T]["fields"],
14
+ recordId: string,
15
+ ) {
16
+ return await tailordb.file.download(namespaces[type], type, field, recordId);
17
+ }
18
+
19
+ export async function uploadFile<T extends keyof TypeWithFiles>(
20
+ type: T,
21
+ field: TypeWithFiles[T]["fields"],
22
+ recordId: string,
23
+ data: string | ArrayBuffer | Uint8Array<ArrayBufferLike> | number[],
24
+ options?: FileUploadOptions,
25
+ ): Promise<FileUploadResponse> {
26
+ return await tailordb.file.upload(namespaces[type], type, field, recordId, data, options);
27
+ }
28
+
29
+ export async function deleteFile<T extends keyof TypeWithFiles>(
30
+ type: T,
31
+ field: TypeWithFiles[T]["fields"],
32
+ recordId: string,
33
+ ): Promise<void> {
34
+ return await tailordb.file.delete(namespaces[type], type, field, recordId);
35
+ }
36
+
37
+ export async function getFileMetadata<T extends keyof TypeWithFiles>(
38
+ type: T,
39
+ field: TypeWithFiles[T]["fields"],
40
+ recordId: string,
41
+ ): Promise<FileMetadata> {
42
+ return await tailordb.file.getMetadata(namespaces[type], type, field, recordId);
43
+ }
44
+
45
+ export async function openFileDownloadStream<T extends keyof TypeWithFiles>(
46
+ type: T,
47
+ field: TypeWithFiles[T]["fields"],
48
+ recordId: string,
49
+ ): Promise<FileStreamIterator> {
50
+ return await tailordb.file.openDownloadStream(namespaces[type], type, field, recordId);
51
+ }
@@ -0,0 +1,92 @@
1
+ import { unauthenticatedTailorUser } from "@tailor-platform/sdk/test";
2
+ import { afterAll, afterEach, beforeAll, describe, expect, test, vi } from "vitest";
3
+ import resolver from "./getProduct";
4
+
5
+ describe("getProduct resolver", () => {
6
+ const mockQueryObject = vi.fn();
7
+ beforeAll(() => {
8
+ vi.stubGlobal("tailordb", {
9
+ Client: vi.fn(
10
+ class {
11
+ connect = vi.fn();
12
+ end = vi.fn();
13
+ queryObject = mockQueryObject;
14
+ },
15
+ ),
16
+ });
17
+ });
18
+ afterAll(() => {
19
+ vi.unstubAllGlobals();
20
+ });
21
+ afterEach(() => {
22
+ mockQueryObject.mockReset();
23
+ });
24
+
25
+ test("returns product with category", async () => {
26
+ // Select product
27
+ mockQueryObject.mockResolvedValueOnce({
28
+ rows: [
29
+ {
30
+ id: "product-1",
31
+ name: "Widget",
32
+ price: 9.99,
33
+ status: "ACTIVE",
34
+ categoryId: "cat-1",
35
+ description: null,
36
+ createdAt: new Date(),
37
+ updatedAt: null,
38
+ },
39
+ ],
40
+ });
41
+ // Select category
42
+ mockQueryObject.mockResolvedValueOnce({
43
+ rows: [{ name: "Gadgets" }],
44
+ });
45
+
46
+ const result = await resolver.body({
47
+ input: { productId: "product-1" },
48
+ user: unauthenticatedTailorUser,
49
+ env: {},
50
+ });
51
+
52
+ expect(result).toEqual({
53
+ name: "Widget",
54
+ price: 9.99,
55
+ status: "ACTIVE",
56
+ categoryName: "Gadgets",
57
+ });
58
+ expect(mockQueryObject).toHaveBeenCalledTimes(2);
59
+ });
60
+
61
+ test("returns product without category", async () => {
62
+ // Select product (no categoryId)
63
+ mockQueryObject.mockResolvedValueOnce({
64
+ rows: [
65
+ {
66
+ id: "product-2",
67
+ name: "Standalone Item",
68
+ price: 19.99,
69
+ status: "DRAFT",
70
+ categoryId: null,
71
+ description: null,
72
+ createdAt: new Date(),
73
+ updatedAt: null,
74
+ },
75
+ ],
76
+ });
77
+
78
+ const result = await resolver.body({
79
+ input: { productId: "product-2" },
80
+ user: unauthenticatedTailorUser,
81
+ env: {},
82
+ });
83
+
84
+ expect(result).toEqual({
85
+ name: "Standalone Item",
86
+ price: 19.99,
87
+ status: "DRAFT",
88
+ categoryName: null,
89
+ });
90
+ expect(mockQueryObject).toHaveBeenCalledTimes(1);
91
+ });
92
+ });