@geekmidas/envkit 0.4.0 → 0.6.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.
Files changed (59) hide show
  1. package/dist/{EnvironmentBuilder-DHfDXJUm.d.mts → EnvironmentBuilder-jF-b7WQg.d.mts} +1 -1
  2. package/dist/{EnvironmentBuilder-DHfDXJUm.d.mts.map → EnvironmentBuilder-jF-b7WQg.d.mts.map} +1 -1
  3. package/dist/EnvironmentBuilder.d.mts +1 -1
  4. package/dist/{EnvironmentParser-CY8TosTN.d.mts → EnvironmentParser-CkLfmn4Y.d.mts} +1 -1
  5. package/dist/{EnvironmentParser-CY8TosTN.d.mts.map → EnvironmentParser-CkLfmn4Y.d.mts.map} +1 -1
  6. package/dist/{EnvironmentParser-Bt246UeP.cjs → EnvironmentParser-DJdW7vOL.cjs} +7 -2
  7. package/dist/EnvironmentParser-DJdW7vOL.cjs.map +1 -0
  8. package/dist/EnvironmentParser-DtOL86NU.d.cts.map +1 -1
  9. package/dist/{EnvironmentParser-c06agx31.mjs → EnvironmentParser-zMblItla.mjs} +7 -2
  10. package/dist/EnvironmentParser-zMblItla.mjs.map +1 -0
  11. package/dist/EnvironmentParser.cjs +2 -1
  12. package/dist/EnvironmentParser.d.mts +1 -1
  13. package/dist/EnvironmentParser.mjs +2 -1
  14. package/dist/SnifferEnvironmentParser.cjs +58 -1
  15. package/dist/SnifferEnvironmentParser.cjs.map +1 -1
  16. package/dist/SnifferEnvironmentParser.d.cts +54 -1
  17. package/dist/SnifferEnvironmentParser.d.cts.map +1 -1
  18. package/dist/SnifferEnvironmentParser.d.mts +55 -2
  19. package/dist/SnifferEnvironmentParser.d.mts.map +1 -1
  20. package/dist/SnifferEnvironmentParser.mjs +58 -2
  21. package/dist/SnifferEnvironmentParser.mjs.map +1 -1
  22. package/dist/{SstEnvironmentBuilder-CjURMGjW.d.mts → SstEnvironmentBuilder-BZngSQKQ.d.mts} +2 -2
  23. package/dist/{SstEnvironmentBuilder-CjURMGjW.d.mts.map → SstEnvironmentBuilder-BZngSQKQ.d.mts.map} +1 -1
  24. package/dist/{SstEnvironmentBuilder-BEBFSUYr.mjs → SstEnvironmentBuilder-DVB7cJq4.mjs} +1 -1
  25. package/dist/{SstEnvironmentBuilder-BEBFSUYr.mjs.map → SstEnvironmentBuilder-DVB7cJq4.mjs.map} +1 -1
  26. package/dist/{SstEnvironmentBuilder-wFnN2M5O.cjs → SstEnvironmentBuilder-jsnqgtcW.cjs} +1 -1
  27. package/dist/{SstEnvironmentBuilder-wFnN2M5O.cjs.map → SstEnvironmentBuilder-jsnqgtcW.cjs.map} +1 -1
  28. package/dist/SstEnvironmentBuilder.cjs +1 -1
  29. package/dist/SstEnvironmentBuilder.d.mts +2 -2
  30. package/dist/SstEnvironmentBuilder.mjs +1 -1
  31. package/dist/formatter-BRRrxQi3.mjs +111 -0
  32. package/dist/formatter-BRRrxQi3.mjs.map +1 -0
  33. package/dist/formatter-Cox0NGxT.d.mts +51 -0
  34. package/dist/formatter-Cox0NGxT.d.mts.map +1 -0
  35. package/dist/formatter-D85aIkpd.d.cts +51 -0
  36. package/dist/formatter-D85aIkpd.d.cts.map +1 -0
  37. package/dist/formatter-HxePpSy2.cjs +123 -0
  38. package/dist/formatter-HxePpSy2.cjs.map +1 -0
  39. package/dist/formatter.cjs +4 -0
  40. package/dist/formatter.d.cts +2 -0
  41. package/dist/formatter.d.mts +2 -0
  42. package/dist/formatter.mjs +3 -0
  43. package/dist/index.cjs +5 -2
  44. package/dist/index.d.cts +2 -1
  45. package/dist/index.d.mts +4 -3
  46. package/dist/index.mjs +3 -2
  47. package/dist/sst.cjs +1 -1
  48. package/dist/sst.d.mts +2 -2
  49. package/dist/sst.mjs +1 -1
  50. package/package.json +1 -1
  51. package/src/EnvironmentParser.ts +7 -2
  52. package/src/SnifferEnvironmentParser.ts +97 -0
  53. package/src/__tests__/SnifferEnvironmentParser.spec.ts +105 -1
  54. package/src/__tests__/formatter.spec.ts +267 -0
  55. package/src/formatter.ts +146 -0
  56. package/src/index.ts +5 -0
  57. package/tsconfig.tsbuildinfo +1 -0
  58. package/dist/EnvironmentParser-Bt246UeP.cjs.map +0 -1
  59. package/dist/EnvironmentParser-c06agx31.mjs.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"SstEnvironmentBuilder-BEBFSUYr.mjs","names":["name: string","value: SecretValue","key: string","value: PostgresValue","value: BucketValue","value: SnsTopicValue","sstResolvers: Resolvers","record: TRecord","additionalResolvers?: CustomResolvers<TRecord>","options?: EnvironmentBuilderOptions","mergedResolvers: Resolvers"],"sources":["../src/SstEnvironmentBuilder.ts"],"sourcesContent":["import {\n\tEnvironmentBuilder,\n\ttype EnvironmentBuilderOptions,\n\ttype EnvironmentResolver,\n\ttype EnvRecord,\n\ttype InputValue,\n\ttype Resolvers,\n} from './EnvironmentBuilder';\n\n/**\n * Enumeration of supported SST (Serverless Stack Toolkit) resource types.\n * Used to identify and process different AWS and SST resources.\n */\nexport enum ResourceType {\n\t// Legacy format (dot notation)\n\tApiGatewayV2 = 'sst.aws.ApiGatewayV2',\n\tPostgres = 'sst.aws.Postgres',\n\tFunction = 'sst.aws.Function',\n\tBucket = 'sst.aws.Bucket',\n\tVpc = 'sst.aws.Vpc',\n\tSecret = 'sst.sst.Secret',\n\n\t// Modern format (colon notation)\n\tSSTSecret = 'sst:sst:Secret',\n\tSSTFunction = 'sst:sst:Function',\n\tSSTApiGatewayV2 = 'sst:aws:ApiGatewayV2',\n\tSSTPostgres = 'sst:aws:Postgres',\n\tSSTBucket = 'sst:aws:Bucket',\n\tSnsTopic = 'sst:aws:SnsTopic',\n}\n\n/**\n * AWS API Gateway V2 resource type.\n * Represents an HTTP/WebSocket API.\n */\nexport type ApiGatewayV2 = {\n\ttype: ResourceType.ApiGatewayV2 | ResourceType.SSTApiGatewayV2;\n\turl: string;\n};\n\n/**\n * PostgreSQL database resource type.\n * Contains all connection details needed to connect to the database.\n */\nexport type Postgres = {\n\ttype: ResourceType.Postgres | ResourceType.SSTPostgres;\n\tdatabase: string;\n\thost: string;\n\tpassword: string;\n\tport: number;\n\tusername: string;\n};\n\n/**\n * AWS Lambda Function resource type.\n */\nexport type Function = {\n\ttype: ResourceType.Function | ResourceType.SSTFunction;\n\tname: string;\n};\n\n/**\n * AWS S3 Bucket resource type.\n */\nexport type Bucket = {\n\ttype: ResourceType.Bucket | ResourceType.SSTBucket;\n\tname: string;\n};\n\n/**\n * AWS VPC (Virtual Private Cloud) resource type.\n */\nexport type Vpc = {\n\ttype: ResourceType.Vpc;\n\tbastion: string;\n};\n\n/**\n * Secret resource type for storing sensitive values.\n */\nexport type Secret = {\n\ttype: ResourceType.Secret | ResourceType.SSTSecret;\n\tvalue: string;\n};\n\n/**\n * AWS SNS Topic resource type.\n */\nexport type SnsTopic = {\n\ttype: ResourceType.SnsTopic;\n\tarn: string;\n};\n\n/**\n * Union type of all supported SST resource types.\n */\nexport type SstResource =\n\t| ApiGatewayV2\n\t| Postgres\n\t| Function\n\t| Bucket\n\t| Vpc\n\t| Secret\n\t| SnsTopic;\n\n// Value types without the `type` key (for resolver parameters)\ntype SecretValue = Omit<Secret, 'type'>;\ntype PostgresValue = Omit<Postgres, 'type'>;\ntype BucketValue = Omit<Bucket, 'type'>;\ntype SnsTopicValue = Omit<SnsTopic, 'type'>;\n\n/**\n * Function type for processing a specific resource type into environment variables.\n *\n * @template K - The specific resource type (without `type` key)\n * @param name - The resource name\n * @param value - The resource value (without `type` key)\n * @returns Object mapping environment variable names to values\n */\nexport type ResourceProcessor<K> = (name: string, value: K) => EnvRecord;\n\n// SST Resource Resolvers (receive values without `type` key)\n\nconst secretResolver = (name: string, value: SecretValue) => ({\n\t[name]: value.value,\n});\n\nconst postgresResolver = (key: string, value: PostgresValue) => ({\n\t[`${key}Name`]: value.database,\n\t[`${key}Host`]: value.host,\n\t[`${key}Password`]: value.password,\n\t[`${key}Port`]: value.port,\n\t[`${key}Username`]: value.username,\n});\n\nconst bucketResolver = (name: string, value: BucketValue) => ({\n\t[`${name}Name`]: value.name,\n});\n\nconst topicResolver = (name: string, value: SnsTopicValue) => ({\n\t[`${name}Arn`]: value.arn,\n});\n\nconst noopResolver = () => ({});\n\n/**\n * Pre-configured resolvers for all SST resource types.\n */\nexport const sstResolvers: Resolvers = {\n\t// Legacy format\n\t[ResourceType.ApiGatewayV2]: noopResolver,\n\t[ResourceType.Function]: noopResolver,\n\t[ResourceType.Vpc]: noopResolver,\n\t[ResourceType.Secret]: secretResolver,\n\t[ResourceType.Postgres]: postgresResolver,\n\t[ResourceType.Bucket]: bucketResolver,\n\n\t// Modern format\n\t[ResourceType.SSTSecret]: secretResolver,\n\t[ResourceType.SSTBucket]: bucketResolver,\n\t[ResourceType.SSTFunction]: noopResolver,\n\t[ResourceType.SSTPostgres]: postgresResolver,\n\t[ResourceType.SSTApiGatewayV2]: noopResolver,\n\t[ResourceType.SnsTopic]: topicResolver,\n};\n\n/**\n * All known SST resource type strings.\n */\ntype SstResourceTypeString = `${ResourceType}`;\n\n/**\n * Extracts the `type` string value from an input value.\n */\ntype ExtractType<T> = T extends { type: infer U extends string } ? U : never;\n\n/**\n * Removes the `type` key from an object type.\n */\ntype OmitType<T> = T extends { type: string } ? Omit<T, 'type'> : never;\n\n/**\n * Extracts all unique `type` values from a record (excluding plain strings).\n */\ntype AllTypeValues<TRecord extends Record<string, InputValue>> = {\n\t[K in keyof TRecord]: ExtractType<TRecord[K]>;\n}[keyof TRecord];\n\n/**\n * Extracts only the custom (non-SST) type values from a record.\n */\ntype CustomTypeValues<TRecord extends Record<string, InputValue>> = Exclude<\n\tAllTypeValues<TRecord>,\n\tSstResourceTypeString\n>;\n\n/**\n * For a given type value, finds the corresponding value type (without `type` key).\n */\ntype ValueForType<\n\tTRecord extends Record<string, InputValue>,\n\tTType extends string,\n> = {\n\t[K in keyof TRecord]: TRecord[K] extends { type: TType }\n\t\t? OmitType<TRecord[K]>\n\t\t: never;\n}[keyof TRecord];\n\n/**\n * Generates typed resolvers for custom (non-SST) types in the input record.\n */\ntype CustomResolvers<TRecord extends Record<string, InputValue>> =\n\tCustomTypeValues<TRecord> extends never\n\t\t? Resolvers | undefined\n\t\t: {\n\t\t\t\t[TType in CustomTypeValues<TRecord>]: EnvironmentResolver<\n\t\t\t\t\tValueForType<TRecord, TType>\n\t\t\t\t>;\n\t\t\t};\n\n/**\n * SST-specific environment builder with built-in resolvers for all known\n * SST resource types.\n *\n * Wraps the generic EnvironmentBuilder with pre-configured SST resolvers.\n *\n * @template TRecord - The input record type for type inference\n *\n * @example\n * ```typescript\n * const env = new SstEnvironmentBuilder({\n * database: { type: 'sst:aws:Postgres', host: '...', ... },\n * apiKey: { type: 'sst:sst:Secret', value: 'secret' },\n * appName: 'my-app',\n * }).build();\n *\n * // With custom resolvers (typed based on input)\n * const env = new SstEnvironmentBuilder(\n * {\n * database: postgresResource,\n * custom: { type: 'my-custom' as const, data: 'foo' },\n * },\n * {\n * // TypeScript requires 'my-custom' resolver with typed value\n * 'my-custom': (key, value) => ({ [`${key}Data`]: value.data }),\n * }\n * ).build();\n * ```\n */\nexport class SstEnvironmentBuilder<\n\tTRecord extends Record<string, SstResource | InputValue | string>,\n> {\n\tprivate readonly builder: EnvironmentBuilder<\n\t\tRecord<string, InputValue>,\n\t\tResolvers\n\t>;\n\n\t/**\n\t * Create a new SST environment builder.\n\t *\n\t * @param record - Object containing SST resources, custom resources, and/or string values\n\t * @param additionalResolvers - Optional custom resolvers (typed based on custom types in record)\n\t * @param options - Optional configuration options\n\t */\n\tconstructor(\n\t\trecord: TRecord,\n\t\tadditionalResolvers?: CustomResolvers<TRecord>,\n\t\toptions?: EnvironmentBuilderOptions,\n\t) {\n\t\t// Merge resolvers with custom ones taking precedence\n\t\tconst mergedResolvers: Resolvers = additionalResolvers\n\t\t\t? { ...sstResolvers, ...additionalResolvers }\n\t\t\t: sstResolvers;\n\n\t\tthis.builder = new EnvironmentBuilder(\n\t\t\trecord as Record<string, InputValue>,\n\t\t\tmergedResolvers,\n\t\t\toptions,\n\t\t);\n\t}\n\n\t/**\n\t * Build environment variables from the input record.\n\t *\n\t * @returns A record of environment variables\n\t */\n\tbuild(): EnvRecord {\n\t\treturn this.builder.build();\n\t}\n}\n\nexport type {\n\tEnvironmentBuilderOptions,\n\tEnvRecord,\n\tEnvValue,\n} from './EnvironmentBuilder';\n// Re-export useful types\nexport { environmentCase } from './EnvironmentBuilder';\n"],"mappings":";;;;;;;AAaA,IAAY,wDAAL;AAEN;AACA;AACA;AACA;AACA;AACA;AAGA;AACA;AACA;AACA;AACA;AACA;;AACA;AA8FD,MAAM,iBAAiB,CAACA,MAAcC,WAAwB,GAC5D,OAAO,MAAM,MACd;AAED,MAAM,mBAAmB,CAACC,KAAaC,WAA0B;GAC9D,EAAE,IAAI,QAAQ,MAAM;GACpB,EAAE,IAAI,QAAQ,MAAM;GACpB,EAAE,IAAI,YAAY,MAAM;GACxB,EAAE,IAAI,QAAQ,MAAM;GACpB,EAAE,IAAI,YAAY,MAAM;AAC1B;AAED,MAAM,iBAAiB,CAACH,MAAcI,WAAwB,IAC3D,EAAE,KAAK,QAAQ,MAAM,KACvB;AAED,MAAM,gBAAgB,CAACJ,MAAcK,WAA0B,IAC5D,EAAE,KAAK,OAAO,MAAM,IACtB;AAED,MAAM,eAAe,OAAO,CAAE;;;;AAK9B,MAAaC,eAA0B;EAErC,aAAa,eAAe;EAC5B,aAAa,WAAW;EACxB,aAAa,MAAM;EACnB,aAAa,SAAS;EACtB,aAAa,WAAW;EACxB,aAAa,SAAS;EAGtB,aAAa,YAAY;EACzB,aAAa,YAAY;EACzB,aAAa,cAAc;EAC3B,aAAa,cAAc;EAC3B,aAAa,kBAAkB;EAC/B,aAAa,WAAW;AACzB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqFD,IAAa,wBAAb,MAEE;CACD,AAAiB;;;;;;;;CAYjB,YACCC,QACAC,qBACAC,SACC;EAED,MAAMC,kBAA6B,sBAChC;GAAE,GAAG;GAAc,GAAG;EAAqB,IAC3C;AAEH,OAAK,UAAU,IAAI,mBAClB,QACA,iBACA;CAED;;;;;;CAOD,QAAmB;AAClB,SAAO,KAAK,QAAQ,OAAO;CAC3B;AACD"}
