docusaurus-plugin-generate-schema-docs 1.7.1 → 1.8.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.
@@ -0,0 +1,853 @@
1
+ export const DEFAULT_SNIPPET_TARGET_ID = 'web-datalayer-js';
2
+ export const FIREBASE_SNIPPET_SOURCES = [
3
+ {
4
+ id: 'firebase-analytics-android-events',
5
+ url: 'https://firebase.google.com/docs/analytics/android/events',
6
+ reviewedAt: '2026-03-05',
7
+ },
8
+ {
9
+ id: 'firebase-analytics-ios-events',
10
+ url: 'https://firebase.google.com/docs/analytics/ios/events',
11
+ reviewedAt: '2026-03-05',
12
+ },
13
+ {
14
+ id: 'firebase-analytics-screenviews',
15
+ url: 'https://firebase.google.com/docs/analytics/screenviews',
16
+ reviewedAt: '2026-03-05',
17
+ },
18
+ {
19
+ id: 'firebase-android-event-reference',
20
+ url: 'https://firebase.google.com/docs/reference/android/com/google/firebase/analytics/FirebaseAnalytics.Event',
21
+ reviewedAt: '2026-03-05',
22
+ },
23
+ {
24
+ id: 'firebase-android-param-reference',
25
+ url: 'https://firebase.google.com/docs/reference/android/com/google/firebase/analytics/FirebaseAnalytics.Param',
26
+ reviewedAt: '2026-03-05',
27
+ },
28
+ {
29
+ id: 'firebase-ios-constants-reference',
30
+ url: 'https://firebase.google.com/docs/reference/ios/firebaseanalytics/api/reference/Constants',
31
+ reviewedAt: '2026-03-05',
32
+ },
33
+ {
34
+ id: 'firebase-android-user-property-reference',
35
+ url: 'https://firebase.google.com/docs/reference/android/com/google/firebase/analytics/FirebaseAnalytics.UserProperty',
36
+ reviewedAt: '2026-03-05',
37
+ },
38
+ ];
39
+
40
+ const FIREBASE_PREDEFINED_EVENTS = new Set([
41
+ 'ad_impression',
42
+ 'add_payment_info',
43
+ 'add_shipping_info',
44
+ 'add_to_cart',
45
+ 'add_to_wishlist',
46
+ 'app_open',
47
+ 'begin_checkout',
48
+ 'campaign_details',
49
+ 'earn_virtual_currency',
50
+ 'generate_lead',
51
+ 'in_app_purchase',
52
+ 'join_group',
53
+ 'level_end',
54
+ 'level_start',
55
+ 'level_up',
56
+ 'login',
57
+ 'post_score',
58
+ 'purchase',
59
+ 'refund',
60
+ 'remove_from_cart',
61
+ 'screen_view',
62
+ 'search',
63
+ 'select_content',
64
+ 'select_item',
65
+ 'select_promotion',
66
+ 'share',
67
+ 'sign_up',
68
+ 'spend_virtual_currency',
69
+ 'tutorial_begin',
70
+ 'tutorial_complete',
71
+ 'unlock_achievement',
72
+ 'view_cart',
73
+ 'view_item',
74
+ 'view_item_list',
75
+ 'view_promotion',
76
+ 'view_search_results',
77
+ ]);
78
+
79
+ const FIREBASE_PREDEFINED_PARAMS = new Set([
80
+ 'achievement_id',
81
+ 'aclid',
82
+ 'ad_format',
83
+ 'ad_platform',
84
+ 'ad_source',
85
+ 'ad_unit_name',
86
+ 'affiliation',
87
+ 'campaign',
88
+ 'campaign_id',
89
+ 'character',
90
+ 'content',
91
+ 'content_type',
92
+ 'coupon',
93
+ 'cp1',
94
+ 'creative_name',
95
+ 'creative_format',
96
+ 'creative_slot',
97
+ 'currency',
98
+ 'destination',
99
+ 'discount',
100
+ 'end_date',
101
+ 'extend_session',
102
+ 'flight_number',
103
+ 'free_trial',
104
+ 'group_id',
105
+ 'index',
106
+ 'items',
107
+ 'item_brand',
108
+ 'item_category',
109
+ 'item_category2',
110
+ 'item_category3',
111
+ 'item_category4',
112
+ 'item_category5',
113
+ 'item_id',
114
+ 'item_list_id',
115
+ 'item_list_name',
116
+ 'item_name',
117
+ 'item_variant',
118
+ 'level',
119
+ 'level_name',
120
+ 'location',
121
+ 'location_id',
122
+ 'medium',
123
+ 'method',
124
+ 'marketing_tactic',
125
+ 'number_of_nights',
126
+ 'number_of_passengers',
127
+ 'number_of_rooms',
128
+ 'origin',
129
+ 'payment_type',
130
+ 'price',
131
+ 'price_is_discounted',
132
+ 'product_id',
133
+ 'product_name',
134
+ 'promotion_id',
135
+ 'promotion_name',
136
+ 'quantity',
137
+ 'score',
138
+ 'screen_class',
139
+ 'screen_name',
140
+ 'search_term',
141
+ 'shipping',
142
+ 'shipping_tier',
143
+ 'source',
144
+ 'source_platform',
145
+ 'start_date',
146
+ 'subscription',
147
+ 'success',
148
+ 'tax',
149
+ 'term',
150
+ 'transaction_id',
151
+ 'travel_class',
152
+ 'value',
153
+ 'virtual_currency_name',
154
+ ]);
155
+
156
+ const FIREBASE_PARAM_ALIASES = {
157
+ firebase_screen: 'screen_name',
158
+ firebase_screen_class: 'screen_class',
159
+ };
160
+
161
+ const FIREBASE_PARAM_CONSTANTS = {
162
+ aclid: {
163
+ kotlin: 'FirebaseAnalytics.Param.ACLID',
164
+ java: 'FirebaseAnalytics.Param.ACLID',
165
+ swift: 'AnalyticsParameterAdNetworkClickID',
166
+ objc: 'kFIRParameterAdNetworkClickID',
167
+ },
168
+ };
169
+
170
+ const FIREBASE_USER_PROPERTY_CONSTANTS = {
171
+ allow_personalized_ads: {
172
+ kotlin: 'FirebaseAnalytics.UserProperty.ALLOW_AD_PERSONALIZATION_SIGNALS',
173
+ java: 'FirebaseAnalytics.UserProperty.ALLOW_AD_PERSONALIZATION_SIGNALS',
174
+ swift: 'AnalyticsUserPropertyAllowAdPersonalizationSignals',
175
+ objc: 'kFIRUserPropertyAllowAdPersonalizationSignals',
176
+ },
177
+ sign_up_method: {
178
+ kotlin: 'FirebaseAnalytics.UserProperty.SIGN_UP_METHOD',
179
+ java: 'FirebaseAnalytics.UserProperty.SIGN_UP_METHOD',
180
+ swift: 'AnalyticsUserPropertySignUpMethod',
181
+ objc: 'kFIRUserPropertySignUpMethod',
182
+ },
183
+ };
184
+
185
+ const FIREBASE_USER_PROPERTY_ALIASES = {
186
+ allow_ad_personalization_signals: 'allow_personalized_ads',
187
+ };
188
+
189
+ const FIREBASE_ABBREVIATIONS = {
190
+ aclid: 'ACLID',
191
+ id: 'ID',
192
+ cp1: 'CP1',
193
+ };
194
+
195
+ function toFirebaseUpperSnake(key) {
196
+ return key.toUpperCase();
197
+ }
198
+
199
+ function toFirebasePascalCase(key) {
200
+ return key
201
+ .split('_')
202
+ .filter(Boolean)
203
+ .map((segment) => {
204
+ const abbreviation = FIREBASE_ABBREVIATIONS[segment.toLowerCase()];
205
+ if (abbreviation) return abbreviation;
206
+ return segment.charAt(0).toUpperCase() + segment.slice(1);
207
+ })
208
+ .join('');
209
+ }
210
+
211
+ export const findClearableProperties = (schema) => {
212
+ if (!schema || !schema.properties) return [];
213
+
214
+ return Object.entries(schema.properties)
215
+ .filter(([, definition]) => definition['x-gtm-clear'] === true)
216
+ .map(([key]) => key);
217
+ };
218
+
219
+ function generateWebDataLayerSnippet({
220
+ example,
221
+ schema,
222
+ config = {},
223
+ dataLayerName,
224
+ }) {
225
+ const resolvedDataLayerName =
226
+ dataLayerName || config.dataLayerName || 'dataLayer';
227
+ const clearableProperties = findClearableProperties(schema || {});
228
+ const propertiesToClear = clearableProperties.filter(
229
+ (prop) => prop in example,
230
+ );
231
+
232
+ let codeSnippet = '';
233
+ if (propertiesToClear.length > 0) {
234
+ const resetObject = {};
235
+ propertiesToClear.forEach((prop) => {
236
+ resetObject[prop] = null;
237
+ });
238
+ codeSnippet += `window.${resolvedDataLayerName}.push(${JSON.stringify(
239
+ resetObject,
240
+ null,
241
+ 2,
242
+ )});\n`;
243
+ }
244
+
245
+ codeSnippet += `window.${resolvedDataLayerName}.push(${JSON.stringify(
246
+ example,
247
+ null,
248
+ 2,
249
+ )});`;
250
+
251
+ return codeSnippet;
252
+ }
253
+
254
+ function isPlainObject(value) {
255
+ return (
256
+ value !== null &&
257
+ typeof value === 'object' &&
258
+ !Array.isArray(value) &&
259
+ Object.getPrototypeOf(value) === Object.prototype
260
+ );
261
+ }
262
+
263
+ function toFirebaseParamEntries(example) {
264
+ const entries = [];
265
+ Object.entries(example || {}).forEach(([key, value]) => {
266
+ if (key === 'event' || key === '$schema' || value === undefined) return;
267
+ if (key === 'user_properties') return;
268
+
269
+ entries.push([key, value]);
270
+ });
271
+ return entries;
272
+ }
273
+
274
+ function toFirebaseUserPropertyEntries(example) {
275
+ if (!isPlainObject(example?.user_properties)) return [];
276
+ return Object.entries(example.user_properties).filter(
277
+ ([, value]) => value !== undefined,
278
+ );
279
+ }
280
+
281
+ function getFirebaseEventExpression(eventName, platform) {
282
+ if (FIREBASE_PREDEFINED_EVENTS.has(eventName)) {
283
+ const upper = toFirebaseUpperSnake(eventName);
284
+ const pascal = toFirebasePascalCase(eventName);
285
+ if (platform === 'kotlin' || platform === 'java') {
286
+ return `FirebaseAnalytics.Event.${upper}`;
287
+ }
288
+ if (platform === 'swift') return `AnalyticsEvent${pascal}`;
289
+ if (platform === 'objc') return `kFIREvent${pascal}`;
290
+ }
291
+ if (platform === 'objc') return `@"${escapeObjCString(eventName)}"`;
292
+ return JSON.stringify(eventName);
293
+ }
294
+
295
+ function getFirebaseParamExpression(key, platform) {
296
+ const canonicalKey = FIREBASE_PARAM_ALIASES[key] || key;
297
+ const known = FIREBASE_PARAM_CONSTANTS[canonicalKey]?.[platform];
298
+ if (known) return known;
299
+ if (FIREBASE_PREDEFINED_PARAMS.has(canonicalKey)) {
300
+ const upper = toFirebaseUpperSnake(canonicalKey);
301
+ const pascal = toFirebasePascalCase(canonicalKey);
302
+ if (platform === 'kotlin' || platform === 'java') {
303
+ return `FirebaseAnalytics.Param.${upper}`;
304
+ }
305
+ if (platform === 'swift') return `AnalyticsParameter${pascal}`;
306
+ if (platform === 'objc') return `kFIRParameter${pascal}`;
307
+ }
308
+ if (platform === 'objc') return `@"${escapeObjCString(key)}"`;
309
+ return JSON.stringify(key);
310
+ }
311
+
312
+ function getFirebaseUserPropertyExpression(key, platform) {
313
+ const canonicalKey = FIREBASE_USER_PROPERTY_ALIASES[key] || key;
314
+ const known = FIREBASE_USER_PROPERTY_CONSTANTS[canonicalKey]?.[platform];
315
+ if (known) return known;
316
+ if (platform === 'objc') return `@"${escapeObjCString(key)}"`;
317
+ return JSON.stringify(key);
318
+ }
319
+
320
+ function getFirebaseValueTypeLabel(value) {
321
+ if (value === null) return 'null';
322
+ if (Array.isArray(value)) return 'array';
323
+ return typeof value;
324
+ }
325
+
326
+ function createFirebaseShapeError({ targetId, fieldPath, value, expected }) {
327
+ return new Error(
328
+ `[${targetId}] Unsupported Firebase payload at "${fieldPath}": got ${getFirebaseValueTypeLabel(
329
+ value,
330
+ )}. Expected ${expected}.`,
331
+ );
332
+ }
333
+
334
+ function resolveTypedFirebaseValue({ rawValue, targetId, fieldPath }) {
335
+ if (typeof rawValue === 'string') {
336
+ return { kind: 'string', value: rawValue };
337
+ }
338
+ if (typeof rawValue === 'number') {
339
+ if (Number.isFinite(rawValue) && Number.isInteger(rawValue)) {
340
+ return { kind: 'long', value: rawValue };
341
+ }
342
+ return { kind: 'double', value: rawValue };
343
+ }
344
+ if (typeof rawValue === 'boolean') {
345
+ return { kind: 'long', value: rawValue ? 1 : 0 };
346
+ }
347
+ throw createFirebaseShapeError({
348
+ targetId,
349
+ fieldPath,
350
+ value: rawValue,
351
+ expected: 'primitive (string | number | boolean)',
352
+ });
353
+ }
354
+
355
+ function resolveTypedFirebaseUserPropertyValue({
356
+ rawValue,
357
+ targetId,
358
+ fieldPath,
359
+ }) {
360
+ if (rawValue === null) {
361
+ return { kind: 'null', value: null };
362
+ }
363
+ if (typeof rawValue === 'string') {
364
+ return { kind: 'string', value: rawValue };
365
+ }
366
+ if (typeof rawValue === 'number' || typeof rawValue === 'boolean') {
367
+ return {
368
+ kind: 'string',
369
+ value: String(rawValue),
370
+ };
371
+ }
372
+ throw createFirebaseShapeError({
373
+ targetId,
374
+ fieldPath,
375
+ value: rawValue,
376
+ expected: 'string | number | boolean | null',
377
+ });
378
+ }
379
+
380
+ function buildKotlinItemBundles(items, targetId) {
381
+ const lines = [];
382
+ const names = items.map((_, idx) => `item${idx + 1}`);
383
+
384
+ items.forEach((item, idx) => {
385
+ const varName = names[idx];
386
+ lines.push(`val ${varName} = Bundle().apply {`);
387
+ Object.entries(item).forEach(([key, rawValue]) => {
388
+ const keyExpr = getFirebaseParamExpression(key, 'kotlin');
389
+ const typed = resolveTypedFirebaseValue({
390
+ rawValue,
391
+ targetId,
392
+ fieldPath: `items[${idx}].${key}`,
393
+ });
394
+ if (typed.kind === 'string') {
395
+ lines.push(` putString(${keyExpr}, ${JSON.stringify(typed.value)})`);
396
+ } else if (typed.kind === 'long') {
397
+ lines.push(` putLong(${keyExpr}, ${typed.value}L)`);
398
+ } else {
399
+ lines.push(` putDouble(${keyExpr}, ${typed.value})`);
400
+ }
401
+ });
402
+ lines.push('}');
403
+ });
404
+
405
+ return { lines, names };
406
+ }
407
+
408
+ function buildJavaItemBundles(items, targetId) {
409
+ const lines = [];
410
+ const names = items.map((_, idx) => `item${idx + 1}`);
411
+
412
+ items.forEach((item, idx) => {
413
+ const varName = names[idx];
414
+ lines.push(`Bundle ${varName} = new Bundle();`);
415
+ Object.entries(item).forEach(([key, rawValue]) => {
416
+ const keyExpr = getFirebaseParamExpression(key, 'java');
417
+ const typed = resolveTypedFirebaseValue({
418
+ rawValue,
419
+ targetId,
420
+ fieldPath: `items[${idx}].${key}`,
421
+ });
422
+ if (typed.kind === 'string') {
423
+ lines.push(
424
+ `${varName}.putString(${keyExpr}, ${JSON.stringify(typed.value)});`,
425
+ );
426
+ } else if (typed.kind === 'long') {
427
+ lines.push(`${varName}.putLong(${keyExpr}, ${typed.value}L);`);
428
+ } else {
429
+ lines.push(`${varName}.putDouble(${keyExpr}, ${typed.value});`);
430
+ }
431
+ });
432
+ });
433
+
434
+ return { lines, names };
435
+ }
436
+
437
+ function buildSwiftItems(items, targetId) {
438
+ const lines = [];
439
+ const names = items.map((_, idx) => `item${idx + 1}`);
440
+
441
+ items.forEach((item, idx) => {
442
+ const varName = names[idx];
443
+ lines.push(`var ${varName}: [String: Any] = [`);
444
+ const entries = Object.entries(item);
445
+ entries.forEach(([key, rawValue], entryIndex) => {
446
+ const keyExpr = getFirebaseParamExpression(key, 'swift');
447
+ const typed = resolveTypedFirebaseValue({
448
+ rawValue,
449
+ targetId,
450
+ fieldPath: `items[${idx}].${key}`,
451
+ });
452
+ const comma = entryIndex < entries.length - 1 ? ',' : '';
453
+ if (typed.kind === 'string') {
454
+ lines.push(` ${keyExpr}: ${JSON.stringify(typed.value)}${comma}`);
455
+ } else {
456
+ lines.push(` ${keyExpr}: ${typed.value}${comma}`);
457
+ }
458
+ });
459
+ lines.push(']');
460
+ });
461
+
462
+ return { lines, names };
463
+ }
464
+
465
+ function buildObjcItems(items, targetId) {
466
+ const lines = [];
467
+ const names = items.map((_, idx) => `item${idx + 1}`);
468
+
469
+ items.forEach((item, idx) => {
470
+ const varName = names[idx];
471
+ lines.push(`NSMutableDictionary *${varName} = [@{`);
472
+ const entries = Object.entries(item);
473
+ entries.forEach(([key, rawValue], entryIndex) => {
474
+ const keyExpr = getFirebaseParamExpression(key, 'objc');
475
+ const typed = resolveTypedFirebaseValue({
476
+ rawValue,
477
+ targetId,
478
+ fieldPath: `items[${idx}].${key}`,
479
+ });
480
+ const comma = entryIndex < entries.length - 1 ? ',' : '';
481
+ if (typed.kind === 'string') {
482
+ lines.push(` ${keyExpr}: @"${escapeObjCString(typed.value)}"${comma}`);
483
+ } else {
484
+ lines.push(` ${keyExpr}: @(${typed.value})${comma}`);
485
+ }
486
+ });
487
+ lines.push('} mutableCopy];');
488
+ });
489
+
490
+ return { lines, names };
491
+ }
492
+
493
+ function resolveFirebaseEvent(example, targetId) {
494
+ const eventName = example?.event;
495
+ if (typeof eventName !== 'string' || eventName.trim().length === 0) {
496
+ throw createFirebaseShapeError({
497
+ targetId,
498
+ fieldPath: 'event',
499
+ value: eventName,
500
+ expected: 'non-empty string',
501
+ });
502
+ }
503
+
504
+ const params = [];
505
+ toFirebaseParamEntries(example).forEach(([key, value]) => {
506
+ if (key === 'items') {
507
+ if (
508
+ Array.isArray(value) &&
509
+ value.length > 0 &&
510
+ value.every((item) => isPlainObject(item))
511
+ ) {
512
+ params.push({ key, kind: 'itemsObjectArray', items: value });
513
+ return;
514
+ }
515
+ throw createFirebaseShapeError({
516
+ targetId,
517
+ fieldPath: key,
518
+ value,
519
+ expected: 'non-empty array of objects',
520
+ });
521
+ }
522
+
523
+ if (typeof value === 'string') {
524
+ params.push({ key, kind: 'string', value });
525
+ return;
526
+ }
527
+ if (typeof value === 'number') {
528
+ if (Number.isFinite(value) && Number.isInteger(value)) {
529
+ params.push({ key, kind: 'long', value });
530
+ } else {
531
+ params.push({ key, kind: 'double', value });
532
+ }
533
+ return;
534
+ }
535
+ if (typeof value === 'boolean') {
536
+ params.push({ key, kind: 'long', value: value ? 1 : 0 });
537
+ return;
538
+ }
539
+ throw createFirebaseShapeError({
540
+ targetId,
541
+ fieldPath: key,
542
+ value,
543
+ expected:
544
+ 'primitive (string | number | boolean), or "items" as non-empty array of objects',
545
+ });
546
+ });
547
+
548
+ const userProperties = toFirebaseUserPropertyEntries(example).map(
549
+ ([key, rawValue]) => {
550
+ const typed = resolveTypedFirebaseUserPropertyValue({
551
+ rawValue,
552
+ targetId,
553
+ fieldPath: `user_properties.${key}`,
554
+ });
555
+ return {
556
+ key,
557
+ kind: typed.kind,
558
+ value: typed.value,
559
+ };
560
+ },
561
+ );
562
+
563
+ return {
564
+ eventName,
565
+ params,
566
+ userProperties,
567
+ };
568
+ }
569
+
570
+ function generateAndroidKotlinFirebaseSnippet({ example, targetId }) {
571
+ const { eventName, params, userProperties } = resolveFirebaseEvent(
572
+ example,
573
+ targetId,
574
+ );
575
+ const lines = [];
576
+ const eventExpr = getFirebaseEventExpression(eventName, 'kotlin');
577
+ const itemsParam = params.find((p) => p.kind === 'itemsObjectArray');
578
+ const itemBundles = itemsParam
579
+ ? buildKotlinItemBundles(itemsParam.items, targetId)
580
+ : null;
581
+
582
+ if (itemBundles) {
583
+ lines.push(...itemBundles.lines);
584
+ lines.push('');
585
+ }
586
+
587
+ userProperties.forEach((property) => {
588
+ const keyExpr = getFirebaseUserPropertyExpression(property.key, 'kotlin');
589
+ const valueExpr =
590
+ property.kind === 'null' ? 'null' : JSON.stringify(property.value);
591
+ lines.push(`firebaseAnalytics.setUserProperty(${keyExpr}, ${valueExpr})`);
592
+ });
593
+ if (userProperties.length > 0) {
594
+ lines.push('');
595
+ }
596
+
597
+ lines.push(`firebaseAnalytics.logEvent(${eventExpr}) {`);
598
+ params.forEach((param) => {
599
+ const keyExpr = getFirebaseParamExpression(param.key, 'kotlin');
600
+ if (param.kind === 'itemsObjectArray') {
601
+ lines.push(
602
+ ` param(${keyExpr}, arrayOf(${itemBundles.names.join(', ')}))`,
603
+ );
604
+ return;
605
+ }
606
+ if (param.kind === 'string') {
607
+ lines.push(` param(${keyExpr}, ${JSON.stringify(param.value)})`);
608
+ return;
609
+ }
610
+ if (param.kind === 'long') {
611
+ lines.push(` param(${keyExpr}, ${param.value}L)`);
612
+ return;
613
+ }
614
+ lines.push(` param(${keyExpr}, ${param.value})`);
615
+ });
616
+ lines.push('}');
617
+ return lines.join('\n');
618
+ }
619
+
620
+ function generateAndroidJavaFirebaseSnippet({ example, targetId }) {
621
+ const { eventName, params, userProperties } = resolveFirebaseEvent(
622
+ example,
623
+ targetId,
624
+ );
625
+ const lines = [];
626
+ const eventExpr = getFirebaseEventExpression(eventName, 'java');
627
+ const itemsParam = params.find((p) => p.kind === 'itemsObjectArray');
628
+ const itemBundles = itemsParam
629
+ ? buildJavaItemBundles(itemsParam.items, targetId)
630
+ : null;
631
+
632
+ if (itemBundles) {
633
+ lines.push(...itemBundles.lines);
634
+ lines.push('');
635
+ }
636
+
637
+ userProperties.forEach((property) => {
638
+ const keyExpr = getFirebaseUserPropertyExpression(property.key, 'java');
639
+ const valueExpr =
640
+ property.kind === 'null' ? 'null' : JSON.stringify(property.value);
641
+ lines.push(`mFirebaseAnalytics.setUserProperty(${keyExpr}, ${valueExpr});`);
642
+ });
643
+ if (userProperties.length > 0) {
644
+ lines.push('');
645
+ }
646
+
647
+ lines.push('Bundle eventParams = new Bundle();');
648
+ params.forEach((param) => {
649
+ const keyExpr = getFirebaseParamExpression(param.key, 'java');
650
+ if (param.kind === 'itemsObjectArray') {
651
+ lines.push(
652
+ `eventParams.putParcelableArray(${keyExpr}, new Parcelable[]{${itemBundles.names.join(', ')}});`,
653
+ );
654
+ return;
655
+ }
656
+ if (param.kind === 'string') {
657
+ lines.push(
658
+ `eventParams.putString(${keyExpr}, ${JSON.stringify(param.value)});`,
659
+ );
660
+ return;
661
+ }
662
+ if (param.kind === 'long') {
663
+ lines.push(`eventParams.putLong(${keyExpr}, ${param.value}L);`);
664
+ return;
665
+ }
666
+ lines.push(`eventParams.putDouble(${keyExpr}, ${param.value});`);
667
+ });
668
+ lines.push(`mFirebaseAnalytics.logEvent(${eventExpr}, eventParams);`);
669
+ return lines.join('\n');
670
+ }
671
+
672
+ function generateIosSwiftFirebaseSnippet({ example, targetId }) {
673
+ const { eventName, params, userProperties } = resolveFirebaseEvent(
674
+ example,
675
+ targetId,
676
+ );
677
+ const lines = [];
678
+ const eventExpr = getFirebaseEventExpression(eventName, 'swift');
679
+ const normalParams = params.filter((p) => p.kind !== 'itemsObjectArray');
680
+ const itemsParam = params.find((p) => p.kind === 'itemsObjectArray');
681
+ const swiftItems = itemsParam
682
+ ? buildSwiftItems(itemsParam.items, targetId)
683
+ : null;
684
+
685
+ if (swiftItems) {
686
+ lines.push(...swiftItems.lines);
687
+ lines.push('');
688
+ }
689
+
690
+ userProperties.forEach((property) => {
691
+ const keyExpr = getFirebaseUserPropertyExpression(property.key, 'swift');
692
+ const valueExpr =
693
+ property.kind === 'null' ? 'nil' : JSON.stringify(property.value);
694
+ lines.push(`Analytics.setUserProperty(${valueExpr}, forName: ${keyExpr})`);
695
+ });
696
+ if (userProperties.length > 0) {
697
+ lines.push('');
698
+ }
699
+
700
+ if (params.length === 0) {
701
+ lines.push(`Analytics.logEvent(${eventExpr}, parameters: nil)`);
702
+ return lines.join('\n');
703
+ }
704
+
705
+ lines.push('var eventParams: [String: Any] = [');
706
+ normalParams.forEach((param, index) => {
707
+ const comma = index < normalParams.length - 1 ? ',' : '';
708
+ const keyExpr = getFirebaseParamExpression(param.key, 'swift');
709
+ if (param.kind === 'string') {
710
+ lines.push(` ${keyExpr}: ${JSON.stringify(param.value)}${comma}`);
711
+ return;
712
+ }
713
+ lines.push(` ${keyExpr}: ${param.value}${comma}`);
714
+ });
715
+ lines.push(']');
716
+
717
+ if (itemsParam) {
718
+ const keyExpr = getFirebaseParamExpression(itemsParam.key, 'swift');
719
+ lines.push(`eventParams[${keyExpr}] = [${swiftItems.names.join(', ')}]`);
720
+ }
721
+
722
+ lines.push(`Analytics.logEvent(${eventExpr}, parameters: eventParams)`);
723
+ return lines.join('\n');
724
+ }
725
+
726
+ function escapeObjCString(value) {
727
+ return String(value).replace(/\\/g, '\\\\').replace(/"/g, '\\"');
728
+ }
729
+
730
+ function generateIosObjcFirebaseSnippet({ example, targetId }) {
731
+ const { eventName, params, userProperties } = resolveFirebaseEvent(
732
+ example,
733
+ targetId,
734
+ );
735
+ const lines = [];
736
+ const eventExpr = getFirebaseEventExpression(eventName, 'objc');
737
+ const normalParams = params.filter((p) => p.kind !== 'itemsObjectArray');
738
+ const itemsParam = params.find((p) => p.kind === 'itemsObjectArray');
739
+ const objcItems = itemsParam
740
+ ? buildObjcItems(itemsParam.items, targetId)
741
+ : null;
742
+
743
+ if (objcItems) {
744
+ lines.push(...objcItems.lines);
745
+ lines.push('');
746
+ }
747
+
748
+ userProperties.forEach((property) => {
749
+ const keyExpr = getFirebaseUserPropertyExpression(property.key, 'objc');
750
+ if (property.kind === 'null') {
751
+ lines.push(
752
+ `[FIRAnalytics setUserPropertyString:nil forName:${keyExpr}];`,
753
+ );
754
+ return;
755
+ }
756
+ lines.push(
757
+ `[FIRAnalytics setUserPropertyString:@"${escapeObjCString(property.value)}" forName:${keyExpr}];`,
758
+ );
759
+ });
760
+ if (userProperties.length > 0) {
761
+ lines.push('');
762
+ }
763
+
764
+ if (params.length === 0) {
765
+ lines.push(`[FIRAnalytics logEventWithName:${eventExpr} parameters:nil];`);
766
+ return lines.join('\n');
767
+ }
768
+
769
+ lines.push('NSMutableDictionary *eventParams = [@{');
770
+ normalParams.forEach((param, index) => {
771
+ const comma = index < normalParams.length - 1 ? ',' : '';
772
+ const keyExpr = getFirebaseParamExpression(param.key, 'objc');
773
+ if (param.kind === 'string') {
774
+ lines.push(` ${keyExpr}: @"${escapeObjCString(param.value)}"${comma}`);
775
+ return;
776
+ }
777
+ lines.push(` ${keyExpr}: @(${param.value})${comma}`);
778
+ });
779
+ lines.push('} mutableCopy];');
780
+
781
+ if (itemsParam) {
782
+ const keyExpr = getFirebaseParamExpression(itemsParam.key, 'objc');
783
+ lines.push(`eventParams[${keyExpr}] = @[${objcItems.names.join(', ')}];`);
784
+ }
785
+
786
+ lines.push(
787
+ `[FIRAnalytics logEventWithName:${eventExpr} parameters:eventParams];`,
788
+ );
789
+ return lines.join('\n');
790
+ }
791
+
792
+ export const SNIPPET_TARGETS = [
793
+ {
794
+ id: 'web-datalayer-js',
795
+ group: 'web',
796
+ label: 'Web Data Layer (JS)',
797
+ language: 'javascript',
798
+ generator: generateWebDataLayerSnippet,
799
+ },
800
+ {
801
+ id: 'android-firebase-kotlin-sdk',
802
+ group: 'android',
803
+ label: 'Android Firebase (Kotlin)',
804
+ language: 'kotlin',
805
+ generator: generateAndroidKotlinFirebaseSnippet,
806
+ },
807
+ {
808
+ id: 'android-firebase-java-sdk',
809
+ group: 'android',
810
+ label: 'Android Firebase (Java)',
811
+ language: 'java',
812
+ generator: generateAndroidJavaFirebaseSnippet,
813
+ },
814
+ {
815
+ id: 'ios-firebase-swift-sdk',
816
+ group: 'ios',
817
+ label: 'iOS Firebase (Swift)',
818
+ language: 'swift',
819
+ generator: generateIosSwiftFirebaseSnippet,
820
+ },
821
+ {
822
+ id: 'ios-firebase-objc-sdk',
823
+ group: 'ios',
824
+ label: 'iOS Firebase (Obj-C)',
825
+ language: 'objectivec',
826
+ generator: generateIosObjcFirebaseSnippet,
827
+ },
828
+ ];
829
+
830
+ export function getSnippetTarget(targetId = DEFAULT_SNIPPET_TARGET_ID) {
831
+ const target = SNIPPET_TARGETS.find((item) => item.id === targetId);
832
+ if (!target) {
833
+ throw new Error(`Unknown snippet target: ${targetId}`);
834
+ }
835
+ return target;
836
+ }
837
+
838
+ export function generateSnippetForTarget({
839
+ targetId = DEFAULT_SNIPPET_TARGET_ID,
840
+ example,
841
+ schema,
842
+ config = {},
843
+ dataLayerName,
844
+ }) {
845
+ const target = getSnippetTarget(targetId);
846
+ return target.generator({
847
+ example,
848
+ schema,
849
+ config,
850
+ dataLayerName,
851
+ targetId,
852
+ });
853
+ }