@foir/sdk 0.18.0 → 0.20.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/CHANGELOG.md +365 -0
- package/README.md +8 -1
- package/dist/app/client.d.ts +129 -21
- package/dist/app/contract/proto/apps/v1/apps_pb.d.ts +223 -211
- package/dist/app/errors.d.ts +2 -2
- package/dist/app/index.d.ts +4 -4
- package/dist/app/manifest.d.ts +1 -1
- package/dist/app/vocabulary.generated.d.ts +13 -10
- package/dist/app-contract.js +27 -31
- package/dist/app.js +90 -25
- package/dist/auth/access.d.ts +106 -0
- package/dist/auth/grant-table.generated.d.ts +13 -0
- package/dist/auth/grants.d.ts +38 -0
- package/dist/auth/index.d.ts +2 -0
- package/dist/auth/operations.d.ts +6 -1
- package/dist/auth/ops.d.ts +1 -0
- package/dist/auth.js +269 -1
- package/dist/data/builtins.d.ts +59 -3
- package/dist/data/compatibility.d.ts +95 -0
- package/dist/data/document.d.ts +11 -1
- package/dist/data/index.d.ts +1 -1
- package/dist/data/transport.d.ts +51 -27
- package/dist/data.js +337 -7
- package/dist/next.js +3 -0
- package/dist/placement/index.d.ts +40 -8
- package/dist/placement.js +224 -2
- package/dist/push.js +3 -0
- package/dist/react/FoirProvider.d.ts +40 -1
- package/dist/react/feedback-notes.d.ts +1 -1
- package/dist/react/index.d.ts +5 -4
- package/dist/react.js +347 -3
- package/dist/server/events-client.d.ts +5 -5
- package/dist/server/index.d.ts +1 -1
- package/dist/server/older-claims.generated.d.ts +8 -0
- package/dist/server/require-scoped-token.d.ts +1 -1
- package/dist/server/verify-scoped-token.d.ts +36 -17
- package/dist/server.js +267 -5
- package/package.json +6 -5
package/dist/server.js
CHANGED
|
@@ -72,6 +72,208 @@ async function verifyWebhookSignature(payload, signature, secret) {
|
|
|
72
72
|
return mismatch === 0;
|
|
73
73
|
}
|
|
74
74
|
|
|
75
|
+
// src/auth/grant-table.generated.ts
|
|
76
|
+
var GRANT_TABLE = [
|
|
77
|
+
["records:read", true, ["own", "named", "all"], []],
|
|
78
|
+
["records:create", true, [], []],
|
|
79
|
+
["records:write", true, ["own", "named", "all"], []],
|
|
80
|
+
["records:delete", true, ["own", "named", "all"], []],
|
|
81
|
+
["records:publish", true, ["own", "all"], []],
|
|
82
|
+
["records:attribute", true, [], []],
|
|
83
|
+
["search:read", true, [], []],
|
|
84
|
+
["embeddings:read", false, [], []],
|
|
85
|
+
["embeddings:write", false, [], []],
|
|
86
|
+
["schemas:read", false, [], []],
|
|
87
|
+
["drafts:read", false, [], []],
|
|
88
|
+
["files:read", false, ["own", "all"], []],
|
|
89
|
+
["files:write", false, ["own", "all"], []],
|
|
90
|
+
["files:delete", false, ["own", "all"], []],
|
|
91
|
+
["notifications:read", false, ["own", "all"], []],
|
|
92
|
+
["notifications:write", false, ["own", "named", "all"], []],
|
|
93
|
+
["notifications:consent", false, [], []],
|
|
94
|
+
["pushcredentials:read", false, [], []],
|
|
95
|
+
["pushcredentials:write", false, [], []],
|
|
96
|
+
["notes:read", false, [], []],
|
|
97
|
+
["notes:write", false, [], []],
|
|
98
|
+
["notes:create", false, [], []],
|
|
99
|
+
["approvals:read", false, [], []],
|
|
100
|
+
["approvals:write", false, [], []],
|
|
101
|
+
["rooms:read", true, [], []],
|
|
102
|
+
["rooms:write", true, [], []],
|
|
103
|
+
["presence:read", true, [], []],
|
|
104
|
+
["operations:read", false, [], []],
|
|
105
|
+
["operations:execute", true, [], []],
|
|
106
|
+
["operations:write", false, [], []],
|
|
107
|
+
["operations:complete", false, [], []],
|
|
108
|
+
["status:write", false, [], []],
|
|
109
|
+
["appconfig:read", false, [], []],
|
|
110
|
+
["schedules:read", false, [], []],
|
|
111
|
+
["schedules:write", false, [], []],
|
|
112
|
+
["hooks:read", false, [], []],
|
|
113
|
+
["hooks:write", false, [], []],
|
|
114
|
+
["relyingparties:read", false, [], []],
|
|
115
|
+
["relyingparties:write", false, [], []],
|
|
116
|
+
["domains:read", false, [], []],
|
|
117
|
+
["domains:write", false, [], []],
|
|
118
|
+
["secrets:read", false, [], []],
|
|
119
|
+
["secrets:list", false, [], []],
|
|
120
|
+
["secrets:put", false, [], []],
|
|
121
|
+
["secrets:delete", false, [], []],
|
|
122
|
+
["appsecrets:read", false, [], []],
|
|
123
|
+
["appsecrets:list", false, [], []],
|
|
124
|
+
["appsecrets:put", false, [], []],
|
|
125
|
+
["appsecrets:delete", false, [], []],
|
|
126
|
+
["opsecrets:read", false, [], []],
|
|
127
|
+
["opsecrets:write", false, [], []],
|
|
128
|
+
["settings:read", false, [], []],
|
|
129
|
+
["settings:write", false, [], []],
|
|
130
|
+
["designtokens:read", false, [], []],
|
|
131
|
+
["designtokens:write", false, [], []],
|
|
132
|
+
["models:read", false, [], []],
|
|
133
|
+
["models:write", false, [], []],
|
|
134
|
+
["configs:read", false, [], []],
|
|
135
|
+
["configs:write", false, [], []],
|
|
136
|
+
["apps:read", false, [], []],
|
|
137
|
+
["apps:write", false, [], []],
|
|
138
|
+
["events:read", false, [], []],
|
|
139
|
+
["targeting:debug", false, [], []],
|
|
140
|
+
["visitors:forward", false, [], []],
|
|
141
|
+
["apikeys:read", false, [], []],
|
|
142
|
+
["apikeys:write", false, [], []],
|
|
143
|
+
["organizations:read", false, [], []],
|
|
144
|
+
["organizations:write", false, [], []],
|
|
145
|
+
["organizations:create", false, [], []],
|
|
146
|
+
["organizations:delete", false, [], []],
|
|
147
|
+
["organizations:reach", false, [], []],
|
|
148
|
+
["members:read", false, [], []],
|
|
149
|
+
["members:write", false, [], []],
|
|
150
|
+
["roles:read", false, [], []],
|
|
151
|
+
["roles:write", false, [], []],
|
|
152
|
+
["projects:read", false, [], []],
|
|
153
|
+
["projects:write", false, [], []],
|
|
154
|
+
["project:manage", false, [], ["records:read.all", "records:create", "records:write.all", "records:delete.all", "records:publish.all", "records:attribute", "search:read", "embeddings:read", "embeddings:write", "schemas:read", "drafts:read", "files:read.all", "files:write.all", "files:delete.all", "users:read.all", "identities:read", "users:create", "identities:delete", "users:write.all", "users:delete.all", "notifications:read.all", "notifications:write.all", "notifications:consent", "pushcredentials:read", "pushcredentials:write", "notes:read", "notes:write", "notes:create", "approvals:read", "approvals:write", "rooms:read", "rooms:write", "presence:read", "operations:read", "operations:execute", "operations:write", "appconfig:read", "schedules:read", "schedules:write", "hooks:read", "hooks:write", "auth:login_with_foir", "relyingparties:read", "relyingparties:write", "domains:read", "domains:write", "secrets:read", "secrets:list", "secrets:put", "secrets:delete", "appsecrets:read", "appsecrets:list", "appsecrets:put", "appsecrets:delete", "usersecrets:read", "usersecrets:list", "usersecrets:put", "usersecrets:delete", "opsecrets:read", "opsecrets:write", "settings:read", "settings:write", "designtokens:read", "designtokens:write", "models:read", "models:write", "configs:read", "configs:write", "signinproviders:read", "signinproviders:write", "apps:read", "apps:write", "events:read", "targeting:debug", "visitors:forward", "apikeys:read", "apikeys:write", "organizations:read", "organizations:create", "organizations:delete", "organizations:write", "organizations:reach", "members:read", "members:write", "roles:read", "roles:write", "projects:read", "projects:write"]],
|
|
155
|
+
["projects:create", false, [], []],
|
|
156
|
+
["projects:delete", false, [], []],
|
|
157
|
+
["tenants:read", false, [], []],
|
|
158
|
+
["tenants:write", false, [], []],
|
|
159
|
+
["tenants:delete", false, [], []],
|
|
160
|
+
["audit:read", false, [], []],
|
|
161
|
+
["export:run", false, [], []],
|
|
162
|
+
["billing:read", false, [], []],
|
|
163
|
+
["billing:manage", false, [], []],
|
|
164
|
+
["usage:read", false, [], []],
|
|
165
|
+
["controlkeys:read", false, [], []],
|
|
166
|
+
["controlkeys:write", false, [], []],
|
|
167
|
+
["tenanthooks:read", false, [], []],
|
|
168
|
+
["tenanthooks:write", false, [], []],
|
|
169
|
+
["apps:install", false, [], []],
|
|
170
|
+
["tenant:manage", false, [], ["project:manage", "projects:create", "projects:delete", "tenants:read", "tenants:write", "tenants:delete", "audit:read", "export:run", "billing:read", "billing:manage", "usage:read", "controlkeys:read", "controlkeys:write", "tenanthooks:read", "tenanthooks:write", "apps:install"]],
|
|
171
|
+
["platform:read", false, [], []],
|
|
172
|
+
["platform:manage", false, [], ["tenant:manage", "platform:read", "platform:create_workspace", "users:setup"]],
|
|
173
|
+
["platform:create_workspace", false, [], []],
|
|
174
|
+
["users:read", false, ["own", "named", "all"], []],
|
|
175
|
+
["users:write", false, ["own", "all"], []],
|
|
176
|
+
["users:setup", false, [], []],
|
|
177
|
+
["users:delete", false, ["own", "all"], []],
|
|
178
|
+
["users:create", false, [], []],
|
|
179
|
+
["identities:read", false, [], []],
|
|
180
|
+
["identities:delete", false, [], []],
|
|
181
|
+
["usersecrets:read", false, [], []],
|
|
182
|
+
["usersecrets:list", false, [], []],
|
|
183
|
+
["usersecrets:put", false, [], []],
|
|
184
|
+
["usersecrets:delete", false, [], []],
|
|
185
|
+
["auth:login_with_foir", false, [], []],
|
|
186
|
+
["signinproviders:read", false, [], []],
|
|
187
|
+
["signinproviders:write", false, [], []]
|
|
188
|
+
];
|
|
189
|
+
|
|
190
|
+
// src/auth/grants.ts
|
|
191
|
+
var index;
|
|
192
|
+
function catalogue() {
|
|
193
|
+
if (!index) {
|
|
194
|
+
const byName = new Map(GRANT_TABLE.map((row) => [row[0], row]));
|
|
195
|
+
const longestFirst = [...byName.keys()].sort(
|
|
196
|
+
(a, b) => a.length !== b.length ? b.length - a.length : a < b ? -1 : 1
|
|
197
|
+
);
|
|
198
|
+
index = { byName, longestFirst };
|
|
199
|
+
}
|
|
200
|
+
return index;
|
|
201
|
+
}
|
|
202
|
+
function hasReach(permission, reach) {
|
|
203
|
+
const reaches = permission[2];
|
|
204
|
+
return reaches.length === 0 ? reach === "own" : reaches.includes(reach);
|
|
205
|
+
}
|
|
206
|
+
function parseGrant(s) {
|
|
207
|
+
const { byName, longestFirst } = catalogue();
|
|
208
|
+
for (const name of longestFirst) {
|
|
209
|
+
if (!s.startsWith(name)) continue;
|
|
210
|
+
let rest = s.slice(name.length);
|
|
211
|
+
if (rest !== "" && rest[0] !== "." && rest[0] !== ":") continue;
|
|
212
|
+
const permission = byName.get(name);
|
|
213
|
+
let reach = "own";
|
|
214
|
+
if (rest.startsWith(".")) {
|
|
215
|
+
const after = rest.slice(1);
|
|
216
|
+
const colon = after.indexOf(":");
|
|
217
|
+
const word = colon < 0 ? after : after.slice(0, colon);
|
|
218
|
+
if (word !== "named" && word !== "all") return null;
|
|
219
|
+
if (!hasReach(permission, word)) return null;
|
|
220
|
+
reach = word;
|
|
221
|
+
rest = after.slice(word.length);
|
|
222
|
+
}
|
|
223
|
+
let target = "";
|
|
224
|
+
if (rest.startsWith(":")) {
|
|
225
|
+
target = rest.slice(1);
|
|
226
|
+
if (!permission[1]) return null;
|
|
227
|
+
if (target === "" || /[: \t\n*]/.test(target)) return null;
|
|
228
|
+
}
|
|
229
|
+
return { permission, reach, target };
|
|
230
|
+
}
|
|
231
|
+
return null;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
// src/server/older-claims.generated.ts
|
|
235
|
+
var OLDER_CLAIM_TARGET = "{target}";
|
|
236
|
+
var OLDER_CAPABILITY_GRANTS = {
|
|
237
|
+
"config:read": ["appconfig:read"],
|
|
238
|
+
"customers:read": ["users:read.all"],
|
|
239
|
+
"customers:read:identity": ["identities:read"],
|
|
240
|
+
"customers:read:named": ["users:read.named"],
|
|
241
|
+
"customers:write": ["users:create"],
|
|
242
|
+
"embeddings:read": ["embeddings:read"],
|
|
243
|
+
"embeddings:write": ["embeddings:write"],
|
|
244
|
+
"files:delete": ["files:delete"],
|
|
245
|
+
"files:list": ["files:read"],
|
|
246
|
+
"files:read": ["files:read"],
|
|
247
|
+
"files:write": ["files:write"],
|
|
248
|
+
"notifications:consent": ["notifications:consent"],
|
|
249
|
+
"notifications:read": ["notifications:read"],
|
|
250
|
+
"notifications:write": ["notifications:write.named"],
|
|
251
|
+
"operations:complete": ["operations:complete"],
|
|
252
|
+
"records:attribute": ["records:attribute"],
|
|
253
|
+
"records:attribute:{target}": ["records:attribute:{target}"],
|
|
254
|
+
"records:delete": [],
|
|
255
|
+
"records:delete:{target}": ["records:delete:{target}"],
|
|
256
|
+
"records:publish": [],
|
|
257
|
+
"records:publish:{target}": ["records:publish:{target}"],
|
|
258
|
+
"records:read": [],
|
|
259
|
+
"records:read:{target}": ["records:read:{target}"],
|
|
260
|
+
"records:write": [],
|
|
261
|
+
"records:write:{target}": ["records:write.all:{target}", "records:create:{target}"],
|
|
262
|
+
"secrets:delete.app": ["appsecrets:delete"],
|
|
263
|
+
"secrets:delete.customer": ["usersecrets:delete"],
|
|
264
|
+
"secrets:delete.project": ["secrets:delete"],
|
|
265
|
+
"secrets:list.app": ["appsecrets:list"],
|
|
266
|
+
"secrets:list.customer": ["usersecrets:list"],
|
|
267
|
+
"secrets:list.project": ["secrets:list"],
|
|
268
|
+
"secrets:put.app": ["appsecrets:put"],
|
|
269
|
+
"secrets:put.customer": ["usersecrets:put"],
|
|
270
|
+
"secrets:put.project": ["secrets:put"],
|
|
271
|
+
"secrets:read.app": ["appsecrets:read"],
|
|
272
|
+
"secrets:read.customer": ["usersecrets:read"],
|
|
273
|
+
"secrets:read.project": ["secrets:read"],
|
|
274
|
+
"status:write": ["status:write"]
|
|
275
|
+
};
|
|
276
|
+
|
|
75
277
|
// src/server/verify-scoped-token.ts
|
|
76
278
|
var JWKS_CACHE_TTL_MS = 5 * 60 * 1e3;
|
|
77
279
|
function getCache() {
|
|
@@ -129,11 +331,66 @@ function parseSubject(sub) {
|
|
|
129
331
|
}
|
|
130
332
|
return { tenantId, projectId, appName: sub.slice(second + 1) };
|
|
131
333
|
}
|
|
334
|
+
function modelsFor(claims, permission) {
|
|
335
|
+
const out = [];
|
|
336
|
+
for (const grant of claims.grants) {
|
|
337
|
+
const parsed = parseGrant(grant);
|
|
338
|
+
if (!parsed || parsed.permission[0] !== permission || parsed.target === "") continue;
|
|
339
|
+
if (!out.includes(parsed.target)) out.push(parsed.target);
|
|
340
|
+
}
|
|
341
|
+
return out;
|
|
342
|
+
}
|
|
132
343
|
function recordsReadModels(claims) {
|
|
133
|
-
return claims
|
|
344
|
+
return modelsFor(claims, "records:read");
|
|
134
345
|
}
|
|
135
346
|
function recordsWriteModels(claims) {
|
|
136
|
-
return claims
|
|
347
|
+
return modelsFor(claims, "records:write");
|
|
348
|
+
}
|
|
349
|
+
function recordsCreateModels(claims) {
|
|
350
|
+
return modelsFor(claims, "records:create");
|
|
351
|
+
}
|
|
352
|
+
var OLDER_RECORD_LANES = [
|
|
353
|
+
["records:read", "rrm"],
|
|
354
|
+
["records:write", "rwm"],
|
|
355
|
+
["records:delete", "rdm"],
|
|
356
|
+
["records:publish", "rpm"]
|
|
357
|
+
];
|
|
358
|
+
function strings(value) {
|
|
359
|
+
return Array.isArray(value) ? value.filter((item) => typeof item === "string") : [];
|
|
360
|
+
}
|
|
361
|
+
function worthBefore(capability) {
|
|
362
|
+
if (Object.hasOwn(OLDER_CAPABILITY_GRANTS, capability)) return OLDER_CAPABILITY_GRANTS[capability] ?? [];
|
|
363
|
+
for (const [form, grants] of Object.entries(OLDER_CAPABILITY_GRANTS)) {
|
|
364
|
+
if (!form.endsWith(OLDER_CLAIM_TARGET)) continue;
|
|
365
|
+
const prefix = form.slice(0, -OLDER_CLAIM_TARGET.length);
|
|
366
|
+
if (capability.startsWith(prefix) && capability.length > prefix.length) {
|
|
367
|
+
const model = capability.slice(prefix.length);
|
|
368
|
+
return grants.map((grant) => grant.replace(OLDER_CLAIM_TARGET, model));
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
return [];
|
|
372
|
+
}
|
|
373
|
+
var OLDER_WRITE = "records:write";
|
|
374
|
+
var OLDER_DELETE = "records:delete";
|
|
375
|
+
var OLDER_CREATE = "customers:write";
|
|
376
|
+
function grantsOfOlderClaims(payload) {
|
|
377
|
+
const cap = strings(payload.cap);
|
|
378
|
+
const written = new Set(cap.includes(OLDER_WRITE) ? strings(payload.rwm) : []);
|
|
379
|
+
const grants = [];
|
|
380
|
+
for (const [marker, claim] of OLDER_RECORD_LANES) {
|
|
381
|
+
if (!cap.includes(marker)) continue;
|
|
382
|
+
for (const model of strings(payload[claim])) {
|
|
383
|
+
if (marker !== OLDER_WRITE && written.has(model)) grants.push(`${marker}.all:${model}`);
|
|
384
|
+
else grants.push(...worthBefore(`${marker}:${model}`));
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
for (const capability of cap) {
|
|
388
|
+
if (!OLDER_RECORD_LANES.some(([marker]) => marker === capability)) grants.push(...worthBefore(capability));
|
|
389
|
+
}
|
|
390
|
+
if (cap.includes(OLDER_CREATE) && cap.includes(OLDER_DELETE) && strings(payload.rdm).length > 0) {
|
|
391
|
+
grants.push("identities:delete");
|
|
392
|
+
}
|
|
393
|
+
return grants;
|
|
137
394
|
}
|
|
138
395
|
async function verifyScopedToken(token, jwksUrl, options) {
|
|
139
396
|
return verifyWithKeys(token, () => loadJwks(jwksUrl), void 0, options);
|
|
@@ -169,12 +426,16 @@ async function verifyWithKeys(token, loadKeys, refetchForUnknownKid, options) {
|
|
|
169
426
|
)
|
|
170
427
|
);
|
|
171
428
|
if (!ok) throw new Error("signature invalid");
|
|
172
|
-
let
|
|
429
|
+
let payload;
|
|
173
430
|
try {
|
|
174
|
-
|
|
431
|
+
payload = JSON.parse(new TextDecoder().decode(base64UrlDecode(rawPayload)));
|
|
175
432
|
} catch {
|
|
176
433
|
throw new Error("unreadable token payload");
|
|
177
434
|
}
|
|
435
|
+
const claims = {
|
|
436
|
+
...payload,
|
|
437
|
+
grants: "grants" in payload ? strings(payload.grants) : grantsOfOlderClaims(payload)
|
|
438
|
+
};
|
|
178
439
|
const now = Math.floor((options?.now?.() ?? Date.now()) / 1e3);
|
|
179
440
|
if (claims.iss !== expectedIssuer) throw new Error(`bad iss ${claims.iss}`);
|
|
180
441
|
if (typeof claims.exp !== "number" || claims.exp < now) {
|
|
@@ -1241,7 +1502,7 @@ function describe2(payload) {
|
|
|
1241
1502
|
|
|
1242
1503
|
// src/server/events-client.ts
|
|
1243
1504
|
var FOIR_EVENTS_PATH = "/v1/events";
|
|
1244
|
-
var FOIR_EVENTS_SCOPE = "events:
|
|
1505
|
+
var FOIR_EVENTS_SCOPE = "events:read";
|
|
1245
1506
|
var FOIR_EVENTS_RETENTION_DAYS = 90;
|
|
1246
1507
|
var FoirEventCursorExpiredError = class extends FoirRequestError {
|
|
1247
1508
|
/**
|
|
@@ -1529,6 +1790,7 @@ export {
|
|
|
1529
1790
|
parseContextHeader,
|
|
1530
1791
|
parseSubject,
|
|
1531
1792
|
readDispatch,
|
|
1793
|
+
recordsCreateModels,
|
|
1532
1794
|
recordsReadModels,
|
|
1533
1795
|
recordsWriteModels,
|
|
1534
1796
|
requireScopedToken,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@foir/sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.20.0",
|
|
4
4
|
"description": "Official Foir SDK — editor iframe client + server-side platform helpers",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"publishConfig": {
|
|
@@ -177,18 +177,19 @@
|
|
|
177
177
|
"ws": "^8.18.0",
|
|
178
178
|
"y-websocket": "^3.0.0",
|
|
179
179
|
"yjs": "^13.6.30",
|
|
180
|
+
"@foir/access-vocab": "0.0.0",
|
|
180
181
|
"@foir/proto-ts": "0.109.0"
|
|
181
182
|
},
|
|
182
183
|
"engines": {
|
|
183
184
|
"node": ">=18.0.0"
|
|
184
185
|
},
|
|
185
186
|
"scripts": {
|
|
186
|
-
"build": "node scripts/generate-app-vocabulary.mjs && node scripts/clean-dist.mjs && tsup && tsc -p tsconfig.build.json && node scripts/bundle-app-contract-types.mjs && node scripts/assert-export-types.mjs && node scripts/assert-public-exports.mjs",
|
|
187
|
+
"build": "node scripts/generate-app-vocabulary.mjs && node scripts/generate-grant-table.mjs && node scripts/clean-dist.mjs && tsup && tsc -p tsconfig.build.json && node scripts/bundle-app-contract-types.mjs && node scripts/assert-export-types.mjs && node scripts/assert-public-exports.mjs",
|
|
187
188
|
"snapshot:exports": "node scripts/assert-public-exports.mjs --update",
|
|
188
189
|
"dev": "node scripts/dev-watch.mjs",
|
|
189
|
-
"check-types": "node scripts/generate-app-vocabulary.mjs && tsc --noEmit",
|
|
190
|
-
"test": "node scripts/generate-app-vocabulary.mjs && vitest run",
|
|
191
|
-
"test:watch": "node scripts/generate-app-vocabulary.mjs && vitest watch",
|
|
190
|
+
"check-types": "node scripts/generate-app-vocabulary.mjs && node scripts/generate-grant-table.mjs && tsc --noEmit",
|
|
191
|
+
"test": "node scripts/generate-app-vocabulary.mjs && node scripts/generate-grant-table.mjs && vitest run",
|
|
192
|
+
"test:watch": "node scripts/generate-app-vocabulary.mjs && node scripts/generate-grant-table.mjs && vitest watch",
|
|
192
193
|
"release:patch": "pnpm version patch",
|
|
193
194
|
"release:minor": "pnpm version minor",
|
|
194
195
|
"release:major": "pnpm version major"
|