@tailor-platform/sdk 0.16.3 → 0.18.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 +29 -0
- package/README.md +75 -8
- package/dist/cli/api.d.mts +35 -31
- package/dist/cli/api.mjs +2 -2
- package/dist/cli/api.mjs.map +1 -1
- package/dist/cli/index.mjs +51 -75
- package/dist/cli/index.mjs.map +1 -1
- package/dist/configure/index.d.mts +3 -3
- package/dist/{index-Bin7-j3v.d.mts → index-BWqIQ4iC.d.mts} +2 -2
- package/dist/job-CL8myeqs.mjs.map +1 -1
- package/dist/{resume-kyHIaNvK.mjs → resume-ChDChtAZ.mjs} +200 -137
- package/dist/{resume-kyHIaNvK.mjs.map → resume-ChDChtAZ.mjs.map} +1 -1
- package/dist/{types-Da_WnvA0.d.mts → types-DgaCdTug.d.mts} +21 -13
- package/dist/utils/test/index.d.mts +9 -3
- package/dist/utils/test/index.mjs +8 -6
- package/dist/utils/test/index.mjs.map +1 -1
- package/docs/cli/application.md +136 -0
- package/docs/cli/auth.md +110 -0
- package/docs/cli/secret.md +125 -0
- package/docs/cli/user.md +183 -0
- package/docs/cli/workflow.md +144 -0
- package/docs/cli/workspace.md +122 -0
- package/docs/cli-reference.md +80 -801
- package/docs/configuration.md +62 -32
- package/docs/generator/builtin.md +194 -0
- package/docs/generator/custom.md +150 -0
- package/docs/generator/index.md +56 -0
- package/docs/quickstart.md +9 -4
- package/docs/services/auth.md +244 -0
- package/docs/services/executor.md +304 -0
- package/docs/services/idp.md +106 -0
- package/docs/services/resolver.md +213 -0
- package/docs/services/secret.md +116 -0
- package/docs/services/staticwebsite.md +132 -0
- package/docs/services/tailordb.md +325 -0
- package/docs/services/workflow.md +176 -0
- package/docs/testing.md +3 -1
- package/package.json +9 -8
- package/docs/core-concepts.md +0 -609
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
# Auth
|
|
2
|
+
|
|
3
|
+
Auth is a service for configuring authentication and authorization in your Tailor Platform application.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
Auth provides:
|
|
8
|
+
|
|
9
|
+
- User profile mapping to TailorDB types
|
|
10
|
+
- Machine users for service-to-service authentication
|
|
11
|
+
- OAuth 2.0 client configuration
|
|
12
|
+
- Identity provider integration
|
|
13
|
+
|
|
14
|
+
For the official Tailor Platform documentation, see [Auth Guide](https://docs.tailor.tech/guides/auth/overview).
|
|
15
|
+
|
|
16
|
+
## Configuration
|
|
17
|
+
|
|
18
|
+
Configure Auth service using `defineAuth()`:
|
|
19
|
+
|
|
20
|
+
```typescript
|
|
21
|
+
import { defineAuth } from "@tailor-platform/sdk";
|
|
22
|
+
import { user } from "./tailordb/user";
|
|
23
|
+
|
|
24
|
+
const auth = defineAuth("my-auth", {
|
|
25
|
+
userProfile: {
|
|
26
|
+
type: user,
|
|
27
|
+
usernameField: "email",
|
|
28
|
+
attributes: { role: true },
|
|
29
|
+
},
|
|
30
|
+
machineUsers: {
|
|
31
|
+
"admin-machine-user": {
|
|
32
|
+
attributes: { role: "ADMIN" },
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
oauth2Clients: {
|
|
36
|
+
"my-oauth2-client": {
|
|
37
|
+
redirectURIs: ["https://example.com/callback"],
|
|
38
|
+
grantTypes: ["authorization_code", "refresh_token"],
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
idProvider: idp.provider("my-provider", "my-client"),
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
export default defineConfig({
|
|
45
|
+
auth,
|
|
46
|
+
});
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## User Profile
|
|
50
|
+
|
|
51
|
+
Maps authenticated identities to a TailorDB type:
|
|
52
|
+
|
|
53
|
+
```typescript
|
|
54
|
+
userProfile: {
|
|
55
|
+
type: user, // TailorDB type for user records
|
|
56
|
+
usernameField: "email", // Field used as username (must be unique)
|
|
57
|
+
attributes: {
|
|
58
|
+
role: true, // Enable 'role' as a user attribute
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Example TailorDB type for user profile:
|
|
64
|
+
|
|
65
|
+
```typescript
|
|
66
|
+
// tailordb/user.ts
|
|
67
|
+
import { db } from "@tailor-platform/sdk";
|
|
68
|
+
|
|
69
|
+
export const user = db.type("User", {
|
|
70
|
+
email: db.string().unique(), // usernameField must have unique constraint
|
|
71
|
+
role: db.enum(["admin", "user"]),
|
|
72
|
+
...db.fields.timestamps(),
|
|
73
|
+
});
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
**type**: The TailorDB type that stores user records.
|
|
77
|
+
|
|
78
|
+
**usernameField**: The field in the TailorDB type used as the username. This field must have a unique constraint (`.unique()`) since it is used to uniquely identify users.
|
|
79
|
+
|
|
80
|
+
**attributes**: Specifies which fields from the TailorDB type are used as user attributes. Set to `true` to enable a field. Enabled attributes must be assigned values in all machine user definitions.
|
|
81
|
+
|
|
82
|
+
## Machine Users
|
|
83
|
+
|
|
84
|
+
Service accounts for automated access without user interaction:
|
|
85
|
+
|
|
86
|
+
```typescript
|
|
87
|
+
machineUsers: {
|
|
88
|
+
"admin-machine-user": {
|
|
89
|
+
attributes: { role: "ADMIN" },
|
|
90
|
+
},
|
|
91
|
+
"readonly-machine-user": {
|
|
92
|
+
attributes: { role: "READER" },
|
|
93
|
+
},
|
|
94
|
+
},
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
**attributes**: Values for attributes enabled in `userProfile.attributes`. All fields marked as `true` in `userProfile.attributes` must be set here. These values are accessible via `user.attributes`:
|
|
98
|
+
|
|
99
|
+
```typescript
|
|
100
|
+
// In a resolver
|
|
101
|
+
body: (context) => {
|
|
102
|
+
const role = context.user.attributes?.role;
|
|
103
|
+
},
|
|
104
|
+
|
|
105
|
+
// In TailorDB hooks
|
|
106
|
+
.hooks({
|
|
107
|
+
field: {
|
|
108
|
+
create: ({ user }) => user.attributes?.role === "ADMIN" ? "default" : null,
|
|
109
|
+
},
|
|
110
|
+
})
|
|
111
|
+
|
|
112
|
+
// In TailorDB validate
|
|
113
|
+
.validate({
|
|
114
|
+
field: [
|
|
115
|
+
({ user }) => user.attributes?.role === "ADMIN",
|
|
116
|
+
"Only admins can set this field",
|
|
117
|
+
],
|
|
118
|
+
})
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
Machine users are useful for:
|
|
122
|
+
|
|
123
|
+
- CI/CD pipelines
|
|
124
|
+
- Background jobs
|
|
125
|
+
- Service-to-service communication
|
|
126
|
+
- E2E testing
|
|
127
|
+
|
|
128
|
+
Get a machine user token using the CLI:
|
|
129
|
+
|
|
130
|
+
```bash
|
|
131
|
+
tailor-sdk machineuser token <name>
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
### Using auth.invoker()
|
|
135
|
+
|
|
136
|
+
The `auth.invoker()` method creates a type-safe reference to a machine user for use in workflow triggers. This specifies which machine user's permissions should be used when executing the workflow.
|
|
137
|
+
|
|
138
|
+
```typescript
|
|
139
|
+
// tailor.config.ts
|
|
140
|
+
export const auth = defineAuth("my-auth", {
|
|
141
|
+
machineUsers: {
|
|
142
|
+
"admin-machine-user": {
|
|
143
|
+
attributes: { role: "ADMIN" },
|
|
144
|
+
},
|
|
145
|
+
},
|
|
146
|
+
// ... other config
|
|
147
|
+
});
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
```typescript
|
|
151
|
+
// resolvers/trigger-workflow.ts
|
|
152
|
+
import { createResolver, t } from "@tailor-platform/sdk";
|
|
153
|
+
import { auth } from "../tailor.config";
|
|
154
|
+
import myWorkflow from "../workflows/my-workflow";
|
|
155
|
+
|
|
156
|
+
export default createResolver({
|
|
157
|
+
name: "triggerMyWorkflow",
|
|
158
|
+
operation: "mutation",
|
|
159
|
+
input: {
|
|
160
|
+
id: t.string(),
|
|
161
|
+
},
|
|
162
|
+
body: async ({ input }) => {
|
|
163
|
+
// Trigger workflow with machine user permissions
|
|
164
|
+
const workflowRunId = await myWorkflow.trigger(
|
|
165
|
+
{ id: input.id },
|
|
166
|
+
{ authInvoker: auth.invoker("admin-machine-user") },
|
|
167
|
+
);
|
|
168
|
+
return { workflowRunId };
|
|
169
|
+
},
|
|
170
|
+
output: t.object({
|
|
171
|
+
workflowRunId: t.string(),
|
|
172
|
+
}),
|
|
173
|
+
});
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
The `invoker()` method is type-safe and only accepts machine user names defined in the auth configuration.
|
|
177
|
+
|
|
178
|
+
## OAuth 2.0 Clients
|
|
179
|
+
|
|
180
|
+
Configure OAuth 2.0 clients for third-party applications:
|
|
181
|
+
|
|
182
|
+
```typescript
|
|
183
|
+
oauth2Clients: {
|
|
184
|
+
"my-oauth2-client": {
|
|
185
|
+
redirectURIs: [
|
|
186
|
+
"https://example.com/callback",
|
|
187
|
+
`${website.url}/callback`, // Type-safe URL from StaticWebsite
|
|
188
|
+
],
|
|
189
|
+
description: "My OAuth2 client",
|
|
190
|
+
grantTypes: ["authorization_code", "refresh_token"],
|
|
191
|
+
accessTokenLifetimeSeconds: 3600, // 1 hour
|
|
192
|
+
refreshTokenLifetimeSeconds: 604800, // 7 days
|
|
193
|
+
},
|
|
194
|
+
},
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
**redirectURIs**: Allowed redirect URIs after authentication.
|
|
198
|
+
|
|
199
|
+
**description**: Optional description of the client.
|
|
200
|
+
|
|
201
|
+
**grantTypes**: Supported OAuth 2.0 grant types:
|
|
202
|
+
|
|
203
|
+
- `authorization_code` - Standard OAuth 2.0 authorization code flow
|
|
204
|
+
- `refresh_token` - Allow refreshing access tokens
|
|
205
|
+
|
|
206
|
+
**accessTokenLifetimeSeconds**: Optional access token lifetime in seconds. Minimum: 60 seconds, Maximum: 86400 seconds (1 day). If not specified, uses platform default.
|
|
207
|
+
|
|
208
|
+
**refreshTokenLifetimeSeconds**: Optional refresh token lifetime in seconds. Minimum: 60 seconds, Maximum: 604800 seconds (7 days). If not specified, uses platform default.
|
|
209
|
+
|
|
210
|
+
Get OAuth2 client credentials using the CLI:
|
|
211
|
+
|
|
212
|
+
```bash
|
|
213
|
+
tailor-sdk oauth2client get <name>
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
## Identity Provider
|
|
217
|
+
|
|
218
|
+
Connect to an external identity provider:
|
|
219
|
+
|
|
220
|
+
```typescript
|
|
221
|
+
idProvider: idp.provider("my-provider", "my-client"),
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
See [IdP](./idp.md) for configuring identity providers.
|
|
225
|
+
|
|
226
|
+
## CLI Commands
|
|
227
|
+
|
|
228
|
+
Manage Auth resources using the CLI:
|
|
229
|
+
|
|
230
|
+
```bash
|
|
231
|
+
# List machine users
|
|
232
|
+
tailor-sdk machineuser list
|
|
233
|
+
|
|
234
|
+
# Get machine user token
|
|
235
|
+
tailor-sdk machineuser token <name>
|
|
236
|
+
|
|
237
|
+
# List OAuth2 clients
|
|
238
|
+
tailor-sdk oauth2client list
|
|
239
|
+
|
|
240
|
+
# Get OAuth2 client credentials
|
|
241
|
+
tailor-sdk oauth2client get <name>
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
See [Auth Resource Commands](../cli/auth.md) for full documentation.
|
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
# Executor
|
|
2
|
+
|
|
3
|
+
Executors are event-driven handlers that automatically trigger in response to data changes, schedules, or external events.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
Executors provide:
|
|
8
|
+
|
|
9
|
+
- Automatic triggers on record changes (create, update, delete)
|
|
10
|
+
- Scheduled execution via cron expressions
|
|
11
|
+
- Incoming webhook handlers
|
|
12
|
+
- Post-resolver execution hooks
|
|
13
|
+
- Multiple execution targets (functions, webhooks, GraphQL)
|
|
14
|
+
|
|
15
|
+
For the official Tailor Platform documentation, see [Executor Guide](https://docs.tailor.tech/guides/executor/overview).
|
|
16
|
+
|
|
17
|
+
## Creating an Executor
|
|
18
|
+
|
|
19
|
+
Define executors in files matching glob patterns specified in `tailor.config.ts`.
|
|
20
|
+
|
|
21
|
+
```typescript
|
|
22
|
+
import { createExecutor, recordCreatedTrigger, t } from "@tailor-platform/sdk";
|
|
23
|
+
import { user } from "../tailordb/user";
|
|
24
|
+
|
|
25
|
+
export default createExecutor({
|
|
26
|
+
name: "user-welcome",
|
|
27
|
+
description: "Send welcome email to new users",
|
|
28
|
+
trigger: recordCreatedTrigger({
|
|
29
|
+
type: user,
|
|
30
|
+
condition: ({ newRecord }) => !!newRecord.email && newRecord.isActive,
|
|
31
|
+
}),
|
|
32
|
+
operation: {
|
|
33
|
+
kind: "function",
|
|
34
|
+
body: async ({ newRecord }) => {
|
|
35
|
+
// Send welcome email logic here
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
});
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Trigger Types
|
|
42
|
+
|
|
43
|
+
### Record Triggers
|
|
44
|
+
|
|
45
|
+
Fire when records are created, updated, or deleted:
|
|
46
|
+
|
|
47
|
+
- `recordCreatedTrigger()`: Fires when a new record is created
|
|
48
|
+
- `recordUpdatedTrigger()`: Fires when a record is updated
|
|
49
|
+
- `recordDeletedTrigger()`: Fires when a record is deleted
|
|
50
|
+
|
|
51
|
+
Each trigger can include an optional filter function:
|
|
52
|
+
|
|
53
|
+
```typescript
|
|
54
|
+
recordUpdatedTrigger({
|
|
55
|
+
type: order,
|
|
56
|
+
condition: ({ newRecord, oldRecord }) =>
|
|
57
|
+
newRecord.status === "completed" && oldRecord.status !== "completed",
|
|
58
|
+
});
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### Schedule Trigger
|
|
62
|
+
|
|
63
|
+
Fires on a cron schedule:
|
|
64
|
+
|
|
65
|
+
```typescript
|
|
66
|
+
scheduleTrigger({ cron: "*/5 * * * *" }); // Every 5 minutes
|
|
67
|
+
scheduleTrigger({ cron: "0 9 * * 1" }); // Every Monday at 9am
|
|
68
|
+
scheduleTrigger({ cron: "0 0 1 * *" }); // First day of every month
|
|
69
|
+
scheduleTrigger({ cron: "0 * * * *", timezone: "Asia/Tokyo" });
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### Incoming Webhook Trigger
|
|
73
|
+
|
|
74
|
+
Fires when an external webhook is received:
|
|
75
|
+
|
|
76
|
+
```typescript
|
|
77
|
+
incomingWebhookTrigger<WebhookPayload>();
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### Resolver Executed Trigger
|
|
81
|
+
|
|
82
|
+
Fires when a resolver is executed:
|
|
83
|
+
|
|
84
|
+
```typescript
|
|
85
|
+
resolverExecutedTrigger({
|
|
86
|
+
resolver: createOrderResolver,
|
|
87
|
+
condition: ({ result, error }) => !error && result?.order?.id,
|
|
88
|
+
});
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## Execution Targets
|
|
92
|
+
|
|
93
|
+
### Function Execution
|
|
94
|
+
|
|
95
|
+
Execute JavaScript/TypeScript functions:
|
|
96
|
+
|
|
97
|
+
```typescript
|
|
98
|
+
createExecutor({
|
|
99
|
+
operation: {
|
|
100
|
+
kind: "function",
|
|
101
|
+
body: async ({ newRecord }) => {
|
|
102
|
+
console.log("New record created:", newRecord);
|
|
103
|
+
},
|
|
104
|
+
},
|
|
105
|
+
});
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### Webhook Execution
|
|
109
|
+
|
|
110
|
+
Call external webhooks with dynamic data:
|
|
111
|
+
|
|
112
|
+
```typescript
|
|
113
|
+
createExecutor({
|
|
114
|
+
operation: {
|
|
115
|
+
kind: "webhook",
|
|
116
|
+
url: ({ newRecord }) =>
|
|
117
|
+
`https://api.example.com/webhooks/${newRecord.type}`,
|
|
118
|
+
headers: {
|
|
119
|
+
"Content-Type": "application/json",
|
|
120
|
+
"X-API-Key": { vault: "api-keys", key: "external-api" },
|
|
121
|
+
},
|
|
122
|
+
requestBody: ({ newRecord }) => ({
|
|
123
|
+
id: newRecord.id,
|
|
124
|
+
timestamp: new Date(),
|
|
125
|
+
data: newRecord,
|
|
126
|
+
}),
|
|
127
|
+
},
|
|
128
|
+
});
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### GraphQL Execution
|
|
132
|
+
|
|
133
|
+
Execute GraphQL queries and mutations:
|
|
134
|
+
|
|
135
|
+
```typescript
|
|
136
|
+
import { gql } from "@tailor-platform/sdk";
|
|
137
|
+
|
|
138
|
+
createExecutor({
|
|
139
|
+
operation: {
|
|
140
|
+
kind: "graphql",
|
|
141
|
+
appName: "my-app",
|
|
142
|
+
query: gql`
|
|
143
|
+
mutation UpdateUserStatus($id: ID!, $status: String!) {
|
|
144
|
+
updateUser(id: $id, input: { status: $status }) {
|
|
145
|
+
id
|
|
146
|
+
status
|
|
147
|
+
updatedAt
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
`,
|
|
151
|
+
variables: ({ newRecord }) => ({
|
|
152
|
+
id: newRecord.userId,
|
|
153
|
+
status: "active",
|
|
154
|
+
}),
|
|
155
|
+
},
|
|
156
|
+
});
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
## Event Payloads
|
|
160
|
+
|
|
161
|
+
Each trigger type provides specific context data in the callback functions.
|
|
162
|
+
|
|
163
|
+
### Record Event Payloads
|
|
164
|
+
|
|
165
|
+
Record triggers receive context based on the operation type:
|
|
166
|
+
|
|
167
|
+
#### Created Event
|
|
168
|
+
|
|
169
|
+
```typescript
|
|
170
|
+
interface RecordCreatedContext<T> {
|
|
171
|
+
workspaceId: string; // Workspace identifier
|
|
172
|
+
namespaceName: string; // Application/namespace name
|
|
173
|
+
typeName: string; // TailorDB type name
|
|
174
|
+
newRecord: T; // The newly created record
|
|
175
|
+
}
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
#### Updated Event
|
|
179
|
+
|
|
180
|
+
```typescript
|
|
181
|
+
interface RecordUpdatedContext<T> {
|
|
182
|
+
workspaceId: string;
|
|
183
|
+
namespaceName: string;
|
|
184
|
+
typeName: string;
|
|
185
|
+
oldRecord: T; // Previous record state
|
|
186
|
+
newRecord: T; // Current record state
|
|
187
|
+
}
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
#### Deleted Event
|
|
191
|
+
|
|
192
|
+
```typescript
|
|
193
|
+
interface RecordDeletedContext<T> {
|
|
194
|
+
workspaceId: string;
|
|
195
|
+
namespaceName: string;
|
|
196
|
+
typeName: string;
|
|
197
|
+
oldRecord: T; // The deleted record
|
|
198
|
+
}
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
**Usage Example:**
|
|
202
|
+
|
|
203
|
+
```typescript
|
|
204
|
+
import { createExecutor, recordUpdatedTrigger, t } from "@tailor-platform/sdk";
|
|
205
|
+
import { order } from "../tailordb/order";
|
|
206
|
+
|
|
207
|
+
export default createExecutor({
|
|
208
|
+
name: "order-status-changed",
|
|
209
|
+
trigger: recordUpdatedTrigger({
|
|
210
|
+
type: order,
|
|
211
|
+
condition: ({ oldRecord, newRecord }) =>
|
|
212
|
+
oldRecord.status !== newRecord.status,
|
|
213
|
+
}),
|
|
214
|
+
operation: {
|
|
215
|
+
kind: "function",
|
|
216
|
+
body: async ({ oldRecord, newRecord, typeName }) => {
|
|
217
|
+
console.log(`${typeName} status changed:`);
|
|
218
|
+
console.log(` From: ${oldRecord.status}`);
|
|
219
|
+
console.log(` To: ${newRecord.status}`);
|
|
220
|
+
},
|
|
221
|
+
},
|
|
222
|
+
});
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
### Schedule Event Payload
|
|
226
|
+
|
|
227
|
+
Schedule triggers receive minimal context:
|
|
228
|
+
|
|
229
|
+
```typescript
|
|
230
|
+
interface ScheduleContext {
|
|
231
|
+
scheduledTime: string; // ISO 8601 timestamp
|
|
232
|
+
}
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
### Incoming Webhook Payload
|
|
236
|
+
|
|
237
|
+
Webhook triggers receive HTTP request data:
|
|
238
|
+
|
|
239
|
+
```typescript
|
|
240
|
+
interface WebhookContext<T = unknown> {
|
|
241
|
+
body: T; // Parsed request body
|
|
242
|
+
headers: Record<string, string>; // Request headers
|
|
243
|
+
method: string; // HTTP method (POST, etc.)
|
|
244
|
+
rawBody: string; // Raw request body as string
|
|
245
|
+
}
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
**Usage Example:**
|
|
249
|
+
|
|
250
|
+
```typescript
|
|
251
|
+
import { createExecutor, incomingWebhookTrigger } from "@tailor-platform/sdk";
|
|
252
|
+
|
|
253
|
+
interface StripeWebhook {
|
|
254
|
+
type: string;
|
|
255
|
+
data: { object: { id: string; amount: number } };
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
export default createExecutor({
|
|
259
|
+
name: "stripe-webhook",
|
|
260
|
+
trigger: incomingWebhookTrigger<StripeWebhook>(),
|
|
261
|
+
operation: {
|
|
262
|
+
kind: "function",
|
|
263
|
+
body: async ({ body, headers }) => {
|
|
264
|
+
const signature = headers["stripe-signature"];
|
|
265
|
+
console.log(`Received ${body.type} event`);
|
|
266
|
+
// Process webhook...
|
|
267
|
+
},
|
|
268
|
+
},
|
|
269
|
+
});
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
### Resolver Executed Payload
|
|
273
|
+
|
|
274
|
+
Resolver triggers receive the resolver's result or error:
|
|
275
|
+
|
|
276
|
+
```typescript
|
|
277
|
+
interface ResolverExecutedContext<TResult> {
|
|
278
|
+
resolverName: string; // Name of the executed resolver
|
|
279
|
+
result?: TResult; // Return value (on success)
|
|
280
|
+
error?: Error; // Error object (on failure)
|
|
281
|
+
}
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
**Usage Example:**
|
|
285
|
+
|
|
286
|
+
```typescript
|
|
287
|
+
import { createExecutor, resolverExecutedTrigger } from "@tailor-platform/sdk";
|
|
288
|
+
import { createOrderResolver } from "../resolvers/create-order";
|
|
289
|
+
|
|
290
|
+
export default createExecutor({
|
|
291
|
+
name: "order-created-notification",
|
|
292
|
+
trigger: resolverExecutedTrigger({
|
|
293
|
+
resolver: createOrderResolver,
|
|
294
|
+
condition: ({ result, error }) => !error && !!result?.order,
|
|
295
|
+
}),
|
|
296
|
+
operation: {
|
|
297
|
+
kind: "function",
|
|
298
|
+
body: async ({ result, resolverName }) => {
|
|
299
|
+
console.log(`${resolverName} completed successfully`);
|
|
300
|
+
console.log(`Order ID: ${result.order.id}`);
|
|
301
|
+
},
|
|
302
|
+
},
|
|
303
|
+
});
|
|
304
|
+
```
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
# IdP (Identity Provider)
|
|
2
|
+
|
|
3
|
+
IdP is a built-in identity provider service for managing user authentication.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
The Built-in IdP provides:
|
|
8
|
+
|
|
9
|
+
- User registration and authentication
|
|
10
|
+
- OAuth client management
|
|
11
|
+
- Integration with Auth service
|
|
12
|
+
|
|
13
|
+
For the official Tailor Platform documentation, see [Identity Provider Setup](https://docs.tailor.tech/tutorials/setup-auth/setup-identity-provider).
|
|
14
|
+
|
|
15
|
+
## Configuration
|
|
16
|
+
|
|
17
|
+
Configure the Built-in IdP using `defineIdp()`:
|
|
18
|
+
|
|
19
|
+
```typescript
|
|
20
|
+
import { defineIdp, defineConfig } from "@tailor-platform/sdk";
|
|
21
|
+
|
|
22
|
+
const idp = defineIdp("my-idp", {
|
|
23
|
+
authorization: "loggedIn",
|
|
24
|
+
clients: ["my-client"],
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
export default defineConfig({
|
|
28
|
+
idp: [idp],
|
|
29
|
+
});
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Options
|
|
33
|
+
|
|
34
|
+
### authorization
|
|
35
|
+
|
|
36
|
+
User management permissions. Controls who can manage users in the IdP.
|
|
37
|
+
|
|
38
|
+
```typescript
|
|
39
|
+
defineIdp("my-idp", {
|
|
40
|
+
authorization: "loggedIn", // Only logged-in users can manage
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
defineIdp("my-idp", {
|
|
44
|
+
authorization: "insecure", // Anyone can manage (development only)
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
defineIdp("my-idp", {
|
|
48
|
+
authorization: "user.role == 'admin'", // CEL expression
|
|
49
|
+
});
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
**Values:**
|
|
53
|
+
|
|
54
|
+
- `"insecure"` - No authentication required (use only for development)
|
|
55
|
+
- `"loggedIn"` - Requires authenticated user
|
|
56
|
+
- CEL expression - Custom authorization logic
|
|
57
|
+
|
|
58
|
+
### clients
|
|
59
|
+
|
|
60
|
+
OAuth client names that can use this IdP:
|
|
61
|
+
|
|
62
|
+
```typescript
|
|
63
|
+
defineIdp("my-idp", {
|
|
64
|
+
clients: ["default-client", "mobile-client"],
|
|
65
|
+
});
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Using idp.provider()
|
|
69
|
+
|
|
70
|
+
The `idp.provider()` method creates a type-safe reference to the IdP for use in Auth configuration. The client name is validated at compile time against the clients defined in the IdP.
|
|
71
|
+
|
|
72
|
+
```typescript
|
|
73
|
+
import { defineIdp, defineAuth, defineConfig } from "@tailor-platform/sdk";
|
|
74
|
+
import { user } from "./tailordb/user";
|
|
75
|
+
|
|
76
|
+
const idp = defineIdp("my-idp", {
|
|
77
|
+
authorization: "loggedIn",
|
|
78
|
+
clients: ["default-client", "mobile-client"],
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
const auth = defineAuth("my-auth", {
|
|
82
|
+
userProfile: {
|
|
83
|
+
type: user,
|
|
84
|
+
usernameField: "email",
|
|
85
|
+
attributes: { role: true },
|
|
86
|
+
},
|
|
87
|
+
// Type-safe: only "default-client" or "mobile-client" are allowed
|
|
88
|
+
idProvider: idp.provider("my-provider", "default-client"),
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
export default defineConfig({
|
|
92
|
+
idp: [idp],
|
|
93
|
+
auth,
|
|
94
|
+
});
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
**Parameters:**
|
|
98
|
+
|
|
99
|
+
```typescript
|
|
100
|
+
idp.provider(
|
|
101
|
+
"provider-name", // Name for the provider reference
|
|
102
|
+
"client-name", // Must be one of the clients defined in the IdP
|
|
103
|
+
);
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
The second argument only accepts client names that were defined in the `clients` array of the IdP configuration.
|