1
+ {"version":3,"file":"SstEnvironmentBuilder-DVB7cJq4.mjs","names":["name: string","value: SecretValue","key: string","value: PostgresValue","value: BucketValue","value: SnsTopicValue","sstResolvers: Resolvers","record: TRecord","additionalResolvers?: CustomResolvers<TRecord>","options?: EnvironmentBuilderOptions","mergedResolvers: Resolvers"],"sources":["../src/SstEnvironmentBuilder.ts"],"sourcesContent":["import {\n\tEnvironmentBuilder,\n\ttype EnvironmentBuilderOptions,\n\ttype EnvironmentResolver,\n\ttype EnvRecord,\n\ttype InputValue,\n\ttype Resolvers,\n} from './EnvironmentBuilder';\n\n/**\n * Enumeration of supported SST (Serverless Stack Toolkit) resource types.\n * Used to identify and process different AWS and SST resources.\n */\nexport enum ResourceType {\n\t// Legacy format (dot notation)\n\tApiGatewayV2 = 'sst.aws.ApiGatewayV2',\n\tPostgres = 'sst.aws.Postgres',\n\tFunction = 'sst.aws.Function',\n\tBucket = 'sst.aws.Bucket',\n\tVpc = 'sst.aws.Vpc',\n\tSecret = 'sst.sst.Secret',\n\n\t// Modern format (colon notation)\n\tSSTSecret = 'sst:sst:Secret',\n\tSSTFunction = 'sst:sst:Function',\n\tSSTApiGatewayV2 = 'sst:aws:ApiGatewayV2',\n\tSSTPostgres = 'sst:aws:Postgres',\n\tSSTBucket = 'sst:aws:Bucket',\n\tSnsTopic = 'sst:aws:SnsTopic',\n}\n\n/**\n * AWS API Gateway V2 resource type.\n * Represents an HTTP/WebSocket API.\n */\nexport type ApiGatewayV2 = {\n\ttype: ResourceType.ApiGatewayV2 | ResourceType.SSTApiGatewayV2;\n\turl: string;\n};\n\n/**\n * PostgreSQL database resource type.\n * Contains all connection details needed to connect to the database.\n */\nexport type Postgres = {\n\ttype: ResourceType.Postgres | ResourceType.SSTPostgres;\n\tdatabase: string;\n\thost: string;\n\tpassword: string;\n\tport: number;\n\tusername: string;\n};\n\n/**\n * AWS Lambda Function resource type.\n */\nexport type Function = {\n\ttype: ResourceType.Function | ResourceType.SSTFunction;\n\tname: string;\n};\n\n/**\n * AWS S3 Bucket resource type.\n */\nexport type Bucket = {\n\ttype: ResourceType.Bucket | ResourceType.SSTBucket;\n\tname: string;\n};\n\n/**\n * AWS VPC (Virtual Private Cloud) resource type.\n */\nexport type Vpc = {\n\ttype: ResourceType.Vpc;\n\tbastion: string;\n};\n\n/**\n * Secret resource type for storing sensitive values.\n */\nexport type Secret = {\n\ttype: ResourceType.Secret | ResourceType.SSTSecret;\n\tvalue: string;\n};\n\n/**\n * AWS SNS Topic resource type.\n */\nexport type SnsTopic = {\n\ttype: ResourceType.SnsTopic;\n\tarn: string;\n};\n\n/**\n * Union type of all supported SST resource types.\n */\nexport type SstResource =\n\t| ApiGatewayV2\n\t| Postgres\n\t| Function\n\t| Bucket\n\t| Vpc\n\t| Secret\n\t| SnsTopic;\n\n// Value types without the `type` key (for resolver parameters)\ntype SecretValue = Omit<Secret, 'type'>;\ntype PostgresValue = Omit<Postgres, 'type'>;\ntype BucketValue = Omit<Bucket, 'type'>;\ntype SnsTopicValue = Omit<SnsTopic, 'type'>;\n\n/**\n * Function type for processing a specific resource type into environment variables.\n *\n * @template K - The specific resource type (without `type` key)\n * @param name - The resource name\n * @param value - The resource value (without `type` key)\n * @returns Object mapping environment variable names to values\n */\nexport type ResourceProcessor<K> = (name: string, value: K) => EnvRecord;\n\n// SST Resource Resolvers (receive values without `type` key)\n\nconst secretResolver = (name: string, value: SecretValue) => ({\n\t[name]: value.value,\n});\n\nconst postgresResolver = (key: string, value: PostgresValue) => ({\n\t[`${key}Name`]: value.database,\n\t[`${key}Host`]: value.host,\n\t[`${key}Password`]: value.password,\n\t[`${key}Port`]: value.port,\n\t[`${key}Username`]: value.username,\n});\n\nconst bucketResolver = (name: string, value: BucketValue) => ({\n\t[`${name}Name`]: value.name,\n});\n\nconst topicResolver = (name: string, value: SnsTopicValue) => ({\n\t[`${name}Arn`]: value.arn,\n});\n\nconst noopResolver = () => ({});\n\n/**\n * Pre-configured resolvers for all SST resource types.\n */\nexport const sstResolvers: Resolvers = {\n\t// Legacy format\n\t[ResourceType.ApiGatewayV2]: noopResolver,\n\t[ResourceType.Function]: noopResolver,\n\t[ResourceType.Vpc]: noopResolver,\n\t[ResourceType.Secret]: secretResolver,\n\t[ResourceType.Postgres]: postgresResolver,\n\t[ResourceType.Bucket]: bucketResolver,\n\n\t// Modern format\n\t[ResourceType.SSTSecret]: secretResolver,\n\t[ResourceType.SSTBucket]: bucketResolver,\n\t[ResourceType.SSTFunction]: noopResolver,\n\t[ResourceType.SSTPostgres]: postgresResolver,\n\t[ResourceType.SSTApiGatewayV2]: noopResolver,\n\t[ResourceType.SnsTopic]: topicResolver,\n};\n\n/**\n * All known SST resource type strings.\n */\ntype SstResourceTypeString = `${ResourceType}`;\n\n/**\n * Extracts the `type` string value from an input value.\n */\ntype ExtractType<T> = T extends { type: infer U extends string } ? U : never;\n\n/**\n * Removes the `type` key from an object type.\n */\ntype OmitType<T> = T extends { type: string } ? Omit<T, 'type'> : never;\n\n/**\n * Extracts all unique `type` values from a record (excluding plain strings).\n */\ntype AllTypeValues<TRecord extends Record<string, InputValue>> = {\n\t[K in keyof TRecord]: ExtractType<TRecord[K]>;\n}[keyof TRecord];\n\n/**\n * Extracts only the custom (non-SST) type values from a record.\n */\ntype CustomTypeValues<TRecord extends Record<string, InputValue>> = Exclude<\n\tAllTypeValues<TRecord>,\n\tSstResourceTypeString\n>;\n\n/**\n * For a given type value, finds the corresponding value type (without `type` key).\n */\ntype ValueForType<\n\tTRecord extends Record<string, InputValue>,\n\tTType extends string,\n> = {\n\t[K in keyof TRecord]: TRecord[K] extends { type: TType }\n\t\t? OmitType<TRecord[K]>\n\t\t: never;\n}[keyof TRecord];\n\n/**\n * Generates typed resolvers for custom (non-SST) types in the input record.\n */\ntype CustomResolvers<TRecord extends Record<string, InputValue>> =\n\tCustomTypeValues<TRecord> extends never\n\t\t? Resolvers | undefined\n\t\t: {\n\t\t\t\t[TType in CustomTypeValues<TRecord>]: EnvironmentResolver<\n\t\t\t\t\tValueForType<TRecord, TType>\n\t\t\t\t>;\n\t\t\t};\n\n/**\n * SST-specific environment builder with built-in resolvers for all known\n * SST resource types.\n *\n * Wraps the generic EnvironmentBuilder with pre-configured SST resolvers.\n *\n * @template TRecord - The input record type for type inference\n *\n * @example\n * ```typescript\n * const env = new SstEnvironmentBuilder({\n * database: { type: 'sst:aws:Postgres', host: '...', ... },\n * apiKey: { type: 'sst:sst:Secret', value: 'secret' },\n * appName: 'my-app',\n * }).build();\n *\n * // With custom resolvers (typed based on input)\n * const env = new SstEnvironmentBuilder(\n * {\n * database: postgresResource,\n * custom: { type: 'my-custom' as const, data: 'foo' },\n * },\n * {\n * // TypeScript requires 'my-custom' resolver with typed value\n * 'my-custom': (key, value) => ({ [`${key}Data`]: value.data }),\n * }\n * ).build();\n * ```\n */\nexport class SstEnvironmentBuilder<\n\tTRecord extends Record<string, SstResource | InputValue | string>,\n> {\n\tprivate readonly builder: EnvironmentBuilder<\n\t\tRecord<string, InputValue>,\n\t\tResolvers\n\t>;\n\n\t/**\n\t * Create a new SST environment builder.\n\t *\n\t * @param record - Object containing SST resources, custom resources, and/or string values\n\t * @param additionalResolvers - Optional custom resolvers (typed based on custom types in record)\n\t * @param options - Optional configuration options\n\t */\n\tconstructor(\n\t\trecord: TRecord,\n\t\tadditionalResolvers?: CustomResolvers<TRecord>,\n\t\toptions?: EnvironmentBuilderOptions,\n\t) {\n\t\t// Merge resolvers with custom ones taking precedence\n\t\tconst mergedResolvers: Resolvers = additionalResolvers\n\t\t\t? { ...sstResolvers, ...additionalResolvers }\n\t\t\t: sstResolvers;\n\n\t\tthis.builder = new EnvironmentBuilder(\n\t\t\trecord as Record<string, InputValue>,\n\t\t\tmergedResolvers,\n\t\t\toptions,\n\t\t);\n\t}\n\n\t/**\n\t * Build environment variables from the input record.\n\t *\n\t * @returns A record of environment variables\n\t */\n\tbuild(): EnvRecord {\n\t\treturn this.builder.build();\n\t}\n}\n\nexport type {\n\tEnvironmentBuilderOptions,\n\tEnvRecord,\n\tEnvValue,\n} from './EnvironmentBuilder';\n// Re-export useful types\nexport { environmentCase } from './EnvironmentBuilder';\n"],"mappings":";;;;;;;AAaA,IAAY,wDAAL;AAEN;AACA;AACA;AACA;AACA;AACA;AAGA;AACA;AACA;AACA;AACA;AACA;;AACA;AA8FD,MAAM,iBAAiB,CAACA,MAAcC,WAAwB,GAC5D,OAAO,MAAM,MACd;AAED,MAAM,mBAAmB,CAACC,KAAaC,WAA0B;GAC9D,EAAE,IAAI,QAAQ,MAAM;GACpB,EAAE,IAAI,QAAQ,MAAM;GACpB,EAAE,IAAI,YAAY,MAAM;GACxB,EAAE,IAAI,QAAQ,MAAM;GACpB,EAAE,IAAI,YAAY,MAAM;AAC1B;AAED,MAAM,iBAAiB,CAACH,MAAcI,WAAwB,IAC3D,EAAE,KAAK,QAAQ,MAAM,KACvB;AAED,MAAM,gBAAgB,CAACJ,MAAcK,WAA0B,IAC5D,EAAE,KAAK,OAAO,MAAM,IACtB;AAED,MAAM,eAAe,OAAO,CAAE;;;;AAK9B,MAAaC,eAA0B;EAErC,aAAa,eAAe;EAC5B,aAAa,WAAW;EACxB,aAAa,MAAM;EACnB,aAAa,SAAS;EACtB,aAAa,WAAW;EACxB,aAAa,SAAS;EAGtB,aAAa,YAAY;EACzB,aAAa,YAAY;EACzB,aAAa,cAAc;EAC3B,aAAa,cAAc;EAC3B,aAAa,kBAAkB;EAC/B,aAAa,WAAW;AACzB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqFD,IAAa,wBAAb,MAEE;CACD,AAAiB;;;;;;;;CAYjB,YACCC,QACAC,qBACAC,SACC;EAED,MAAMC,kBAA6B,sBAChC;GAAE,GAAG;GAAc,GAAG;EAAqB,IAC3C;AAEH,OAAK,UAAU,IAAI,mBAClB,QACA,iBACA;CAED;;;;;;CAOD,QAAmB;AAClB,SAAO,KAAK,QAAQ,OAAO;CAC3B;AACD"}
@@ -122,4 +122,4 @@ Object.defineProperty(exports, 'sstResolvers', {
122
122
  return sstResolvers;
123
123
  }
124
124
  });
