@ttt-productions/q-core 0.1.5 → 0.1.7
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/dist/constants/media.d.ts +2 -0
- package/dist/constants/media.d.ts.map +1 -1
- package/dist/constants/media.js +6 -0
- package/dist/constants/media.js.map +1 -1
- package/dist/doc-schemas/award-group-grant.d.ts +7 -0
- package/dist/doc-schemas/award-group-grant.d.ts.map +1 -1
- package/dist/doc-schemas/award-group-grant.js +9 -0
- package/dist/doc-schemas/award-group-grant.js.map +1 -1
- package/dist/schemas/uploads.d.ts +16 -0
- package/dist/schemas/uploads.d.ts.map +1 -1
- package/dist/schemas/uploads.js +15 -2
- package/dist/schemas/uploads.js.map +1 -1
- package/package.json +1 -1
|
@@ -13,4 +13,6 @@ export declare const MEDIA_SWEEP_BACKOFF_BASE_MS: number;
|
|
|
13
13
|
export declare const MEDIA_SWEEP_BACKOFF_MAX_MS: number;
|
|
14
14
|
export declare const MAX_V1_PICTURE_CARRY_ATTEMPTS = 3;
|
|
15
15
|
export declare const MAX_STAGING_UPLOAD_PATH_LENGTH = 300;
|
|
16
|
+
export declare const UPLOAD_TRAY_WINDOW_MS: number;
|
|
17
|
+
export declare const MAX_UPLOADS_MARKED_SEEN_PER_CALL = 200;
|
|
16
18
|
//# sourceMappingURL=media.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"media.d.ts","sourceRoot":"","sources":["../../src/constants/media.ts"],"names":[],"mappings":"AASA,eAAO,MAAM,6BAA6B,IAAI,CAAC;AAI/C,eAAO,MAAM,yBAAyB,QAAiB,CAAC;AAIxD,eAAO,MAAM,0BAA0B,QAAiB,CAAC;AAIzD,eAAO,MAAM,wBAAwB,QAAe,CAAC;AAIrD,eAAO,MAAM,6BAA6B,MAAM,CAAC;AACjD,eAAO,MAAM,qCAAqC,IAAI,CAAC;AACvD,eAAO,MAAM,4BAA4B,KAAK,CAAC;AAC/C,eAAO,MAAM,mCAAmC,MAAM,CAAC;AACvD,eAAO,MAAM,sBAAsB,OAAO,CAAC;AAC3C,eAAO,MAAM,2BAA2B,MAAM,CAAC;AAK/C,eAAO,MAAM,4BAA4B,QAA6B,CAAC;AAQvE,eAAO,MAAM,2BAA2B,QAAiB,CAAC;AAC1D,eAAO,MAAM,0BAA0B,QAAe,CAAC;AAIvD,eAAO,MAAM,6BAA6B,IAAI,CAAC;AAG/C,eAAO,MAAM,8BAA8B,MAAM,CAAC"}
|
|
1
|
+
{"version":3,"file":"media.d.ts","sourceRoot":"","sources":["../../src/constants/media.ts"],"names":[],"mappings":"AASA,eAAO,MAAM,6BAA6B,IAAI,CAAC;AAI/C,eAAO,MAAM,yBAAyB,QAAiB,CAAC;AAIxD,eAAO,MAAM,0BAA0B,QAAiB,CAAC;AAIzD,eAAO,MAAM,wBAAwB,QAAe,CAAC;AAIrD,eAAO,MAAM,6BAA6B,MAAM,CAAC;AACjD,eAAO,MAAM,qCAAqC,IAAI,CAAC;AACvD,eAAO,MAAM,4BAA4B,KAAK,CAAC;AAC/C,eAAO,MAAM,mCAAmC,MAAM,CAAC;AACvD,eAAO,MAAM,sBAAsB,OAAO,CAAC;AAC3C,eAAO,MAAM,2BAA2B,MAAM,CAAC;AAK/C,eAAO,MAAM,4BAA4B,QAA6B,CAAC;AAQvE,eAAO,MAAM,2BAA2B,QAAiB,CAAC;AAC1D,eAAO,MAAM,0BAA0B,QAAe,CAAC;AAIvD,eAAO,MAAM,6BAA6B,IAAI,CAAC;AAG/C,eAAO,MAAM,8BAA8B,MAAM,CAAC;AAKlD,eAAO,MAAM,qBAAqB,QAAe,CAAC;AAGlD,eAAO,MAAM,gCAAgC,MAAM,CAAC"}
|
package/dist/constants/media.js
CHANGED
|
@@ -41,4 +41,10 @@ export const MEDIA_SWEEP_BACKOFF_MAX_MS = 24 * HOUR_MS;
|
|
|
41
41
|
export const MAX_V1_PICTURE_CARRY_ATTEMPTS = 3;
|
|
42
42
|
// The longest staging path a callable accepts: `uploads/{origin}/{uid}/{uuid}` is far shorter.
|
|
43
43
|
export const MAX_STAGING_UPLOAD_PATH_LENGTH = 300;
|
|
44
|
+
// How far back an admin's upload tray follows their uploads: only rows accepted within this window are
|
|
45
|
+
// listened to. Every unfinished upload is inside it, since the sweep fails one still unfinished after
|
|
46
|
+
// `STALE_PENDING_MEDIA_AGE_MS`.
|
|
47
|
+
export const UPLOAD_TRAY_WINDOW_MS = 24 * HOUR_MS;
|
|
48
|
+
// The most uploads one call marks seen in the tray: the finished rows the tray shows at once.
|
|
49
|
+
export const MAX_UPLOADS_MARKED_SEEN_PER_CALL = 200;
|
|
44
50
|
//# sourceMappingURL=media.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"media.js","sourceRoot":"","sources":["../../src/constants/media.ts"],"names":[],"mappings":"AAAA,oGAAoG;AACpG,mGAAmG;AACnG,6CAA6C;AAE7C,MAAM,SAAS,GAAG,EAAE,GAAG,IAAI,CAAC;AAC5B,MAAM,OAAO,GAAG,EAAE,GAAG,SAAS,CAAC;AAE/B,iGAAiG;AACjG,yCAAyC;AACzC,MAAM,CAAC,MAAM,6BAA6B,GAAG,CAAC,CAAC;AAE/C,+FAA+F;AAC/F,wFAAwF;AACxF,MAAM,CAAC,MAAM,yBAAyB,GAAG,EAAE,GAAG,SAAS,CAAC;AAExD,oGAAoG;AACpG,oEAAoE;AACpE,MAAM,CAAC,MAAM,0BAA0B,GAAG,EAAE,GAAG,SAAS,CAAC;AAEzD,6FAA6F;AAC7F,4FAA4F;AAC5F,MAAM,CAAC,MAAM,wBAAwB,GAAG,EAAE,GAAG,OAAO,CAAC;AAErD,kGAAkG;AAClG,2BAA2B;AAC3B,MAAM,CAAC,MAAM,6BAA6B,GAAG,GAAG,CAAC;AACjD,MAAM,CAAC,MAAM,qCAAqC,GAAG,CAAC,CAAC;AACvD,MAAM,CAAC,MAAM,4BAA4B,GAAG,EAAE,CAAC;AAC/C,MAAM,CAAC,MAAM,mCAAmC,GAAG,GAAG,CAAC;AACvD,MAAM,CAAC,MAAM,sBAAsB,GAAG,IAAI,CAAC;AAC3C,MAAM,CAAC,MAAM,2BAA2B,GAAG,GAAG,CAAC;AAC/C,4FAA4F;AAC5F,sGAAsG;AACtG,mGAAmG;AACnG,qGAAqG;AACrG,MAAM,CAAC,MAAM,4BAA4B,GAAG,CAAC,GAAG,sBAAsB,CAAC;AAEvE,qGAAqG;AACrG,8EAA8E;AAC9E,oGAAoG;AACpG,mGAAmG;AACnG,oGAAoG;AACpG,uBAAuB;AACvB,MAAM,CAAC,MAAM,2BAA2B,GAAG,EAAE,GAAG,SAAS,CAAC;AAC1D,MAAM,CAAC,MAAM,0BAA0B,GAAG,EAAE,GAAG,OAAO,CAAC;AAEvD,iHAAiH;AACjH,YAAY;AACZ,MAAM,CAAC,MAAM,6BAA6B,GAAG,CAAC,CAAC;AAE/C,+FAA+F;AAC/F,MAAM,CAAC,MAAM,8BAA8B,GAAG,GAAG,CAAC","sourcesContent":["// Upload pipeline policy: the processing claim, the maintenance sweep's windows and bounds, and the\n// retry ceiling of the migration console's picture carry. The generic claim and lease machinery is\n// media-schemas'; the numbers are Q-Sports'.\n\nconst MINUTE_MS = 60 * 1000;\nconst HOUR_MS = 60 * MINUTE_MS;\n\n// Processing attempts a picture upload gets, the first included. A second attempt exists only to\n// recover a crashed or killed first one.\nexport const MEDIA_PROCESSING_MAX_ATTEMPTS = 2;\n\n// How long a processing claim owns its row before a redelivery may reclaim it. Longer than the\n// processing trigger's timeout, so a live attempt is never reclaimed from under itself.\nexport const MEDIA_PROCESSING_LEASE_MS = 10 * MINUTE_MS;\n\n// An upload still `pending` or `processing` this long after it was accepted, past its lease, has no\n// live attempt left driving it, and the maintenance sweep fails it.\nexport const STALE_PENDING_MEDIA_AGE_MS = 30 * MINUTE_MS;\n\n// A staged object this old with no `pending` or `processing` upload row is abandoned — never\n// accepted, consumed by a signing, or left by a finished upload — and the sweep deletes it.\nexport const ABANDONED_STAGING_AGE_MS = 24 * HOUR_MS;\n\n// The maintenance sweep's per-run bounds (BACKEND-112). Each pass stops at its bound and the next\n// scheduled run continues.\nexport const STALE_PENDING_MEDIA_PAGE_SIZE = 100;\nexport const MAX_STALE_PENDING_MEDIA_PAGES_PER_RUN = 5;\nexport const PICTURE_RETIREMENT_PAGE_SIZE = 50;\nexport const GALLERY_RETIREMENT_PICTURES_PER_RUN = 100;\nexport const STAGING_LIST_PAGE_SIZE = 1000;\nexport const MAX_STAGING_DELETES_PER_RUN = 500;\n// The most staged objects one abandoned-staging pass examines before it stops and saves its\n// position. Kept objects (young, with a live row, unreadable) cost nothing against the delete cap, so\n// this is what bounds a pass over a long kept stretch; two listing pages keep the pass well inside\n// the sweep's timeout beside its other passes, and the next run resumes after the last one examined.\nexport const MAX_STAGING_EXAMINED_PER_RUN = 2 * STAGING_LIST_PAGE_SIZE;\n\n// Deferral backoff for the sweep's picture-retirement and stale-upload passes. A row a pass keeps or\n// fails on leaves its scan window as a sweep-state `deferred` entry, next due\n// `min(BASE × 2^(n−1), MAX)` from now with `n` its attempt count: 15 and 30 minutes, 1, 2, 4, 8 and\n// 16 hours, then a day from there on. The base is the sweep's 15-minute cadence, since any shorter\n// delay is simply the next run; the cap bounds how long a released reference or a recovered failure\n// waits to be noticed.\nexport const MEDIA_SWEEP_BACKOFF_BASE_MS = 15 * MINUTE_MS;\nexport const MEDIA_SWEEP_BACKOFF_MAX_MS = 24 * HOUR_MS;\n\n// How many times the migration console's picture carry enqueues one source before reporting it as refused by the\n// pipeline.\nexport const MAX_V1_PICTURE_CARRY_ATTEMPTS = 3;\n\n// The longest staging path a callable accepts: `uploads/{origin}/{uid}/{uuid}` is far shorter.\nexport const MAX_STAGING_UPLOAD_PATH_LENGTH = 300;\n"]}
|
|
1
|
+
{"version":3,"file":"media.js","sourceRoot":"","sources":["../../src/constants/media.ts"],"names":[],"mappings":"AAAA,oGAAoG;AACpG,mGAAmG;AACnG,6CAA6C;AAE7C,MAAM,SAAS,GAAG,EAAE,GAAG,IAAI,CAAC;AAC5B,MAAM,OAAO,GAAG,EAAE,GAAG,SAAS,CAAC;AAE/B,iGAAiG;AACjG,yCAAyC;AACzC,MAAM,CAAC,MAAM,6BAA6B,GAAG,CAAC,CAAC;AAE/C,+FAA+F;AAC/F,wFAAwF;AACxF,MAAM,CAAC,MAAM,yBAAyB,GAAG,EAAE,GAAG,SAAS,CAAC;AAExD,oGAAoG;AACpG,oEAAoE;AACpE,MAAM,CAAC,MAAM,0BAA0B,GAAG,EAAE,GAAG,SAAS,CAAC;AAEzD,6FAA6F;AAC7F,4FAA4F;AAC5F,MAAM,CAAC,MAAM,wBAAwB,GAAG,EAAE,GAAG,OAAO,CAAC;AAErD,kGAAkG;AAClG,2BAA2B;AAC3B,MAAM,CAAC,MAAM,6BAA6B,GAAG,GAAG,CAAC;AACjD,MAAM,CAAC,MAAM,qCAAqC,GAAG,CAAC,CAAC;AACvD,MAAM,CAAC,MAAM,4BAA4B,GAAG,EAAE,CAAC;AAC/C,MAAM,CAAC,MAAM,mCAAmC,GAAG,GAAG,CAAC;AACvD,MAAM,CAAC,MAAM,sBAAsB,GAAG,IAAI,CAAC;AAC3C,MAAM,CAAC,MAAM,2BAA2B,GAAG,GAAG,CAAC;AAC/C,4FAA4F;AAC5F,sGAAsG;AACtG,mGAAmG;AACnG,qGAAqG;AACrG,MAAM,CAAC,MAAM,4BAA4B,GAAG,CAAC,GAAG,sBAAsB,CAAC;AAEvE,qGAAqG;AACrG,8EAA8E;AAC9E,oGAAoG;AACpG,mGAAmG;AACnG,oGAAoG;AACpG,uBAAuB;AACvB,MAAM,CAAC,MAAM,2BAA2B,GAAG,EAAE,GAAG,SAAS,CAAC;AAC1D,MAAM,CAAC,MAAM,0BAA0B,GAAG,EAAE,GAAG,OAAO,CAAC;AAEvD,iHAAiH;AACjH,YAAY;AACZ,MAAM,CAAC,MAAM,6BAA6B,GAAG,CAAC,CAAC;AAE/C,+FAA+F;AAC/F,MAAM,CAAC,MAAM,8BAA8B,GAAG,GAAG,CAAC;AAElD,uGAAuG;AACvG,sGAAsG;AACtG,gCAAgC;AAChC,MAAM,CAAC,MAAM,qBAAqB,GAAG,EAAE,GAAG,OAAO,CAAC;AAElD,8FAA8F;AAC9F,MAAM,CAAC,MAAM,gCAAgC,GAAG,GAAG,CAAC","sourcesContent":["// Upload pipeline policy: the processing claim, the maintenance sweep's windows and bounds, and the\n// retry ceiling of the migration console's picture carry. The generic claim and lease machinery is\n// media-schemas'; the numbers are Q-Sports'.\n\nconst MINUTE_MS = 60 * 1000;\nconst HOUR_MS = 60 * MINUTE_MS;\n\n// Processing attempts a picture upload gets, the first included. A second attempt exists only to\n// recover a crashed or killed first one.\nexport const MEDIA_PROCESSING_MAX_ATTEMPTS = 2;\n\n// How long a processing claim owns its row before a redelivery may reclaim it. Longer than the\n// processing trigger's timeout, so a live attempt is never reclaimed from under itself.\nexport const MEDIA_PROCESSING_LEASE_MS = 10 * MINUTE_MS;\n\n// An upload still `pending` or `processing` this long after it was accepted, past its lease, has no\n// live attempt left driving it, and the maintenance sweep fails it.\nexport const STALE_PENDING_MEDIA_AGE_MS = 30 * MINUTE_MS;\n\n// A staged object this old with no `pending` or `processing` upload row is abandoned — never\n// accepted, consumed by a signing, or left by a finished upload — and the sweep deletes it.\nexport const ABANDONED_STAGING_AGE_MS = 24 * HOUR_MS;\n\n// The maintenance sweep's per-run bounds (BACKEND-112). Each pass stops at its bound and the next\n// scheduled run continues.\nexport const STALE_PENDING_MEDIA_PAGE_SIZE = 100;\nexport const MAX_STALE_PENDING_MEDIA_PAGES_PER_RUN = 5;\nexport const PICTURE_RETIREMENT_PAGE_SIZE = 50;\nexport const GALLERY_RETIREMENT_PICTURES_PER_RUN = 100;\nexport const STAGING_LIST_PAGE_SIZE = 1000;\nexport const MAX_STAGING_DELETES_PER_RUN = 500;\n// The most staged objects one abandoned-staging pass examines before it stops and saves its\n// position. Kept objects (young, with a live row, unreadable) cost nothing against the delete cap, so\n// this is what bounds a pass over a long kept stretch; two listing pages keep the pass well inside\n// the sweep's timeout beside its other passes, and the next run resumes after the last one examined.\nexport const MAX_STAGING_EXAMINED_PER_RUN = 2 * STAGING_LIST_PAGE_SIZE;\n\n// Deferral backoff for the sweep's picture-retirement and stale-upload passes. A row a pass keeps or\n// fails on leaves its scan window as a sweep-state `deferred` entry, next due\n// `min(BASE × 2^(n−1), MAX)` from now with `n` its attempt count: 15 and 30 minutes, 1, 2, 4, 8 and\n// 16 hours, then a day from there on. The base is the sweep's 15-minute cadence, since any shorter\n// delay is simply the next run; the cap bounds how long a released reference or a recovered failure\n// waits to be noticed.\nexport const MEDIA_SWEEP_BACKOFF_BASE_MS = 15 * MINUTE_MS;\nexport const MEDIA_SWEEP_BACKOFF_MAX_MS = 24 * HOUR_MS;\n\n// How many times the migration console's picture carry enqueues one source before reporting it as refused by the\n// pipeline.\nexport const MAX_V1_PICTURE_CARRY_ATTEMPTS = 3;\n\n// The longest staging path a callable accepts: `uploads/{origin}/{uid}/{uuid}` is far shorter.\nexport const MAX_STAGING_UPLOAD_PATH_LENGTH = 300;\n\n// How far back an admin's upload tray follows their uploads: only rows accepted within this window are\n// listened to. Every unfinished upload is inside it, since the sweep fails one still unfinished after\n// `STALE_PENDING_MEDIA_AGE_MS`.\nexport const UPLOAD_TRAY_WINDOW_MS = 24 * HOUR_MS;\n\n// The most uploads one call marks seen in the tray: the finished rows the tray shows at once.\nexport const MAX_UPLOADS_MARKED_SEEN_PER_CALL = 200;\n"]}
|
|
@@ -38,6 +38,13 @@ export declare const AwardGroupGrantSchema: z.ZodObject<{
|
|
|
38
38
|
lastError: z.ZodOptional<z.ZodString>;
|
|
39
39
|
}, z.core.$strict>;
|
|
40
40
|
export type AwardGroupGrant = z.infer<typeof AwardGroupGrantSchema>;
|
|
41
|
+
/**
|
|
42
|
+
* Whether a request opens a new decision on an award for a group, given the group's latest decision
|
|
43
|
+
* (`null` when it has none): a grant opens unless the latest is a grant, and a take-back opens only
|
|
44
|
+
* when it is. A request the latest decision already settles opens nothing. The server applies it in
|
|
45
|
+
* the transaction that opens the decision; the admin surface offers only the request it opens.
|
|
46
|
+
*/
|
|
47
|
+
export declare function awardGroupGrantOpens(latest: Pick<AwardGroupGrant, 'action'> | null, action: AwardGroupGrant['action']): boolean;
|
|
41
48
|
export declare const AwardGroupGrantPersonSchema: z.ZodObject<{
|
|
42
49
|
userId: z.ZodString;
|
|
43
50
|
heldBefore: z.ZodBoolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"award-group-grant.d.ts","sourceRoot":"","sources":["../../src/doc-schemas/award-group-grant.ts"],"names":[],"mappings":"AAWA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAWxB,eAAO,MAAM,oBAAoB;;;EAAgC,CAAC;AAClE,eAAO,MAAM,2BAA2B;;;EAAwC,CAAC;AACjF,eAAO,MAAM,2BAA2B;;;EAAwC,CAAC;AAGjF,eAAO,MAAM,6BAA6B,aAAiB,CAAC;AAE5D,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;kBA6B9B,CAAC;AACL,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"award-group-grant.d.ts","sourceRoot":"","sources":["../../src/doc-schemas/award-group-grant.ts"],"names":[],"mappings":"AAWA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAWxB,eAAO,MAAM,oBAAoB;;;EAAgC,CAAC;AAClE,eAAO,MAAM,2BAA2B;;;EAAwC,CAAC;AACjF,eAAO,MAAM,2BAA2B;;;EAAwC,CAAC;AAGjF,eAAO,MAAM,6BAA6B,aAAiB,CAAC;AAE5D,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;kBA6B9B,CAAC;AACL,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAEpE;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,IAAI,CAAC,eAAe,EAAE,QAAQ,CAAC,GAAG,IAAI,EAC9C,MAAM,EAAE,eAAe,CAAC,QAAQ,CAAC,GAChC,OAAO,CAET;AAMD,eAAO,MAAM,2BAA2B;;;;;;;;;;kBAOtC,CAAC;AACH,MAAM,MAAM,qBAAqB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,2BAA2B,CAAC,CAAC"}
|
|
@@ -48,6 +48,15 @@ export const AwardGroupGrantSchema = z
|
|
|
48
48
|
ctx.addIssue({ code: 'custom', path: ['grantId'], message: 'grantId must be the target key and the decision.' });
|
|
49
49
|
}
|
|
50
50
|
});
|
|
51
|
+
/**
|
|
52
|
+
* Whether a request opens a new decision on an award for a group, given the group's latest decision
|
|
53
|
+
* (`null` when it has none): a grant opens unless the latest is a grant, and a take-back opens only
|
|
54
|
+
* when it is. A request the latest decision already settles opens nothing. The server applies it in
|
|
55
|
+
* the transaction that opens the decision; the admin surface offers only the request it opens.
|
|
56
|
+
*/
|
|
57
|
+
export function awardGroupGrantOpens(latest, action) {
|
|
58
|
+
return action === 'grant' ? latest?.action !== 'grant' : latest?.action === 'grant';
|
|
59
|
+
}
|
|
51
60
|
// `awardGroupGrants/{grantId}/awardGroupGrantPeople/{userId}` — one person a grant decision reached,
|
|
52
61
|
// recorded before their profile changed. `heldBefore` says they already held the award, so the grant
|
|
53
62
|
// gave them nothing. `revoked` turns true once a revoke has dealt with them; `revokeSkipped` says why
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"award-group-grant.js","sourceRoot":"","sources":["../../src/doc-schemas/award-group-grant.ts"],"names":[],"mappings":"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","sourcesContent":["// `awardGroupGrants/{grantId}` — one decision on one award for one group (a team, or a whole league):\n// grant the award to the group's active members, or take back what the group's grants gave. The\n// people are reached a page at a time, after the decision opens in its own small transaction. Written\n// only by Cloud Functions; an admin reads a decision through the status callable.\n//\n// A grant records each person in `awardGroupGrantPeople` before it changes their profile, so a re-run\n// after any interruption finds every recorded person and finishes them, and its revoke reverses exactly\n// the people it gave the award to. Someone who already held the award is recorded as holding it before,\n// and a revoke leaves them holding it. `status` stays `pending` until every page is done; the retry\n// ledger lets a decision that keeps failing back off instead of holding the resume's window.\n\nimport { z } from 'zod';\nimport { buildAwardGroupGrantId, buildAwardGroupGrantTargetKey } from '../ids/award-grant-ids.js';\nimport {\n AWARD_GROUP_GRANT_ACTION_KEYS,\n AWARD_GROUP_GRANT_STATUS_KEYS,\n AWARD_GROUP_REVOKE_SKIP_KEYS,\n AWARD_GROUP_TYPE_KEYS,\n} from '../types/unions.js';\nimport { countSchema, documentIdSegmentSchema, epochMsSchema, revisionSchema, userIdSchema } from './atoms.js';\nimport { awardIdSchema } from './catalogs.js';\n\nexport const awardGroupTypeSchema = z.enum(AWARD_GROUP_TYPE_KEYS);\nexport const awardGroupGrantActionSchema = z.enum(AWARD_GROUP_GRANT_ACTION_KEYS);\nexport const awardGroupGrantStatusSchema = z.enum(AWARD_GROUP_GRANT_STATUS_KEYS);\n\n// A decision's number among every decision on its award and group: the first is 1.\nexport const awardGroupGrantDecisionSchema = revisionSchema;\n\nexport const AwardGroupGrantSchema = z\n .strictObject({\n grantId: z.string().min(1),\n action: awardGroupGrantActionSchema,\n awardId: awardIdSchema,\n groupType: awardGroupTypeSchema,\n // The team id or the league id, as `groupType` says.\n groupId: documentIdSegmentSchema,\n targetKey: z.string().min(1),\n decision: awardGroupGrantDecisionSchema,\n // The admin who decided. Each person's audit event is recorded as their action.\n actorUid: userIdSchema,\n status: awardGroupGrantStatusSchema,\n createdAt: epochMsSchema,\n completedAt: epochMsSchema.optional(),\n attemptCount: countSchema,\n nextAttemptAt: epochMsSchema,\n lastError: z.string().optional(),\n })\n .superRefine((grant, ctx) => {\n // The key and the id are derived fields: a decision whose stored key or id disagrees with its\n // award, group, and number would sit outside that pair's decision sequence.\n const targetKey = buildAwardGroupGrantTargetKey(grant);\n if (grant.targetKey !== targetKey) {\n ctx.addIssue({ code: 'custom', path: ['targetKey'], message: 'targetKey must be the award and group target key.' });\n }\n if (grant.grantId !== buildAwardGroupGrantId(targetKey, grant.decision)) {\n ctx.addIssue({ code: 'custom', path: ['grantId'], message: 'grantId must be the target key and the decision.' });\n }\n });\nexport type AwardGroupGrant = z.infer<typeof AwardGroupGrantSchema>;\n\n// `awardGroupGrants/{grantId}/awardGroupGrantPeople/{userId}` — one person a grant decision reached,\n// recorded before their profile changed. `heldBefore` says they already held the award, so the grant\n// gave them nothing. `revoked` turns true once a revoke has dealt with them; `revokeSkipped` says why\n// that revoke left them holding the award.\nexport const AwardGroupGrantPersonSchema = z.strictObject({\n userId: userIdSchema,\n heldBefore: z.boolean(),\n recordedAt: epochMsSchema,\n revoked: z.boolean(),\n revokedAt: epochMsSchema.optional(),\n revokeSkipped: z.enum(AWARD_GROUP_REVOKE_SKIP_KEYS).optional(),\n});\nexport type AwardGroupGrantPerson = z.infer<typeof AwardGroupGrantPersonSchema>;\n"]}
|
|
1
|
+
{"version":3,"file":"award-group-grant.js","sourceRoot":"","sources":["../../src/doc-schemas/award-group-grant.ts"],"names":[],"mappings":"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","sourcesContent":["// `awardGroupGrants/{grantId}` — one decision on one award for one group (a team, or a whole league):\n// grant the award to the group's active members, or take back what the group's grants gave. The\n// people are reached a page at a time, after the decision opens in its own small transaction. Written\n// only by Cloud Functions; an admin reads a decision through the status callable.\n//\n// A grant records each person in `awardGroupGrantPeople` before it changes their profile, so a re-run\n// after any interruption finds every recorded person and finishes them, and its revoke reverses exactly\n// the people it gave the award to. Someone who already held the award is recorded as holding it before,\n// and a revoke leaves them holding it. `status` stays `pending` until every page is done; the retry\n// ledger lets a decision that keeps failing back off instead of holding the resume's window.\n\nimport { z } from 'zod';\nimport { buildAwardGroupGrantId, buildAwardGroupGrantTargetKey } from '../ids/award-grant-ids.js';\nimport {\n AWARD_GROUP_GRANT_ACTION_KEYS,\n AWARD_GROUP_GRANT_STATUS_KEYS,\n AWARD_GROUP_REVOKE_SKIP_KEYS,\n AWARD_GROUP_TYPE_KEYS,\n} from '../types/unions.js';\nimport { countSchema, documentIdSegmentSchema, epochMsSchema, revisionSchema, userIdSchema } from './atoms.js';\nimport { awardIdSchema } from './catalogs.js';\n\nexport const awardGroupTypeSchema = z.enum(AWARD_GROUP_TYPE_KEYS);\nexport const awardGroupGrantActionSchema = z.enum(AWARD_GROUP_GRANT_ACTION_KEYS);\nexport const awardGroupGrantStatusSchema = z.enum(AWARD_GROUP_GRANT_STATUS_KEYS);\n\n// A decision's number among every decision on its award and group: the first is 1.\nexport const awardGroupGrantDecisionSchema = revisionSchema;\n\nexport const AwardGroupGrantSchema = z\n .strictObject({\n grantId: z.string().min(1),\n action: awardGroupGrantActionSchema,\n awardId: awardIdSchema,\n groupType: awardGroupTypeSchema,\n // The team id or the league id, as `groupType` says.\n groupId: documentIdSegmentSchema,\n targetKey: z.string().min(1),\n decision: awardGroupGrantDecisionSchema,\n // The admin who decided. Each person's audit event is recorded as their action.\n actorUid: userIdSchema,\n status: awardGroupGrantStatusSchema,\n createdAt: epochMsSchema,\n completedAt: epochMsSchema.optional(),\n attemptCount: countSchema,\n nextAttemptAt: epochMsSchema,\n lastError: z.string().optional(),\n })\n .superRefine((grant, ctx) => {\n // The key and the id are derived fields: a decision whose stored key or id disagrees with its\n // award, group, and number would sit outside that pair's decision sequence.\n const targetKey = buildAwardGroupGrantTargetKey(grant);\n if (grant.targetKey !== targetKey) {\n ctx.addIssue({ code: 'custom', path: ['targetKey'], message: 'targetKey must be the award and group target key.' });\n }\n if (grant.grantId !== buildAwardGroupGrantId(targetKey, grant.decision)) {\n ctx.addIssue({ code: 'custom', path: ['grantId'], message: 'grantId must be the target key and the decision.' });\n }\n });\nexport type AwardGroupGrant = z.infer<typeof AwardGroupGrantSchema>;\n\n/**\n * Whether a request opens a new decision on an award for a group, given the group's latest decision\n * (`null` when it has none): a grant opens unless the latest is a grant, and a take-back opens only\n * when it is. A request the latest decision already settles opens nothing. The server applies it in\n * the transaction that opens the decision; the admin surface offers only the request it opens.\n */\nexport function awardGroupGrantOpens(\n latest: Pick<AwardGroupGrant, 'action'> | null,\n action: AwardGroupGrant['action'],\n): boolean {\n return action === 'grant' ? latest?.action !== 'grant' : latest?.action === 'grant';\n}\n\n// `awardGroupGrants/{grantId}/awardGroupGrantPeople/{userId}` — one person a grant decision reached,\n// recorded before their profile changed. `heldBefore` says they already held the award, so the grant\n// gave them nothing. `revoked` turns true once a revoke has dealt with them; `revokeSkipped` says why\n// that revoke left them holding the award.\nexport const AwardGroupGrantPersonSchema = z.strictObject({\n userId: userIdSchema,\n heldBefore: z.boolean(),\n recordedAt: epochMsSchema,\n revoked: z.boolean(),\n revokedAt: epochMsSchema.optional(),\n revokeSkipped: z.enum(AWARD_GROUP_REVOKE_SKIP_KEYS).optional(),\n});\nexport type AwardGroupGrantPerson = z.infer<typeof AwardGroupGrantPersonSchema>;\n"]}
|
|
@@ -89,5 +89,21 @@ export declare const AdminStartUploadResultSchema: z.ZodObject<{
|
|
|
89
89
|
awardId: z.ZodOptional<z.ZodString>;
|
|
90
90
|
}, z.core.$strict>;
|
|
91
91
|
export type AdminStartUploadResult = z.infer<typeof AdminStartUploadResultSchema>;
|
|
92
|
+
export declare const AdminMarkUploadsSeenInputSchema: z.ZodObject<{
|
|
93
|
+
pendingMediaIds: z.ZodArray<z.ZodString>;
|
|
94
|
+
}, z.core.$strict>;
|
|
95
|
+
export type AdminMarkUploadsSeenInput = z.infer<typeof AdminMarkUploadsSeenInputSchema>;
|
|
96
|
+
export declare const AdminMarkUploadsSeenResultSchema: z.ZodObject<{
|
|
97
|
+
marked: z.ZodNumber;
|
|
98
|
+
}, z.core.$strict>;
|
|
99
|
+
export type AdminMarkUploadsSeenResult = z.infer<typeof AdminMarkUploadsSeenResultSchema>;
|
|
100
|
+
export declare const AdminClearUploadActivityInputSchema: z.ZodObject<{
|
|
101
|
+
pendingMediaId: z.ZodString;
|
|
102
|
+
}, z.core.$strict>;
|
|
103
|
+
export type AdminClearUploadActivityInput = z.infer<typeof AdminClearUploadActivityInputSchema>;
|
|
104
|
+
export declare const AdminClearUploadActivityResultSchema: z.ZodObject<{
|
|
105
|
+
cleared: z.ZodLiteral<true>;
|
|
106
|
+
}, z.core.$strict>;
|
|
107
|
+
export type AdminClearUploadActivityResult = z.infer<typeof AdminClearUploadActivityResultSchema>;
|
|
92
108
|
export {};
|
|
93
109
|
//# sourceMappingURL=uploads.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"uploads.d.ts","sourceRoot":"","sources":["../../src/schemas/uploads.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAOxB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AACvE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAG9D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAEnE,eAAO,MAAM,uBAAuB,aAAwD,CAAC;AAG7F,eAAO,MAAM,6BAA6B;;kBAAkD,CAAC;AAC7F,eAAO,MAAM,2BAA2B;;kBAA8C,CAAC;AAEvF,eAAO,MAAM,8BAA8B,iCAAwB,CAAC;AACpE,eAAO,MAAM,+BAA+B;;kBAA8D,CAAC;AAG3G,eAAO,MAAM,kCAAkC;;kBAAgD,CAAC;AAChG,eAAO,MAAM,6BAA6B;;kBAAuD,CAAC;AAClG,eAAO,MAAM,0BAA0B;;;;oBAA+E,CAAC;AAEvH,UAAU,aAAa,CAAC,OAAO,SAAS,CAAC,CAAC,UAAU;IAClD,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,gEAAgE;IAChE,QAAQ,CAAC,SAAS,EAAE,gBAAgB,CAAC;IACrC,sGAAsG;IACtG,QAAQ,CAAC,OAAO,EAAE,CAAC,MAAM,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,SAAS,EAAE,MAAM,GAAG,SAAS,KAAK,MAAM,CAAC;CACvF;AAUD,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;CAc2C,CAAC;AAExE,MAAM,MAAM,iBAAiB,GAAG;KAC7B,CAAC,IAAI,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,OAAO,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;CACrE,CAAC,aAAa,CAAC,CAAC;AAEjB;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,UAAU,EAAE,aAAa,EAAE,UAAU,EAAE,OAAO,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,eAAe,CAGnH;AAED,2FAA2F;AAC3F,wBAAgB,cAAc,CAAC,UAAU,EAAE,aAAa,EAAE,UAAU,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAIjG;AAED,eAAO,MAAM,2BAA2B;;;;;;;;;;;;;;;;;;;;;;;kBAyBpC,CAAC;AACL,MAAM,MAAM,qBAAqB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,2BAA2B,CAAC,CAAC;AAEhF,eAAO,MAAM,4BAA4B;;;kBAO9B,CAAC;AACZ,MAAM,MAAM,sBAAsB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,4BAA4B,CAAC,CAAC"}
|
|
1
|
+
{"version":3,"file":"uploads.d.ts","sourceRoot":"","sources":["../../src/schemas/uploads.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAOxB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AACvE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAG9D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAEnE,eAAO,MAAM,uBAAuB,aAAwD,CAAC;AAG7F,eAAO,MAAM,6BAA6B;;kBAAkD,CAAC;AAC7F,eAAO,MAAM,2BAA2B;;kBAA8C,CAAC;AAEvF,eAAO,MAAM,8BAA8B,iCAAwB,CAAC;AACpE,eAAO,MAAM,+BAA+B;;kBAA8D,CAAC;AAG3G,eAAO,MAAM,kCAAkC;;kBAAgD,CAAC;AAChG,eAAO,MAAM,6BAA6B;;kBAAuD,CAAC;AAClG,eAAO,MAAM,0BAA0B;;;;oBAA+E,CAAC;AAEvH,UAAU,aAAa,CAAC,OAAO,SAAS,CAAC,CAAC,UAAU;IAClD,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,gEAAgE;IAChE,QAAQ,CAAC,SAAS,EAAE,gBAAgB,CAAC;IACrC,sGAAsG;IACtG,QAAQ,CAAC,OAAO,EAAE,CAAC,MAAM,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,SAAS,EAAE,MAAM,GAAG,SAAS,KAAK,MAAM,CAAC;CACvF;AAUD,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;CAc2C,CAAC;AAExE,MAAM,MAAM,iBAAiB,GAAG;KAC7B,CAAC,IAAI,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,OAAO,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;CACrE,CAAC,aAAa,CAAC,CAAC;AAEjB;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,UAAU,EAAE,aAAa,EAAE,UAAU,EAAE,OAAO,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,eAAe,CAGnH;AAED,2FAA2F;AAC3F,wBAAgB,cAAc,CAAC,UAAU,EAAE,aAAa,EAAE,UAAU,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAIjG;AAED,eAAO,MAAM,2BAA2B;;;;;;;;;;;;;;;;;;;;;;;kBAyBpC,CAAC;AACL,MAAM,MAAM,qBAAqB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,2BAA2B,CAAC,CAAC;AAEhF,eAAO,MAAM,4BAA4B;;;kBAO9B,CAAC;AACZ,MAAM,MAAM,sBAAsB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,4BAA4B,CAAC,CAAC;AAOlF,eAAO,MAAM,+BAA+B;;kBAIjC,CAAC;AACZ,MAAM,MAAM,yBAAyB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,+BAA+B,CAAC,CAAC;AACxF,eAAO,MAAM,gCAAgC;;kBAA6C,CAAC;AAC3F,MAAM,MAAM,0BAA0B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gCAAgC,CAAC,CAAC;AAG1F,eAAO,MAAM,mCAAmC;;kBAAyD,CAAC;AAC1G,MAAM,MAAM,6BAA6B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mCAAmC,CAAC,CAAC;AAChG,eAAO,MAAM,oCAAoC;;kBAAkD,CAAC;AACpG,MAAM,MAAM,8BAA8B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oCAAoC,CAAC,CAAC"}
|
package/dist/schemas/uploads.js
CHANGED
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
// id, and every path the picture is later written to is derived on the server.
|
|
6
6
|
import { z } from 'zod';
|
|
7
7
|
import { ClientMediaClaimSchema } from '@ttt-productions/media-schemas';
|
|
8
|
-
import { MAX_STAGING_UPLOAD_PATH_LENGTH } from '../constants/media.js';
|
|
9
|
-
import { leagueIdSchema, stagingIdSchema, teamIdSchema } from '../doc-schemas/atoms.js';
|
|
8
|
+
import { MAX_STAGING_UPLOAD_PATH_LENGTH, MAX_UPLOADS_MARKED_SEEN_PER_CALL } from '../constants/media.js';
|
|
9
|
+
import { countSchema, leagueIdSchema, stagingIdSchema, teamIdSchema } from '../doc-schemas/atoms.js';
|
|
10
10
|
import { awardIdSchema, awardNameSchema } from '../doc-schemas/catalogs.js';
|
|
11
11
|
import { gameLocationIdSchema } from '../doc-schemas/game-location.js';
|
|
12
12
|
import { pictureOriginSchema } from '../doc-schemas/pending-media.js';
|
|
@@ -90,4 +90,17 @@ export const AdminStartUploadResultSchema = z
|
|
|
90
90
|
awardId: awardIdSchema.optional(),
|
|
91
91
|
})
|
|
92
92
|
.strict();
|
|
93
|
+
// The admin's upload tray. Each call names only which uploads; the callable decides from the stored
|
|
94
|
+
// rows that each is the caller's own and finished. Tray state, never a sensitive action.
|
|
95
|
+
// Marks the caller's finished uploads seen when the tray's Uploads view opens. An id that is not the
|
|
96
|
+
// caller's, not finished, already seen, or gone is skipped, so one stale id never fails the batch.
|
|
97
|
+
export const AdminMarkUploadsSeenInputSchema = z
|
|
98
|
+
.object({
|
|
99
|
+
pendingMediaIds: z.array(stagingIdSchema).min(1).max(MAX_UPLOADS_MARKED_SEEN_PER_CALL),
|
|
100
|
+
})
|
|
101
|
+
.strict();
|
|
102
|
+
export const AdminMarkUploadsSeenResultSchema = z.object({ marked: countSchema }).strict();
|
|
103
|
+
// Clears one of the caller's finished uploads from the tray.
|
|
104
|
+
export const AdminClearUploadActivityInputSchema = z.object({ pendingMediaId: stagingIdSchema }).strict();
|
|
105
|
+
export const AdminClearUploadActivityResultSchema = z.object({ cleared: z.literal(true) }).strict();
|
|
93
106
|
//# sourceMappingURL=uploads.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"uploads.js","sourceRoot":"","sources":["../../src/schemas/uploads.ts"],"names":[],"mappings":"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","sourcesContent":["// Callable contracts for accepting a picture upload.\n//\n// A client stages its bytes at its own staging path and hands that path, the origin, and the origin's\n// target to `adminStartUpload`. Nothing about any path is negotiable: the target names the owner by\n// id, and every path the picture is later written to is derived on the server.\n\nimport { z } from 'zod';\nimport { ClientMediaClaimSchema } from '@ttt-productions/media-schemas';\nimport { MAX_STAGING_UPLOAD_PATH_LENGTH } from '../constants/media.js';\nimport { leagueIdSchema, stagingIdSchema, teamIdSchema } from '../doc-schemas/atoms.js';\nimport { awardIdSchema, awardNameSchema } from '../doc-schemas/catalogs.js';\nimport { gameLocationIdSchema } from '../doc-schemas/game-location.js';\nimport { pictureOriginSchema } from '../doc-schemas/pending-media.js';\nimport type { PictureOwnerRef } from '../doc-schemas/pending-media.js';\nimport type { PictureOrigin } from '../media/file-origins.js';\nimport { SPECIAL_DOCS } from '../paths/collections.js';\nimport { AWARD_DEFINITION_OWNER_KIND } from '../types/picture-owners.js';\nimport type { PictureOwnerKind } from '../types/picture-owners.js';\n\nexport const stagingUploadPathSchema = z.string().min(1).max(MAX_STAGING_UPLOAD_PATH_LENGTH);\n\n// Each picture origin's target: which owner the picture is for, by id.\nexport const LeaguePictureTargetInfoSchema = z.object({ leagueId: leagueIdSchema }).strict();\nexport const TeamPictureTargetInfoSchema = z.object({ teamId: teamIdSchema }).strict();\n// There is one landing page, so its target names nothing.\nexport const LandingPictureTargetInfoSchema = z.object({}).strict();\nexport const LocationPictureTargetInfoSchema = z.object({ gameLocationId: gameLocationIdSchema }).strict();\n// A badge either replaces an existing award's (`awardId`) or creates the award it is the first badge\n// of (`newAwardName`), whose id is the upload's staging id.\nexport const ExistingAwardBadgeTargetInfoSchema = z.object({ awardId: awardIdSchema }).strict();\nexport const NewAwardBadgeTargetInfoSchema = z.object({ newAwardName: awardNameSchema }).strict();\nexport const AwardBadgeTargetInfoSchema = z.union([ExistingAwardBadgeTargetInfoSchema, NewAwardBadgeTargetInfoSchema]);\n\ninterface PictureTarget<TSchema extends z.ZodTypeAny> {\n readonly schema: TSchema;\n /** The kind of document a picture of this origin belongs to. */\n readonly ownerKind: PictureOwnerKind;\n /** The owner's id. A target naming an owner that does not exist yet takes the upload's staging id. */\n readonly ownerId: (target: z.infer<TSchema>, stagingId: string | undefined) => string;\n}\n\nfunction pictureTarget<TSchema extends z.ZodTypeAny>(\n schema: TSchema,\n ownerKind: PictureOwnerKind,\n ownerId: (target: z.infer<TSchema>, stagingId: string | undefined) => string,\n): PictureTarget<TSchema> {\n return { schema, ownerKind, ownerId };\n}\n\nexport const PICTURE_TARGETS = {\n 'league-picture': pictureTarget(LeaguePictureTargetInfoSchema, 'sportLeague', (target) => target.leagueId),\n 'team-picture': pictureTarget(TeamPictureTargetInfoSchema, 'leagueTeam', (target) => target.teamId),\n 'landing-picture': pictureTarget(LandingPictureTargetInfoSchema, 'landingPage', () => SPECIAL_DOCS.LANDING_PAGE),\n 'location-picture': pictureTarget(\n LocationPictureTargetInfoSchema,\n 'gameLocation',\n (target) => target.gameLocationId,\n ),\n 'award-badge': pictureTarget(AwardBadgeTargetInfoSchema, AWARD_DEFINITION_OWNER_KIND, (target, stagingId) => {\n if ('awardId' in target) return target.awardId;\n if (stagingId === undefined) throw new Error(\"A new award's id is its badge upload's staging id, which was not given.\");\n return stagingId;\n }),\n} as const satisfies Record<PictureOrigin, PictureTarget<z.ZodTypeAny>>;\n\nexport type PictureTargetInfo = {\n [O in PictureOrigin]: z.infer<(typeof PICTURE_TARGETS)[O]['schema']>;\n}[PictureOrigin];\n\n/**\n * Parse a picture upload's target with its origin's schema and normalize it to the owner the\n * picture belongs to — the form an upload row stores. A badge creating its award names the award by\n * the upload's `stagingId`. Throws the schema's error on a target that does not fit the origin.\n */\nexport function parseTargetInfo(fileOrigin: PictureOrigin, targetInfo: unknown, stagingId?: string): PictureOwnerRef {\n const target = PICTURE_TARGETS[fileOrigin] as PictureTarget<z.ZodTypeAny>;\n return { kind: target.ownerKind, id: target.ownerId(target.schema.parse(targetInfo), stagingId) };\n}\n\n/** The name of the award a badge upload creates, or `undefined` for every other upload. */\nexport function newAwardNameOf(fileOrigin: PictureOrigin, targetInfo: unknown): string | undefined {\n if (PICTURE_TARGETS[fileOrigin].ownerKind !== AWARD_DEFINITION_OWNER_KIND) return undefined;\n const target = AwardBadgeTargetInfoSchema.parse(targetInfo);\n return 'newAwardName' in target ? target.newAwardName : undefined;\n}\n\nexport const AdminStartUploadInputSchema = z\n .object({\n fileOrigin: pictureOriginSchema,\n // The full staging path the client uploaded to. Only its last segment, the staging id, is\n // taken from it; the server rebuilds the rest and refuses anything not exactly equal.\n storagePath: stagingUploadPathSchema,\n // Checked against the origin's own target schema below, so a target that does not fit its\n // origin is refused with the rest of a malformed payload.\n targetInfo: z.unknown(),\n // What the admin actually did — chose a file in the picker, an advisory claim. Untrusted\n // context kept on the row for the processing pipeline; the byte inspection alone decides what\n // the file is, and a request without it is inspected all the same.\n clientMediaClaim: ClientMediaClaimSchema.optional(),\n })\n .strict()\n .superRefine((input, context) => {\n const target = PICTURE_TARGETS[input.fileOrigin] as PictureTarget<z.ZodTypeAny>;\n const parsed = target.schema.safeParse(input.targetInfo);\n if (!parsed.success) {\n context.addIssue({\n code: 'custom',\n path: ['targetInfo'],\n message: `The target does not fit a ${input.fileOrigin} upload: ${parsed.error.issues[0]?.message ?? 'invalid'}`,\n });\n }\n });\nexport type AdminStartUploadInput = z.infer<typeof AdminStartUploadInputSchema>;\n\nexport const AdminStartUploadResultSchema = z\n .object({\n // The upload's row, which the uploading control follows to its end. It is also the picture's id.\n pendingMediaId: stagingIdSchema,\n // A badge's award: the existing one it replaces, or the one its publication will create.\n awardId: awardIdSchema.optional(),\n })\n .strict();\nexport type AdminStartUploadResult = z.infer<typeof AdminStartUploadResultSchema>;\n"]}
|
|
1
|
+
{"version":3,"file":"uploads.js","sourceRoot":"","sources":["../../src/schemas/uploads.ts"],"names":[],"mappings":"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","sourcesContent":["// Callable contracts for accepting a picture upload.\n//\n// A client stages its bytes at its own staging path and hands that path, the origin, and the origin's\n// target to `adminStartUpload`. Nothing about any path is negotiable: the target names the owner by\n// id, and every path the picture is later written to is derived on the server.\n\nimport { z } from 'zod';\nimport { ClientMediaClaimSchema } from '@ttt-productions/media-schemas';\nimport { MAX_STAGING_UPLOAD_PATH_LENGTH, MAX_UPLOADS_MARKED_SEEN_PER_CALL } from '../constants/media.js';\nimport { countSchema, leagueIdSchema, stagingIdSchema, teamIdSchema } from '../doc-schemas/atoms.js';\nimport { awardIdSchema, awardNameSchema } from '../doc-schemas/catalogs.js';\nimport { gameLocationIdSchema } from '../doc-schemas/game-location.js';\nimport { pictureOriginSchema } from '../doc-schemas/pending-media.js';\nimport type { PictureOwnerRef } from '../doc-schemas/pending-media.js';\nimport type { PictureOrigin } from '../media/file-origins.js';\nimport { SPECIAL_DOCS } from '../paths/collections.js';\nimport { AWARD_DEFINITION_OWNER_KIND } from '../types/picture-owners.js';\nimport type { PictureOwnerKind } from '../types/picture-owners.js';\n\nexport const stagingUploadPathSchema = z.string().min(1).max(MAX_STAGING_UPLOAD_PATH_LENGTH);\n\n// Each picture origin's target: which owner the picture is for, by id.\nexport const LeaguePictureTargetInfoSchema = z.object({ leagueId: leagueIdSchema }).strict();\nexport const TeamPictureTargetInfoSchema = z.object({ teamId: teamIdSchema }).strict();\n// There is one landing page, so its target names nothing.\nexport const LandingPictureTargetInfoSchema = z.object({}).strict();\nexport const LocationPictureTargetInfoSchema = z.object({ gameLocationId: gameLocationIdSchema }).strict();\n// A badge either replaces an existing award's (`awardId`) or creates the award it is the first badge\n// of (`newAwardName`), whose id is the upload's staging id.\nexport const ExistingAwardBadgeTargetInfoSchema = z.object({ awardId: awardIdSchema }).strict();\nexport const NewAwardBadgeTargetInfoSchema = z.object({ newAwardName: awardNameSchema }).strict();\nexport const AwardBadgeTargetInfoSchema = z.union([ExistingAwardBadgeTargetInfoSchema, NewAwardBadgeTargetInfoSchema]);\n\ninterface PictureTarget<TSchema extends z.ZodTypeAny> {\n readonly schema: TSchema;\n /** The kind of document a picture of this origin belongs to. */\n readonly ownerKind: PictureOwnerKind;\n /** The owner's id. A target naming an owner that does not exist yet takes the upload's staging id. */\n readonly ownerId: (target: z.infer<TSchema>, stagingId: string | undefined) => string;\n}\n\nfunction pictureTarget<TSchema extends z.ZodTypeAny>(\n schema: TSchema,\n ownerKind: PictureOwnerKind,\n ownerId: (target: z.infer<TSchema>, stagingId: string | undefined) => string,\n): PictureTarget<TSchema> {\n return { schema, ownerKind, ownerId };\n}\n\nexport const PICTURE_TARGETS = {\n 'league-picture': pictureTarget(LeaguePictureTargetInfoSchema, 'sportLeague', (target) => target.leagueId),\n 'team-picture': pictureTarget(TeamPictureTargetInfoSchema, 'leagueTeam', (target) => target.teamId),\n 'landing-picture': pictureTarget(LandingPictureTargetInfoSchema, 'landingPage', () => SPECIAL_DOCS.LANDING_PAGE),\n 'location-picture': pictureTarget(\n LocationPictureTargetInfoSchema,\n 'gameLocation',\n (target) => target.gameLocationId,\n ),\n 'award-badge': pictureTarget(AwardBadgeTargetInfoSchema, AWARD_DEFINITION_OWNER_KIND, (target, stagingId) => {\n if ('awardId' in target) return target.awardId;\n if (stagingId === undefined) throw new Error(\"A new award's id is its badge upload's staging id, which was not given.\");\n return stagingId;\n }),\n} as const satisfies Record<PictureOrigin, PictureTarget<z.ZodTypeAny>>;\n\nexport type PictureTargetInfo = {\n [O in PictureOrigin]: z.infer<(typeof PICTURE_TARGETS)[O]['schema']>;\n}[PictureOrigin];\n\n/**\n * Parse a picture upload's target with its origin's schema and normalize it to the owner the\n * picture belongs to — the form an upload row stores. A badge creating its award names the award by\n * the upload's `stagingId`. Throws the schema's error on a target that does not fit the origin.\n */\nexport function parseTargetInfo(fileOrigin: PictureOrigin, targetInfo: unknown, stagingId?: string): PictureOwnerRef {\n const target = PICTURE_TARGETS[fileOrigin] as PictureTarget<z.ZodTypeAny>;\n return { kind: target.ownerKind, id: target.ownerId(target.schema.parse(targetInfo), stagingId) };\n}\n\n/** The name of the award a badge upload creates, or `undefined` for every other upload. */\nexport function newAwardNameOf(fileOrigin: PictureOrigin, targetInfo: unknown): string | undefined {\n if (PICTURE_TARGETS[fileOrigin].ownerKind !== AWARD_DEFINITION_OWNER_KIND) return undefined;\n const target = AwardBadgeTargetInfoSchema.parse(targetInfo);\n return 'newAwardName' in target ? target.newAwardName : undefined;\n}\n\nexport const AdminStartUploadInputSchema = z\n .object({\n fileOrigin: pictureOriginSchema,\n // The full staging path the client uploaded to. Only its last segment, the staging id, is\n // taken from it; the server rebuilds the rest and refuses anything not exactly equal.\n storagePath: stagingUploadPathSchema,\n // Checked against the origin's own target schema below, so a target that does not fit its\n // origin is refused with the rest of a malformed payload.\n targetInfo: z.unknown(),\n // What the admin actually did — chose a file in the picker, an advisory claim. Untrusted\n // context kept on the row for the processing pipeline; the byte inspection alone decides what\n // the file is, and a request without it is inspected all the same.\n clientMediaClaim: ClientMediaClaimSchema.optional(),\n })\n .strict()\n .superRefine((input, context) => {\n const target = PICTURE_TARGETS[input.fileOrigin] as PictureTarget<z.ZodTypeAny>;\n const parsed = target.schema.safeParse(input.targetInfo);\n if (!parsed.success) {\n context.addIssue({\n code: 'custom',\n path: ['targetInfo'],\n message: `The target does not fit a ${input.fileOrigin} upload: ${parsed.error.issues[0]?.message ?? 'invalid'}`,\n });\n }\n });\nexport type AdminStartUploadInput = z.infer<typeof AdminStartUploadInputSchema>;\n\nexport const AdminStartUploadResultSchema = z\n .object({\n // The upload's row, which the uploading control follows to its end. It is also the picture's id.\n pendingMediaId: stagingIdSchema,\n // A badge's award: the existing one it replaces, or the one its publication will create.\n awardId: awardIdSchema.optional(),\n })\n .strict();\nexport type AdminStartUploadResult = z.infer<typeof AdminStartUploadResultSchema>;\n\n// The admin's upload tray. Each call names only which uploads; the callable decides from the stored\n// rows that each is the caller's own and finished. Tray state, never a sensitive action.\n\n// Marks the caller's finished uploads seen when the tray's Uploads view opens. An id that is not the\n// caller's, not finished, already seen, or gone is skipped, so one stale id never fails the batch.\nexport const AdminMarkUploadsSeenInputSchema = z\n .object({\n pendingMediaIds: z.array(stagingIdSchema).min(1).max(MAX_UPLOADS_MARKED_SEEN_PER_CALL),\n })\n .strict();\nexport type AdminMarkUploadsSeenInput = z.infer<typeof AdminMarkUploadsSeenInputSchema>;\nexport const AdminMarkUploadsSeenResultSchema = z.object({ marked: countSchema }).strict();\nexport type AdminMarkUploadsSeenResult = z.infer<typeof AdminMarkUploadsSeenResultSchema>;\n\n// Clears one of the caller's finished uploads from the tray.\nexport const AdminClearUploadActivityInputSchema = z.object({ pendingMediaId: stagingIdSchema }).strict();\nexport type AdminClearUploadActivityInput = z.infer<typeof AdminClearUploadActivityInputSchema>;\nexport const AdminClearUploadActivityResultSchema = z.object({ cleared: z.literal(true) }).strict();\nexport type AdminClearUploadActivityResult = z.infer<typeof AdminClearUploadActivityResultSchema>;\n"]}
|