@automate.ax/api-contract 0.7.0 → 0.8.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/README.md +2 -1
- package/dist/deployment.d.ts +0 -5
- package/dist/deployment.js +0 -7
- package/dist/index.d.ts +678 -52
- package/dist/index.js +53 -5
- package/dist/runtime.d.ts +1 -1
- package/dist/runtime.js +1 -1
- package/package.json +8 -3
- package/src/api-key.ts +84 -0
- package/src/auth.ts +39 -0
- package/src/authorization.ts +151 -0
- package/src/deployment.ts +107 -0
- package/src/events/gmail.ts +34 -0
- package/src/events/google-calendar.ts +18 -0
- package/src/events/google-forms.ts +41 -0
- package/src/events/index.ts +9 -0
- package/src/index.ts +100 -0
- package/src/org.ts +205 -0
- package/src/project.ts +104 -0
- package/src/runtime.ts +113 -0
- package/src/schemas.ts +3 -0
package/dist/index.js
CHANGED
|
@@ -7,19 +7,67 @@ import { orgContract } from "./org.js";
|
|
|
7
7
|
import { projectContract } from "./project.js";
|
|
8
8
|
import { runtimeContract } from "./runtime.js";
|
|
9
9
|
export { AUTOMATION_SDK_VERSION, deploymentTriggerInfoSchema, } from "./deployment.js";
|
|
10
|
+
export { runtimeContract } from "./runtime.js";
|
|
10
11
|
export { createdOrganizationApiKeyOutputSchema, organizationApiKeyOutputSchema, } from "./api-key.js";
|
|
11
12
|
export { integrationServiceManifestSchema, } from "./authorization.js";
|
|
12
13
|
export { activeSubscriptionOutputSchema, createdInvitationOutputSchema, organizationDetailsOutputSchema, organizationInvitationOutputSchema, organizationMemberOutputSchema, organizationProjectOutputSchema, organizationRoleSchema, organizationSummaryOutputSchema, publicOrganizationOutputSchema, } from "./org.js";
|
|
13
14
|
export { projectOutputSchema, projectWithOrganizationOutputSchema, } from "./project.js";
|
|
14
15
|
export { reasonableNameSchema } from "./schemas.js";
|
|
15
16
|
export { userOutputSchema } from "./auth.js";
|
|
16
|
-
|
|
17
|
+
/** Procedures exposed by the public Node client and OpenAPI document. */
|
|
18
|
+
export const publicContract = {
|
|
17
19
|
apiKey: apiKeyContract,
|
|
18
|
-
|
|
20
|
+
org: {
|
|
21
|
+
create: orgContract.create,
|
|
22
|
+
delete: orgContract.delete,
|
|
23
|
+
get: orgContract.get,
|
|
24
|
+
invite: orgContract.invite,
|
|
25
|
+
leave: orgContract.leave,
|
|
26
|
+
list: orgContract.list,
|
|
27
|
+
remove: orgContract.remove,
|
|
28
|
+
update: orgContract.update,
|
|
29
|
+
},
|
|
30
|
+
project: {
|
|
31
|
+
create: projectContract.create,
|
|
32
|
+
delete: projectContract.delete,
|
|
33
|
+
get: projectContract.get,
|
|
34
|
+
list: projectContract.list,
|
|
35
|
+
update: projectContract.update,
|
|
36
|
+
},
|
|
37
|
+
session: {
|
|
38
|
+
me: authContract.me,
|
|
39
|
+
},
|
|
40
|
+
};
|
|
41
|
+
/** Procedures used by first-party control-plane clients. */
|
|
42
|
+
export const firstPartyContract = {
|
|
43
|
+
...publicContract,
|
|
44
|
+
authorization: {
|
|
45
|
+
beginConnection: authorizationContract.beginConnection,
|
|
46
|
+
get: authorizationContract.get,
|
|
47
|
+
selectAccount: authorizationContract.selectAccount,
|
|
48
|
+
submitCredentials: authorizationContract.submitCredentials,
|
|
49
|
+
},
|
|
19
50
|
deployment: deploymentContract,
|
|
51
|
+
org: {
|
|
52
|
+
...publicContract.org,
|
|
53
|
+
canInvite: orgContract.canInvite,
|
|
54
|
+
},
|
|
55
|
+
project: {
|
|
56
|
+
...publicContract.project,
|
|
57
|
+
canCreate: projectContract.canCreate,
|
|
58
|
+
},
|
|
59
|
+
session: {
|
|
60
|
+
...publicContract.session,
|
|
61
|
+
linkDeviceSession: authContract.linkDeviceSession,
|
|
62
|
+
},
|
|
63
|
+
};
|
|
64
|
+
/** Complete contract implemented by the API service. */
|
|
65
|
+
export const contract = {
|
|
66
|
+
...firstPartyContract,
|
|
67
|
+
authorization: {
|
|
68
|
+
...firstPartyContract.authorization,
|
|
69
|
+
callback: authorizationContract.callback,
|
|
70
|
+
},
|
|
20
71
|
events: eventsContract,
|
|
21
|
-
org: orgContract,
|
|
22
|
-
project: projectContract,
|
|
23
72
|
runtime: runtimeContract,
|
|
24
|
-
session: authContract,
|
|
25
73
|
};
|
package/dist/runtime.d.ts
CHANGED
|
@@ -64,7 +64,7 @@ export declare const runtimeContract: {
|
|
|
64
64
|
sendEmail: import("@orpc/contract").ContractProcedureBuilderWithInputOutput<z.ZodObject<{
|
|
65
65
|
subject: z.ZodString;
|
|
66
66
|
text: z.ZodString;
|
|
67
|
-
to: z.ZodEmail
|
|
67
|
+
to: z.ZodUnion<readonly [z.ZodEmail, z.ZodLiteral<"*">]>;
|
|
68
68
|
}, z.core.$strip>, z.ZodObject<{
|
|
69
69
|
id: z.ZodNullable<z.ZodString>;
|
|
70
70
|
}, z.core.$strip>, Record<never, never>, Record<never, never>>;
|
package/dist/runtime.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@automate.ax/api-contract",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"description": "Public oRPC contract for the Automate.ax API.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -20,10 +20,13 @@
|
|
|
20
20
|
"exports": {
|
|
21
21
|
".": "./src/index.ts"
|
|
22
22
|
},
|
|
23
|
-
"cjs": false
|
|
23
|
+
"cjs": false,
|
|
24
|
+
"conditions": {
|
|
25
|
+
"bun": "src"
|
|
26
|
+
}
|
|
24
27
|
},
|
|
25
28
|
"dependencies": {
|
|
26
|
-
"@automate.ax/codec": "0.
|
|
29
|
+
"@automate.ax/codec": "0.8.0",
|
|
27
30
|
"@orpc/contract": "1.13.14",
|
|
28
31
|
"zod": "^4.3.6"
|
|
29
32
|
},
|
|
@@ -48,6 +51,7 @@
|
|
|
48
51
|
},
|
|
49
52
|
"files": [
|
|
50
53
|
"dist",
|
|
54
|
+
"src",
|
|
51
55
|
"README.md",
|
|
52
56
|
"LICENSE"
|
|
53
57
|
],
|
|
@@ -59,6 +63,7 @@
|
|
|
59
63
|
},
|
|
60
64
|
"exports": {
|
|
61
65
|
".": {
|
|
66
|
+
"bun": "./src/index.ts",
|
|
62
67
|
"types": "./dist/index.d.ts",
|
|
63
68
|
"default": "./dist/index.js"
|
|
64
69
|
}
|
package/src/api-key.ts
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { oc } from "@orpc/contract"
|
|
2
|
+
import { z } from "zod"
|
|
3
|
+
import { reasonableNameSchema } from "./schemas"
|
|
4
|
+
|
|
5
|
+
export const organizationApiKeyOutputSchema = z.object({
|
|
6
|
+
id: z.string(),
|
|
7
|
+
name: z.string().nullable(),
|
|
8
|
+
start: z.string().nullable(),
|
|
9
|
+
createdAt: z.date(),
|
|
10
|
+
updatedAt: z.date(),
|
|
11
|
+
expiresAt: z.date().nullable(),
|
|
12
|
+
})
|
|
13
|
+
|
|
14
|
+
export const createdOrganizationApiKeyOutputSchema =
|
|
15
|
+
organizationApiKeyOutputSchema.extend({
|
|
16
|
+
key: z.string(),
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
export const apiKeyContract = {
|
|
20
|
+
create: oc
|
|
21
|
+
.route({
|
|
22
|
+
method: "POST",
|
|
23
|
+
path: "/organizations/{organizationId}/api-keys",
|
|
24
|
+
operationId: "createOrganizationApiKey",
|
|
25
|
+
summary: "Create organization API key",
|
|
26
|
+
description:
|
|
27
|
+
"Creates an API key owned by the organization. The secret is returned once.",
|
|
28
|
+
successStatus: 201,
|
|
29
|
+
successDescription: "API key created.",
|
|
30
|
+
tags: ["API Keys"],
|
|
31
|
+
})
|
|
32
|
+
.input(
|
|
33
|
+
z.object({
|
|
34
|
+
organizationId: z.string(),
|
|
35
|
+
name: reasonableNameSchema,
|
|
36
|
+
}),
|
|
37
|
+
)
|
|
38
|
+
.output(createdOrganizationApiKeyOutputSchema),
|
|
39
|
+
delete: oc
|
|
40
|
+
.route({
|
|
41
|
+
method: "DELETE",
|
|
42
|
+
path: "/organizations/{organizationId}/api-keys/{keyId}",
|
|
43
|
+
operationId: "deleteOrganizationApiKey",
|
|
44
|
+
summary: "Delete organization API key",
|
|
45
|
+
description: "Permanently revokes an organization API key.",
|
|
46
|
+
successStatus: 204,
|
|
47
|
+
tags: ["API Keys"],
|
|
48
|
+
})
|
|
49
|
+
.input(
|
|
50
|
+
z.object({
|
|
51
|
+
keyId: z.string(),
|
|
52
|
+
organizationId: z.string(),
|
|
53
|
+
}),
|
|
54
|
+
)
|
|
55
|
+
.output(z.void()),
|
|
56
|
+
list: oc
|
|
57
|
+
.route({
|
|
58
|
+
method: "GET",
|
|
59
|
+
path: "/organizations/{organizationId}/api-keys",
|
|
60
|
+
operationId: "listOrganizationApiKeys",
|
|
61
|
+
summary: "List organization API keys",
|
|
62
|
+
description: "Lists API keys owned by an organization.",
|
|
63
|
+
tags: ["API Keys"],
|
|
64
|
+
})
|
|
65
|
+
.input(z.object({ organizationId: z.string() }))
|
|
66
|
+
.output(organizationApiKeyOutputSchema.array()),
|
|
67
|
+
update: oc
|
|
68
|
+
.route({
|
|
69
|
+
method: "PATCH",
|
|
70
|
+
path: "/organizations/{organizationId}/api-keys/{keyId}",
|
|
71
|
+
operationId: "updateOrganizationApiKey",
|
|
72
|
+
summary: "Update organization API key",
|
|
73
|
+
description: "Updates an organization API key's display name.",
|
|
74
|
+
tags: ["API Keys"],
|
|
75
|
+
})
|
|
76
|
+
.input(
|
|
77
|
+
z.object({
|
|
78
|
+
keyId: z.string(),
|
|
79
|
+
name: reasonableNameSchema,
|
|
80
|
+
organizationId: z.string(),
|
|
81
|
+
}),
|
|
82
|
+
)
|
|
83
|
+
.output(organizationApiKeyOutputSchema),
|
|
84
|
+
}
|
package/src/auth.ts
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { oc } from "@orpc/contract"
|
|
2
|
+
import { z } from "zod"
|
|
3
|
+
|
|
4
|
+
export const userOutputSchema = z.object({
|
|
5
|
+
id: z.string(),
|
|
6
|
+
name: z.string(),
|
|
7
|
+
email: z.email(),
|
|
8
|
+
emailVerified: z.boolean(),
|
|
9
|
+
image: z.string().nullable().optional(),
|
|
10
|
+
createdAt: z.date(),
|
|
11
|
+
updatedAt: z.date(),
|
|
12
|
+
})
|
|
13
|
+
|
|
14
|
+
export const authContract = {
|
|
15
|
+
me: oc
|
|
16
|
+
.route({
|
|
17
|
+
method: "GET",
|
|
18
|
+
path: "/me",
|
|
19
|
+
operationId: "getCurrentUser",
|
|
20
|
+
summary: "Get current user",
|
|
21
|
+
description:
|
|
22
|
+
"Returns the authenticated user for the current bearer token or cookie session.",
|
|
23
|
+
tags: ["Session"],
|
|
24
|
+
})
|
|
25
|
+
.output(userOutputSchema),
|
|
26
|
+
linkDeviceSession: oc
|
|
27
|
+
.route({
|
|
28
|
+
method: "POST",
|
|
29
|
+
path: "/me/session/link-device",
|
|
30
|
+
operationId: "linkDeviceSession",
|
|
31
|
+
summary: "Link device session",
|
|
32
|
+
description:
|
|
33
|
+
"Migrates anonymous-session data into authenticated user context.",
|
|
34
|
+
tags: ["Session"],
|
|
35
|
+
successStatus: 204,
|
|
36
|
+
})
|
|
37
|
+
.input(z.object({ newAccessToken: z.string() }))
|
|
38
|
+
.output(z.void()),
|
|
39
|
+
}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import { oc } from "@orpc/contract"
|
|
2
|
+
import { z } from "zod"
|
|
3
|
+
|
|
4
|
+
const integrationFormFieldBaseSchema = z.object({
|
|
5
|
+
description: z.string().optional(),
|
|
6
|
+
label: z.string().min(1),
|
|
7
|
+
name: z.string().min(1),
|
|
8
|
+
required: z.boolean(),
|
|
9
|
+
})
|
|
10
|
+
|
|
11
|
+
const INTEGRATION_FORM_FIELD_SCHEMA = z.discriminatedUnion("input", [
|
|
12
|
+
integrationFormFieldBaseSchema.extend({
|
|
13
|
+
default: z.string().optional(),
|
|
14
|
+
input: z.enum(["email", "text", "url"]),
|
|
15
|
+
placeholder: z.string().optional(),
|
|
16
|
+
}),
|
|
17
|
+
integrationFormFieldBaseSchema.extend({
|
|
18
|
+
input: z.literal("password"),
|
|
19
|
+
placeholder: z.string().optional(),
|
|
20
|
+
}),
|
|
21
|
+
integrationFormFieldBaseSchema.extend({
|
|
22
|
+
default: z.number().optional(),
|
|
23
|
+
input: z.literal("number"),
|
|
24
|
+
placeholder: z.string().optional(),
|
|
25
|
+
}),
|
|
26
|
+
integrationFormFieldBaseSchema.extend({
|
|
27
|
+
default: z.boolean().optional(),
|
|
28
|
+
input: z.literal("boolean"),
|
|
29
|
+
}),
|
|
30
|
+
])
|
|
31
|
+
|
|
32
|
+
export const integrationServiceManifestSchema = z.object({
|
|
33
|
+
connection: z.discriminatedUnion("type", [
|
|
34
|
+
z.object({
|
|
35
|
+
type: z.literal("redirect"),
|
|
36
|
+
}),
|
|
37
|
+
z.object({
|
|
38
|
+
fields: INTEGRATION_FORM_FIELD_SCHEMA.array().min(1),
|
|
39
|
+
type: z.literal("form"),
|
|
40
|
+
}),
|
|
41
|
+
]),
|
|
42
|
+
description: z.string().optional(),
|
|
43
|
+
name: z.string().min(1),
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
export type IntegrationServiceManifest = z.infer<
|
|
47
|
+
typeof integrationServiceManifestSchema
|
|
48
|
+
>
|
|
49
|
+
|
|
50
|
+
type ScopeRequirement =
|
|
51
|
+
| string
|
|
52
|
+
| {
|
|
53
|
+
requirements: ScopeRequirement[]
|
|
54
|
+
type: "and" | "or"
|
|
55
|
+
}
|
|
56
|
+
const SCOPE_REQUIREMENT_SCHEMA: z.ZodType<ScopeRequirement> = z.lazy(() =>
|
|
57
|
+
z.union([
|
|
58
|
+
z.string(),
|
|
59
|
+
z.strictObject({
|
|
60
|
+
requirements: SCOPE_REQUIREMENT_SCHEMA.array(),
|
|
61
|
+
type: z.enum(["and", "or"]),
|
|
62
|
+
}),
|
|
63
|
+
]),
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
export const authorizationContract = {
|
|
67
|
+
beginConnection: oc
|
|
68
|
+
.input(
|
|
69
|
+
z.object({
|
|
70
|
+
binding: z.string().min(1),
|
|
71
|
+
deploymentId: z.string(),
|
|
72
|
+
serviceId: z.string().min(1),
|
|
73
|
+
}),
|
|
74
|
+
)
|
|
75
|
+
.output(z.object({ url: z.url() })),
|
|
76
|
+
callback: oc
|
|
77
|
+
.route({
|
|
78
|
+
method: "GET",
|
|
79
|
+
path: "/integrations/{serviceId}/callback",
|
|
80
|
+
operationId: "completeIntegrationAuthorization",
|
|
81
|
+
summary: "Complete integration authorization",
|
|
82
|
+
description: "Completes a redirect-based integration authorization flow.",
|
|
83
|
+
tags: ["Integrations"],
|
|
84
|
+
})
|
|
85
|
+
.input(z.object({ serviceId: z.string().min(1) }))
|
|
86
|
+
.output(z.string()),
|
|
87
|
+
get: oc
|
|
88
|
+
.input(
|
|
89
|
+
z.object({
|
|
90
|
+
deploymentId: z.string(),
|
|
91
|
+
}),
|
|
92
|
+
)
|
|
93
|
+
.output(
|
|
94
|
+
z.object({
|
|
95
|
+
accounts: z
|
|
96
|
+
.object({
|
|
97
|
+
checkedAt: z.date().nullable(),
|
|
98
|
+
error: z
|
|
99
|
+
.object({
|
|
100
|
+
code: z.string(),
|
|
101
|
+
message: z.string(),
|
|
102
|
+
})
|
|
103
|
+
.nullable(),
|
|
104
|
+
id: z.string(),
|
|
105
|
+
label: z.string(),
|
|
106
|
+
scopes: z.string().array(),
|
|
107
|
+
serviceId: z.string(),
|
|
108
|
+
serviceSub: z.string(),
|
|
109
|
+
})
|
|
110
|
+
.array(),
|
|
111
|
+
requirements: z
|
|
112
|
+
.object({
|
|
113
|
+
accountId: z.string().nullable(),
|
|
114
|
+
binding: z.string(),
|
|
115
|
+
eligibleAccountIds: z.string().array(),
|
|
116
|
+
minimalScopes: z.string().array(),
|
|
117
|
+
requiredScopes: SCOPE_REQUIREMENT_SCHEMA.array(),
|
|
118
|
+
satisfied: z.boolean(),
|
|
119
|
+
serviceId: z.string(),
|
|
120
|
+
})
|
|
121
|
+
.array(),
|
|
122
|
+
services: integrationServiceManifestSchema
|
|
123
|
+
.extend({
|
|
124
|
+
id: z.string().min(1),
|
|
125
|
+
})
|
|
126
|
+
.array(),
|
|
127
|
+
}),
|
|
128
|
+
),
|
|
129
|
+
submitCredentials: oc
|
|
130
|
+
.input(
|
|
131
|
+
z.object({
|
|
132
|
+
binding: z.string().min(1),
|
|
133
|
+
data: z.record(
|
|
134
|
+
z.string(),
|
|
135
|
+
z.union([z.string(), z.number(), z.boolean()]),
|
|
136
|
+
),
|
|
137
|
+
deploymentId: z.string(),
|
|
138
|
+
serviceId: z.string().min(1),
|
|
139
|
+
}),
|
|
140
|
+
)
|
|
141
|
+
.output(z.void()),
|
|
142
|
+
selectAccount: oc
|
|
143
|
+
.input(
|
|
144
|
+
z.object({
|
|
145
|
+
accountId: z.string(),
|
|
146
|
+
binding: z.string().min(1),
|
|
147
|
+
deploymentId: z.string(),
|
|
148
|
+
}),
|
|
149
|
+
)
|
|
150
|
+
.output(z.void()),
|
|
151
|
+
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { oc } from "@orpc/contract"
|
|
2
|
+
import { z } from "zod"
|
|
3
|
+
|
|
4
|
+
/** SDK compatibility version used to select the immutable runtime image. */
|
|
5
|
+
export const AUTOMATION_SDK_VERSION = "1"
|
|
6
|
+
|
|
7
|
+
export const deploymentTriggerInfoSchema = z.object({
|
|
8
|
+
details: z
|
|
9
|
+
.object({
|
|
10
|
+
label: z.string(),
|
|
11
|
+
value: z.string(),
|
|
12
|
+
})
|
|
13
|
+
.array(),
|
|
14
|
+
name: z.string(),
|
|
15
|
+
type: z.string(),
|
|
16
|
+
})
|
|
17
|
+
|
|
18
|
+
export type DeploymentTriggerInfo = z.infer<typeof deploymentTriggerInfoSchema>
|
|
19
|
+
|
|
20
|
+
export const deploymentContract = {
|
|
21
|
+
create: oc
|
|
22
|
+
.input(
|
|
23
|
+
z.object({
|
|
24
|
+
artifact: z.instanceof(Blob),
|
|
25
|
+
manifest: z
|
|
26
|
+
.object({
|
|
27
|
+
entrypoint: z.string().min(1),
|
|
28
|
+
identityKey: z.string().min(1),
|
|
29
|
+
})
|
|
30
|
+
.array()
|
|
31
|
+
.min(1, "Deployment must include at least one automation.")
|
|
32
|
+
.superRefine((manifest, context) => {
|
|
33
|
+
const identityKeys = new Set<string>()
|
|
34
|
+
|
|
35
|
+
for (const [index, entry] of manifest.entries()) {
|
|
36
|
+
if (identityKeys.has(entry.identityKey)) {
|
|
37
|
+
context.addIssue({
|
|
38
|
+
code: "custom",
|
|
39
|
+
message: "Automation identity keys must be unique.",
|
|
40
|
+
path: [index, "identityKey"],
|
|
41
|
+
})
|
|
42
|
+
}
|
|
43
|
+
identityKeys.add(entry.identityKey)
|
|
44
|
+
|
|
45
|
+
if (
|
|
46
|
+
entry.entrypoint.includes("\\") ||
|
|
47
|
+
entry.entrypoint.startsWith("/") ||
|
|
48
|
+
entry.entrypoint
|
|
49
|
+
.split("/")
|
|
50
|
+
.some(
|
|
51
|
+
(segment) =>
|
|
52
|
+
segment === "" || segment === "." || segment === "..",
|
|
53
|
+
)
|
|
54
|
+
) {
|
|
55
|
+
context.addIssue({
|
|
56
|
+
code: "custom",
|
|
57
|
+
message: "Entrypoint must be a safe relative POSIX path.",
|
|
58
|
+
path: [index, "entrypoint"],
|
|
59
|
+
})
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}),
|
|
63
|
+
mode: z.enum(["reconcile", "upsert"]),
|
|
64
|
+
projectId: z.string(),
|
|
65
|
+
}),
|
|
66
|
+
)
|
|
67
|
+
.output(z.object({ id: z.string() })),
|
|
68
|
+
get: oc
|
|
69
|
+
.input(
|
|
70
|
+
z.object({
|
|
71
|
+
deploymentId: z.string(),
|
|
72
|
+
projectId: z.string(),
|
|
73
|
+
}),
|
|
74
|
+
)
|
|
75
|
+
.output(
|
|
76
|
+
z.object({
|
|
77
|
+
automations: z
|
|
78
|
+
.object({
|
|
79
|
+
description: z.string(),
|
|
80
|
+
identityKey: z.string(),
|
|
81
|
+
triggers: deploymentTriggerInfoSchema.array(),
|
|
82
|
+
})
|
|
83
|
+
.array(),
|
|
84
|
+
id: z.string(),
|
|
85
|
+
job: z
|
|
86
|
+
.object({
|
|
87
|
+
attempts: z.number().int().nonnegative(),
|
|
88
|
+
error: z.string().nullable(),
|
|
89
|
+
maxAttempts: z.number().int().positive(),
|
|
90
|
+
nextRunAt: z.date(),
|
|
91
|
+
})
|
|
92
|
+
.nullable(),
|
|
93
|
+
project: z.object({
|
|
94
|
+
id: z.string(),
|
|
95
|
+
name: z.string(),
|
|
96
|
+
}),
|
|
97
|
+
status: z.enum([
|
|
98
|
+
"planning",
|
|
99
|
+
"awaiting_authorization",
|
|
100
|
+
"configuring",
|
|
101
|
+
"publishing",
|
|
102
|
+
"succeeded",
|
|
103
|
+
"failed",
|
|
104
|
+
]),
|
|
105
|
+
}),
|
|
106
|
+
),
|
|
107
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { oc } from "@orpc/contract"
|
|
2
|
+
import { z } from "zod"
|
|
3
|
+
|
|
4
|
+
export const gmailEventsContract = {
|
|
5
|
+
gmailPush: oc
|
|
6
|
+
.route({
|
|
7
|
+
method: "POST",
|
|
8
|
+
path: "/events/gmail",
|
|
9
|
+
operationId: "receiveGmailPush",
|
|
10
|
+
summary: "Receive a Gmail push notification",
|
|
11
|
+
description:
|
|
12
|
+
"Receives and authenticates Gmail mailbox notifications delivered by Google Cloud Pub/Sub.",
|
|
13
|
+
tags: ["Events"],
|
|
14
|
+
successStatus: 204,
|
|
15
|
+
})
|
|
16
|
+
.input(
|
|
17
|
+
z.object({
|
|
18
|
+
/** Pub/Sub message containing the encoded Gmail notification. */
|
|
19
|
+
message: z.object({
|
|
20
|
+
/** Base64-encoded Gmail mailbox notification. */
|
|
21
|
+
data: z.string().min(1),
|
|
22
|
+
|
|
23
|
+
/** Provider-assigned identifier used to deduplicate delivery. */
|
|
24
|
+
messageId: z.string().min(1),
|
|
25
|
+
}),
|
|
26
|
+
|
|
27
|
+
/** Pub/Sub subscription that delivered the message. */
|
|
28
|
+
subscription: z.literal(
|
|
29
|
+
"projects/opkitty/subscriptions/automate-ax-gmail-push",
|
|
30
|
+
),
|
|
31
|
+
}),
|
|
32
|
+
)
|
|
33
|
+
.output(z.void()),
|
|
34
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { oc } from "@orpc/contract"
|
|
2
|
+
import { z } from "zod"
|
|
3
|
+
|
|
4
|
+
export const googleCalendarEventsContract = {
|
|
5
|
+
googleCalendarPush: oc
|
|
6
|
+
.route({
|
|
7
|
+
method: "POST",
|
|
8
|
+
path: "/events/google-calendar",
|
|
9
|
+
operationId: "receiveGoogleCalendarPush",
|
|
10
|
+
summary: "Receive a Google Calendar push notification",
|
|
11
|
+
description:
|
|
12
|
+
"Receives header-only Google Calendar resource-change notifications.",
|
|
13
|
+
tags: ["Events"],
|
|
14
|
+
successStatus: 204,
|
|
15
|
+
})
|
|
16
|
+
.input(z.void())
|
|
17
|
+
.output(z.void()),
|
|
18
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { oc } from "@orpc/contract"
|
|
2
|
+
import { z } from "zod"
|
|
3
|
+
|
|
4
|
+
export const googleFormsEventsContract = {
|
|
5
|
+
googleFormsPush: oc
|
|
6
|
+
.route({
|
|
7
|
+
method: "POST",
|
|
8
|
+
path: "/events/google-forms",
|
|
9
|
+
operationId: "receiveGoogleFormsPush",
|
|
10
|
+
summary: "Receive a Google Forms push notification",
|
|
11
|
+
description:
|
|
12
|
+
"Receives and authenticates Google Forms notifications delivered by Google Cloud Pub/Sub.",
|
|
13
|
+
tags: ["Events"],
|
|
14
|
+
successStatus: 204,
|
|
15
|
+
})
|
|
16
|
+
.input(
|
|
17
|
+
z.object({
|
|
18
|
+
/** Pub/Sub message containing Google Forms notification attributes. */
|
|
19
|
+
message: z.object({
|
|
20
|
+
/** Provider routing fields for the watched form. */
|
|
21
|
+
attributes: z.object({
|
|
22
|
+
eventType: z.enum(["SCHEMA", "RESPONSES"]),
|
|
23
|
+
formId: z.string().min(1),
|
|
24
|
+
watchId: z.string().min(1),
|
|
25
|
+
}),
|
|
26
|
+
|
|
27
|
+
/** Provider-assigned identifier used to deduplicate delivery. */
|
|
28
|
+
messageId: z.string().min(1),
|
|
29
|
+
|
|
30
|
+
/** RFC 3339 time at which Pub/Sub published the notification. */
|
|
31
|
+
publishTime: z.iso.datetime({ offset: true }),
|
|
32
|
+
}),
|
|
33
|
+
|
|
34
|
+
/** Pub/Sub subscription that delivered the message. */
|
|
35
|
+
subscription: z.literal(
|
|
36
|
+
"projects/opkitty/subscriptions/automate-ax-google-forms-push",
|
|
37
|
+
),
|
|
38
|
+
}),
|
|
39
|
+
)
|
|
40
|
+
.output(z.void()),
|
|
41
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { googleCalendarEventsContract } from "./google-calendar"
|
|
2
|
+
import { googleFormsEventsContract } from "./google-forms"
|
|
3
|
+
import { gmailEventsContract } from "./gmail"
|
|
4
|
+
|
|
5
|
+
export const eventsContract = {
|
|
6
|
+
...googleCalendarEventsContract,
|
|
7
|
+
...googleFormsEventsContract,
|
|
8
|
+
...gmailEventsContract,
|
|
9
|
+
}
|