@molecule/api-resource-meeting 1.0.0 → 1.0.2
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/README.md +348 -0
- package/package.json +14 -7
package/README.md
ADDED
|
@@ -0,0 +1,348 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
AUTO-GENERATED — DO NOT EDIT THIS FILE.
|
|
3
|
+
Generated by `mlcl sync-docs` from the package's src/index.ts JSDoc + mlcl/registry.json.
|
|
4
|
+
Edits here are overwritten on the next commit (molecule's pre-commit hook regenerates).
|
|
5
|
+
To change this document, edit the module-level JSDoc in src/index.ts.
|
|
6
|
+
Generated: 2026-08-04T01:49:15.618Z
|
|
7
|
+
-->
|
|
8
|
+
|
|
9
|
+
# @molecule/api-resource-meeting
|
|
10
|
+
|
|
11
|
+
> **Auto-generated, AI-first package reference** for the [molecule.dev](https://molecule.dev) ecosystem.
|
|
12
|
+
> It is written to be read by coding agents as much as by people, and is generated from this
|
|
13
|
+
> package's source — edit `src/index.ts` JSDoc, not this file.
|
|
14
|
+
|
|
15
|
+
`@molecule/api-resource-meeting` — meeting CRUD + action items.
|
|
16
|
+
|
|
17
|
+
Tracks scheduled/in_progress/completed/cancelled meetings with
|
|
18
|
+
attendees, optional recording URL, transcript, and AI-friendly
|
|
19
|
+
summary slot. Action items nest under meetings and track
|
|
20
|
+
completion + assignee + due date + source excerpt.
|
|
21
|
+
|
|
22
|
+
Extracted from the ai-meeting-notes flagship.
|
|
23
|
+
|
|
24
|
+
## Quick Start
|
|
25
|
+
|
|
26
|
+
```ts
|
|
27
|
+
import { createMeetingRouter } from '@molecule/api-resource-meeting'
|
|
28
|
+
app.use('/meetings', createMeetingRouter())
|
|
29
|
+
// GET|POST / · GET|PUT|DELETE /:id
|
|
30
|
+
// GET|POST /:id/action-items · PUT|DELETE /:id/action-items/:itemId
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
```ts
|
|
34
|
+
import { createActionItem, createMeetingForOwner } from '@molecule/api-resource-meeting'
|
|
35
|
+
|
|
36
|
+
const meeting = await createMeetingForOwner(userId, {
|
|
37
|
+
title: 'Sprint planning',
|
|
38
|
+
scheduled_at: '2026-08-01T10:00:00Z',
|
|
39
|
+
})
|
|
40
|
+
await createActionItem(meeting.id, userId, { description: 'Send recap' })
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Type
|
|
44
|
+
|
|
45
|
+
`resource`
|
|
46
|
+
|
|
47
|
+
## Installation
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
npm install @molecule/api-resource-meeting @molecule/api-bonds-default-express @molecule/api-database @molecule/api-i18n @molecule/api-middleware-validation express zod
|
|
51
|
+
npm install -D @types/express
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## API
|
|
55
|
+
|
|
56
|
+
### Interfaces
|
|
57
|
+
|
|
58
|
+
#### `ActionItemRow`
|
|
59
|
+
|
|
60
|
+
Raw database row shape for an action item linked to a meeting.
|
|
61
|
+
|
|
62
|
+
```typescript
|
|
63
|
+
interface ActionItemRow {
|
|
64
|
+
id: string
|
|
65
|
+
meeting_id: string
|
|
66
|
+
description: string
|
|
67
|
+
assignee: string | null
|
|
68
|
+
due_date: string | Date | null
|
|
69
|
+
is_completed: boolean
|
|
70
|
+
source_excerpt: string | null
|
|
71
|
+
created_at: string | Date
|
|
72
|
+
updated_at: string | Date
|
|
73
|
+
}
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
#### `MeetingRow`
|
|
77
|
+
|
|
78
|
+
Raw database row shape for a meeting record.
|
|
79
|
+
|
|
80
|
+
```typescript
|
|
81
|
+
interface MeetingRow {
|
|
82
|
+
id: string
|
|
83
|
+
owner_id: string
|
|
84
|
+
title: string
|
|
85
|
+
description: string | null
|
|
86
|
+
status: MeetingStatus
|
|
87
|
+
scheduled_at: string | Date | null
|
|
88
|
+
started_at: string | Date | null
|
|
89
|
+
ended_at: string | Date | null
|
|
90
|
+
duration_seconds: number
|
|
91
|
+
recording_url: string | null
|
|
92
|
+
transcript: string | null
|
|
93
|
+
summary: string | null
|
|
94
|
+
attendees: Array<{ name: string; email?: string }>
|
|
95
|
+
created_at: string | Date
|
|
96
|
+
updated_at: string | Date
|
|
97
|
+
}
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### Types
|
|
101
|
+
|
|
102
|
+
#### `MeetingStatus`
|
|
103
|
+
|
|
104
|
+
Lifecycle states a meeting can occupy from creation through completion.
|
|
105
|
+
|
|
106
|
+
```typescript
|
|
107
|
+
type MeetingStatus = 'scheduled' | 'in_progress' | 'completed' | 'cancelled'
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### Functions
|
|
111
|
+
|
|
112
|
+
#### `createActionItem(meetingId, ownerId, data)`
|
|
113
|
+
|
|
114
|
+
Creates a new action item under a meeting owned by the given owner; returns the inserted row or null if the meeting is not found/owned.
|
|
115
|
+
|
|
116
|
+
```typescript
|
|
117
|
+
function createActionItem(
|
|
118
|
+
meetingId: string,
|
|
119
|
+
ownerId: string,
|
|
120
|
+
data: {
|
|
121
|
+
description: string
|
|
122
|
+
assignee?: string | null
|
|
123
|
+
due_date?: string | null
|
|
124
|
+
source_excerpt?: string | null
|
|
125
|
+
},
|
|
126
|
+
): Promise<ActionItemRow | null>
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
#### `createMeetingForOwner(ownerId, data)`
|
|
130
|
+
|
|
131
|
+
Creates a new meeting record owned by the given owner and returns the inserted row.
|
|
132
|
+
|
|
133
|
+
```typescript
|
|
134
|
+
function createMeetingForOwner(
|
|
135
|
+
ownerId: string,
|
|
136
|
+
data: {
|
|
137
|
+
title: string
|
|
138
|
+
description?: string | null
|
|
139
|
+
scheduled_at?: string | null
|
|
140
|
+
attendees?: Array<{ name: string; email?: string }>
|
|
141
|
+
},
|
|
142
|
+
): Promise<MeetingRow>
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
#### `createMeetingRouter()`
|
|
146
|
+
|
|
147
|
+
Creates and returns an Express Router with all meeting and action-item CRUD routes.
|
|
148
|
+
|
|
149
|
+
```typescript
|
|
150
|
+
function createMeetingRouter(): Router
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
#### `deleteActionItem(itemId, meetingId, ownerId)`
|
|
154
|
+
|
|
155
|
+
Deletes an action item by ID if its parent meeting belongs to the given owner; returns true on success, false if not found or not owned.
|
|
156
|
+
|
|
157
|
+
```typescript
|
|
158
|
+
function deleteActionItem(itemId: string, meetingId: string, ownerId: string): Promise<boolean>
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
#### `deleteMeetingForOwner(meetingId, ownerId)`
|
|
162
|
+
|
|
163
|
+
Deletes a meeting by ID if it belongs to the given owner; returns true on success, false if not found or not owned.
|
|
164
|
+
|
|
165
|
+
```typescript
|
|
166
|
+
function deleteMeetingForOwner(meetingId: string, ownerId: string): Promise<boolean>
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
#### `getMeetingForOwner(meetingId, ownerId)`
|
|
170
|
+
|
|
171
|
+
Fetches a single meeting by ID, returning null if it does not exist or does not belong to the owner.
|
|
172
|
+
|
|
173
|
+
```typescript
|
|
174
|
+
function getMeetingForOwner(meetingId: string, ownerId: string): Promise<MeetingRow | null>
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
#### `listActionItems(meetingId, ownerId)`
|
|
178
|
+
|
|
179
|
+
Returns all action items for a meeting in creation order, or null if the meeting is not found/owned.
|
|
180
|
+
|
|
181
|
+
```typescript
|
|
182
|
+
function listActionItems(meetingId: string, ownerId: string): Promise<ActionItemRow[] | null>
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
#### `listMeetingsForOwner(ownerId, opts?)`
|
|
186
|
+
|
|
187
|
+
Returns a paginated list of meetings belonging to the given owner, optionally filtered by status.
|
|
188
|
+
|
|
189
|
+
```typescript
|
|
190
|
+
function listMeetingsForOwner(
|
|
191
|
+
ownerId: string,
|
|
192
|
+
opts?: { status?: MeetingStatus; page?: number; limit?: number },
|
|
193
|
+
): Promise<{ data: MeetingRow[]; total: number }>
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
#### `updateActionItem(itemId, meetingId, ownerId, patch)`
|
|
197
|
+
|
|
198
|
+
Applies a partial patch to an action item; returns the updated row or null if the meeting or item is not found/owned.
|
|
199
|
+
|
|
200
|
+
```typescript
|
|
201
|
+
function updateActionItem(
|
|
202
|
+
itemId: string,
|
|
203
|
+
meetingId: string,
|
|
204
|
+
ownerId: string,
|
|
205
|
+
patch: Partial<ActionItemRow>,
|
|
206
|
+
): Promise<ActionItemRow | null>
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
#### `updateMeetingForOwner(meetingId, ownerId, patch)`
|
|
210
|
+
|
|
211
|
+
Applies a partial patch to a meeting, recomputing duration_seconds when both timestamps are present, and returns the updated row or null if not found/owned.
|
|
212
|
+
|
|
213
|
+
```typescript
|
|
214
|
+
function updateMeetingForOwner(
|
|
215
|
+
meetingId: string,
|
|
216
|
+
ownerId: string,
|
|
217
|
+
patch: Partial<MeetingRow>,
|
|
218
|
+
): Promise<MeetingRow | null>
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
### Constants
|
|
222
|
+
|
|
223
|
+
#### `actionItemCreateSchema`
|
|
224
|
+
|
|
225
|
+
Zod schema for validating action item creation payloads.
|
|
226
|
+
|
|
227
|
+
```typescript
|
|
228
|
+
const actionItemCreateSchema: z.ZodObject<
|
|
229
|
+
{
|
|
230
|
+
description: z.ZodString
|
|
231
|
+
assignee: z.ZodOptional<z.ZodNullable<z.ZodString>>
|
|
232
|
+
due_date: z.ZodOptional<z.ZodNullable<z.ZodString>>
|
|
233
|
+
source_excerpt: z.ZodOptional<z.ZodNullable<z.ZodString>>
|
|
234
|
+
},
|
|
235
|
+
z.core.$strip
|
|
236
|
+
>
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
#### `actionItemUpdateSchema`
|
|
240
|
+
|
|
241
|
+
Zod schema for validating action item update payloads.
|
|
242
|
+
|
|
243
|
+
```typescript
|
|
244
|
+
const actionItemUpdateSchema: z.ZodObject<
|
|
245
|
+
{
|
|
246
|
+
description: z.ZodOptional<z.ZodString>
|
|
247
|
+
assignee: z.ZodOptional<z.ZodOptional<z.ZodNullable<z.ZodString>>>
|
|
248
|
+
due_date: z.ZodOptional<z.ZodOptional<z.ZodNullable<z.ZodString>>>
|
|
249
|
+
source_excerpt: z.ZodOptional<z.ZodOptional<z.ZodNullable<z.ZodString>>>
|
|
250
|
+
is_completed: z.ZodOptional<z.ZodBoolean>
|
|
251
|
+
},
|
|
252
|
+
z.core.$strip
|
|
253
|
+
>
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
#### `MEETING_STATUSES`
|
|
257
|
+
|
|
258
|
+
All valid status values a meeting can be in.
|
|
259
|
+
|
|
260
|
+
```typescript
|
|
261
|
+
const MEETING_STATUSES: readonly ['scheduled', 'in_progress', 'completed', 'cancelled']
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
#### `meetingCreateSchema`
|
|
265
|
+
|
|
266
|
+
Zod schema for validating meeting creation payloads.
|
|
267
|
+
|
|
268
|
+
```typescript
|
|
269
|
+
const meetingCreateSchema: z.ZodObject<
|
|
270
|
+
{
|
|
271
|
+
title: z.ZodString
|
|
272
|
+
description: z.ZodOptional<z.ZodNullable<z.ZodString>>
|
|
273
|
+
scheduled_at: z.ZodOptional<z.ZodNullable<z.ZodString>>
|
|
274
|
+
attendees: z.ZodOptional<
|
|
275
|
+
z.ZodArray<
|
|
276
|
+
z.ZodObject<{ name: z.ZodString; email: z.ZodOptional<z.ZodString> }, z.core.$strip>
|
|
277
|
+
>
|
|
278
|
+
>
|
|
279
|
+
},
|
|
280
|
+
z.core.$strip
|
|
281
|
+
>
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
#### `meetingUpdateSchema`
|
|
285
|
+
|
|
286
|
+
Zod schema for validating meeting update payloads.
|
|
287
|
+
|
|
288
|
+
```typescript
|
|
289
|
+
const meetingUpdateSchema: z.ZodObject<
|
|
290
|
+
{
|
|
291
|
+
title: z.ZodOptional<z.ZodString>
|
|
292
|
+
description: z.ZodOptional<z.ZodNullable<z.ZodString>>
|
|
293
|
+
status: z.ZodOptional<
|
|
294
|
+
z.ZodEnum<{
|
|
295
|
+
scheduled: 'scheduled'
|
|
296
|
+
in_progress: 'in_progress'
|
|
297
|
+
completed: 'completed'
|
|
298
|
+
cancelled: 'cancelled'
|
|
299
|
+
}>
|
|
300
|
+
>
|
|
301
|
+
scheduled_at: z.ZodOptional<z.ZodNullable<z.ZodString>>
|
|
302
|
+
started_at: z.ZodOptional<z.ZodNullable<z.ZodString>>
|
|
303
|
+
ended_at: z.ZodOptional<z.ZodNullable<z.ZodString>>
|
|
304
|
+
recording_url: z.ZodOptional<z.ZodNullable<z.ZodString>>
|
|
305
|
+
transcript: z.ZodOptional<z.ZodNullable<z.ZodString>>
|
|
306
|
+
summary: z.ZodOptional<z.ZodNullable<z.ZodString>>
|
|
307
|
+
attendees: z.ZodOptional<
|
|
308
|
+
z.ZodArray<
|
|
309
|
+
z.ZodObject<{ name: z.ZodString; email: z.ZodOptional<z.ZodString> }, z.core.$strip>
|
|
310
|
+
>
|
|
311
|
+
>
|
|
312
|
+
},
|
|
313
|
+
z.core.$strip
|
|
314
|
+
>
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
## Injection Notes
|
|
318
|
+
|
|
319
|
+
### Requirements
|
|
320
|
+
|
|
321
|
+
Peer dependencies:
|
|
322
|
+
|
|
323
|
+
- `@molecule/api-bonds-default-express` ^1.0.1
|
|
324
|
+
- `@molecule/api-database` ^1.0.1
|
|
325
|
+
- `@molecule/api-i18n` ^1.0.1
|
|
326
|
+
- `@molecule/api-middleware-validation` ^1.0.1
|
|
327
|
+
- `express` ^5.0.0
|
|
328
|
+
- `zod` ^4.0.0
|
|
329
|
+
|
|
330
|
+
### Runtime Dependencies
|
|
331
|
+
|
|
332
|
+
- `@molecule/api-bonds-default-express`
|
|
333
|
+
- `@molecule/api-database`
|
|
334
|
+
- `@molecule/api-i18n`
|
|
335
|
+
- `@molecule/api-middleware-validation`
|
|
336
|
+
- `express`
|
|
337
|
+
- `zod`
|
|
338
|
+
|
|
339
|
+
Tables: `src/__setup__/meetings.sql` creates `meetings` +
|
|
340
|
+
`meeting_action_items`. An mlcl-scaffolded API replays `__setup__/*.sql`
|
|
341
|
+
automatically on migrate; anywhere else run it once — nothing at runtime
|
|
342
|
+
creates them.
|
|
343
|
+
|
|
344
|
+
The router does not authenticate — it reads the caller from
|
|
345
|
+
`res.locals.session` (populated by your global auth middleware) and 401s
|
|
346
|
+
without a session. All service functions are owner-scoped
|
|
347
|
+
(`…ForOwner(…, ownerId)` / `(meetingId, ownerId, …)`) and return `null`
|
|
348
|
+
for rows the caller doesn't own — always pass the AUTHENTICATED user's id.
|
package/package.json
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@molecule/api-resource-meeting",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"description": "Meeting capture + transcription + action-item extraction",
|
|
5
|
+
"homepage": "https://www.molecule.dev/packages/api-resource-meeting",
|
|
5
6
|
"type": "module",
|
|
6
7
|
"main": "dist/index.js",
|
|
7
8
|
"types": "dist/index.d.ts",
|
|
@@ -17,7 +18,8 @@
|
|
|
17
18
|
}
|
|
18
19
|
},
|
|
19
20
|
"files": [
|
|
20
|
-
"dist"
|
|
21
|
+
"dist",
|
|
22
|
+
"README.md"
|
|
21
23
|
],
|
|
22
24
|
"keywords": [
|
|
23
25
|
"molecule",
|
|
@@ -27,19 +29,24 @@
|
|
|
27
29
|
"resource"
|
|
28
30
|
],
|
|
29
31
|
"license": "Apache-2.0",
|
|
32
|
+
"repository": {
|
|
33
|
+
"type": "git",
|
|
34
|
+
"url": "https://github.com/molecule-dev/molecule.git",
|
|
35
|
+
"directory": "packages/api/resources/meeting"
|
|
36
|
+
},
|
|
30
37
|
"devDependencies": {
|
|
31
38
|
"@types/express": "5.0.6",
|
|
32
39
|
"@types/node": "26.1.2",
|
|
33
40
|
"express": "5.2.1",
|
|
34
41
|
"typescript": "6.0.3",
|
|
35
|
-
"vitest": "4.1.
|
|
42
|
+
"vitest": "4.1.11",
|
|
36
43
|
"zod": "4.4.3"
|
|
37
44
|
},
|
|
38
45
|
"peerDependencies": {
|
|
39
|
-
"@molecule/api-bonds-default-express": "^1.0.
|
|
40
|
-
"@molecule/api-database": "^1.0.
|
|
41
|
-
"@molecule/api-i18n": "^1.0.
|
|
42
|
-
"@molecule/api-middleware-validation": "^1.0.
|
|
46
|
+
"@molecule/api-bonds-default-express": "^1.0.1",
|
|
47
|
+
"@molecule/api-database": "^1.0.1",
|
|
48
|
+
"@molecule/api-i18n": "^1.0.1",
|
|
49
|
+
"@molecule/api-middleware-validation": "^1.0.1",
|
|
43
50
|
"express": "^5.0.0",
|
|
44
51
|
"zod": "^4.0.0"
|
|
45
52
|
}
|