@player-tools/fluent 0.12.1--canary.241.6077

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 (134) hide show
  1. package/dist/cjs/index.cjs +2396 -0
  2. package/dist/cjs/index.cjs.map +1 -0
  3. package/dist/index.legacy-esm.js +2276 -0
  4. package/dist/index.mjs +2276 -0
  5. package/dist/index.mjs.map +1 -0
  6. package/package.json +38 -0
  7. package/src/core/base-builder/__tests__/fluent-builder-base.test.ts +2423 -0
  8. package/src/core/base-builder/__tests__/fluent-partial.test.ts +179 -0
  9. package/src/core/base-builder/__tests__/id-generator.test.ts +658 -0
  10. package/src/core/base-builder/__tests__/registry.test.ts +534 -0
  11. package/src/core/base-builder/__tests__/resolution-mixed-arrays.test.ts +319 -0
  12. package/src/core/base-builder/__tests__/resolution-pipeline.test.ts +416 -0
  13. package/src/core/base-builder/__tests__/resolution-switches.test.ts +468 -0
  14. package/src/core/base-builder/__tests__/resolution-templates.test.ts +255 -0
  15. package/src/core/base-builder/__tests__/switch.test.ts +815 -0
  16. package/src/core/base-builder/__tests__/template.test.ts +596 -0
  17. package/src/core/base-builder/__tests__/value-extraction.test.ts +200 -0
  18. package/src/core/base-builder/__tests__/value-storage.test.ts +459 -0
  19. package/src/core/base-builder/conditional/index.ts +64 -0
  20. package/src/core/base-builder/context.ts +152 -0
  21. package/src/core/base-builder/errors.ts +69 -0
  22. package/src/core/base-builder/fluent-builder-base.ts +308 -0
  23. package/src/core/base-builder/guards.ts +137 -0
  24. package/src/core/base-builder/id/generator.ts +290 -0
  25. package/src/core/base-builder/id/registry.ts +152 -0
  26. package/src/core/base-builder/index.ts +72 -0
  27. package/src/core/base-builder/resolution/path-resolver.ts +116 -0
  28. package/src/core/base-builder/resolution/pipeline.ts +103 -0
  29. package/src/core/base-builder/resolution/steps/__tests__/nested-asset-wrappers.test.ts +206 -0
  30. package/src/core/base-builder/resolution/steps/asset-id.ts +77 -0
  31. package/src/core/base-builder/resolution/steps/asset-wrappers.ts +64 -0
  32. package/src/core/base-builder/resolution/steps/builders.ts +84 -0
  33. package/src/core/base-builder/resolution/steps/mixed-arrays.ts +95 -0
  34. package/src/core/base-builder/resolution/steps/nested-asset-wrappers.ts +124 -0
  35. package/src/core/base-builder/resolution/steps/static-values.ts +35 -0
  36. package/src/core/base-builder/resolution/steps/switches.ts +71 -0
  37. package/src/core/base-builder/resolution/steps/templates.ts +40 -0
  38. package/src/core/base-builder/resolution/value-resolver.ts +333 -0
  39. package/src/core/base-builder/storage/auxiliary-storage.ts +82 -0
  40. package/src/core/base-builder/storage/value-storage.ts +282 -0
  41. package/src/core/base-builder/types.ts +266 -0
  42. package/src/core/base-builder/utils.ts +10 -0
  43. package/src/core/flow/__tests__/index.test.ts +292 -0
  44. package/src/core/flow/index.ts +118 -0
  45. package/src/core/index.ts +8 -0
  46. package/src/core/mocks/generated/action.builder.ts +92 -0
  47. package/src/core/mocks/generated/choice-item.builder.ts +120 -0
  48. package/src/core/mocks/generated/choice.builder.ts +134 -0
  49. package/src/core/mocks/generated/collection.builder.ts +93 -0
  50. package/src/core/mocks/generated/field-collection.builder.ts +86 -0
  51. package/src/core/mocks/generated/index.ts +10 -0
  52. package/src/core/mocks/generated/info.builder.ts +64 -0
  53. package/src/core/mocks/generated/input.builder.ts +63 -0
  54. package/src/core/mocks/generated/overview-collection.builder.ts +65 -0
  55. package/src/core/mocks/generated/splash-collection.builder.ts +93 -0
  56. package/src/core/mocks/generated/text.builder.ts +47 -0
  57. package/src/core/mocks/index.ts +1 -0
  58. package/src/core/mocks/types/action.ts +92 -0
  59. package/src/core/mocks/types/choice.ts +129 -0
  60. package/src/core/mocks/types/collection.ts +140 -0
  61. package/src/core/mocks/types/info.ts +7 -0
  62. package/src/core/mocks/types/input.ts +7 -0
  63. package/src/core/mocks/types/text.ts +5 -0
  64. package/src/core/schema/__tests__/index.test.ts +127 -0
  65. package/src/core/schema/index.ts +195 -0
  66. package/src/core/schema/types.ts +7 -0
  67. package/src/core/switch/__tests__/index.test.ts +156 -0
  68. package/src/core/switch/index.ts +81 -0
  69. package/src/core/tagged-template/README.md +448 -0
  70. package/src/core/tagged-template/__tests__/extract-bindings-from-schema.test.ts +207 -0
  71. package/src/core/tagged-template/__tests__/index.test.ts +190 -0
  72. package/src/core/tagged-template/__tests__/schema-std-integration.test.ts +580 -0
  73. package/src/core/tagged-template/binding.ts +95 -0
  74. package/src/core/tagged-template/expression.ts +92 -0
  75. package/src/core/tagged-template/extract-bindings-from-schema.ts +120 -0
  76. package/src/core/tagged-template/index.ts +5 -0
  77. package/src/core/tagged-template/std.ts +472 -0
  78. package/src/core/tagged-template/types.ts +123 -0
  79. package/src/core/template/__tests__/index.test.ts +380 -0
  80. package/src/core/template/index.ts +196 -0
  81. package/src/core/utils/index.ts +160 -0
  82. package/src/fp/README.md +411 -0
  83. package/src/fp/__tests__/index.test.ts +1178 -0
  84. package/src/fp/index.ts +386 -0
  85. package/src/gen/common.ts +15 -0
  86. package/src/index.ts +5 -0
  87. package/src/types.ts +203 -0
  88. package/types/core/base-builder/conditional/index.d.ts +21 -0
  89. package/types/core/base-builder/context.d.ts +39 -0
  90. package/types/core/base-builder/errors.d.ts +45 -0
  91. package/types/core/base-builder/fluent-builder-base.d.ts +147 -0
  92. package/types/core/base-builder/guards.d.ts +58 -0
  93. package/types/core/base-builder/id/generator.d.ts +69 -0
  94. package/types/core/base-builder/id/registry.d.ts +93 -0
  95. package/types/core/base-builder/index.d.ts +9 -0
  96. package/types/core/base-builder/resolution/path-resolver.d.ts +15 -0
  97. package/types/core/base-builder/resolution/pipeline.d.ts +27 -0
  98. package/types/core/base-builder/resolution/steps/asset-id.d.ts +14 -0
  99. package/types/core/base-builder/resolution/steps/asset-wrappers.d.ts +14 -0
  100. package/types/core/base-builder/resolution/steps/builders.d.ts +14 -0
  101. package/types/core/base-builder/resolution/steps/mixed-arrays.d.ts +14 -0
  102. package/types/core/base-builder/resolution/steps/nested-asset-wrappers.d.ts +14 -0
  103. package/types/core/base-builder/resolution/steps/static-values.d.ts +14 -0
  104. package/types/core/base-builder/resolution/steps/switches.d.ts +15 -0
  105. package/types/core/base-builder/resolution/steps/templates.d.ts +14 -0
  106. package/types/core/base-builder/resolution/value-resolver.d.ts +62 -0
  107. package/types/core/base-builder/storage/auxiliary-storage.d.ts +50 -0
  108. package/types/core/base-builder/storage/value-storage.d.ts +82 -0
  109. package/types/core/base-builder/types.d.ts +183 -0
  110. package/types/core/base-builder/utils.d.ts +2 -0
  111. package/types/core/flow/index.d.ts +23 -0
  112. package/types/core/index.d.ts +8 -0
  113. package/types/core/mocks/index.d.ts +2 -0
  114. package/types/core/mocks/types/action.d.ts +58 -0
  115. package/types/core/mocks/types/choice.d.ts +95 -0
  116. package/types/core/mocks/types/collection.d.ts +102 -0
  117. package/types/core/mocks/types/info.d.ts +7 -0
  118. package/types/core/mocks/types/input.d.ts +7 -0
  119. package/types/core/mocks/types/text.d.ts +5 -0
  120. package/types/core/schema/index.d.ts +34 -0
  121. package/types/core/schema/types.d.ts +5 -0
  122. package/types/core/switch/index.d.ts +21 -0
  123. package/types/core/tagged-template/binding.d.ts +19 -0
  124. package/types/core/tagged-template/expression.d.ts +11 -0
  125. package/types/core/tagged-template/extract-bindings-from-schema.d.ts +7 -0
  126. package/types/core/tagged-template/index.d.ts +6 -0
  127. package/types/core/tagged-template/std.d.ts +174 -0
  128. package/types/core/tagged-template/types.d.ts +69 -0
  129. package/types/core/template/index.d.ts +97 -0
  130. package/types/core/utils/index.d.ts +47 -0
  131. package/types/fp/index.d.ts +149 -0
  132. package/types/gen/common.d.ts +6 -0
  133. package/types/index.d.ts +3 -0
  134. package/types/types.d.ts +163 -0