125
- //# sourceMappingURL=SstEnvironmentBuilder-wFnN2M5O.cjs.map
125
+ //# sourceMappingURL=SstEnvironmentBuilder-jsnqgtcW.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"SstEnvironmentBuilder-wFnN2M5O.cjs","names":["name: string","value: SecretValue","key: string","value: PostgresValue","value: BucketValue","value: SnsTopicValue","sstResolvers: Resolvers","record: TRecord","additionalResolvers?: CustomResolvers<TRecord>","options?: EnvironmentBuilderOptions","mergedResolvers: Resolvers","EnvironmentBuilder"],"sources":["../src/SstEnvironmentBuilder.ts"],"sourcesContent":["import {\n\tEnvironmentBuilder,\n\ttype EnvironmentBuilderOptions,\n\ttype EnvironmentResolver,\n\ttype EnvRecord,\n\ttype InputValue,\n\ttype Resolvers,\n} from './EnvironmentBuilder';\n\n/**\n * Enumeration of supported SST (Serverless Stack Toolkit) resource types.\n * Used to identify and process different AWS and SST resources.\n */\nexport enum ResourceType {\n\t// Legacy format (dot notation)\n\tApiGatewayV2 = 'sst.aws.ApiGatewayV2',\n\tPostgres = 'sst.aws.Postgres',\n\tFunction = 'sst.aws.Function',\n\tBucket = 'sst.aws.Bucket',\n\tVpc = 'sst.aws.Vpc',\n\tSecret = 'sst.sst.Secret',\n\n\t// Modern format (colon notation)\n\tSSTSecret = 'sst:sst:Secret',\n\tSSTFunction = 'sst:sst:Function',\n\tSSTApiGatewayV2 = 'sst:aws:ApiGatewayV2',\n\tSSTPostgres = 'sst:aws:Postgres',\n\tSSTBucket = 'sst:aws:Bucket',\n\tSnsTopic = 'sst:aws:SnsTopic',\n}\n\n/**\n * AWS API Gateway V2 resource type.\n * Represents an HTTP/WebSocket API.\n */\nexport type ApiGatewayV2 = {\n\ttype: ResourceType.ApiGatewayV2 | ResourceType.SSTApiGatewayV2;\n\turl: string;\n};\n\n/**\n * PostgreSQL database resource type.\n * Contains all connection details needed to connect to the database.\n */\nexport type Postgres = {\n\ttype: ResourceType.Postgres | ResourceType.SSTPostgres;\n\tdatabase: string;\n\thost: string;\n\tpassword: string;\n\tport: number;\n\tusername: string;\n};\n\n/**\n * AWS Lambda Function resource type.\n */\nexport type Function = {\n\ttype: ResourceType.Function | ResourceType.SSTFunction;\n\tname: string;\n};\n\n/**\n * AWS S3 Bucket resource type.\n */\nexport type Bucket = {\n\ttype: ResourceType.Bucket | ResourceType.SSTBucket;\n\tname: string;\n};\n\n/**\n * AWS VPC (Virtual Private Cloud) resource type.\n */\nexport type Vpc = {\n\ttype: ResourceType.Vpc;\n\tbastion: string;\n};\n\n/**\n * Secret resource type for storing sensitive values.\n */\nexport type Secret = {\n\ttype: ResourceType.Secret | ResourceType.SSTSecret;\n\tvalue: string;\n};\n\n/**\n * AWS SNS Topic resource type.\n */\nexport type SnsTopic = {\n\ttype: ResourceType.SnsTopic;\n\tarn: string;\n};\n\n/**\n * Union type of all supported SST resource types.\n */\nexport type SstResource =\n\t| ApiGatewayV2\n\t| Postgres\n\t| Function\n\t| Bucket\n\t| Vpc\n\t| Secret\n\t| SnsTopic;\n\n// Value types without the `type` key (for resolver parameters)\ntype SecretValue = Omit<Secret, 'type'>;\ntype PostgresValue = Omit<Postgres, 'type'>;\ntype BucketValue = Omit<Bucket, 'type'>;\ntype SnsTopicValue = Omit<SnsTopic, 'type'>;\n\n/**\n * Function type for processing a specific resource type into environment variables.\n *\n * @template K - The specific resource type (without `type` key)\n * @param name - The resource name\n * @param value - The resource value (without `type` key)\n * @returns Object mapping environment variable names to values\n */\nexport type ResourceProcessor<K> = (name: string, value: K) => EnvRecord;\n\n// SST Resource Resolvers (receive values without `type` key)\n\nconst secretResolver = (name: string, value: SecretValue) => ({\n\t[name]: value.value,\n});\n\nconst postgresResolver = (key: string, value: PostgresValue) => ({\n\t[`${key}Name`]: value.database,\n\t[`${key}Host`]: value.host,\n\t[`${key}Password`]: value.password,\n\t[`${key}Port`]: value.port,\n\t[`${key}Username`]: value.username,\n});\n\nconst bucketResolver = (name: string, value: BucketValue) => ({\n\t[`${name}Name`]: value.name,\n});\n\nconst topicResolver = (name: string, value: SnsTopicValue) => ({\n\t[`${name}Arn`]: value.arn,\n});\n\nconst noopResolver = () => ({});\n\n/**\n * Pre-configured resolvers for all SST resource types.\n */\nexport const sstResolvers: Resolvers = {\n\t// Legacy format\n\t[ResourceType.ApiGatewayV2]: noopResolver,\n\t[ResourceType.Function]: noopResolver,\n\t[ResourceType.Vpc]: noopResolver,\n\t[ResourceType.Secret]: secretResolver,\n\t[ResourceType.Postgres]: postgresResolver,\n\t[ResourceType.Bucket]: bucketResolver,\n\n\t// Modern format\n\t[ResourceType.SSTSecret]: secretResolver,\n\t[ResourceType.SSTBucket]: bucketResolver,\n\t[ResourceType.SSTFunction]: noopResolver,\n\t[ResourceType.SSTPostgres]: postgresResolver,\n\t[ResourceType.SSTApiGatewayV2]: noopResolver,\n\t[ResourceType.SnsTopic]: topicResolver,\n};\n\n/**\n * All known SST resource type strings.\n */\ntype SstResourceTypeString = `${ResourceType}`;\n\n/**\n * Extracts the `type` string value from an input value.\n */\ntype ExtractType<T> = T extends { type: infer U extends string } ? U : never;\n\n/**\n * Removes the `type` key from an object type.\n */\ntype OmitType<T> = T extends { type: string } ? Omit<T, 'type'> : never;\n\n/**\n * Extracts all unique `type` values from a record (excluding plain strings).\n */\ntype AllTypeValues<TRecord extends Record<string, InputValue>> = {\n\t[K in keyof TRecord]: ExtractType<TRecord[K]>;\n}[keyof TRecord];\n\n/**\n * Extracts only the custom (non-SST) type values from a record.\n */\ntype CustomTypeValues<TRecord extends Record<string, InputValue>> = Exclude<\n\tAllTypeValues<TRecord>,\n\tSstResourceTypeString\n>;\n\n/**\n * For a given type value, finds the corresponding value type (without `type` key).\n */\ntype ValueForType<\n\tTRecord extends Record<string, InputValue>,\n\tTType extends string,\n> = {\n\t[K in keyof TRecord]: TRecord[K] extends { type: TType }\n\t\t? OmitType<TRecord[K]>\n\t\t: never;\n}[keyof TRecord];\n\n/**\n * Generates typed resolvers for custom (non-SST) types in the input record.\n */\ntype CustomResolvers<TRecord extends Record<string, InputValue>> =\n\tCustomTypeValues<TRecord> extends never\n\t\t? Resolvers | undefined\n\t\t: {\n\t\t\t\t[TType in CustomTypeValues<TRecord>]: EnvironmentResolver<\n\t\t\t\t\tValueForType<TRecord, TType>\n\t\t\t\t>;\n\t\t\t};\n\n/**\n * SST-specific environment builder with built-in resolvers for all known\n * SST resource types.\n *\n * Wraps the generic EnvironmentBuilder with pre-configured SST resolvers.\n *\n * @template TRecord - The input record type for type inference\n *\n * @example\n * ```typescript\n * const env = new SstEnvironmentBuilder({\n * database: { type: 'sst:aws:Postgres', host: '...', ... },\n * apiKey: { type: 'sst:sst:Secret', value: 'secret' },\n * appName: 'my-app',\n * }).build();\n *\n * // With custom resolvers (typed based on input)\n * const env = new SstEnvironmentBuilder(\n * {\n * database: postgresResource,\n * custom: { type: 'my-custom' as const, data: 'foo' },\n * },\n * {\n * // TypeScript requires 'my-custom' resolver with typed value\n * 'my-custom': (key, value) => ({ [`${key}Data`]: value.data }),\n * }\n * ).build();\n * ```\n */\nexport class SstEnvironmentBuilder<\n\tTRecord extends Record<string, SstResource | InputValue | string>,\n> {\n\tprivate readonly builder: EnvironmentBuilder<\n\t\tRecord<string, InputValue>,\n\t\tResolvers\n\t>;\n\n\t/**\n\t * Create a new SST environment builder.\n\t *\n\t * @param record - Object containing SST resources, custom resources, and/or string values\n\t * @param additionalResolvers - Optional custom resolvers (typed based on custom types in record)\n\t * @param options - Optional configuration options\n\t */\n\tconstructor(\n\t\trecord: TRecord,\n\t\tadditionalResolvers?: CustomResolvers<TRecord>,\n\t\toptions?: EnvironmentBuilderOptions,\n\t) {\n\t\t// Merge resolvers with custom ones taking precedence\n\t\tconst mergedResolvers: Resolvers = additionalResolvers\n\t\t\t? { ...sstResolvers, ...additionalResolvers }\n\t\t\t: sstResolvers;\n\n\t\tthis.builder = new EnvironmentBuilder(\n\t\t\trecord as Record<string, InputValue>,\n\t\t\tmergedResolvers,\n\t\t\toptions,\n\t\t);\n\t}\n\n\t/**\n\t * Build environment variables from the input record.\n\t *\n\t * @returns A record of environment variables\n\t */\n\tbuild(): EnvRecord {\n\t\treturn this.builder.build();\n\t}\n}\n\nexport type {\n\tEnvironmentBuilderOptions,\n\tEnvRecord,\n\tEnvValue,\n} from './EnvironmentBuilder';\n// Re-export useful types\nexport { environmentCase } from './EnvironmentBuilder';\n"],"mappings":";;;;;;;AAaA,IAAY,wDAAL;AAEN;AACA;AACA;AACA;AACA;AACA;AAGA;AACA;AACA;AACA;AACA;AACA;;AACA;AA8FD,MAAM,iBAAiB,CAACA,MAAcC,WAAwB,GAC5D,OAAO,MAAM,MACd;AAED,MAAM,mBAAmB,CAACC,KAAaC,WAA0B;GAC9D,EAAE,IAAI,QAAQ,MAAM;GACpB,EAAE,IAAI,QAAQ,MAAM;GACpB,EAAE,IAAI,YAAY,MAAM;GACxB,EAAE,IAAI,QAAQ,MAAM;GACpB,EAAE,IAAI,YAAY,MAAM;AAC1B;AAED,MAAM,iBAAiB,CAACH,MAAcI,WAAwB,IAC3D,EAAE,KAAK,QAAQ,MAAM,KACvB;AAED,MAAM,gBAAgB,CAACJ,MAAcK,WAA0B,IAC5D,EAAE,KAAK,OAAO,MAAM,IACtB;AAED,MAAM,eAAe,OAAO,CAAE;;;;AAK9B,MAAaC,eAA0B;EAErC,aAAa,eAAe;EAC5B,aAAa,WAAW;EACxB,aAAa,MAAM;EACnB,aAAa,SAAS;EACtB,aAAa,WAAW;EACxB,aAAa,SAAS;EAGtB,aAAa,YAAY;EACzB,aAAa,YAAY;EACzB,aAAa,cAAc;EAC3B,aAAa,cAAc;EAC3B,aAAa,kBAAkB;EAC/B,aAAa,WAAW;AACzB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqFD,IAAa,wBAAb,MAEE;CACD,AAAiB;;;;;;;;CAYjB,YACCC,QACAC,qBACAC,SACC;EAED,MAAMC,kBAA6B,sBAChC;GAAE,GAAG;GAAc,GAAG;EAAqB,IAC3C;AAEH,OAAK,UAAU,IAAIC,8CAClB,QACA,iBACA;CAED;;;;;;CAOD,QAAmB;AAClB,SAAO,KAAK,QAAQ,OAAO;CAC3B;AACD"}
1
+ {"version":3,"file":"SstEnvironmentBuilder-jsnqgtcW.cjs","names":["name: string","value: SecretValue","key: string","value: PostgresValue","value: BucketValue","value: SnsTopicValue","sstResolvers: Resolvers","record: TRecord","additionalResolvers?: CustomResolvers<TRecord>","options?: EnvironmentBuilderOptions","mergedResolvers: Resolvers","EnvironmentBuilder"],"sources":["../src/SstEnvironmentBuilder.ts"],"sourcesContent":["import {\n\tEnvironmentBuilder,\n\ttype EnvironmentBuilderOptions,\n\ttype EnvironmentResolver,\n\ttype EnvRecord,\n\ttype InputValue,\n\ttype Resolvers,\n} from './EnvironmentBuilder';\n\n/**\n * Enumeration of supported SST (Serverless Stack Toolkit) resource types.\n * Used to identify and process different AWS and SST resources.\n */\nexport enum ResourceType {\n\t// Legacy format (dot notation)\n\tApiGatewayV2 = 'sst.aws.ApiGatewayV2',\n\tPostgres = 'sst.aws.Postgres',\n\tFunction = 'sst.aws.Function',\n\tBucket = 'sst.aws.Bucket',\n\tVpc = 'sst.aws.Vpc',\n\tSecret = 'sst.sst.Secret',\n\n\t// Modern format (colon notation)\n\tSSTSecret = 'sst:sst:Secret',\n\tSSTFunction = 'sst:sst:Function',\n\tSSTApiGatewayV2 = 'sst:aws:ApiGatewayV2',\n\tSSTPostgres = 'sst:aws:Postgres',\n\tSSTBucket = 'sst:aws:Bucket',\n\tSnsTopic = 'sst:aws:SnsTopic',\n}\n\n/**\n * AWS API Gateway V2 resource type.\n * Represents an HTTP/WebSocket API.\n */\nexport type ApiGatewayV2 = {\n\ttype: ResourceType.ApiGatewayV2 | ResourceType.SSTApiGatewayV2;\n\turl: string;\n};\n\n/**\n * PostgreSQL database resource type.\n * Contains all connection details needed to connect to the database.\n */\nexport type Postgres = {\n\ttype: ResourceType.Postgres | ResourceType.SSTPostgres;\n\tdatabase: string;\n\thost: string;\n\tpassword: string;\n\tport: number;\n\tusername: string;\n};\n\n/**\n * AWS Lambda Function resource type.\n */\nexport type Function = {\n\ttype: ResourceType.Function | ResourceType.SSTFunction;\n\tname: string;\n};\n\n/**\n * AWS S3 Bucket resource type.\n */\nexport type Bucket = {\n\ttype: ResourceType.Bucket | ResourceType.SSTBucket;\n\tname: string;\n};\n\n/**\n * AWS VPC (Virtual Private Cloud) resource type.\n */\nexport type Vpc = {\n\ttype: ResourceType.Vpc;\n\tbastion: string;\n};\n\n/**\n * Secret resource type for storing sensitive values.\n */\nexport type Secret = {\n\ttype: ResourceType.Secret | ResourceType.SSTSecret;\n\tvalue: string;\n};\n\n/**\n * AWS SNS Topic resource type.\n */\nexport type SnsTopic = {\n\ttype: ResourceType.SnsTopic;\n\tarn: string;\n};\n\n/**\n * Union type of all supported SST resource types.\n */\nexport type SstResource =\n\t| ApiGatewayV2\n\t| Postgres\n\t| Function\n\t| Bucket\n\t| Vpc\n\t| Secret\n\t| SnsTopic;\n\n// Value types without the `type` key (for resolver parameters)\ntype SecretValue = Omit<Secret, 'type'>;\ntype PostgresValue = Omit<Postgres, 'type'>;\ntype BucketValue = Omit<Bucket, 'type'>;\ntype SnsTopicValue = Omit<SnsTopic, 'type'>;\n\n/**\n * Function type for processing a specific resource type into environment variables.\n *\n * @template K - The specific resource type (without `type` key)\n * @param name - The resource name\n * @param value - The resource value (without `type` key)\n * @returns Object mapping environment variable names to values\n */\nexport type ResourceProcessor<K> = (name: string, value: K) => EnvRecord;\n\n// SST Resource Resolvers (receive values without `type` key)\n\nconst secretResolver = (name: string, value: SecretValue) => ({\n\t[name]: value.value,\n});\n\nconst postgresResolver = (key: string, value: PostgresValue) => ({\n\t[`${key}Name`]: value.database,\n\t[`${key}Host`]: value.host,\n\t[`${key}Password`]: value.password,\n\t[`${key}Port`]: value.port,\n\t[`${key}Username`]: value.username,\n});\n\nconst bucketResolver = (name: string, value: BucketValue) => ({\n\t[`${name}Name`]: value.name,\n});\n\nconst topicResolver = (name: string, value: SnsTopicValue) => ({\n\t[`${name}Arn`]: value.arn,\n});\n\nconst noopResolver = () => ({});\n\n/**\n * Pre-configured resolvers for all SST resource types.\n */\nexport const sstResolvers: Resolvers = {\n\t// Legacy format\n\t[ResourceType.ApiGatewayV2]: noopResolver,\n\t[ResourceType.Function]: noopResolver,\n\t[ResourceType.Vpc]: noopResolver,\n\t[ResourceType.Secret]: secretResolver,\n\t[ResourceType.Postgres]: postgresResolver,\n\t[ResourceType.Bucket]: bucketResolver,\n\n\t// Modern format\n\t[ResourceType.SSTSecret]: secretResolver,\n\t[ResourceType.SSTBucket]: bucketResolver,\n\t[ResourceType.SSTFunction]: noopResolver,\n\t[ResourceType.SSTPostgres]: postgresResolver,\n\t[ResourceType.SSTApiGatewayV2]: noopResolver,\n\t[ResourceType.SnsTopic]: topicResolver,\n};\n\n/**\n * All known SST resource type strings.\n */\ntype SstResourceTypeString = `${ResourceType}`;\n\n/**\n * Extracts the `type` string value from an input value.\n */\ntype ExtractType<T> = T extends { type: infer U extends string } ? U : never;\n\n/**\n * Removes the `type` key from an object type.\n */\ntype OmitType<T> = T extends { type: string } ? Omit<T, 'type'> : never;\n\n/**\n * Extracts all unique `type` values from a record (excluding plain strings).\n */\ntype AllTypeValues<TRecord extends Record<string, InputValue>> = {\n\t[K in keyof TRecord]: ExtractType<TRecord[K]>;\n}[keyof TRecord];\n\n/**\n * Extracts only the custom (non-SST) type values from a record.\n */\ntype CustomTypeValues<TRecord extends Record<string, InputValue>> = Exclude<\n\tAllTypeValues<TRecord>,\n\tSstResourceTypeString\n>;\n\n/**\n * For a given type value, finds the corresponding value type (without `type` key).\n */\ntype ValueForType<\n\tTRecord extends Record<string, InputValue>,\n\tTType extends string,\n> = {\n\t[K in keyof TRecord]: TRecord[K] extends { type: TType }\n\t\t? OmitType<TRecord[K]>\n\t\t: never;\n}[keyof TRecord];\n\n/**\n * Generates typed resolvers for custom (non-SST) types in the input record.\n */\ntype CustomResolvers<TRecord extends Record<string, InputValue>> =\n\tCustomTypeValues<TRecord> extends never\n\t\t? Resolvers | undefined\n\t\t: {\n\t\t\t\t[TType in CustomTypeValues<TRecord>]: EnvironmentResolver<\n\t\t\t\t\tValueForType<TRecord, TType>\n\t\t\t\t>;\n\t\t\t};\n\n/**\n * SST-specific environment builder with built-in resolvers for all known\n * SST resource types.\n *\n * Wraps the generic EnvironmentBuilder with pre-configured SST resolvers.\n *\n * @template TRecord - The input record type for type inference\n *\n * @example\n * ```typescript\n * const env = new SstEnvironmentBuilder({\n * database: { type: 'sst:aws:Postgres', host: '...', ... },\n * apiKey: { type: 'sst:sst:Secret', value: 'secret' },\n * appName: 'my-app',\n * }).build();\n *\n * // With custom resolvers (typed based on input)\n * const env = new SstEnvironmentBuilder(\n * {\n * database: postgresResource,\n * custom: { type: 'my-custom' as const, data: 'foo' },\n * },\n * {\n * // TypeScript requires 'my-custom' resolver with typed value\n * 'my-custom': (key, value) => ({ [`${key}Data`]: value.data }),\n * }\n * ).build();\n * ```\n */\nexport class SstEnvironmentBuilder<\n\tTRecord extends Record<string, SstResource | InputValue | string>,\n> {\n\tprivate readonly builder: EnvironmentBuilder<\n\t\tRecord<string, InputValue>,\n\t\tResolvers\n\t>;\n\n\t/**\n\t * Create a new SST environment builder.\n\t *\n\t * @param record - Object containing SST resources, custom resources, and/or string values\n\t * @param additionalResolvers - Optional custom resolvers (typed based on custom types in record)\n\t * @param options - Optional configuration options\n\t */\n\tconstructor(\n\t\trecord: TRecord,\n\t\tadditionalResolvers?: CustomResolvers<TRecord>,\n\t\toptions?: EnvironmentBuilderOptions,\n\t) {\n\t\t// Merge resolvers with custom ones taking precedence\n\t\tconst mergedResolvers: Resolvers = additionalResolvers\n\t\t\t? { ...sstResolvers, ...additionalResolvers }\n\t\t\t: sstResolvers;\n\n\t\tthis.builder = new EnvironmentBuilder(\n\t\t\trecord as Record<string, InputValue>,\n\t\t\tmergedResolvers,\n\t\t\toptions,\n\t\t);\n\t}\n\n\t/**\n\t * Build environment variables from the input record.\n\t *\n\t * @returns A record of environment variables\n\t */\n\tbuild(): EnvRecord {\n\t\treturn this.builder.build();\n\t}\n}\n\nexport type {\n\tEnvironmentBuilderOptions,\n\tEnvRecord,\n\tEnvValue,\n} from './EnvironmentBuilder';\n// Re-export useful types\nexport { environmentCase } from './EnvironmentBuilder';\n"],"mappings":";;;;;;;AAaA,IAAY,wDAAL;AAEN;AACA;AACA;AACA;AACA;AACA;AAGA;AACA;AACA;AACA;AACA;AACA;;AACA;AA8FD,MAAM,iBAAiB,CAACA,MAAcC,WAAwB,GAC5D,OAAO,MAAM,MACd;AAED,MAAM,mBAAmB,CAACC,KAAaC,WAA0B;GAC9D,EAAE,IAAI,QAAQ,MAAM;GACpB,EAAE,IAAI,QAAQ,MAAM;GACpB,EAAE,IAAI,YAAY,MAAM;GACxB,EAAE,IAAI,QAAQ,MAAM;GACpB,EAAE,IAAI,YAAY,MAAM;AAC1B;AAED,MAAM,iBAAiB,CAACH,MAAcI,WAAwB,IAC3D,EAAE,KAAK,QAAQ,MAAM,KACvB;AAED,MAAM,gBAAgB,CAACJ,MAAcK,WAA0B,IAC5D,EAAE,KAAK,OAAO,MAAM,IACtB;AAED,MAAM,eAAe,OAAO,CAAE;;;;AAK9B,MAAaC,eAA0B;EAErC,aAAa,eAAe;EAC5B,aAAa,WAAW;EACxB,aAAa,MAAM;EACnB,aAAa,SAAS;EACtB,aAAa,WAAW;EACxB,aAAa,SAAS;EAGtB,aAAa,YAAY;EACzB,aAAa,YAAY;EACzB,aAAa,cAAc;EAC3B,aAAa,cAAc;EAC3B,aAAa,kBAAkB;EAC/B,aAAa,WAAW;AACzB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqFD,IAAa,wBAAb,MAEE;CACD,AAAiB;;;;;;;;CAYjB,YACCC,QACAC,qBACAC,SACC;EAED,MAAMC,kBAA6B,sBAChC;GAAE,GAAG;GAAc,GAAG;EAAqB,IAC3C;AAEH,OAAK,UAAU,IAAIC,8CAClB,QACA,iBACA;CAED;;;;;;CAOD,QAAmB;AAClB,SAAO,KAAK,QAAQ,OAAO;CAC3B;AACD"}
@@ -1,5 +1,5 @@
1
1
  const require_EnvironmentBuilder = require('./EnvironmentBuilder-Djr1VsWM.cjs');
