@agent-native/scheduling 0.1.57 → 0.1.58-nightly-20260905133321
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/dist/schema/bookings.d.ts +195 -309
- package/dist/schema/bookings.d.ts.map +1 -1
- package/dist/schema/bookings.js +4 -5
- package/dist/schema/bookings.js.map +1 -1
- package/dist/schema/calendar-cache.d.ts +26 -42
- package/dist/schema/calendar-cache.d.ts.map +1 -1
- package/dist/schema/credentials.d.ts +121 -191
- package/dist/schema/credentials.d.ts.map +1 -1
- package/dist/schema/credentials.js +4 -5
- package/dist/schema/credentials.js.map +1 -1
- package/dist/schema/event-types.d.ts +213 -313
- package/dist/schema/event-types.d.ts.map +1 -1
- package/dist/schema/event-types.js +8 -15
- package/dist/schema/event-types.js.map +1 -1
- package/dist/schema/routing-forms.d.ts +93 -149
- package/dist/schema/routing-forms.d.ts.map +1 -1
- package/dist/schema/routing-forms.js +3 -2
- package/dist/schema/routing-forms.js.map +1 -1
- package/dist/schema/schedules.d.ts +135 -213
- package/dist/schema/schedules.d.ts.map +1 -1
- package/dist/schema/schedules.js +2 -3
- package/dist/schema/schedules.js.map +1 -1
- package/dist/schema/teams.d.ts +93 -147
- package/dist/schema/teams.d.ts.map +1 -1
- package/dist/schema/teams.js +4 -5
- package/dist/schema/teams.js.map +1 -1
- package/dist/schema/workflows.d.ts +224 -344
- package/dist/schema/workflows.d.ts.map +1 -1
- package/dist/schema/workflows.js +6 -5
- package/dist/schema/workflows.js.map +1 -1
- package/docs/llms-full.txt +1 -1
- package/docs/schema.md +1 -1
- package/package.json +4 -5
- package/src/actions/booking-authz.spec.ts +34 -21
- package/src/actions/event-type-authz.spec.ts +34 -21
- package/src/schema/bookings.ts +4 -5
- package/src/schema/credentials.ts +4 -5
- package/src/schema/event-types.ts +8 -15
- package/src/schema/routing-forms.ts +2 -2
- package/src/schema/schedules.ts +2 -3
- package/src/schema/teams.ts +3 -5
- package/src/schema/workflows.ts +6 -5
- package/src/server/booking-service.spec.ts +47 -34
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workflows.d.ts","sourceRoot":"","sources":["../../src/schema/workflows.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"workflows.d.ts","sourceRoot":"","sources":["../../src/schema/workflows.ts"],"names":[],"mappings":"AAgBA,eAAO,MAAM,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAsBpB,CAAC;AAEH,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA0BxB,CAAC;AAEH;;;;GAIG;AACH,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAc7B,CAAC;AAEH,sCAAsC;AACtC,eAAO,MAAM,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAanB,CAAC;AAEH,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAS5B,CAAC;AAEH,wCAAwC;AACxC,eAAO,MAAM,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EASlB,CAAC;AAEH,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAAuC,CAAC"}
|
package/dist/schema/workflows.js
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
* we materialize scheduled reminders; a job processes them when due.
|
|
7
7
|
*/
|
|
8
8
|
import { table, text, integer, ownableColumns, createSharesTable, } from "@agent-native/core/db/schema";
|
|
9
|
+
import { boolean } from "drizzle-orm/pg-core";
|
|
9
10
|
export const workflows = table("workflows", {
|
|
10
11
|
id: text("id").primaryKey(),
|
|
11
12
|
name: text("name").notNull(),
|
|
@@ -20,7 +21,7 @@ export const workflows = table("workflows", {
|
|
|
20
21
|
],
|
|
21
22
|
}).notNull(),
|
|
22
23
|
teamId: text("team_id"),
|
|
23
|
-
disabled:
|
|
24
|
+
disabled: boolean("disabled").notNull().default(false),
|
|
24
25
|
/** JSON array of eventTypeIds this workflow runs on. Empty = none. */
|
|
25
26
|
activeOnEventTypeIds: text("active_on_event_type_ids")
|
|
26
27
|
.notNull()
|
|
@@ -69,9 +70,9 @@ export const scheduledReminders = table("scheduled_reminders", {
|
|
|
69
70
|
enum: ["email", "sms", "webhook"],
|
|
70
71
|
}).notNull(),
|
|
71
72
|
scheduledFor: text("scheduled_for").notNull(),
|
|
72
|
-
sent:
|
|
73
|
+
sent: boolean("sent").notNull().default(false),
|
|
73
74
|
sentAt: text("sent_at"),
|
|
74
|
-
failed:
|
|
75
|
+
failed: boolean("failed").notNull().default(false),
|
|
75
76
|
failureReason: text("failure_reason"),
|
|
76
77
|
attempts: integer("attempts").notNull().default(0),
|
|
77
78
|
createdAt: text("created_at").notNull(),
|
|
@@ -82,7 +83,7 @@ export const webhooks = table("webhooks", {
|
|
|
82
83
|
name: text("name"),
|
|
83
84
|
subscriberUrl: text("subscriber_url").notNull(),
|
|
84
85
|
secret: text("secret"),
|
|
85
|
-
active:
|
|
86
|
+
active: boolean("active").notNull().default(true),
|
|
86
87
|
/** JSON array of trigger keys */
|
|
87
88
|
eventTriggers: text("event_triggers").notNull().default("[]"),
|
|
88
89
|
teamId: text("team_id"),
|
|
@@ -98,7 +99,7 @@ export const webhookDeliveries = table("webhook_deliveries", {
|
|
|
98
99
|
payload: text("payload").notNull(),
|
|
99
100
|
responseStatus: integer("response_status"),
|
|
100
101
|
responseBody: text("response_body"),
|
|
101
|
-
success:
|
|
102
|
+
success: boolean("success").notNull().default(false),
|
|
102
103
|
attempts: integer("attempts").notNull().default(0),
|
|
103
104
|
});
|
|
104
105
|
/** API keys for programmatic access. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workflows.js","sourceRoot":"","sources":["../../src/schema/workflows.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EACL,KAAK,EACL,IAAI,EACJ,OAAO,EACP,cAAc,EACd,iBAAiB,GAClB,MAAM,8BAA8B,CAAC;
|
|
1
|
+
{"version":3,"file":"workflows.js","sourceRoot":"","sources":["../../src/schema/workflows.ts"],"names":[],"mappings":"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"}
|
package/docs/llms-full.txt
CHANGED
|
@@ -393,7 +393,7 @@ tokens; the package never reads a token store or environment directly.
|
|
|
393
393
|
|
|
394
394
|
# Schema reference
|
|
395
395
|
|
|
396
|
-
All tables use
|
|
396
|
+
All tables use PostgreSQL helpers from `@agent-native/core/db/schema`
|
|
397
397
|
and compose with `ownableColumns()` + `createSharesTable()` for framework-
|
|
398
398
|
wide sharing.
|
|
399
399
|
|
package/docs/schema.md
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agent-native/scheduling",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.58-nightly-20260905133321",
|
|
4
4
|
"description": "Scheduling primitives for agent-native apps — event types, availability, bookings, team scheduling, workflows, and routing forms.",
|
|
5
5
|
"homepage": "https://github.com/BuilderIO/agent-native#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -56,10 +56,9 @@
|
|
|
56
56
|
"nanoid": "^5.1.9",
|
|
57
57
|
"rrule": "^2.8.1",
|
|
58
58
|
"zod": "^4.3.6",
|
|
59
|
-
"@agent-native/toolkit": "^0.19.
|
|
59
|
+
"@agent-native/toolkit": "^0.19.4-nightly-20260905133321"
|
|
60
60
|
},
|
|
61
61
|
"devDependencies": {
|
|
62
|
-
"@libsql/client": "^0.15.8",
|
|
63
62
|
"@tabler/icons-react": "^3.41.1",
|
|
64
63
|
"@types/node": "^24.2.1",
|
|
65
64
|
"@types/react": "^19.2.14",
|
|
@@ -67,10 +66,10 @@
|
|
|
67
66
|
"react": "^19.2.5",
|
|
68
67
|
"typescript-7": "npm:typescript@^7.0.2",
|
|
69
68
|
"vitest": "^4.1.5",
|
|
70
|
-
"@agent-native/core": "0.
|
|
69
|
+
"@agent-native/core": "0.177.0-nightly-20260905133321"
|
|
71
70
|
},
|
|
72
71
|
"peerDependencies": {
|
|
73
|
-
"@agent-native/core": "
|
|
72
|
+
"@agent-native/core": "0.177.0-nightly-20260905133321",
|
|
74
73
|
"@tabler/icons-react": "^3.41.1",
|
|
75
74
|
"drizzle-orm": ">=0.45",
|
|
76
75
|
"react": ">=18",
|
|
@@ -4,13 +4,11 @@
|
|
|
4
4
|
* another host. Mirrors the `isHost` guard already proven in
|
|
5
5
|
* `cancel-booking.ts` / `reschedule-booking.ts`.
|
|
6
6
|
*/
|
|
7
|
-
import { randomUUID } from "node:crypto";
|
|
8
7
|
import { mkdtempSync, rmSync } from "node:fs";
|
|
9
8
|
import { tmpdir } from "node:os";
|
|
10
9
|
import { join } from "node:path";
|
|
11
10
|
|
|
12
|
-
import {
|
|
13
|
-
import { drizzle } from "drizzle-orm/libsql";
|
|
11
|
+
import { closeDbExec, createGetDb, getDbExec } from "@agent-native/core/db";
|
|
14
12
|
import { afterEach, beforeEach, describe, expect, it } from "vitest";
|
|
15
13
|
|
|
16
14
|
import * as schema from "../schema/index.js";
|
|
@@ -23,18 +21,33 @@ import removeBookingAttendee from "./remove-booking-attendee.js";
|
|
|
23
21
|
import sendRescheduleLink from "./send-reschedule-link.js";
|
|
24
22
|
|
|
25
23
|
const HOST_EMAIL = "host@example.com";
|
|
24
|
+
|
|
25
|
+
type SqlStatement = string | { sql: string; args?: unknown[] };
|
|
26
|
+
|
|
27
|
+
function postgresSql(sql: string): string {
|
|
28
|
+
let index = 0;
|
|
29
|
+
return sql.replace(/\?/g, () => "$" + ++index);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
async function execute(statement: SqlStatement) {
|
|
33
|
+
if (typeof statement === "string")
|
|
34
|
+
return getDbExec().execute(postgresSql(statement));
|
|
35
|
+
return getDbExec().execute({
|
|
36
|
+
...statement,
|
|
37
|
+
sql: postgresSql(statement.sql),
|
|
38
|
+
});
|
|
39
|
+
}
|
|
26
40
|
const OUTSIDER_EMAIL = "outsider@example.com";
|
|
27
41
|
const BOOKING_UID = "booking-uid-1";
|
|
28
42
|
const ATTENDEE_EMAIL = "attendee@example.com";
|
|
29
43
|
|
|
30
|
-
let client: Client;
|
|
31
44
|
let dbDir: string;
|
|
32
45
|
let currentUserEmail: string | undefined;
|
|
33
46
|
|
|
34
47
|
beforeEach(async () => {
|
|
35
48
|
dbDir = mkdtempSync(join(tmpdir(), "scheduling-booking-authz-test-"));
|
|
36
|
-
|
|
37
|
-
await
|
|
49
|
+
process.env.DATABASE_URL = `pglite:${dbDir}`;
|
|
50
|
+
await execute(`
|
|
38
51
|
CREATE TABLE bookings (
|
|
39
52
|
id TEXT PRIMARY KEY,
|
|
40
53
|
uid TEXT NOT NULL UNIQUE,
|
|
@@ -56,8 +69,8 @@ beforeEach(async () => {
|
|
|
56
69
|
ical_uid TEXT NOT NULL,
|
|
57
70
|
ical_sequence INTEGER NOT NULL DEFAULT 0,
|
|
58
71
|
recurring_event_id TEXT,
|
|
59
|
-
paid
|
|
60
|
-
no_show_host
|
|
72
|
+
paid BOOLEAN NOT NULL DEFAULT false,
|
|
73
|
+
no_show_host BOOLEAN NOT NULL DEFAULT false,
|
|
61
74
|
metadata TEXT,
|
|
62
75
|
created_at TEXT NOT NULL,
|
|
63
76
|
updated_at TEXT NOT NULL,
|
|
@@ -66,7 +79,7 @@ beforeEach(async () => {
|
|
|
66
79
|
visibility TEXT NOT NULL DEFAULT 'private'
|
|
67
80
|
);
|
|
68
81
|
`);
|
|
69
|
-
await
|
|
82
|
+
await execute(`
|
|
70
83
|
CREATE TABLE booking_attendees (
|
|
71
84
|
id TEXT PRIMARY KEY,
|
|
72
85
|
booking_id TEXT NOT NULL,
|
|
@@ -74,11 +87,11 @@ beforeEach(async () => {
|
|
|
74
87
|
name TEXT NOT NULL,
|
|
75
88
|
timezone TEXT,
|
|
76
89
|
locale TEXT,
|
|
77
|
-
no_show
|
|
90
|
+
no_show BOOLEAN NOT NULL DEFAULT false,
|
|
78
91
|
created_at TEXT NOT NULL
|
|
79
92
|
);
|
|
80
93
|
`);
|
|
81
|
-
await
|
|
94
|
+
await execute(`
|
|
82
95
|
CREATE TABLE booking_references (
|
|
83
96
|
id TEXT PRIMARY KEY,
|
|
84
97
|
booking_id TEXT NOT NULL,
|
|
@@ -90,7 +103,7 @@ beforeEach(async () => {
|
|
|
90
103
|
created_at TEXT NOT NULL
|
|
91
104
|
);
|
|
92
105
|
`);
|
|
93
|
-
await
|
|
106
|
+
await execute(`
|
|
94
107
|
CREATE TABLE booking_notes (
|
|
95
108
|
id TEXT PRIMARY KEY,
|
|
96
109
|
booking_id TEXT NOT NULL,
|
|
@@ -100,7 +113,7 @@ beforeEach(async () => {
|
|
|
100
113
|
);
|
|
101
114
|
`);
|
|
102
115
|
|
|
103
|
-
const db =
|
|
116
|
+
const db = createGetDb(schema)();
|
|
104
117
|
currentUserEmail = HOST_EMAIL;
|
|
105
118
|
setSchedulingContext({
|
|
106
119
|
getDb: () => db,
|
|
@@ -109,7 +122,7 @@ beforeEach(async () => {
|
|
|
109
122
|
});
|
|
110
123
|
|
|
111
124
|
const now = new Date().toISOString();
|
|
112
|
-
await
|
|
125
|
+
await execute({
|
|
113
126
|
sql: `INSERT INTO bookings (
|
|
114
127
|
id, uid, event_type_id, host_email, title, start_time, end_time,
|
|
115
128
|
timezone, status, cancel_token, reschedule_token, ical_uid, created_at, updated_at
|
|
@@ -131,19 +144,19 @@ beforeEach(async () => {
|
|
|
131
144
|
now,
|
|
132
145
|
],
|
|
133
146
|
});
|
|
134
|
-
await
|
|
147
|
+
await execute({
|
|
135
148
|
sql: `INSERT INTO booking_attendees (id, booking_id, email, name, created_at) VALUES (?, ?, ?, ?, ?)`,
|
|
136
149
|
args: ["attendee-1", "booking-1", ATTENDEE_EMAIL, "Attendee One", now],
|
|
137
150
|
});
|
|
138
151
|
});
|
|
139
152
|
|
|
140
|
-
afterEach(() => {
|
|
141
|
-
|
|
153
|
+
afterEach(async () => {
|
|
154
|
+
await closeDbExec();
|
|
142
155
|
rmSync(dbDir, { recursive: true, force: true });
|
|
143
156
|
});
|
|
144
157
|
|
|
145
158
|
async function bookingStatus(): Promise<string> {
|
|
146
|
-
const { rows } = await
|
|
159
|
+
const { rows } = await execute({
|
|
147
160
|
sql: "SELECT status FROM bookings WHERE uid = ?",
|
|
148
161
|
args: [BOOKING_UID],
|
|
149
162
|
});
|
|
@@ -151,14 +164,14 @@ async function bookingStatus(): Promise<string> {
|
|
|
151
164
|
}
|
|
152
165
|
|
|
153
166
|
async function attendeeEmails(): Promise<string[]> {
|
|
154
|
-
const { rows } = await
|
|
167
|
+
const { rows } = await execute({
|
|
155
168
|
sql: "SELECT email FROM booking_attendees WHERE booking_id = 'booking-1'",
|
|
156
169
|
});
|
|
157
170
|
return rows.map((r: any) => String(r.email)).sort();
|
|
158
171
|
}
|
|
159
172
|
|
|
160
173
|
async function attendeeNoShow(email: string): Promise<boolean> {
|
|
161
|
-
const { rows } = await
|
|
174
|
+
const { rows } = await execute({
|
|
162
175
|
sql: "SELECT no_show FROM booking_attendees WHERE booking_id = 'booking-1' AND email = ?",
|
|
163
176
|
args: [email],
|
|
164
177
|
});
|
|
@@ -166,7 +179,7 @@ async function attendeeNoShow(email: string): Promise<boolean> {
|
|
|
166
179
|
}
|
|
167
180
|
|
|
168
181
|
async function noteCount(): Promise<number> {
|
|
169
|
-
const { rows } = await
|
|
182
|
+
const { rows } = await execute("SELECT * FROM booking_notes");
|
|
170
183
|
return rows.length;
|
|
171
184
|
}
|
|
172
185
|
|
|
@@ -5,11 +5,11 @@
|
|
|
5
5
|
* ..., <role>)` guard already used by `add-private-link.ts` /
|
|
6
6
|
* `delete-event-type.ts`.
|
|
7
7
|
*/
|
|
8
|
-
import { randomUUID } from "node:crypto";
|
|
9
8
|
import { mkdtempSync, rmSync } from "node:fs";
|
|
10
9
|
import { tmpdir } from "node:os";
|
|
11
10
|
import { join } from "node:path";
|
|
12
11
|
|
|
12
|
+
import { closeDbExec, createGetDb, getDbExec } from "@agent-native/core/db";
|
|
13
13
|
import {
|
|
14
14
|
getRequestUserEmail,
|
|
15
15
|
runWithRequestContext,
|
|
@@ -18,8 +18,6 @@ import {
|
|
|
18
18
|
ForbiddenError,
|
|
19
19
|
registerShareableResource,
|
|
20
20
|
} from "@agent-native/core/sharing";
|
|
21
|
-
import { createClient, type Client } from "@libsql/client";
|
|
22
|
-
import { drizzle } from "drizzle-orm/libsql";
|
|
23
21
|
import { afterEach, beforeEach, describe, expect, it } from "vitest";
|
|
24
22
|
|
|
25
23
|
import * as schema from "../schema/index.js";
|
|
@@ -28,17 +26,32 @@ import duplicateEventType from "./duplicate-event-type.js";
|
|
|
28
26
|
import revokePrivateLink from "./revoke-private-link.js";
|
|
29
27
|
|
|
30
28
|
const OWNER_EMAIL = "owner@example.com";
|
|
29
|
+
|
|
30
|
+
type SqlStatement = string | { sql: string; args?: unknown[] };
|
|
31
|
+
|
|
32
|
+
function postgresSql(sql: string): string {
|
|
33
|
+
let index = 0;
|
|
34
|
+
return sql.replace(/\?/g, () => "$" + ++index);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
async function execute(statement: SqlStatement) {
|
|
38
|
+
if (typeof statement === "string")
|
|
39
|
+
return getDbExec().execute(postgresSql(statement));
|
|
40
|
+
return getDbExec().execute({
|
|
41
|
+
...statement,
|
|
42
|
+
sql: postgresSql(statement.sql),
|
|
43
|
+
});
|
|
44
|
+
}
|
|
31
45
|
const OUTSIDER_EMAIL = "outsider@example.com";
|
|
32
46
|
const EVENT_TYPE_ID = "event-type-1";
|
|
33
47
|
const HASH = "private-link-hash-1";
|
|
34
48
|
|
|
35
|
-
let client: Client;
|
|
36
49
|
let dbDir: string;
|
|
37
50
|
|
|
38
51
|
beforeEach(async () => {
|
|
39
52
|
dbDir = mkdtempSync(join(tmpdir(), "scheduling-eventtype-authz-test-"));
|
|
40
|
-
|
|
41
|
-
await
|
|
53
|
+
process.env.DATABASE_URL = `pglite:${dbDir}`;
|
|
54
|
+
await execute(`
|
|
42
55
|
CREATE TABLE event_types (
|
|
43
56
|
id TEXT PRIMARY KEY,
|
|
44
57
|
title TEXT NOT NULL,
|
|
@@ -47,7 +60,7 @@ beforeEach(async () => {
|
|
|
47
60
|
length INTEGER NOT NULL DEFAULT 30,
|
|
48
61
|
durations TEXT,
|
|
49
62
|
position INTEGER NOT NULL DEFAULT 0,
|
|
50
|
-
hidden
|
|
63
|
+
hidden BOOLEAN NOT NULL DEFAULT false,
|
|
51
64
|
color TEXT,
|
|
52
65
|
scheduling_type TEXT NOT NULL DEFAULT 'personal',
|
|
53
66
|
team_id TEXT,
|
|
@@ -63,12 +76,12 @@ beforeEach(async () => {
|
|
|
63
76
|
period_start_date TEXT,
|
|
64
77
|
period_end_date TEXT,
|
|
65
78
|
seats_per_time_slot INTEGER,
|
|
66
|
-
requires_confirmation
|
|
67
|
-
disable_guests
|
|
68
|
-
hide_calendar_notes
|
|
79
|
+
requires_confirmation BOOLEAN NOT NULL DEFAULT false,
|
|
80
|
+
disable_guests BOOLEAN NOT NULL DEFAULT false,
|
|
81
|
+
hide_calendar_notes BOOLEAN NOT NULL DEFAULT false,
|
|
69
82
|
success_redirect_url TEXT,
|
|
70
83
|
booking_limits TEXT,
|
|
71
|
-
lock_time_zone_toggle
|
|
84
|
+
lock_time_zone_toggle BOOLEAN NOT NULL DEFAULT false,
|
|
72
85
|
recurring_event TEXT,
|
|
73
86
|
event_name TEXT,
|
|
74
87
|
metadata TEXT,
|
|
@@ -79,18 +92,18 @@ beforeEach(async () => {
|
|
|
79
92
|
visibility TEXT NOT NULL DEFAULT 'private'
|
|
80
93
|
);
|
|
81
94
|
`);
|
|
82
|
-
await
|
|
95
|
+
await execute(`
|
|
83
96
|
CREATE TABLE hashed_links (
|
|
84
97
|
id TEXT PRIMARY KEY,
|
|
85
98
|
hash TEXT NOT NULL UNIQUE,
|
|
86
99
|
event_type_id TEXT NOT NULL,
|
|
87
100
|
expires_at TEXT,
|
|
88
|
-
is_single_use
|
|
101
|
+
is_single_use BOOLEAN NOT NULL DEFAULT false,
|
|
89
102
|
used_at TEXT,
|
|
90
103
|
created_at TEXT NOT NULL
|
|
91
104
|
);
|
|
92
105
|
`);
|
|
93
|
-
await
|
|
106
|
+
await execute(`
|
|
94
107
|
CREATE TABLE event_type_shares (
|
|
95
108
|
id TEXT PRIMARY KEY,
|
|
96
109
|
resource_id TEXT NOT NULL,
|
|
@@ -102,7 +115,7 @@ beforeEach(async () => {
|
|
|
102
115
|
);
|
|
103
116
|
`);
|
|
104
117
|
|
|
105
|
-
const db =
|
|
118
|
+
const db = createGetDb(schema)();
|
|
106
119
|
setSchedulingContext({
|
|
107
120
|
getDb: () => db,
|
|
108
121
|
schema,
|
|
@@ -121,7 +134,7 @@ beforeEach(async () => {
|
|
|
121
134
|
});
|
|
122
135
|
|
|
123
136
|
const now = new Date().toISOString();
|
|
124
|
-
await
|
|
137
|
+
await execute({
|
|
125
138
|
sql: `INSERT INTO event_types (
|
|
126
139
|
id, title, slug, length, created_at, updated_at, owner_email, visibility
|
|
127
140
|
) VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
@@ -136,19 +149,19 @@ beforeEach(async () => {
|
|
|
136
149
|
"private",
|
|
137
150
|
],
|
|
138
151
|
});
|
|
139
|
-
await
|
|
152
|
+
await execute({
|
|
140
153
|
sql: `INSERT INTO hashed_links (id, hash, event_type_id, created_at) VALUES (?, ?, ?, ?)`,
|
|
141
154
|
args: ["link-1", HASH, EVENT_TYPE_ID, now],
|
|
142
155
|
});
|
|
143
156
|
});
|
|
144
157
|
|
|
145
|
-
afterEach(() => {
|
|
146
|
-
|
|
158
|
+
afterEach(async () => {
|
|
159
|
+
await closeDbExec();
|
|
147
160
|
rmSync(dbDir, { recursive: true, force: true });
|
|
148
161
|
});
|
|
149
162
|
|
|
150
163
|
async function hashedLinkExists(): Promise<boolean> {
|
|
151
|
-
const { rows } = await
|
|
164
|
+
const { rows } = await execute({
|
|
152
165
|
sql: "SELECT 1 FROM hashed_links WHERE hash = ?",
|
|
153
166
|
args: [HASH],
|
|
154
167
|
});
|
|
@@ -156,7 +169,7 @@ async function hashedLinkExists(): Promise<boolean> {
|
|
|
156
169
|
}
|
|
157
170
|
|
|
158
171
|
async function eventTypeCount(): Promise<number> {
|
|
159
|
-
const { rows } = await
|
|
172
|
+
const { rows } = await execute("SELECT * FROM event_types");
|
|
160
173
|
return rows.length;
|
|
161
174
|
}
|
|
162
175
|
|
package/src/schema/bookings.ts
CHANGED
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
ownableColumns,
|
|
14
14
|
createSharesTable,
|
|
15
15
|
} from "@agent-native/core/db/schema";
|
|
16
|
+
import { boolean } from "drizzle-orm/pg-core";
|
|
16
17
|
|
|
17
18
|
export const bookings = table("bookings", {
|
|
18
19
|
id: text("id").primaryKey(),
|
|
@@ -60,12 +61,10 @@ export const bookings = table("bookings", {
|
|
|
60
61
|
recurringEventId: text("recurring_event_id"),
|
|
61
62
|
|
|
62
63
|
/** Payment state (Tier 2) */
|
|
63
|
-
paid:
|
|
64
|
+
paid: boolean("paid").notNull().default(false),
|
|
64
65
|
|
|
65
66
|
/** Whether the host marked themselves a no-show */
|
|
66
|
-
noShowHost:
|
|
67
|
-
.notNull()
|
|
68
|
-
.default(false),
|
|
67
|
+
noShowHost: boolean("no_show_host").notNull().default(false),
|
|
69
68
|
|
|
70
69
|
metadata: text("metadata"),
|
|
71
70
|
createdAt: text("created_at").notNull(),
|
|
@@ -82,7 +81,7 @@ export const bookingAttendees = table("booking_attendees", {
|
|
|
82
81
|
name: text("name").notNull(),
|
|
83
82
|
timezone: text("timezone"),
|
|
84
83
|
locale: text("locale"),
|
|
85
|
-
noShow:
|
|
84
|
+
noShow: boolean("no_show").notNull().default(false),
|
|
86
85
|
createdAt: text("created_at").notNull(),
|
|
87
86
|
});
|
|
88
87
|
|
|
@@ -5,7 +5,8 @@
|
|
|
5
5
|
* metadata and flags needed by the scheduling UI (display name, invalid
|
|
6
6
|
* flag, app icon, default-for-type).
|
|
7
7
|
*/
|
|
8
|
-
import { table, text
|
|
8
|
+
import { table, text } from "@agent-native/core/db/schema";
|
|
9
|
+
import { boolean } from "drizzle-orm/pg-core";
|
|
9
10
|
|
|
10
11
|
export const schedulingCredentials = table("scheduling_credentials", {
|
|
11
12
|
id: text("id").primaryKey(),
|
|
@@ -23,11 +24,9 @@ export const schedulingCredentials = table("scheduling_credentials", {
|
|
|
23
24
|
/** External account email (e.g. Google account email) */
|
|
24
25
|
externalEmail: text("external_email"),
|
|
25
26
|
/** True after a 401/403 — UI prompts re-connect */
|
|
26
|
-
invalid:
|
|
27
|
+
invalid: boolean("invalid").notNull().default(false),
|
|
27
28
|
/** Whether this is the user's default for its category (e.g. default video) */
|
|
28
|
-
isDefault:
|
|
29
|
-
.notNull()
|
|
30
|
-
.default(false),
|
|
29
|
+
isDefault: boolean("is_default").notNull().default(false),
|
|
31
30
|
createdAt: text("created_at").notNull(),
|
|
32
31
|
updatedAt: text("updated_at").notNull(),
|
|
33
32
|
});
|
|
@@ -16,6 +16,7 @@ import {
|
|
|
16
16
|
ownableColumns,
|
|
17
17
|
createSharesTable,
|
|
18
18
|
} from "@agent-native/core/db/schema";
|
|
19
|
+
import { boolean } from "drizzle-orm/pg-core";
|
|
19
20
|
|
|
20
21
|
export const eventTypes = table("event_types", {
|
|
21
22
|
id: text("id").primaryKey(),
|
|
@@ -29,7 +30,7 @@ export const eventTypes = table("event_types", {
|
|
|
29
30
|
/** JSON array of additional duration choices, e.g. [15, 30, 60] */
|
|
30
31
|
durations: text("durations"),
|
|
31
32
|
position: integer("position").notNull().default(0),
|
|
32
|
-
hidden:
|
|
33
|
+
hidden: boolean("hidden").notNull().default(false),
|
|
33
34
|
color: text("color"),
|
|
34
35
|
|
|
35
36
|
// Scheduling model
|
|
@@ -69,21 +70,15 @@ export const eventTypes = table("event_types", {
|
|
|
69
70
|
|
|
70
71
|
// Capacity & policies
|
|
71
72
|
seatsPerTimeSlot: integer("seats_per_time_slot"),
|
|
72
|
-
requiresConfirmation:
|
|
73
|
-
.notNull()
|
|
74
|
-
.default(false),
|
|
75
|
-
disableGuests: integer("disable_guests", { mode: "boolean" })
|
|
76
|
-
.notNull()
|
|
77
|
-
.default(false),
|
|
78
|
-
hideCalendarNotes: integer("hide_calendar_notes", { mode: "boolean" })
|
|
73
|
+
requiresConfirmation: boolean("requires_confirmation")
|
|
79
74
|
.notNull()
|
|
80
75
|
.default(false),
|
|
76
|
+
disableGuests: boolean("disable_guests").notNull().default(false),
|
|
77
|
+
hideCalendarNotes: boolean("hide_calendar_notes").notNull().default(false),
|
|
81
78
|
successRedirectUrl: text("success_redirect_url"),
|
|
82
79
|
bookingLimits: text("booking_limits"),
|
|
83
80
|
/** Lock timezone on Booker (for in-person or local-only events) */
|
|
84
|
-
lockTimeZoneToggle:
|
|
85
|
-
.notNull()
|
|
86
|
-
.default(false),
|
|
81
|
+
lockTimeZoneToggle: boolean("lock_time_zone_toggle").notNull().default(false),
|
|
87
82
|
|
|
88
83
|
// Recurring (JSON RecurringEventRule) — Tier 2
|
|
89
84
|
recurringEvent: text("recurring_event"),
|
|
@@ -107,7 +102,7 @@ export const eventTypeHosts = table("event_type_hosts", {
|
|
|
107
102
|
eventTypeId: text("event_type_id").notNull(),
|
|
108
103
|
userEmail: text("user_email").notNull(),
|
|
109
104
|
/** Fixed hosts always attend; non-fixed hosts rotate in round-robin */
|
|
110
|
-
isFixed:
|
|
105
|
+
isFixed: boolean("is_fixed").notNull().default(false),
|
|
111
106
|
/** Relative weight for weighted round-robin (default 1) */
|
|
112
107
|
weight: integer("weight").notNull().default(1),
|
|
113
108
|
/** Lower number = higher priority in round-robin tiebreak */
|
|
@@ -144,9 +139,7 @@ export const hashedLinks = table("hashed_links", {
|
|
|
144
139
|
hash: text("hash").notNull().unique(),
|
|
145
140
|
eventTypeId: text("event_type_id").notNull(),
|
|
146
141
|
expiresAt: text("expires_at"),
|
|
147
|
-
isSingleUse:
|
|
148
|
-
.notNull()
|
|
149
|
-
.default(false),
|
|
142
|
+
isSingleUse: boolean("is_single_use").notNull().default(false),
|
|
150
143
|
usedAt: text("used_at"),
|
|
151
144
|
createdAt: text("created_at").notNull(),
|
|
152
145
|
});
|
|
@@ -10,17 +10,17 @@
|
|
|
10
10
|
import {
|
|
11
11
|
table,
|
|
12
12
|
text,
|
|
13
|
-
integer,
|
|
14
13
|
ownableColumns,
|
|
15
14
|
createSharesTable,
|
|
16
15
|
} from "@agent-native/core/db/schema";
|
|
16
|
+
import { boolean } from "drizzle-orm/pg-core";
|
|
17
17
|
|
|
18
18
|
export const routingForms = table("routing_forms", {
|
|
19
19
|
id: text("id").primaryKey(),
|
|
20
20
|
name: text("name").notNull(),
|
|
21
21
|
description: text("description"),
|
|
22
22
|
teamId: text("team_id"),
|
|
23
|
-
disabled:
|
|
23
|
+
disabled: boolean("disabled").notNull().default(false),
|
|
24
24
|
/** JSON array of RoutingFormField */
|
|
25
25
|
fields: text("fields").notNull().default("[]"),
|
|
26
26
|
/** JSON array of RoutingFormRule */
|
package/src/schema/schedules.ts
CHANGED
|
@@ -14,14 +14,13 @@ import {
|
|
|
14
14
|
ownableColumns,
|
|
15
15
|
createSharesTable,
|
|
16
16
|
} from "@agent-native/core/db/schema";
|
|
17
|
+
import { boolean } from "drizzle-orm/pg-core";
|
|
17
18
|
|
|
18
19
|
export const schedules = table("schedules", {
|
|
19
20
|
id: text("id").primaryKey(),
|
|
20
21
|
name: text("name").notNull(),
|
|
21
22
|
timezone: text("timezone").notNull().default("UTC"),
|
|
22
|
-
isDefault:
|
|
23
|
-
.notNull()
|
|
24
|
-
.default(false),
|
|
23
|
+
isDefault: boolean("is_default").notNull().default(false),
|
|
25
24
|
createdAt: text("created_at").notNull(),
|
|
26
25
|
updatedAt: text("updated_at").notNull(),
|
|
27
26
|
...ownableColumns(),
|
package/src/schema/teams.ts
CHANGED
|
@@ -8,10 +8,10 @@
|
|
|
8
8
|
import {
|
|
9
9
|
table,
|
|
10
10
|
text,
|
|
11
|
-
integer,
|
|
12
11
|
ownableColumns,
|
|
13
12
|
createSharesTable,
|
|
14
13
|
} from "@agent-native/core/db/schema";
|
|
14
|
+
import { boolean } from "drizzle-orm/pg-core";
|
|
15
15
|
|
|
16
16
|
export const teams = table("teams", {
|
|
17
17
|
id: text("id").primaryKey(),
|
|
@@ -21,9 +21,7 @@ export const teams = table("teams", {
|
|
|
21
21
|
brandColor: text("brand_color"),
|
|
22
22
|
darkBrandColor: text("dark_brand_color"),
|
|
23
23
|
bio: text("bio"),
|
|
24
|
-
hideBranding:
|
|
25
|
-
.notNull()
|
|
26
|
-
.default(false),
|
|
24
|
+
hideBranding: boolean("hide_branding").notNull().default(false),
|
|
27
25
|
metadata: text("metadata"),
|
|
28
26
|
createdAt: text("created_at").notNull(),
|
|
29
27
|
updatedAt: text("updated_at").notNull(),
|
|
@@ -37,7 +35,7 @@ export const teamMembers = table("team_members", {
|
|
|
37
35
|
role: text("role", { enum: ["owner", "admin", "member"] })
|
|
38
36
|
.notNull()
|
|
39
37
|
.default("member"),
|
|
40
|
-
accepted:
|
|
38
|
+
accepted: boolean("accepted").notNull().default(false),
|
|
41
39
|
inviteToken: text("invite_token"),
|
|
42
40
|
invitedAt: text("invited_at").notNull(),
|
|
43
41
|
joinedAt: text("joined_at"),
|