@crossdelta/infrastructure 0.8.1 → 0.8.3

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.
@@ -188,6 +188,8 @@ export interface RuntimeDeploymentConfig {
188
188
  export interface RuntimeDeploymentResult {
189
189
  /** NATS internal URL */
190
190
  natsUrl?: pulumi.Output<string>;
191
+ /** NATS Helm release resource (for dependsOn in downstream jobs) */
192
+ natsRelease?: pulumi.Resource;
191
193
  /** LoadBalancer IP (if ingress enabled) */
192
194
  loadBalancerIp?: pulumi.Output<string>;
193
195
  /** Cert manager ready */
@@ -14,11 +14,11 @@
14
14
  */
15
15
  import type { Provider } from '@pulumi/kubernetes';
16
16
  import * as k8s from '@pulumi/kubernetes';
17
- import type { Output } from '@pulumi/pulumi';
17
+ import type { Output, Resource } from '@pulumi/pulumi';
18
18
  import type { StreamPolicy } from './deploy-streams';
19
19
  import { type ResolvedStream } from './stream-setup';
20
- export type { ResolvedStream };
21
20
  export { computeConfigHash, generateSetupScript, msToNatsDuration, resolveStreams } from './stream-setup';
21
+ export type { ResolvedStream };
22
22
  export interface MaterializeStreamsConfig {
23
23
  /** NATS connection URL (cluster-internal) */
24
24
  natsUrl: Output<string>;
@@ -37,8 +37,10 @@ export interface MaterializeStreamsConfig {
37
37
  image?: string;
38
38
  /** Job TTL after completion in seconds (default: 300) */
39
39
  ttlAfterFinished?: number;
40
- /** Max retry attempts (default: 3) */
40
+ /** Max retry attempts (default: 6) */
41
41
  backoffLimit?: number;
42
+ /** Pulumi resources the Job depends on (e.g., NATS Helm release) */
43
+ dependsOn?: Resource[];
42
44
  }
43
45
  /**
44
46
  * Materialize NATS JetStream streams via a K8s Job.
@@ -35,7 +35,7 @@ export declare const resolveStreams: (definitions: StreamDefinition[], policies?
35
35
  */
36
36
  export declare const generateSetupScript: (streams: ResolvedStream[]) => string;
37
37
  /**
38
- * Compute a short hash from stream config for change detection.
39
- * When config changes, the Job name changes → Pulumi recreates it.
38
+ * Compute a short hash from stream config + script for change detection.
39
+ * When config or script template changes, the Job name changes → Pulumi recreates it.
40
40
  */
41
- export declare const computeConfigHash: (streams: ResolvedStream[]) => string;
41
+ export declare const computeConfigHash: (streams: ResolvedStream[], script?: string) => string;
package/dist/index.cjs CHANGED
@@ -352,7 +352,7 @@ function deployNginxIngress(provider, config = {}) {
352
352
  var k8s3 = __toESM(require("@pulumi/kubernetes"));
353
353
  var pulumi2 = __toESM(require("@pulumi/pulumi"));
354
354
  var NATS_DEFAULTS = {
355
- replicas: 3,
355
+ replicas: 1,
356
356
  jetstream: {
357
357
  enabled: true,
358
358
  storageSize: "20Gi",
@@ -537,6 +537,7 @@ function deployRuntime(provider, namespace, config, runtimeProvider) {
537
537
  if (config.nats?.enabled && providerName === "doks") {
538
538
  const nats = deployNats(provider, namespace, config.nats.config || {});
539
539
  result.natsUrl = pulumi3.output(nats.internalUrl);
540
+ result.natsRelease = nats.release;
540
541
  }
541
542
  if (config.ingress?.enabled && providerName === "doks") {
542
543
  const ingress = deployNginxIngress(provider, config.ingress.config || {});
@@ -1011,6 +1012,20 @@ var generateSetupScript = (streams) => {
1011
1012
  ` NATS_OPTS="$NATS_OPTS --user $NATS_USER --password $NATS_PASSWORD"`,
1012
1013
  `fi`,
1013
1014
  ``,
1015
+ `echo "⏳ Waiting for NATS to become available..."`,
1016
+ `RETRIES=0`,
1017
+ `MAX_RETRIES=30`,
1018
+ `until nats $NATS_OPTS server ping --count 1 > /dev/null 2>&1; do`,
1019
+ ` RETRIES=$((RETRIES + 1))`,
1020
+ ` if [ "$RETRIES" -ge "$MAX_RETRIES" ]; then`,
1021
+ ` echo "❌ NATS not available after $MAX_RETRIES attempts"`,
1022
+ ` exit 1`,
1023
+ ` fi`,
1024
+ ` echo " NATS not ready (attempt $RETRIES/$MAX_RETRIES), retrying in 2s..."`,
1025
+ ` sleep 2`,
1026
+ `done`,
1027
+ `echo "✅ NATS is available"`,
1028
+ ``,
1014
1029
  `echo "\uD83D\uDE80 Materializing ${streams.length} stream(s)..."`,
1015
1030
  `echo ""`,
1016
1031
  ``,
@@ -1020,8 +1035,8 @@ var generateSetupScript = (streams) => {
1020
1035
  ].join(`
1021
1036
  `);
1022
1037
  };
1023
- var computeConfigHash = (streams) => {
1024
- const data = JSON.stringify(streams);
1038
+ var computeConfigHash = (streams, script) => {
1039
+ const data = JSON.stringify(streams) + (script ?? "");
1025
1040
  let hash = 0;
1026
1041
  for (let i = 0;i < data.length; i++) {
1027
1042
  const char = data.charCodeAt(i);
@@ -1045,13 +1060,14 @@ var materializeStreams = (provider, namespace, config) => {
1045
1060
  defaults = DEFAULT_POLICY2,
1046
1061
  image = NATS_BOX_IMAGE,
1047
1062
  ttlAfterFinished = 300,
1048
- backoffLimit = 3
1063
+ backoffLimit = 6,
1064
+ dependsOn: externalDeps = []
1049
1065
  } = config;
1050
1066
  validateStreamDefinitions(contracts);
1051
1067
  const definitions = collectStreamDefinitions(contracts);
1052
1068
  const resolved = resolveStreams(definitions, policies, defaults);
1053
1069
  const script = generateSetupScript(resolved);
1054
- const configHash = computeConfigHash(resolved);
1070
+ const configHash = computeConfigHash(resolved, script);
1055
1071
  console.log(`\uD83D\uDCCB Collecting stream definitions from contracts...`);
1056
1072
  console.log(`✅ Found ${definitions.length} stream(s):`);
1057
1073
  for (const { stream, subjects } of definitions) {
@@ -1067,7 +1083,7 @@ var materializeStreams = (provider, namespace, config) => {
1067
1083
  "setup.sh": script,
1068
1084
  "streams.json": JSON.stringify(resolved, null, 2)
1069
1085
  }
1070
- }, { provider });
1086
+ }, { provider, deleteBeforeReplace: true });
1071
1087
  const envVars = [{ name: "NATS_URL", value: config.natsUrl }];
1072
1088
  if (config.credentials?.user) {
1073
1089
  envVars.push({ name: "NATS_USER", value: config.credentials.user });
@@ -1110,7 +1126,7 @@ var materializeStreams = (provider, namespace, config) => {
1110
1126
  }
1111
1127
  }, {
1112
1128
  provider,
1113
- dependsOn: [configMap],
1129
+ dependsOn: [configMap, ...externalDeps],
1114
1130
  deleteBeforeReplace: true
1115
1131
  });
1116
1132
  return job;
package/dist/index.js CHANGED
@@ -258,7 +258,7 @@ function deployNginxIngress(provider, config = {}) {
258
258
  import * as k8s3 from "@pulumi/kubernetes";
259
259
  import * as pulumi2 from "@pulumi/pulumi";
260
260
  var NATS_DEFAULTS = {
261
- replicas: 3,
261
+ replicas: 1,
262
262
  jetstream: {
263
263
  enabled: true,
264
264
  storageSize: "20Gi",
@@ -443,6 +443,7 @@ function deployRuntime(provider, namespace, config, runtimeProvider) {
443
443
  if (config.nats?.enabled && providerName === "doks") {
444
444
  const nats = deployNats(provider, namespace, config.nats.config || {});
445
445
  result.natsUrl = pulumi3.output(nats.internalUrl);
446
+ result.natsRelease = nats.release;
446
447
  }
447
448
  if (config.ingress?.enabled && providerName === "doks") {
448
449
  const ingress = deployNginxIngress(provider, config.ingress.config || {});
@@ -917,6 +918,20 @@ var generateSetupScript = (streams) => {
917
918
  ` NATS_OPTS="$NATS_OPTS --user $NATS_USER --password $NATS_PASSWORD"`,
918
919
  `fi`,
919
920
  ``,
921
+ `echo "⏳ Waiting for NATS to become available..."`,
922
+ `RETRIES=0`,
923
+ `MAX_RETRIES=30`,
924
+ `until nats $NATS_OPTS server ping --count 1 > /dev/null 2>&1; do`,
925
+ ` RETRIES=$((RETRIES + 1))`,
926
+ ` if [ "$RETRIES" -ge "$MAX_RETRIES" ]; then`,
927
+ ` echo "❌ NATS not available after $MAX_RETRIES attempts"`,
928
+ ` exit 1`,
929
+ ` fi`,
930
+ ` echo " NATS not ready (attempt $RETRIES/$MAX_RETRIES), retrying in 2s..."`,
931
+ ` sleep 2`,
932
+ `done`,
933
+ `echo "✅ NATS is available"`,
934
+ ``,
920
935
  `echo "\uD83D\uDE80 Materializing ${streams.length} stream(s)..."`,
921
936
  `echo ""`,
922
937
  ``,
@@ -926,8 +941,8 @@ var generateSetupScript = (streams) => {
926
941
  ].join(`
927
942
  `);
928
943
  };
929
- var computeConfigHash = (streams) => {
930
- const data = JSON.stringify(streams);
944
+ var computeConfigHash = (streams, script) => {
945
+ const data = JSON.stringify(streams) + (script ?? "");
931
946
  let hash = 0;
932
947
  for (let i = 0;i < data.length; i++) {
933
948
  const char = data.charCodeAt(i);
@@ -951,13 +966,14 @@ var materializeStreams = (provider, namespace, config) => {
951
966
  defaults = DEFAULT_POLICY2,
952
967
  image = NATS_BOX_IMAGE,
953
968
  ttlAfterFinished = 300,
954
- backoffLimit = 3
969
+ backoffLimit = 6,
970
+ dependsOn: externalDeps = []
955
971
  } = config;
956
972
  validateStreamDefinitions(contracts);
957
973
  const definitions = collectStreamDefinitions(contracts);
958
974
  const resolved = resolveStreams(definitions, policies, defaults);
959
975
  const script = generateSetupScript(resolved);
960
- const configHash = computeConfigHash(resolved);
976
+ const configHash = computeConfigHash(resolved, script);
961
977
  console.log(`\uD83D\uDCCB Collecting stream definitions from contracts...`);
962
978
  console.log(`✅ Found ${definitions.length} stream(s):`);
963
979
  for (const { stream, subjects } of definitions) {
@@ -973,7 +989,7 @@ var materializeStreams = (provider, namespace, config) => {
973
989
  "setup.sh": script,
974
990
  "streams.json": JSON.stringify(resolved, null, 2)
975
991
  }
976
- }, { provider });
992
+ }, { provider, deleteBeforeReplace: true });
977
993
  const envVars = [{ name: "NATS_URL", value: config.natsUrl }];
978
994
  if (config.credentials?.user) {
979
995
  envVars.push({ name: "NATS_USER", value: config.credentials.user });
@@ -1016,7 +1032,7 @@ var materializeStreams = (provider, namespace, config) => {
1016
1032
  }
1017
1033
  }, {
1018
1034
  provider,
1019
- dependsOn: [configMap],
1035
+ dependsOn: [configMap, ...externalDeps],
1020
1036
  deleteBeforeReplace: true
1021
1037
  });
1022
1038
  return job;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@crossdelta/infrastructure",
3
- "version": "0.8.1",
3
+ "version": "0.8.3",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "publishConfig": {
@@ -35,7 +35,7 @@
35
35
  }
36
36
  },
37
37
  "dependencies": {
38
- "@crossdelta/cloudevents": "^0.7.14"
38
+ "@crossdelta/cloudevents": "^0.7.18"
39
39
  },
40
40
  "peerDependencies": {
41
41
  "@pulumi/digitalocean": "^4.0.0",