2
- const require_SstEnvironmentBuilder = require('./SstEnvironmentBuilder-wFnN2M5O.cjs');
2
+ const require_SstEnvironmentBuilder = require('./SstEnvironmentBuilder-jsnqgtcW.cjs');
3
3
 
4
4
  exports.ResourceType = require_SstEnvironmentBuilder.ResourceType;
5
5
  exports.SstEnvironmentBuilder = require_SstEnvironmentBuilder.SstEnvironmentBuilder;
@@ -1,3 +1,3 @@
1
- import { EnvRecord, EnvValue, EnvironmentBuilderOptions, environmentCase } from "./EnvironmentBuilder-DHfDXJUm.mjs";
2
- import { ApiGatewayV2, Bucket, Function, Postgres, ResourceProcessor, ResourceType, Secret, SnsTopic, SstEnvironmentBuilder, SstResource, Vpc, sstResolvers } from "./SstEnvironmentBuilder-CjURMGjW.mjs";
1
+ import { EnvRecord, EnvValue, EnvironmentBuilderOptions, environmentCase } from "./EnvironmentBuilder-jF-b7WQg.mjs";
2
+ import { ApiGatewayV2, Bucket, Function, Postgres, ResourceProcessor, ResourceType, Secret, SnsTopic, SstEnvironmentBuilder, SstResource, Vpc, sstResolvers } from "./SstEnvironmentBuilder-BZngSQKQ.mjs";
3
3
  export { ApiGatewayV2, Bucket, EnvRecord, EnvValue, EnvironmentBuilderOptions, Function, Postgres, ResourceProcessor, ResourceType, Secret, SnsTopic, SstEnvironmentBuilder, SstResource, Vpc, environmentCase, sstResolvers };