@@ -0,0 +1,319 @@
1
+ import { describe, test, expect, beforeEach, vi } from "vitest";
2
+ import type {
3
+ BaseBuildContext,
4
+ FluentBuilder,
5
+ MixedArrayMetadata,
6
+ } from "../types";
7
+ import { FLUENT_BUILDER_SYMBOL } from "../types";
8
+ import { ValueStorage } from "../storage/value-storage";
9
+ import { resolveMixedArrays } from "../resolution/steps/mixed-arrays";
10
+
11
+ // Create a mock builder that satisfies the FluentBuilder interface
12
+ function createMockBuilder<T = { id: string; type: string }>(
13
+ buildResult: T,
14
+ ): FluentBuilder<T, BaseBuildContext> {
15
+ const builder = {
16
+ [FLUENT_BUILDER_SYMBOL]: true as const,
17
+ build: vi.fn((ctx?: BaseBuildContext) => ({
18
+ ...buildResult,
19
+ id: ctx?.parentId
20
+ ? `${ctx.parentId}-${(buildResult as { type?: string }).type ?? "unknown"}`
21
+ : (buildResult as { id?: string }).id,
22
+ })) as () => T,
23
+ };
24
+ return builder as FluentBuilder<T, BaseBuildContext>;
25
+ }
26
+
27
+ describe("resolveMixedArrays - Array Resolution", () => {
28
+ let storage: ValueStorage<{ values: unknown[] }>;
29
+
30
+ beforeEach(() => {
31
+ storage = new ValueStorage();
32
+ });
33
+
34
+ test("resolves array with all builders", () => {
35
+ const builder1 = createMockBuilder({
36
+ id: "1",
37
+ type: "text",
38
+ value: "first",
39
+ });
40
+ const builder2 = createMockBuilder({
41
+ id: "2",
42
+ type: "text",
43
+ value: "second",
44
+ });
45
+
46
+ storage.set("values", [builder1, builder2]);
47
+
48
+ const result: Record<string, unknown> = {};
49
+ const context: BaseBuildContext = { parentId: "parent" };
50
+
51
+ resolveMixedArrays(storage, result, context);
52
+
53
+ expect(result.values).toBeInstanceOf(Array);
54
+ expect((result.values as unknown[]).length).toBe(2);
55
+ });
56
+
57
+ test("resolves array with mixed builders and static values", () => {
58
+ const builder = createMockBuilder({ id: "1", type: "text" });
59
+ const staticValue = { id: "static", type: "text", value: "static" };
60
+
61
+ storage.set("values", [builder, staticValue]);
62
+
63
+ const result: Record<string, unknown> = {};
64
+ const context: BaseBuildContext = { parentId: "parent" };
65
+
66
+ resolveMixedArrays(storage, result, context);
67
+
68
+ expect(result.values).toBeInstanceOf(Array);
69
+ expect((result.values as unknown[]).length).toBe(2);
70
+ });
71
+
72
+ test("filters null/undefined values from array", () => {
73
+ const builder = createMockBuilder({ id: "1", type: "text" });
74
+ const staticValue = { id: "static", type: "text" };
75
+
76
+ // Mock the storage with null/undefined values
77
+ const mixedArrayMeta: MixedArrayMetadata = {
78
+ array: [builder, null, undefined, staticValue],
79
+ builderIndices: new Set([0]),
80
+ objectIndices: new Set(),
81
+ };
82
+
83
+ // Directly inject the mixed array metadata
84
+ (
85
+ storage as unknown as { mixedArrays: Map<string, MixedArrayMetadata> }
86
+ ).mixedArrays = new Map([["values", mixedArrayMeta]]);
87
+
88
+ const result: Record<string, unknown> = {};
89
+ const context: BaseBuildContext = { parentId: "parent" };
90
+
91
+ resolveMixedArrays(storage, result, context);
92
+
93
+ // Should filter out null and undefined
94
+ expect(result.values).toBeInstanceOf(Array);
95
+ expect((result.values as unknown[]).length).toBe(2);
96
+ });
97
+
98
+ test("preserves order after filtering", () => {
99
+ const builder1 = createMockBuilder({ id: "1", type: "text" });
100
+ const builder2 = createMockBuilder({ id: "2", type: "text" });
101
+ const staticValue = { id: "static", type: "text" };
102
+
103
+ const mixedArrayMeta: MixedArrayMetadata = {
104
+ array: [null, builder1, undefined, staticValue, null, builder2],
105
+ builderIndices: new Set([1, 5]),
106
+ objectIndices: new Set(),
107
+ };
108
+
109
+ (
110
+ storage as unknown as { mixedArrays: Map<string, MixedArrayMetadata> }
111
+ ).mixedArrays = new Map([["values", mixedArrayMeta]]);
112
+
113
+ const result: Record<string, unknown> = {};
114
+ const context: BaseBuildContext = { parentId: "parent" };
115
+
116
+ resolveMixedArrays(storage, result, context);
117
+
118
+ expect(result.values).toBeInstanceOf(Array);
119
+ expect((result.values as unknown[]).length).toBe(3);
120
+ // Order should be: builder1, staticValue, builder2
121
+ });
122
+ });
123
+
124
+ describe("resolveMixedArrays - AssetWrapper Objects", () => {
125
+ let storage: ValueStorage<{ values: unknown }>;
126
+
127
+ beforeEach(() => {
128
+ storage = new ValueStorage();
129
+ });
130
+
131
+ test("handles AssetWrapper format objects containing builders", () => {
132
+ const builder = createMockBuilder({ id: "1", type: "text" });
133
+
134
+ // AssetWrapper format: { asset: builder }
135
+ storage.set("values", { asset: builder });
136
+
137
+ const result: Record<string, unknown> = {};
138
+ const context: BaseBuildContext = { parentId: "parent" };
139
+
140
+ // resolveMixedArrays handles mixed arrays, not AssetWrapper objects directly
141
+ // Those are handled by resolveAssetWrappers step
142
+ resolveMixedArrays(storage, result, context);
143
+
144
+ // No mixed array to process, result should be empty
145
+ expect(Object.keys(result).length).toBe(0);
146
+ });
147
+
148
+ test("processes array containing AssetWrapper-like objects", () => {
149
+ const builder = createMockBuilder({ id: "1", type: "text" });
150
+ const wrapperObject = { asset: builder };
151
+
152
+ storage.set("values", [wrapperObject]);
153
+
154
+ const result: Record<string, unknown> = {};
155
+ const context: BaseBuildContext = { parentId: "parent" };
156
+
157
+ resolveMixedArrays(storage, result, context);
158
+
159
+ // Array with nested builders should be processed
160
+ expect(result.values).toBeInstanceOf(Array);
161
+ expect((result.values as unknown[]).length).toBe(1);
162
+ });
163
+
164
+ test("handles mixed array with both builders and AssetWrapper objects", () => {
165
+ const builder1 = createMockBuilder({ id: "1", type: "text" });
166
+ const builder2 = createMockBuilder({ id: "2", type: "text" });
167
+ const wrapperObject = { asset: builder2 };
168
+
169
+ storage.set("values", [builder1, wrapperObject, "static"]);
170
+
171
+ const result: Record<string, unknown> = {};
172
+ const context: BaseBuildContext = { parentId: "parent" };
173
+
174
+ resolveMixedArrays(storage, result, context);
175
+
176
+ expect(result.values).toBeInstanceOf(Array);
177
+ expect((result.values as unknown[]).length).toBe(3);
178
+ });
179
+ });
180
+
181
+ describe("resolveMixedArrays - Context Handling", () => {
182
+ let storage: ValueStorage<{ values: unknown[] }>;
183
+
184
+ beforeEach(() => {
185
+ storage = new ValueStorage();
186
+ });
187
+
188
+ test("generates indexed slot names (key-0, key-1, ...)", () => {
189
+ const builder1 = createMockBuilder({ id: "1", type: "text" });
190
+ const builder2 = createMockBuilder({ id: "2", type: "text" });
191
+
192
+ storage.set("values", [builder1, builder2]);
193
+
194
+ const result: Record<string, unknown> = {};
195
+ const context: BaseBuildContext = { parentId: "parent" };
196
+
197
+ resolveMixedArrays(storage, result, context);
198
+
199
+ // Builders should receive context with indexed slot names
200
+ expect(builder1.build).toHaveBeenCalled();
201
+ expect(builder2.build).toHaveBeenCalled();
202
+ });
203
+
204
+ test("handles undefined context gracefully", () => {
205
+ const builder = createMockBuilder({ id: "1", type: "text" });
206
+
207
+ storage.set("values", [builder]);
208
+
209
+ const result: Record<string, unknown> = {};
210
+
211
+ // Should not throw when context is undefined
212
+ expect(() => {
213
+ resolveMixedArrays(storage, result, undefined);
214
+ }).not.toThrow();
215
+
216
+ expect(result.values).toBeInstanceOf(Array);
217
+ });
218
+
219
+ test("processes multiple mixed arrays", () => {
220
+ const builder1 = createMockBuilder({ id: "1", type: "text" });
221
+ const builder2 = createMockBuilder({ id: "2", type: "action" });
222
+
223
+ const storage2 = new ValueStorage<{
224
+ items: unknown[];
225
+ actions: unknown[];
226
+ }>();
227
+ storage2.set("items", [builder1, { id: "static", type: "text" }]);
228
+ storage2.set("actions", [builder2]);
229
+
230
+ const result: Record<string, unknown> = {};
231
+ const context: BaseBuildContext = { parentId: "parent" };
232
+
233
+ resolveMixedArrays(storage2, result, context);
234
+
235
+ expect(result.items).toBeInstanceOf(Array);
236
+ expect(result.actions).toBeInstanceOf(Array);
237
+ expect((result.items as unknown[]).length).toBe(2);
238
+ expect((result.actions as unknown[]).length).toBe(1);
239
+ });
240
+ });
241
+
242
+ describe("resolveMixedArrays - Empty and Edge Cases", () => {
243
+ test("handles empty storage", () => {
244
+ const storage = new ValueStorage<{ values: unknown[] }>();
245
+ const result: Record<string, unknown> = {};
246
+ const context: BaseBuildContext = { parentId: "parent" };
247
+
248
+ expect(() => {
249
+ resolveMixedArrays(storage, result, context);
250
+ }).not.toThrow();
251
+
252
+ expect(result).toEqual({});
253
+ });
254
+
255
+ test("handles empty array", () => {
256
+ const storage = new ValueStorage<{ values: unknown[] }>();
257
+
258
+ const mixedArrayMeta: MixedArrayMetadata = {
259
+ array: [],
260
+ builderIndices: new Set(),
261
+ objectIndices: new Set(),
262
+ };
263
+
264
+ (
265
+ storage as unknown as { mixedArrays: Map<string, MixedArrayMetadata> }
266
+ ).mixedArrays = new Map([["values", mixedArrayMeta]]);
267
+
268
+ const result: Record<string, unknown> = {};
269
+ const context: BaseBuildContext = { parentId: "parent" };
270
+
271
+ resolveMixedArrays(storage, result, context);
272
+
273
+ expect(result.values).toEqual([]);
274
+ });
275
+
276
+ test("handles array with only null/undefined", () => {
277
+ const storage = new ValueStorage<{ values: unknown[] }>();
278
+
279
+ const mixedArrayMeta: MixedArrayMetadata = {
280
+ array: [null, undefined, null],
281
+ builderIndices: new Set(),
282
+ objectIndices: new Set(),
283
+ };
284
+
285
+ (
286
+ storage as unknown as { mixedArrays: Map<string, MixedArrayMetadata> }
287
+ ).mixedArrays = new Map([["values", mixedArrayMeta]]);
288
+
289
+ const result: Record<string, unknown> = {};
290
+ const context: BaseBuildContext = { parentId: "parent" };
291
+
292
+ resolveMixedArrays(storage, result, context);
293
+
294
+ expect(result.values).toEqual([]);
295
+ });
296
+
297
+ test("handles deeply nested objects in array", () => {
298
+ const storage = new ValueStorage<{ values: unknown[] }>();
299
+ const builder = createMockBuilder({ id: "1", type: "text" });
300
+
301
+ const nestedObject = {
302
+ nested: {
303
+ deep: {
304
+ builder,
305
+ },
306
+ },
307
+ };
308
+
309
+ storage.set("values", [nestedObject]);
310
+
311
+ const result: Record<string, unknown> = {};
312
+ const context: BaseBuildContext = { parentId: "parent" };
313
+
314
+ resolveMixedArrays(storage, result, context);
315
+
316
+ expect(result.values).toBeInstanceOf(Array);
317
+ expect((result.values as unknown[]).length).toBe(1);
318
+ });
319
+ });