@fragno-dev/backoffice-api 0.0.0-stage → 0.0.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.md +16 -0
- package/README.md +90 -2
- package/dist/api.d.ts +35 -0
- package/dist/api.d.ts.map +1 -0
- package/dist/api.js +10 -0
- package/dist/api.js.map +1 -0
- package/dist/errors.d.ts +45 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +35 -0
- package/dist/errors.js.map +1 -0
- package/dist/openapi.d.ts +46 -0
- package/dist/openapi.d.ts.map +1 -0
- package/dist/openapi.js +205 -0
- package/dist/openapi.js.map +1 -0
- package/dist/v0/account.d.ts +171 -0
- package/dist/v0/account.d.ts.map +1 -0
- package/dist/v0/account.js +78 -0
- package/dist/v0/account.js.map +1 -0
- package/dist/v0/api.d.ts +3437 -0
- package/dist/v0/api.d.ts.map +1 -0
- package/dist/v0/api.js +52 -0
- package/dist/v0/api.js.map +1 -0
- package/dist/v0/app-actions.d.ts +105 -0
- package/dist/v0/app-actions.d.ts.map +1 -0
- package/dist/v0/app-actions.js +100 -0
- package/dist/v0/app-actions.js.map +1 -0
- package/dist/v0/apps.d.ts +417 -0
- package/dist/v0/apps.d.ts.map +1 -0
- package/dist/v0/apps.js +163 -0
- package/dist/v0/apps.js.map +1 -0
- package/dist/v0/automation.d.ts +730 -0
- package/dist/v0/automation.d.ts.map +1 -0
- package/dist/v0/automation.js +355 -0
- package/dist/v0/automation.js.map +1 -0
- package/dist/v0/capabilities.d.ts +97 -0
- package/dist/v0/capabilities.d.ts.map +1 -0
- package/dist/v0/capabilities.js +41 -0
- package/dist/v0/capabilities.js.map +1 -0
- package/dist/v0/client.d.ts +39 -0
- package/dist/v0/client.d.ts.map +1 -0
- package/dist/v0/client.js +61 -0
- package/dist/v0/client.js.map +1 -0
- package/dist/v0/events.d.ts +789 -0
- package/dist/v0/events.d.ts.map +1 -0
- package/dist/v0/events.js +153 -0
- package/dist/v0/events.js.map +1 -0
- package/dist/v0/forms.d.ts +172 -0
- package/dist/v0/forms.d.ts.map +1 -0
- package/dist/v0/forms.js +88 -0
- package/dist/v0/forms.js.map +1 -0
- package/dist/v0/hooks.d.ts +61 -0
- package/dist/v0/hooks.d.ts.map +1 -0
- package/dist/v0/hooks.js +49 -0
- package/dist/v0/hooks.js.map +1 -0
- package/dist/v0/identity.d.ts +73 -0
- package/dist/v0/identity.d.ts.map +1 -0
- package/dist/v0/identity.js +46 -0
- package/dist/v0/identity.js.map +1 -0
- package/dist/v0/integrations.d.ts +847 -0
- package/dist/v0/integrations.d.ts.map +1 -0
- package/dist/v0/integrations.js +255 -0
- package/dist/v0/integrations.js.map +1 -0
- package/dist/v0/javascript.d.ts +160 -0
- package/dist/v0/javascript.d.ts.map +1 -0
- package/dist/v0/javascript.js +123 -0
- package/dist/v0/javascript.js.map +1 -0
- package/dist/v0/marketplace.d.ts +825 -0
- package/dist/v0/marketplace.d.ts.map +1 -0
- package/dist/v0/marketplace.js +284 -0
- package/dist/v0/marketplace.js.map +1 -0
- package/dist/v0/organization.d.ts +182 -0
- package/dist/v0/organization.d.ts.map +1 -0
- package/dist/v0/organization.js +88 -0
- package/dist/v0/organization.js.map +1 -0
- package/dist/v0/otp.d.ts +37 -0
- package/dist/v0/otp.d.ts.map +1 -0
- package/dist/v0/otp.js +29 -0
- package/dist/v0/otp.js.map +1 -0
- package/dist/v0/pi.d.ts +322 -0
- package/dist/v0/pi.d.ts.map +1 -0
- package/dist/v0/pi.js +146 -0
- package/dist/v0/pi.js.map +1 -0
- package/dist/v0/sandbox.d.ts +173 -0
- package/dist/v0/sandbox.d.ts.map +1 -0
- package/dist/v0/sandbox.js +97 -0
- package/dist/v0/sandbox.js.map +1 -0
- package/dist/v0/shared/bytes.d.ts +12 -0
- package/dist/v0/shared/bytes.d.ts.map +1 -0
- package/dist/v0/shared/bytes.js +16 -0
- package/dist/v0/shared/bytes.js.map +1 -0
- package/dist/v0/shared/datetime.d.ts +10 -0
- package/dist/v0/shared/datetime.d.ts.map +1 -0
- package/dist/v0/shared/datetime.js +14 -0
- package/dist/v0/shared/datetime.js.map +1 -0
- package/dist/v0/shared/json.d.ts +9 -0
- package/dist/v0/shared/json.d.ts.map +1 -0
- package/dist/v0/shared/json.js +14 -0
- package/dist/v0/shared/json.js.map +1 -0
- package/dist/v0/shared/pagination.d.ts +11 -0
- package/dist/v0/shared/pagination.d.ts.map +1 -0
- package/dist/v0/shared/pagination.js +11 -0
- package/dist/v0/shared/pagination.js.map +1 -0
- package/dist/v0/shared/permissions.d.ts +279 -0
- package/dist/v0/shared/permissions.d.ts.map +1 -0
- package/dist/v0/shared/permissions.js +285 -0
- package/dist/v0/shared/permissions.js.map +1 -0
- package/dist/v0/shared/pi-agent-name.d.ts +10 -0
- package/dist/v0/shared/pi-agent-name.d.ts.map +1 -0
- package/dist/v0/shared/pi-agent-name.js +11 -0
- package/dist/v0/shared/pi-agent-name.js.map +1 -0
- package/dist/v0/shared/scope.d.ts +305 -0
- package/dist/v0/shared/scope.d.ts.map +1 -0
- package/dist/v0/shared/scope.js +279 -0
- package/dist/v0/shared/scope.js.map +1 -0
- package/dist/v0/state.d.ts +512 -0
- package/dist/v0/state.d.ts.map +1 -0
- package/dist/v0/state.js +267 -0
- package/dist/v0/state.js.map +1 -0
- package/dist/v0/store.d.ts +138 -0
- package/dist/v0/store.d.ts.map +1 -0
- package/dist/v0/store.js +83 -0
- package/dist/v0/store.js.map +1 -0
- package/dist/v0/upload.d.ts +568 -0
- package/dist/v0/upload.d.ts.map +1 -0
- package/dist/v0/upload.js +109 -0
- package/dist/v0/upload.js.map +1 -0
- package/dist/v0/web.d.ts +47 -0
- package/dist/v0/web.d.ts.map +1 -0
- package/dist/v0/web.js +31 -0
- package/dist/v0/web.js.map +1 -0
- package/dist/v0/workflow.d.ts +267 -0
- package/dist/v0/workflow.d.ts.map +1 -0
- package/dist/v0/workflow.js +116 -0
- package/dist/v0/workflow.js.map +1 -0
- package/package.json +64 -3
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
//#region src/v0/shared/scope.d.ts
|
|
3
|
+
/** How a scope names the organization and project it belongs to. */
|
|
4
|
+
type BackofficeScopeNames = {
|
|
5
|
+
organization: object;
|
|
6
|
+
project: object;
|
|
7
|
+
};
|
|
8
|
+
/** An organization scope, generic over how it names the organization. */
|
|
9
|
+
type BackofficeOrganizationScope<TNames extends BackofficeScopeNames> = {
|
|
10
|
+
kind: "org";
|
|
11
|
+
} & TNames["organization"];
|
|
12
|
+
/** A user's personal scope. */
|
|
13
|
+
type BackofficeUserScope = {
|
|
14
|
+
kind: "user";
|
|
15
|
+
userId: string;
|
|
16
|
+
};
|
|
17
|
+
/** The scopes that own everything else: every scope chain ends in an organization or a user. */
|
|
18
|
+
type BackofficeRootOwner<TNames extends BackofficeScopeNames> = BackofficeOrganizationScope<TNames> | BackofficeUserScope;
|
|
19
|
+
/**
|
|
20
|
+
* An installed app's own workspace, one per installation. The installation's owner owns it, and
|
|
21
|
+
* the app ID is stable, so every spelling names the app by ID.
|
|
22
|
+
*/
|
|
23
|
+
type BackofficeAppScope<TNames extends BackofficeScopeNames> = {
|
|
24
|
+
kind: "app";
|
|
25
|
+
owner: BackofficeRootOwner<TNames>;
|
|
26
|
+
appId: string;
|
|
27
|
+
};
|
|
28
|
+
/** The scopes that can own a project. Projects never own projects. */
|
|
29
|
+
type BackofficeProjectOwner<TNames extends BackofficeScopeNames> = BackofficeRootOwner<TNames> | BackofficeAppScope<TNames>;
|
|
30
|
+
/**
|
|
31
|
+
* Where Backoffice work runs, generic over how it names its organization and project: by ID at
|
|
32
|
+
* runtime, by slug in Backoffice URLs, or as loaded records. App and project scopes name their
|
|
33
|
+
* owner as a scope.
|
|
34
|
+
*/
|
|
35
|
+
type BackofficeScope<TNames extends BackofficeScopeNames> = {
|
|
36
|
+
kind: "system";
|
|
37
|
+
} | BackofficeRootOwner<TNames> | BackofficeAppScope<TNames> | ({
|
|
38
|
+
kind: "project";
|
|
39
|
+
owner: BackofficeProjectOwner<TNames>;
|
|
40
|
+
} & TNames["project"]);
|
|
41
|
+
/** Scopes that own resources; system scope only administers them. */
|
|
42
|
+
type BackofficeRoutable<TScope extends {
|
|
43
|
+
kind: string;
|
|
44
|
+
}> = Exclude<TScope, {
|
|
45
|
+
kind: "system";
|
|
46
|
+
}>;
|
|
47
|
+
type BackofficeScopeIdNames = {
|
|
48
|
+
organization: {
|
|
49
|
+
orgId: string;
|
|
50
|
+
};
|
|
51
|
+
project: {
|
|
52
|
+
projectId: string;
|
|
53
|
+
};
|
|
54
|
+
};
|
|
55
|
+
/** Where Backoffice work runs, naming organizations and projects by ID. */
|
|
56
|
+
type BackofficeContextScope = BackofficeScope<BackofficeScopeIdNames>;
|
|
57
|
+
type BackofficeRoutableScope = BackofficeRoutable<BackofficeContextScope>;
|
|
58
|
+
/**
|
|
59
|
+
* Public routes and CLI arguments name organizations by slug, never by internal ID. Projects keep
|
|
60
|
+
* their ID, because public URLs are registered with external services and must survive renames.
|
|
61
|
+
*/
|
|
62
|
+
type BackofficeScopePublicNames = {
|
|
63
|
+
organization: {
|
|
64
|
+
orgSlug: string;
|
|
65
|
+
};
|
|
66
|
+
project: {
|
|
67
|
+
projectId: string;
|
|
68
|
+
};
|
|
69
|
+
};
|
|
70
|
+
type BackofficePublicScope = BackofficeScope<BackofficeScopePublicNames>;
|
|
71
|
+
declare const backofficeOrganizationScopeSchema: z.ZodLazy<z.ZodObject<{
|
|
72
|
+
kind: z.ZodLiteral<"org">;
|
|
73
|
+
orgId: z.ZodString;
|
|
74
|
+
}, z.core.$strict>>;
|
|
75
|
+
declare const backofficeUserScopeSchema: z.ZodLazy<z.ZodObject<{
|
|
76
|
+
kind: z.ZodLiteral<"user">;
|
|
77
|
+
userId: z.ZodString;
|
|
78
|
+
}, z.core.$strict>>;
|
|
79
|
+
declare const backofficeRootOwnerSchema: z.ZodLazy<z.ZodDiscriminatedUnion<[z.ZodLazy<z.ZodObject<{
|
|
80
|
+
kind: z.ZodLiteral<"org">;
|
|
81
|
+
orgId: z.ZodString;
|
|
82
|
+
}, z.core.$strict>>, z.ZodLazy<z.ZodObject<{
|
|
83
|
+
kind: z.ZodLiteral<"user">;
|
|
84
|
+
userId: z.ZodString;
|
|
85
|
+
}, z.core.$strict>>], "kind">>;
|
|
86
|
+
declare const backofficeAppScopeSchema: z.ZodLazy<z.ZodObject<{
|
|
87
|
+
kind: z.ZodLiteral<"app">;
|
|
88
|
+
owner: z.ZodLazy<z.ZodDiscriminatedUnion<[z.ZodLazy<z.ZodObject<{
|
|
89
|
+
kind: z.ZodLiteral<"org">;
|
|
90
|
+
orgId: z.ZodString;
|
|
91
|
+
}, z.core.$strict>>, z.ZodLazy<z.ZodObject<{
|
|
92
|
+
kind: z.ZodLiteral<"user">;
|
|
93
|
+
userId: z.ZodString;
|
|
94
|
+
}, z.core.$strict>>], "kind">>;
|
|
95
|
+
appId: z.ZodString;
|
|
96
|
+
}, z.core.$strict>>;
|
|
97
|
+
declare const backofficeProjectScopeSchema: z.ZodLazy<z.ZodObject<{
|
|
98
|
+
kind: z.ZodLiteral<"project">;
|
|
99
|
+
owner: z.ZodDiscriminatedUnion<[z.ZodLazy<z.ZodObject<{
|
|
100
|
+
kind: z.ZodLiteral<"org">;
|
|
101
|
+
orgId: z.ZodString;
|
|
102
|
+
}, z.core.$strict>>, z.ZodLazy<z.ZodObject<{
|
|
103
|
+
kind: z.ZodLiteral<"user">;
|
|
104
|
+
userId: z.ZodString;
|
|
105
|
+
}, z.core.$strict>>, z.ZodLazy<z.ZodObject<{
|
|
106
|
+
kind: z.ZodLiteral<"app">;
|
|
107
|
+
owner: z.ZodLazy<z.ZodDiscriminatedUnion<[z.ZodLazy<z.ZodObject<{
|
|
108
|
+
kind: z.ZodLiteral<"org">;
|
|
109
|
+
orgId: z.ZodString;
|
|
110
|
+
}, z.core.$strict>>, z.ZodLazy<z.ZodObject<{
|
|
111
|
+
kind: z.ZodLiteral<"user">;
|
|
112
|
+
userId: z.ZodString;
|
|
113
|
+
}, z.core.$strict>>], "kind">>;
|
|
114
|
+
appId: z.ZodString;
|
|
115
|
+
}, z.core.$strict>>], "kind">;
|
|
116
|
+
projectId: z.ZodString;
|
|
117
|
+
}, z.core.$strict>>;
|
|
118
|
+
declare const backofficeRoutableScopeSchema: z.ZodLazy<z.ZodDiscriminatedUnion<[z.ZodLazy<z.ZodObject<{
|
|
119
|
+
kind: z.ZodLiteral<"org">;
|
|
120
|
+
orgId: z.ZodString;
|
|
121
|
+
}, z.core.$strict>>, z.ZodLazy<z.ZodObject<{
|
|
122
|
+
kind: z.ZodLiteral<"user">;
|
|
123
|
+
userId: z.ZodString;
|
|
124
|
+
}, z.core.$strict>>, z.ZodLazy<z.ZodObject<{
|
|
125
|
+
kind: z.ZodLiteral<"app">;
|
|
126
|
+
owner: z.ZodLazy<z.ZodDiscriminatedUnion<[z.ZodLazy<z.ZodObject<{
|
|
127
|
+
kind: z.ZodLiteral<"org">;
|
|
128
|
+
orgId: z.ZodString;
|
|
129
|
+
}, z.core.$strict>>, z.ZodLazy<z.ZodObject<{
|
|
130
|
+
kind: z.ZodLiteral<"user">;
|
|
131
|
+
userId: z.ZodString;
|
|
132
|
+
}, z.core.$strict>>], "kind">>;
|
|
133
|
+
appId: z.ZodString;
|
|
134
|
+
}, z.core.$strict>>, z.ZodLazy<z.ZodObject<{
|
|
135
|
+
kind: z.ZodLiteral<"project">;
|
|
136
|
+
owner: z.ZodDiscriminatedUnion<[z.ZodLazy<z.ZodObject<{
|
|
137
|
+
kind: z.ZodLiteral<"org">;
|
|
138
|
+
orgId: z.ZodString;
|
|
139
|
+
}, z.core.$strict>>, z.ZodLazy<z.ZodObject<{
|
|
140
|
+
kind: z.ZodLiteral<"user">;
|
|
141
|
+
userId: z.ZodString;
|
|
142
|
+
}, z.core.$strict>>, z.ZodLazy<z.ZodObject<{
|
|
143
|
+
kind: z.ZodLiteral<"app">;
|
|
144
|
+
owner: z.ZodLazy<z.ZodDiscriminatedUnion<[z.ZodLazy<z.ZodObject<{
|
|
145
|
+
kind: z.ZodLiteral<"org">;
|
|
146
|
+
orgId: z.ZodString;
|
|
147
|
+
}, z.core.$strict>>, z.ZodLazy<z.ZodObject<{
|
|
148
|
+
kind: z.ZodLiteral<"user">;
|
|
149
|
+
userId: z.ZodString;
|
|
150
|
+
}, z.core.$strict>>], "kind">>;
|
|
151
|
+
appId: z.ZodString;
|
|
152
|
+
}, z.core.$strict>>], "kind">;
|
|
153
|
+
projectId: z.ZodString;
|
|
154
|
+
}, z.core.$strict>>], "kind">>;
|
|
155
|
+
declare const backofficeContextScopeSchema: z.ZodLazy<z.ZodDiscriminatedUnion<[z.ZodLazy<z.ZodObject<{
|
|
156
|
+
kind: z.ZodLiteral<"system">;
|
|
157
|
+
}, z.core.$strict>>, z.ZodLazy<z.ZodObject<{
|
|
158
|
+
kind: z.ZodLiteral<"org">;
|
|
159
|
+
orgId: z.ZodString;
|
|
160
|
+
}, z.core.$strict>>, z.ZodLazy<z.ZodObject<{
|
|
161
|
+
kind: z.ZodLiteral<"user">;
|
|
162
|
+
userId: z.ZodString;
|
|
163
|
+
}, z.core.$strict>>, z.ZodLazy<z.ZodObject<{
|
|
164
|
+
kind: z.ZodLiteral<"app">;
|
|
165
|
+
owner: z.ZodLazy<z.ZodDiscriminatedUnion<[z.ZodLazy<z.ZodObject<{
|
|
166
|
+
kind: z.ZodLiteral<"org">;
|
|
167
|
+
orgId: z.ZodString;
|
|
168
|
+
}, z.core.$strict>>, z.ZodLazy<z.ZodObject<{
|
|
169
|
+
kind: z.ZodLiteral<"user">;
|
|
170
|
+
userId: z.ZodString;
|
|
171
|
+
}, z.core.$strict>>], "kind">>;
|
|
172
|
+
appId: z.ZodString;
|
|
173
|
+
}, z.core.$strict>>, z.ZodLazy<z.ZodObject<{
|
|
174
|
+
kind: z.ZodLiteral<"project">;
|
|
175
|
+
owner: z.ZodDiscriminatedUnion<[z.ZodLazy<z.ZodObject<{
|
|
176
|
+
kind: z.ZodLiteral<"org">;
|
|
177
|
+
orgId: z.ZodString;
|
|
178
|
+
}, z.core.$strict>>, z.ZodLazy<z.ZodObject<{
|
|
179
|
+
kind: z.ZodLiteral<"user">;
|
|
180
|
+
userId: z.ZodString;
|
|
181
|
+
}, z.core.$strict>>, z.ZodLazy<z.ZodObject<{
|
|
182
|
+
kind: z.ZodLiteral<"app">;
|
|
183
|
+
owner: z.ZodLazy<z.ZodDiscriminatedUnion<[z.ZodLazy<z.ZodObject<{
|
|
184
|
+
kind: z.ZodLiteral<"org">;
|
|
185
|
+
orgId: z.ZodString;
|
|
186
|
+
}, z.core.$strict>>, z.ZodLazy<z.ZodObject<{
|
|
187
|
+
kind: z.ZodLiteral<"user">;
|
|
188
|
+
userId: z.ZodString;
|
|
189
|
+
}, z.core.$strict>>], "kind">>;
|
|
190
|
+
appId: z.ZodString;
|
|
191
|
+
}, z.core.$strict>>], "kind">;
|
|
192
|
+
projectId: z.ZodString;
|
|
193
|
+
}, z.core.$strict>>], "kind">>;
|
|
194
|
+
declare function isBackofficeRoutableScope(scope: BackofficeContextScope): scope is BackofficeRoutableScope;
|
|
195
|
+
type ProjectNamesOf<TScope> = Omit<Extract<TScope, {
|
|
196
|
+
kind: "project";
|
|
197
|
+
}>, "kind" | "owner">;
|
|
198
|
+
/** The root owners among a scope type's kinds, found by following each owner chain. */
|
|
199
|
+
type BackofficeRootOwnerOf<TScope> = TScope extends {
|
|
200
|
+
kind: "org";
|
|
201
|
+
} | {
|
|
202
|
+
kind: "user";
|
|
203
|
+
} ? TScope : TScope extends {
|
|
204
|
+
owner: infer TOwner;
|
|
205
|
+
} ? BackofficeRootOwnerOf<TOwner> : never;
|
|
206
|
+
/** The organization scope a scope type's chains can end in. */
|
|
207
|
+
type BackofficeOrganizationScopeOf<TScope> = Extract<BackofficeRootOwnerOf<TScope>, {
|
|
208
|
+
kind: "org";
|
|
209
|
+
}>;
|
|
210
|
+
type OrganizationNamesOf<TScope> = Omit<BackofficeOrganizationScopeOf<TScope>, "kind">;
|
|
211
|
+
/** `null` when a scope type includes the system scope, which no root owner owns. */
|
|
212
|
+
type NullIfSystem<TScope> = [Extract<TScope, {
|
|
213
|
+
kind: "system";
|
|
214
|
+
}>] extends [never] ? never : null;
|
|
215
|
+
/** `null` when a scope type includes scopes that belong to no organization. */
|
|
216
|
+
type NullUnlessOrganizationOwned<TScope> = [Extract<TScope, {
|
|
217
|
+
kind: "system";
|
|
218
|
+
}> | Extract<BackofficeRootOwnerOf<TScope>, {
|
|
219
|
+
kind: "user";
|
|
220
|
+
}>] extends [never] ? never : null;
|
|
221
|
+
/**
|
|
222
|
+
* The organization or user at the end of a scope's owner chain, who answers for everything in it.
|
|
223
|
+
* The system scope has none, so the result is only nullable when the scope type includes it.
|
|
224
|
+
*/
|
|
225
|
+
declare function backofficeScopeRootOwner<TScope extends BackofficeScope<BackofficeScopeNames>>(scope: TScope): BackofficeRootOwnerOf<TScope> | NullIfSystem<TScope>;
|
|
226
|
+
/**
|
|
227
|
+
* The organization a scope belongs to: its root owner, when that is an organization. The result is
|
|
228
|
+
* only nullable when the scope type includes scopes that a user or nobody owns.
|
|
229
|
+
*/
|
|
230
|
+
declare function backofficeScopeOrganization<TScope extends BackofficeScope<BackofficeScopeNames>>(scope: TScope): BackofficeOrganizationScopeOf<TScope> | NullUnlessOrganizationOwned<TScope>;
|
|
231
|
+
/**
|
|
232
|
+
* The scope whose projects sit beside a workspace: the workspace itself, or a project's owner.
|
|
233
|
+
* The system scope owns no projects.
|
|
234
|
+
*/
|
|
235
|
+
declare function backofficeScopeProjectOwner<TNames extends BackofficeScopeNames>(scope: BackofficeScope<TNames>): BackofficeProjectOwner<TNames> | null;
|
|
236
|
+
/**
|
|
237
|
+
* The organization whose own workspace a scope is: the organization, or one of its projects. Unlike
|
|
238
|
+
* `backofficeScopeOrganization`, an installed app's workspace is not its organization's.
|
|
239
|
+
*/
|
|
240
|
+
declare function backofficeWorkspaceOrganization<TNames extends BackofficeScopeNames>(scope: BackofficeScope<TNames>): BackofficeOrganizationScope<TNames> | null;
|
|
241
|
+
/** Renames the records a scope refers to, e.g. from route slugs to runtime IDs; kinds are kept. */
|
|
242
|
+
declare function mapBackofficeScopeNames<TScope extends BackofficeScope<BackofficeScopeNames>, TOrganization extends object, TProject extends object>(scope: TScope, map: {
|
|
243
|
+
organization(names: OrganizationNamesOf<TScope>): TOrganization;
|
|
244
|
+
project(names: ProjectNamesOf<TScope>): TProject;
|
|
245
|
+
}): Extract<BackofficeScope<{
|
|
246
|
+
organization: TOrganization;
|
|
247
|
+
project: TProject;
|
|
248
|
+
}>, {
|
|
249
|
+
kind: TScope["kind"];
|
|
250
|
+
}>;
|
|
251
|
+
declare function backofficeContextScopesEqual(left: BackofficeContextScope, right: BackofficeContextScope): boolean;
|
|
252
|
+
/**
|
|
253
|
+
* A scope restriction is an upper bound: a project's owner contains the project. Containment does
|
|
254
|
+
* not chain, so an organization contains neither its apps' workspaces nor their projects.
|
|
255
|
+
*/
|
|
256
|
+
declare function backofficeScopeContains(restriction: BackofficeContextScope, target: BackofficeContextScope): boolean;
|
|
257
|
+
/** A scope could not be read from untrusted text, such as a URL. */
|
|
258
|
+
declare class BackofficeScopeParseError extends Error {
|
|
259
|
+
readonly code = "INVALID_BACKOFFICE_SCOPE";
|
|
260
|
+
constructor(message: string);
|
|
261
|
+
}
|
|
262
|
+
/** Matches by code too, because errors lose their class across module copies and RPC. */
|
|
263
|
+
declare function isBackofficeScopeParseError(error: unknown): error is BackofficeScopeParseError;
|
|
264
|
+
/** How one of a scope's names is written in text, and what a parse error calls it. */
|
|
265
|
+
type BackofficeNameCodec<TName extends object> = {
|
|
266
|
+
label: string;
|
|
267
|
+
format(name: TName): string;
|
|
268
|
+
parse(value: string): TName;
|
|
269
|
+
};
|
|
270
|
+
type BackofficeScopeCodec<TNames extends BackofficeScopeNames> = {
|
|
271
|
+
organization: BackofficeNameCodec<TNames["organization"]>;
|
|
272
|
+
project: BackofficeNameCodec<TNames["project"]>;
|
|
273
|
+
};
|
|
274
|
+
declare const backofficeOrganizationSlugCodec: BackofficeNameCodec<{
|
|
275
|
+
orgSlug: string;
|
|
276
|
+
}>;
|
|
277
|
+
declare const backofficeScopeIdCodec: BackofficeScopeCodec<BackofficeScopeIdNames>;
|
|
278
|
+
declare const backofficePublicScopeCodec: BackofficeScopeCodec<BackofficeScopePublicNames>;
|
|
279
|
+
/**
|
|
280
|
+
* Names a scope in one URL path segment, e.g. `project:org:<org>:<projectId>`: app and project
|
|
281
|
+
* scopes embed their owner's segment. Components are URI-encoded, so `:` only ever separates them.
|
|
282
|
+
*/
|
|
283
|
+
declare function formatBackofficeScopeSegment<TNames extends BackofficeScopeNames>(scope: BackofficeScope<TNames>, codec: BackofficeScopeCodec<TNames>): string;
|
|
284
|
+
/** Reads a segment written by `formatBackofficeScopeSegment`; anything else is a parse error. */
|
|
285
|
+
declare function parseBackofficeScopeSegment<TNames extends BackofficeScopeNames>(segment: string, codec: BackofficeScopeCodec<TNames>): BackofficeScope<TNames>;
|
|
286
|
+
/**
|
|
287
|
+
* Escapes scope text for a URL path segment that a router decodes once before it is parsed. Paths
|
|
288
|
+
* allow a literal `:`, so the separator stays readable; a `:` inside a component was already
|
|
289
|
+
* escaped when the segment was formatted.
|
|
290
|
+
*/
|
|
291
|
+
declare function encodeBackofficeScopeForPath(text: string): string;
|
|
292
|
+
/** Names a scope in two URL path segments, `<kind>/<id>`, e.g. `project/org:acme:website`. */
|
|
293
|
+
declare function formatBackofficeScopeRoutePath<TNames extends BackofficeScopeNames>(scope: BackofficeScope<TNames>, codec: BackofficeScopeCodec<TNames>): string;
|
|
294
|
+
/** Reads the decoded `<kind>/<id>` route parameters written by `formatBackofficeScopeRoutePath`. */
|
|
295
|
+
declare function parseBackofficeScopeRouteParams<TNames extends BackofficeScopeNames>(params: {
|
|
296
|
+
scopeKind: string;
|
|
297
|
+
scopeId: string;
|
|
298
|
+
}, codec: BackofficeScopeCodec<TNames>): BackofficeScope<TNames>;
|
|
299
|
+
/** Names an ID-backed scope in one URL path segment, as the Backoffice API addresses scopes. */
|
|
300
|
+
declare function backofficeScopePathSegment(scope: BackofficeContextScope): string;
|
|
301
|
+
/** Reads a segment written by `backofficeScopePathSegment`; anything else is a parse error. */
|
|
302
|
+
declare function parseBackofficeScopePathSegment(segment: string): BackofficeContextScope;
|
|
303
|
+
//#endregion
|
|
304
|
+
export { BackofficeAppScope, BackofficeContextScope, BackofficeNameCodec, BackofficeOrganizationScope, BackofficeOrganizationScopeOf, BackofficeProjectOwner, BackofficePublicScope, BackofficeRootOwner, BackofficeRootOwnerOf, BackofficeRoutable, BackofficeRoutableScope, BackofficeScope, BackofficeScopeCodec, BackofficeScopeIdNames, BackofficeScopeNames, BackofficeScopeParseError, BackofficeScopePublicNames, BackofficeUserScope, backofficeAppScopeSchema, backofficeContextScopeSchema, backofficeContextScopesEqual, backofficeOrganizationScopeSchema, backofficeOrganizationSlugCodec, backofficeProjectScopeSchema, backofficePublicScopeCodec, backofficeRootOwnerSchema, backofficeRoutableScopeSchema, backofficeScopeContains, backofficeScopeIdCodec, backofficeScopeOrganization, backofficeScopePathSegment, backofficeScopeProjectOwner, backofficeScopeRootOwner, backofficeUserScopeSchema, backofficeWorkspaceOrganization, encodeBackofficeScopeForPath, formatBackofficeScopeRoutePath, formatBackofficeScopeSegment, isBackofficeRoutableScope, isBackofficeScopeParseError, mapBackofficeScopeNames, parseBackofficeScopePathSegment, parseBackofficeScopeRouteParams, parseBackofficeScopeSegment };
|
|
305
|
+
//# sourceMappingURL=scope.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scope.d.ts","names":[],"sources":["../../../src/v0/shared/scope.ts"],"mappings":"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"}
|
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
//#region src/v0/shared/scope.ts
|
|
3
|
+
const backofficeSystemScopeSchema = z.lazy(() => z.strictObject({ kind: z.literal("system") }));
|
|
4
|
+
const backofficeOrganizationScopeSchema = z.lazy(() => z.strictObject({
|
|
5
|
+
kind: z.literal("org"),
|
|
6
|
+
orgId: z.string().trim().min(1)
|
|
7
|
+
}));
|
|
8
|
+
const backofficeUserScopeSchema = z.lazy(() => z.strictObject({
|
|
9
|
+
kind: z.literal("user"),
|
|
10
|
+
userId: z.string().trim().min(1)
|
|
11
|
+
}));
|
|
12
|
+
const backofficeRootOwnerSchema = z.lazy(() => z.discriminatedUnion("kind", [backofficeOrganizationScopeSchema, backofficeUserScopeSchema]));
|
|
13
|
+
const backofficeAppScopeSchema = z.lazy(() => z.strictObject({
|
|
14
|
+
kind: z.literal("app"),
|
|
15
|
+
owner: backofficeRootOwnerSchema,
|
|
16
|
+
appId: z.string().trim().min(1)
|
|
17
|
+
}));
|
|
18
|
+
const backofficeProjectScopeSchema = z.lazy(() => z.strictObject({
|
|
19
|
+
kind: z.literal("project"),
|
|
20
|
+
owner: z.discriminatedUnion("kind", [
|
|
21
|
+
backofficeOrganizationScopeSchema,
|
|
22
|
+
backofficeUserScopeSchema,
|
|
23
|
+
backofficeAppScopeSchema
|
|
24
|
+
]),
|
|
25
|
+
projectId: z.string().trim().min(1)
|
|
26
|
+
}));
|
|
27
|
+
const backofficeRoutableScopeSchema = z.lazy(() => z.discriminatedUnion("kind", [
|
|
28
|
+
backofficeOrganizationScopeSchema,
|
|
29
|
+
backofficeUserScopeSchema,
|
|
30
|
+
backofficeAppScopeSchema,
|
|
31
|
+
backofficeProjectScopeSchema
|
|
32
|
+
]));
|
|
33
|
+
const backofficeContextScopeSchema = z.lazy(() => z.discriminatedUnion("kind", [
|
|
34
|
+
backofficeSystemScopeSchema,
|
|
35
|
+
backofficeOrganizationScopeSchema,
|
|
36
|
+
backofficeUserScopeSchema,
|
|
37
|
+
backofficeAppScopeSchema,
|
|
38
|
+
backofficeProjectScopeSchema
|
|
39
|
+
]));
|
|
40
|
+
function isBackofficeRoutableScope(scope) {
|
|
41
|
+
return scope.kind !== "system";
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* The organization or user at the end of a scope's owner chain, who answers for everything in it.
|
|
45
|
+
* The system scope has none, so the result is only nullable when the scope type includes it.
|
|
46
|
+
*/
|
|
47
|
+
function backofficeScopeRootOwner(scope) {
|
|
48
|
+
const named = scope;
|
|
49
|
+
switch (named.kind) {
|
|
50
|
+
case "org":
|
|
51
|
+
case "user": return named;
|
|
52
|
+
case "app":
|
|
53
|
+
case "project": return backofficeScopeRootOwner(named.owner);
|
|
54
|
+
case "system": return null;
|
|
55
|
+
default: throw new Error("Unsupported Backoffice scope kind.", { cause: named });
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* The organization a scope belongs to: its root owner, when that is an organization. The result is
|
|
60
|
+
* only nullable when the scope type includes scopes that a user or nobody owns.
|
|
61
|
+
*/
|
|
62
|
+
function backofficeScopeOrganization(scope) {
|
|
63
|
+
const owner = backofficeScopeRootOwner(scope);
|
|
64
|
+
return owner?.kind === "org" ? owner : null;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* The scope whose projects sit beside a workspace: the workspace itself, or a project's owner.
|
|
68
|
+
* The system scope owns no projects.
|
|
69
|
+
*/
|
|
70
|
+
function backofficeScopeProjectOwner(scope) {
|
|
71
|
+
switch (scope.kind) {
|
|
72
|
+
case "system": return null;
|
|
73
|
+
case "project": return scope.owner;
|
|
74
|
+
case "org":
|
|
75
|
+
case "user":
|
|
76
|
+
case "app": return scope;
|
|
77
|
+
default: throw new Error("Unsupported Backoffice scope kind.", { cause: scope });
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* The organization whose own workspace a scope is: the organization, or one of its projects. Unlike
|
|
82
|
+
* `backofficeScopeOrganization`, an installed app's workspace is not its organization's.
|
|
83
|
+
*/
|
|
84
|
+
function backofficeWorkspaceOrganization(scope) {
|
|
85
|
+
const owner = backofficeScopeProjectOwner(scope);
|
|
86
|
+
return owner?.kind === "org" ? owner : null;
|
|
87
|
+
}
|
|
88
|
+
/** Renames the records a scope refers to, e.g. from route slugs to runtime IDs; kinds are kept. */
|
|
89
|
+
function mapBackofficeScopeNames(scope, map) {
|
|
90
|
+
return renameScope(scope);
|
|
91
|
+
function renameScope(named) {
|
|
92
|
+
switch (named.kind) {
|
|
93
|
+
case "system": return { kind: "system" };
|
|
94
|
+
case "org": return {
|
|
95
|
+
kind: "org",
|
|
96
|
+
...map.organization(named)
|
|
97
|
+
};
|
|
98
|
+
case "user": return {
|
|
99
|
+
kind: "user",
|
|
100
|
+
userId: named.userId
|
|
101
|
+
};
|
|
102
|
+
case "app": return {
|
|
103
|
+
kind: "app",
|
|
104
|
+
owner: renameScope(named.owner),
|
|
105
|
+
appId: named.appId
|
|
106
|
+
};
|
|
107
|
+
case "project": return {
|
|
108
|
+
kind: "project",
|
|
109
|
+
...map.project(named),
|
|
110
|
+
owner: renameScope(named.owner)
|
|
111
|
+
};
|
|
112
|
+
default: throw new Error("Unsupported Backoffice scope kind.", { cause: named });
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
function backofficeContextScopesEqual(left, right) {
|
|
117
|
+
return backofficeScopePathSegment(left) === backofficeScopePathSegment(right);
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* A scope restriction is an upper bound: a project's owner contains the project. Containment does
|
|
121
|
+
* not chain, so an organization contains neither its apps' workspaces nor their projects.
|
|
122
|
+
*/
|
|
123
|
+
function backofficeScopeContains(restriction, target) {
|
|
124
|
+
return backofficeContextScopesEqual(restriction, target) || target.kind === "project" && backofficeContextScopesEqual(restriction, target.owner);
|
|
125
|
+
}
|
|
126
|
+
const INVALID_BACKOFFICE_SCOPE = "INVALID_BACKOFFICE_SCOPE";
|
|
127
|
+
/** A scope could not be read from untrusted text, such as a URL. */
|
|
128
|
+
var BackofficeScopeParseError = class extends Error {
|
|
129
|
+
code = INVALID_BACKOFFICE_SCOPE;
|
|
130
|
+
constructor(message) {
|
|
131
|
+
super(message);
|
|
132
|
+
this.name = "BackofficeScopeParseError";
|
|
133
|
+
}
|
|
134
|
+
};
|
|
135
|
+
/** Matches by code too, because errors lose their class across module copies and RPC. */
|
|
136
|
+
function isBackofficeScopeParseError(error) {
|
|
137
|
+
return error instanceof BackofficeScopeParseError || typeof error === "object" && error !== null && "code" in error && error.code === INVALID_BACKOFFICE_SCOPE;
|
|
138
|
+
}
|
|
139
|
+
const organizationIdCodec = {
|
|
140
|
+
label: "org id",
|
|
141
|
+
format: (name) => name.orgId,
|
|
142
|
+
parse: (orgId) => ({ orgId })
|
|
143
|
+
};
|
|
144
|
+
const projectIdCodec = {
|
|
145
|
+
label: "project id",
|
|
146
|
+
format: (name) => name.projectId,
|
|
147
|
+
parse: (projectId) => ({ projectId })
|
|
148
|
+
};
|
|
149
|
+
const backofficeOrganizationSlugCodec = {
|
|
150
|
+
label: "organization slug",
|
|
151
|
+
format: (name) => name.orgSlug,
|
|
152
|
+
parse: (orgSlug) => ({ orgSlug })
|
|
153
|
+
};
|
|
154
|
+
const backofficeScopeIdCodec = {
|
|
155
|
+
organization: organizationIdCodec,
|
|
156
|
+
project: projectIdCodec
|
|
157
|
+
};
|
|
158
|
+
const backofficePublicScopeCodec = {
|
|
159
|
+
organization: backofficeOrganizationSlugCodec,
|
|
160
|
+
project: projectIdCodec
|
|
161
|
+
};
|
|
162
|
+
/**
|
|
163
|
+
* Names a scope in one URL path segment, e.g. `project:org:<org>:<projectId>`: app and project
|
|
164
|
+
* scopes embed their owner's segment. Components are URI-encoded, so `:` only ever separates them.
|
|
165
|
+
*/
|
|
166
|
+
function formatBackofficeScopeSegment(scope, codec) {
|
|
167
|
+
switch (scope.kind) {
|
|
168
|
+
case "system": return "system";
|
|
169
|
+
case "org": return `org:${encodeURIComponent(codec.organization.format(scope))}`;
|
|
170
|
+
case "user": return `user:${encodeURIComponent(scope.userId)}`;
|
|
171
|
+
case "app": return `app:${formatBackofficeScopeSegment(scope.owner, codec)}:${encodeURIComponent(scope.appId)}`;
|
|
172
|
+
case "project": return `project:${formatBackofficeScopeSegment(scope.owner, codec)}:${encodeURIComponent(codec.project.format(scope))}`;
|
|
173
|
+
default: throw new Error("Unsupported Backoffice scope kind.", { cause: scope });
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
/** Reads a segment written by `formatBackofficeScopeSegment`; anything else is a parse error. */
|
|
177
|
+
function parseBackofficeScopeSegment(segment, codec) {
|
|
178
|
+
const components = segment.split(":");
|
|
179
|
+
let next = 0;
|
|
180
|
+
const scope = readScope();
|
|
181
|
+
if (next !== components.length) throw new BackofficeScopeParseError(`${scopeLabel(scope.kind)} scope has unexpected components after it.`);
|
|
182
|
+
return scope;
|
|
183
|
+
function readScope() {
|
|
184
|
+
const kind = components[next++];
|
|
185
|
+
switch (kind) {
|
|
186
|
+
case "system": return { kind: "system" };
|
|
187
|
+
case "org": return {
|
|
188
|
+
kind: "org",
|
|
189
|
+
...codec.organization.parse(readComponent(codec.organization.label))
|
|
190
|
+
};
|
|
191
|
+
case "user": return {
|
|
192
|
+
kind: "user",
|
|
193
|
+
userId: readComponent("user id")
|
|
194
|
+
};
|
|
195
|
+
case "app": {
|
|
196
|
+
const owner = readOwner("App");
|
|
197
|
+
if (owner.kind !== "org" && owner.kind !== "user") throw new BackofficeScopeParseError(`${scopeLabel(owner.kind)} scope cannot own an app.`);
|
|
198
|
+
return {
|
|
199
|
+
kind: "app",
|
|
200
|
+
owner,
|
|
201
|
+
appId: readComponent("app id")
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
case "project": {
|
|
205
|
+
const owner = readOwner("Project");
|
|
206
|
+
if (owner.kind === "system" || owner.kind === "project") throw new BackofficeScopeParseError(`${scopeLabel(owner.kind)} scope cannot own a project.`);
|
|
207
|
+
return {
|
|
208
|
+
kind: "project",
|
|
209
|
+
owner,
|
|
210
|
+
...codec.project.parse(readComponent(codec.project.label))
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
default: throw new BackofficeScopeParseError(`Unknown scope kind '${kind ?? ""}'.`);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
function readOwner(ownedLabel) {
|
|
217
|
+
if (next === components.length) throw new BackofficeScopeParseError(`${ownedLabel} scope requires an owner scope.`);
|
|
218
|
+
return readScope();
|
|
219
|
+
}
|
|
220
|
+
function readComponent(label) {
|
|
221
|
+
const value = components[next++];
|
|
222
|
+
if (value === void 0) throw new BackofficeScopeParseError(`Missing ${label}.`);
|
|
223
|
+
return decodeSegmentComponent(value, label);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
function decodeSegmentComponent(value, label) {
|
|
227
|
+
let decoded;
|
|
228
|
+
try {
|
|
229
|
+
decoded = decodeURIComponent(value);
|
|
230
|
+
} catch {
|
|
231
|
+
throw new BackofficeScopeParseError(`Invalid ${label} encoding.`);
|
|
232
|
+
}
|
|
233
|
+
if (!decoded) throw new BackofficeScopeParseError(`Missing ${label}.`);
|
|
234
|
+
return decoded;
|
|
235
|
+
}
|
|
236
|
+
function scopeLabel(kind) {
|
|
237
|
+
switch (kind) {
|
|
238
|
+
case "system": return "System";
|
|
239
|
+
case "org": return "Org";
|
|
240
|
+
case "user": return "User";
|
|
241
|
+
case "app": return "App";
|
|
242
|
+
case "project": return "Project";
|
|
243
|
+
default: throw new Error("Unsupported Backoffice scope kind.", { cause: kind });
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* Escapes scope text for a URL path segment that a router decodes once before it is parsed. Paths
|
|
248
|
+
* allow a literal `:`, so the separator stays readable; a `:` inside a component was already
|
|
249
|
+
* escaped when the segment was formatted.
|
|
250
|
+
*/
|
|
251
|
+
function encodeBackofficeScopeForPath(text) {
|
|
252
|
+
return encodeURIComponent(text).replaceAll("%3A", ":");
|
|
253
|
+
}
|
|
254
|
+
/** Names a scope in two URL path segments, `<kind>/<id>`, e.g. `project/org:acme:website`. */
|
|
255
|
+
function formatBackofficeScopeRoutePath(scope, codec) {
|
|
256
|
+
if (scope.kind === "system") return "system/system";
|
|
257
|
+
const components = formatBackofficeScopeSegment(scope, codec).slice(scope.kind.length + 1);
|
|
258
|
+
return `${scope.kind}/${encodeBackofficeScopeForPath(components)}`;
|
|
259
|
+
}
|
|
260
|
+
/** Reads the decoded `<kind>/<id>` route parameters written by `formatBackofficeScopeRoutePath`. */
|
|
261
|
+
function parseBackofficeScopeRouteParams(params, codec) {
|
|
262
|
+
if (params.scopeKind === "system") {
|
|
263
|
+
if (params.scopeId !== "system") throw new BackofficeScopeParseError("System scope requires the system id.");
|
|
264
|
+
return { kind: "system" };
|
|
265
|
+
}
|
|
266
|
+
return parseBackofficeScopeSegment(`${params.scopeKind}:${params.scopeId}`, codec);
|
|
267
|
+
}
|
|
268
|
+
/** Names an ID-backed scope in one URL path segment, as the Backoffice API addresses scopes. */
|
|
269
|
+
function backofficeScopePathSegment(scope) {
|
|
270
|
+
return formatBackofficeScopeSegment(scope, backofficeScopeIdCodec);
|
|
271
|
+
}
|
|
272
|
+
/** Reads a segment written by `backofficeScopePathSegment`; anything else is a parse error. */
|
|
273
|
+
function parseBackofficeScopePathSegment(segment) {
|
|
274
|
+
return parseBackofficeScopeSegment(segment, backofficeScopeIdCodec);
|
|
275
|
+
}
|
|
276
|
+
//#endregion
|
|
277
|
+
export { BackofficeScopeParseError, backofficeAppScopeSchema, backofficeContextScopeSchema, backofficeContextScopesEqual, backofficeOrganizationScopeSchema, backofficeOrganizationSlugCodec, backofficeProjectScopeSchema, backofficePublicScopeCodec, backofficeRootOwnerSchema, backofficeRoutableScopeSchema, backofficeScopeContains, backofficeScopeIdCodec, backofficeScopeOrganization, backofficeScopePathSegment, backofficeScopeProjectOwner, backofficeScopeRootOwner, backofficeUserScopeSchema, backofficeWorkspaceOrganization, encodeBackofficeScopeForPath, formatBackofficeScopeRoutePath, formatBackofficeScopeSegment, isBackofficeRoutableScope, isBackofficeScopeParseError, mapBackofficeScopeNames, parseBackofficeScopePathSegment, parseBackofficeScopeRouteParams, parseBackofficeScopeSegment };
|
|
278
|
+
|
|
279
|
+
//# sourceMappingURL=scope.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scope.js","names":[],"sources":["../../../src/v0/shared/scope.ts"],"sourcesContent":["import { z } from \"zod\";\n\n/** How a scope names the organization and project it belongs to. */\nexport type BackofficeScopeNames = { organization: object; project: object };\n\n/** An organization scope, generic over how it names the organization. */\nexport type BackofficeOrganizationScope<TNames extends BackofficeScopeNames> = {\n kind: \"org\";\n} & TNames[\"organization\"];\n\n/** A user's personal scope. */\nexport type BackofficeUserScope = { kind: \"user\"; userId: string };\n\n/** The scopes that own everything else: every scope chain ends in an organization or a user. */\nexport type BackofficeRootOwner<TNames extends BackofficeScopeNames> =\n | BackofficeOrganizationScope<TNames>\n | BackofficeUserScope;\n\n/**\n * An installed app's own workspace, one per installation. The installation's owner owns it, and\n * the app ID is stable, so every spelling names the app by ID.\n */\nexport type BackofficeAppScope<TNames extends BackofficeScopeNames> = {\n kind: \"app\";\n owner: BackofficeRootOwner<TNames>;\n appId: string;\n};\n\n/** The scopes that can own a project. Projects never own projects. */\nexport type BackofficeProjectOwner<TNames extends BackofficeScopeNames> =\n | BackofficeRootOwner<TNames>\n | BackofficeAppScope<TNames>;\n\n/**\n * Where Backoffice work runs, generic over how it names its organization and project: by ID at\n * runtime, by slug in Backoffice URLs, or as loaded records. App and project scopes name their\n * owner as a scope.\n */\nexport type BackofficeScope<TNames extends BackofficeScopeNames> =\n | { kind: \"system\" }\n | BackofficeRootOwner<TNames>\n | BackofficeAppScope<TNames>\n | ({ kind: \"project\"; owner: BackofficeProjectOwner<TNames> } & TNames[\"project\"]);\n\n/** Scopes that own resources; system scope only administers them. */\nexport type BackofficeRoutable<TScope extends { kind: string }> = Exclude<\n TScope,\n { kind: \"system\" }\n>;\n\nexport type BackofficeScopeIdNames = {\n organization: { orgId: string };\n project: { projectId: string };\n};\n\n/** Where Backoffice work runs, naming organizations and projects by ID. */\nexport type BackofficeContextScope = BackofficeScope<BackofficeScopeIdNames>;\n\nexport type BackofficeRoutableScope = BackofficeRoutable<BackofficeContextScope>;\n\n/**\n * Public routes and CLI arguments name organizations by slug, never by internal ID. Projects keep\n * their ID, because public URLs are registered with external services and must survive renames.\n */\nexport type BackofficeScopePublicNames = {\n organization: { orgSlug: string };\n project: { projectId: string };\n};\n\nexport type BackofficePublicScope = BackofficeScope<BackofficeScopePublicNames>;\n\nconst backofficeSystemScopeSchema = z.lazy(() => z.strictObject({ kind: z.literal(\"system\") }));\nexport const backofficeOrganizationScopeSchema = z.lazy(() =>\n z.strictObject({\n kind: z.literal(\"org\"),\n orgId: z.string().trim().min(1),\n }),\n);\nexport const backofficeUserScopeSchema = z.lazy(() =>\n z.strictObject({\n kind: z.literal(\"user\"),\n userId: z.string().trim().min(1),\n }),\n);\nexport const backofficeRootOwnerSchema = z.lazy(() =>\n z.discriminatedUnion(\"kind\", [backofficeOrganizationScopeSchema, backofficeUserScopeSchema]),\n);\nexport const backofficeAppScopeSchema = z.lazy(() =>\n z.strictObject({\n kind: z.literal(\"app\"),\n owner: backofficeRootOwnerSchema,\n appId: z.string().trim().min(1),\n }),\n);\nexport const backofficeProjectScopeSchema = z.lazy(() =>\n z.strictObject({\n kind: z.literal(\"project\"),\n owner: z.discriminatedUnion(\"kind\", [\n backofficeOrganizationScopeSchema,\n backofficeUserScopeSchema,\n backofficeAppScopeSchema,\n ]),\n projectId: z.string().trim().min(1),\n }),\n);\n\nexport const backofficeRoutableScopeSchema = z.lazy(() =>\n z.discriminatedUnion(\"kind\", [\n backofficeOrganizationScopeSchema,\n backofficeUserScopeSchema,\n backofficeAppScopeSchema,\n backofficeProjectScopeSchema,\n ]),\n) satisfies z.ZodType<BackofficeRoutableScope>;\n\nexport const backofficeContextScopeSchema = z.lazy(() =>\n z.discriminatedUnion(\"kind\", [\n backofficeSystemScopeSchema,\n backofficeOrganizationScopeSchema,\n backofficeUserScopeSchema,\n backofficeAppScopeSchema,\n backofficeProjectScopeSchema,\n ]),\n) satisfies z.ZodType<BackofficeContextScope>;\n\nexport function isBackofficeRoutableScope(\n scope: BackofficeContextScope,\n): scope is BackofficeRoutableScope {\n return scope.kind !== \"system\";\n}\n\ntype ProjectNamesOf<TScope> = Omit<Extract<TScope, { kind: \"project\" }>, \"kind\" | \"owner\">;\n\n/** The root owners among a scope type's kinds, found by following each owner chain. */\nexport type BackofficeRootOwnerOf<TScope> = TScope extends { kind: \"org\" } | { kind: \"user\" }\n ? TScope\n : TScope extends { owner: infer TOwner }\n ? BackofficeRootOwnerOf<TOwner>\n : never;\n\n/** The organization scope a scope type's chains can end in. */\nexport type BackofficeOrganizationScopeOf<TScope> = Extract<\n BackofficeRootOwnerOf<TScope>,\n { kind: \"org\" }\n>;\n\ntype OrganizationNamesOf<TScope> = Omit<BackofficeOrganizationScopeOf<TScope>, \"kind\">;\n\n/** `null` when a scope type includes the system scope, which no root owner owns. */\ntype NullIfSystem<TScope> = [Extract<TScope, { kind: \"system\" }>] extends [never] ? never : null;\n\n/** `null` when a scope type includes scopes that belong to no organization. */\ntype NullUnlessOrganizationOwned<TScope> = [\n Extract<TScope, { kind: \"system\" }> | Extract<BackofficeRootOwnerOf<TScope>, { kind: \"user\" }>,\n] extends [never]\n ? never\n : null;\n\n/**\n * The organization or user at the end of a scope's owner chain, who answers for everything in it.\n * The system scope has none, so the result is only nullable when the scope type includes it.\n */\nexport function backofficeScopeRootOwner<TScope extends BackofficeScope<BackofficeScopeNames>>(\n scope: TScope,\n): BackofficeRootOwnerOf<TScope> | NullIfSystem<TScope> {\n const named: BackofficeScope<BackofficeScopeNames> = scope;\n switch (named.kind) {\n case \"org\":\n case \"user\":\n return named as BackofficeRootOwnerOf<TScope>;\n case \"app\":\n case \"project\":\n return backofficeScopeRootOwner(named.owner) as BackofficeRootOwnerOf<TScope>;\n case \"system\":\n return null as NullIfSystem<TScope>;\n default:\n throw new Error(\"Unsupported Backoffice scope kind.\", { cause: named satisfies never });\n }\n}\n\n/**\n * The organization a scope belongs to: its root owner, when that is an organization. The result is\n * only nullable when the scope type includes scopes that a user or nobody owns.\n */\nexport function backofficeScopeOrganization<TScope extends BackofficeScope<BackofficeScopeNames>>(\n scope: TScope,\n): BackofficeOrganizationScopeOf<TScope> | NullUnlessOrganizationOwned<TScope> {\n const owner: BackofficeRootOwner<BackofficeScopeNames> | null = backofficeScopeRootOwner(scope);\n return (owner?.kind === \"org\" ? owner : null) as\n | BackofficeOrganizationScopeOf<TScope>\n | NullUnlessOrganizationOwned<TScope>;\n}\n\n/**\n * The scope whose projects sit beside a workspace: the workspace itself, or a project's owner.\n * The system scope owns no projects.\n */\nexport function backofficeScopeProjectOwner<TNames extends BackofficeScopeNames>(\n scope: BackofficeScope<TNames>,\n): BackofficeProjectOwner<TNames> | null {\n switch (scope.kind) {\n case \"system\":\n return null;\n case \"project\":\n return scope.owner;\n case \"org\":\n case \"user\":\n case \"app\":\n return scope;\n default:\n throw new Error(\"Unsupported Backoffice scope kind.\", { cause: scope satisfies never });\n }\n}\n\n/**\n * The organization whose own workspace a scope is: the organization, or one of its projects. Unlike\n * `backofficeScopeOrganization`, an installed app's workspace is not its organization's.\n */\nexport function backofficeWorkspaceOrganization<TNames extends BackofficeScopeNames>(\n scope: BackofficeScope<TNames>,\n): BackofficeOrganizationScope<TNames> | null {\n const owner = backofficeScopeProjectOwner(scope);\n return owner?.kind === \"org\" ? owner : null;\n}\n\n/** Renames the records a scope refers to, e.g. from route slugs to runtime IDs; kinds are kept. */\nexport function mapBackofficeScopeNames<\n TScope extends BackofficeScope<BackofficeScopeNames>,\n TOrganization extends object,\n TProject extends object,\n>(\n scope: TScope,\n map: {\n organization(names: OrganizationNamesOf<TScope>): TOrganization;\n project(names: ProjectNamesOf<TScope>): TProject;\n },\n): Extract<\n BackofficeScope<{ organization: TOrganization; project: TProject }>,\n { kind: TScope[\"kind\"] }\n> {\n return renameScope(scope) as Extract<\n BackofficeScope<{ organization: TOrganization; project: TProject }>,\n { kind: TScope[\"kind\"] }\n >;\n\n // Narrowing a generic scope by kind does not narrow `TScope`, so each kind's names are cast to\n // the callback types. A project's owner is renamed as a scope of its own.\n function renameScope(\n named: BackofficeScope<BackofficeScopeNames>,\n ): BackofficeScope<{ organization: TOrganization; project: TProject }> {\n switch (named.kind) {\n case \"system\":\n return { kind: \"system\" };\n case \"org\":\n return { kind: \"org\", ...map.organization(named as OrganizationNamesOf<TScope>) };\n case \"user\":\n return { kind: \"user\", userId: named.userId };\n case \"app\":\n return {\n kind: \"app\",\n owner: renameScope(named.owner) as BackofficeRootOwner<{\n organization: TOrganization;\n project: TProject;\n }>,\n appId: named.appId,\n };\n case \"project\":\n return {\n kind: \"project\",\n ...map.project(named as unknown as ProjectNamesOf<TScope>),\n owner: renameScope(named.owner) as BackofficeProjectOwner<{\n organization: TOrganization;\n project: TProject;\n }>,\n };\n default:\n throw new Error(\"Unsupported Backoffice scope kind.\", { cause: named satisfies never });\n }\n }\n}\n\nexport function backofficeContextScopesEqual(\n left: BackofficeContextScope,\n right: BackofficeContextScope,\n): boolean {\n // The path segment names a scope exactly, so equal segments mean equal scopes.\n return backofficeScopePathSegment(left) === backofficeScopePathSegment(right);\n}\n\n/**\n * A scope restriction is an upper bound: a project's owner contains the project. Containment does\n * not chain, so an organization contains neither its apps' workspaces nor their projects.\n */\nexport function backofficeScopeContains(\n restriction: BackofficeContextScope,\n target: BackofficeContextScope,\n): boolean {\n return (\n backofficeContextScopesEqual(restriction, target) ||\n (target.kind === \"project\" && backofficeContextScopesEqual(restriction, target.owner))\n );\n}\n\nconst INVALID_BACKOFFICE_SCOPE = \"INVALID_BACKOFFICE_SCOPE\";\n\n/** A scope could not be read from untrusted text, such as a URL. */\nexport class BackofficeScopeParseError extends Error {\n readonly code = INVALID_BACKOFFICE_SCOPE;\n\n constructor(message: string) {\n super(message);\n this.name = \"BackofficeScopeParseError\";\n }\n}\n\n/** Matches by code too, because errors lose their class across module copies and RPC. */\nexport function isBackofficeScopeParseError(error: unknown): error is BackofficeScopeParseError {\n return (\n error instanceof BackofficeScopeParseError ||\n (typeof error === \"object\" &&\n error !== null &&\n \"code\" in error &&\n error.code === INVALID_BACKOFFICE_SCOPE)\n );\n}\n\n/** How one of a scope's names is written in text, and what a parse error calls it. */\nexport type BackofficeNameCodec<TName extends object> = {\n label: string;\n format(name: TName): string;\n parse(value: string): TName;\n};\n\nexport type BackofficeScopeCodec<TNames extends BackofficeScopeNames> = {\n organization: BackofficeNameCodec<TNames[\"organization\"]>;\n project: BackofficeNameCodec<TNames[\"project\"]>;\n};\n\nconst organizationIdCodec: BackofficeNameCodec<{ orgId: string }> = {\n label: \"org id\",\n format: (name) => name.orgId,\n parse: (orgId) => ({ orgId }),\n};\n\nconst projectIdCodec: BackofficeNameCodec<{ projectId: string }> = {\n label: \"project id\",\n format: (name) => name.projectId,\n parse: (projectId) => ({ projectId }),\n};\n\nexport const backofficeOrganizationSlugCodec: BackofficeNameCodec<{ orgSlug: string }> = {\n label: \"organization slug\",\n format: (name) => name.orgSlug,\n parse: (orgSlug) => ({ orgSlug }),\n};\n\nexport const backofficeScopeIdCodec: BackofficeScopeCodec<BackofficeScopeIdNames> = {\n organization: organizationIdCodec,\n project: projectIdCodec,\n};\n\nexport const backofficePublicScopeCodec: BackofficeScopeCodec<BackofficeScopePublicNames> = {\n organization: backofficeOrganizationSlugCodec,\n project: projectIdCodec,\n};\n\n/**\n * Names a scope in one URL path segment, e.g. `project:org:<org>:<projectId>`: app and project\n * scopes embed their owner's segment. Components are URI-encoded, so `:` only ever separates them.\n */\nexport function formatBackofficeScopeSegment<TNames extends BackofficeScopeNames>(\n scope: BackofficeScope<TNames>,\n codec: BackofficeScopeCodec<TNames>,\n): string {\n switch (scope.kind) {\n case \"system\":\n return \"system\";\n case \"org\":\n return `org:${encodeURIComponent(codec.organization.format(scope))}`;\n case \"user\":\n return `user:${encodeURIComponent(scope.userId)}`;\n case \"app\":\n return `app:${formatBackofficeScopeSegment<TNames>(scope.owner, codec)}:${encodeURIComponent(scope.appId)}`;\n case \"project\":\n return `project:${formatBackofficeScopeSegment<TNames>(scope.owner, codec)}:${encodeURIComponent(codec.project.format(scope))}`;\n default:\n throw new Error(\"Unsupported Backoffice scope kind.\", { cause: scope satisfies never });\n }\n}\n\n/** Reads a segment written by `formatBackofficeScopeSegment`; anything else is a parse error. */\nexport function parseBackofficeScopeSegment<TNames extends BackofficeScopeNames>(\n segment: string,\n codec: BackofficeScopeCodec<TNames>,\n): BackofficeScope<TNames> {\n const components = segment.split(\":\");\n let next = 0;\n const scope = readScope();\n if (next !== components.length) {\n throw new BackofficeScopeParseError(\n `${scopeLabel(scope.kind)} scope has unexpected components after it.`,\n );\n }\n return scope;\n\n // Reads one scope from the components, leaving those after it for an enclosing scope.\n function readScope(): BackofficeScope<TNames> {\n const kind = components[next++];\n switch (kind) {\n case \"system\":\n return { kind: \"system\" };\n case \"org\":\n return {\n kind: \"org\",\n ...codec.organization.parse(readComponent(codec.organization.label)),\n } as BackofficeOrganizationScope<TNames>;\n case \"user\":\n return { kind: \"user\", userId: readComponent(\"user id\") };\n case \"app\": {\n const owner = readOwner(\"App\");\n if (owner.kind !== \"org\" && owner.kind !== \"user\") {\n throw new BackofficeScopeParseError(`${scopeLabel(owner.kind)} scope cannot own an app.`);\n }\n return { kind: \"app\", owner, appId: readComponent(\"app id\") };\n }\n case \"project\": {\n const owner = readOwner(\"Project\");\n if (owner.kind === \"system\" || owner.kind === \"project\") {\n throw new BackofficeScopeParseError(\n `${scopeLabel(owner.kind)} scope cannot own a project.`,\n );\n }\n return {\n kind: \"project\",\n owner,\n ...codec.project.parse(readComponent(codec.project.label)),\n };\n }\n default:\n throw new BackofficeScopeParseError(`Unknown scope kind '${kind ?? \"\"}'.`);\n }\n }\n\n function readOwner(ownedLabel: string): BackofficeScope<TNames> {\n if (next === components.length) {\n throw new BackofficeScopeParseError(`${ownedLabel} scope requires an owner scope.`);\n }\n return readScope();\n }\n\n function readComponent(label: string): string {\n const value = components[next++];\n if (value === undefined) {\n throw new BackofficeScopeParseError(`Missing ${label}.`);\n }\n return decodeSegmentComponent(value, label);\n }\n}\n\nfunction decodeSegmentComponent(value: string, label: string): string {\n let decoded: string;\n try {\n decoded = decodeURIComponent(value);\n } catch {\n throw new BackofficeScopeParseError(`Invalid ${label} encoding.`);\n }\n if (!decoded) {\n throw new BackofficeScopeParseError(`Missing ${label}.`);\n }\n return decoded;\n}\n\nfunction scopeLabel(kind: BackofficeContextScope[\"kind\"]): string {\n switch (kind) {\n case \"system\":\n return \"System\";\n case \"org\":\n return \"Org\";\n case \"user\":\n return \"User\";\n case \"app\":\n return \"App\";\n case \"project\":\n return \"Project\";\n default:\n throw new Error(\"Unsupported Backoffice scope kind.\", { cause: kind satisfies never });\n }\n}\n\n/**\n * Escapes scope text for a URL path segment that a router decodes once before it is parsed. Paths\n * allow a literal `:`, so the separator stays readable; a `:` inside a component was already\n * escaped when the segment was formatted.\n */\nexport function encodeBackofficeScopeForPath(text: string): string {\n return encodeURIComponent(text).replaceAll(\"%3A\", \":\");\n}\n\n/** Names a scope in two URL path segments, `<kind>/<id>`, e.g. `project/org:acme:website`. */\nexport function formatBackofficeScopeRoutePath<TNames extends BackofficeScopeNames>(\n scope: BackofficeScope<TNames>,\n codec: BackofficeScopeCodec<TNames>,\n): string {\n if (scope.kind === \"system\") {\n return \"system/system\";\n }\n const components = formatBackofficeScopeSegment(scope, codec).slice(scope.kind.length + 1);\n return `${scope.kind}/${encodeBackofficeScopeForPath(components)}`;\n}\n\n/** Reads the decoded `<kind>/<id>` route parameters written by `formatBackofficeScopeRoutePath`. */\nexport function parseBackofficeScopeRouteParams<TNames extends BackofficeScopeNames>(\n params: { scopeKind: string; scopeId: string },\n codec: BackofficeScopeCodec<TNames>,\n): BackofficeScope<TNames> {\n if (params.scopeKind === \"system\") {\n if (params.scopeId !== \"system\") {\n throw new BackofficeScopeParseError(\"System scope requires the system id.\");\n }\n return { kind: \"system\" };\n }\n return parseBackofficeScopeSegment(`${params.scopeKind}:${params.scopeId}`, codec);\n}\n\n/** Names an ID-backed scope in one URL path segment, as the Backoffice API addresses scopes. */\nexport function backofficeScopePathSegment(scope: BackofficeContextScope): string {\n return formatBackofficeScopeSegment(scope, backofficeScopeIdCodec);\n}\n\n/** Reads a segment written by `backofficeScopePathSegment`; anything else is a parse error. */\nexport function parseBackofficeScopePathSegment(segment: string): BackofficeContextScope {\n return parseBackofficeScopeSegment(segment, backofficeScopeIdCodec);\n}\n"],"mappings":"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"}
|