@@ -1,4 +1,4 @@
1
1
  import { environmentCase } from "./EnvironmentBuilder-BSuHZm0y.mjs";
2
- import { ResourceType, SstEnvironmentBuilder, sstResolvers } from "./SstEnvironmentBuilder-BEBFSUYr.mjs";
2
+ import { ResourceType, SstEnvironmentBuilder, sstResolvers } from "./SstEnvironmentBuilder-DVB7cJq4.mjs";
3
3
 
4
4
  export { ResourceType, SstEnvironmentBuilder, environmentCase, sstResolvers };
@@ -0,0 +1,111 @@
1
+ //#region src/formatter.ts
2
+ /**
3
+ * ANSI color codes for terminal output.
4
+ */
5
+ const colors = {
6
+ reset: "\x1B[0m",
7
+ red: "\x1B[31m",
8
+ yellow: "\x1B[33m",
9
+ cyan: "\x1B[36m",
10
+ dim: "\x1B[2m",
11
+ bold: "\x1B[1m"
12
+ };
13
+ /**
14
+ * Formats a ZodError into a user-friendly string for development.
15
+ *
16
+ * @param error - The ZodError to format
17
+ * @param options - Formatting options
18
+ * @returns Formatted error message
19
+ *
20
+ * @example
21
+ * ```typescript
22
+ * try {
23
+ * config.parse();
24
+ * } catch (error) {
25
+ * if (error instanceof ZodError) {
26
+ * console.error(formatParseError(error));
27
+ * }
28
+ * }
29
+ * ```
30
+ *
31
+ * Output:
32
+ * ```
33
+ * Environment Configuration Failed
34
+ *
35
+ * Missing Variables:
36
+ * DATABASE_URL - Required
37
+ * JWT_SECRET - Required
38
+ *
39
+ * Invalid Values:
40
+ * NODE_ENV = "invalid"
41
+ * Expected: "development" | "staging" | "production"
42
+ * ```
43
+ */
44
+ function formatParseError(error, options = {}) {
45
+ const useColors = options.colors ?? (process.stdout?.isTTY && process.env.NO_COLOR == null);
46
+ const c = useColors ? colors : {
47
+ reset: "",
48
+ red: "",
49
+ yellow: "",
50
+ cyan: "",
51
+ dim: "",
52
+ bold: ""
53
+ };
54
+ const missingVars = [];
55
+ const invalidVars = [];
56
+ for (const issue of error.issues) {
57
+ let envName = "";
58
+ if (issue.path.length > 0) envName = issue.path.map(String).join(".");
59
+ else {
60
+ const match = issue.message.match(/Environment variable "([^"]+)"/);
61
+ if (match?.[1]) envName = match[1];
62
+ }
63
+ const received = "received" in issue ? issue.received : void 0;
64
+ const isMissing = issue.code === "invalid_type" && (received === "undefined" || received === "null");
65
+ if (isMissing) missingVars.push({
66
+ name: envName || "Unknown",
67
+ message: cleanMessage(issue.message)
68
+ });
69
+ else invalidVars.push({
70
+ name: envName || "Unknown",
71
+ value: received,
72
+ message: cleanMessage(issue.message)
73
+ });
74
+ }
75
+ const lines = [];
76
+ lines.push("");
77
+ lines.push(`${c.red}${c.bold}Environment Configuration Failed${c.reset}`);
78
+ lines.push("");
79
+ if (missingVars.length > 0) {
80
+ lines.push(`${c.yellow}Missing Variables:${c.reset}`);
81
+ for (const v of missingVars) lines.push(` ${c.cyan}${v.name}${c.reset} ${c.dim}- Required${c.reset}`);
82
+ lines.push("");
83
+ }
84
+ if (invalidVars.length > 0) {
85
+ lines.push(`${c.yellow}Invalid Values:${c.reset}`);
86
+ for (const v of invalidVars) {
87
+ const valueStr = v.value !== void 0 ? ` = ${JSON.stringify(v.value)}` : "";
88
+ lines.push(` ${c.cyan}${v.name}${c.reset}${valueStr}`);
89
+ lines.push(` ${c.dim}${v.message}${c.reset}`);
90
+ }
91
+ lines.push("");
92
+ }
93
+ return lines.join("\n");
94
+ }
95
+ /**
96
+ * Cleans up a Zod error message by removing redundant prefixes.
97
+ */
98
+ function cleanMessage(message) {
99
+ return message.replace(/^Environment variable "[^"]+": /, "");
100
+ }
101
+ /**
102
+ * Checks if the current environment is development.
103
+ */
104
+ function isDevelopment() {
105
+ const nodeEnv = process.env.NODE_ENV?.toLowerCase();
106
+ return nodeEnv == null || nodeEnv === "development" || nodeEnv === "dev";
107
+ }
108
+
109
+ //#endregion
110
+ export { formatParseError, isDevelopment };
111
+ //# sourceMappingURL=formatter-BRRrxQi3.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"formatter-BRRrxQi3.mjs","names":["error: z.ZodError","options: FormatOptions","missingVars: Array<{ name: string; message: string }>","invalidVars: Array<{ name: string; value: unknown; message: string }>","lines: string[]","message: string"],"sources":["../src/formatter.ts"],"sourcesContent":["import type { z } from 'zod/v4';\n\n/**\n * Options for formatting parse errors.\n */\nexport interface FormatOptions {\n\t/** Whether to use colors in output. Defaults to auto-detect TTY. */\n\tcolors?: boolean;\n}\n\n/**\n * ANSI color codes for terminal output.\n */\nconst colors = {\n\treset: '\\x1b[0m',\n\tred: '\\x1b[31m',\n\tyellow: '\\x1b[33m',\n\tcyan: '\\x1b[36m',\n\tdim: '\\x1b[2m',\n\tbold: '\\x1b[1m',\n};\n\n/**\n * Formats a ZodError into a user-friendly string for development.\n *\n * @param error - The ZodError to format\n * @param options - Formatting options\n * @returns Formatted error message\n *\n * @example\n * ```typescript\n * try {\n * config.parse();\n * } catch (error) {\n * if (error instanceof ZodError) {\n * console.error(formatParseError(error));\n * }\n * }\n * ```\n *\n * Output:\n * ```\n * Environment Configuration Failed\n *\n * Missing Variables:\n * DATABASE_URL - Required\n * JWT_SECRET - Required\n *\n * Invalid Values:\n * NODE_ENV = \"invalid\"\n * Expected: \"development\" | \"staging\" | \"production\"\n * ```\n */\nexport function formatParseError(\n\terror: z.ZodError,\n\toptions: FormatOptions = {},\n): string {\n\tconst useColors =\n\t\toptions.colors ?? (process.stdout?.isTTY && process.env.NO_COLOR == null);\n\n\tconst c = useColors\n\t\t? colors\n\t\t: { reset: '', red: '', yellow: '', cyan: '', dim: '', bold: '' };\n\n\tconst missingVars: Array<{ name: string; message: string }> = [];\n\tconst invalidVars: Array<{ name: string; value: unknown; message: string }> =\n\t\t[];\n\n\tfor (const issue of error.issues) {\n\t\t// Extract environment variable name from path or message\n\t\tlet envName = '';\n\t\tif (issue.path.length > 0) {\n\t\t\t// Join the full path with '.' to show nested config keys and env var name\n\t\t\tenvName = issue.path.map(String).join('.');\n\t\t} else {\n\t\t\t// Try to extract from message like 'Environment variable \"NAME\": ...'\n\t\t\tconst match = issue.message.match(/Environment variable \"([^\"]+)\"/);\n\t\t\tif (match?.[1]) {\n\t\t\t\tenvName = match[1];\n\t\t\t}\n\t\t}\n\n\t\t// Determine if this is a missing or invalid value\n\t\t// Use type guard for received property\n\t\tconst received = 'received' in issue ? issue.received : undefined;\n\t\tconst isMissing =\n\t\t\tissue.code === 'invalid_type' &&\n\t\t\t(received === 'undefined' || received === 'null');\n\n\t\tif (isMissing) {\n\t\t\tmissingVars.push({\n\t\t\t\tname: envName || 'Unknown',\n\t\t\t\tmessage: cleanMessage(issue.message),\n\t\t\t});\n\t\t} else {\n\t\t\tinvalidVars.push({\n\t\t\t\tname: envName || 'Unknown',\n\t\t\t\tvalue: received,\n\t\t\t\tmessage: cleanMessage(issue.message),\n\t\t\t});\n\t\t}\n\t}\n\n\tconst lines: string[] = [];\n\n\tlines.push('');\n\tlines.push(`${c.red}${c.bold}Environment Configuration Failed${c.reset}`);\n\tlines.push('');\n\n\tif (missingVars.length > 0) {\n\t\tlines.push(`${c.yellow}Missing Variables:${c.reset}`);\n\t\tfor (const v of missingVars) {\n\t\t\tlines.push(` ${c.cyan}${v.name}${c.reset} ${c.dim}- Required${c.reset}`);\n\t\t}\n\t\tlines.push('');\n\t}\n\n\tif (invalidVars.length > 0) {\n\t\tlines.push(`${c.yellow}Invalid Values:${c.reset}`);\n\t\tfor (const v of invalidVars) {\n\t\t\tconst valueStr =\n\t\t\t\tv.value !== undefined ? ` = ${JSON.stringify(v.value)}` : '';\n\t\t\tlines.push(` ${c.cyan}${v.name}${c.reset}${valueStr}`);\n\t\t\tlines.push(` ${c.dim}${v.message}${c.reset}`);\n\t\t}\n\t\tlines.push('');\n\t}\n\n\treturn lines.join('\\n');\n}\n\n/**\n * Cleans up a Zod error message by removing redundant prefixes.\n */\nfunction cleanMessage(message: string): string {\n\t// Remove \"Environment variable \"NAME\": \" prefix if present\n\treturn message.replace(/^Environment variable \"[^\"]+\": /, '');\n}\n\n/**\n * Checks if the current environment is development.\n */\nexport function isDevelopment(): boolean {\n\tconst nodeEnv = process.env.NODE_ENV?.toLowerCase();\n\treturn nodeEnv == null || nodeEnv === 'development' || nodeEnv === 'dev';\n}\n"],"mappings":";;;;AAaA,MAAM,SAAS;CACd,OAAO;CACP,KAAK;CACL,QAAQ;CACR,MAAM;CACN,KAAK;CACL,MAAM;AACN;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiCD,SAAgB,iBACfA,OACAC,UAAyB,CAAE,GAClB;CACT,MAAM,YACL,QAAQ,WAAW,QAAQ,QAAQ,SAAS,QAAQ,IAAI,YAAY;CAErE,MAAM,IAAI,YACP,SACA;EAAE,OAAO;EAAI,KAAK;EAAI,QAAQ;EAAI,MAAM;EAAI,KAAK;EAAI,MAAM;CAAI;CAElE,MAAMC,cAAwD,CAAE;CAChE,MAAMC,cACL,CAAE;AAEH,MAAK,MAAM,SAAS,MAAM,QAAQ;EAEjC,IAAI,UAAU;AACd,MAAI,MAAM,KAAK,SAAS,EAEvB,WAAU,MAAM,KAAK,IAAI,OAAO,CAAC,KAAK,IAAI;OACpC;GAEN,MAAM,QAAQ,MAAM,QAAQ,MAAM,iCAAiC;AACnE,OAAI,QAAQ,GACX,WAAU,MAAM;EAEjB;EAID,MAAM,WAAW,cAAc,QAAQ,MAAM;EAC7C,MAAM,YACL,MAAM,SAAS,mBACd,aAAa,eAAe,aAAa;AAE3C,MAAI,UACH,aAAY,KAAK;GAChB,MAAM,WAAW;GACjB,SAAS,aAAa,MAAM,QAAQ;EACpC,EAAC;MAEF,aAAY,KAAK;GAChB,MAAM,WAAW;GACjB,OAAO;GACP,SAAS,aAAa,MAAM,QAAQ;EACpC,EAAC;CAEH;CAED,MAAMC,QAAkB,CAAE;AAE1B,OAAM,KAAK,GAAG;AACd,OAAM,MAAM,EAAE,EAAE,IAAI,EAAE,EAAE,KAAK,kCAAkC,EAAE,MAAM,EAAE;AACzE,OAAM,KAAK,GAAG;AAEd,KAAI,YAAY,SAAS,GAAG;AAC3B,QAAM,MAAM,EAAE,EAAE,OAAO,oBAAoB,EAAE,MAAM,EAAE;AACrD,OAAK,MAAM,KAAK,YACf,OAAM,MAAM,IAAI,EAAE,KAAK,EAAE,EAAE,KAAK,EAAE,EAAE,MAAM,GAAG,EAAE,IAAI,YAAY,EAAE,MAAM,EAAE;AAE1E,QAAM,KAAK,GAAG;CACd;AAED,KAAI,YAAY,SAAS,GAAG;AAC3B,QAAM,MAAM,EAAE,EAAE,OAAO,iBAAiB,EAAE,MAAM,EAAE;AAClD,OAAK,MAAM,KAAK,aAAa;GAC5B,MAAM,WACL,EAAE,oBAAuB,KAAK,KAAK,UAAU,EAAE,MAAM,CAAC,IAAI;AAC3D,SAAM,MAAM,IAAI,EAAE,KAAK,EAAE,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE;AACvD,SAAM,MAAM,MAAM,EAAE,IAAI,EAAE,EAAE,QAAQ,EAAE,EAAE,MAAM,EAAE;EAChD;AACD,QAAM,KAAK,GAAG;CACd;AAED,QAAO,MAAM,KAAK,KAAK;AACvB;;;;AAKD,SAAS,aAAaC,SAAyB;AAE9C,QAAO,QAAQ,QAAQ,mCAAmC,GAAG;AAC7D;;;;AAKD,SAAgB,gBAAyB;CACxC,MAAM,UAAU,QAAQ,IAAI,UAAU,aAAa;AACnD,QAAO,WAAW,QAAQ,YAAY,iBAAiB,YAAY;AACnE"}
@@ -0,0 +1,51 @@
1
+ import { z } from "zod/v4";
2
+
3
+ //#region src/formatter.d.ts
4
+
5
+ /**
6
+ * Options for formatting parse errors.
7
+ */
8
+ interface FormatOptions {
9
+ /** Whether to use colors in output. Defaults to auto-detect TTY. */
10
+ colors?: boolean;
11
+ }
12
+ /**
13
+ * Formats a ZodError into a user-friendly string for development.
14
+ *
15
+ * @param error - The ZodError to format
16
+ * @param options - Formatting options
17
+ * @returns Formatted error message
18
+ *
19
+ * @example
20
+ * ```typescript
21
+ * try {
22
+ * config.parse();
23
+ * } catch (error) {
24
+ * if (error instanceof ZodError) {
25
+ * console.error(formatParseError(error));
26
+ * }
27
+ * }
28
+ * ```
29
+ *
30
+ * Output:
31
+ * ```
32
+ * Environment Configuration Failed
33
+ *
34
+ * Missing Variables:
35
+ * DATABASE_URL - Required
36
+ * JWT_SECRET - Required
37
+ *
38
+ * Invalid Values:
39
+ * NODE_ENV = "invalid"
40
+ * Expected: "development" | "staging" | "production"
41
+ * ```
42
+ */
43
+ declare function formatParseError(error: z.ZodError, options?: FormatOptions): string;
44
+ /**
45
+ * Checks if the current environment is development.
46
+ */
47
+ declare function isDevelopment(): boolean;
48
+ //# sourceMappingURL=formatter.d.ts.map
49
+ //#endregion
50
+ export { FormatOptions, formatParseError, isDevelopment };
51
+ //# sourceMappingURL=formatter-Cox0NGxT.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"formatter-Cox0NGxT.d.mts","names":[],"sources":["../src/formatter.ts"],"sourcesContent":[],"mappings":";;;;;;AAKA;AAgDgB,UAhDC,aAAA,CAgDe;EAAA;EAAA,MACtB,CAAA,EAAA,OAAA;;AACkB;AAuF5B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAzFgB,gBAAA,QACR,CAAA,CAAE,oBACA;;;;iBAuFM,aAAA,CAAA"}
@@ -0,0 +1,51 @@
1
+ import { z } from "zod/v4";
2
+
3
+ //#region src/formatter.d.ts
4
+
5
+ /**
6
+ * Options for formatting parse errors.
7
+ */
8
+ interface FormatOptions {
9
+ /** Whether to use colors in output. Defaults to auto-detect TTY. */
10
+ colors?: boolean;
11
+ }
12
+ /**
13
+ * Formats a ZodError into a user-friendly string for development.
14
+ *
15
+ * @param error - The ZodError to format
16
+ * @param options - Formatting options
17
+ * @returns Formatted error message
18
+ *
19
+ * @example
20
+ * ```typescript
21
+ * try {
22
+ * config.parse();
23
+ * } catch (error) {
24
+ * if (error instanceof ZodError) {
25
+ * console.error(formatParseError(error));
26
+ * }
27
+ * }
28
+ * ```
29
+ *
30
+ * Output:
31
+ * ```
32
+ * Environment Configuration Failed
33
+ *
34
+ * Missing Variables:
35
+ * DATABASE_URL - Required
36
+ * JWT_SECRET - Required
37
+ *
38
+ * Invalid Values:
39
+ * NODE_ENV = "invalid"
40
+ * Expected: "development" | "staging" | "production"
41
+ * ```
42
+ */
43
+ declare function formatParseError(error: z.ZodError, options?: FormatOptions): string;
44
+ /**
45
+ * Checks if the current environment is development.
46
+ */
47
+ declare function isDevelopment(): boolean;
48
+ //# sourceMappingURL=formatter.d.ts.map
49
+ //#endregion
50
+ export { FormatOptions, formatParseError, isDevelopment };
51
+ //# sourceMappingURL=formatter-D85aIkpd.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"formatter-D85aIkpd.d.cts","names":[],"sources":["../src/formatter.ts"],"sourcesContent":[],"mappings":";;;;;;AAKA;AAgDgB,UAhDC,aAAA,CAgDe;EAAA;EAAA,MACtB,CAAA,EAAA,OAAA;;AACkB;AAuF5B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAzFgB,gBAAA,QACR,CAAA,CAAE,oBACA;;;;iBAuFM,aAAA,CAAA"}
@@ -0,0 +1,123 @@
1
+
2
+ //#region src/formatter.ts
3
+ /**
4
+ * ANSI color codes for terminal output.
5
+ */
6
+ const colors = {
7
+ reset: "\x1B[0m",
8
+ red: "\x1B[31m",
9
+ yellow: "\x1B[33m",
10
+ cyan: "\x1B[36m",
11
+ dim: "\x1B[2m",
12
+ bold: "\x1B[1m"
13
+ };
14
+ /**
15
+ * Formats a ZodError into a user-friendly string for development.
16
+ *
17
+ * @param error - The ZodError to format
18
+ * @param options - Formatting options
19
+ * @returns Formatted error message
20
+ *
21
+ * @example
22
+ * ```typescript
23
+ * try {
24
+ * config.parse();
25
+ * } catch (error) {
26
+ * if (error instanceof ZodError) {
27
+ * console.error(formatParseError(error));
28
+ * }
29
+ * }
30
+ * ```
31
+ *
32
+ * Output:
33
+ * ```
34
+ * Environment Configuration Failed
35
+ *
36
+ * Missing Variables:
37
+ * DATABASE_URL - Required
38
+ * JWT_SECRET - Required
39
+ *
40
+ * Invalid Values:
41
+ * NODE_ENV = "invalid"
42
+ * Expected: "development" | "staging" | "production"
43
+ * ```
44
+ */
45
+ function formatParseError(error, options = {}) {
46
+ const useColors = options.colors ?? (process.stdout?.isTTY && process.env.NO_COLOR == null);
47
+ const c = useColors ? colors : {
48
+ reset: "",
49
+ red: "",
50
+ yellow: "",
51
+ cyan: "",
52
+ dim: "",
53
+ bold: ""
54
+ };
55
+ const missingVars = [];
56
+ const invalidVars = [];
57
+ for (const issue of error.issues) {
58
+ let envName = "";
59
+ if (issue.path.length > 0) envName = issue.path.map(String).join(".");
60
+ else {
61
+ const match = issue.message.match(/Environment variable "([^"]+)"/);
62
+ if (match?.[1]) envName = match[1];
63
+ }
64
+ const received = "received" in issue ? issue.received : void 0;
65
+ const isMissing = issue.code === "invalid_type" && (received === "undefined" || received === "null");
66
+ if (isMissing) missingVars.push({
67
+ name: envName || "Unknown",
68
+ message: cleanMessage(issue.message)
69
+ });
70
+ else invalidVars.push({
71
+ name: envName || "Unknown",
72
+ value: received,
73
+ message: cleanMessage(issue.message)
74
+ });
75
+ }
76
+ const lines = [];
77
+ lines.push("");
78
+ lines.push(`${c.red}${c.bold}Environment Configuration Failed${c.reset}`);
79
+ lines.push("");
80
+ if (missingVars.length > 0) {
81
+ lines.push(`${c.yellow}Missing Variables:${c.reset}`);
82
+ for (const v of missingVars) lines.push(` ${c.cyan}${v.name}${c.reset} ${c.dim}- Required${c.reset}`);
83
+ lines.push("");
84
+ }
85
+ if (invalidVars.length > 0) {
86
+ lines.push(`${c.yellow}Invalid Values:${c.reset}`);
87
+ for (const v of invalidVars) {
88
+ const valueStr = v.value !== void 0 ? ` = ${JSON.stringify(v.value)}` : "";
89
+ lines.push(` ${c.cyan}${v.name}${c.reset}${valueStr}`);
90
+ lines.push(` ${c.dim}${v.message}${c.reset}`);
91
+ }
92
+ lines.push("");
93
+ }
94
+ return lines.join("\n");
95
+ }
96
+ /**
97
+ * Cleans up a Zod error message by removing redundant prefixes.
98
+ */
99
+ function cleanMessage(message) {
100
+ return message.replace(/^Environment variable "[^"]+": /, "");
101
+ }
102
+ /**
103
+ * Checks if the current environment is development.
104
+ */
105
+ function isDevelopment() {
106
+ const nodeEnv = process.env.NODE_ENV?.toLowerCase();
107
+ return nodeEnv == null || nodeEnv === "development" || nodeEnv === "dev";
108
+ }
109
+
110
+ //#endregion
111
+ Object.defineProperty(exports, 'formatParseError', {
112
+ enumerable: true,
113
+ get: function () {
114
+ return formatParseError;
115
+ }
116
+ });
117
+ Object.defineProperty(exports, 'isDevelopment', {
118
+ enumerable: true,
119
+ get: function () {
120
+ return isDevelopment;
121
+ }
122
+ });
123
+ //# sourceMappingURL=formatter-HxePpSy2.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"formatter-HxePpSy2.cjs","names":["error: z.ZodError","options: FormatOptions","missingVars: Array<{ name: string; message: string }>","invalidVars: Array<{ name: string; value: unknown; message: string }>","lines: string[]","message: string"],"sources":["../src/formatter.ts"],"sourcesContent":["import type { z } from 'zod/v4';\n\n/**\n * Options for formatting parse errors.\n */\nexport interface FormatOptions {\n\t/** Whether to use colors in output. Defaults to auto-detect TTY. */\n\tcolors?: boolean;\n}\n\n/**\n * ANSI color codes for terminal output.\n */\nconst colors = {\n\treset: '\\x1b[0m',\n\tred: '\\x1b[31m',\n\tyellow: '\\x1b[33m',\n\tcyan: '\\x1b[36m',\n\tdim: '\\x1b[2m',\n\tbold: '\\x1b[1m',\n};\n\n/**\n * Formats a ZodError into a user-friendly string for development.\n *\n * @param error - The ZodError to format\n * @param options - Formatting options\n * @returns Formatted error message\n *\n * @example\n * ```typescript\n * try {\n * config.parse();\n * } catch (error) {\n * if (error instanceof ZodError) {\n * console.error(formatParseError(error));\n * }\n * }\n * ```\n *\n * Output:\n * ```\n * Environment Configuration Failed\n *\n * Missing Variables:\n * DATABASE_URL - Required\n * JWT_SECRET - Required\n *\n * Invalid Values:\n * NODE_ENV = \"invalid\"\n * Expected: \"development\" | \"staging\" | \"production\"\n * ```\n */\nexport function formatParseError(\n\terror: z.ZodError,\n\toptions: FormatOptions = {},\n): string {\n\tconst useColors =\n\t\toptions.colors ?? (process.stdout?.isTTY && process.env.NO_COLOR == null);\n\n\tconst c = useColors\n\t\t? colors\n\t\t: { reset: '', red: '', yellow: '', cyan: '', dim: '', bold: '' };\n\n\tconst missingVars: Array<{ name: string; message: string }> = [];\n\tconst invalidVars: Array<{ name: string; value: unknown; message: string }> =\n\t\t[];\n\n\tfor (const issue of error.issues) {\n\t\t// Extract environment variable name from path or message\n\t\tlet envName = '';\n\t\tif (issue.path.length > 0) {\n\t\t\t// Join the full path with '.' to show nested config keys and env var name\n\t\t\tenvName = issue.path.map(String).join('.');\n\t\t} else {\n\t\t\t// Try to extract from message like 'Environment variable \"NAME\": ...'\n\t\t\tconst match = issue.message.match(/Environment variable \"([^\"]+)\"/);\n\t\t\tif (match?.[1]) {\n\t\t\t\tenvName = match[1];\n\t\t\t}\n\t\t}\n\n\t\t// Determine if this is a missing or invalid value\n\t\t// Use type guard for received property\n\t\tconst received = 'received' in issue ? issue.received : undefined;\n\t\tconst isMissing =\n\t\t\tissue.code === 'invalid_type' &&\n\t\t\t(received === 'undefined' || received === 'null');\n\n\t\tif (isMissing) {\n\t\t\tmissingVars.push({\n\t\t\t\tname: envName || 'Unknown',\n\t\t\t\tmessage: cleanMessage(issue.message),\n\t\t\t});\n\t\t} else {\n\t\t\tinvalidVars.push({\n\t\t\t\tname: envName || 'Unknown',\n\t\t\t\tvalue: received,\n\t\t\t\tmessage: cleanMessage(issue.message),\n\t\t\t});\n\t\t}\n\t}\n\n\tconst lines: string[] = [];\n\n\tlines.push('');\n\tlines.push(`${c.red}${c.bold}Environment Configuration Failed${c.reset}`);\n\tlines.push('');\n\n\tif (missingVars.length > 0) {\n\t\tlines.push(`${c.yellow}Missing Variables:${c.reset}`);\n\t\tfor (const v of missingVars) {\n\t\t\tlines.push(` ${c.cyan}${v.name}${c.reset} ${c.dim}- Required${c.reset}`);\n\t\t}\n\t\tlines.push('');\n\t}\n\n\tif (invalidVars.length > 0) {\n\t\tlines.push(`${c.yellow}Invalid Values:${c.reset}`);\n\t\tfor (const v of invalidVars) {\n\t\t\tconst valueStr =\n\t\t\t\tv.value !== undefined ? ` = ${JSON.stringify(v.value)}` : '';\n\t\t\tlines.push(` ${c.cyan}${v.name}${c.reset}${valueStr}`);\n\t\t\tlines.push(` ${c.dim}${v.message}${c.reset}`);\n\t\t}\n\t\tlines.push('');\n\t}\n\n\treturn lines.join('\\n');\n}\n\n/**\n * Cleans up a Zod error message by removing redundant prefixes.\n */\nfunction cleanMessage(message: string): string {\n\t// Remove \"Environment variable \"NAME\": \" prefix if present\n\treturn message.replace(/^Environment variable \"[^\"]+\": /, '');\n}\n\n/**\n * Checks if the current environment is development.\n */\nexport function isDevelopment(): boolean {\n\tconst nodeEnv = process.env.NODE_ENV?.toLowerCase();\n\treturn nodeEnv == null || nodeEnv === 'development' || nodeEnv === 'dev';\n}\n"],"mappings":";;;;;AAaA,MAAM,SAAS;CACd,OAAO;CACP,KAAK;CACL,QAAQ;CACR,MAAM;CACN,KAAK;CACL,MAAM;AACN;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiCD,SAAgB,iBACfA,OACAC,UAAyB,CAAE,GAClB;CACT,MAAM,YACL,QAAQ,WAAW,QAAQ,QAAQ,SAAS,QAAQ,IAAI,YAAY;CAErE,MAAM,IAAI,YACP,SACA;EAAE,OAAO;EAAI,KAAK;EAAI,QAAQ;EAAI,MAAM;EAAI,KAAK;EAAI,MAAM;CAAI;CAElE,MAAMC,cAAwD,CAAE;CAChE,MAAMC,cACL,CAAE;AAEH,MAAK,MAAM,SAAS,MAAM,QAAQ;EAEjC,IAAI,UAAU;AACd,MAAI,MAAM,KAAK,SAAS,EAEvB,WAAU,MAAM,KAAK,IAAI,OAAO,CAAC,KAAK,IAAI;OACpC;GAEN,MAAM,QAAQ,MAAM,QAAQ,MAAM,iCAAiC;AACnE,OAAI,QAAQ,GACX,WAAU,MAAM;EAEjB;EAID,MAAM,WAAW,cAAc,QAAQ,MAAM;EAC7C,MAAM,YACL,MAAM,SAAS,mBACd,aAAa,eAAe,aAAa;AAE3C,MAAI,UACH,aAAY,KAAK;GAChB,MAAM,WAAW;GACjB,SAAS,aAAa,MAAM,QAAQ;EACpC,EAAC;MAEF,aAAY,KAAK;GAChB,MAAM,WAAW;GACjB,OAAO;GACP,SAAS,aAAa,MAAM,QAAQ;EACpC,EAAC;CAEH;CAED,MAAMC,QAAkB,CAAE;AAE1B,OAAM,KAAK,GAAG;AACd,OAAM,MAAM,EAAE,EAAE,IAAI,EAAE,EAAE,KAAK,kCAAkC,EAAE,MAAM,EAAE;AACzE,OAAM,KAAK,GAAG;AAEd,KAAI,YAAY,SAAS,GAAG;AAC3B,QAAM,MAAM,EAAE,EAAE,OAAO,oBAAoB,EAAE,MAAM,EAAE;AACrD,OAAK,MAAM,KAAK,YACf,OAAM,MAAM,IAAI,EAAE,KAAK,EAAE,EAAE,KAAK,EAAE,EAAE,MAAM,GAAG,EAAE,IAAI,YAAY,EAAE,MAAM,EAAE;AAE1E,QAAM,KAAK,GAAG;CACd;AAED,KAAI,YAAY,SAAS,GAAG;AAC3B,QAAM,MAAM,EAAE,EAAE,OAAO,iBAAiB,EAAE,MAAM,EAAE;AAClD,OAAK,MAAM,KAAK,aAAa;GAC5B,MAAM,WACL,EAAE,oBAAuB,KAAK,KAAK,UAAU,EAAE,MAAM,CAAC,IAAI;AAC3D,SAAM,MAAM,IAAI,EAAE,KAAK,EAAE,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE;AACvD,SAAM,MAAM,MAAM,EAAE,IAAI,EAAE,EAAE,QAAQ,EAAE,EAAE,MAAM,EAAE;EAChD;AACD,QAAM,KAAK,GAAG;CACd;AAED,QAAO,MAAM,KAAK,KAAK;AACvB;;;;AAKD,SAAS,aAAaC,SAAyB;AAE9C,QAAO,QAAQ,QAAQ,mCAAmC,GAAG;AAC7D;;;;AAKD,SAAgB,gBAAyB;CACxC,MAAM,UAAU,QAAQ,IAAI,UAAU,aAAa;AACnD,QAAO,WAAW,QAAQ,YAAY,iBAAiB,YAAY;AACnE"}
@@ -0,0 +1,4 @@
1
+ const require_formatter = require('./formatter-HxePpSy2.cjs');
2
+
3
+ exports.formatParseError = require_formatter.formatParseError;
4
+ exports.isDevelopment = require_formatter.isDevelopment;
@@ -0,0 +1,2 @@
1
+ import { FormatOptions, formatParseError, isDevelopment } from "./formatter-D85aIkpd.cjs";
2
+ export { FormatOptions, formatParseError, isDevelopment };
@@ -0,0 +1,2 @@
1
+ import { FormatOptions, formatParseError, isDevelopment } from "./formatter-Cox0NGxT.mjs";
2
+ export { FormatOptions, formatParseError, isDevelopment };
@@ -0,0 +1,3 @@
1
+ import { formatParseError, isDevelopment } from "./formatter-BRRrxQi3.mjs";
2
+
3
+ export { formatParseError, isDevelopment };
package/dist/index.cjs CHANGED
@@ -1,7 +1,10 @@
1
1
  const require_EnvironmentBuilder = require('./EnvironmentBuilder-Djr1VsWM.cjs');
