Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions docs/guides/tailordb/versioning.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ This approach preserves historical data and enables change monitoring and analys
## How to enable Data Versioning

1. Create a history table
2. Enable `PublishRecordEvents` settings
2. Enable `publishEvents` feature
3. Add an event based trigger

## Example
Expand Down Expand Up @@ -51,15 +51,15 @@ db.type("StockSummaryHistory", {
});
```

### 2. Enable `PublishRecordEvents` settings
### 2. Enable `publishEvents` feature

By enabling `PublishRecordEvents` in the `StockSummary` settings, you can create an event-based trigger that executes on every `StockSummary` record update.
By enabling `publishEvents` in the `StockSummary` features, you can create an event-based trigger that executes on every `StockSummary` record update.

```typescript
db.type("StockSummary", {
// fields...
}).settings({
publishRecordEvents: true,
}).features({
publishEvents: true,
});
```

Expand Down
4 changes: 2 additions & 2 deletions docs/tutorials/manage-data-schema/create-data-schema.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export const task = db.type("Task", {
.enum(["todo", "in_progress", "completed", "blocked"])
.description("Current task status"),
priority: db.enum(["low", "medium", "high", "urgent"]).description("Task priority level"),
projectId: db.string().foreignKey(project).description("Associated project"),
projectId: db.uuid().relation({ type: "n-1", toward: { type: project } }).description("Associated project"),
assigneeId: db.string().optional().description("ID of assigned team member"),
dueDate: db.string().optional().description("Task due date"),
estimatedHours: db.float().optional().description("Estimated hours to complete"),
Expand All @@ -45,7 +45,7 @@ export type task = typeof task;
- **description**: Optional detailed description
- **status**: Enumeration with predefined status values
- **priority**: Enumeration for priority levels
- **projectId**: Foreign key relationship to the Project type
- **projectId**: Many-to-one relation to the Project type
- **assigneeId**: Optional reference to a team member
- **dueDate**: Optional date field
- **estimatedHours**: Optional float for time estimation
Expand Down
57 changes: 54 additions & 3 deletions docs/tutorials/resolver.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@ export const task = db.type("Task", {
description: db.string().optional().description("Task description"),
status: db.enum(["todo", "in_progress", "completed"]).description("Task status"),
priority: db.enum(["low", "medium", "high"]).description("Task priority"),
projectId: db.string().foreignKey(project).description("Associated project"),
assigneeId: db.string().foreignKey(teamMember).optional().description("Assigned team member"),
projectId: db.uuid().relation({ type: "n-1", toward: { type: project } }).description("Associated project"),
assigneeId: db.uuid().relation({ type: "n-1", toward: { type: teamMember } }).optional().description("Assigned team member"),
dueDate: db.string().optional().description("Due date"),
...db.fields.timestamps(),
});
Expand Down Expand Up @@ -153,7 +153,15 @@ export default createResolver({

## 4. Deploy and Test

Deploy your changes to the workspace:
First, generate Kysely types for type-safe database queries:

```bash
npm run generate
```

This generates TypeScript types and the `getDB()` helper in the `generated/` directory based on your TailorDB schema.

Then deploy your changes to the workspace:

```bash
npm run deploy -- --workspace-id <your-workspace-id>
Expand Down Expand Up @@ -248,6 +256,49 @@ You can view resolver execution logs in the [Console](https://console.tailor.tec

This helps you debug issues and understand how your resolver processes requests.

## Advanced: Triggering Executors from Resolvers

You can configure resolvers to publish events when they execute, allowing executors to trigger automatically after resolver execution. This is useful for post-processing tasks like sending notifications or updating related data.

```typescript
export default createResolver({
name: "assignTask",
operation: "mutation",
publishEvents: true, // Enable event publishing
// ... rest of resolver config
});
```

**How it works:**

- When `publishEvents: true`, the resolver publishes execution events
- Executors can listen for these events using `resolverExecutedTrigger()`
- The SDK **automatically enables** `publishEvents` when an executor references the resolver

**Example executor that triggers after resolver execution:**

```typescript
import { createExecutor, resolverExecutedTrigger } from "@tailor-platform/sdk";
import assignTaskResolver from "../resolver/assign-task";

export default createExecutor({
name: "notify-task-assigned",
trigger: resolverExecutedTrigger({
resolver: assignTaskResolver,
condition: ({ result, error }) => !error && !!result.taskId,
}),
operation: {
kind: "function",
body: async ({ result }) => {
console.log(`Task ${result.taskId} assigned to ${result.assigneeName}`);
// Send notification logic here
},
},
});
```

For more details, see [Executor Service - Resolver Executed Trigger](../sdk/services/executor#resolver-executed-trigger).

## Next Steps

Learn more about resolvers:
Expand Down
165 changes: 80 additions & 85 deletions docs/tutorials/setup-auth/register-identity-provider.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,45 @@ To enable authentication through an identity provider, you need to register it w

### OIDC (OpenID Connect)

Update your `tailor.config.ts` to include the Auth service with OIDC configuration:
First, ensure you have a User type defined in your database schema (e.g., `db/user.ts`):

```typescript
import { defineConfig, t } from "@tailor-platform/sdk";
import { db } from "@tailor-platform/sdk";

export const user = db.type("User", {
email: db.string().unique(), // usernameField must be unique
name: db.string(),
roles: db.array(db.string()).optional(),
...db.fields.timestamps(),
});
```

Then update your `tailor.config.ts` to include the Auth service with OIDC configuration:

```typescript
import { defineAuth, defineConfig } from "@tailor-platform/sdk";
import { user } from "./db/user";

const auth = defineAuth("project-management-auth", {
userProfile: {
type: user,
usernameField: "email",
attributes: {
roles: true,
},
},
idProvider: {
name: "oidc-provider",
oidc: {
clientId: process.env.OIDC_CLIENT_ID!,
clientSecret: {
vaultName: "my-vault",
secretName: "oidc-client-secret",
},
providerUrl: process.env.OIDC_PROVIDER_URL!,
},
},
});

export default defineConfig({
name: "project-management",
Expand All @@ -29,30 +64,7 @@ export default defineConfig({
files: ["db/**/*.ts"],
},
},
auth: {
namespace: "project-management-auth",
idpConfigs: [
{
name: "oidc-provider",
oidc: {
clientId: process.env.OIDC_CLIENT_ID!,
clientSecret: {
vaultName: "my-vault",
secretName: "oidc-client-secret",
},
providerUrl: process.env.OIDC_PROVIDER_URL!,
},
},
],
userProfileConfig: {
tailordb: {
namespace: "main-db",
type: "User",
usernameField: "email",
attributeFields: ["roles"],
},
},
},
auth,
});
```

Expand Down Expand Up @@ -82,29 +94,34 @@ tailor-sdk secret create \

**Vault naming rules:** Only lowercase letters (a-z), numbers (0-9), and hyphens (-). Must start and end with a letter or number, 2-62 characters long.

**User Type Definition:**

Make sure you have a User type defined in your database schema (e.g., `db/user.ts`):

```typescript
import { t } from "@tailor-platform/sdk";

export const User = t.object({
id: t.uuid(),
email: t.string().email(),
name: t.string(),
roles: t.array(t.string()).optional(),
});
```

### SAML

The Tailor Platform provides a built-in key for signing SAML authentication requests. When request signing is enabled, the platform automatically signs requests sent from the SP to the IdP. The SP metadata, including the public key for signature verification, is available at `https://api.tailor.tech/saml/{workspace_id}/{auth_namespace}/metadata.xml`.

Update your `tailor.config.ts` to include SAML configuration:

```typescript
import { defineConfig } from "@tailor-platform/sdk";
import { defineAuth, defineConfig } from "@tailor-platform/sdk";
import { user } from "./db/user";

const auth = defineAuth("project-management-auth", {
userProfile: {
type: user,
usernameField: "email",
attributes: {
roles: true,
},
},
idProvider: {
name: "saml-provider",
saml: {
metadataUrl: process.env.SAML_METADATA_URL!,
// Alternative: use rawMetadata for inline XML
// rawMetadata: `<?xml version="1.0"?>...`,
enableSignRequest: false, // Set to true to enable request signing
},
},
});

export default defineConfig({
name: "project-management",
Expand All @@ -113,28 +130,7 @@ export default defineConfig({
files: ["db/**/*.ts"],
},
},
auth: {
namespace: "project-management-auth",
idpConfigs: [
{
name: "saml-provider",
saml: {
metadataUrl: process.env.SAML_METADATA_URL!,
// Alternative: use rawMetadata for inline XML
// rawMetadata: `<?xml version="1.0"?>...`,
enableSignRequest: false, // Set to true to enable request signing
},
},
],
userProfileConfig: {
tailordb: {
namespace: "main-db",
type: "User",
usernameField: "email",
attributeFields: ["roles"],
},
},
},
auth,
});
```

Expand All @@ -161,7 +157,25 @@ The metadata URL is provided by your Identity Provider (IdP). You can typically
For ID Token-based authentication, update your `tailor.config.ts`:

```typescript
import { defineConfig } from "@tailor-platform/sdk";
import { defineAuth, defineConfig } from "@tailor-platform/sdk";
import { user } from "./db/user";

const auth = defineAuth("project-management-auth", {
userProfile: {
type: user,
usernameField: "email",
attributes: {
roles: true,
},
},
idProvider: {
name: "idtoken-provider",
idToken: {
clientId: process.env.ID_TOKEN_CLIENT_ID!,
providerUrl: process.env.ID_TOKEN_PROVIDER_URL!,
},
},
});

export default defineConfig({
name: "project-management",
Expand All @@ -170,26 +184,7 @@ export default defineConfig({
files: ["db/**/*.ts"],
},
},
auth: {
namespace: "project-management-auth",
idpConfigs: [
{
name: "idtoken-provider",
idToken: {
clientId: process.env.ID_TOKEN_CLIENT_ID!,
providerUrl: process.env.ID_TOKEN_PROVIDER_URL!,
},
},
],
userProfileConfig: {
tailordb: {
namespace: "main-db",
type: "User",
usernameField: "email",
attributeFields: ["roles"],
},
},
},
auth,
});
```

Expand Down
Loading