xpt-shared-types 1.0.4 → 1.3.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.
Files changed (39) hide show
  1. package/README.md +121 -38
  2. package/dist/bracket.d.ts +56 -0
  3. package/dist/bracket.js +144 -0
  4. package/dist/contracts/index.d.ts +139 -0
  5. package/dist/contracts/index.js +8 -0
  6. package/dist/data/countriesList.d.ts +1 -1
  7. package/dist/data/countriesList.js +1 -1
  8. package/dist/generated/enums.d.ts +48 -0
  9. package/dist/generated/enums.js +5 -0
  10. package/dist/generated/index.d.ts +3 -0
  11. package/dist/generated/index.js +22 -0
  12. package/dist/generated/inputs.d.ts +420 -0
  13. package/dist/generated/inputs.js +5 -0
  14. package/dist/generated/models.d.ts +420 -0
  15. package/dist/generated/models.js +5 -0
  16. package/dist/index.d.ts +4 -3
  17. package/dist/index.js +9 -5
  18. package/dist/manual/index.d.ts +4 -0
  19. package/dist/manual/index.js +20 -0
  20. package/package.json +26 -23
  21. package/scripts/sync-from-strapi.js +281 -0
  22. package/src/bracket.ts +193 -0
  23. package/src/contracts/index.ts +158 -0
  24. package/src/data/countriesList.ts +1156 -1156
  25. package/src/generated/enums.ts +175 -0
  26. package/src/generated/index.ts +7 -0
  27. package/src/generated/inputs.ts +496 -0
  28. package/src/generated/models.ts +497 -0
  29. package/src/index.ts +14 -7
  30. package/src/manual/index.ts +4 -0
  31. package/dist/types/match.d.ts +0 -1
  32. package/dist/types/match.js +0 -2
  33. package/dist/types/tournament.d.ts +0 -1
  34. package/dist/types/tournament.js +0 -2
  35. package/src/types/match.ts +0 -8
  36. package/src/types/tournament.ts +0 -4
  37. /package/dist/{types → manual}/country.d.ts +0 -0
  38. /package/dist/{types → manual}/country.js +0 -0
  39. /package/src/{types → manual}/country.ts +0 -0