2
- const require_EnvironmentParser = require('./EnvironmentParser-Bt246UeP.cjs');
2
+ const require_formatter = require('./formatter-HxePpSy2.cjs');
3
+ const require_EnvironmentParser = require('./EnvironmentParser-DJdW7vOL.cjs');
3
4
 
4
5
  exports.ConfigParser = require_EnvironmentParser.ConfigParser;
5
6
  exports.EnvironmentBuilder = require_EnvironmentBuilder.EnvironmentBuilder;
6
7
  exports.EnvironmentParser = require_EnvironmentParser.EnvironmentParser;
7
- exports.environmentCase = require_EnvironmentBuilder.environmentCase;
8
+ exports.environmentCase = require_EnvironmentBuilder.environmentCase;
9
+ exports.formatParseError = require_formatter.formatParseError;
10
+ exports.isDevelopment = require_formatter.isDevelopment;
package/dist/index.d.cts CHANGED
@@ -1,3 +1,4 @@
1
1
  import { EnvRecord, EnvValue, EnvironmentBuilder, EnvironmentBuilderOptions, EnvironmentResolver, InputValue, Resolvers, TypedInputValue, TypedResolvers, environmentCase } from "./EnvironmentBuilder-Xuf2Dd9u.cjs";
2
2
  import { ConfigParser, EnvironmentParser } from "./EnvironmentParser-DtOL86NU.cjs";
