@reventlessdev/rescript-pulumi-aws 3.0.0-alpha.3 → 3.0.0-alpha.30

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 (35) hide show
  1. package/CHANGELOG.md +224 -0
  2. package/package.json +8 -7
  3. package/rescript.json +2 -1
  4. package/src/AppSync/AppSync_ResolverRuntime.res +4 -5
  5. package/src/AppSync/AppSync_Resolver_Functions.res +524 -396
  6. package/src/AppSync/AppSync_Resolver_Functions.res.mjs +206 -130
  7. package/src/AppSync/AppSync_SourceApiAssociation.res +1 -3
  8. package/src/AwsNative/AppSync/AwsNative_AppSync_Api.res +2 -3
  9. package/src/AwsNative/AppSync/AwsNative_AppSync_ChannelNamespace.res +2 -6
  10. package/src/AwsNative/AppSync/AwsNative_AppSync_Resolver.res +2 -5
  11. package/src/Cloudwatch/Cloudwatch_EventRule.res +4 -0
  12. package/src/Cloudwatch/Cloudwatch_EventTarget.res +11 -0
  13. package/src/Cloudwatch/Cloudwatch_LogMetricFilter.res +0 -1
  14. package/src/Cloudwatch/Cloudwatch_MetricAlarm.res +0 -1
  15. package/src/Cognito/Cognito_UserPool.res +2 -4
  16. package/src/IAM/IAM.res +1 -1
  17. package/src/IAM/PolicyDocument.res +2 -2
  18. package/src/IAM/PolicyDocument.res.mjs +3 -3
  19. package/src/Kinesis/Kinesis_Stream.res +3 -6
  20. package/src/Lambda/FunctionUrl.res +5 -2
  21. package/src/Lambda/Lambda.res +138 -52
  22. package/src/Lambda/Lambda.res.mjs +152 -23
  23. package/src/Rds/Rds_Cluster.res +0 -1
  24. package/src/Rds/Rds_Instance.res +0 -1
  25. package/src/Rds/Rds_Proxy.res +1 -2
  26. package/src/S3/S3_BucketV2.res +1 -3
  27. package/src/Scheduler/Scheduler.res +4 -0
  28. package/src/Scheduler/Scheduler.res.mjs +9 -0
  29. package/src/Scheduler/Scheduler_ScheduleGroup.res +14 -0
  30. package/src/Scheduler/Scheduler_ScheduleGroup.res.mjs +2 -0
  31. package/src/example/AlarmMailExample.res +34 -0
  32. package/src/example/AlarmMailExample.res.mjs +44 -0
  33. package/src/example/CustomDomainExample.res +2 -3
  34. package/src/example/MergedApiExample.res +1 -3
  35. package/tests/AppSync_Resolver_FunctionsTest.mjs +421 -28
