rampkit-expo-dev 0.0.43 → 0.0.44

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.
@@ -424,9 +424,170 @@ function preloadRampkitOverlay(opts) {
424
424
  // best-effort preloading; ignore errors
425
425
  }
426
426
  }
427
+ /**
428
+ * Evaluate a comparison condition against variables
429
+ * Supports: ==, !=, >, <, >=, <=, and truthy checks
430
+ */
431
+ function evaluateCondition(condition, vars) {
432
+ condition = condition.trim();
433
+ // Match comparison operators: ==, !=, >=, <=, >, <
434
+ const comparisonMatch = condition.match(/^([A-Za-z_][A-Za-z0-9_.]*)\s*(==|!=|>=|<=|>|<)\s*(.+)$/);
435
+ if (comparisonMatch) {
436
+ const [, varName, operator, rawRight] = comparisonMatch;
437
+ const leftValue = vars.hasOwnProperty(varName) ? vars[varName] : undefined;
438
+ let rightValue = rawRight.trim();
439
+ // Parse right side - could be a quoted string or a number or a variable
440
+ if ((rightValue.startsWith('"') && rightValue.endsWith('"')) ||
441
+ (rightValue.startsWith("'") && rightValue.endsWith("'"))) {
442
+ // Quoted string literal
443
+ rightValue = rightValue.slice(1, -1);
444
+ }
445
+ else if (!isNaN(Number(rightValue))) {
446
+ // Numeric literal
447
+ rightValue = Number(rightValue);
448
+ }
449
+ else if (rightValue === "true") {
450
+ rightValue = true;
451
+ }
452
+ else if (rightValue === "false") {
453
+ rightValue = false;
454
+ }
455
+ else if (rightValue === "null") {
456
+ rightValue = null;
457
+ }
458
+ else if (vars.hasOwnProperty(rightValue)) {
459
+ // Variable reference
460
+ rightValue = vars[rightValue];
461
+ }
462
+ // Perform comparison
463
+ switch (operator) {
464
+ case "==":
465
+ return leftValue == rightValue;
466
+ case "!=":
467
+ return leftValue != rightValue;
468
+ case ">":
469
+ return Number(leftValue) > Number(rightValue);
470
+ case "<":
471
+ return Number(leftValue) < Number(rightValue);
472
+ case ">=":
473
+ return Number(leftValue) >= Number(rightValue);
474
+ case "<=":
475
+ return Number(leftValue) <= Number(rightValue);
476
+ default:
477
+ return false;
478
+ }
479
+ }
480
+ // Truthy check - just the variable name
481
+ const varName = condition.trim();
482
+ if (vars.hasOwnProperty(varName)) {
483
+ const value = vars[varName];
484
+ // Consider empty string as falsy
485
+ if (value === "")
486
+ return false;
487
+ return !!value;
488
+ }
489
+ // Unknown variable - treat as falsy
490
+ return false;
491
+ }
492
+ /**
493
+ * Parse a ternary value (the part after ? or after :)
494
+ * Returns the resolved value, handling both quoted strings and variable references
495
+ */
496
+ function parseTernaryValue(value, vars) {
497
+ value = value.trim();
498
+ // Check if it's a quoted string
499
+ if ((value.startsWith('"') && value.endsWith('"')) ||
500
+ (value.startsWith("'") && value.endsWith("'"))) {
501
+ return value.slice(1, -1);
502
+ }
503
+ // Otherwise treat as a variable reference
504
+ if (vars.hasOwnProperty(value)) {
505
+ const varValue = vars[value];
506
+ if (varValue === undefined || varValue === null)
507
+ return "";
508
+ if (typeof varValue === "boolean")
509
+ return varValue ? "true" : "false";
510
+ if (typeof varValue === "object")
511
+ return JSON.stringify(varValue);
512
+ return String(varValue);
513
+ }
514
+ // Return as-is if not found (could be a literal like a number)
515
+ return value;
516
+ }
517
+ /**
518
+ * Parse a ternary expression and find the colon that separates true/false values
519
+ * Handles nested quotes properly
520
+ */
521
+ function splitTernary(expr) {
522
+ // Find the ? that starts the ternary
523
+ let questionIdx = -1;
524
+ let inQuote = false;
525
+ let quoteChar = "";
526
+ for (let i = 0; i < expr.length; i++) {
527
+ const char = expr[i];
528
+ const prevChar = i > 0 ? expr[i - 1] : "";
529
+ if ((char === '"' || char === "'") && prevChar !== "\\") {
530
+ if (!inQuote) {
531
+ inQuote = true;
532
+ quoteChar = char;
533
+ }
534
+ else if (char === quoteChar) {
535
+ inQuote = false;
536
+ }
537
+ }
538
+ if (!inQuote && char === "?") {
539
+ questionIdx = i;
540
+ break;
541
+ }
542
+ }
543
+ if (questionIdx === -1)
544
+ return null;
545
+ const condition = expr.slice(0, questionIdx).trim();
546
+ const rest = expr.slice(questionIdx + 1);
547
+ // Find the : that separates true/false values
548
+ let colonIdx = -1;
549
+ inQuote = false;
550
+ quoteChar = "";
551
+ for (let i = 0; i < rest.length; i++) {
552
+ const char = rest[i];
553
+ const prevChar = i > 0 ? rest[i - 1] : "";
554
+ if ((char === '"' || char === "'") && prevChar !== "\\") {
555
+ if (!inQuote) {
556
+ inQuote = true;
557
+ quoteChar = char;
558
+ }
559
+ else if (char === quoteChar) {
560
+ inQuote = false;
561
+ }
562
+ }
563
+ if (!inQuote && char === ":") {
564
+ colonIdx = i;
565
+ break;
566
+ }
567
+ }
568
+ if (colonIdx === -1)
569
+ return null;
570
+ const trueValue = rest.slice(0, colonIdx).trim();
571
+ const falseValue = rest.slice(colonIdx + 1).trim();
572
+ return { condition, trueValue, falseValue };
573
+ }
427
574
  /**
428
575
  * Resolve device/user templates in a string
429
- * Replaces ${device.xxx} and ${user.xxx} with actual values from context
576
+ * Supports both simple variables ${varName} and conditional ternary expressions
577
+ * ${condition ? "trueValue" : "falseValue"}
578
+ *
579
+ * Supported operators in conditions:
580
+ * - == (equals)
581
+ * - != (not equals)
582
+ * - > (greater than)
583
+ * - < (less than)
584
+ * - >= (greater or equal)
585
+ * - <= (less or equal)
586
+ * - Truthy check (just variable name)
587
+ *
588
+ * Values can be:
589
+ * - Quoted strings: "hello" or 'hello'
590
+ * - Variable references: username
430
591
  */