3
- export { ConfigParser, EnvRecord, EnvValue, EnvironmentBuilder, EnvironmentBuilderOptions, EnvironmentParser, EnvironmentResolver, InputValue, Resolvers, TypedInputValue, TypedResolvers, environmentCase };
3
+ import { FormatOptions, formatParseError, isDevelopment } from "./formatter-D85aIkpd.cjs";
4
+ export { ConfigParser, EnvRecord, EnvValue, EnvironmentBuilder, EnvironmentBuilderOptions, EnvironmentParser, EnvironmentResolver, FormatOptions, InputValue, Resolvers, TypedInputValue, TypedResolvers, environmentCase, formatParseError, isDevelopment };
package/dist/index.d.mts CHANGED
@@ -1,3 +1,4 @@
1
- import { EnvRecord, EnvValue, EnvironmentBuilder, EnvironmentBuilderOptions, EnvironmentResolver, InputValue, Resolvers, TypedInputValue, TypedResolvers, environmentCase } from "./EnvironmentBuilder-DHfDXJUm.mjs";
2
- import { ConfigParser, EnvironmentParser } from "./EnvironmentParser-CY8TosTN.mjs";
3
- export { ConfigParser, EnvRecord, EnvValue, EnvironmentBuilder, EnvironmentBuilderOptions, EnvironmentParser, EnvironmentResolver, InputValue, Resolvers, TypedInputValue, TypedResolvers, environmentCase };
1
+ import { EnvRecord, EnvValue, EnvironmentBuilder, EnvironmentBuilderOptions, EnvironmentResolver, InputValue, Resolvers, TypedInputValue, TypedResolvers, environmentCase } from "./EnvironmentBuilder-jF-b7WQg.mjs";
2
+ import { ConfigParser, EnvironmentParser } from "./EnvironmentParser-CkLfmn4Y.mjs";
3
+ import { FormatOptions, formatParseError, isDevelopment } from "./formatter-Cox0NGxT.mjs";
4
+ export { ConfigParser, EnvRecord, EnvValue, EnvironmentBuilder, EnvironmentBuilderOptions, EnvironmentParser, EnvironmentResolver, FormatOptions, InputValue, Resolvers, TypedInputValue, TypedResolvers, environmentCase, formatParseError, isDevelopment };
package/dist/index.mjs CHANGED
@@ -1,4 +1,5 @@
1
1
  import { EnvironmentBuilder, environmentCase } from "./EnvironmentBuilder-BSuHZm0y.mjs";
