@kelpie/schemas 0.1.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/LICENSE +661 -0
- package/README.md +33 -0
- package/dist/account.d.ts +79 -0
- package/dist/account.d.ts.map +1 -0
- package/dist/account.js +66 -0
- package/dist/account.js.map +1 -0
- package/dist/activity.d.ts +23 -0
- package/dist/activity.d.ts.map +1 -0
- package/dist/activity.js +27 -0
- package/dist/activity.js.map +1 -0
- package/dist/agentTask.d.ts +97 -0
- package/dist/agentTask.d.ts.map +1 -0
- package/dist/agentTask.js +127 -0
- package/dist/agentTask.js.map +1 -0
- package/dist/candidate.d.ts +39 -0
- package/dist/candidate.d.ts.map +1 -0
- package/dist/candidate.js +40 -0
- package/dist/candidate.js.map +1 -0
- package/dist/company.d.ts +38 -0
- package/dist/company.d.ts.map +1 -0
- package/dist/company.js +57 -0
- package/dist/company.js.map +1 -0
- package/dist/dashboard.d.ts +112 -0
- package/dist/dashboard.d.ts.map +1 -0
- package/dist/dashboard.js +165 -0
- package/dist/dashboard.js.map +1 -0
- package/dist/deal.d.ts +40 -0
- package/dist/deal.d.ts.map +1 -0
- package/dist/deal.js +59 -0
- package/dist/deal.js.map +1 -0
- package/dist/decision.d.ts +46 -0
- package/dist/decision.d.ts.map +1 -0
- package/dist/decision.js +48 -0
- package/dist/decision.js.map +1 -0
- package/dist/form.d.ts +97 -0
- package/dist/form.d.ts.map +1 -0
- package/dist/form.js +98 -0
- package/dist/form.js.map +1 -0
- package/dist/formSubmission.d.ts +47 -0
- package/dist/formSubmission.d.ts.map +1 -0
- package/dist/formSubmission.js +47 -0
- package/dist/formSubmission.js.map +1 -0
- package/dist/handbookPage.d.ts +52 -0
- package/dist/handbookPage.d.ts.map +1 -0
- package/dist/handbookPage.js +56 -0
- package/dist/handbookPage.js.map +1 -0
- package/dist/importExport.d.ts +143 -0
- package/dist/importExport.d.ts.map +1 -0
- package/dist/importExport.js +239 -0
- package/dist/importExport.js.map +1 -0
- package/dist/index.d.ts +75 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +45 -0
- package/dist/index.js.map +1 -0
- package/dist/invite.d.ts +35 -0
- package/dist/invite.d.ts.map +1 -0
- package/dist/invite.js +31 -0
- package/dist/invite.js.map +1 -0
- package/dist/mcpTool.d.ts +26 -0
- package/dist/mcpTool.d.ts.map +1 -0
- package/dist/mcpTool.js +13 -0
- package/dist/mcpTool.js.map +1 -0
- package/dist/member.d.ts +26 -0
- package/dist/member.d.ts.map +1 -0
- package/dist/member.js +24 -0
- package/dist/member.js.map +1 -0
- package/dist/moduleSetting.d.ts +19 -0
- package/dist/moduleSetting.d.ts.map +1 -0
- package/dist/moduleSetting.js +16 -0
- package/dist/moduleSetting.js.map +1 -0
- package/dist/note.d.ts +34 -0
- package/dist/note.d.ts.map +1 -0
- package/dist/note.js +35 -0
- package/dist/note.js.map +1 -0
- package/dist/opportunity.d.ts +30 -0
- package/dist/opportunity.d.ts.map +1 -0
- package/dist/opportunity.js +41 -0
- package/dist/opportunity.js.map +1 -0
- package/dist/partnership.d.ts +36 -0
- package/dist/partnership.d.ts.map +1 -0
- package/dist/partnership.js +50 -0
- package/dist/partnership.js.map +1 -0
- package/dist/person.d.ts +45 -0
- package/dist/person.d.ts.map +1 -0
- package/dist/person.js +60 -0
- package/dist/person.js.map +1 -0
- package/dist/pipelineStage.d.ts +29 -0
- package/dist/pipelineStage.d.ts.map +1 -0
- package/dist/pipelineStage.js +38 -0
- package/dist/pipelineStage.js.map +1 -0
- package/dist/planItem.d.ts +43 -0
- package/dist/planItem.d.ts.map +1 -0
- package/dist/planItem.js +44 -0
- package/dist/planItem.js.map +1 -0
- package/dist/position.d.ts +22 -0
- package/dist/position.d.ts.map +1 -0
- package/dist/position.js +25 -0
- package/dist/position.js.map +1 -0
- package/dist/raise.d.ts +38 -0
- package/dist/raise.d.ts.map +1 -0
- package/dist/raise.js +53 -0
- package/dist/raise.js.map +1 -0
- package/dist/role.d.ts +21 -0
- package/dist/role.d.ts.map +1 -0
- package/dist/role.js +21 -0
- package/dist/role.js.map +1 -0
- package/dist/search.d.ts +41 -0
- package/dist/search.d.ts.map +1 -0
- package/dist/search.js +41 -0
- package/dist/search.js.map +1 -0
- package/dist/session.d.ts +92 -0
- package/dist/session.d.ts.map +1 -0
- package/dist/session.js +67 -0
- package/dist/session.js.map +1 -0
- package/dist/values.d.ts +216 -0
- package/dist/values.d.ts.map +1 -0
- package/dist/values.js +329 -0
- package/dist/values.js.map +1 -0
- package/dist/webhook.d.ts +85 -0
- package/dist/webhook.d.ts.map +1 -0
- package/dist/webhook.js +75 -0
- package/dist/webhook.js.map +1 -0
- package/dist/wire.d.ts +40 -0
- package/dist/wire.d.ts.map +1 -0
- package/dist/wire.js +40 -0
- package/dist/wire.js.map +1 -0
- package/package.json +51 -0
- package/src/account.ts +149 -0
- package/src/activity.ts +52 -0
- package/src/agentTask.ts +254 -0
- package/src/candidate.ts +83 -0
- package/src/company.ts +98 -0
- package/src/dashboard.ts +307 -0
- package/src/deal.ts +102 -0
- package/src/decision.ts +106 -0
- package/src/form.ts +217 -0
- package/src/formSubmission.ts +99 -0
- package/src/handbookPage.ts +99 -0
- package/src/importExport.ts +339 -0
- package/src/index.ts +324 -0
- package/src/invite.ts +69 -0
- package/src/mcpTool.ts +32 -0
- package/src/member.ts +53 -0
- package/src/moduleSetting.ts +37 -0
- package/src/note.ts +73 -0
- package/src/opportunity.ts +74 -0
- package/src/partnership.ts +89 -0
- package/src/person.ts +116 -0
- package/src/pipelineStage.ts +71 -0
- package/src/planItem.ts +91 -0
- package/src/position.ts +50 -0
- package/src/raise.ts +94 -0
- package/src/role.ts +45 -0
- package/src/search.ts +86 -0
- package/src/session.ts +177 -0
- package/src/values.ts +427 -0
- package/src/webhook.ts +164 -0
- package/src/wire.ts +51 -0
package/src/invite.ts
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { z } from 'zod'
|
|
2
|
+
|
|
3
|
+
import { INVITABLE_ROLES, INVITE_STATUSES } from './values.ts'
|
|
4
|
+
import type { InvitableRole } from './values.ts'
|
|
5
|
+
import { idSchema, timestampSchema } from './wire.ts'
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Wire shapes for `/v1/workspaces/:id/invites`.
|
|
9
|
+
*
|
|
10
|
+
* `status` is derived from `expires_at` rather than stored, so a workspace that
|
|
11
|
+
* nobody has looked at still reports its stale invitations correctly. Nothing
|
|
12
|
+
* sweeps the table.
|
|
13
|
+
*
|
|
14
|
+
* Both write bodies carry `invite_url_template`: the service sends the email and
|
|
15
|
+
* has no idea what URL the caller's browser or agent is reachable at, so the
|
|
16
|
+
* caller supplies the address the token goes into.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
export interface Invite {
|
|
20
|
+
readonly id: string
|
|
21
|
+
readonly email: string
|
|
22
|
+
readonly role: InvitableRole
|
|
23
|
+
readonly status: (typeof INVITE_STATUSES)[number]
|
|
24
|
+
readonly expiresAt: Date
|
|
25
|
+
readonly createdAt: Date
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export const inviteSchema: z.ZodType<Invite, unknown> = z
|
|
29
|
+
.object({
|
|
30
|
+
id: idSchema,
|
|
31
|
+
email: z.string(),
|
|
32
|
+
role: z.enum(INVITABLE_ROLES),
|
|
33
|
+
status: z.enum(INVITE_STATUSES),
|
|
34
|
+
expires_at: timestampSchema,
|
|
35
|
+
created_at: timestampSchema,
|
|
36
|
+
})
|
|
37
|
+
.transform(
|
|
38
|
+
(wire): Invite => ({
|
|
39
|
+
id: wire.id,
|
|
40
|
+
email: wire.email,
|
|
41
|
+
role: wire.role,
|
|
42
|
+
status: wire.status,
|
|
43
|
+
expiresAt: wire.expires_at,
|
|
44
|
+
createdAt: wire.created_at,
|
|
45
|
+
}),
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
export interface CreateInviteInput {
|
|
49
|
+
readonly email: string
|
|
50
|
+
readonly role: InvitableRole
|
|
51
|
+
/** An absolute URL containing the literal `{token}`, which the email replaces. */
|
|
52
|
+
readonly inviteUrlTemplate: string
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export function createInviteBody(input: CreateInviteInput): Record<string, unknown> {
|
|
56
|
+
return {
|
|
57
|
+
email: input.email,
|
|
58
|
+
role: input.role,
|
|
59
|
+
invite_url_template: input.inviteUrlTemplate,
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export interface ResendInviteInput {
|
|
64
|
+
readonly inviteUrlTemplate: string
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export function resendInviteBody(input: ResendInviteInput): Record<string, unknown> {
|
|
68
|
+
return { invite_url_template: input.inviteUrlTemplate }
|
|
69
|
+
}
|
package/src/mcpTool.ts
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { z } from 'zod'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Wire shape for `GET /v1/mcp/tools`: what this deployment exposes over MCP.
|
|
5
|
+
*
|
|
6
|
+
* The same listing an MCP client gets from `tools/list`, read with ordinary
|
|
7
|
+
* credentials. A browser cannot call `/mcp` — it takes bearer keys only — so
|
|
8
|
+
* this is how the admin page shows what is actually registered rather than a
|
|
9
|
+
* hand-written copy that drifts.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
export interface McpTool {
|
|
13
|
+
/** `people_list`, `handbook_pages_get`, `import_commit`. Resource, then verb. */
|
|
14
|
+
readonly name: string
|
|
15
|
+
readonly description: string
|
|
16
|
+
/** JSON Schema for the tool's arguments, as the MCP client sees it. */
|
|
17
|
+
readonly inputSchema: Record<string, unknown>
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export const mcpToolSchema = z
|
|
21
|
+
.strictObject({
|
|
22
|
+
name: z.string().min(1),
|
|
23
|
+
description: z.string(),
|
|
24
|
+
input_schema: z.record(z.string(), z.unknown()),
|
|
25
|
+
})
|
|
26
|
+
.transform(
|
|
27
|
+
(wire): McpTool => ({
|
|
28
|
+
name: wire.name,
|
|
29
|
+
description: wire.description,
|
|
30
|
+
inputSchema: wire.input_schema,
|
|
31
|
+
}),
|
|
32
|
+
)
|
package/src/member.ts
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { z } from 'zod'
|
|
2
|
+
|
|
3
|
+
import { MEMBER_ROLES } from './values.ts'
|
|
4
|
+
import type { MemberRole } from './values.ts'
|
|
5
|
+
import { idSchema, timestampSchema } from './wire.ts'
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Wire shape for `GET /v1/workspaces/:id/members`.
|
|
9
|
+
*
|
|
10
|
+
* `id` is the membership, not the user. Notes and activities attribute to this
|
|
11
|
+
* id, so it is what a panel keys its name lookup on.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
export interface Member {
|
|
15
|
+
readonly id: string
|
|
16
|
+
readonly userId: string
|
|
17
|
+
readonly name: string
|
|
18
|
+
readonly email: string
|
|
19
|
+
readonly role: MemberRole
|
|
20
|
+
readonly joinedAt: Date
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export const memberSchema: z.ZodType<Member, unknown> = z
|
|
24
|
+
.object({
|
|
25
|
+
id: idSchema,
|
|
26
|
+
user_id: idSchema,
|
|
27
|
+
name: z.string(),
|
|
28
|
+
email: z.string(),
|
|
29
|
+
role: z.enum(MEMBER_ROLES),
|
|
30
|
+
joined_at: timestampSchema,
|
|
31
|
+
})
|
|
32
|
+
.transform(
|
|
33
|
+
(wire): Member => ({
|
|
34
|
+
id: wire.id,
|
|
35
|
+
userId: wire.user_id,
|
|
36
|
+
name: wire.name,
|
|
37
|
+
email: wire.email,
|
|
38
|
+
role: wire.role,
|
|
39
|
+
joinedAt: wire.joined_at,
|
|
40
|
+
}),
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
export interface UpdateMemberRoleInput {
|
|
44
|
+
/**
|
|
45
|
+
* `owner` transfers ownership: the workspace holds exactly one, so the caller
|
|
46
|
+
* giving it away becomes an admin in the same write.
|
|
47
|
+
*/
|
|
48
|
+
readonly role: MemberRole
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function updateMemberRoleBody(input: UpdateMemberRoleInput): Record<string, unknown> {
|
|
52
|
+
return { role: input.role }
|
|
53
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { z } from 'zod'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Wire shapes for `/v1/workspaces/:id/modules`.
|
|
5
|
+
*
|
|
6
|
+
* No `id` or timestamps: a setting is identified by `module_id`, and a reader
|
|
7
|
+
* only ever needs the current value, not its history.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
export interface ModuleSetting {
|
|
11
|
+
readonly moduleId: string
|
|
12
|
+
readonly enabled: boolean
|
|
13
|
+
/** True when a deploy-time config file holds this value, not the workspace's own choice. */
|
|
14
|
+
readonly locked: boolean
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export const moduleSettingSchema: z.ZodType<ModuleSetting, unknown> = z
|
|
18
|
+
.object({
|
|
19
|
+
module_id: z.string(),
|
|
20
|
+
enabled: z.boolean(),
|
|
21
|
+
locked: z.boolean(),
|
|
22
|
+
})
|
|
23
|
+
.transform(
|
|
24
|
+
(wire): ModuleSetting => ({
|
|
25
|
+
moduleId: wire.module_id,
|
|
26
|
+
enabled: wire.enabled,
|
|
27
|
+
locked: wire.locked,
|
|
28
|
+
}),
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
export interface UpdateModuleSettingInput {
|
|
32
|
+
readonly enabled: boolean
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function updateModuleSettingBody(input: UpdateModuleSettingInput): Record<string, unknown> {
|
|
36
|
+
return { enabled: input.enabled }
|
|
37
|
+
}
|
package/src/note.ts
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { z } from 'zod'
|
|
2
|
+
|
|
3
|
+
import { RECORD_TARGET_TYPES } from './values.ts'
|
|
4
|
+
import type { RecordTargetType } from './values.ts'
|
|
5
|
+
import { definedFields, idSchema, recordTimestamps } from './wire.ts'
|
|
6
|
+
import type { RecordTimestamps } from './wire.ts'
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Wire and write shapes for `/v1/notes`.
|
|
10
|
+
*
|
|
11
|
+
* `authorId` is a workspace member id, not a user id. It is null when no member
|
|
12
|
+
* was behind the write, which today means a workspace API key. Resolving it to a
|
|
13
|
+
* name is the caller's job: `api.md` has no include-expansion, so a panel joins
|
|
14
|
+
* against the workspace member list it already holds.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
export interface Note extends RecordTimestamps {
|
|
18
|
+
readonly id: string
|
|
19
|
+
readonly targetType: RecordTargetType
|
|
20
|
+
readonly targetId: string
|
|
21
|
+
readonly body: string
|
|
22
|
+
readonly authorId: string | null
|
|
23
|
+
readonly pinned: boolean
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export const noteSchema: z.ZodType<Note, unknown> = z
|
|
27
|
+
.object({
|
|
28
|
+
id: idSchema,
|
|
29
|
+
target_type: z.enum(RECORD_TARGET_TYPES),
|
|
30
|
+
target_id: idSchema,
|
|
31
|
+
body: z.string(),
|
|
32
|
+
author_id: idSchema.nullable(),
|
|
33
|
+
pinned: z.boolean(),
|
|
34
|
+
...recordTimestamps,
|
|
35
|
+
})
|
|
36
|
+
.transform(
|
|
37
|
+
(wire): Note => ({
|
|
38
|
+
id: wire.id,
|
|
39
|
+
targetType: wire.target_type,
|
|
40
|
+
targetId: wire.target_id,
|
|
41
|
+
body: wire.body,
|
|
42
|
+
authorId: wire.author_id,
|
|
43
|
+
pinned: wire.pinned,
|
|
44
|
+
createdAt: wire.created_at,
|
|
45
|
+
updatedAt: wire.updated_at,
|
|
46
|
+
}),
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
export interface CreateNoteInput {
|
|
50
|
+
readonly targetType: RecordTargetType
|
|
51
|
+
readonly targetId: string
|
|
52
|
+
readonly body: string
|
|
53
|
+
readonly pinned?: boolean
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export function createNoteBody(input: CreateNoteInput): Record<string, unknown> {
|
|
57
|
+
return definedFields({
|
|
58
|
+
target_type: input.targetType,
|
|
59
|
+
target_id: input.targetId,
|
|
60
|
+
body: input.body,
|
|
61
|
+
pinned: input.pinned,
|
|
62
|
+
})
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/** The target never moves: re-filing a note under another record is a delete and a create. */
|
|
66
|
+
export interface NoteInput {
|
|
67
|
+
readonly body?: string
|
|
68
|
+
readonly pinned?: boolean
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export function noteBody(input: NoteInput): Record<string, unknown> {
|
|
72
|
+
return definedFields({ body: input.body, pinned: input.pinned })
|
|
73
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { z } from 'zod'
|
|
2
|
+
|
|
3
|
+
import { definedFields, idSchema, recordTimestamps } from './wire.ts'
|
|
4
|
+
import type { RecordTimestamps } from './wire.ts'
|
|
5
|
+
|
|
6
|
+
/** Wire and write shapes for `/v1/opportunities`. */
|
|
7
|
+
|
|
8
|
+
export interface Opportunity extends RecordTimestamps {
|
|
9
|
+
readonly id: string
|
|
10
|
+
readonly name: string
|
|
11
|
+
/** Free text ("Grant", "Accelerator", …), not an enum: the seed's own kinds vary by workspace. */
|
|
12
|
+
readonly kind: string
|
|
13
|
+
readonly stageId: string
|
|
14
|
+
/** Nullable: a speaking slot or a grant need not belong to a company on file. */
|
|
15
|
+
readonly companyId: string | null
|
|
16
|
+
readonly ownerId: string | null
|
|
17
|
+
/** `YYYY-MM-DD`, per `api.md` date-only fields. */
|
|
18
|
+
readonly expectedClose: string | null
|
|
19
|
+
readonly summary: string
|
|
20
|
+
readonly tags: readonly string[]
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export const opportunitySchema: z.ZodType<Opportunity, unknown> = z
|
|
24
|
+
.object({
|
|
25
|
+
id: idSchema,
|
|
26
|
+
name: z.string(),
|
|
27
|
+
kind: z.string(),
|
|
28
|
+
stage_id: idSchema,
|
|
29
|
+
company_id: idSchema.nullable(),
|
|
30
|
+
owner_id: idSchema.nullable(),
|
|
31
|
+
expected_close: z.string().nullable(),
|
|
32
|
+
summary: z.string(),
|
|
33
|
+
tags: z.array(z.string()),
|
|
34
|
+
...recordTimestamps,
|
|
35
|
+
})
|
|
36
|
+
.transform(
|
|
37
|
+
(wire): Opportunity => ({
|
|
38
|
+
id: wire.id,
|
|
39
|
+
name: wire.name,
|
|
40
|
+
kind: wire.kind,
|
|
41
|
+
stageId: wire.stage_id,
|
|
42
|
+
companyId: wire.company_id,
|
|
43
|
+
ownerId: wire.owner_id,
|
|
44
|
+
expectedClose: wire.expected_close,
|
|
45
|
+
summary: wire.summary,
|
|
46
|
+
tags: wire.tags,
|
|
47
|
+
createdAt: wire.created_at,
|
|
48
|
+
updatedAt: wire.updated_at,
|
|
49
|
+
}),
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
export interface OpportunityInput {
|
|
53
|
+
readonly name?: string
|
|
54
|
+
readonly kind?: string
|
|
55
|
+
readonly stageId?: string
|
|
56
|
+
readonly companyId?: string | null
|
|
57
|
+
readonly ownerId?: string | null
|
|
58
|
+
readonly expectedClose?: string | null
|
|
59
|
+
readonly summary?: string
|
|
60
|
+
readonly tags?: readonly string[]
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export function opportunityBody(input: OpportunityInput): Record<string, unknown> {
|
|
64
|
+
return definedFields({
|
|
65
|
+
name: input.name,
|
|
66
|
+
kind: input.kind,
|
|
67
|
+
stage_id: input.stageId,
|
|
68
|
+
company_id: input.companyId,
|
|
69
|
+
owner_id: input.ownerId,
|
|
70
|
+
expected_close: input.expectedClose,
|
|
71
|
+
summary: input.summary,
|
|
72
|
+
tags: input.tags,
|
|
73
|
+
})
|
|
74
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { z } from 'zod'
|
|
2
|
+
|
|
3
|
+
import { definedFields, idSchema, recordTimestamps } from './wire.ts'
|
|
4
|
+
import type { RecordTimestamps } from './wire.ts'
|
|
5
|
+
|
|
6
|
+
/** Wire and write shapes for `/v1/partnerships`. */
|
|
7
|
+
|
|
8
|
+
export interface Partnership extends RecordTimestamps {
|
|
9
|
+
readonly id: string
|
|
10
|
+
readonly name: string
|
|
11
|
+
/** Required: a partnership is with an organisation, unlike an opportunity. */
|
|
12
|
+
readonly companyId: string
|
|
13
|
+
readonly stageId: string
|
|
14
|
+
/** Free text ("Integration", "Co-marketing", …), not an enum: the seed's own kinds vary by workspace. */
|
|
15
|
+
readonly kind: string
|
|
16
|
+
/** `YYYY-MM-DD`, per `api.md` date-only fields. */
|
|
17
|
+
readonly nextTouchpoint: string | null
|
|
18
|
+
readonly ownerId: string | null
|
|
19
|
+
readonly goals: string
|
|
20
|
+
readonly successLooksLike: string
|
|
21
|
+
readonly personIds: readonly string[]
|
|
22
|
+
readonly summary: string
|
|
23
|
+
readonly tags: readonly string[]
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export const partnershipSchema: z.ZodType<Partnership, unknown> = z
|
|
27
|
+
.object({
|
|
28
|
+
id: idSchema,
|
|
29
|
+
name: z.string(),
|
|
30
|
+
company_id: idSchema,
|
|
31
|
+
stage_id: idSchema,
|
|
32
|
+
kind: z.string(),
|
|
33
|
+
next_touchpoint: z.string().nullable(),
|
|
34
|
+
owner_id: idSchema.nullable(),
|
|
35
|
+
goals: z.string(),
|
|
36
|
+
success_looks_like: z.string(),
|
|
37
|
+
person_ids: z.array(idSchema),
|
|
38
|
+
summary: z.string(),
|
|
39
|
+
tags: z.array(z.string()),
|
|
40
|
+
...recordTimestamps,
|
|
41
|
+
})
|
|
42
|
+
.transform(
|
|
43
|
+
(wire): Partnership => ({
|
|
44
|
+
id: wire.id,
|
|
45
|
+
name: wire.name,
|
|
46
|
+
companyId: wire.company_id,
|
|
47
|
+
stageId: wire.stage_id,
|
|
48
|
+
kind: wire.kind,
|
|
49
|
+
nextTouchpoint: wire.next_touchpoint,
|
|
50
|
+
ownerId: wire.owner_id,
|
|
51
|
+
goals: wire.goals,
|
|
52
|
+
successLooksLike: wire.success_looks_like,
|
|
53
|
+
personIds: wire.person_ids,
|
|
54
|
+
summary: wire.summary,
|
|
55
|
+
tags: wire.tags,
|
|
56
|
+
createdAt: wire.created_at,
|
|
57
|
+
updatedAt: wire.updated_at,
|
|
58
|
+
}),
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
export interface PartnershipInput {
|
|
62
|
+
readonly name?: string
|
|
63
|
+
readonly companyId?: string
|
|
64
|
+
readonly stageId?: string
|
|
65
|
+
readonly kind?: string
|
|
66
|
+
readonly nextTouchpoint?: string | null
|
|
67
|
+
readonly ownerId?: string | null
|
|
68
|
+
readonly goals?: string
|
|
69
|
+
readonly successLooksLike?: string
|
|
70
|
+
readonly personIds?: readonly string[]
|
|
71
|
+
readonly summary?: string
|
|
72
|
+
readonly tags?: readonly string[]
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export function partnershipBody(input: PartnershipInput): Record<string, unknown> {
|
|
76
|
+
return definedFields({
|
|
77
|
+
name: input.name,
|
|
78
|
+
company_id: input.companyId,
|
|
79
|
+
stage_id: input.stageId,
|
|
80
|
+
kind: input.kind,
|
|
81
|
+
next_touchpoint: input.nextTouchpoint,
|
|
82
|
+
owner_id: input.ownerId,
|
|
83
|
+
goals: input.goals,
|
|
84
|
+
success_looks_like: input.successLooksLike,
|
|
85
|
+
person_ids: input.personIds,
|
|
86
|
+
summary: input.summary,
|
|
87
|
+
tags: input.tags,
|
|
88
|
+
})
|
|
89
|
+
}
|
package/src/person.ts
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { z } from 'zod'
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
INFLUENCE_LEVELS,
|
|
5
|
+
PREFERRED_CHANNELS,
|
|
6
|
+
RELATIONSHIP_LEVELS,
|
|
7
|
+
SOCIAL_NETWORK_IDS,
|
|
8
|
+
} from './values.ts'
|
|
9
|
+
import type { Influence, PreferredChannel, Relationship, SocialNetworkId } from './values.ts'
|
|
10
|
+
import { definedFields, idSchema, nullableTimestampSchema, recordTimestamps } from './wire.ts'
|
|
11
|
+
import type { RecordTimestamps } from './wire.ts'
|
|
12
|
+
|
|
13
|
+
/** Wire and write shapes for `/v1/people`. Job title is not here: it lives on Position. */
|
|
14
|
+
|
|
15
|
+
export interface SocialProfile {
|
|
16
|
+
readonly network: SocialNetworkId
|
|
17
|
+
readonly url: string
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface Person extends RecordTimestamps {
|
|
21
|
+
readonly id: string
|
|
22
|
+
readonly name: string
|
|
23
|
+
readonly email: string | null
|
|
24
|
+
readonly phones: readonly string[]
|
|
25
|
+
readonly socialProfiles: readonly SocialProfile[]
|
|
26
|
+
readonly timezone: string | null
|
|
27
|
+
readonly location: string | null
|
|
28
|
+
readonly preferredChannel: PreferredChannel
|
|
29
|
+
readonly influence: Influence
|
|
30
|
+
readonly relationship: Relationship
|
|
31
|
+
readonly summary: string
|
|
32
|
+
readonly tags: readonly string[]
|
|
33
|
+
readonly lastContactedAt: Date | null
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const socialProfileSchema = z.object({
|
|
37
|
+
network: z.enum(SOCIAL_NETWORK_IDS),
|
|
38
|
+
url: z.string(),
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
export const personSchema: z.ZodType<Person, unknown> = z
|
|
42
|
+
.object({
|
|
43
|
+
id: idSchema,
|
|
44
|
+
name: z.string(),
|
|
45
|
+
email: z.string().nullable(),
|
|
46
|
+
phones: z.array(z.string()),
|
|
47
|
+
social_profiles: z.array(socialProfileSchema),
|
|
48
|
+
timezone: z.string().nullable(),
|
|
49
|
+
location: z.string().nullable(),
|
|
50
|
+
preferred_channel: z.enum(PREFERRED_CHANNELS),
|
|
51
|
+
influence: z.enum(INFLUENCE_LEVELS),
|
|
52
|
+
relationship: z.enum(RELATIONSHIP_LEVELS),
|
|
53
|
+
summary: z.string(),
|
|
54
|
+
tags: z.array(z.string()),
|
|
55
|
+
last_contacted_at: nullableTimestampSchema,
|
|
56
|
+
...recordTimestamps,
|
|
57
|
+
})
|
|
58
|
+
.transform(
|
|
59
|
+
(wire): Person => ({
|
|
60
|
+
id: wire.id,
|
|
61
|
+
name: wire.name,
|
|
62
|
+
email: wire.email,
|
|
63
|
+
phones: wire.phones,
|
|
64
|
+
socialProfiles: wire.social_profiles,
|
|
65
|
+
timezone: wire.timezone,
|
|
66
|
+
location: wire.location,
|
|
67
|
+
preferredChannel: wire.preferred_channel,
|
|
68
|
+
influence: wire.influence,
|
|
69
|
+
relationship: wire.relationship,
|
|
70
|
+
summary: wire.summary,
|
|
71
|
+
tags: wire.tags,
|
|
72
|
+
lastContactedAt: wire.last_contacted_at,
|
|
73
|
+
createdAt: wire.created_at,
|
|
74
|
+
updatedAt: wire.updated_at,
|
|
75
|
+
}),
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* A create or update body. Every field is optional because `POST` defaults all
|
|
80
|
+
* but `name` server-side and `PATCH` sends only what changed; `name` is required
|
|
81
|
+
* on create by the route, not by this type.
|
|
82
|
+
*/
|
|
83
|
+
export interface PersonInput {
|
|
84
|
+
readonly name?: string
|
|
85
|
+
readonly email?: string | null
|
|
86
|
+
readonly phones?: readonly string[]
|
|
87
|
+
readonly socialProfiles?: readonly SocialProfile[]
|
|
88
|
+
readonly timezone?: string | null
|
|
89
|
+
readonly location?: string | null
|
|
90
|
+
readonly preferredChannel?: PreferredChannel
|
|
91
|
+
readonly influence?: Influence
|
|
92
|
+
readonly relationship?: Relationship
|
|
93
|
+
readonly summary?: string
|
|
94
|
+
readonly tags?: readonly string[]
|
|
95
|
+
readonly lastContactedAt?: Date | null
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export function personBody(input: PersonInput): Record<string, unknown> {
|
|
99
|
+
return definedFields({
|
|
100
|
+
name: input.name,
|
|
101
|
+
email: input.email,
|
|
102
|
+
phones: input.phones,
|
|
103
|
+
social_profiles: input.socialProfiles,
|
|
104
|
+
timezone: input.timezone,
|
|
105
|
+
location: input.location,
|
|
106
|
+
preferred_channel: input.preferredChannel,
|
|
107
|
+
influence: input.influence,
|
|
108
|
+
relationship: input.relationship,
|
|
109
|
+
summary: input.summary,
|
|
110
|
+
tags: input.tags,
|
|
111
|
+
last_contacted_at:
|
|
112
|
+
input.lastContactedAt === undefined || input.lastContactedAt === null
|
|
113
|
+
? input.lastContactedAt
|
|
114
|
+
: input.lastContactedAt.toISOString(),
|
|
115
|
+
})
|
|
116
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { z } from 'zod'
|
|
2
|
+
|
|
3
|
+
import { PIPELINE_KINDS } from './values.ts'
|
|
4
|
+
import type { PipelineKind } from './values.ts'
|
|
5
|
+
import { definedFields, idSchema, recordTimestamps } from './wire.ts'
|
|
6
|
+
import type { RecordTimestamps } from './wire.ts'
|
|
7
|
+
|
|
8
|
+
/** Wire and write shapes for `/v1/pipeline_stages`. */
|
|
9
|
+
|
|
10
|
+
export interface PipelineStage extends RecordTimestamps {
|
|
11
|
+
readonly id: string
|
|
12
|
+
readonly kind: PipelineKind
|
|
13
|
+
/** The stable import-alias id. Renaming the label never moves it. */
|
|
14
|
+
readonly slug: string
|
|
15
|
+
readonly label: string
|
|
16
|
+
/** When false, hidden from the board's Open scope. */
|
|
17
|
+
readonly open: boolean
|
|
18
|
+
readonly sortOrder: number
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export const pipelineStageSchema: z.ZodType<PipelineStage, unknown> = z
|
|
22
|
+
.object({
|
|
23
|
+
id: idSchema,
|
|
24
|
+
kind: z.enum(PIPELINE_KINDS),
|
|
25
|
+
slug: z.string(),
|
|
26
|
+
label: z.string(),
|
|
27
|
+
open: z.boolean(),
|
|
28
|
+
sort_order: z.number().int(),
|
|
29
|
+
...recordTimestamps,
|
|
30
|
+
})
|
|
31
|
+
.transform(
|
|
32
|
+
(wire): PipelineStage => ({
|
|
33
|
+
id: wire.id,
|
|
34
|
+
kind: wire.kind,
|
|
35
|
+
slug: wire.slug,
|
|
36
|
+
label: wire.label,
|
|
37
|
+
open: wire.open,
|
|
38
|
+
sortOrder: wire.sort_order,
|
|
39
|
+
createdAt: wire.created_at,
|
|
40
|
+
updatedAt: wire.updated_at,
|
|
41
|
+
}),
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
export interface CreatePipelineStageInput {
|
|
45
|
+
readonly kind: PipelineKind
|
|
46
|
+
readonly label: string
|
|
47
|
+
readonly open?: boolean
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export function createPipelineStageBody(input: CreatePipelineStageInput): Record<string, unknown> {
|
|
51
|
+
return definedFields({
|
|
52
|
+
kind: input.kind,
|
|
53
|
+
label: input.label,
|
|
54
|
+
open: input.open,
|
|
55
|
+
})
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export interface UpdatePipelineStageInput {
|
|
59
|
+
readonly label?: string
|
|
60
|
+
readonly open?: boolean
|
|
61
|
+
/** The stage's new 0-based position on its board. */
|
|
62
|
+
readonly sortOrder?: number
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export function updatePipelineStageBody(input: UpdatePipelineStageInput): Record<string, unknown> {
|
|
66
|
+
return definedFields({
|
|
67
|
+
label: input.label,
|
|
68
|
+
open: input.open,
|
|
69
|
+
sort_order: input.sortOrder,
|
|
70
|
+
})
|
|
71
|
+
}
|