431
592
  function resolveContextTemplates(text, context) {
432
593
  if (!text || !text.includes("${"))
@@ -446,8 +607,23 @@ function resolveContextTemplates(text, context) {
446
607
  });
447
608
  }
448
609
  console.log("[RampKit] Resolving templates with vars:", JSON.stringify(vars));
449
- // Replace ${varName} patterns
450
- return text.replace(/\$\{([A-Za-z_][A-Za-z0-9_.]*)\}/g, (match, varName) => {
610
+ // Match ${...} expressions - use a more permissive regex to capture full expressions
611
+ // including ternary operators with quotes
612
+ return text.replace(/\$\{([^}]+)\}/g, (match, innerExpr) => {
613
+ const expr = innerExpr.trim();
614
+ // Check if this is a ternary expression
615
+ const ternary = splitTernary(expr);
616
+ if (ternary) {
617
+ const { condition, trueValue, falseValue } = ternary;
618
+ const result = evaluateCondition(condition, vars);
619
+ const value = result
620
+ ? parseTernaryValue(trueValue, vars)
621
+ : parseTernaryValue(falseValue, vars);
622
+ console.log(`[RampKit] Ternary: ${condition} ? ${trueValue} : ${falseValue} => ${result} => "${value}"`);
623
+ return value;
624
+ }
625
+ // Simple variable substitution
626
+ const varName = expr;
451
627
  if (vars.hasOwnProperty(varName)) {
452
628
  const value = vars[varName];
453
629
  console.log(`[RampKit] Replacing ${match} with:`, value);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rampkit-expo-dev",
3
- "version": "0.0.43",
3
+ "version": "0.0.44",
4
4
  "description": "The Expo SDK for RampKit. Build, test, and personalize app onboardings with instant updates.",
5
5
  "main": "build/index.js",
6
6
  "types": "build/index.d.ts",