2
- import { ConfigParser, EnvironmentParser } from "./EnvironmentParser-c06agx31.mjs";
2
+ import { formatParseError, isDevelopment } from "./formatter-BRRrxQi3.mjs";
3
+ import { ConfigParser, EnvironmentParser } from "./EnvironmentParser-zMblItla.mjs";
3
4
 
4
- export { ConfigParser, EnvironmentBuilder, EnvironmentParser, environmentCase };
5
+ export { ConfigParser, EnvironmentBuilder, EnvironmentParser, environmentCase, formatParseError, isDevelopment };
package/dist/sst.cjs CHANGED
@@ -1,5 +1,5 @@
1
1
  const require_EnvironmentBuilder = require('./EnvironmentBuilder-Djr1VsWM.cjs');
2
- const require_SstEnvironmentBuilder = require('./SstEnvironmentBuilder-wFnN2M5O.cjs');
2
+ const require_SstEnvironmentBuilder = require('./SstEnvironmentBuilder-jsnqgtcW.cjs');
3
3
 
4
4
  //#region src/sst.ts
5
5
  /**
package/dist/sst.d.mts CHANGED
@@ -1,5 +1,5 @@
1
- import { EnvRecord, EnvValue, EnvironmentBuilderOptions, environmentCase } from "./EnvironmentBuilder-DHfDXJUm.mjs";
2
- import { ApiGatewayV2, Bucket, Function, Postgres, ResourceProcessor, ResourceType, Secret, SnsTopic, SstEnvironmentBuilder, SstResource, Vpc, sstResolvers } from "./SstEnvironmentBuilder-CjURMGjW.mjs";
1
+ import { EnvRecord, EnvValue, EnvironmentBuilderOptions, environmentCase } from "./EnvironmentBuilder-jF-b7WQg.mjs";
2
+ import { ApiGatewayV2, Bucket, Function, Postgres, ResourceProcessor, ResourceType, Secret, SnsTopic, SstEnvironmentBuilder, SstResource, Vpc, sstResolvers } from "./SstEnvironmentBuilder-BZngSQKQ.mjs";
3
3
 
4
4
  //#region src/sst.d.ts
5
5
 
package/dist/sst.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  import { environmentCase } from "./EnvironmentBuilder-BSuHZm0y.mjs";
2
- import { ResourceType, SstEnvironmentBuilder, sstResolvers } from "./SstEnvironmentBuilder-BEBFSUYr.mjs";
2
+ import { ResourceType, SstEnvironmentBuilder, sstResolvers } from "./SstEnvironmentBuilder-DVB7cJq4.mjs";
3
3
 
4
4
  //#region src/sst.ts
5
5
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@geekmidas/envkit",
3
- "version": "0.4.0",
3
+ "version": "0.6.0",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "exports": {
@@ -1,6 +1,7 @@
1
1
  import get from 'lodash.get';
2
2
  import set from 'lodash.set';
3
3
  import { z } from 'zod/v4';
4
+ import { formatParseError, isDevelopment } from './formatter.js';
4
5
 
5
6
  /**
6
7
  * Parses and validates configuration objects against Zod schemas.
@@ -63,8 +64,12 @@ export class ConfigParser<TResponse extends EmptyObject> {
63
64
  ) as unknown as InferConfig<TResponse>;
64
65
 
65
66
  if (errors.length > 0) {
66
- // If there are errors, throw them
67
- throw new z.ZodError(errors);
67
+ const zodError = new z.ZodError(errors);
68
+ // In development, log a formatted error message before throwing
69
+ if (isDevelopment()) {
70
+ console.error(formatParseError(zodError));
71
+ }
72
+ throw zodError;
68
73
  }
69
74
 
70
75
  return parsedConfig;