@tailor-platform/sdk 2.1.0 → 2.3.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 +199 -0
- package/{dist/cli/index.mjs → bin/tailor.mjs} +1 -1
- package/dist/application-BZfk4HKm.mjs +3 -0
- package/dist/{application-D77KJFKD.mjs → application-F-nl107y.mjs} +121 -27
- package/dist/application-F-nl107y.mjs.map +1 -0
- package/dist/cli/commands/deploy/tailordb/index.d.mts +2 -1
- package/dist/cli/commands/deploy/types.d.mts +2 -1
- package/dist/cli/commands/tailordb/migrate/diff-calculator.d.mts +52 -22
- package/dist/cli/commands/tailordb/migrate/file-state.d.mts +1 -0
- package/dist/cli/commands/tailordb/migrate/generate.d.mts +6 -0
- package/dist/cli/commands/tailordb/migrate/rename-detection.d.mts +22 -0
- package/dist/cli/commands/tailordb/migrate/schema-checks.d.mts +2 -2
- package/dist/cli/commands/tailordb/migrate/snapshot-types.d.mts +9 -2
- package/dist/cli/commands/tailordb/migrate/snapshot.d.mts +30 -9
- package/dist/cli/lib.d.mts +4 -4
- package/dist/cli/lib.mjs +3 -482
- package/dist/cli/lib.mjs.map +1 -1
- package/dist/cli/main.mjs +1151 -208
- package/dist/cli/main.mjs.map +1 -1
- package/dist/cli/ts-hook.mjs +52 -7
- package/dist/completion/zsh-worker.zsh +167 -4
- package/dist/configure/index.d.mts +3 -3
- package/dist/configure/index.mjs +90 -23
- package/dist/configure/index.mjs.map +1 -1
- package/dist/configure/services/index.d.mts +3 -2
- package/dist/configure/services/tailordb/index.d.mts +2 -1
- package/dist/configure/services/tailordb/schema.d.mts +46 -46
- package/dist/configure/services/tailordb/types.d.mts +30 -4
- package/dist/configure/services/workflow/index.d.mts +2 -2
- package/dist/configure/services/workflow/wait-point.d.mts +72 -13
- package/dist/{crashreport-B5LqCTfF.mjs → crashreport-CIIfLnoO.mjs} +2 -2
- package/dist/{crashreport-B5LqCTfF.mjs.map → crashreport-CIIfLnoO.mjs.map} +1 -1
- package/dist/{crashreport-eI7ty7ok.mjs → crashreport-CINZ5dVN.mjs} +1 -1
- package/dist/errors-BVb6vYGy.mjs +89 -0
- package/dist/errors-BVb6vYGy.mjs.map +1 -0
- package/dist/kysely/index.d.mts +53 -5
- package/dist/kysely/index.mjs +7 -2
- package/dist/kysely/index.mjs.map +1 -1
- package/dist/{logger-CXQq9YIp.mjs → logger-DSdExfor.mjs} +83 -42
- package/dist/logger-DSdExfor.mjs.map +1 -0
- package/dist/plugin/builtin/seed/index.mjs +1 -1
- package/dist/{register-ts-hook-BU18uU44.mjs → register-ts-hook-ClI226n2.mjs} +3541 -703
- package/dist/register-ts-hook-ClI226n2.mjs.map +1 -0
- package/dist/schema--xYWRGfe.mjs.map +1 -1
- package/dist/seed/index.d.mts +52 -3
- package/dist/seed/index.mjs +200 -44
- package/dist/seed/index.mjs.map +1 -1
- package/dist/{seed-B-yckgQY.mjs → seed-xqM9WIHP.mjs} +8 -8
- package/dist/seed-xqM9WIHP.mjs.map +1 -0
- package/dist/{service-k1xy_A5G.mjs → service-C_WpbKHu.mjs} +39 -5
- package/dist/service-C_WpbKHu.mjs.map +1 -0
- package/dist/service-D1RCdzIL.mjs +3 -0
- package/dist/{service-B5WynBHQ.mjs → service-hZskxZmg.mjs} +3 -3
- package/dist/{service-B5WynBHQ.mjs.map → service-hZskxZmg.mjs.map} +1 -1
- package/dist/{service_pb-D5--My_M.mjs → service_pb-BEWj1pOV.mjs} +2 -2
- package/dist/{service_pb-D5--My_M.mjs.map → service_pb-BEWj1pOV.mjs.map} +1 -1
- package/dist/{service_pb-i8CmnQP4.mjs → service_pb-BjlhvK9E.mjs} +1 -1
- package/dist/utils/test/index.d.mts +6 -3
- package/dist/utils/test/index.mjs +25 -13
- package/dist/utils/test/index.mjs.map +1 -1
- package/dist/vitest/index.d.mts +2 -1
- package/dist/vitest/index.mjs +167 -3
- package/dist/vitest/index.mjs.map +1 -1
- package/dist/vitest/mocks/workflow.d.mts +13 -1
- package/dist/vitest/pglite-kysely.d.mts +43 -0
- package/dist/wait-point-invoker-__oE88_P.mjs +148 -0
- package/dist/wait-point-invoker-__oE88_P.mjs.map +1 -0
- package/dist/wait-point-registry-TL99zotw.mjs +47 -0
- package/dist/wait-point-registry-TL99zotw.mjs.map +1 -0
- package/dist/{workspace_resource_pb-DXnO2AT-.mjs → workspace_resource_pb-HNIL_Vfj.mjs} +10 -2
- package/dist/{workspace_resource_pb-DXnO2AT-.mjs.map → workspace_resource_pb-HNIL_Vfj.mjs.map} +1 -1
- package/docs/cli/setup.md +14 -1
- package/docs/cli/tailordb.md +96 -28
- package/docs/cli-reference.md +15 -12
- package/docs/configuration.md +1 -1
- package/docs/github-actions.md +73 -28
- package/docs/migration/v2.md +55 -1
- package/docs/plugin/custom.md +48 -48
- package/docs/plugin/index.md +24 -24
- package/docs/services/auth.md +10 -10
- package/docs/services/executor.md +1 -1
- package/docs/services/resolver.md +2 -2
- package/docs/services/tailordb-migration.md +485 -84
- package/docs/services/tailordb.md +28 -28
- package/docs/services/workflow.md +52 -2
- package/docs/testing.md +14 -0
- package/package.json +12 -7
- package/dist/application-Af1zIqSI.mjs +0 -3
- package/dist/application-D77KJFKD.mjs.map +0 -1
- package/dist/errors-D7583Zz7.mjs +0 -58
- package/dist/errors-D7583Zz7.mjs.map +0 -1
- package/dist/logger-CXQq9YIp.mjs.map +0 -1
- package/dist/register-ts-hook-BU18uU44.mjs.map +0 -1
- package/dist/seed-B-yckgQY.mjs.map +0 -1
- package/dist/service-M7OYziQP.mjs +0 -3
- package/dist/service-k1xy_A5G.mjs.map +0 -1
- package/dist/test-env-key-D7UkZp99.mjs +0 -75
- package/dist/test-env-key-D7UkZp99.mjs.map +0 -1
package/docs/plugin/custom.md
CHANGED
|
@@ -18,7 +18,7 @@ const myPlugin: Plugin = {
|
|
|
18
18
|
export default myPlugin; // Required: must be default export
|
|
19
19
|
```
|
|
20
20
|
|
|
21
|
-
This is required so that other plugins and generation-time hooks can use plugin-generated TailorDB
|
|
21
|
+
This is required so that other plugins and generation-time hooks can use plugin-generated TailorDB tables via `getGeneratedType()`.
|
|
22
22
|
|
|
23
23
|
## Plugin Interface
|
|
24
24
|
|
|
@@ -56,38 +56,38 @@ interface Plugin<TypeConfig = unknown, PluginConfig = unknown> {
|
|
|
56
56
|
| `id` | Yes | Unique plugin identifier (e.g., `"@my-company/soft-delete"`) |
|
|
57
57
|
| `description` | Yes | Human-readable description |
|
|
58
58
|
| `importPath` | When using definition-time hooks | Path resolvable from `tailor.config.ts` directory. Used for import statements in generated code. |
|
|
59
|
-
| `typeConfigRequired` | No | Whether per-
|
|
59
|
+
| `typeConfigRequired` | No | Whether per-table config is required when attaching via `.plugin()`. Default: optional. |
|
|
60
60
|
| `pluginConfig` | No | Plugin-level config passed via `definePlugins()`. Set via factory function. |
|
|
61
61
|
|
|
62
62
|
## Hook Reference
|
|
63
63
|
|
|
64
64
|
### onTypeLoaded
|
|
65
65
|
|
|
66
|
-
**Trigger**: Called once for each TailorDB
|
|
66
|
+
**Trigger**: Called once for each TailorDB table that has `.plugin({ pluginId: config })` attached.
|
|
67
67
|
|
|
68
68
|
**Context** (`PluginProcessContext`):
|
|
69
69
|
|
|
70
70
|
| Field | Type | Description |
|
|
71
71
|
| -------------- | ----------------- | ------------------------------------------ |
|
|
72
|
-
| `type` | `TailorAnyDBType` | The TailorDB
|
|
73
|
-
| `typeConfig` | `TypeConfig` | Per-
|
|
72
|
+
| `type` | `TailorAnyDBType` | The TailorDB table being processed |
|
|
73
|
+
| `typeConfig` | `TypeConfig` | Per-table config from `.plugin()` |
|
|
74
74
|
| `pluginConfig` | `PluginConfig` | Plugin-level config from `definePlugins()` |
|
|
75
|
-
| `namespace` | `string` | Namespace of the TailorDB
|
|
75
|
+
| `namespace` | `string` | Namespace of the TailorDB table |
|
|
76
76
|
|
|
77
77
|
**Returns** (`TypePluginOutput`):
|
|
78
78
|
|
|
79
|
-
| Field | Type | Description
|
|
80
|
-
| ----------- | ----------------------------------------------- |
|
|
81
|
-
| `types` | `Record<string, TailorAnyDBType>` | Additional TailorDB
|
|
82
|
-
| `resolvers` | `PluginGeneratedResolver[]` | Additional resolvers to generate
|
|
83
|
-
| `executors` | `PluginGeneratedExecutor[]` | Additional executors to generate
|
|
84
|
-
| `extends` | `{ fields?: Record<string, TailorAnyDBField> }` | Fields to add to the source
|
|
79
|
+
| Field | Type | Description |
|
|
80
|
+
| ----------- | ----------------------------------------------- | ------------------------------------------------------ |
|
|
81
|
+
| `types` | `Record<string, TailorAnyDBType>` | Additional TailorDB tables to generate (keyed by kind) |
|
|
82
|
+
| `resolvers` | `PluginGeneratedResolver[]` | Additional resolvers to generate |
|
|
83
|
+
| `executors` | `PluginGeneratedExecutor[]` | Additional executors to generate |
|
|
84
|
+
| `extends` | `{ fields?: Record<string, TailorAnyDBField> }` | Fields to add to the source table |
|
|
85
85
|
|
|
86
86
|
**Use cases**:
|
|
87
87
|
|
|
88
|
-
- Generate derived
|
|
89
|
-
- Add fields to existing
|
|
90
|
-
- Generate executors triggered by record events on the source
|
|
88
|
+
- Generate derived tables (e.g., archive tables, history tables) from user-defined tables
|
|
89
|
+
- Add fields to existing tables (e.g., `deletedAt` for soft delete)
|
|
90
|
+
- Generate executors triggered by record events on the source table
|
|
91
91
|
|
|
92
92
|
```typescript
|
|
93
93
|
onTypeLoaded(context) {
|
|
@@ -102,7 +102,7 @@ onTypeLoaded(context) {
|
|
|
102
102
|
|
|
103
103
|
### onNamespaceLoaded
|
|
104
104
|
|
|
105
|
-
**Trigger**: Called once per namespace for plugins that do not require a source
|
|
105
|
+
**Trigger**: Called once per namespace for plugins that do not require a source table.
|
|
106
106
|
|
|
107
107
|
**Context** (`PluginNamespaceProcessContext`):
|
|
108
108
|
|
|
@@ -113,11 +113,11 @@ onTypeLoaded(context) {
|
|
|
113
113
|
|
|
114
114
|
**Returns** (`PluginOutput`):
|
|
115
115
|
|
|
116
|
-
Same as `TypePluginOutput` but without `extends` (namespace plugins cannot extend a source
|
|
116
|
+
Same as `TypePluginOutput` but without `extends` (namespace plugins cannot extend a source table).
|
|
117
117
|
|
|
118
118
|
**Use cases**:
|
|
119
119
|
|
|
120
|
-
- Generate
|
|
120
|
+
- Generate tables that don't derive from a specific user table (e.g., audit log, settings table)
|
|
121
121
|
|
|
122
122
|
```typescript
|
|
123
123
|
onNamespaceLoaded(context) {
|
|
@@ -129,26 +129,26 @@ onNamespaceLoaded(context) {
|
|
|
129
129
|
|
|
130
130
|
### onTailorDBReady
|
|
131
131
|
|
|
132
|
-
**Trigger**: Called once after all TailorDB
|
|
132
|
+
**Trigger**: Called once after all TailorDB tables are loaded and auth is resolved.
|
|
133
133
|
|
|
134
134
|
**Context** (`TailorDBReadyContext`):
|
|
135
135
|
|
|
136
|
-
| Field | Type | Description
|
|
137
|
-
| -------------- | ------------------------- |
|
|
138
|
-
| `tailordb` | `TailorDBNamespaceData[]` | All namespaces with
|
|
139
|
-
| `auth` | `GeneratorAuthInput?` | Auth configuration (machine users, OAuth2 clients, etc.)
|
|
140
|
-
| `baseDir` | `string` | Output directory for generated files
|
|
141
|
-
| `configPath` | `string` | Path to `tailor.config.ts`
|
|
142
|
-
| `pluginConfig` | `PluginConfig` | Plugin-level config from `definePlugins()`
|
|
136
|
+
| Field | Type | Description |
|
|
137
|
+
| -------------- | ------------------------- | --------------------------------------------------------------- |
|
|
138
|
+
| `tailordb` | `TailorDBNamespaceData[]` | All namespaces with tables, source info, and plugin attachments |
|
|
139
|
+
| `auth` | `GeneratorAuthInput?` | Auth configuration (machine users, OAuth2 clients, etc.) |
|
|
140
|
+
| `baseDir` | `string` | Output directory for generated files |
|
|
141
|
+
| `configPath` | `string` | Path to `tailor.config.ts` |
|
|
142
|
+
| `pluginConfig` | `PluginConfig` | Plugin-level config from `definePlugins()` |
|
|
143
143
|
|
|
144
144
|
`TailorDBNamespaceData` contains:
|
|
145
145
|
|
|
146
|
-
| Field | Type | Description
|
|
147
|
-
| ------------------- | ------------------------------------------ |
|
|
148
|
-
| `namespace` | `string` | Namespace name
|
|
149
|
-
| `types` | `Record<string, TailorDBType>` | All finalized
|
|
150
|
-
| `sourceInfo` | `ReadonlyMap<string, TypeSourceInfoEntry>` | Source file info for each
|
|
151
|
-
| `pluginAttachments` | `ReadonlyMap<string, PluginAttachment[]>` | Plugin configs attached to each
|
|
146
|
+
| Field | Type | Description |
|
|
147
|
+
| ------------------- | ------------------------------------------ | ------------------------------------- |
|
|
148
|
+
| `namespace` | `string` | Namespace name |
|
|
149
|
+
| `types` | `Record<string, TailorDBType>` | All finalized tables in the namespace |
|
|
150
|
+
| `sourceInfo` | `ReadonlyMap<string, TypeSourceInfoEntry>` | Source file info for each table |
|
|
151
|
+
| `pluginAttachments` | `ReadonlyMap<string, PluginAttachment[]>` | Plugin configs attached to each table |
|
|
152
152
|
|
|
153
153
|
**Returns** (`GeneratorResult`):
|
|
154
154
|
|
|
@@ -159,9 +159,9 @@ onNamespaceLoaded(context) {
|
|
|
159
159
|
|
|
160
160
|
**Use cases**:
|
|
161
161
|
|
|
162
|
-
- Generate
|
|
163
|
-
- Generate seed data scaffolding from
|
|
164
|
-
- Generate
|
|
162
|
+
- Generate table definitions (e.g., Kysely types, enum constants)
|
|
163
|
+
- Generate seed data scaffolding from table schemas
|
|
164
|
+
- Generate table lists or metadata files
|
|
165
165
|
|
|
166
166
|
```typescript
|
|
167
167
|
onTailorDBReady(ctx) {
|
|
@@ -276,7 +276,7 @@ import type {
|
|
|
276
276
|
|
|
277
277
|
## getGeneratedType Helper
|
|
278
278
|
|
|
279
|
-
The SDK provides an async `getGeneratedType()` helper function to retrieve plugin-generated TailorDB
|
|
279
|
+
The SDK provides an async `getGeneratedType()` helper function to retrieve plugin-generated TailorDB tables. This enables plugins and other tools to work with tables generated by plugins.
|
|
280
280
|
|
|
281
281
|
```typescript
|
|
282
282
|
import { join } from "node:path";
|
|
@@ -285,7 +285,7 @@ import { customer } from "./tailordb/customer";
|
|
|
285
285
|
|
|
286
286
|
const configPath = join(import.meta.dirname, "./tailor.config.ts");
|
|
287
287
|
|
|
288
|
-
//
|
|
288
|
+
// Table-attached plugin
|
|
289
289
|
const DeletedCustomer = await getGeneratedType(
|
|
290
290
|
configPath,
|
|
291
291
|
"@example/soft-delete",
|
|
@@ -301,8 +301,8 @@ const AuditLog = await getGeneratedType(configPath, "@example/audit-log", null,
|
|
|
301
301
|
|
|
302
302
|
- `configPath`: Path to `tailor.config.ts` (absolute or relative to cwd)
|
|
303
303
|
- `pluginId`: The plugin's unique identifier (e.g., `"@example/soft-delete"`)
|
|
304
|
-
- `sourceType`: The TailorDB
|
|
305
|
-
- `kind`: The generated
|
|
304
|
+
- `sourceType`: The TailorDB table that the plugin is attached to (`null` for namespace plugins)
|
|
305
|
+
- `kind`: The generated table kind (e.g., `"archive"`, `"auditLog"`)
|
|
306
306
|
|
|
307
307
|
**How it works:**
|
|
308
308
|
|
|
@@ -311,7 +311,7 @@ const AuditLog = await getGeneratedType(configPath, "@example/audit-log", null,
|
|
|
311
311
|
3. Auto-resolves the namespace from config
|
|
312
312
|
4. Calls the plugin's `onTypeLoaded()` or `onNamespaceLoaded()` method
|
|
313
313
|
5. Caches the result to avoid redundant processing
|
|
314
|
-
6. Returns the generated
|
|
314
|
+
6. Returns the generated table matching the specified kind
|
|
315
315
|
|
|
316
316
|
## Examples
|
|
317
317
|
|
|
@@ -341,7 +341,7 @@ function processSoftDelete(
|
|
|
341
341
|
const { type, typeConfig, pluginConfig, namespace } = context;
|
|
342
342
|
const prefix = pluginConfig?.archiveTablePrefix ?? "Deleted_";
|
|
343
343
|
|
|
344
|
-
// Generate archive
|
|
344
|
+
// Generate archive table
|
|
345
345
|
const archiveType = db
|
|
346
346
|
.table(`${prefix}${type.name}`, {
|
|
347
347
|
originalId: db.uuid().description("ID of the deleted record"),
|
|
@@ -355,7 +355,7 @@ function processSoftDelete(
|
|
|
355
355
|
})
|
|
356
356
|
.description(`Archive for deleted ${type.name} records`);
|
|
357
357
|
|
|
358
|
-
// Extend source
|
|
358
|
+
// Extend source table with deletedAt field
|
|
359
359
|
const extendFields = {
|
|
360
360
|
deletedAt: db.datetime({ optional: true }).description("Soft delete timestamp"),
|
|
361
361
|
};
|
|
@@ -470,7 +470,7 @@ import type { Plugin, GeneratorResult } from "@tailor-platform/sdk";
|
|
|
470
470
|
|
|
471
471
|
const typeListPlugin: Plugin = {
|
|
472
472
|
id: "@example/type-list",
|
|
473
|
-
description: "Generates a list of all TailorDB
|
|
473
|
+
description: "Generates a list of all TailorDB table names",
|
|
474
474
|
|
|
475
475
|
onTailorDBReady(ctx): GeneratorResult {
|
|
476
476
|
const allTypes = ctx.tailordb.flatMap((ns) =>
|
|
@@ -495,15 +495,15 @@ A plugin that uses both definition-time and generation-time hooks:
|
|
|
495
495
|
```typescript
|
|
496
496
|
const plugin: Plugin = {
|
|
497
497
|
id: "@example/hybrid",
|
|
498
|
-
description: "Generates derived
|
|
498
|
+
description: "Generates derived tables and produces output files",
|
|
499
499
|
importPath: "./plugins/hybrid",
|
|
500
500
|
|
|
501
|
-
// Definition-time: Generate additional
|
|
501
|
+
// Definition-time: Generate additional tables from attached source tables
|
|
502
502
|
onTypeLoaded(context) {
|
|
503
503
|
return { types: { derived: createDerivedType(context.type) } };
|
|
504
504
|
},
|
|
505
505
|
|
|
506
|
-
// Generation-time: Generate output files from all finalized
|
|
506
|
+
// Generation-time: Generate output files from all finalized tables
|
|
507
507
|
onTailorDBReady(ctx) {
|
|
508
508
|
const allTypes = ctx.tailordb.flatMap((ns) => Object.values(ns.types).map((t) => t.name));
|
|
509
509
|
return {
|
|
@@ -539,7 +539,7 @@ const plugin: Plugin<MyTypeConfig, MyPluginConfig> = {
|
|
|
539
539
|
};
|
|
540
540
|
```
|
|
541
541
|
|
|
542
|
-
### Per-
|
|
542
|
+
### Per-table `.plugin()` type safety (declaration merging)
|
|
543
543
|
|
|
544
544
|
To enable type checking when users attach plugins via `.plugin()`, provide a declaration merge
|
|
545
545
|
for the `PluginConfigs` interface. Plugin authors should ship this in their package's type definitions:
|
|
@@ -556,7 +556,7 @@ declare module "@tailor-platform/sdk" {
|
|
|
556
556
|
}
|
|
557
557
|
```
|
|
558
558
|
|
|
559
|
-
The `Fields` type parameter provides field names from the
|
|
559
|
+
The `Fields` type parameter provides field names from the table being configured, enabling field-aware configurations:
|
|
560
560
|
|
|
561
561
|
```typescript
|
|
562
562
|
declare module "@tailor-platform/sdk" {
|
package/docs/plugin/index.md
CHANGED
|
@@ -2,15 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
> **Beta Feature**: The plugin system is currently in beta. APIs may change in future releases.
|
|
4
4
|
|
|
5
|
-
Plugins extend TailorDB
|
|
5
|
+
Plugins extend TailorDB tables by automatically generating additional tables, executors, and output files based on your table definitions.
|
|
6
6
|
|
|
7
7
|
## Overview
|
|
8
8
|
|
|
9
9
|
When you run `tailor generate`, the SDK:
|
|
10
10
|
|
|
11
|
-
1. Loads all TailorDB
|
|
12
|
-
2. Passes each
|
|
13
|
-
3. Generates additional
|
|
11
|
+
1. Loads all TailorDB tables with plugin attachments
|
|
12
|
+
2. Passes each table to the attached plugins
|
|
13
|
+
3. Generates additional tables and executors based on plugin output
|
|
14
14
|
4. Writes all generated files to the appropriate locations
|
|
15
15
|
|
|
16
16
|
This enables plugins to create derived functionality based on your application's schema.
|
|
@@ -35,9 +35,9 @@ export default defineConfig({
|
|
|
35
35
|
|
|
36
36
|
**Important**: The `plugins` export must be a named export (not default).
|
|
37
37
|
|
|
38
|
-
### Attaching Plugins to
|
|
38
|
+
### Attaching Plugins to Tables
|
|
39
39
|
|
|
40
|
-
Use the `.plugin()` method to attach plugins to specific
|
|
40
|
+
Use the `.plugin()` method to attach plugins to specific tables:
|
|
41
41
|
|
|
42
42
|
```typescript
|
|
43
43
|
import { db } from "@tailor-platform/sdk";
|
|
@@ -54,7 +54,7 @@ export const user = db
|
|
|
54
54
|
|
|
55
55
|
### Plugin Configuration
|
|
56
56
|
|
|
57
|
-
Some plugins accept per-
|
|
57
|
+
Some plugins accept per-table configuration:
|
|
58
58
|
|
|
59
59
|
```typescript
|
|
60
60
|
export const customer = db
|
|
@@ -70,9 +70,9 @@ export const customer = db
|
|
|
70
70
|
});
|
|
71
71
|
```
|
|
72
72
|
|
|
73
|
-
### Per-
|
|
73
|
+
### Per-table Config Requirement
|
|
74
74
|
|
|
75
|
-
Per-
|
|
75
|
+
Per-table config is optional by default. Plugin authors can change this with
|
|
76
76
|
`typeConfigRequired` (boolean or function). When a function is used, it receives
|
|
77
77
|
the plugin-level config from `definePlugins()`.
|
|
78
78
|
|
|
@@ -97,9 +97,9 @@ export const plugins = definePlugins(
|
|
|
97
97
|
|
|
98
98
|
Plugins can generate:
|
|
99
99
|
|
|
100
|
-
- **
|
|
100
|
+
- **Tables**: Additional TailorDB tables (e.g., `CustomerHistory`, `Deleted_Customer`)
|
|
101
101
|
- **Executors**: Event handlers triggered by record changes
|
|
102
|
-
- **Field Extensions**: Additional fields added to the source
|
|
102
|
+
- **Field Extensions**: Additional fields added to the source table
|
|
103
103
|
- **Output Files**: TypeScript code and other files via generation-time hooks
|
|
104
104
|
|
|
105
105
|
Generated files are placed under `.tailor/<plugin-id>/` (the plugin ID is sanitized,
|
|
@@ -115,13 +115,13 @@ Plugins have 5 hooks across two lifecycle phases. Each hook fires at a specific
|
|
|
115
115
|
```
|
|
116
116
|
tailor generate
|
|
117
117
|
│
|
|
118
|
-
├─ Load TailorDB
|
|
119
|
-
│ ├─ onTypeLoaded ← per
|
|
118
|
+
├─ Load TailorDB tables
|
|
119
|
+
│ ├─ onTypeLoaded ← per table with .plugin() attached
|
|
120
120
|
│ └─ onNamespaceLoaded ← once per namespace (namespace plugins)
|
|
121
121
|
│
|
|
122
122
|
├─ Resolve Auth
|
|
123
123
|
│
|
|
124
|
-
├─ onTailorDBReady ← all
|
|
124
|
+
├─ onTailorDBReady ← all tables finalized
|
|
125
125
|
│
|
|
126
126
|
├─ Load Resolvers
|
|
127
127
|
│
|
|
@@ -134,20 +134,20 @@ tailor generate
|
|
|
134
134
|
|
|
135
135
|
### Definition-time hooks
|
|
136
136
|
|
|
137
|
-
| Hook | Trigger
|
|
138
|
-
| ------------------- |
|
|
139
|
-
| `onTypeLoaded` | Each
|
|
140
|
-
| `onNamespaceLoaded` | Once per namespace
|
|
137
|
+
| Hook | Trigger | Can do |
|
|
138
|
+
| ------------------- | ------------------------------------ | ----------------------------------------------------------------- |
|
|
139
|
+
| `onTypeLoaded` | Each table with `.plugin()` attached | Generate tables, resolvers, executors; extend source table fields |
|
|
140
|
+
| `onNamespaceLoaded` | Once per namespace | Generate tables, resolvers, executors |
|
|
141
141
|
|
|
142
|
-
These hooks produce TailorDB
|
|
142
|
+
These hooks produce TailorDB tables, resolvers, and executors that become part of the application. Requires `importPath` on the plugin.
|
|
143
143
|
|
|
144
144
|
### Generation-time hooks
|
|
145
145
|
|
|
146
|
-
| Hook | Available data
|
|
147
|
-
| ----------------- |
|
|
148
|
-
| `onTailorDBReady` | TailorDB
|
|
149
|
-
| `onResolverReady` | TailorDB
|
|
150
|
-
| `onExecutorReady` | TailorDB
|
|
146
|
+
| Hook | Available data | Can do |
|
|
147
|
+
| ----------------- | ------------------------------------------- | ------------------ |
|
|
148
|
+
| `onTailorDBReady` | TailorDB tables, Auth | Write output files |
|
|
149
|
+
| `onResolverReady` | TailorDB tables, Resolvers, Auth | Write output files |
|
|
150
|
+
| `onExecutorReady` | TailorDB tables, Resolvers, Executors, Auth | Write output files |
|
|
151
151
|
|
|
152
152
|
These hooks receive all finalized data and produce output files (TypeScript code, etc.). No `importPath` required.
|
|
153
153
|
|
package/docs/services/auth.md
CHANGED
|
@@ -6,7 +6,7 @@ Auth is a service for configuring authentication and authorization in your Tailo
|
|
|
6
6
|
|
|
7
7
|
Auth provides:
|
|
8
8
|
|
|
9
|
-
- User profile mapping to TailorDB
|
|
9
|
+
- User profile mapping to TailorDB tables
|
|
10
10
|
- Machine users for service-to-service authentication
|
|
11
11
|
- OAuth 2.0 client configuration
|
|
12
12
|
- Identity provider integration
|
|
@@ -68,11 +68,11 @@ export default defineConfig({
|
|
|
68
68
|
|
|
69
69
|
## User Profile
|
|
70
70
|
|
|
71
|
-
Maps authenticated identities to a TailorDB
|
|
71
|
+
Maps authenticated identities to a TailorDB table:
|
|
72
72
|
|
|
73
73
|
```typescript
|
|
74
74
|
userProfile: {
|
|
75
|
-
type: user, // TailorDB
|
|
75
|
+
type: user, // TailorDB table for user records
|
|
76
76
|
usernameField: "email", // Field used as username (must be unique)
|
|
77
77
|
attributes: {
|
|
78
78
|
role: true, // Enable 'role' as a user attribute
|
|
@@ -80,7 +80,7 @@ userProfile: {
|
|
|
80
80
|
},
|
|
81
81
|
```
|
|
82
82
|
|
|
83
|
-
Example TailorDB
|
|
83
|
+
Example TailorDB table for user profile:
|
|
84
84
|
|
|
85
85
|
```typescript
|
|
86
86
|
// tailordb/user.ts
|
|
@@ -93,9 +93,9 @@ export const user = db.table("User", {
|
|
|
93
93
|
});
|
|
94
94
|
```
|
|
95
95
|
|
|
96
|
-
**type**: The TailorDB
|
|
96
|
+
**type**: The TailorDB table that stores user records.
|
|
97
97
|
|
|
98
|
-
**namespace** (optional): The TailorDB namespace where the user
|
|
98
|
+
**namespace** (optional): The TailorDB namespace where the user table is defined. Usually auto-resolved from your `db` configuration, so you don't need to specify it. Required only when multiple TailorDB namespaces exist and the table lives in an external TailorDB:
|
|
99
99
|
|
|
100
100
|
```typescript
|
|
101
101
|
userProfile: {
|
|
@@ -105,9 +105,9 @@ userProfile: {
|
|
|
105
105
|
},
|
|
106
106
|
```
|
|
107
107
|
|
|
108
|
-
**usernameField**: The field in the TailorDB
|
|
108
|
+
**usernameField**: The field in the TailorDB table used as the username. This field must have a unique constraint (`.unique()`) since it is used to uniquely identify users.
|
|
109
109
|
|
|
110
|
-
**attributes**: Specifies which fields from the TailorDB
|
|
110
|
+
**attributes**: Specifies which fields from the TailorDB table are used as user attributes. Set to `true` to enable a field. Machine user definitions must assign values to attributes derived from required fields; attributes derived from optional fields may be omitted (see [Machine Users](#machine-users)). Only fields with ValueOperand types (string, boolean, string[], boolean[]) can be used as attributes. The `id` field and datetime/date/time types are excluded.
|
|
111
111
|
|
|
112
112
|
## Attribute List
|
|
113
113
|
|
|
@@ -122,9 +122,9 @@ userProfile: {
|
|
|
122
122
|
},
|
|
123
123
|
```
|
|
124
124
|
|
|
125
|
-
**attributeList**: An array of field names from the TailorDB
|
|
125
|
+
**attributeList**: An array of field names from the TailorDB table. These fields will be exposed as an ordered list of UUIDs. Only UUID-type fields (non-array) can be included in the attribute list.
|
|
126
126
|
|
|
127
|
-
Example TailorDB
|
|
127
|
+
Example TailorDB table with UUID fields for attribute list:
|
|
128
128
|
|
|
129
129
|
```typescript
|
|
130
130
|
// tailordb/user.ts
|
|
@@ -406,7 +406,7 @@ interface RecordCreatedContext<T> {
|
|
|
406
406
|
rawEvent: "tailordb.type_record.created"; // Full event type string
|
|
407
407
|
workspaceId: string; // Workspace identifier
|
|
408
408
|
appNamespace: string; // Application/namespace name
|
|
409
|
-
typeName: string; // TailorDB
|
|
409
|
+
typeName: string; // TailorDB table name
|
|
410
410
|
newRecord: T; // The newly created record
|
|
411
411
|
}
|
|
412
412
|
```
|
|
@@ -150,11 +150,11 @@ createResolver({
|
|
|
150
150
|
|
|
151
151
|
This is useful when the same logical type appears in multiple resolvers or when you want a predictable, human-readable name in the generated GraphQL schema.
|
|
152
152
|
|
|
153
|
-
**Warning:** Do not set `typeName` to an existing TailorDB
|
|
153
|
+
**Warning:** Do not set `typeName` to an existing TailorDB table name on an `object()` that contains enum or nested fields. Child fields without an explicit `typeName` auto-generate names using `{parentTypeName}{FieldName}`, which can collide with the TailorDB table's own enum/nested type names.
|
|
154
154
|
|
|
155
155
|
```typescript
|
|
156
156
|
// Collision — "Item" + "status" auto-generates "ItemStatus",
|
|
157
|
-
// which collides with the TailorDB Item
|
|
157
|
+
// which collides with the TailorDB Item table's status enum
|
|
158
158
|
output: t
|
|
159
159
|
.object({
|
|
160
160
|
id: t.uuid(),
|