@replayablejs/config 0.1.0-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Replayable contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,29 @@
1
+ # @replayablejs/config
2
+
3
+ Validate project settings and expand versions, networks and languages into playable variants.
4
+
5
+ Part of [Replayable](https://github.com/replayablejs/replayable) **0.1.0-alpha.0**.
6
+ APIs may change during the alpha series.
7
+
8
+ ## Install
9
+
10
+ ```sh
11
+ pnpm add -D @replayablejs/config@0.1.0-alpha.0
12
+ ```
13
+
14
+ ## Public surface
15
+
16
+ `defineConfig`, `replayableConfigSchema`, `replayableAssetsSchema`, `createVariants`; configuration input/output and `PlayableVariant` types.
17
+
18
+ [Usage and reference](https://github.com/replayablejs/replayable/blob/main/docs/reference/config.md).
19
+ The package manifest defines supported import paths; internal source files are not public APIs.
20
+
21
+ ## Development
22
+
23
+ From the repository root, install with `pnpm install --frozen-lockfile` and build dependencies
24
+ with `pnpm build`. Run `pnpm --filter @replayablejs/config test` for this package's tests.
25
+
26
+ ## License
27
+
28
+ Original code is [MIT licensed](https://github.com/replayablejs/replayable/blob/main/LICENSE). Bundled third-party resources retain
29
+ their accompanying license terms.
@@ -0,0 +1,608 @@
1
+ import { z } from "zod";
2
+ import { AssetConfig } from "@replayablejs/assets";
3
+ //#region src/config/schemas/assets.d.ts
4
+ /**
5
+ * Language-independent asset configuration authored as part of a project config.
6
+ *
7
+ * Replayable derives this contract from the assets package instead of
8
+ * maintaining a second copy. Variant expansion adds each playable's fixed
9
+ * language before producing the complete asset configuration.
10
+ */
11
+ declare const replayableAssetsSchema: z.ZodObject<{
12
+ sourceDir: z.ZodString;
13
+ outDir: z.ZodString;
14
+ bundles: z.ZodPrefault<z.ZodObject<{
15
+ secondary: z.ZodOptional<z.ZodObject<{
16
+ exclude: z.ZodOptional<z.ZodArray<z.ZodString>>;
17
+ include: z.ZodArray<z.ZodString>;
18
+ }, z.core.$strict>>;
19
+ }, z.core.$strict>>;
20
+ assets: z.ZodObject<{
21
+ atlases: z.ZodDefault<z.ZodArray<z.ZodObject<{
22
+ match: z.ZodDefault<z.ZodString>;
23
+ exclude: z.ZodOptional<z.ZodArray<z.ZodString>>;
24
+ options: z.ZodPrefault<z.ZodUnion<readonly [z.ZodObject<{
25
+ scale: z.ZodDefault<z.ZodNumber>;
26
+ lossless: z.ZodDefault<z.ZodLiteral<false>>;
27
+ quality: z.ZodOptional<z.ZodNumber>;
28
+ allowTrim: z.ZodDefault<z.ZodBoolean>;
29
+ allowRotation: z.ZodDefault<z.ZodBoolean>;
30
+ padding: z.ZodDefault<z.ZodNumber>;
31
+ extrude: z.ZodDefault<z.ZodNumber>;
32
+ powerOfTwo: z.ZodDefault<z.ZodBoolean>;
33
+ }, z.core.$strict>, z.ZodObject<{
34
+ scale: z.ZodDefault<z.ZodNumber>;
35
+ lossless: z.ZodLiteral<true>;
36
+ allowTrim: z.ZodDefault<z.ZodBoolean>;
37
+ allowRotation: z.ZodDefault<z.ZodBoolean>;
38
+ padding: z.ZodDefault<z.ZodNumber>;
39
+ extrude: z.ZodDefault<z.ZodNumber>;
40
+ powerOfTwo: z.ZodDefault<z.ZodBoolean>;
41
+ }, z.core.$strict>]>>;
42
+ }, z.core.$strict>>>;
43
+ fonts: z.ZodDefault<z.ZodArray<z.ZodObject<{
44
+ match: z.ZodDefault<z.ZodString>;
45
+ exclude: z.ZodOptional<z.ZodArray<z.ZodString>>;
46
+ options: z.ZodObject<{
47
+ family: z.ZodString;
48
+ extraCharacters: z.ZodOptional<z.ZodString>;
49
+ }, z.core.$strict>;
50
+ }, z.core.$strict>>>;
51
+ locales: z.ZodDefault<z.ZodArray<z.ZodObject<{
52
+ match: z.ZodDefault<z.ZodString>;
53
+ exclude: z.ZodOptional<z.ZodArray<z.ZodString>>;
54
+ }, z.core.$strict>>>;
55
+ shaders: z.ZodDefault<z.ZodArray<z.ZodObject<{
56
+ match: z.ZodDefault<z.ZodString>;
57
+ exclude: z.ZodOptional<z.ZodArray<z.ZodString>>;
58
+ }, z.core.$strict>>>;
59
+ sounds: z.ZodDefault<z.ZodArray<z.ZodObject<{
60
+ match: z.ZodDefault<z.ZodString>;
61
+ exclude: z.ZodOptional<z.ZodArray<z.ZodString>>;
62
+ options: z.ZodPrefault<z.ZodObject<{
63
+ bitrate: z.ZodDefault<z.ZodNumber>;
64
+ channels: z.ZodDefault<z.ZodEnum<{
65
+ mono: "mono";
66
+ source: "source";
67
+ stereo: "stereo";
68
+ }>>;
69
+ sampleRate: z.ZodDefault<z.ZodNumber>;
70
+ }, z.core.$strict>>;
71
+ }, z.core.$strict>>>;
72
+ spines: z.ZodDefault<z.ZodArray<z.ZodObject<{
73
+ match: z.ZodDefault<z.ZodString>;
74
+ exclude: z.ZodOptional<z.ZodArray<z.ZodString>>;
75
+ options: z.ZodPrefault<z.ZodUnion<readonly [z.ZodObject<{
76
+ scale: z.ZodDefault<z.ZodNumber>;
77
+ lossless: z.ZodDefault<z.ZodLiteral<false>>;
78
+ quality: z.ZodOptional<z.ZodNumber>;
79
+ }, z.core.$strict>, z.ZodObject<{
80
+ scale: z.ZodDefault<z.ZodNumber>;
81
+ lossless: z.ZodLiteral<true>;
82
+ }, z.core.$strict>]>>;
83
+ }, z.core.$strict>>>;
84
+ sprites: z.ZodDefault<z.ZodArray<z.ZodObject<{
85
+ match: z.ZodDefault<z.ZodString>;
86
+ exclude: z.ZodOptional<z.ZodArray<z.ZodString>>;
87
+ options: z.ZodPrefault<z.ZodUnion<readonly [z.ZodObject<{
88
+ scale: z.ZodDefault<z.ZodNumber>;
89
+ lossless: z.ZodDefault<z.ZodLiteral<false>>;
90
+ quality: z.ZodOptional<z.ZodNumber>;
91
+ }, z.core.$strict>, z.ZodObject<{
92
+ scale: z.ZodDefault<z.ZodNumber>;
93
+ lossless: z.ZodLiteral<true>;
94
+ }, z.core.$strict>]>>;
95
+ }, z.core.$strict>>>;
96
+ textures: z.ZodDefault<z.ZodArray<z.ZodObject<{
97
+ match: z.ZodDefault<z.ZodString>;
98
+ exclude: z.ZodOptional<z.ZodArray<z.ZodString>>;
99
+ options: z.ZodPrefault<z.ZodUnion<readonly [z.ZodObject<{
100
+ scale: z.ZodDefault<z.ZodNumber>;
101
+ lossless: z.ZodDefault<z.ZodLiteral<false>>;
102
+ quality: z.ZodOptional<z.ZodNumber>;
103
+ }, z.core.$strict>, z.ZodObject<{
104
+ scale: z.ZodDefault<z.ZodNumber>;
105
+ lossless: z.ZodLiteral<true>;
106
+ }, z.core.$strict>]>>;
107
+ }, z.core.$strict>>>;
108
+ }, z.core.$strict>;
109
+ exclude: z.ZodDefault<z.ZodArray<z.ZodString>>;
110
+ emit: z.ZodObject<{
111
+ assets: z.ZodDefault<z.ZodString>;
112
+ registries: z.ZodOptional<z.ZodString>;
113
+ }, z.core.$strict>;
114
+ }, z.core.$strict>;
115
+ //#endregion
116
+ //#region src/config/schema.d.ts
117
+ /**
118
+ * Runtime schema for the human-authored `replayable.config.ts` contract.
119
+ *
120
+ * Parsing trims meaningful strings; applies the default audio capability,
121
+ * background color, entry, version, and preview network; and rejects unknown
122
+ * fields.
123
+ */
124
+ declare const replayableConfigSchema: z.ZodObject<{
125
+ assets: z.ZodObject<{
126
+ sourceDir: z.ZodString;
127
+ outDir: z.ZodString;
128
+ bundles: z.ZodPrefault<z.ZodObject<{
129
+ secondary: z.ZodOptional<z.ZodObject<{
130
+ exclude: z.ZodOptional<z.ZodArray<z.ZodString>>;
131
+ include: z.ZodArray<z.ZodString>;
132
+ }, z.core.$strict>>;
133
+ }, z.core.$strict>>;
134
+ assets: z.ZodObject<{
135
+ atlases: z.ZodDefault<z.ZodArray<z.ZodObject<{
136
+ match: z.ZodDefault<z.ZodString>;
137
+ exclude: z.ZodOptional<z.ZodArray<z.ZodString>>;
138
+ options: z.ZodPrefault<z.ZodUnion<readonly [z.ZodObject<{
139
+ scale: z.ZodDefault<z.ZodNumber>;
140
+ lossless: z.ZodDefault<z.ZodLiteral<false>>;
141
+ quality: z.ZodOptional<z.ZodNumber>;
142
+ allowTrim: z.ZodDefault<z.ZodBoolean>;
143
+ allowRotation: z.ZodDefault<z.ZodBoolean>;
144
+ padding: z.ZodDefault<z.ZodNumber>;
145
+ extrude: z.ZodDefault<z.ZodNumber>;
146
+ powerOfTwo: z.ZodDefault<z.ZodBoolean>;
147
+ }, z.core.$strict>, z.ZodObject<{
148
+ scale: z.ZodDefault<z.ZodNumber>;
149
+ lossless: z.ZodLiteral<true>;
150
+ allowTrim: z.ZodDefault<z.ZodBoolean>;
151
+ allowRotation: z.ZodDefault<z.ZodBoolean>;
152
+ padding: z.ZodDefault<z.ZodNumber>;
153
+ extrude: z.ZodDefault<z.ZodNumber>;
154
+ powerOfTwo: z.ZodDefault<z.ZodBoolean>;
155
+ }, z.core.$strict>]>>;
156
+ }, z.core.$strict>>>;
157
+ fonts: z.ZodDefault<z.ZodArray<z.ZodObject<{
158
+ match: z.ZodDefault<z.ZodString>;
159
+ exclude: z.ZodOptional<z.ZodArray<z.ZodString>>;
160
+ options: z.ZodObject<{
161
+ family: z.ZodString;
162
+ extraCharacters: z.ZodOptional<z.ZodString>;
163
+ }, z.core.$strict>;
164
+ }, z.core.$strict>>>;
165
+ locales: z.ZodDefault<z.ZodArray<z.ZodObject<{
166
+ match: z.ZodDefault<z.ZodString>;
167
+ exclude: z.ZodOptional<z.ZodArray<z.ZodString>>;
168
+ }, z.core.$strict>>>;
169
+ shaders: z.ZodDefault<z.ZodArray<z.ZodObject<{
170
+ match: z.ZodDefault<z.ZodString>;
171
+ exclude: z.ZodOptional<z.ZodArray<z.ZodString>>;
172
+ }, z.core.$strict>>>;
173
+ sounds: z.ZodDefault<z.ZodArray<z.ZodObject<{
174
+ match: z.ZodDefault<z.ZodString>;
175
+ exclude: z.ZodOptional<z.ZodArray<z.ZodString>>;
176
+ options: z.ZodPrefault<z.ZodObject<{
177
+ bitrate: z.ZodDefault<z.ZodNumber>;
178
+ channels: z.ZodDefault<z.ZodEnum<{
179
+ mono: "mono";
180
+ source: "source";
181
+ stereo: "stereo";
182
+ }>>;
183
+ sampleRate: z.ZodDefault<z.ZodNumber>;
184
+ }, z.core.$strict>>;
185
+ }, z.core.$strict>>>;
186
+ spines: z.ZodDefault<z.ZodArray<z.ZodObject<{
187
+ match: z.ZodDefault<z.ZodString>;
188
+ exclude: z.ZodOptional<z.ZodArray<z.ZodString>>;
189
+ options: z.ZodPrefault<z.ZodUnion<readonly [z.ZodObject<{
190
+ scale: z.ZodDefault<z.ZodNumber>;
191
+ lossless: z.ZodDefault<z.ZodLiteral<false>>;
192
+ quality: z.ZodOptional<z.ZodNumber>;
193
+ }, z.core.$strict>, z.ZodObject<{
194
+ scale: z.ZodDefault<z.ZodNumber>;
195
+ lossless: z.ZodLiteral<true>;
196
+ }, z.core.$strict>]>>;
197
+ }, z.core.$strict>>>;
198
+ sprites: z.ZodDefault<z.ZodArray<z.ZodObject<{
199
+ match: z.ZodDefault<z.ZodString>;
200
+ exclude: z.ZodOptional<z.ZodArray<z.ZodString>>;
201
+ options: z.ZodPrefault<z.ZodUnion<readonly [z.ZodObject<{
202
+ scale: z.ZodDefault<z.ZodNumber>;
203
+ lossless: z.ZodDefault<z.ZodLiteral<false>>;
204
+ quality: z.ZodOptional<z.ZodNumber>;
205
+ }, z.core.$strict>, z.ZodObject<{
206
+ scale: z.ZodDefault<z.ZodNumber>;
207
+ lossless: z.ZodLiteral<true>;
208
+ }, z.core.$strict>]>>;
209
+ }, z.core.$strict>>>;
210
+ textures: z.ZodDefault<z.ZodArray<z.ZodObject<{
211
+ match: z.ZodDefault<z.ZodString>;
212
+ exclude: z.ZodOptional<z.ZodArray<z.ZodString>>;
213
+ options: z.ZodPrefault<z.ZodUnion<readonly [z.ZodObject<{
214
+ scale: z.ZodDefault<z.ZodNumber>;
215
+ lossless: z.ZodDefault<z.ZodLiteral<false>>;
216
+ quality: z.ZodOptional<z.ZodNumber>;
217
+ }, z.core.$strict>, z.ZodObject<{
218
+ scale: z.ZodDefault<z.ZodNumber>;
219
+ lossless: z.ZodLiteral<true>;
220
+ }, z.core.$strict>]>>;
221
+ }, z.core.$strict>>>;
222
+ }, z.core.$strict>;
223
+ exclude: z.ZodDefault<z.ZodArray<z.ZodString>>;
224
+ emit: z.ZodObject<{
225
+ assets: z.ZodDefault<z.ZodString>;
226
+ registries: z.ZodOptional<z.ZodString>;
227
+ }, z.core.$strict>;
228
+ }, z.core.$strict>;
229
+ audio: z.ZodDefault<z.ZodBoolean>;
230
+ backgroundColor: z.ZodDefault<z.ZodString>;
231
+ build: z.ZodPrefault<z.ZodObject<{
232
+ outDir: z.ZodDefault<z.ZodString>;
233
+ }, z.core.$strict>>;
234
+ completion: z.ZodDefault<z.ZodObject<{
235
+ duration: z.ZodOptional<z.ZodNumber>;
236
+ inactivity: z.ZodOptional<z.ZodNumber>;
237
+ }, z.core.$strict>>;
238
+ controls: z.ZodPrefault<z.ZodObject<{
239
+ persistentCta: z.ZodDefault<z.ZodBoolean>;
240
+ }, z.core.$strict>>;
241
+ devtools: z.ZodPrefault<z.ZodObject<{
242
+ stats: z.ZodPipe<z.ZodDefault<z.ZodUnion<readonly [z.ZodBoolean, z.ZodObject<{
243
+ display: z.ZodDefault<z.ZodEnum<{
244
+ compact: "compact";
245
+ expanded: "expanded";
246
+ }>>;
247
+ fps: z.ZodDefault<z.ZodBoolean>;
248
+ frameInterval: z.ZodDefault<z.ZodBoolean>;
249
+ jsHeap: z.ZodDefault<z.ZodBoolean>;
250
+ drawCalls: z.ZodDefault<z.ZodBoolean>;
251
+ textureBinds: z.ZodDefault<z.ZodBoolean>;
252
+ programUses: z.ZodDefault<z.ZodBoolean>;
253
+ }, z.core.$strict>]>>, z.ZodTransform<false | {
254
+ display: "compact" | "expanded";
255
+ fps: boolean;
256
+ frameInterval: boolean;
257
+ jsHeap: boolean;
258
+ drawCalls: boolean;
259
+ textureBinds: boolean;
260
+ programUses: boolean;
261
+ }, boolean | {
262
+ display: "compact" | "expanded";
263
+ fps: boolean;
264
+ frameInterval: boolean;
265
+ jsHeap: boolean;
266
+ drawCalls: boolean;
267
+ textureBinds: boolean;
268
+ programUses: boolean;
269
+ }>>;
270
+ endCardTrigger: z.ZodDefault<z.ZodBoolean>;
271
+ soundControl: z.ZodDefault<z.ZodBoolean>;
272
+ }, z.core.$strict>>;
273
+ entry: z.ZodDefault<z.ZodString>;
274
+ localization: z.ZodObject<{
275
+ languages: z.ZodArray<z.ZodString>;
276
+ fallback: z.ZodString;
277
+ }, z.core.$strict>;
278
+ name: z.ZodString;
279
+ networks: z.ZodDefault<z.ZodRecord<z.ZodEnum<{
280
+ applovin: "applovin";
281
+ google: "google";
282
+ liftoff: "liftoff";
283
+ meta: "meta";
284
+ mintegral: "mintegral";
285
+ moloco: "moloco";
286
+ preview: "preview";
287
+ unity: "unity";
288
+ }> & z.core.$partial, z.ZodObject<{
289
+ assets: z.ZodOptional<z.ZodObject<{
290
+ exclude: z.ZodDefault<z.ZodArray<z.ZodString>>;
291
+ }, z.core.$strict>>;
292
+ audio: z.ZodOptional<z.ZodLiteral<false>>;
293
+ completion: z.ZodOptional<z.ZodObject<{
294
+ duration: z.ZodOptional<z.ZodUnion<[z.ZodNumber, z.ZodLiteral<false>]>>;
295
+ inactivity: z.ZodOptional<z.ZodUnion<[z.ZodNumber, z.ZodLiteral<false>]>>;
296
+ }, z.core.$strict>>;
297
+ params: z.ZodOptional<z.ZodType<Record<string, string | number | boolean>, Record<string, string | number | boolean>, z.core.$ZodTypeInternals<Record<string, string | number | boolean>, Record<string, string | number | boolean>>>>;
298
+ }, z.core.$strict>>>;
299
+ params: z.ZodDefault<z.ZodType<Record<string, {
300
+ description: string;
301
+ when?: {
302
+ param: string;
303
+ equals: string | number | boolean;
304
+ } | undefined;
305
+ type: "boolean";
306
+ default: boolean;
307
+ } | {
308
+ description: string;
309
+ when?: {
310
+ param: string;
311
+ equals: string | number | boolean;
312
+ } | undefined;
313
+ type: "number";
314
+ default: number;
315
+ range: {
316
+ min: number;
317
+ max: number;
318
+ step: number;
319
+ };
320
+ } | {
321
+ description: string;
322
+ when?: {
323
+ param: string;
324
+ equals: string | number | boolean;
325
+ } | undefined;
326
+ type: "string";
327
+ default: string;
328
+ options: string[];
329
+ }>, Record<string, {
330
+ description: string;
331
+ when?: {
332
+ param: string;
333
+ equals: string | number | boolean;
334
+ } | undefined;
335
+ type: "boolean";
336
+ default: boolean;
337
+ } | {
338
+ description: string;
339
+ when?: {
340
+ param: string;
341
+ equals: string | number | boolean;
342
+ } | undefined;
343
+ type: "number";
344
+ default: number;
345
+ range: {
346
+ min: number;
347
+ max: number;
348
+ step: number;
349
+ };
350
+ } | {
351
+ description: string;
352
+ when?: {
353
+ param: string;
354
+ equals: string | number | boolean;
355
+ } | undefined;
356
+ type: "string";
357
+ default: string;
358
+ options: string[];
359
+ }>, z.core.$ZodTypeInternals<Record<string, {
360
+ description: string;
361
+ when?: {
362
+ param: string;
363
+ equals: string | number | boolean;
364
+ } | undefined;
365
+ type: "boolean";
366
+ default: boolean;
367
+ } | {
368
+ description: string;
369
+ when?: {
370
+ param: string;
371
+ equals: string | number | boolean;
372
+ } | undefined;
373
+ type: "number";
374
+ default: number;
375
+ range: {
376
+ min: number;
377
+ max: number;
378
+ step: number;
379
+ };
380
+ } | {
381
+ description: string;
382
+ when?: {
383
+ param: string;
384
+ equals: string | number | boolean;
385
+ } | undefined;
386
+ type: "string";
387
+ default: string;
388
+ options: string[];
389
+ }>, Record<string, {
390
+ description: string;
391
+ when?: {
392
+ param: string;
393
+ equals: string | number | boolean;
394
+ } | undefined;
395
+ type: "boolean";
396
+ default: boolean;
397
+ } | {
398
+ description: string;
399
+ when?: {
400
+ param: string;
401
+ equals: string | number | boolean;
402
+ } | undefined;
403
+ type: "number";
404
+ default: number;
405
+ range: {
406
+ min: number;
407
+ max: number;
408
+ step: number;
409
+ };
410
+ } | {
411
+ description: string;
412
+ when?: {
413
+ param: string;
414
+ equals: string | number | boolean;
415
+ } | undefined;
416
+ type: "string";
417
+ default: string;
418
+ options: string[];
419
+ }>>>>;
420
+ screen: z.ZodObject<{
421
+ orientations: z.ZodObject<{
422
+ portrait: z.ZodObject<{
423
+ enabled: z.ZodBoolean;
424
+ width: z.ZodNumber;
425
+ height: z.ZodNumber;
426
+ ratio: z.ZodObject<{
427
+ min: z.ZodNumber;
428
+ max: z.ZodNumber;
429
+ }, z.core.$strict>;
430
+ }, z.core.$strict>;
431
+ landscape: z.ZodObject<{
432
+ enabled: z.ZodBoolean;
433
+ width: z.ZodNumber;
434
+ height: z.ZodNumber;
435
+ ratio: z.ZodObject<{
436
+ min: z.ZodNumber;
437
+ max: z.ZodNumber;
438
+ }, z.core.$strict>;
439
+ }, z.core.$strict>;
440
+ }, z.core.$strict>;
441
+ resolution: z.ZodObject<{
442
+ pixelRatio: z.ZodObject<{
443
+ min: z.ZodNumber;
444
+ max: z.ZodNumber;
445
+ }, z.core.$strict>;
446
+ renderScale: z.ZodObject<{
447
+ minimal: z.ZodNumber;
448
+ reduced: z.ZodNumber;
449
+ balanced: z.ZodNumber;
450
+ full: z.ZodNumber;
451
+ }, z.core.$strict>;
452
+ }, z.core.$strict>;
453
+ }, z.core.$strict>;
454
+ store: z.ZodObject<{
455
+ androidUrl: z.ZodPipe<z.ZodString, z.ZodURL>;
456
+ iosUrl: z.ZodPipe<z.ZodString, z.ZodURL>;
457
+ }, z.core.$strict>;
458
+ versions: z.ZodDefault<z.ZodType<Record<string, {
459
+ assets?: {
460
+ exclude: string[];
461
+ } | undefined;
462
+ audio?: false | undefined;
463
+ completion?: {
464
+ duration?: number | false | undefined;
465
+ inactivity?: number | false | undefined;
466
+ } | undefined;
467
+ params?: Record<string, string | number | boolean> | undefined;
468
+ }>, Record<string, {
469
+ assets?: {
470
+ exclude?: string[] | undefined;
471
+ } | undefined;
472
+ audio?: false | undefined;
473
+ completion?: {
474
+ duration?: number | false | undefined;
475
+ inactivity?: number | false | undefined;
476
+ } | undefined;
477
+ params?: Record<string, string | number | boolean> | undefined;
478
+ }>, z.core.$ZodTypeInternals<Record<string, {
479
+ assets?: {
480
+ exclude: string[];
481
+ } | undefined;
482
+ audio?: false | undefined;
483
+ completion?: {
484
+ duration?: number | false | undefined;
485
+ inactivity?: number | false | undefined;
486
+ } | undefined;
487
+ params?: Record<string, string | number | boolean> | undefined;
488
+ }>, Record<string, {
489
+ assets?: {
490
+ exclude?: string[] | undefined;
491
+ } | undefined;
492
+ audio?: false | undefined;
493
+ completion?: {
494
+ duration?: number | false | undefined;
495
+ inactivity?: number | false | undefined;
496
+ } | undefined;
497
+ params?: Record<string, string | number | boolean> | undefined;
498
+ }>>>>;
499
+ }, z.core.$strict>;
500
+ //#endregion
501
+ //#region src/config/schemas/variants.d.ts
502
+ /** Delivery networks whose behavior is implemented internally by Replayable. */
503
+ declare const networkSchema: z.ZodEnum<{
504
+ applovin: "applovin";
505
+ google: "google";
506
+ liftoff: "liftoff";
507
+ meta: "meta";
508
+ mintegral: "mintegral";
509
+ moloco: "moloco";
510
+ preview: "preview";
511
+ unity: "unity";
512
+ }>;
513
+ //#endregion
514
+ //#region src/types/config.d.ts
515
+ /** Validated Replayable project configuration with every schema default applied. */
516
+ type ReplayableConfig = z.infer<typeof replayableConfigSchema>;
517
+ /** Human-authored Replayable project configuration accepted before defaults are applied. */
518
+ type ReplayableConfigInput = z.input<typeof replayableConfigSchema>;
519
+ /** Validated language-independent asset configuration stored in the project config. */
520
+ type ReplayableAssetsConfig = z.infer<typeof replayableAssetsSchema>;
521
+ /** Language-independent asset configuration accepted from project authors. */
522
+ type ReplayableAssetsConfigInput = z.input<typeof replayableAssetsSchema>;
523
+ /** Validated project-wide build configuration. */
524
+ type ReplayableBuild = ReplayableConfig['build'];
525
+ /** Project-wide build configuration accepted before defaults are applied. */
526
+ type ReplayableBuildInput = ReplayableConfigInput['build'];
527
+ /** Validated automatic playable completion conditions. */
528
+ type ReplayableCompletion = ReplayableConfig['completion'];
529
+ /** Automatic completion conditions accepted before defaults are applied. */
530
+ type ReplayableCompletionInput = ReplayableConfigInput['completion'];
531
+ /** Preview control preferences; ad-network profiles own the final visibility. */
532
+ type ReplayableControls = ReplayableConfig['controls'];
533
+ /** Optional preview controls accepted before defaults are applied. */
534
+ type ReplayableControlsInput = ReplayableConfigInput['controls'];
535
+ /** Validated project-wide development tool settings. */
536
+ type ReplayableDevtools = ReplayableConfig['devtools'];
537
+ /** Development tool shorthand accepted before defaults are applied. */
538
+ type ReplayableDevtoolsInput = ReplayableConfigInput['devtools'];
539
+ /** Validated build languages and missing-translation fallback. */
540
+ type ReplayableLocalization = ReplayableConfig['localization'];
541
+ /** Localization configuration accepted in a human-authored Replayable config. */
542
+ type ReplayableLocalizationInput = ReplayableConfigInput['localization'];
543
+ /** Delivery network with an implementation owned by Replayable. */
544
+ type ReplayableNetwork = z.infer<typeof networkSchema>;
545
+ /** One validated boolean, number, or string parameter definition. */
546
+ type ReplayableParamDefinition = ReplayableConfig['params'][string];
547
+ /** Primitive value accepted by a concrete parameter. */
548
+ type ReplayableParamValue = ReplayableParamDefinition['default'];
549
+ /** Parameter definitions accepted in a human-authored Replayable config. */
550
+ type ReplayableParamsInput = ReplayableConfigInput['params'];
551
+ /** Validated rendering dimensions and resolution policy. */
552
+ type ReplayableScreen = ReplayableConfig['screen'];
553
+ /** Screen configuration accepted in a human-authored Replayable config. */
554
+ type ReplayableScreenInput = ReplayableConfigInput['screen'];
555
+ /** Validated iOS and Android destinations for the playable's call to action. */
556
+ type ReplayableStore = ReplayableConfig['store'];
557
+ /** Store destinations accepted in a human-authored Replayable config. */
558
+ type ReplayableStoreInput = ReplayableConfigInput['store'];
559
+ //#endregion
560
+ //#region src/config/define-config.d.ts
561
+ /**
562
+ * Validates an authored Replayable project configuration and applies defaults.
563
+ *
564
+ * @param input - Human-authored Replayable configuration.
565
+ * @returns The validated and normalized project configuration.
566
+ * @throws When a field is missing, unknown, or invalid.
567
+ */
568
+ declare function defineConfig(input: ReplayableConfigInput): ReplayableConfig;
569
+ //#endregion
570
+ //#region src/types/variant.d.ts
571
+ /** One concrete version, network, and language combination. */
572
+ interface PlayableVariant {
573
+ readonly assets: AssetConfig;
574
+ readonly audio: boolean;
575
+ readonly backgroundColor: string;
576
+ readonly completion: Readonly<ReplayableConfig['completion']>;
577
+ /** Preview preferences; ad-network profiles replace these during build resolution. */
578
+ readonly controls: Readonly<ReplayableConfig['controls']>;
579
+ readonly devtools: Readonly<ReplayableConfig['devtools']>;
580
+ readonly entry: string;
581
+ readonly id: string;
582
+ readonly localization: {
583
+ readonly language: string;
584
+ readonly fallback: string;
585
+ };
586
+ readonly network: ReplayableNetwork;
587
+ readonly params: Readonly<Record<string, ReplayableParamValue>>;
588
+ readonly projectName: string;
589
+ readonly screen: Readonly<ReplayableConfig['screen']>;
590
+ readonly store: Readonly<ReplayableConfig['store']>;
591
+ readonly version: string;
592
+ }
593
+ //#endregion
594
+ //#region src/variants/create-variants.d.ts
595
+ /**
596
+ * Expands one project configuration into every version/network/language combination.
597
+ *
598
+ * Every returned variant contains resolved values. Base parameters are extended
599
+ * by network parameters and then version parameters, making the version the
600
+ * most specific override. Asset exclusions follow the same precedence.
601
+ *
602
+ * @param config - Validated Replayable project configuration.
603
+ * @returns The ordered concrete playable variants.
604
+ */
605
+ declare function createVariants(config: ReplayableConfig): PlayableVariant[];
606
+ //#endregion
607
+ export { type PlayableVariant, type ReplayableAssetsConfig, type ReplayableAssetsConfigInput, type ReplayableBuild, type ReplayableBuildInput, type ReplayableCompletion, type ReplayableCompletionInput, type ReplayableConfig, type ReplayableConfigInput, type ReplayableControls, type ReplayableControlsInput, type ReplayableDevtools, type ReplayableDevtoolsInput, type ReplayableLocalization, type ReplayableLocalizationInput, type ReplayableNetwork, type ReplayableParamDefinition, type ReplayableParamValue, type ReplayableParamsInput, type ReplayableScreen, type ReplayableScreenInput, type ReplayableStore, type ReplayableStoreInput, createVariants, defineConfig, replayableAssetsSchema, replayableConfigSchema };
608
+ //# sourceMappingURL=index.d.mts.map
package/dist/index.mjs ADDED
@@ -0,0 +1,485 @@
1
+ import { z } from "zod";
2
+ import { assetConfigSchema } from "@replayablejs/assets";
3
+ //#region src/config/schemas/base.ts
4
+ /** Non-empty authored text normalized by trimming surrounding whitespace. */
5
+ const requiredStringSchema = z.string().trim().min(1);
6
+ /** Stable lowercase name accepted for a project-defined version. */
7
+ const dimensionNameSchema = requiredStringSchema.regex(/^[a-z][a-z0-9_-]*$/, "Target names must begin with a lowercase letter and contain only lowercase letters, numbers, underscores, and hyphens.");
8
+ /** Finite numeric value greater than zero. */
9
+ const positiveNumberSchema = z.number().positive();
10
+ //#endregion
11
+ //#region src/config/schemas/assets.ts
12
+ /**
13
+ * Language-independent asset configuration authored as part of a project config.
14
+ *
15
+ * Replayable derives this contract from the assets package instead of
16
+ * maintaining a second copy. Variant expansion adds each playable's fixed
17
+ * language before producing the complete asset configuration.
18
+ */
19
+ const replayableAssetsSchema = assetConfigSchema.omit({ localization: true });
20
+ /** Asset changes that may be applied by one version or network. */
21
+ const assetOverrideSchema = z.strictObject({ exclude: z.array(requiredStringSchema).default([]) });
22
+ //#endregion
23
+ //#region src/config/schemas/audio.ts
24
+ /** Whether generated playable variants include runtime audio capability. */
25
+ const audioSchema = z.boolean().default(true);
26
+ /** Allows a variant dimension to disable—but never re-enable—project audio. */
27
+ const audioOverrideSchema = z.literal(false);
28
+ /** First-paint color shown behind the playable before and after content mounts. */
29
+ const backgroundColorSchema = z.string().regex(/^#(?:[\da-f]{3}|[\da-f]{6})$/i, "Background color must be an opaque three- or six-digit hexadecimal CSS color.").default("#000000");
30
+ //#endregion
31
+ //#region src/config/schemas/build.ts
32
+ /** Project-wide destinations used when producing playable output. */
33
+ const buildSchema = z.strictObject({ outDir: requiredStringSchema.default("dist") }).prefault({});
34
+ //#endregion
35
+ //#region src/config/schemas/completion.ts
36
+ /** Positive duration in seconds used by a playable completion timer. */
37
+ const completionDurationSchema = z.number().positive();
38
+ /** Automatic conditions that may complete a playable. */
39
+ const completionSchema = z.strictObject({
40
+ /** Maximum playable duration in seconds. */
41
+ duration: completionDurationSchema.optional(),
42
+ /** Allowed inactivity in seconds after the first interaction. */
43
+ inactivity: completionDurationSchema.optional()
44
+ }).default({});
45
+ /** Per-variant completion values, where `false` disables an inherited timer. */
46
+ const completionOverrideSchema = z.strictObject({
47
+ duration: completionDurationSchema.or(z.literal(false)).optional(),
48
+ inactivity: completionDurationSchema.or(z.literal(false)).optional()
49
+ });
50
+ //#endregion
51
+ //#region src/config/schemas/controls.ts
52
+ /**
53
+ * Authored control visibility for local development and exported preview.
54
+ * Ad-network profiles replace these preferences with their delivery policy.
55
+ */
56
+ const controlsSchema = z.strictObject({
57
+ /** Shows the persistent CTA in preview; ad networks own their final policy. */
58
+ persistentCta: z.boolean().default(true) }).prefault({});
59
+ //#endregion
60
+ //#region src/config/schemas/stats.ts
61
+ /** Enabled stats request every metric in expanded mode unless explicitly configured. */
62
+ const statsOptionsSchema = z.strictObject({
63
+ display: z.enum(["expanded", "compact"]).default("expanded"),
64
+ fps: z.boolean().default(true),
65
+ frameInterval: z.boolean().default(true),
66
+ jsHeap: z.boolean().default(true),
67
+ /** Submitted draw operations, not rendered objects, triangles, or instances. */
68
+ drawCalls: z.boolean().default(true),
69
+ /** Calls to bindTexture, not the number of allocated or unique textures. */
70
+ textureBinds: z.boolean().default(true),
71
+ /** Calls to useProgram, not the number of allocated or unique programs. */
72
+ programUses: z.boolean().default(true)
73
+ });
74
+ /** Resolves the shorthand once into disabled stats or explicit display and panel settings. */
75
+ const statsSchema = z.union([z.boolean(), statsOptionsSchema]).default(false).transform((stats) => stats === true ? statsOptionsSchema.parse({}) : stats);
76
+ //#endregion
77
+ //#region src/config/schemas/devtools.ts
78
+ /** Project-wide development tools; omitted tools remain disabled. */
79
+ const devtoolsSchema = z.strictObject({
80
+ stats: statsSchema,
81
+ /** Development-only Escape shortcut and DOM Skip button; never included in exports. */
82
+ endCardTrigger: z.boolean().default(false),
83
+ /** Development-only audio toggle; omitted from every production build, including preview. */
84
+ soundControl: z.boolean().default(false)
85
+ }).prefault({});
86
+ //#endregion
87
+ //#region src/config/schemas/localization.ts
88
+ const languageSchema = requiredStringSchema.refine(isLanguageTag, {
89
+ message: "Language must be a valid BCP 47 tag.",
90
+ abort: true
91
+ });
92
+ /** Languages expanded into fixed-language variants and their missing-value fallback. */
93
+ const localizationSchema = z.strictObject({
94
+ languages: z.array(languageSchema).min(1),
95
+ fallback: languageSchema
96
+ }).superRefine(({ fallback, languages }, context) => {
97
+ if (Intl.getCanonicalLocales(languages).length !== languages.length) context.addIssue({
98
+ code: "custom",
99
+ message: "Localization languages must be unique after BCP 47 canonicalization.",
100
+ path: ["languages"]
101
+ });
102
+ if (!languages.includes(fallback)) context.addIssue({
103
+ code: "custom",
104
+ message: "The fallback language must also appear in localization.languages.",
105
+ path: ["fallback"]
106
+ });
107
+ });
108
+ /** Uses the runtime's Unicode locale data instead of maintaining a fixed language list. */
109
+ function isLanguageTag(language) {
110
+ try {
111
+ Intl.getCanonicalLocales(language);
112
+ return true;
113
+ } catch {
114
+ return false;
115
+ }
116
+ }
117
+ //#endregion
118
+ //#region src/config/validation/params.ts
119
+ /** Validates catalog values and conditions after schema parsing. */
120
+ function validateParamDefinitions(params, context) {
121
+ for (const [name, definition] of Object.entries(params)) validateParamDefinition(name, definition, params, context);
122
+ }
123
+ /** Validates constraints and dependency references within the parameter catalog. */
124
+ function validateParamDefinition(name, definition, params, context) {
125
+ switch (definition.type) {
126
+ case "boolean": break;
127
+ case "number":
128
+ validateNumberParam(name, definition, context);
129
+ break;
130
+ case "string": validateStringParam(name, definition, context);
131
+ }
132
+ validateParamCondition(name, definition, params, context);
133
+ }
134
+ /** Validates one number parameter's range and default value. */
135
+ function validateNumberParam(name, definition, context) {
136
+ const { max, min } = definition.range;
137
+ if (min > max) addParamIssue(context, name, ["range"], "The minimum cannot exceed the maximum.");
138
+ else if (!isStepAligned(max, definition.range)) addParamIssue(context, name, ["range", "step"], "The maximum must be reachable from the minimum using the configured step.");
139
+ else if (definition.default < min || definition.default > max) addParamIssue(context, name, ["default"], "The default must be within its configured range.");
140
+ else if (!isStepAligned(definition.default, definition.range)) addParamIssue(context, name, ["default"], "The default must align with the configured range step.");
141
+ }
142
+ /** Validates one string parameter's options and default value. */
143
+ function validateStringParam(name, definition, context) {
144
+ if (new Set(definition.options).size !== definition.options.length) addParamIssue(context, name, ["options"], "Parameter options must be unique.");
145
+ if (!definition.options.includes(definition.default)) addParamIssue(context, name, ["default"], "The default must appear in its configured options.");
146
+ }
147
+ /** Validates one parameter's optional condition against the complete catalog. */
148
+ function validateParamCondition(name, definition, params, context) {
149
+ const condition = definition.when;
150
+ if (condition === void 0) return;
151
+ const referencedParam = params[condition.param];
152
+ if (referencedParam === void 0) {
153
+ addParamIssue(context, name, ["when", "param"], "The condition references a parameter that does not exist.");
154
+ return;
155
+ }
156
+ if (condition.param === name) addParamIssue(context, name, ["when", "param"], "A parameter cannot condition itself.");
157
+ if (!isAllowedParamValue(referencedParam, condition.equals)) addParamIssue(context, name, ["when", "equals"], "The condition value must be allowed by the referenced parameter.");
158
+ }
159
+ /** Ensures every dimension override names an existing parameter and supplies an allowed value. */
160
+ function validateParamOverrides(groupName, overrides, params, context) {
161
+ for (const [dimensionName, dimensionOverride] of Object.entries(overrides)) for (const [paramName, value] of Object.entries(dimensionOverride.params ?? {})) {
162
+ const definition = params[paramName];
163
+ if (definition === void 0) {
164
+ context.addIssue({
165
+ code: "custom",
166
+ message: "The overridden parameter does not exist.",
167
+ path: [
168
+ groupName,
169
+ dimensionName,
170
+ "params",
171
+ paramName
172
+ ]
173
+ });
174
+ continue;
175
+ }
176
+ if (!isAllowedParamValue(definition, value)) context.addIssue({
177
+ code: "custom",
178
+ message: "The override does not satisfy the parameter definition.",
179
+ path: [
180
+ groupName,
181
+ dimensionName,
182
+ "params",
183
+ paramName
184
+ ]
185
+ });
186
+ }
187
+ }
188
+ /** Checks an override against the parameter's finite set of allowed values. */
189
+ function isAllowedParamValue(definition, value) {
190
+ let allowed;
191
+ switch (definition.type) {
192
+ case "boolean":
193
+ allowed = typeof value === "boolean";
194
+ break;
195
+ case "number":
196
+ allowed = typeof value === "number" && isAllowedNumberValue(value, definition.range);
197
+ break;
198
+ case "string": allowed = typeof value === "string" && definition.options.includes(value);
199
+ }
200
+ return allowed;
201
+ }
202
+ /** Checks both numeric bounds and membership in the range's discrete step sequence. */
203
+ function isAllowedNumberValue(value, range) {
204
+ return value >= range.min && value <= range.max && isStepAligned(value, range);
205
+ }
206
+ /** Tolerates the small rounding error produced by fractional JavaScript arithmetic. */
207
+ function isStepAligned(value, range) {
208
+ const stepsFromMinimum = (value - range.min) / range.step;
209
+ return Math.abs(stepsFromMinimum - Math.round(stepsFromMinimum)) < 1e-9;
210
+ }
211
+ /** Adds one issue at a parameter-relative path. */
212
+ function addParamIssue(context, name, path, message) {
213
+ context.addIssue({
214
+ code: "custom",
215
+ message,
216
+ path: [name, ...path]
217
+ });
218
+ }
219
+ //#endregion
220
+ //#region src/config/schemas/record.ts
221
+ /** Checks authored keys before a record schema trims them and could overwrite a value. */
222
+ function withUniqueTrimmedKeys(schema) {
223
+ return z.transform((input, context) => {
224
+ if (typeof input !== "object" || input === null || Array.isArray(input)) return input;
225
+ const keys = /* @__PURE__ */ new Set();
226
+ for (const key of Object.keys(input)) {
227
+ const normalized = key.trim();
228
+ if (keys.has(normalized)) context.addIssue({
229
+ code: "custom",
230
+ message: "Names must be unique after trimming whitespace.",
231
+ path: [key]
232
+ });
233
+ keys.add(normalized);
234
+ }
235
+ return input;
236
+ }).pipe(schema);
237
+ }
238
+ //#endregion
239
+ //#region src/config/schemas/params.ts
240
+ const paramValueSchema = z.union([
241
+ z.boolean(),
242
+ z.number(),
243
+ requiredStringSchema
244
+ ]);
245
+ /** Another parameter value that controls when a parameter is relevant. */
246
+ const paramConditionSchema = z.strictObject({
247
+ param: requiredStringSchema,
248
+ equals: paramValueSchema
249
+ });
250
+ const paramDescriptionField = { description: requiredStringSchema };
251
+ const paramConditionField = { when: paramConditionSchema.optional() };
252
+ const numberRangeSchema = z.strictObject({
253
+ min: z.number(),
254
+ max: z.number(),
255
+ step: z.number().positive()
256
+ });
257
+ /** Boolean, number, and string parameters exposed to builds and development tools. */
258
+ const paramDefinitionSchema = z.discriminatedUnion("type", [
259
+ z.strictObject({
260
+ type: z.literal("boolean"),
261
+ default: z.boolean(),
262
+ ...paramDescriptionField,
263
+ ...paramConditionField
264
+ }),
265
+ z.strictObject({
266
+ type: z.literal("number"),
267
+ default: z.number(),
268
+ ...paramDescriptionField,
269
+ range: numberRangeSchema,
270
+ ...paramConditionField
271
+ }),
272
+ z.strictObject({
273
+ type: z.literal("string"),
274
+ default: requiredStringSchema,
275
+ ...paramDescriptionField,
276
+ options: z.array(requiredStringSchema).min(1),
277
+ ...paramConditionField
278
+ })
279
+ ]);
280
+ const paramsSchema = withUniqueTrimmedKeys(z.record(requiredStringSchema, paramDefinitionSchema)).superRefine(validateParamDefinitions).default({});
281
+ const paramOverridesSchema = withUniqueTrimmedKeys(z.record(requiredStringSchema, paramValueSchema));
282
+ //#endregion
283
+ //#region src/config/schemas/screen.ts
284
+ /** Inclusive numeric bounds whose lower value cannot exceed the upper value. */
285
+ const rangeSchema = z.strictObject({
286
+ min: positiveNumberSchema,
287
+ max: positiveNumberSchema
288
+ }).refine(({ max, min }) => min <= max, "The minimum cannot exceed the maximum.");
289
+ /** One orientation's authored coordinate system and availability. */
290
+ const orientationSchema = z.strictObject({
291
+ enabled: z.boolean(),
292
+ width: z.number().int().positive(),
293
+ height: z.number().int().positive(),
294
+ ratio: rangeSchema
295
+ });
296
+ /** Ordered renderer-quality multipliers from the lowest to the highest policy. */
297
+ const renderScaleSchema = z.strictObject({
298
+ minimal: positiveNumberSchema.max(1),
299
+ reduced: positiveNumberSchema.max(1),
300
+ balanced: positiveNumberSchema.max(1),
301
+ full: positiveNumberSchema.max(1)
302
+ }).refine(({ balanced, full, minimal, reduced }) => minimal <= reduced && reduced <= balanced && balanced <= full, "Render scales must be ordered: minimal <= reduced <= balanced <= full.");
303
+ /** Device-pixel bounds and the render scale assigned to each quality policy. */
304
+ const resolutionSchema = z.strictObject({
305
+ pixelRatio: rangeSchema,
306
+ renderScale: renderScaleSchema
307
+ });
308
+ /** Rendering dimensions, supported aspect ratios, and resolution scaling policy. */
309
+ const screenSchema = z.strictObject({
310
+ orientations: z.strictObject({
311
+ portrait: orientationSchema,
312
+ landscape: orientationSchema
313
+ }),
314
+ resolution: resolutionSchema
315
+ }).refine(({ orientations }) => orientations.landscape.enabled || orientations.portrait.enabled, "At least one screen orientation must be enabled.");
316
+ //#endregion
317
+ //#region src/config/schemas/store.ts
318
+ /** Platform destinations opened when the playable's call to action is activated. */
319
+ const storeSchema = z.strictObject({
320
+ androidUrl: requiredStringSchema.pipe(z.url()),
321
+ iosUrl: requiredStringSchema.pipe(z.url())
322
+ });
323
+ //#endregion
324
+ //#region src/config/schemas/variants.ts
325
+ /** Values that one version or network may override for its playable variants. */
326
+ const variantOverrideSchema = z.strictObject({
327
+ assets: assetOverrideSchema.optional(),
328
+ audio: audioOverrideSchema.optional(),
329
+ completion: completionOverrideSchema.optional(),
330
+ params: paramOverridesSchema.optional()
331
+ });
332
+ /** Named versions normalized to the default version when omitted. */
333
+ const versionsSchema = withUniqueTrimmedKeys(z.record(dimensionNameSchema, variantOverrideSchema)).refine((versions) => Object.keys(versions).length > 0, "At least one version is required.").default({ default: {} });
334
+ /** Delivery networks whose behavior is implemented internally by Replayable. */
335
+ const networkSchema = z.enum([
336
+ "preview",
337
+ "applovin",
338
+ "meta",
339
+ "google",
340
+ "liftoff",
341
+ "mintegral",
342
+ "moloco",
343
+ "unity"
344
+ ]);
345
+ /** Selected supported networks, normalized to local preview when omitted. */
346
+ const networksSchema = z.partialRecord(networkSchema, variantOverrideSchema).refine((networks) => Object.keys(networks).length > 0, "At least one network is required.").default({ preview: {} });
347
+ //#endregion
348
+ //#region src/config/schema.ts
349
+ /**
350
+ * Runtime schema for the human-authored `replayable.config.ts` contract.
351
+ *
352
+ * Parsing trims meaningful strings; applies the default audio capability,
353
+ * background color, entry, version, and preview network; and rejects unknown
354
+ * fields.
355
+ */
356
+ const replayableConfigSchema = z.strictObject({
357
+ assets: replayableAssetsSchema,
358
+ audio: audioSchema,
359
+ backgroundColor: backgroundColorSchema,
360
+ build: buildSchema,
361
+ completion: completionSchema,
362
+ controls: controlsSchema,
363
+ devtools: devtoolsSchema,
364
+ entry: requiredStringSchema.default("src/main.ts"),
365
+ localization: localizationSchema,
366
+ name: requiredStringSchema,
367
+ networks: networksSchema,
368
+ params: paramsSchema,
369
+ screen: screenSchema,
370
+ store: storeSchema,
371
+ versions: versionsSchema
372
+ }).superRefine(({ networks, params, versions }, context) => {
373
+ validateParamOverrides("networks", networks, params, context);
374
+ validateParamOverrides("versions", versions, params, context);
375
+ });
376
+ //#endregion
377
+ //#region src/config/define-config.ts
378
+ /**
379
+ * Validates an authored Replayable project configuration and applies defaults.
380
+ *
381
+ * @param input - Human-authored Replayable configuration.
382
+ * @returns The validated and normalized project configuration.
383
+ * @throws When a field is missing, unknown, or invalid.
384
+ */
385
+ function defineConfig(input) {
386
+ return replayableConfigSchema.parse(input);
387
+ }
388
+ //#endregion
389
+ //#region src/variants/create-variants.ts
390
+ const ALL_SOUNDS_PATTERN = "sounds/**";
391
+ /**
392
+ * Expands one project configuration into every version/network/language combination.
393
+ *
394
+ * Every returned variant contains resolved values. Base parameters are extended
395
+ * by network parameters and then version parameters, making the version the
396
+ * most specific override. Asset exclusions follow the same precedence.
397
+ *
398
+ * @param config - Validated Replayable project configuration.
399
+ * @returns The ordered concrete playable variants.
400
+ */
401
+ function createVariants(config) {
402
+ const variants = [];
403
+ for (const [version, versionOverride] of Object.entries(config.versions)) for (const network of networkSchema.options) {
404
+ const networkOverride = config.networks[network];
405
+ if (networkOverride === void 0) continue;
406
+ for (const language of config.localization.languages) variants.push(createPlayableVariant(config, {
407
+ language,
408
+ network,
409
+ networkOverride,
410
+ version,
411
+ versionOverride
412
+ }));
413
+ }
414
+ return variants;
415
+ }
416
+ /** Creates one fully concrete playable from the three configured dimensions. */
417
+ function createPlayableVariant(config, selection) {
418
+ const { language, network, networkOverride, version, versionOverride } = selection;
419
+ const audio = resolveAudio(config.audio, networkOverride.audio, versionOverride.audio);
420
+ const localization = {
421
+ language,
422
+ fallback: config.localization.fallback
423
+ };
424
+ return {
425
+ assets: resolveAssetConfig(config.assets, localization, audio, networkOverride.assets, versionOverride.assets),
426
+ audio,
427
+ backgroundColor: config.backgroundColor,
428
+ completion: resolveCompletion(config.completion, networkOverride.completion, versionOverride.completion),
429
+ controls: config.controls,
430
+ devtools: config.devtools,
431
+ entry: config.entry,
432
+ id: `${version}/${network}/${language}`,
433
+ localization,
434
+ network,
435
+ params: resolveParams(config.params, networkOverride.params, versionOverride.params),
436
+ projectName: config.name,
437
+ screen: config.screen,
438
+ store: config.store,
439
+ version
440
+ };
441
+ }
442
+ /** Resolves each completion timer independently using project, network, then version precedence. */
443
+ function resolveCompletion(project, network, version) {
444
+ const duration = resolveCompletionDuration(project.duration, network?.duration, version?.duration);
445
+ const inactivity = resolveCompletionDuration(project.inactivity, network?.inactivity, version?.inactivity);
446
+ const completion = {};
447
+ if (duration !== void 0) completion.duration = duration;
448
+ if (inactivity !== void 0) completion.inactivity = inactivity;
449
+ return completion;
450
+ }
451
+ /** Selects the most specific timer value and removes an explicit `false`. */
452
+ function resolveCompletionDuration(project, network, version) {
453
+ const resolved = version ?? network ?? project;
454
+ return resolved === false ? void 0 : resolved;
455
+ }
456
+ /** Completes the shared asset configuration for one fixed-language variant. */
457
+ function resolveAssetConfig(base, localization, audio, network, version) {
458
+ const exclude = [
459
+ ...base.exclude,
460
+ ...network?.exclude ?? [],
461
+ ...version?.exclude ?? []
462
+ ];
463
+ if (!audio && !exclude.includes(ALL_SOUNDS_PATTERN)) exclude.push(ALL_SOUNDS_PATTERN);
464
+ return {
465
+ ...base,
466
+ localization,
467
+ exclude
468
+ };
469
+ }
470
+ /** Resolves audio as a capability that any configuration dimension may disable. */
471
+ function resolveAudio(project, network, version) {
472
+ return project && network !== false && version !== false;
473
+ }
474
+ /** Extracts authored defaults, then applies network and version value overrides. */
475
+ function resolveParams(definitions, network, version) {
476
+ return {
477
+ ...Object.fromEntries(Object.entries(definitions).map(([name, definition]) => [name, definition.default])),
478
+ ...network,
479
+ ...version
480
+ };
481
+ }
482
+ //#endregion
483
+ export { createVariants, defineConfig, replayableAssetsSchema, replayableConfigSchema };
484
+
485
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../src/config/schemas/base.ts","../src/config/schemas/assets.ts","../src/config/schemas/audio.ts","../src/config/schemas/background.ts","../src/config/schemas/build.ts","../src/config/schemas/completion.ts","../src/config/schemas/controls.ts","../src/config/schemas/stats.ts","../src/config/schemas/devtools.ts","../src/config/schemas/localization.ts","../src/config/validation/params.ts","../src/config/schemas/record.ts","../src/config/schemas/params.ts","../src/config/schemas/screen.ts","../src/config/schemas/store.ts","../src/config/schemas/variants.ts","../src/config/schema.ts","../src/config/define-config.ts","../src/variants/create-variants.ts"],"sourcesContent":["import { z } from 'zod';\n\n/** Non-empty authored text normalized by trimming surrounding whitespace. */\nexport const requiredStringSchema = z.string().trim().min(1);\n\n/** Stable lowercase name accepted for a project-defined version. */\nexport const dimensionNameSchema = requiredStringSchema.regex(\n /^[a-z][a-z0-9_-]*$/,\n 'Target names must begin with a lowercase letter and contain only lowercase letters, numbers, underscores, and hyphens.',\n);\n\n/** Finite numeric value greater than zero. */\nexport const positiveNumberSchema = z.number().positive();\n","import { assetConfigSchema } from '@replayablejs/assets';\nimport { z } from 'zod';\n\nimport { requiredStringSchema } from './base.js';\n\n/**\n * Language-independent asset configuration authored as part of a project config.\n *\n * Replayable derives this contract from the assets package instead of\n * maintaining a second copy. Variant expansion adds each playable's fixed\n * language before producing the complete asset configuration.\n */\nexport const replayableAssetsSchema = assetConfigSchema.omit({ localization: true });\n\n/** Asset changes that may be applied by one version or network. */\nexport const assetOverrideSchema = z.strictObject({\n exclude: z.array(requiredStringSchema).default([]),\n});\n","import { z } from 'zod';\n\n/** Whether generated playable variants include runtime audio capability. */\nexport const audioSchema = z.boolean().default(true);\n\n/** Allows a variant dimension to disable—but never re-enable—project audio. */\nexport const audioOverrideSchema = z.literal(false);\n","import { z } from 'zod';\n\nconst OPAQUE_HEX_COLOR_PATTERN = /^#(?:[\\da-f]{3}|[\\da-f]{6})$/i;\n\n/** First-paint color shown behind the playable before and after content mounts. */\nexport const backgroundColorSchema = z\n .string()\n .regex(\n OPAQUE_HEX_COLOR_PATTERN,\n 'Background color must be an opaque three- or six-digit hexadecimal CSS color.',\n )\n .default('#000000');\n","import { z } from 'zod';\n\nimport { requiredStringSchema } from './base.js';\n\n/** Project-wide destinations used when producing playable output. */\nexport const buildSchema = z\n .strictObject({\n outDir: requiredStringSchema.default('dist'),\n })\n .prefault({});\n","import { z } from 'zod';\n\n/** Positive duration in seconds used by a playable completion timer. */\nconst completionDurationSchema = z.number().positive();\n\n/** Automatic conditions that may complete a playable. */\nexport const completionSchema = z\n .strictObject({\n /** Maximum playable duration in seconds. */\n duration: completionDurationSchema.optional(),\n /** Allowed inactivity in seconds after the first interaction. */\n inactivity: completionDurationSchema.optional(),\n })\n .default({});\n\n/** Per-variant completion values, where `false` disables an inherited timer. */\nexport const completionOverrideSchema = z.strictObject({\n duration: completionDurationSchema.or(z.literal(false)).optional(),\n inactivity: completionDurationSchema.or(z.literal(false)).optional(),\n});\n","import { z } from 'zod';\n\n/**\n * Authored control visibility for local development and exported preview.\n * Ad-network profiles replace these preferences with their delivery policy.\n */\nexport const controlsSchema = z\n .strictObject({\n /** Shows the persistent CTA in preview; ad networks own their final policy. */\n persistentCta: z.boolean().default(true),\n })\n .prefault({});\n","import { z } from 'zod';\n\n/** Enabled stats request every metric in expanded mode unless explicitly configured. */\nconst statsOptionsSchema = z.strictObject({\n display: z.enum(['expanded', 'compact']).default('expanded'),\n fps: z.boolean().default(true),\n frameInterval: z.boolean().default(true),\n jsHeap: z.boolean().default(true),\n /** Submitted draw operations, not rendered objects, triangles, or instances. */\n drawCalls: z.boolean().default(true),\n /** Calls to bindTexture, not the number of allocated or unique textures. */\n textureBinds: z.boolean().default(true),\n /** Calls to useProgram, not the number of allocated or unique programs. */\n programUses: z.boolean().default(true),\n});\n\n/** Resolves the shorthand once into disabled stats or explicit display and panel settings. */\nexport const statsSchema = z\n .union([z.boolean(), statsOptionsSchema])\n .default(false)\n .transform((stats) => (stats === true ? statsOptionsSchema.parse({}) : stats));\n","import { z } from 'zod';\n\nimport { statsSchema } from './stats.js';\n\n/** Project-wide development tools; omitted tools remain disabled. */\nexport const devtoolsSchema = z\n .strictObject({\n stats: statsSchema,\n /** Development-only Escape shortcut and DOM Skip button; never included in exports. */\n endCardTrigger: z.boolean().default(false),\n /** Development-only audio toggle; omitted from every production build, including preview. */\n soundControl: z.boolean().default(false),\n })\n .prefault({});\n","import { z } from 'zod';\n\nimport { requiredStringSchema } from './base.js';\n\nconst languageSchema = requiredStringSchema.refine(isLanguageTag, {\n message: 'Language must be a valid BCP 47 tag.',\n // Canonical uniqueness below only runs after every tag is known to be valid.\n abort: true,\n});\n\n/** Languages expanded into fixed-language variants and their missing-value fallback. */\nexport const localizationSchema = z\n .strictObject({\n languages: z.array(languageSchema).min(1),\n fallback: languageSchema,\n })\n .superRefine(({ fallback, languages }, context) => {\n // Preserve authored spelling for asset lookup, but reject equivalent language identities.\n if (Intl.getCanonicalLocales(languages).length !== languages.length) {\n context.addIssue({\n code: 'custom',\n message: 'Localization languages must be unique after BCP 47 canonicalization.',\n path: ['languages'],\n });\n }\n\n if (!languages.includes(fallback)) {\n context.addIssue({\n code: 'custom',\n message: 'The fallback language must also appear in localization.languages.',\n path: ['fallback'],\n });\n }\n });\n\n/** Uses the runtime's Unicode locale data instead of maintaining a fixed language list. */\nfunction isLanguageTag(language: string): boolean {\n try {\n Intl.getCanonicalLocales(language);\n\n return true;\n } catch {\n return false;\n }\n}\n","import type {\n ParamDefinition,\n ParamDefinitions,\n ParamOverrideGroup,\n NumberParamRange,\n ValidationContext,\n} from '#types/params.js';\n\n/** Validates catalog values and conditions after schema parsing. */\nexport function validateParamDefinitions(\n params: ParamDefinitions,\n context: ValidationContext,\n): void {\n for (const [name, definition] of Object.entries(params)) {\n validateParamDefinition(name, definition, params, context);\n }\n}\n\n/** Validates constraints and dependency references within the parameter catalog. */\nfunction validateParamDefinition(\n name: string,\n definition: ParamDefinition,\n params: ParamDefinitions,\n context: ValidationContext,\n): void {\n switch (definition.type) {\n case 'boolean':\n break;\n case 'number':\n validateNumberParam(name, definition, context);\n break;\n case 'string':\n validateStringParam(name, definition, context);\n break;\n }\n\n validateParamCondition(name, definition, params, context);\n}\n\n/** Validates one number parameter's range and default value. */\nfunction validateNumberParam(\n name: string,\n definition: Extract<ParamDefinition, { type: 'number' }>,\n context: ValidationContext,\n): void {\n const { max, min } = definition.range;\n\n if (min > max) {\n addParamIssue(context, name, ['range'], 'The minimum cannot exceed the maximum.');\n } else if (!isStepAligned(max, definition.range)) {\n addParamIssue(\n context,\n name,\n ['range', 'step'],\n 'The maximum must be reachable from the minimum using the configured step.',\n );\n } else if (definition.default < min || definition.default > max) {\n addParamIssue(context, name, ['default'], 'The default must be within its configured range.');\n } else if (!isStepAligned(definition.default, definition.range)) {\n addParamIssue(\n context,\n name,\n ['default'],\n 'The default must align with the configured range step.',\n );\n }\n}\n\n/** Validates one string parameter's options and default value. */\nfunction validateStringParam(\n name: string,\n definition: Extract<ParamDefinition, { type: 'string' }>,\n context: ValidationContext,\n): void {\n if (new Set(definition.options).size !== definition.options.length) {\n addParamIssue(context, name, ['options'], 'Parameter options must be unique.');\n }\n\n if (!definition.options.includes(definition.default)) {\n addParamIssue(context, name, ['default'], 'The default must appear in its configured options.');\n }\n}\n\n/** Validates one parameter's optional condition against the complete catalog. */\nfunction validateParamCondition(\n name: string,\n definition: ParamDefinition,\n params: ParamDefinitions,\n context: ValidationContext,\n): void {\n const condition = definition.when;\n\n if (condition === undefined) {\n return;\n }\n\n const referencedParam = params[condition.param];\n\n if (referencedParam === undefined) {\n addParamIssue(\n context,\n name,\n ['when', 'param'],\n 'The condition references a parameter that does not exist.',\n );\n\n return;\n }\n\n if (condition.param === name) {\n addParamIssue(context, name, ['when', 'param'], 'A parameter cannot condition itself.');\n }\n\n if (!isAllowedParamValue(referencedParam, condition.equals)) {\n addParamIssue(\n context,\n name,\n ['when', 'equals'],\n 'The condition value must be allowed by the referenced parameter.',\n );\n }\n}\n\n/** Ensures every dimension override names an existing parameter and supplies an allowed value. */\nexport function validateParamOverrides(\n groupName: 'networks' | 'versions',\n overrides: ParamOverrideGroup,\n params: ParamDefinitions,\n context: ValidationContext,\n): void {\n for (const [dimensionName, dimensionOverride] of Object.entries(overrides)) {\n for (const [paramName, value] of Object.entries(dimensionOverride.params ?? {})) {\n const definition = params[paramName];\n\n if (definition === undefined) {\n context.addIssue({\n code: 'custom',\n message: 'The overridden parameter does not exist.',\n path: [groupName, dimensionName, 'params', paramName],\n });\n\n continue;\n }\n\n if (!isAllowedParamValue(definition, value)) {\n context.addIssue({\n code: 'custom',\n message: 'The override does not satisfy the parameter definition.',\n path: [groupName, dimensionName, 'params', paramName],\n });\n }\n }\n }\n}\n\n/** Checks an override against the parameter's finite set of allowed values. */\nfunction isAllowedParamValue(definition: ParamDefinition, value: unknown): boolean {\n let allowed: boolean;\n\n switch (definition.type) {\n case 'boolean':\n allowed = typeof value === 'boolean';\n break;\n case 'number':\n allowed = typeof value === 'number' && isAllowedNumberValue(value, definition.range);\n break;\n case 'string':\n allowed = typeof value === 'string' && definition.options.includes(value);\n break;\n }\n\n return allowed;\n}\n\n/** Checks both numeric bounds and membership in the range's discrete step sequence. */\nfunction isAllowedNumberValue(value: number, range: NumberParamRange): boolean {\n return value >= range.min && value <= range.max && isStepAligned(value, range);\n}\n\n/** Tolerates the small rounding error produced by fractional JavaScript arithmetic. */\nfunction isStepAligned(value: number, range: NumberParamRange): boolean {\n const stepsFromMinimum = (value - range.min) / range.step;\n\n return Math.abs(stepsFromMinimum - Math.round(stepsFromMinimum)) < 1e-9;\n}\n\n/** Adds one issue at a parameter-relative path. */\nfunction addParamIssue(\n context: ValidationContext,\n name: string,\n path: readonly PropertyKey[],\n message: string,\n): void {\n context.addIssue({\n code: 'custom',\n message,\n path: [name, ...path],\n });\n}\n","import { z } from 'zod';\n\n/** Checks authored keys before a record schema trims them and could overwrite a value. */\nexport function withUniqueTrimmedKeys<Value extends z.ZodType>(\n schema: z.ZodRecord<z.ZodString, Value>,\n): z.ZodType<Record<string, z.output<Value>>, Record<string, z.input<Value>>> {\n return z\n .transform((input: Record<string, z.input<Value>>, context) => {\n // Leave shape errors to the record schema; this check only owns key collisions.\n if (typeof input !== 'object' || input === null || Array.isArray(input)) {\n return input;\n }\n\n const keys = new Set<string>();\n for (const key of Object.keys(input)) {\n const normalized = key.trim();\n if (keys.has(normalized)) {\n context.addIssue({\n code: 'custom',\n message: 'Names must be unique after trimming whitespace.',\n path: [key],\n });\n }\n keys.add(normalized);\n }\n\n return input;\n })\n .pipe(schema);\n}\n","import { z } from 'zod';\n\nimport { validateParamDefinitions } from '../validation/params.js';\nimport { requiredStringSchema } from './base.js';\nimport { withUniqueTrimmedKeys } from './record.js';\n\nconst paramValueSchema = z.union([z.boolean(), z.number(), requiredStringSchema]);\n\n/** Another parameter value that controls when a parameter is relevant. */\nconst paramConditionSchema = z.strictObject({\n param: requiredStringSchema,\n equals: paramValueSchema,\n});\n\nconst paramDescriptionField = {\n description: requiredStringSchema,\n};\nconst paramConditionField = {\n when: paramConditionSchema.optional(),\n};\n\nconst numberRangeSchema = z.strictObject({\n min: z.number(),\n max: z.number(),\n step: z.number().positive(),\n});\n\n/** Boolean, number, and string parameters exposed to builds and development tools. */\nexport const paramDefinitionSchema = z.discriminatedUnion('type', [\n z.strictObject({\n type: z.literal('boolean'),\n default: z.boolean(),\n ...paramDescriptionField,\n ...paramConditionField,\n }),\n z.strictObject({\n type: z.literal('number'),\n default: z.number(),\n ...paramDescriptionField,\n range: numberRangeSchema,\n ...paramConditionField,\n }),\n z.strictObject({\n type: z.literal('string'),\n default: requiredStringSchema,\n ...paramDescriptionField,\n options: z.array(requiredStringSchema).min(1),\n ...paramConditionField,\n }),\n]);\n\nexport const paramsSchema = withUniqueTrimmedKeys(\n z.record(requiredStringSchema, paramDefinitionSchema),\n)\n .superRefine(validateParamDefinitions)\n .default({});\n\nexport const paramOverridesSchema = withUniqueTrimmedKeys(\n z.record(requiredStringSchema, paramValueSchema),\n);\n","import { z } from 'zod';\n\nimport { positiveNumberSchema } from './base.js';\n\n/** Inclusive numeric bounds whose lower value cannot exceed the upper value. */\nconst rangeSchema = z\n .strictObject({\n min: positiveNumberSchema,\n max: positiveNumberSchema,\n })\n .refine(({ max, min }) => min <= max, 'The minimum cannot exceed the maximum.');\n\n/** One orientation's authored coordinate system and availability. */\nconst orientationSchema = z.strictObject({\n enabled: z.boolean(),\n width: z.number().int().positive(),\n height: z.number().int().positive(),\n ratio: rangeSchema,\n});\n\n/** Ordered renderer-quality multipliers from the lowest to the highest policy. */\nconst renderScaleSchema = z\n .strictObject({\n minimal: positiveNumberSchema.max(1),\n reduced: positiveNumberSchema.max(1),\n balanced: positiveNumberSchema.max(1),\n full: positiveNumberSchema.max(1),\n })\n .refine(\n ({ balanced, full, minimal, reduced }) =>\n minimal <= reduced && reduced <= balanced && balanced <= full,\n 'Render scales must be ordered: minimal <= reduced <= balanced <= full.',\n );\n\n/** Device-pixel bounds and the render scale assigned to each quality policy. */\nconst resolutionSchema = z.strictObject({\n pixelRatio: rangeSchema,\n renderScale: renderScaleSchema,\n});\n\n/** Rendering dimensions, supported aspect ratios, and resolution scaling policy. */\nexport const screenSchema = z\n .strictObject({\n orientations: z.strictObject({\n portrait: orientationSchema,\n landscape: orientationSchema,\n }),\n resolution: resolutionSchema,\n })\n .refine(\n ({ orientations }) => orientations.landscape.enabled || orientations.portrait.enabled,\n 'At least one screen orientation must be enabled.',\n );\n","import { z } from 'zod';\n\nimport { requiredStringSchema } from './base.js';\n\n/** Platform destinations opened when the playable's call to action is activated. */\nexport const storeSchema = z.strictObject({\n androidUrl: requiredStringSchema.pipe(z.url()),\n iosUrl: requiredStringSchema.pipe(z.url()),\n});\n","import { z } from 'zod';\n\nimport { assetOverrideSchema } from './assets.js';\nimport { audioOverrideSchema } from './audio.js';\nimport { dimensionNameSchema } from './base.js';\nimport { completionOverrideSchema } from './completion.js';\nimport { paramOverridesSchema } from './params.js';\nimport { withUniqueTrimmedKeys } from './record.js';\n\n/** Values that one version or network may override for its playable variants. */\nconst variantOverrideSchema = z.strictObject({\n assets: assetOverrideSchema.optional(),\n audio: audioOverrideSchema.optional(),\n completion: completionOverrideSchema.optional(),\n params: paramOverridesSchema.optional(),\n});\n\n/** Named versions normalized to the default version when omitted. */\nexport const versionsSchema = withUniqueTrimmedKeys(\n z.record(dimensionNameSchema, variantOverrideSchema),\n)\n .refine((versions) => Object.keys(versions).length > 0, 'At least one version is required.')\n .default({ default: {} });\n\n/** Delivery networks whose behavior is implemented internally by Replayable. */\nexport const networkSchema = z.enum([\n 'preview',\n 'applovin',\n 'meta',\n 'google',\n 'liftoff',\n 'mintegral',\n 'moloco',\n 'unity',\n]);\n\n/** Selected supported networks, normalized to local preview when omitted. */\nexport const networksSchema = z\n .partialRecord(networkSchema, variantOverrideSchema)\n .refine((networks) => Object.keys(networks).length > 0, 'At least one network is required.')\n .default({ preview: {} });\n","import { z } from 'zod';\n\nimport { replayableAssetsSchema } from './schemas/assets.js';\nimport { audioSchema } from './schemas/audio.js';\nimport { backgroundColorSchema } from './schemas/background.js';\nimport { requiredStringSchema } from './schemas/base.js';\nimport { buildSchema } from './schemas/build.js';\nimport { completionSchema } from './schemas/completion.js';\nimport { controlsSchema } from './schemas/controls.js';\nimport { devtoolsSchema } from './schemas/devtools.js';\nimport { localizationSchema } from './schemas/localization.js';\nimport { paramsSchema } from './schemas/params.js';\nimport { screenSchema } from './schemas/screen.js';\nimport { storeSchema } from './schemas/store.js';\nimport { networksSchema, versionsSchema } from './schemas/variants.js';\nimport { validateParamOverrides } from './validation/params.js';\n\nexport { replayableAssetsSchema } from './schemas/assets.js';\n\n/**\n * Runtime schema for the human-authored `replayable.config.ts` contract.\n *\n * Parsing trims meaningful strings; applies the default audio capability,\n * background color, entry, version, and preview network; and rejects unknown\n * fields.\n */\nexport const replayableConfigSchema = z\n .strictObject({\n assets: replayableAssetsSchema,\n audio: audioSchema,\n backgroundColor: backgroundColorSchema,\n build: buildSchema,\n completion: completionSchema,\n controls: controlsSchema,\n devtools: devtoolsSchema,\n entry: requiredStringSchema.default('src/main.ts'),\n localization: localizationSchema,\n name: requiredStringSchema,\n networks: networksSchema,\n params: paramsSchema,\n screen: screenSchema,\n store: storeSchema,\n versions: versionsSchema,\n })\n .superRefine(({ networks, params, versions }, context) => {\n validateParamOverrides('networks', networks, params, context);\n validateParamOverrides('versions', versions, params, context);\n });\n","import type { ReplayableConfig, ReplayableConfigInput } from '#types/config.js';\n\nimport { replayableConfigSchema } from './schema.js';\n\n/**\n * Validates an authored Replayable project configuration and applies defaults.\n *\n * @param input - Human-authored Replayable configuration.\n * @returns The validated and normalized project configuration.\n * @throws When a field is missing, unknown, or invalid.\n */\nexport function defineConfig(input: ReplayableConfigInput): ReplayableConfig {\n return replayableConfigSchema.parse(input);\n}\n","import { networkSchema } from '#config/schemas/variants.js';\nimport type { ReplayableConfig } from '#types/config.js';\nimport type { PlayableVariant, VariantOverride, VariantSelection } from '#types/variant.js';\n\nconst ALL_SOUNDS_PATTERN = 'sounds/**';\n\n/**\n * Expands one project configuration into every version/network/language combination.\n *\n * Every returned variant contains resolved values. Base parameters are extended\n * by network parameters and then version parameters, making the version the\n * most specific override. Asset exclusions follow the same precedence.\n *\n * @param config - Validated Replayable project configuration.\n * @returns The ordered concrete playable variants.\n */\nexport function createVariants(config: ReplayableConfig): PlayableVariant[] {\n const variants: PlayableVariant[] = [];\n\n for (const [version, versionOverride] of Object.entries(config.versions)) {\n for (const network of networkSchema.options) {\n const networkOverride = config.networks[network];\n\n if (networkOverride === undefined) {\n continue;\n }\n\n for (const language of config.localization.languages) {\n variants.push(\n createPlayableVariant(config, {\n language,\n network,\n networkOverride,\n version,\n versionOverride,\n }),\n );\n }\n }\n }\n\n return variants;\n}\n\n/** Creates one fully concrete playable from the three configured dimensions. */\nfunction createPlayableVariant(\n config: ReplayableConfig,\n selection: VariantSelection,\n): PlayableVariant {\n const { language, network, networkOverride, version, versionOverride } = selection;\n const audio = resolveAudio(config.audio, networkOverride.audio, versionOverride.audio);\n const localization = {\n language,\n fallback: config.localization.fallback,\n };\n\n return {\n assets: resolveAssetConfig(\n config.assets,\n localization,\n audio,\n networkOverride.assets,\n versionOverride.assets,\n ),\n audio,\n backgroundColor: config.backgroundColor,\n completion: resolveCompletion(\n config.completion,\n networkOverride.completion,\n versionOverride.completion,\n ),\n controls: config.controls,\n devtools: config.devtools,\n entry: config.entry,\n id: `${version}/${network}/${language}`,\n localization,\n network,\n params: resolveParams(config.params, networkOverride.params, versionOverride.params),\n projectName: config.name,\n screen: config.screen,\n store: config.store,\n version,\n };\n}\n\n/** Resolves each completion timer independently using project, network, then version precedence. */\nfunction resolveCompletion(\n project: ReplayableConfig['completion'],\n network: VariantOverride['completion'],\n version: VariantOverride['completion'],\n): PlayableVariant['completion'] {\n const duration = resolveCompletionDuration(\n project.duration,\n network?.duration,\n version?.duration,\n );\n const inactivity = resolveCompletionDuration(\n project.inactivity,\n network?.inactivity,\n version?.inactivity,\n );\n const completion: { duration?: number; inactivity?: number } = {};\n\n if (duration !== undefined) {\n completion.duration = duration;\n }\n\n if (inactivity !== undefined) {\n completion.inactivity = inactivity;\n }\n\n return completion;\n}\n\n/** Selects the most specific timer value and removes an explicit `false`. */\nfunction resolveCompletionDuration(\n project: number | undefined,\n network: number | false | undefined,\n version: number | false | undefined,\n): number | undefined {\n const resolved = version ?? network ?? project;\n\n return resolved === false ? undefined : resolved;\n}\n\n/** Completes the shared asset configuration for one fixed-language variant. */\nfunction resolveAssetConfig(\n base: ReplayableConfig['assets'],\n localization: PlayableVariant['localization'],\n audio: boolean,\n network: VariantOverride['assets'],\n version: VariantOverride['assets'],\n): PlayableVariant['assets'] {\n const exclude = [...base.exclude, ...(network?.exclude ?? []), ...(version?.exclude ?? [])];\n\n // A silent variant must not process or emit sound files. Preserve an authored\n // all-sounds exclusion without adding the same pattern a second time.\n if (!audio && !exclude.includes(ALL_SOUNDS_PATTERN)) {\n exclude.push(ALL_SOUNDS_PATTERN);\n }\n\n return {\n ...base,\n localization,\n exclude,\n };\n}\n\n/** Resolves audio as a capability that any configuration dimension may disable. */\nfunction resolveAudio(\n project: boolean,\n network: VariantOverride['audio'],\n version: VariantOverride['audio'],\n): boolean {\n return project && network !== false && version !== false;\n}\n\n/** Extracts authored defaults, then applies network and version value overrides. */\nfunction resolveParams(\n definitions: ReplayableConfig['params'],\n network: VariantOverride['params'],\n version: VariantOverride['params'],\n): PlayableVariant['params'] {\n const defaults = Object.fromEntries(\n Object.entries(definitions).map(([name, definition]) => [name, definition.default]),\n );\n\n return {\n ...defaults,\n ...network,\n ...version,\n };\n}\n"],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,54 @@
1
+ {
2
+ "name": "@replayablejs/config",
3
+ "version": "0.1.0-alpha.0",
4
+ "description": "Validated Replayable project configuration and playable variant expansion",
5
+ "homepage": "https://github.com/replayablejs/replayable#readme",
6
+ "bugs": {
7
+ "url": "https://github.com/replayablejs/replayable/issues"
8
+ },
9
+ "license": "MIT",
10
+ "repository": {
11
+ "type": "git",
12
+ "url": "git+https://github.com/replayablejs/replayable.git",
13
+ "directory": "packages/config"
14
+ },
15
+ "files": [
16
+ "dist"
17
+ ],
18
+ "type": "module",
19
+ "sideEffects": false,
20
+ "imports": {
21
+ "#config/*": "./src/config/*",
22
+ "#variants/*": "./src/variants/*",
23
+ "#types/*": "./src/types/*"
24
+ },
25
+ "exports": {
26
+ ".": {
27
+ "types": "./dist/index.d.mts",
28
+ "import": "./dist/index.mjs"
29
+ }
30
+ },
31
+ "publishConfig": {
32
+ "access": "public"
33
+ },
34
+ "dependencies": {
35
+ "zod": "4.4.3",
36
+ "@replayablejs/assets": "0.1.0-alpha.0"
37
+ },
38
+ "devDependencies": {
39
+ "@types/node": "26.2.0",
40
+ "tsdown": "0.22.14",
41
+ "typescript": "7.0.2",
42
+ "vitest": "4.1.10"
43
+ },
44
+ "engines": {
45
+ "node": ">=24.0.0"
46
+ },
47
+ "scripts": {
48
+ "build": "tsdown",
49
+ "dev": "tsdown --watch",
50
+ "lint": "oxlint --type-aware --max-warnings 0 .",
51
+ "test": "vitest run",
52
+ "typecheck": "tsc --noEmit"
53
+ }
54
+ }