package/README.md CHANGED
@@ -1,38 +1,121 @@
1
- # xpt-shared-types
2
-
3
- Shared TypeScript types and data for XPT projects.
4
-
5
- ## Usage
6
-
7
- 1. Install in your project:
8
-
9
- ```sh
10
- yarn add xpt-shared-types
11
- # or
12
- npm install xpt-shared-types
13
- ```
14
-
15
- Or publish to npm/GitHub Packages and install from there.
16
-
17
- 2. Import types and data:
18
- ```ts
19
- import { Country, COUNTRIES_LIST } from "xpt-shared-types";
20
- ```
21
-
22
- ## Development
23
-
24
- - Edit types in `src/types/`
25
- - Edit shared data in `src/data/`
26
- - Run `yarn build` to compile TypeScript
27
-
28
- ## Publish
29
-
30
- 1. Run `npm login` to authenticate with npm (if not already logged in)
31
- 2. Run `yarn build` to compile TypeScript
32
- 3. Run `yarn version --patch` to bump the version (e.g. `1.0.4` → `1.0.5`)
33
- 4. Run `npm publish` to publish to npm
34
- 5. Run `git push` to push the version commit and tag to GitHub
35
-
36
- ## License
37
-
38
- MIT
1
+ # xpt-shared-types
2
+
3
+ The API contract shared by `xpt-strapi` and `xpt-client`.
4
+
5
+ Strapi's content-type schemas are the single source of truth. This package
6
+ turns them into plain TypeScript so both projects describe the same API, and a
7
+ schema change breaks compilation at every stale usage instead of drifting
8
+ silently.
9
+
10
+ ## Layout
11
+
12
+ ```
13
+ src/
14
+ ├── generated/ # DO NOT EDIT — produced by scripts/sync-from-strapi.js
15
+ ├── enums.ts # one union per `enumeration` attribute
16
+ │ ├── models.ts # one interface per content type (read shapes)
17
+ │ └── inputs.ts # one interface per content type (write shapes)
18
+ ├── contracts/ # hand-written primitives the generated code builds on
19
+ ├── manual/ # types with no Strapi content type behind them
20
+ └── data/ # shared runtime data (COUNTRIES_LIST)
21
+ ```
22
+
23
+ Everything is re-exported from the package root:
24
+
25
+ ```ts
26
+ import type { Tournament, TournamentStatus, Populated } from 'xpt-shared-types';
27
+ import { COUNTRIES_LIST } from 'xpt-shared-types';
28
+ ```
29
+
30
+ ## Regenerating after a schema change
31
+
32
+ ```sh
33
+ yarn sync # reads ../xpt-strapi/src/**/content-types/**/schema.json
34
+ yarn build # tsc only
35
+ ```
36
+
37
+ `sync` is deliberately **not** part of `build`, so publishing does not require a
38
+ sibling `xpt-strapi` checkout. The generated output is committed — treat
39
+ `yarn sync` as something you run and commit, like a lockfile.
40
+
41
+ Point it elsewhere with an argument or `XPT_STRAPI_PATH`:
42
+
43
+ ```sh
44
+ node scripts/sync-from-strapi.js ../some/other/xpt-strapi
45
+ ```
46
+
47
+ It reads `schema.json`, **not** `xpt-strapi/types/generated/contentTypes.d.ts`.
48
+ The latter is Strapi's own output for its server-side types; it is regenerated
49
+ by `strapi develop` and expressed in `Schema.Attribute.*` wrappers that the
50
+ frontend cannot consume.
51
+
52
+ ## The rules the generator follows
53
+
54
+ **Everything except `id` and `documentId` is optional.** Not just relations.
55
+ This codebase uses Strapi's `fields` selection pervasively, so even a
56
+ schema-`required` attribute like `user.email` is absent from most responses.
57
+ The base model is the *minimum guarantee*, not the full row.
58
+
59
+ **Single values are `?: T | null`.** Strapi sends `null` for an unset value
60
+ rather than omitting the key. Lists come back as `[]`, so they are not nullable.
61
+
62
+ **Relations and media are optional regardless of the schema**, because whether
63
+ they come back depends entirely on the query's `populate`.
64
+
65
+ **`private` attributes are omitted**, because the content API never returns
66
+ them (for example `user.password`).
67
+
68
+ **Read and write shapes differ**, so both are generated. On read a relation is
69
+ a nested object; on write it is a documentId or a `connect`/`set` form, and
70
+ media is a numeric file id. Use `models.ts` for responses and `inputs.ts` for
71
+ request payloads — typing a mutation with a read model is a common mistake that
72
+ produces confusing optionality errors.
73
+
74
+ **Enums are named `<Model><PascalField>`** — `tournament.currentStatus` becomes
75
+ `TournamentCurrentStatus`. `TournamentStatus` is exported as a readability
76
+ alias.
77
+
78
+ ## Narrowing with `Populated<T, K>`
79
+
80
+ Because relations are always optional, record what a specific query actually
81
+ asked for:
82
+
83
+ ```ts
84
+ const tournament = await getTournament(slug); // Populated<Tournament, 'game' | 'prizes'>
85
+
86
+ tournament.game.title; // ok — the annotation says it was populated
87
+ tournament.region?.name; // still optional — this query did not populate it
88
+ ```
89
+
90
+ If the annotation and the query disagree, that is a bug a reader can see. Do
91
+ not reach for a cast: a cast on a schema-backed field is always avoidable, and
92
+ silently disables exactly the checking this package exists to provide.
93
+
94
+ ## Local development
95
+
96
+ The two apps are on different Yarn majors, so they link differently:
97
+
98
+ | Repo | Yarn | Dependency |
99
+ | --- | --- | --- |
100
+ | `xpt-strapi` | 1.22.5 (classic) | `"xpt-shared-types": "link:../xpt-shared-types"` |
101
+ | `xpt-client` | 4.1.1 (Berry) | `"xpt-shared-types": "portal:../xpt-shared-types"` |
102
+
103
+ `portal:` is Berry-only and fails on Yarn 1. Both symlink to this directory, so
104
+ edits are picked up after `yarn build` with no publish step.
105
+
106
+ > **Before deploying, revert both to the published range (`^1.x`) and publish
107
+ > this package.** The link/portal wiring is for local development only.
108
+
109
+ ## Publishing
110
+
111
+ `prepublishOnly` runs `yarn build`, so `dist/` cannot go stale.
112
+
113
+ 1. `yarn sync` and commit, if schemas changed
114
+ 2. `npm login`
115
+ 3. `yarn version --patch`
116
+ 4. `npm publish`
117
+ 5. `git push --follow-tags`
118
+
119
+ ## License
120
+
121
+ MIT
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Bracket shape — how many rounds a single-elimination tournament has, what
3
+ * each is called, how matches are numbered, and where each winner goes.
4
+ *
5
+ * This is the single source of truth for both apps: xpt-strapi re-exports it
6
+ * from `src/utils/bracket.ts` (adding the Strapi-coupled stage sync), and
7
+ * xpt-client's Storybook fixtures consume it directly — a fixture built any
8
+ * other way could show a bracket the backend can never produce.
9
+ */
10
+ import type { MatchRound } from './generated';
11
+ /** The largest bracket the round names can describe. */
12
+ export declare const MAX_BRACKET_SIZE = 128;
13
+ export declare function nextPowerOf2(n: number): number;
14
+ export interface BracketRound {
15
+ name: MatchRound;
16
+ matchCount: number;
17
+ }
18
+ export declare function buildBracketRounds(bracketSize: number, hasThirdPlace: boolean): BracketRound[];
19
+ /** The rounds a tournament of this many entrants will be played over. */
20
+ export declare function bracketRoundsForParticipants(participants: number, hasThirdPlace: boolean): BracketRound[];
21
+ /** Uniform Fisher–Yates shuffle. A `sort(() => Math.random() - 0.5)` is
22
+ * biased — comparison sorts assume a consistent comparator, so some orderings
23
+ * come up measurably more often than others. */
24
+ export declare function shuffle<T>(items: readonly T[]): T[];
25
+ /**
26
+ * Standard bracket seed order: which seed (0-based) sits in each first-round
27
+ * slot. Built by the usual doubling rule — each seed is paired with its
28
+ * complement, so seed 0 meets seed 1 only in the final.
29
+ *
30
+ * This is also the bye-safety property: slots are paired (s, size-1-s), and
31
+ * byes are the seeds from `checkedIn` upward. Both sides of a pair being byes
32
+ * would need `checkedIn <= (size-1)/2`, but `nextPowerOf2` guarantees
33
+ * `checkedIn > size/2` — so a bye always faces a real entrant.
34
+ */
35
+ export declare function seedOrder(bracketSize: number): number[];
36
+ export interface PlannedMatch {
37
+ round: MatchRound;
38
+ matchNumber: number;
39
+ /** Where this match's winner goes; null for Finals and Third Round. */
40
+ nextMatchNumber: number | null;
41
+ winnerSlot: 'home' | 'away' | null;
42
+ /** First-round matches only: index into the seeded slot array (null = later round). */
43
+ homeSlot: number | null;
44
+ awaySlot: number | null;
45
+ }
46
+ export interface BracketPlan {
47
+ bracketSize: number;
48
+ rounds: BracketRound[];
49
+ matches: PlannedMatch[];
50
+ }
51
+ /**
52
+ * The full bracket as data: every match, its number, and where its winner
53
+ * goes. Numbering is sequential across rounds in bracket order, with Third
54
+ * Round (when present) sitting before Finals.
55
+ */
56
+ export declare function buildBracketPlan(bracketSize: number, hasThirdPlace: boolean): BracketPlan;
@@ -0,0 +1,144 @@
1
+ "use strict";
2
+ /**
3
+ * Bracket shape — how many rounds a single-elimination tournament has, what
4
+ * each is called, how matches are numbered, and where each winner goes.
5
+ *
6
+ * This is the single source of truth for both apps: xpt-strapi re-exports it
7
+ * from `src/utils/bracket.ts` (adding the Strapi-coupled stage sync), and
8
+ * xpt-client's Storybook fixtures consume it directly — a fixture built any
9
+ * other way could show a bracket the backend can never produce.
10
+ */
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.MAX_BRACKET_SIZE = void 0;
13
+ exports.nextPowerOf2 = nextPowerOf2;
14
+ exports.buildBracketRounds = buildBracketRounds;
15
+ exports.bracketRoundsForParticipants = bracketRoundsForParticipants;
16
+ exports.shuffle = shuffle;
17
+ exports.seedOrder = seedOrder;
18
+ exports.buildBracketPlan = buildBracketPlan;
19
+ /** The largest bracket the round names can describe. */
20
+ exports.MAX_BRACKET_SIZE = 128;
21
+ function nextPowerOf2(n) {
22
+ if (n <= 2)
23
+ return 2;
24
+ let p = 2;
25
+ while (p < n)
26
+ p *= 2;
27
+ return p;
28
+ }
29
+ /**
30
+ * The name of the round that *starts* with this many players left. Halving
31
+ * from the bracket size down to 2 walks the whole bracket, so there is no
32
+ * table of per-size name lists to fall out of sync — the one way a size can
33
+ * go wrong is a size that is not a power of two in range, and that throws.
34
+ */
35
+ const ROUND_NAME_BY_SIZE = {
36
+ 128: 'Round 128',
37
+ 64: 'Round 64',
38
+ 32: 'Round 32',
39
+ 16: 'Round 16',
40
+ 8: 'Quarter Final',
41
+ 4: 'Semi-Final',
42
+ 2: 'Finals',
43
+ };
44
+ function buildBracketRounds(bracketSize, hasThirdPlace) {
45
+ // An unrecognised size used to fall back to a single round called "Finals"
46
+ // holding `bracketSize / 2` matches. An unplayable bracket is worse than no
47
+ // bracket.
48
+ if (!ROUND_NAME_BY_SIZE[bracketSize]) {
49
+ throw new Error(`Unsupported bracket size ${bracketSize} — must be a power of two between 2 and ${exports.MAX_BRACKET_SIZE}`);
50
+ }
51
+ const rounds = [];
52
+ for (let size = bracketSize; size >= 2; size /= 2) {
53
+ rounds.push({ name: ROUND_NAME_BY_SIZE[size], matchCount: size / 2 });
54
+ }
55
+ // Inject Third Round slot before Finals when enabled (4+ players)
56
+ if (hasThirdPlace && bracketSize >= 4) {
57
+ const finalsIdx = rounds.findIndex((r) => r.name === 'Finals');
58
+ if (finalsIdx > 0) {
59
+ rounds.splice(finalsIdx, 0, { name: 'Third Round', matchCount: 1 });
60
+ }
61
+ }
62
+ return rounds;
63
+ }
64
+ /** The rounds a tournament of this many entrants will be played over. */
65
+ function bracketRoundsForParticipants(participants, hasThirdPlace) {
66
+ return buildBracketRounds(nextPowerOf2(participants), hasThirdPlace);
67
+ }
68
+ /** Uniform Fisher–Yates shuffle. A `sort(() => Math.random() - 0.5)` is
69
+ * biased — comparison sorts assume a consistent comparator, so some orderings
70
+ * come up measurably more often than others. */
71
+ function shuffle(items) {
72
+ const result = [...items];
73
+ for (let i = result.length - 1; i > 0; i--) {
74
+ const j = Math.floor(Math.random() * (i + 1));
75
+ [result[i], result[j]] = [result[j], result[i]];
76
+ }
77
+ return result;
78
+ }
79
+ /**
80
+ * Standard bracket seed order: which seed (0-based) sits in each first-round
81
+ * slot. Built by the usual doubling rule — each seed is paired with its
82
+ * complement, so seed 0 meets seed 1 only in the final.
83
+ *
84
+ * This is also the bye-safety property: slots are paired (s, size-1-s), and
85
+ * byes are the seeds from `checkedIn` upward. Both sides of a pair being byes
86
+ * would need `checkedIn <= (size-1)/2`, but `nextPowerOf2` guarantees
87
+ * `checkedIn > size/2` — so a bye always faces a real entrant.
88
+ */
89
+ function seedOrder(bracketSize) {
90
+ if (!ROUND_NAME_BY_SIZE[bracketSize]) {
91
+ throw new Error(`Unsupported bracket size ${bracketSize} — must be a power of two between 2 and ${exports.MAX_BRACKET_SIZE}`);
92
+ }
93
+ let order = [0];
94
+ while (order.length < bracketSize) {
95
+ const size = order.length * 2;
96
+ const next = [];
97
+ for (const seed of order) {
98
+ next.push(seed, size - 1 - seed);
99
+ }
100
+ order = next;
101
+ }
102
+ return order;
103
+ }
104
+ /**
105
+ * The full bracket as data: every match, its number, and where its winner
106
+ * goes. Numbering is sequential across rounds in bracket order, with Third
107
+ * Round (when present) sitting before Finals.
108
+ */
109
+ function buildBracketPlan(bracketSize, hasThirdPlace) {
110
+ const rounds = buildBracketRounds(bracketSize, hasThirdPlace);
111
+ let counter = 1;
112
+ const roundMatchNumbers = rounds.map((round) => Array.from({ length: round.matchCount }, () => counter++));
113
+ // Winner linkage skips Third Round — it receives losers, not winners.
114
+ const linkage = {};
115
+ const nonThirdRounds = rounds
116
+ .map((round, index) => ({ round, index }))
117
+ .filter(({ round }) => round.name !== 'Third Round');
118
+ for (let ri = 0; ri < nonThirdRounds.length - 1; ri++) {
119
+ const currentNums = roundMatchNumbers[nonThirdRounds[ri].index];
120
+ const nextNums = roundMatchNumbers[nonThirdRounds[ri + 1].index];
121
+ currentNums.forEach((num, mi) => {
122
+ linkage[num] = {
123
+ nextMatchNumber: nextNums[Math.floor(mi / 2)],
124
+ winnerSlot: mi % 2 === 0 ? 'home' : 'away',
125
+ };
126
+ });
127
+ }
128
+ const matches = [];
129
+ rounds.forEach((round, ri) => {
130
+ roundMatchNumbers[ri].forEach((num, mi) => {
131
+ var _a;
132
+ const link = (_a = linkage[num]) !== null && _a !== void 0 ? _a : { nextMatchNumber: null, winnerSlot: null };
133
+ matches.push({
134
+ round: round.name,
135
+ matchNumber: num,
136
+ nextMatchNumber: link.nextMatchNumber,
137
+ winnerSlot: link.winnerSlot,
138
+ homeSlot: ri === 0 ? mi * 2 : null,
139
+ awaySlot: ri === 0 ? mi * 2 + 1 : null,
140
+ });
141
+ });
142
+ });
143
+ return { bracketSize, rounds, matches };
144
+ }
@@ -0,0 +1,139 @@
1
+ /**
2
+ * Hand-written contract primitives.
3
+ *
4
+ * Everything here is maintained by hand — the generated models in
5
+ * `src/generated` import from this module, so keep the names stable.
6
+ */
7
+ /** Strapi 5 returns flat documents: no `attributes` envelope. */
8
+ export interface StrapiDocument {
9
+ id: number;
10
+ documentId: string;
11
+ createdAt?: string | null;
12
+ updatedAt?: string | null;
13
+ publishedAt?: string | null;
14
+ locale?: string | null;
15
+ }
16
+ /** A single size variant produced by the upload plugin. */
17
+ export interface StrapiMediaFormat {
18
+ name: string;
19
+ hash: string;
20
+ ext: string;
21
+ mime: string;
22
+ width: number;
23
+ height: number;
24
+ size: number;
25
+ url: string;
26
+ path?: string | null;
27
+ }
28
+ /**
29
+ * Size variants the upload plugin generates. The four named breakpoints are
30
+ * Strapi's defaults; the index signature covers custom ones.
31
+ */
32
+ export interface StrapiMediaFormats {
33
+ thumbnail?: StrapiMediaFormat;
34
+ small?: StrapiMediaFormat;
35
+ medium?: StrapiMediaFormat;
36
+ large?: StrapiMediaFormat;
37
+ [breakpoint: string]: StrapiMediaFormat | undefined;
38
+ }
39
+ /** `plugin::upload.file` */
40
+ export interface StrapiMedia {
41
+ id: number;
42
+ documentId?: string;
43
+ name: string;
44
+ alternativeText?: string | null;
45
+ caption?: string | null;
46
+ width?: number | null;
47
+ height?: number | null;
48
+ formats?: StrapiMediaFormats | null;
49
+ hash: string;
50
+ ext?: string | null;
51
+ mime: string;
52
+ size: number;
53
+ url: string;
54
+ previewUrl?: string | null;
55
+ provider?: string;
56
+ provider_metadata?: unknown;
57
+ folderPath?: string;
58
+ createdAt?: string;
59
+ updatedAt?: string;
60
+ publishedAt?: string;
61
+ locale?: string | null;
62
+ }
63
+ /** Rich-text `blocks` payload; shape is defined by the blocks renderer. */
64
+ export type BlocksContent = unknown[];
65
+ /**
66
+ * How a relation is sent on create/update. Strapi accepts a bare documentId,
67
+ * a numeric id, or the connect/set/disconnect long form.
68
+ */
69
+ export type RelationInput = string | number | {
70
+ id: number;
71
+ } | {
72
+ documentId: string;
73
+ } | {
74
+ connect?: Array<string | number>;
75
+ disconnect?: Array<string | number>;
76
+ } | {
77
+ set: Array<string | number>;
78
+ };
79
+ /** Media is written as the uploaded file's numeric id. */
80
+ export type MediaInput = number | number[] | null;
81
+ export interface Pagination {
82
+ page: number;
83
+ pageSize: number;
84
+ pageCount: number;
85
+ total: number;
86
+ }
87
+ export interface Meta {
88
+ pagination?: Pagination;
89
+ [key: string]: unknown;
90
+ }
91
+ /** Single-entity response. Strapi still sends `meta`, usually `{}`. */
92
+ export interface StrapiResponse<T> {
93
+ data: T;
94
+ meta?: Meta;
95
+ }
96
+ /** Collection response. */
97
+ export interface StrapiCollectionResponse<T> {
98
+ data: T[];
99
+ meta?: Meta;
100
+ }
101
+ export interface StrapiError {
102
+ status: number;
103
+ name: string;
104
+ message: string;
105
+ details?: unknown;
106
+ }
107
+ export interface StrapiErrorResponse {
108
+ data: null;
109
+ error: StrapiError;
110
+ }
111
+ /**
112
+ * Marks relations as present.
113
+ *
114
+ * Generated models leave every relation optional, because whether one comes
115
+ * back depends entirely on the query's `populate`. Use this at a call site to
116
+ * record what that particular query actually asked for:
117
+ *
118
+ * ```ts
119
+ * type WithGame = Populated<Tournament, 'game' | 'prizes'>;
120
+ * ```
121
+ *
122
+ * This is the type-level counterpart to remembering to populate — if the query
123
+ * and the annotation disagree, that is a bug the reader can see.
124
+ */
125
+ export type Populated<T, K extends keyof T> = T & {
126
+ [P in K]-?: NonNullable<T[P]>;
127
+ };
128
+ /** Recursively marks every relation on `T` as optional (the default shape). */
129
+ export type Unpopulated<T> = {
130
+ [P in keyof T]?: T[P];
131
+ };
132
+ /** `plugin::users-permissions.role` */
133
+ export interface UserRole {
134
+ id: number;
135
+ documentId?: string;
136
+ name: string;
137
+ description?: string | null;
138
+ type?: string | null;
139
+ }
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ /**
3
+ * Hand-written contract primitives.
4
+ *
5
+ * Everything here is maintained by hand — the generated models in
6
+ * `src/generated` import from this module, so keep the names stable.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -1,2 +1,2 @@
1
- import { Country } from "../types/country";
1
+ import { Country } from "../manual/country";
2
2
  export declare const COUNTRIES_LIST: Country[];
@@ -1090,7 +1090,7 @@ exports.COUNTRIES_LIST = [
1090
1090
  },
1091
1091
  {
1092
1092
  countryName: "United Kingdom",
1093
- alpha2: "GB-UKM",
1093
+ alpha2: "GB",
1094
1094
  alpha3: "GBR",
1095
1095
  numeric: "826",
1096
1096
  },
@@ -0,0 +1,48 @@
1
+ /** `Friendship.status` */
2
+ export type FriendshipStatus = "pending" | "accepted";
3
+ /** `GameRequest.customLobbies` */
4
+ export type GameRequestCustomLobbies = "Yes" | "No" | "Not sure";
5
+ /** `GameRequest.genre` */
6
+ export type GameRequestGenre = "FPS" | "MOBA" | "Battle Royale" | "Fighting (FGC)" | "Sports" | "Strategy/RTS" | "Sim Racing" | "Card Game" | "Other";
7
+ /** `GameRequest.teamPlay` */
8
+ export type GameRequestTeamPlay = "No (solo)" | "Yes, 2v2" | "Yes, 3v3" | "Yes, 4v4+" | "Don't know";
9
+ /** `Match.lobbyStatus` */
10
+ export type MatchLobbyStatus = "waiting" | "ready" | "disputed" | "completed";
11
+ /** `Match.round` */
12
+ export type MatchRound = "Round 128" | "Round 64" | "Round 32" | "Round 16" | "Quarter Final" | "Semi-Final" | "Third Round" | "Finals" | "League";
13
+ /** `Match.streamPlatform` */
14
+ export type MatchStreamPlatform = "twitch" | "youtube" | "kick" | "other";
15
+ /** `Match.winnerSlot` */
16
+ export type MatchWinnerSlot = "home" | "away";
17
+ /** `Prize.rank` */
18
+ export type PrizeRank = "one" | "two" | "three";
19
+ /** `Referral.status` */
20
+ export type ReferralStatus = "pending" | "completed";
21
+ /** `Team.current_status` */
22
+ export type TeamCurrentStatus = "active" | "disbanded";
23
+ /** `TeamInvite.status` */
24
+ export type TeamInviteStatus = "pending" | "accepted" | "declined";
25
+ /** `TeamInvite.team_role` */
26
+ export type TeamInviteTeamRole = "captain" | "co_captain" | "player" | "substitute" | "coach";
27
+ /** `TeamPlayer.team_role` */
28
+ export type TeamPlayerTeamRole = "captain" | "co_captain" | "player" | "substitute" | "coach";
29
+ /** `Tournament.currentStatus` */
30
+ export type TournamentCurrentStatus = "draft" | "open" | "checkIn" | "seeding" | "live" | "completed" | "cancelled";
31
+ /** `TournamentParticipant.entryType` */
32
+ export type TournamentParticipantEntryType = "solo" | "team";
33
+ /** `TournamentParticipant.status` */
34
+ export type TournamentParticipantStatus = "registered" | "active" | "eliminated" | "completed";
35
+ /** `TournamentRole.role` */
36
+ export type TournamentRoleRole = "moderator" | "admin";
37
+ /** `TournamentStage.stageName` */
38
+ export type TournamentStageStageName = "Round 128" | "Round 64" | "Round 32" | "Round 16" | "Quarter Final" | "Semi-Final" | "Third Round" | "Finals" | "League";
39
+ /** `Tournament.teamSize` */
40
+ export type TournamentTeamSize = "one" | "two" | "three" | "four" | "five";
41
+ /** `Tournament.type` */
42
+ export type TournamentType = "Single Elimination" | "League" | "Double Elimination";
43
+ /** `UserTransaction.stripeStatus` */
44
+ export type UserTransactionStripeStatus = "pending" | "completed" | "failed" | "refunded" | "internal";
45
+ /** `UserTransaction.type` */
46
+ export type UserTransactionType = "purchase" | "debit" | "credit" | "refund" | "test";
47
+ /** Readability alias for `tournament.currentStatus`. */
48
+ export type TournamentStatus = TournamentCurrentStatus;
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ // AUTO-GENERATED by scripts/sync-from-strapi.js — DO NOT EDIT MANUALLY.
3
+ // Source: xpt-strapi/src/**/content-types/**/schema.json
4
+ // Regenerate with: yarn sync
5
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,3 @@
1
+ export * from './enums';
2
+ export * from './models';
3
+ export * from './inputs';
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ // AUTO-GENERATED by scripts/sync-from-strapi.js — DO NOT EDIT MANUALLY.
3
+ // Source: xpt-strapi/src/**/content-types/**/schema.json
4
+ // Regenerate with: yarn sync
5
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
6
+ if (k2 === undefined) k2 = k;
7
+ var desc = Object.getOwnPropertyDescriptor(m, k);
8
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
9
+ desc = { enumerable: true, get: function() { return m[k]; } };
10
+ }
11
+ Object.defineProperty(o, k2, desc);
12
+ }) : (function(o, m, k, k2) {
13
+ if (k2 === undefined) k2 = k;
14
+ o[k2] = m[k];
15
+ }));
16
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
17
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
18
+ };
19
+ Object.defineProperty(exports, "__esModule", { value: true });
20
+ __exportStar(require("./enums"), exports);
21
+ __exportStar(require("./models"), exports);
22
+ __exportStar(require("./inputs"), exports);