@@ -388,25 +388,99 @@ export function request(ctx) {
388
388
  `;
389
389
  }
390
390
 
391
- let indexConnectionResponseCode = `
392
- export function response(ctx) {
393
- if (ctx.error) util.error(ctx.error.message, ctx.error.type);
394
- const items = ctx.result?.items ?? [];
395
- const next = ctx.result?.nextToken ?? null;
396
- const edges = items.map((item, i) => ({
391
+ function pageWindowBudget(filtered) {
392
+ return `(` + filtered + ` ? (_first > 1000 ? _first : 1000) : _first + _from + 1)`;
393
+ }
394
+
395
+ let need = "(_backward ? _upTo : _first + _from + 1)";
396
+
397
+ let listPageWindowBudget = `(parts.length > 0 ? (` + need + ` > 1000 ? ` + need + ` : 1000) : ` + need + `)`;
398
+
399
+ function cursorDecode(args) {
400
+ return `
401
+ let _window = null;
402
+ let _from = 0;
403
+ let _cursorPath = null;
404
+ if (` + args + `.after != null && ` + args + `.after !== '') {
405
+ const _c = JSON.parse(util.base64Decode(` + args + `.after));
406
+ _window = (_c.t !== undefined ? _c.t : _c.token) ?? null;
407
+ _from = _c.n !== undefined ? _c.n + 1 : 0;
408
+ _cursorPath = _c.p ?? 's';
409
+ }`;
410
+ }
411
+
412
+ let cursorPathGuard = `
413
+ if (_cursorPath !== null && _cursorPath !== (_exempt ? 's' : 'q')) {
414
+ util.error('This cursor belongs to a different read of this list; restart from the first page.', 'CursorPathMismatch');
415
+ }`;
416
+
417
+ let listCursorPreamble = `
418
+ const _first = ctx.args.first ?? 50;
419
+ let _window = null;
420
+ let _from = 0;
421
+ let _cursorPath = null;
422
+ let _backward = false;
423
+ let _upTo = -1;
424
+ if (ctx.args.before != null && ctx.args.before !== '') {
425
+ const _c = JSON.parse(util.base64Decode(ctx.args.before));
426
+ _window = (_c.t !== undefined ? _c.t : _c.token) ?? null;
427
+ _cursorPath = _c.p ?? 's';
428
+ _backward = true;
429
+ _upTo = _c.n !== undefined ? _c.n : 0;
430
+ _from = (_upTo - _first) > 0 ? (_upTo - _first) : 0;
431
+ } else if (ctx.args.after != null && ctx.args.after !== '') {
432
+ const _c = JSON.parse(util.base64Decode(ctx.args.after));
433
+ _window = (_c.t !== undefined ? _c.t : _c.token) ?? null;
434
+ _from = _c.n !== undefined ? _c.n + 1 : 0;
435
+ _cursorPath = _c.p ?? 's';
436
+ }`;
437
+
438
+ function connectionPageResponse(pathExpr, bidirectionalOpt) {
439
+ let bidirectional = bidirectionalOpt !== undefined ? bidirectionalOpt : false;
440
+ let tag = pathExpr !== undefined ? `, p: ` + pathExpr : "";
441
+ let firstDecl = bidirectional ? "" : "\n const _first = ctx.args.first ?? 50;";
442
+ let slice = bidirectional ? `
443
+ const _rest = _backward ? items.slice(_from, _upTo) : items.slice(_from);
444
+ const _page = _backward ? _rest : _rest.slice(0, _first);
445
+ // A backward page was cut from ahead, so a next page provably exists — the one
446
+ // the caller came from — whatever this window's tail looks like.
447
+ const _more = _backward ? true : _rest.length > _first;` : `
448
+ const _rest = items.slice(_from);
449
+ const _page = _rest.slice(0, _first);
450
+ const _more = _rest.length > _first;`;
451
+ let hasPrevious = bidirectional ? "_from > 0" : "!!ctx.args.after";
452
+ return firstDecl + slice + `
453
+ const _next = ctx.result?.nextToken ?? null;
454
+ const _lastIndex = _page.length - 1;
455
+ // A row's cursor names its own position. The last row of a page that closes its
456
+ // window is the exception — no position follows it there, so it names the next
457
+ // window, or resuming from it answers blank.
458
+ const edges = _page.map((item, i) => ({
397
459
  node: item,
398
- cursor: util.base64Encode(JSON.stringify({ token: next, index: i })),
460
+ cursor: util.base64Encode(JSON.stringify(
461
+ (!_more && _next && i === _lastIndex)
462
+ ? { t: _next, n: -1` + tag + ` }
463
+ : { t: _window, n: _from + i` + tag + ` }
464
+ )),
399
465
  }));
400
- const boundary = next ? util.base64Encode(JSON.stringify({ token: next, index: -1 })) : null;
466
+ // A window the filter emptied leaves no row to cut a cursor from; the token is
467
+ // the window's, so a client can step past it rather than restart.
468
+ const _boundary = _next ? util.base64Encode(JSON.stringify({ t: _next, n: -1` + tag + ` })) : null;
401
469
  return {
402
470
  edges,
403
471
  pageInfo: {
404
- hasNextPage: !!next,
405
- hasPreviousPage: !!ctx.args.after,
406
- startCursor: edges.length > 0 ? edges[0].cursor : boundary,
407
- endCursor: edges.length > 0 ? edges[edges.length - 1].cursor : boundary,
472
+ hasNextPage: _more || !!_next,
473
+ hasPreviousPage: ` + hasPrevious + `,
474
+ startCursor: edges.length > 0 ? edges[0].cursor : _boundary,
475
+ endCursor: edges.length > 0 ? edges[edges.length - 1].cursor : _boundary,
408
476
  },
409
- };
477
+ };`;
478
+ }
479
+
480
+ let indexConnectionResponseCode = `
481
+ export function response(ctx) {
482
+ if (ctx.error) util.error(ctx.error.message, ctx.error.type);
483
+ const items = ctx.result?.items ?? [];` + cursorDecode("ctx.args") + connectionPageResponse(undefined, undefined) + `
410
484
  }`;
411
485
 
412
486
  let indexBackwardPagingGuard = `
@@ -414,12 +488,8 @@ let indexBackwardPagingGuard = `
414
488
  util.error('Backward pagination (last/before) is not supported on by-index connections; use first/after.', 'UnsupportedPagination');
415
489
  }`;
416
490
 
417
- let indexCursorPreamble = `
418
- let after = null;
419
- if (args.after != null && args.after !== '') {
420
- const parsed = JSON.parse(util.base64Decode(args.after));
421
- after = parsed.token ?? null;
422
- }`;
491
+ let indexCursorPreamble = cursorDecode("args") + `
492
+ const _first = args.first ?? 50;`;
423
493
 
424
494
  let indexReservedArgs = `key === 'first' || key === 'after' || key === 'last' || key === 'before' || key === 'includeRetired' || key === 'limit' || key === 'nextToken' || key === 'forward'`;
425
495
 
@@ -458,8 +528,8 @@ export function request(ctx) {
458
528
  operation: 'Query',
459
529
  query,
460
530
  index: '` + index + `',
461
- limit: (args.first ?? 50),
462
- nextToken: after,
531
+ limit: ` + (`(` + "expression" + ` ? (_first > 1000 ? _first : 1000) : _first + _from + 1)`) + `,
532
+ nextToken: _window,
463
533
  scanIndexForward: (args.forward ?? true)
464
534
  };
465
535
  if (expression) {
@@ -515,8 +585,8 @@ export function request(ctx) {
515
585
  operation: 'Query',
516
586
  query,
517
587
  index: '` + index + `',
518
- limit: (args.first ?? 50),
519
- nextToken: after,
588
+ limit: ` + (`(` + "expression" + ` ? (_first > 1000 ? _first : 1000) : _first + _from + 1)`) + `,
589
+ nextToken: _window,
520
590
  scanIndexForward: (args.forward ?? true)
521
591
  };
522
592
  if (expression) {
@@ -539,18 +609,17 @@ export function request(ctx) {
539
609
  ` + resultResponseCode + `
540
610
  `;
541
611
 
542
- function listAllItemsConnection(labelField, filterFieldsOpt, rangeFieldsOpt, sortFieldsOpt, requireAttribute, ownerField, elevatedGroupsOpt, retiredField, retiredValues) {
612
+ function listAllItemsConnection(labelField, filterFieldsOpt, rangeFieldsOpt, sortFieldsOpt, requireAttribute, ownerField, elevatedGroupsOpt, retiredField, retiredValues, ownerIndex, ownerIndexSortField) {
543
613
  let filterFields = filterFieldsOpt !== undefined ? filterFieldsOpt : [];
544
614
  let rangeFields = rangeFieldsOpt !== undefined ? rangeFieldsOpt : [];
545
615
  let sortFields = sortFieldsOpt !== undefined ? sortFieldsOpt : [];
546
616
  let elevatedGroups = elevatedGroupsOpt !== undefined ? elevatedGroupsOpt : [];
617
+ let ownerIndex$1 = Stdlib_Option.isSome(ownerField) ? ownerIndex : undefined;
547
618
  let requireAttributeClause = requireAttribute !== undefined ? `
548
619
  names['#` + requireAttribute + `'] = '` + requireAttribute + `';
549
620
  parts.push('attribute_exists(#` + requireAttribute + `)');` : "";
550
- let ownerClause;
551
- if (ownerField !== undefined) {
552
- let elevatedLiteral = elevatedGroups.map(g => `'` + g + `'`).join(", ");
553
- ownerClause = `
621
+ let elevatedLiteral = elevatedGroups.map(g => `'` + g + `'`).join(", ");
622
+ let ownerIdentityPreamble = `
554
623
  // ── owner scoping (generated) ──
555
624
  // Not read from ctx.args: a predicate deciding what the caller may see must
556
625
  // arrive on a channel the caller cannot name, and this field is usually absent
@@ -561,15 +630,15 @@ function listAllItemsConnection(labelField, filterFieldsOpt, rangeFieldsOpt, sor
561
630
  const _elevated = [` + elevatedLiteral + `];
562
631
  // No identity at all, or an identity with no \`sub\`, is the IAM service caller
563
632
  // the API also accepts — inside the trust boundary, and exempt.
564
- const _exempt = _sub == null || _groups.some(g => _elevated.indexOf(g) >= 0);
633
+ const _exempt = _sub == null || _groups.some(g => _elevated.indexOf(g) >= 0);`;
634
+ let ownerClause = ownerField !== undefined ? (
635
+ ownerIndex$1 !== undefined ? ownerIdentityPreamble : ownerIdentityPreamble + `
565
636
  if (!_exempt) {
566
637
  names['#owner'] = '` + ownerField + `';
567
638
  values[':owner'] = util.dynamodb.toDynamoDB(_sub);
568
639
  parts.push('#owner = :owner');
569
- }`;
570
- } else {
571
- ownerClause = "";
572
- }
640
+ }`
641
+ ) : "";
573
642
  let retiredClause;
574
643
  if (retiredField !== undefined) {
575
644
  let elevatedLiteral$1 = elevatedGroups.map(g => `'` + g + `'`).join(", ");
@@ -621,13 +690,14 @@ function listAllItemsConnection(labelField, filterFieldsOpt, rangeFieldsOpt, sor
621
690
  parts.push('#` + f + ` <= :` + f + `To');
622
691
  }`).join("");
623
692
  let sortFieldsLiteral = sortFields.map(f => `'` + f + `'`).join(", ");
693
+ let sortGuard = ownerIndex$1 !== undefined && ownerIndexSortField !== undefined ? "!_indexOrdered && " : "";
624
694
  let sortBlock = sortFields.length === 0 ? "" : `
625
695
  // Per-page sort (Scan returns items in indeterminate order; ScanIndexForward
626
696
  // does not apply to Scan). Global ordering across pages requires v1.5 index
627
697
  // promotion; @scanSort is per-page even then.
628
698
  const orderBy = ctx.args.orderBy;
629
699
  const sortFields = [` + sortFieldsLiteral + `];
630
- if (orderBy && orderBy.field && sortFields.indexOf(orderBy.field) >= 0) {
700
+ if (` + sortGuard + `orderBy && orderBy.field && sortFields.indexOf(orderBy.field) >= 0) {
631
701
  const field = orderBy.field;
632
702
  const nulls = items.filter(it => it[field] === null || it[field] === undefined);
633
703
  const nonNulls = items.filter(it => it[field] !== null && it[field] !== undefined);
@@ -642,13 +712,53 @@ function listAllItemsConnection(labelField, filterFieldsOpt, rangeFieldsOpt, sor
642
712
  if (orderBy.direction === 'DESC') encoded.reverse();
643
713
  items = encoded.map(e => JSON.parse(e.split('\\x01')[1])).concat(nulls);
644
714
  }`;
715
+ let indexOrderedExpr = ownerIndex$1 !== undefined && ownerIndexSortField !== undefined ? `!_exempt && !!(ctx.args.orderBy && ctx.args.orderBy.field === '` + ownerIndexSortField + `')` : "false";
716
+ let requestOperation = ownerField !== undefined ? (
717
+ ownerIndex$1 !== undefined ? `
718
+ const _indexOrdered = ` + indexOrderedExpr + `;
719
+ const req = _exempt
720
+ ? {
721
+ operation: 'Scan',
722
+ limit: ` + listPageWindowBudget + `,
723
+ nextToken: _window,
724
+ }
725
+ : {
726
+ operation: 'Query',
727
+ index: '` + ownerIndex$1 + `',
728
+ query: {
729
+ expression: '#owner = :owner',
730
+ expressionNames: { '#owner': '` + ownerField + `' },
731
+ expressionValues: { ':owner': util.dynamodb.toDynamoDB(_sub) },
732
+ },
733
+ limit: ` + listPageWindowBudget + `,
734
+ nextToken: _window,
735
+ scanIndexForward: !(_indexOrdered && ctx.args.orderBy.direction === 'DESC'),
736
+ };` : `
737
+ const req = {
738
+ operation: 'Scan',
739
+ limit: ` + listPageWindowBudget + `,
740
+ nextToken: _window,
741
+ };`
742
+ ) : `
743
+ const req = {
744
+ operation: 'Scan',
745
+ limit: ` + listPageWindowBudget + `,
746
+ nextToken: _window,
747
+ };`;
748
+ let requestPathGuard = Stdlib_Option.isSome(ownerIndex$1) ? cursorPathGuard : "";
749
+ let responsePathPreamble = ownerIndex$1 !== undefined ? ownerIdentityPreamble + `
750
+ const _path = _exempt ? 's' : 'q';
751
+ const _indexOrdered = ` + indexOrderedExpr + `;` : "";
752
+ let pageResponse = ownerIndex$1 !== undefined ? connectionPageResponse("_path", true) : connectionPageResponse(undefined, true);
645
753
  return importUtil + `
646
754
  export function request(ctx) {
647
- // Scan cannot page backward (ScanIndexForward is Query-only). Fail loud rather than
648
- // silently returning the forward page. The ordered {single}Items connection
649
- // (queryItemsWithSortConditions) supports last/before — direct backward callers there.
650
- if (ctx.args.before != null || ctx.args.last != null) {
651
- util.error('Backward pagination (last/before) is not supported on full-list connections; use first/after.', 'UnsupportedPagination');
755
+ // 'before' IS served — the page is cut backward out of the window the cursor
756
+ // names. 'last' is not: "the last N rows of the list" needs the end of the
757
+ // list, which a forward-only Scan cursor cannot reach. The ordered
758
+ // {single}Items connection (queryItemsWithSortConditions) has a real keyset
759
+ // cursor and honours both — direct callers who need 'last' there.
760
+ if (ctx.args.last != null) {
761
+ util.error('last is not supported on full-list connections; page backward with first and before.', 'UnsupportedPagination');
652
762
  }
653
763
  const filter = ctx.args.filter ?? {};
654
764
  const names = {};
@@ -673,18 +783,14 @@ export function request(ctx) {
673
783
  });
674
784
  parts.push('#id IN (' + placeholders.join(', ') + ')');
675
785
  }` + filterClauses + rangeClauses + requireAttributeClause + ownerClause + retiredClause + `
676
- // The cursor is base64(JSON({ token, index })); decode the after arg back to the raw
677
- // DynamoDB continuation token the response side emitted (Fix 1 round-trip).
678
- let after = null;
679
- if (ctx.args.after != null && ctx.args.after !== '') {
680
- const parsed = JSON.parse(util.base64Decode(ctx.args.after));
681
- after = parsed.token ?? null;
682
- }
683
- const req = {
684
- operation: 'Scan',
685
- limit: (ctx.args.first ?? 50),
686
- nextToken: after,
687
- };
786
+ ` + listCursorPreamble + requestPathGuard + `
787
+ // The one page a cursor cannot reach: it begins in an earlier window, and a
788
+ // continuation token cannot name the one before it. Refused by itself rather
789
+ // than folded into the 'last' guard, because the two are different limits and a
790
+ // caller can act on this one (page forward from the start).
791
+ if (_backward && _upTo <= 0 && _window !== null) {
792
+ util.error('The previous page begins in an earlier read window, which this cursor cannot name; page forward from the start.', 'UnsupportedPagination');
793
+ }` + requestOperation + `
688
794
  if (parts.length > 0) {
689
795
  req.filter = {
690
796
  expression: parts.join(' AND '),
@@ -696,30 +802,7 @@ export function request(ctx) {
696
802
  }
697
803
  export function response(ctx) {
698
804
  if (ctx.error) util.error(ctx.error.message, ctx.error.type);
699
- let items = ctx.result?.items ?? [];` + sortBlock + `
700
- // One Scan continuation token per page; encode it (with the item's page index for a
701
- // unique, opaque Relay cursor). The request side decodes .token back to the raw
702
- // DynamoDB nextToken (Fix 1).
703
- const next = ctx.result?.nextToken ?? null;
704
- const edges = items.map((item, i) => ({
705
- node: item,
706
- cursor: util.base64Encode(JSON.stringify({ token: next, index: i })),
707
- }));
708
- // A filtered/1MB-capped page can be empty or short while next is still set (limit
709
- // caps rows scanned, not returned). The token is page-level, so synthesise a
710
- // boundary cursor from it alone so a client can resume past a fully-filtered-out
711
- // page instead of restarting from page 1 (Fix 3). The request only reads .token,
712
- // so index -1 is inert on resume.
713
- const boundary = next ? util.base64Encode(JSON.stringify({ token: next, index: -1 })) : null;
714
- return {
715
- edges,
716
- pageInfo: {
717
- hasNextPage: !!next,
718
- hasPreviousPage: !!ctx.args.after,
719
- startCursor: edges.length > 0 ? edges[0].cursor : boundary,
720
- endCursor: edges.length > 0 ? edges[edges.length - 1].cursor : boundary,
721
- },
722
- };
805
+ let items = ctx.result?.items ?? [];` + responsePathPreamble + sortBlock + listCursorPreamble + pageResponse + `
723
806
  }
724
807
  `;
725
808
  }
@@ -894,9 +977,9 @@ export function request(ctx) {
894
977
  `;
895
978
  }
896
979
 
897
- function resolveIds(idsField, sortField, ownerField, retiredField, retiredValues, $staropt$star) {
980
+ function resolveIds(idsField, sortField, ownerField, retiredField, retiredValues, elevatedGroupsOpt) {
981
+ let elevatedGroups = elevatedGroupsOpt !== undefined ? elevatedGroupsOpt : [];
898
982
  return tableName => {
899
- let elevatedGroups = $staropt$star !== undefined ? $staropt$star : [];
900
983
  let keysCode = sortField !== undefined ? `id => ({ id: util.dynamodb.toString(id.id), ` + sortField + `: util.dynamodb.toString(id.` + sortField + `) })` : `id => ({ id: util.dynamodb.toString(id) })`;
901
984
  return importUtil + `
902
985
  import { runtime } from '@aws-appsync/utils';
@@ -928,10 +1011,9 @@ export function response(ctx) {
928
1011
  };
929
1012
  }
930
1013
 
931
- function batchGetItemsByIds(ownerField, retiredField, retiredValues, $staropt$star) {
932
- return tableName => {
933
- let elevatedGroups = $staropt$star !== undefined ? $staropt$star : [];
934
- return importUtil + `
1014
+ function batchGetItemsByIds(ownerField, retiredField, retiredValues, elevatedGroupsOpt) {
1015
+ let elevatedGroups = elevatedGroupsOpt !== undefined ? elevatedGroupsOpt : [];
1016
+ return tableName => importUtil + `
935
1017
  import { runtime } from '@aws-appsync/utils';
936
1018
  export function request(ctx) {
937
1019
  const ids = ctx.args.ids ?? [];
@@ -948,33 +1030,29 @@ export function request(ctx) {
948
1030
  }
949
1031
  export function response(ctx) {
950
1032
  if (ctx.error) util.error(ctx.error.message, ctx.error.type);
951
- // BatchGetItem returns null in the result array for keys that don't exist
952
- // in the table, preserving index correspondence with the input. The SDL
953
- // returns this field as \`[T!]!\` (non-null element list), so any single
954
- // missing id makes the entire field fail with "Cannot return null for
955
- // non-nullable type" and the caller sees data=null. Filter the nulls so
956
- // the field returns just the items that were found.
1033
+ // BatchGetItem returns null for keys that don't exist, preserving index
1034
+ // correspondence. The SDL declares \`[T!]!\`, so one missing id would null the
1035
+ // whole field — drop them and return what was found.
957
1036
  // The owner and retirement guards the list pushes into a FilterExpression,
958
1037
  // applied after the read because BatchGetItem has none to push into. A row the
959
1038
  // caller does not own is dropped rather than refused, for the reason the
960
1039
  // single-key door answers null: distinguishing "not yours" from "not there"
961
1040
  // would make this door an oracle for which ids exist.` + (
962
- ownerField !== undefined ? ownerGuardPreamble(ownerField, elevatedGroups) : ""
963
- ) + retiredGuardPreamble(retiredField, retiredValues, elevatedGroups, Stdlib_Option.isSome(ownerField)) + `
1041
+ ownerField !== undefined ? ownerGuardPreamble(ownerField, elevatedGroups) : ""
1042
+ ) + retiredGuardPreamble(retiredField, retiredValues, elevatedGroups, Stdlib_Option.isSome(ownerField)) + `
964
1043
  return (ctx.result?.data?.['` + tableName + `'] ?? []).filter(item =>
965
1044
  item !== null` + (
966
- Stdlib_Option.isSome(ownerField) ? " && _owns(item)" : ""
967
- ) + (
968
- Stdlib_Option.isSome(retiredField) ? " && _live(item)" : ""
969
- ) + `);
1045
+ Stdlib_Option.isSome(ownerField) ? " && _owns(item)" : ""
1046
+ ) + (
1047
+ Stdlib_Option.isSome(retiredField) ? " && _live(item)" : ""
1048
+ ) + `);
970
1049
  }
971
1050
  `;
972
- };
973
1051
  }
974
1052
 
975
- function refsByIds(labelField, retiredField, retiredValues, namedWhenRetired, ownerField, $staropt$star) {
1053
+ function refsByIds(labelField, retiredField, retiredValues, namedWhenRetired, imageExpr, ownerField, elevatedGroupsOpt) {
1054
+ let elevatedGroups = elevatedGroupsOpt !== undefined ? elevatedGroupsOpt : [];
976
1055
  return tableName => {
977
- let elevatedGroups = $staropt$star !== undefined ? $staropt$star : [];
978
1056
  let ownerGuard = ownerField !== undefined ? ownerGuardPreamble(ownerField, elevatedGroups) : "\n const _owns = (row) => true;";
979
1057
  let retiredExpr;
980
1058
  if (retiredField !== undefined) {
@@ -1015,6 +1093,7 @@ export function response(ctx) {
1015
1093
  .map(row => ({
1016
1094
  id: row.id,
1017
1095
  label: row['` + labelField + `'] ?? row.id,
1096
+ image: ` + Stdlib_Option.getOr(imageExpr, "null") + `,
1018
1097
  retired: _retired(row),
1019
1098
  retiredState: ` + stateExpr + `,
1020
1099
  }));
@@ -1061,6 +1140,23 @@ export function request(ctx) {
1061
1140
  ` + resultResponseCode + `
1062
1141
  `;
1063
1142
 
1143
+ let callerIdentity = `identity: isCognito
1144
+ ? {
1145
+ userId: id.sub,
1146
+ username: id.username,
1147
+ groups: id.claims?.['cognito:groups'] ?? [],
1148
+ claims: id.claims,
1149
+ provider: 'Cognito'
1150
+ }
1151
+ : id != null
1152
+ ? {
1153
+ userArn: id.userArn ?? null,
1154
+ accountId: id.accountId ?? null,
1155
+ username: id.username ?? null,
1156
+ provider: 'IAM'
1157
+ }
1158
+ : null`;
1159
+
1064
1160
  function invokeCommandGenerator(command) {
1065
1161
  return importUtil + `
1066
1162
  export function request(ctx) {
@@ -1076,22 +1172,7 @@ export function request(ctx) {
1076
1172
  user: id?.username ?? null,
1077
1173
  info: ctx.info.parentTypeName + '.' + ctx.info.fieldName
1078
1174
  },
1079
- identity: isCognito
1080
- ? {
1081
- userId: id.sub,
1082
- username: id.username,
1083
- groups: id.claims?.['cognito:groups'] ?? [],
1084
- claims: id.claims,
1085
- provider: 'Cognito'
1086
- }
1087
- : id != null
1088
- ? {
1089
- userArn: id.userArn ?? null,
1090
- accountId: id.accountId ?? null,
1091
- username: id.username ?? null,
1092
- provider: 'IAM'
1093
- }
1094
- : null
1175
+ ` + callerIdentity + `
1095
1176
  }
1096
1177
  };
1097
1178
  }
@@ -1114,22 +1195,7 @@ export function request(ctx) {
1114
1195
  user: id?.username ?? null,
1115
1196
  info: ctx.info.parentTypeName + '.' + ctx.info.fieldName
1116
1197
  },
1117
- identity: isCognito
1118
- ? {
1119
- userId: id.sub,
1120
- username: id.username,
1121
- groups: id.claims?.['cognito:groups'] ?? [],
1122
- claims: id.claims,
1123
- provider: 'Cognito'
1124
- }
1125
- : id != null
1126
- ? {
1127
- userArn: id.userArn ?? null,
1128
- accountId: id.accountId ?? null,
1129
- username: id.username ?? null,
1130
- provider: 'IAM'
1131
- }
1132
- : null
1198
+ ` + callerIdentity + `
1133
1199
  }
1134
1200
  };
1135
1201
  }
@@ -1140,12 +1206,15 @@ export function request(ctx) {
1140
1206
  function invokeInboundTranslation(fieldName) {
1141
1207
  return importUtil + `
1142
1208
  export function request(ctx) {
1209
+ const id = ctx.identity;
1210
+ const isCognito = id != null && id.sub != null;
1143
1211
  return {
1144
1212
  operation: 'Invoke',
1145
1213
  payload: {
1146
1214
  __inboundTranslation: true,
1147
1215
  fieldName: '` + fieldName + `',
1148
- arguments: ctx.args
1216
+ arguments: ctx.args,
1217
+ ` + callerIdentity + `
1149
1218
  }
1150
1219
  };
1151
1220
  }
@@ -1249,6 +1318,12 @@ export {
1249
1318
  queryByIndex,
1250
1319
  queryByIndexDeletable,
1251
1320
  queryByIndexSort,
1321
+ pageWindowBudget,
1322
+ listPageWindowBudget,
1323
+ cursorDecode,
1324
+ cursorPathGuard,
1325
+ listCursorPreamble,
1326
+ connectionPageResponse,
1252
1327
  indexConnectionResponseCode,
1253
1328
  indexBackwardPagingGuard,
1254
1329
  indexCursorPreamble,
@@ -1270,6 +1345,7 @@ export {
1270
1345
  putItem,
1271
1346
  addItemToList,
1272
1347
  deleteItem,
1348
+ callerIdentity,
1273
1349
  invokeCommandGenerator,
1274
1350
  invokeDcbMutation,
1275
1351
  invokeInboundTranslation,
@@ -1285,4 +1361,4 @@ export {
1285
1361
  resolveIdsResult,
1286
1362
  $$null,
1287
1363
  }
1288
- /* No side effect */
1364
+ /* indexConnectionResponseCode Not a pure module */
@@ -28,9 +28,7 @@ type args = {
28
28
  mergedApiArn?: Pulumi.Input.t<string>,
29
29
  sourceApiId?: Pulumi.Input.t<string>,
30
30
  sourceApiArn?: Pulumi.Input.t<string>,
31
- sourceApiAssociationConfigs?: Pulumi.Input.t<
32
- array<Pulumi.Input.t<sourceApiAssociationConfig>>,
33
- >,
31
+ sourceApiAssociationConfigs?: Pulumi.Input.t<array<Pulumi.Input.t<sourceApiAssociationConfig>>>,
34
32
  description?: Pulumi.Input.t<string>,
35
33
  }
36
34
 
@@ -1,11 +1,10 @@
1
+ // ── Auth types ────────────────────────────────────────────────────────────────
2
+
1
3
  /** @pulumi/aws-native/appsync/Api — AppSync Events (Pub/Sub) API.
2
4
  Distinct from AppSync GraphQL API (`aws.appsync.GraphQLApi`).
3
5
  Used for real-time server-to-client event push via AppSync Events channels.
4
6
  See: https://www.pulumi.com/registry/packages/aws-native/api-docs/appsync/api
5
7
  */
6
-
7
- // ── Auth types ────────────────────────────────────────────────────────────────
8
-
9
8
  /** Authentication mode for connections / publish / subscribe. */
10
9
  type authMode = {
11
10
  /** Auth type string — use the `authType` constants below. */
@@ -4,7 +4,6 @@
4
4
  Channels within the namespace are addressed as `/default/{channelName}`.
5
5
  See: https://www.pulumi.com/registry/packages/aws-native/api-docs/appsync/channelnamespace
6
6
  */
7
-
8
7
  type authMode = {
9
8
  authType?: Pulumi.Input.t<string>,
10
9
  }
@@ -74,8 +73,5 @@ type args = {
74
73
  }
75
74
 
76
75
  @module("@pulumi/aws-native") @scope("appsync") @new
77
- external make: (
78
- ~name: string,
79
- ~args: args,
80
- ~opts: option<Pulumi.CustomResourceOptions.t>=?,
81
- ) => t = "ChannelNamespace"
76
+ external make: (~name: string, ~args: args, ~opts: option<Pulumi.CustomResourceOptions.t>=?) => t =
77
+ "ChannelNamespace"
@@ -32,8 +32,5 @@ type args = {
32
32
  }
33
33
 
34
34
  @module("@pulumi/aws-native") @scope("appsync") @new
35
- external make: (
36
- ~name: string,
37
- ~args: args,
38
- ~opts: option<Pulumi.CustomResourceOptions.t>=?,
39
- ) => t = "Resolver"
35
+ external make: (~name: string, ~args: args, ~opts: option<Pulumi.CustomResourceOptions.t>=?) => t =
36
+ "Resolver"
@@ -44,6 +44,10 @@ module ScheduleExpression: {
44
44
  type args = {
45
45
  description?: Pulumi.Input.t<string>,
46
46
  scheduleExpression?: ScheduleExpression.t,
47
+ /** JSON event pattern the rule matches on. A rule fires on a schedule or on a
48
+ pattern — set exactly one of the two.
49
+ see: https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-event-patterns.html */
50
+ eventPattern?: Pulumi.Input.t<string>,
47
51
  roleArn?: Pulumi.Input.t<string>,
48
52
  tags?: Pulumi.Input.t<Aws.tags>,
49
53
  }
@@ -17,10 +17,21 @@ module Rule: {
17
17
  let ofEventRule = (rule: Cloudwatch_EventRule.t) => rule.name->Pulumi.Output.asInput
18
18
  }
19
19
 
20
+ /** Rewrites a matched event before it reaches the target. `inputPaths` binds names to
21
+ JSON paths in the event; `inputTemplate` substitutes them where it writes `<name>`.
22
+ A template that is not JSON arrives as plain text — an SNS email body, say.
23
+ see: https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-transform-target-input.html */
24
+ type inputTransformer = {
25
+ inputPaths?: dict<string>,
26
+ inputTemplate: Pulumi.Input.t<string>,
27
+ }
28
+
20
29
  type args = {
21
30
  rule: Rule.t,
22
31
  arn: Pulumi.Input.t<string>,
32
+ /** A fixed payload, sent verbatim. Mutually exclusive with `inputTransformer`. */
23
33
  input?: Pulumi.Input.t<string>,
34
+ inputTransformer?: Pulumi.Input.t<inputTransformer>,
24
35
  }
25
36
 
26
37
  @module("@pulumi/aws") @scope("cloudwatch") @new
@@ -1,7 +1,6 @@
1
1
  /** @pulumi/aws/cloudwatch/logmetricfilter
2
2
  see: https://www.pulumi.com/registry/packages/aws/api-docs/cloudwatch/logmetricfilter/
3
3
  */
4
-
5
4
  /** How matched log events are turned into a CloudWatch metric data point.
6
5
  `value`/`dimensions` use metric-filter JSON selectors (e.g. `"$.value"`). */
7
6
  type metricTransformation = {
@@ -1,7 +1,6 @@
1
1
  /** @pulumi/aws/cloudwatch/metricalarm
2
2
  see: https://www.pulumi.com/registry/packages/aws/api-docs/cloudwatch/metricalarm/
3
3
  */
4
-
5
4
  type t = {arn: Pulumi.Output.t<string>, id: Pulumi.Output.t<string>}
6
5
 
7
6
  /** Single-metric alarm args. `comparisonOperator` uses CloudWatch's operator
@@ -119,7 +119,5 @@ type getResult = {
119
119
  }
120
120
 
121
121
  @module("@pulumi/aws") @scope("cognito") @val
122
- external getUserPoolOutput: (
123
- ~args: getArgs,
124
- ~opts: InvokeOptions.t=?,
125
- ) => Output.t<getResult> = "getUserPoolOutput"
122
+ external getUserPoolOutput: (~args: getArgs, ~opts: InvokeOptions.t=?) => Output.t<getResult> =
123
+ "getUserPoolOutput"
package/src/IAM/IAM.res CHANGED
@@ -103,7 +103,7 @@ module Role = {
103
103
  assumeRolePolicy: servicePrincipal
104
104
  ->Pulumi.Output.apply(principal => Policy.assumeRolePolicy(name, principal))
105
105
  ->Pulumi.Output.asInput,
106
- tags: ?tags,
106
+ ?tags,
107
107
  },
108
108
  ~opts,
109
109
  )