@sdlcworks/components 0.0.37 → 0.0.38

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.
package/dist/index.d.ts CHANGED
@@ -190,16 +190,13 @@ declare const InfraComponentOptsSchema: z.ZodObject<{
190
190
  connectionTypes: z.ZodRecord<z.ZodString, z.ZodObject<{
191
191
  description: z.ZodString;
192
192
  }, z.core.$strip>>;
193
+ acceptedArtifactTypes: z.ZodOptional<z.ZodArray<z.ZodEnum<typeof DeploymentArtifactType>>>;
193
194
  configSchema: z.ZodCustom<z.ZodObject<Readonly<{
194
195
  [k: string]: z.core.$ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>;
195
196
  }>, z.core.$strip>, z.ZodObject<Readonly<{
196
197
  [k: string]: z.core.$ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>;
197
198
  }>, z.core.$strip>>;
198
- deploymentInputSchema: z.ZodCustom<z.ZodObject<Readonly<{
199
- [k: string]: z.core.$ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>;
200
- }>, z.core.$strip>, z.ZodObject<Readonly<{
201
- [k: string]: z.core.$ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>;
202
- }>, z.core.$strip>>;
199
+ deploymentInputSchema: z.ZodCustom<z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>, z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>>;
203
200
  outputSchema: z.ZodCustom<z.ZodObject<Readonly<{
204
201
  [k: string]: z.core.$ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>;
205
202
  }>, z.core.$strip>, z.ZodObject<Readonly<{
@@ -207,15 +204,20 @@ declare const InfraComponentOptsSchema: z.ZodObject<{
207
204
  }>, z.core.$strip>>;
208
205
  }, z.core.$strip>;
209
206
  export type InfraComponentOptsBase = z.infer<typeof InfraComponentOptsSchema>;
210
- export type InfraComponentOpts<CShape extends z.ZodRawShape, DShape extends z.ZodRawShape, OShape extends z.ZodRawShape, ConnTypes extends Record<string, {
207
+ export type InfraComponentOpts<CShape extends z.ZodRawShape, DSchema extends z.ZodTypeAny, OShape extends z.ZodRawShape, ConnTypes extends Record<string, {
211
208
  description: string;
212
209
  }> = Record<string, {
213
210
  description: string;
214
211
  }>> = Omit<InfraComponentOptsBase, "configSchema" | "deploymentInputSchema" | "outputSchema" | "connectionTypes"> & {
215
212
  configSchema: z.ZodObject<CShape>;
216
- deploymentInputSchema: z.ZodObject<DShape>;
213
+ deploymentInputSchema: DSchema;
217
214
  outputSchema: z.ZodObject<OShape>;
218
215
  connectionTypes: ConnTypes;
216
+ /**
217
+ * Artifact types this infra component supports receiving.
218
+ * Required when any provider implements `upsertArtifacts`.
219
+ */
220
+ acceptedArtifactTypes?: DeploymentArtifactType[];
219
221
  };
220
222
  export type ArtifactInfo = {
221
223
  artifact: {
@@ -319,6 +321,18 @@ export declare function connectionHandler<D extends ConnectionInterfaceDef>(entr
319
321
  * connectorComponentName and selfComponentName) via closure.
320
322
  */
321
323
  export type ConnectFn<S, ConnectionType extends string, P extends CloudProvider = CloudProvider> = (ctx: ConnectFnCtx<S, P>) => readonly ConnectionHandlerEntry<ConnectionType, any>[];
324
+ /**
325
+ * Naming function for Pulumi resources. Used by all component types to generate
326
+ * deterministic, collision-free resource names scoped to the component's unique ID.
327
+ *
328
+ * Supports both tagged-template and plain-string invocation:
329
+ * $`my-resource`
330
+ * $("my-resource")
331
+ */
332
+ export type NamingFn = {
333
+ (name: string, ...values: any[]): string;
334
+ (strings: TemplateStringsArray, ...values: any[]): string;
335
+ };
322
336
  /**
323
337
  * Component entry in the URLRegister provision context.
324
338
  * Reference metadata for components, keyed by their original URI.
@@ -462,18 +476,18 @@ export type DeclaredConnectionInterfaces = Map<string, {
462
476
  schema: z.ZodTypeAny;
463
477
  data: any;
464
478
  }>;
465
- export declare class InfraComponent<CShape extends z.ZodRawShape, DShape extends z.ZodRawShape, OShape extends z.ZodRawShape = EmptyOutputShape, ConnTypes extends Record<string, {
479
+ export declare class InfraComponent<CShape extends z.ZodRawShape, DSchema extends z.ZodTypeAny, OShape extends z.ZodRawShape = EmptyOutputShape, ConnTypes extends Record<string, {
466
480
  description: string;
467
481
  }> = Record<string, {
468
482
  description: string;
469
483
  }>> {
470
- opts: InfraComponentOpts<CShape, DShape, OShape, ConnTypes>;
484
+ opts: InfraComponentOpts<CShape, DSchema, OShape, ConnTypes>;
471
485
  providers: ProviderRegistry;
472
486
  validationSchema: z.ZodTypeAny;
473
487
  validationDeploymentInputSchema: z.ZodTypeAny;
474
488
  private declaredConnectionInterfaces;
475
- constructor(opts: InfraComponentOpts<CShape, DShape, OShape, ConnTypes>);
476
- implement<P extends CloudProvider, SShape extends z.ZodRawShape = EmptyStateShape>(provider: P, fns: ProviderFnsDef<InferZodType<CShape>, InferZodType<DShape>, InferOutputType<OShape>, SShape, keyof ConnTypes & string, P>): this;
489
+ constructor(opts: InfraComponentOpts<CShape, DSchema, OShape, ConnTypes>);
490
+ implement<P extends CloudProvider, SShape extends z.ZodRawShape = EmptyStateShape>(provider: P, fns: ProviderFnsDef<InferZodType<CShape>, z.infer<DSchema>, InferOutputType<OShape>, SShape, keyof ConnTypes & string, P>): this;
477
491
  /**
478
492
  * Get the schema for a specific connection interface.
479
493
  * Used by the orchestrator at runtime.
@@ -568,5 +582,121 @@ export declare class URLRegister<TName extends string, TInterface extends Connec
568
582
  */
569
583
  getProvision(): StoredProvisionFn;
570
584
  }
585
+ /**
586
+ * Context passed to the ArtifactRegistry provision function.
587
+ * Called inside the Pulumi program (during stack:sync) to create cloud resources
588
+ * for the artifact registry (e.g., ECR repository, GCP Artifact Registry repo,
589
+ * CodeArtifact domain, etc.).
590
+ *
591
+ * @property config - Validated config from configSchema (e.g., registry URL, scope)
592
+ * @property state - Mutable state persisted across provision runs
593
+ * @property $ - Naming helper for Pulumi resource names
594
+ * @property getCredentials - Returns typed cloud credentials for the configured provider
595
+ */
596
+ export type ArtifactRegistryProvisionCtx<TConfig, S, P extends CloudProvider = CloudProvider> = {
597
+ config: TConfig;
598
+ state: S;
599
+ $: NamingFn;
600
+ getCredentials: GetCredentialsFn<P>;
601
+ };
602
+ /**
603
+ * Context passed to the ArtifactRegistry publish function.
604
+ * Called outside Pulumi (like deploy/upsertArtifacts) to push a built artifact
605
+ * to the external registry under a versioned tag.
606
+ *
607
+ * @property componentName - Name of the app component being published
608
+ * @property artifact - The build artifact to publish (uri + type)
609
+ * @property version - The version string from the release command
610
+ * @property publishConfig - Per-component publish settings from registry_targets.publish_config
611
+ * @property state - Persisted state from provision (e.g., registry URL, repo name)
612
+ * @property getCredentials - Returns typed cloud credentials for the configured provider
613
+ */
614
+ export type ArtifactRegistryPublishCtx<S, P extends CloudProvider = CloudProvider> = {
615
+ componentName: string;
616
+ artifact: {
617
+ uri: string;
618
+ type: DeploymentArtifactType;
619
+ };
620
+ version: string;
621
+ publishConfig: Record<string, any>;
622
+ state: S;
623
+ getCredentials: GetCredentialsFn<P>;
624
+ };
625
+ /**
626
+ * Type-erased storage for ArtifactRegistry provision function.
627
+ */
628
+ export type StoredArtifactRegistryProvisionFn = (ctx: ArtifactRegistryProvisionCtx<any, any, any>) => Promise<void>;
629
+ /**
630
+ * Type-erased storage for ArtifactRegistry publish function.
631
+ */
632
+ export type StoredArtifactRegistryPublishFn = (ctx: ArtifactRegistryPublishCtx<any, any>) => Promise<void>;
633
+ /**
634
+ * ArtifactRegistry component for publishing build artifacts to external package
635
+ * registries (npm, PyPI, Docker Hub, ECR, GAR, CodeArtifact, etc.).
636
+ *
637
+ * Provides two lifecycle functions:
638
+ * - **`provision`**: Called inside Pulumi to create cloud resources for the registry
639
+ * (e.g., ECR repository, GAR repo, CodeArtifact domain). Runs during `stack:sync`.
640
+ * - **`publish`**: Called outside Pulumi to push a built artifact with a version tag.
641
+ * Runs during the release flow via `sdlc-components-run publish`.
642
+ *
643
+ * App components reference artifact registries via `registry_targets` in the
644
+ * TechStackConfig, parallel to how `infra_targets` links components to infra.
645
+ *
646
+ * @param TName - Unique name for this ArtifactRegistry definition
647
+ * @param CShape - Zod shape for the config schema (provision-time settings)
648
+ * @param SShape - Zod shape for the state schema (persisted across runs, default: empty)
649
+ *
650
+ * @example
651
+ * const registry = new ArtifactRegistry({
652
+ * name: "ecr-registry",
653
+ * acceptedArtifactTypes: [DeploymentArtifactType.oci_spec_image],
654
+ * configSchema: z.object({
655
+ * repositoryPrefix: z.string(),
656
+ * imageTagMutability: z.enum(["MUTABLE", "IMMUTABLE"]).default("IMMUTABLE"),
657
+ * }),
658
+ * stateSchema: z.object({
659
+ * repositoryUrl: z.string(),
660
+ * }),
661
+ * provision: async ({ config, state, $, getCredentials }) => {
662
+ * const repo = new aws.ecr.Repository($`repo`, {
663
+ * name: config.repositoryPrefix,
664
+ * imageTagMutability: config.imageTagMutability,
665
+ * });
666
+ * state.repositoryUrl = repo.repositoryUrl;
667
+ * },
668
+ * publish: async ({ componentName, artifact, version, state, getCredentials }) => {
669
+ * // Push the OCI image from internal store to ECR with version tag
670
+ * // e.g., docker tag + docker push to state.repositoryUrl
671
+ * },
672
+ * });
673
+ */
674
+ export declare class ArtifactRegistry<TName extends string, CShape extends z.ZodRawShape, SShape extends z.ZodRawShape = EmptyStateShape> {
675
+ readonly name: TName;
676
+ readonly acceptedArtifactTypes: DeploymentArtifactType[];
677
+ readonly configSchema: z.ZodObject<CShape>;
678
+ readonly stateSchema: z.ZodObject<SShape>;
679
+ readonly validationSchema: z.ZodTypeAny;
680
+ readonly initialState?: Partial<RuntimeState<SShape>>;
681
+ private readonly provisionFn;
682
+ private readonly publishFn;
683
+ constructor(opts: {
684
+ name: TName;
685
+ acceptedArtifactTypes: DeploymentArtifactType[];
686
+ configSchema: z.ZodObject<CShape>;
687
+ stateSchema?: z.ZodObject<SShape>;
688
+ initialState?: Partial<RuntimeState<SShape>>;
689
+ provision: (ctx: ArtifactRegistryProvisionCtx<InferZodType<CShape>, RuntimeState<SShape>, CloudProvider>) => Promise<void>;
690
+ publish: (ctx: ArtifactRegistryPublishCtx<RuntimeState<SShape>, CloudProvider>) => Promise<void>;
691
+ });
692
+ /**
693
+ * Get the provision function (for orchestrator use during stack:sync).
694
+ */
695
+ getProvision(): StoredArtifactRegistryProvisionFn;
696
+ /**
697
+ * Get the publish function (for orchestrator use during release/publish).
698
+ */
699
+ getPublish(): StoredArtifactRegistryPublishFn;
700
+ }
571
701
 
572
702
  export {};
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- import{z as j}from"zod";import*as Z from"@pulumi/pulumi";var W;((M)=>{M.aws="aws";M.gcloud="gcloud";M.azure="azure";M.linode="linode";M.hetzner="hetzner";M.cloudflare="cloudflare"})(W||={});var X;((F)=>{F.oci_spec_image="oci_spec_image";F.file="file"})(X||={});var Y=new Map;function $(b){return b.replace(/([a-z])([A-Z])/g,"$1-$2").replace(/[_\s]+/g,"-").toLowerCase().replace(/-+/g,"-").replace(/^-|-$/g,"")}function q(b){let B=$(b);if(B.length===0)throw new Error("Connection interface name cannot be empty");let F=Y.get(B);if(F!==void 0&&F!==b)throw new Error(`Connection interface name collision: '${b}' resolves to '${B}' which is already registered by '${F}'`);return Y.set(B,b),B}function E(b,B,F){return{name:q(b),schema:B,resultSchema:F}}function k(b,B){return b.schema.merge(B)}var x=E("public-http",j.object({})),I="@anonymous",R=j.object({});function H(b){if(b instanceof j.ZodObject){let B=b.shape,F={};for(let J in B)F[J]=H(B[J]);return j.object(F)}if(b instanceof j.ZodOptional)return H(b.unwrap()).optional();if(b instanceof j.ZodNullable)return H(b.unwrap()).nullable();if(b instanceof j.ZodDefault)return H(b._def.innerType).default(b._def.defaultValue);if(b instanceof j.ZodArray)return j.array(H(b.element));if(b instanceof j.ZodDiscriminatedUnion){let B=b._def.options.map((F)=>H(F));return j.discriminatedUnion(b._def.discriminator,B)}if(b instanceof j.ZodRecord){let B=b._def.keyType,F=b._def.valueType,J=B?H(B):j.string(),Q=F?H(F):j.any();return j.record(J,Q)}return j.union([b,j.custom((B)=>Z.Output.isInstance(B))])}var G=j.object({metadata:j.object({stateful:j.boolean(),proxiable:j.boolean()}),connectionTypes:j.record(j.string(),j.object({description:j.string().min(5)})),configSchema:j.custom(),deploymentInputSchema:j.custom(),outputSchema:j.custom()});function g(b){return b}var _=j.object({});class K{opts;providers;validationSchema;validationDeploymentInputSchema;declaredConnectionInterfaces=new Map;constructor(b){this.opts=G.parse(b),this.providers={},this.validationSchema=H(b.configSchema),this.validationDeploymentInputSchema=H(b.deploymentInputSchema)}implement(b,B){if(B.allocateComponent&&B.allocateWithPulumiCtx)throw new Error(`Provider '${b}' cannot define both 'allocateComponent' and 'allocateWithPulumiCtx'. These are mutually exclusive allocation strategies.`);return this.providers[b]={...B,stateSchema:B.stateSchema??_,initialState:B.initialState},this}getConnectionSchema(b){return b.schema}createDeclareConnectionInterfacesFn(){return(b)=>{this.declaredConnectionInterfaces=new Map;for(let B of b){let F=B.interface.schema,J=H(F),Q=J.safeParse(B.data);if(!Q.success)throw new Error(`Invalid data for connection interface '${B.interface.name}': ${Q.error.message}`);this.declaredConnectionInterfaces.set(B.interface.name,{schema:J,data:B.data})}}}getDeclaredInterfaces(){return this.declaredConnectionInterfaces}}var L=j.object({name:j.string().min(1),interface:j.custom(),configSchema:j.custom(),stateSchema:j.custom().optional(),provision:j.function()});class U{name;interface;configSchema;stateSchema;validationSchema;provisionFn;initialState;constructor(b){L.parse(b),this.name=b.name,this.interface=b.interface,this.configSchema=b.configSchema,this.stateSchema=b.stateSchema??_,this.validationSchema=H(b.configSchema),this.provisionFn=b.provision,this.initialState=b.initialState}getProvision(){return this.provisionFn}}export{$ as toCanonicalInterfaceName,k as extendSchema,E as defineConnectionInterface,g as connectionHandler,U as URLRegister,x as PublicHTTPCI,K as InfraComponent,X as DeploymentArtifactType,W as CloudProvider,I as ANONYMOUS_CONNECTION_TYPE};
1
+ import{z as B}from"zod";import*as $ from"@pulumi/pulumi";var Z;((Q)=>{Q.aws="aws";Q.gcloud="gcloud";Q.azure="azure";Q.linode="linode";Q.hetzner="hetzner";Q.cloudflare="cloudflare"})(Z||={});var X;((H)=>{H.oci_spec_image="oci_spec_image";H.file="file"})(X||={});var _=new Map;function q(j){return j.replace(/([a-z])([A-Z])/g,"$1-$2").replace(/[_\s]+/g,"-").toLowerCase().replace(/-+/g,"-").replace(/^-|-$/g,"")}function E(j){let F=q(j);if(F.length===0)throw new Error("Connection interface name cannot be empty");let H=_.get(F);if(H!==void 0&&H!==j)throw new Error(`Connection interface name collision: '${j}' resolves to '${F}' which is already registered by '${H}'`);return _.set(F,j),F}function G(j,F,H){return{name:E(j),schema:F,resultSchema:H}}function I(j,F){return j.schema.merge(F)}var R=G("public-http",B.object({})),P="@anonymous",g=B.object({});function J(j){if(j instanceof B.ZodObject){let F=j.shape,H={};for(let M in F)H[M]=J(F[M]);return B.object(H)}if(j instanceof B.ZodOptional)return J(j.unwrap()).optional();if(j instanceof B.ZodNullable)return J(j.unwrap()).nullable();if(j instanceof B.ZodDefault)return J(j._def.innerType).default(j._def.defaultValue);if(j instanceof B.ZodArray)return B.array(J(j.element));if(j instanceof B.ZodDiscriminatedUnion){let F=j._def.options.map((H)=>J(H));return B.discriminatedUnion(j._def.discriminator,F)}if(j instanceof B.ZodRecord){let F=j._def.keyType,H=j._def.valueType,M=F?J(F):B.string(),W=H?J(H):B.any();return B.record(M,W)}return B.union([j,B.custom((F)=>$.Output.isInstance(F))])}var K=B.object({metadata:B.object({stateful:B.boolean(),proxiable:B.boolean()}),connectionTypes:B.record(B.string(),B.object({description:B.string().min(5)})),acceptedArtifactTypes:B.array(B.nativeEnum(X)).optional(),configSchema:B.custom(),deploymentInputSchema:B.custom(),outputSchema:B.custom()});function D(j){return j}var Y=B.object({});class L{opts;providers;validationSchema;validationDeploymentInputSchema;declaredConnectionInterfaces=new Map;constructor(j){this.opts=K.parse(j),this.providers={},this.validationSchema=J(j.configSchema),this.validationDeploymentInputSchema=J(j.deploymentInputSchema)}implement(j,F){if(F.allocateComponent&&F.allocateWithPulumiCtx)throw new Error(`Provider '${j}' cannot define both 'allocateComponent' and 'allocateWithPulumiCtx'. These are mutually exclusive allocation strategies.`);if(F.upsertArtifacts&&(!this.opts.acceptedArtifactTypes||this.opts.acceptedArtifactTypes.length===0))throw new Error(`Provider '${j}' defines 'upsertArtifacts' but the component is missing 'acceptedArtifactTypes'. Declare which artifact types this component supports (e.g. [DeploymentArtifactType.oci_spec_image]).`);return this.providers[j]={...F,stateSchema:F.stateSchema??Y,initialState:F.initialState},this}getConnectionSchema(j){return j.schema}createDeclareConnectionInterfacesFn(){return(j)=>{this.declaredConnectionInterfaces=new Map;for(let F of j){let H=F.interface.schema,M=J(H),W=M.safeParse(F.data);if(!W.success)throw new Error(`Invalid data for connection interface '${F.interface.name}': ${W.error.message}`);this.declaredConnectionInterfaces.set(F.interface.name,{schema:M,data:F.data})}}}getDeclaredInterfaces(){return this.declaredConnectionInterfaces}}var U=B.object({name:B.string().min(1),interface:B.custom(),configSchema:B.custom(),stateSchema:B.custom().optional(),provision:B.function()});class V{name;interface;configSchema;stateSchema;validationSchema;provisionFn;initialState;constructor(j){U.parse(j),this.name=j.name,this.interface=j.interface,this.configSchema=j.configSchema,this.stateSchema=j.stateSchema??Y,this.validationSchema=J(j.configSchema),this.provisionFn=j.provision,this.initialState=j.initialState}getProvision(){return this.provisionFn}}var b=B.object({name:B.string().min(1),acceptedArtifactTypes:B.array(B.nativeEnum(X)).min(1),configSchema:B.custom(),stateSchema:B.custom().optional(),provision:B.function(),publish:B.function()});class N{name;acceptedArtifactTypes;configSchema;stateSchema;validationSchema;initialState;provisionFn;publishFn;constructor(j){b.parse(j),this.name=j.name,this.acceptedArtifactTypes=j.acceptedArtifactTypes,this.configSchema=j.configSchema,this.stateSchema=j.stateSchema??Y,this.validationSchema=J(j.configSchema),this.initialState=j.initialState,this.provisionFn=j.provision,this.publishFn=j.publish}getProvision(){return this.provisionFn}getPublish(){return this.publishFn}}export{q as toCanonicalInterfaceName,I as extendSchema,G as defineConnectionInterface,D as connectionHandler,V as URLRegister,R as PublicHTTPCI,L as InfraComponent,X as DeploymentArtifactType,Z as CloudProvider,N as ArtifactRegistry,P as ANONYMOUS_CONNECTION_TYPE};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sdlcworks/components",
3
- "version": "0.0.37",
3
+ "version": "0.0.38",
4
4
  "module": "dist/index.js",
5
5
  "files": [
6
6
  "dist"