@vyriy/stack 0.2.0 → 0.3.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.
package/AGENTS.md ADDED
@@ -0,0 +1,65 @@
1
+ # Vyriy Package Agent Guide
2
+
3
+ This package belongs to the Vyriy toolkit. Keep changes calm, explicit, reusable, and easy to reason about.
4
+
5
+ ## Architecture
6
+
7
+ - Prefer simple modules over clever frameworks or hidden conventions.
8
+ - Keep package boundaries explicit and avoid project-specific coupling.
9
+ - Extract only proven reusable behavior.
10
+ - Keep public APIs small, typed, documented, and stable.
11
+ - Prefer SSR-friendly and SSG-friendly code paths.
12
+ - Keep integrations replaceable and avoid hard coupling to a CMS or runtime host.
13
+ - Prefer AWS serverless-compatible assumptions when infrastructure concerns appear.
14
+
15
+ ## File Shape
16
+
17
+ - Prefer one exported runtime method, component, or helper per production file when it stays readable.
18
+ - Prefer one matching test file per production file, for example `feature.ts` and `feature.test.ts`.
19
+ - Use focused folders when behavior naturally splits into several related files.
20
+ - Keep `index.ts` as a public re-export surface only. Do not place implementation logic in it.
21
+ - Use `.js` relative import and export specifiers in TypeScript source where package style requires it.
22
+ - Add `types.ts` when public shared types are part of the package contract.
23
+ - Keep constants near the code that owns them unless they are shared or clarify repeated behavior.
24
+
25
+ ## Public Surface
26
+
27
+ - Every new public export should be re-exported from `index.ts`.
28
+ - Add or update `index.test.ts` when the public export surface changes.
29
+ - Add JSDoc for public exports when behavior, parameters, return values, or usage expectations need explanation.
30
+ - Do not hand-maintain source package `exports` maps unless the package has a real custom publishing need.
31
+
32
+ ## Tests
33
+
34
+ - Tests use Jest and `@jest/globals`.
35
+ - Cover public behavior and meaningful edge cases.
36
+ - Prefer behavior-focused tests over private implementation lock-in.
37
+ - When mocking modules, install mocks before loading the module under test.
38
+ - Use focused validation when changing package behavior:
39
+
40
+ ```bash
41
+ yarn jest packages/<package> --runInBand --coverage=false
42
+ ```
43
+
44
+ ## Documentation
45
+
46
+ - Keep `README.md` concise and usage-oriented.
47
+ - Start package READMEs with `# @vyriy/<package>`.
48
+ - Document real public exports, supported options, and examples that actually work.
49
+ - Keep `doc.mdx` as the Storybook/docs wrapper for the README when the package participates in docs.
50
+ - For component packages, include Storybook coverage for supported states and common usage.
51
+
52
+ ## Components
53
+
54
+ - Prefer lightweight React 19+ components with TypeScript.
55
+ - Keep components SSR-friendly and avoid browser globals during render.
56
+ - Prefer composable props and Bootstrap-compatible ergonomics where practical.
57
+ - Put each public component in its own file with a matching test.
58
+ - Add Storybook stories when a component has visual states, variants, or interaction states.
59
+
60
+ ## Change Discipline
61
+
62
+ - Keep changes scoped to the requested behavior.
63
+ - Avoid unrelated refactors and metadata churn.
64
+ - Sync implementation, tests, README, `doc.mdx`, and public re-exports together.
65
+ - Prefer the option that is simpler to explain, easier to evolve, and calmer to maintain.
package/README.md CHANGED
@@ -149,3 +149,322 @@ stack(
149
149
  },
150
150
  );
151
151
  ```
152
+
153
+ ## API Gateway Lambda Example
154
+
155
+ This example wires a Lambda-backed REST API to an API Gateway custom domain:
156
+
157
+ - find an existing hosted zone
158
+ - create a DNS-validated ACM certificate
159
+ - create a Lambda from built API assets
160
+ - create an edge REST API with proxy Lambda integration
161
+ - map the API to a custom domain
162
+ - create a Route 53 alias record for the API Gateway domain
163
+
164
+ Edge API Gateway custom domains use edge-optimized CloudFront distributions, so keep the certificate in `us-east-1`.
165
+
166
+ ```ts
167
+ import { CfnOutput, Stack, type StackProps } from 'aws-cdk-lib';
168
+ import { ApiGatewayDomain } from 'aws-cdk-lib/aws-route53-targets';
169
+ import type { Construct } from 'constructs';
170
+
171
+ import { stack } from '@vyriy/cdk';
172
+ import { acm, apigateway, lambda, route53 } from '@vyriy/stack';
173
+ import { getPackage } from '@vyriy/package';
174
+ import { path } from '@vyriy/path';
175
+
176
+ stack(
177
+ class ApiStack extends Stack {
178
+ constructor(scope: Construct, id: string, props: StackProps & { env: { account: string; region: string } }) {
179
+ super(scope, id, props);
180
+
181
+ const domain = 'api.site.com';
182
+ const hostedZoneName = 'site.com';
183
+ const { description } = getPackage();
184
+
185
+ const zone = route53.getHostedZone(this, 'HostedZone', {
186
+ zoneName: hostedZoneName,
187
+ });
188
+
189
+ const certificate = acm.createCertificate(this, 'Certificate', {
190
+ domainName: domain,
191
+ validation: acm.CertificateValidation.fromDns(zone),
192
+ });
193
+
194
+ const apiLambda = lambda.createLambda(this, 'ApiLambda', {
195
+ code: lambda.Code.fromAsset(path('dist', 'api')),
196
+ description,
197
+ functionName: 'api',
198
+ handler: 'index.handler',
199
+ });
200
+
201
+ const apiGateway = apigateway.createApiGateway(this, 'ApiGateway', {
202
+ defaultIntegration: apigateway.createIntegration(apiLambda, { proxy: true }),
203
+ description,
204
+ restApiName: `${id}-api-gateway`,
205
+ });
206
+
207
+ const apiDomainName = apigateway.createDomainName(this, 'ApiGatewayDomain', {
208
+ certificate,
209
+ domainName: domain,
210
+ });
211
+
212
+ apigateway.createBasePathMapping(this, 'ApiBasePathMapping', {
213
+ domainName: apiDomainName,
214
+ restApi: apiGateway,
215
+ });
216
+
217
+ route53.createARecord(this, 'ARecord', {
218
+ recordName: domain,
219
+ target: route53.RecordTarget.fromAlias(new ApiGatewayDomain(apiDomainName)),
220
+ zone,
221
+ });
222
+
223
+ new CfnOutput(this, 'Account', { value: props.env.account });
224
+ new CfnOutput(this, 'Region', { value: props.env.region });
225
+
226
+ new CfnOutput(this, 'LambdaName', { value: apiLambda.functionName });
227
+
228
+ new CfnOutput(this, 'ApiGatewayId', { value: apiGateway.restApiId });
229
+ new CfnOutput(this, 'ApiGatewayUrl', { value: apiGateway.url });
230
+
231
+ new CfnOutput(this, 'ApiUrl', { value: `https://${domain}/` });
232
+ }
233
+ },
234
+ );
235
+ ```
236
+
237
+ ## Fargate Worker Example
238
+
239
+ This example wires a Fargate task foundation to an existing VPC:
240
+
241
+ - read the VPC id from the environment
242
+ - load package metadata for reusable descriptions
243
+ - create a security group for the workload
244
+ - create an ECR repository for the task image
245
+ - create an ECS cluster in the VPC
246
+ - create a Fargate task definition with AWS Logs configured
247
+
248
+ ```ts
249
+ import { CfnOutput, Stack, type StackProps } from 'aws-cdk-lib';
250
+ import type { Construct } from 'constructs';
251
+
252
+ import { stack } from '@vyriy/cdk';
253
+ import { getVpc } from '@vyriy/env';
254
+ import { getPackage } from '@vyriy/package';
255
+ import { ec2, ecr, ecs } from '@vyriy/stack';
256
+
257
+ stack(
258
+ class FargateWorkerStack extends Stack {
259
+ constructor(scope: Construct, id: string, props: StackProps & { env: { account: string; region: string } }) {
260
+ super(scope, id, props);
261
+
262
+ const { description } = getPackage();
263
+ const vpc = ec2.findVpc(this, 'Vpc', { vpcId: getVpc() });
264
+ const subnets = vpc.privateSubnets;
265
+
266
+ const securityGroup = ec2.createSecurityGroup(this, 'SecurityGroup', {
267
+ allowAllOutbound: true,
268
+ description,
269
+ securityGroupName: `${id}-${vpc.vpcId}-securityGroup`,
270
+ vpc,
271
+ });
272
+
273
+ const repository = ecr.createRepository(this, 'SyncRepository', {
274
+ repositoryName: `${id}-repository`,
275
+ });
276
+
277
+ const cluster = ecs.createCluster(this, 'FargateCluster', {
278
+ clusterName: `${id}-cluster`,
279
+ vpc,
280
+ });
281
+
282
+ const taskDefinition = ecs.createTaskDefinition(this, 'SyncFargateTaskDefinition', {
283
+ cpu: 256,
284
+ family: `${id}-task-definition`,
285
+ memoryLimitMiB: 512,
286
+ });
287
+
288
+ taskDefinition.addContainer('SyncTaskDefinition', {
289
+ cpu: 256,
290
+ image: ecs.ContainerImage.fromEcrRepository(repository),
291
+ logging: ecs.setLogs({ streamPrefix: `${id}-cluster-logs` }),
292
+ memoryLimitMiB: 512,
293
+ });
294
+
295
+ new CfnOutput(this, 'Account', { value: props.env.account });
296
+ new CfnOutput(this, 'Region', { value: props.env.region });
297
+
298
+ new CfnOutput(this, 'VpcId', { value: vpc.vpcId });
299
+ new CfnOutput(this, 'PrivateSubnetIds', { value: subnets.map((subnet) => subnet.subnetId).join(',') });
300
+ new CfnOutput(this, 'SecurityGroupId', { value: securityGroup.securityGroupId });
301
+
302
+ new CfnOutput(this, 'RepositoryName', { value: repository.repositoryName });
303
+ new CfnOutput(this, 'ClusterName', { value: cluster.clusterName });
304
+
305
+ new CfnOutput(this, 'TaskDefinitionArn', { value: taskDefinition.taskDefinitionArn });
306
+ }
307
+ },
308
+ );
309
+ ```
310
+
311
+ ## DynamoDB Access Examples
312
+
313
+ These examples show small DynamoDB table definitions and common IAM access patterns for Lambda and Fargate workloads.
314
+
315
+ Create two country tables:
316
+
317
+ ```ts
318
+ import { dynamodb } from '@vyriy/stack';
319
+
320
+ const countriesIndexTable = dynamodb.createTable(this, 'CountriesIndexTable', {
321
+ partitionKey: {
322
+ name: 'key',
323
+ type: dynamodb.AttributeType.STRING,
324
+ },
325
+ tableName: `${id}-countries-index`,
326
+ });
327
+
328
+ const countriesTable = dynamodb.createTable(this, 'CountriesTable', {
329
+ partitionKey: {
330
+ name: 'key',
331
+ type: dynamodb.AttributeType.STRING,
332
+ },
333
+ sortKey: {
334
+ name: 'code',
335
+ type: dynamodb.AttributeType.STRING,
336
+ },
337
+ tableName: `${id}-countries`,
338
+ });
339
+ ```
340
+
341
+ Grant Lambda access to the tables:
342
+
343
+ ```ts
344
+ countriesIndexTable.grantReadData(apiLambda);
345
+ countriesTable.grantReadWriteData(apiLambda);
346
+
347
+ // Use full access only for maintenance or sync jobs that really need table-level control.
348
+ countriesIndexTable.grantFullAccess(apiLambda);
349
+ ```
350
+
351
+ Grant Fargate task access through the task role:
352
+
353
+ ```ts
354
+ countriesIndexTable.grantReadData(taskDefinition.taskRole);
355
+ countriesTable.grantReadWriteData(taskDefinition.taskRole);
356
+
357
+ // Full access is useful for controlled backfill or indexing tasks.
358
+ countriesIndexTable.grantFullAccess(taskDefinition.taskRole);
359
+ ```
360
+
361
+ Allow a Lambda to run the Fargate task definition:
362
+
363
+ ```ts
364
+ taskDefinition.grantRun(apiLambda);
365
+ ```
366
+
367
+ ## Messaging And Parameter Examples
368
+
369
+ These examples show simple SNS, SQS, and SSM helper usage for application stacks.
370
+
371
+ Create an SNS topic and grant publishers/subscribers:
372
+
373
+ ```ts
374
+ import { sns } from '@vyriy/stack';
375
+
376
+ const eventsTopic = sns.createTopic(this, 'EventsTopic', {
377
+ topicName: `${id}-events`,
378
+ });
379
+
380
+ eventsTopic.grantPublish(apiLambda);
381
+ eventsTopic.grantSubscribe(taskDefinition.taskRole);
382
+ ```
383
+
384
+ Import an existing SNS topic:
385
+
386
+ ```ts
387
+ const importedEventsTopic = sns.fromTopicArn(
388
+ this,
389
+ 'ImportedEventsTopic',
390
+ `arn:aws:sns:${this.region}:${this.account}:${id}-events`,
391
+ );
392
+
393
+ importedEventsTopic.grantPublish(taskDefinition.taskRole);
394
+ ```
395
+
396
+ Create an SQS queue and allow Lambda/Fargate workers to use it:
397
+
398
+ ```ts
399
+ import { Duration } from 'aws-cdk-lib';
400
+
401
+ import { sqs } from '@vyriy/stack';
402
+
403
+ const jobsQueue = sqs.createQueue(this, 'JobsQueue', {
404
+ queueName: `${id}-jobs`,
405
+ visibilityTimeout: Duration.seconds(60),
406
+ });
407
+
408
+ jobsQueue.grantSendMessages(apiLambda);
409
+ jobsQueue.grantConsumeMessages(taskDefinition.taskRole);
410
+ ```
411
+
412
+ Import an existing SQS queue:
413
+
414
+ ```ts
415
+ const importedJobsQueue = sqs.fromQueueAttributes(this, 'ImportedJobsQueue', {
416
+ queueArn: `arn:aws:sqs:${this.region}:${this.account}:${id}-jobs`,
417
+ queueUrl: `https://sqs.${this.region}.amazonaws.com/${this.account}/${id}-jobs`,
418
+ });
419
+
420
+ importedJobsQueue.grantConsumeMessages(apiLambda);
421
+ ```
422
+
423
+ Read SSM parameter values and import parameters:
424
+
425
+ ```ts
426
+ import { ssm } from '@vyriy/stack';
427
+
428
+ const apiBaseUrl = ssm.valueForStringParameter(this, `/${id}/api/base-url`);
429
+
430
+ const importedApiKey = ssm.fromSecureStringParameterAttributes(this, 'ImportedApiKey', {
431
+ parameterName: `/${id}/api/key`,
432
+ version: 1,
433
+ });
434
+
435
+ importedApiKey.grantRead(apiLambda);
436
+ importedApiKey.grantRead(taskDefinition.taskRole);
437
+ ```
438
+
439
+ Pass SSM parameter values into Lambda and Fargate environment variables:
440
+
441
+ ```ts
442
+ const apiBaseUrlParameterName = `/${id}/api/base-url`;
443
+ const apiKeyParameterName = `/${id}/api/key`;
444
+
445
+ const apiBaseUrl = ssm.valueForStringParameter(this, apiBaseUrlParameterName);
446
+ const apiKey = ssm.valueForStringParameter(this, apiKeyParameterName);
447
+
448
+ const apiLambda = lambda.createLambda(this, 'ApiLambda', {
449
+ code: lambda.Code.fromAsset(path('dist', 'api')),
450
+ environment: {
451
+ API_BASE_URL: apiBaseUrl,
452
+ API_KEY_PARAMETER_NAME: apiKeyParameterName,
453
+ },
454
+ handler: 'index.handler',
455
+ });
456
+
457
+ taskDefinition.addContainer('WorkerContainer', {
458
+ environment: {
459
+ API_BASE_URL: apiBaseUrl,
460
+ API_KEY: apiKey,
461
+ },
462
+ image: ecs.ContainerImage.fromEcrRepository(repository),
463
+ logging: ecs.setLogs({ streamPrefix: `${id}-worker-logs` }),
464
+ });
465
+
466
+ const importedApiKeyForEnv = ssm.fromStringParameterName(this, 'ImportedApiKeyForEnv', apiKeyParameterName);
467
+
468
+ importedApiKeyForEnv.grantRead(apiLambda);
469
+ importedApiKeyForEnv.grantRead(taskDefinition.taskRole);
470
+ ```
@@ -0,0 +1,10 @@
1
+ import { Construct } from 'constructs';
2
+ import { AwsIntegration, AwsIntegrationProps, BasePathMapping, BasePathMappingProps, DomainName, DomainNameProps, EndpointType, LambdaIntegration, LambdaIntegrationOptions, Model, RestApi, RestApiProps } from 'aws-cdk-lib/aws-apigateway';
3
+ import { IFunction } from 'aws-cdk-lib/aws-lambda';
4
+ export { RestApi, EndpointType, Model };
5
+ export type { RestApiProps };
6
+ export declare const createApiGateway: (scope: Construct, id: string, props: RestApiProps) => RestApi;
7
+ export declare const createIntegration: (lambda: IFunction, options: LambdaIntegrationOptions) => LambdaIntegration;
8
+ export declare const createDomainName: (scope: Construct, id: string, props: DomainNameProps) => DomainName;
9
+ export declare const createBasePathMapping: (scope: Construct, id: string, props: BasePathMappingProps) => BasePathMapping;
10
+ export declare const createAwsIntegration: (props: AwsIntegrationProps) => AwsIntegration;
@@ -0,0 +1,29 @@
1
+ import { AwsIntegration, BasePathMapping, DomainName, EndpointType, LambdaIntegration, Model, RestApi, } from 'aws-cdk-lib/aws-apigateway';
2
+ export { RestApi, EndpointType, Model };
3
+ export const createApiGateway = (scope, id, props) => {
4
+ const { defaultIntegration, ...rest } = props;
5
+ const apiProps = {
6
+ deployOptions: {
7
+ stageName: 'api',
8
+ methodOptions: {
9
+ '/*/*': {
10
+ throttlingRateLimit: 100,
11
+ throttlingBurstLimit: 200,
12
+ },
13
+ },
14
+ },
15
+ defaultIntegration,
16
+ endpointTypes: [EndpointType.EDGE],
17
+ ...rest,
18
+ };
19
+ const apiGateway = new RestApi(scope, id, apiProps);
20
+ apiGateway.root.addProxy({ anyMethod: true, defaultIntegration });
21
+ return apiGateway;
22
+ };
23
+ export const createIntegration = (lambda, options) => new LambdaIntegration(lambda, options);
24
+ export const createDomainName = (scope, id, props) => new DomainName(scope, id, {
25
+ endpointType: EndpointType.EDGE,
26
+ ...props,
27
+ });
28
+ export const createBasePathMapping = (scope, id, props) => new BasePathMapping(scope, id, props);
29
+ export const createAwsIntegration = (props) => new AwsIntegration(props);
@@ -0,0 +1,4 @@
1
+ import { Construct } from 'constructs';
2
+ import { AttributeType, Table, TableProps } from 'aws-cdk-lib/aws-dynamodb';
3
+ export { AttributeType };
4
+ export declare const createTable: (scope: Construct, id: string, props: TableProps) => Table;
@@ -0,0 +1,8 @@
1
+ import { RemovalPolicy } from 'aws-cdk-lib';
2
+ import { AttributeType, BillingMode, Table } from 'aws-cdk-lib/aws-dynamodb';
3
+ export { AttributeType };
4
+ export const createTable = (scope, id, props) => new Table(scope, id, {
5
+ billingMode: BillingMode.PAY_PER_REQUEST,
6
+ removalPolicy: RemovalPolicy.DESTROY,
7
+ ...props,
8
+ });
package/ec2/index.d.ts ADDED
@@ -0,0 +1,8 @@
1
+ import { Construct } from 'constructs';
2
+ import { IVpc, InterfaceVpcEndpoint, InterfaceVpcEndpointProps, SecurityGroup, SecurityGroupProps, SubnetType, Vpc, VpcLookupOptions } from 'aws-cdk-lib/aws-ec2';
3
+ export { SubnetType };
4
+ export type { IVpc, SecurityGroup };
5
+ export declare const findVpc: (scope: Construct, id: string, props: VpcLookupOptions) => IVpc;
6
+ export declare const createSecurityGroup: (scope: Construct, id: string, props: SecurityGroupProps) => SecurityGroup;
7
+ export declare const createVpcEndpoint: (scope: Construct, id: string, props: InterfaceVpcEndpointProps) => InterfaceVpcEndpoint;
8
+ export declare const createVpc: (scope: Construct, id: string, props?: Omit<Vpc, "subnetConfiguration">) => Vpc;
package/ec2/index.js ADDED
@@ -0,0 +1,19 @@
1
+ import { InterfaceVpcEndpoint, SecurityGroup, SubnetType, Vpc, } from 'aws-cdk-lib/aws-ec2';
2
+ export { SubnetType };
3
+ export const findVpc = (scope, id, props) => Vpc.fromLookup(scope, id, props);
4
+ export const createSecurityGroup = (scope, id, props) => new SecurityGroup(scope, id, props);
5
+ export const createVpcEndpoint = (scope, id, props) => new InterfaceVpcEndpoint(scope, id, props);
6
+ export const createVpc = (scope, id, props) => new Vpc(scope, id, {
7
+ maxAzs: 2,
8
+ subnetConfiguration: [
9
+ {
10
+ name: 'Public',
11
+ subnetType: SubnetType.PUBLIC,
12
+ },
13
+ {
14
+ name: 'Private',
15
+ subnetType: SubnetType.PRIVATE_WITH_EGRESS,
16
+ },
17
+ ],
18
+ ...props,
19
+ });
package/ecr/index.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ import { Construct } from 'constructs';
2
+ import { Repository, RepositoryProps } from 'aws-cdk-lib/aws-ecr';
3
+ export declare const createRepository: (scope: Construct, id: string, props: RepositoryProps) => Repository;
package/ecr/index.js ADDED
@@ -0,0 +1,8 @@
1
+ import { RemovalPolicy } from 'aws-cdk-lib';
2
+ import { Repository } from 'aws-cdk-lib/aws-ecr';
3
+ export const createRepository = (scope, id, props) => new Repository(scope, id, {
4
+ removalPolicy: RemovalPolicy.DESTROY,
5
+ lifecycleRules: [{ maxImageCount: 3 }],
6
+ emptyOnDelete: true,
7
+ ...props,
8
+ });
package/ecs/index.d.ts ADDED
@@ -0,0 +1,6 @@
1
+ import { Construct } from 'constructs';
2
+ import { AwsLogDriverProps, Cluster, ClusterProps, FargateTaskDefinition, FargateTaskDefinitionProps } from 'aws-cdk-lib/aws-ecs';
3
+ export { ContainerImage } from 'aws-cdk-lib/aws-ecs';
4
+ export declare const createCluster: (scope: Construct, id: string, props: ClusterProps) => Cluster;
5
+ export declare const createTaskDefinition: (scope: Construct, id: string, props: FargateTaskDefinitionProps) => FargateTaskDefinition;
6
+ export declare const setLogs: (props: AwsLogDriverProps) => import("aws-cdk-lib/aws-ecs").LogDriver;
package/ecs/index.js ADDED
@@ -0,0 +1,9 @@
1
+ import { Cluster, FargateTaskDefinition, LogDrivers, } from 'aws-cdk-lib/aws-ecs';
2
+ import { RetentionDays } from 'aws-cdk-lib/aws-logs';
3
+ export { ContainerImage } from 'aws-cdk-lib/aws-ecs';
4
+ export const createCluster = (scope, id, props) => new Cluster(scope, id, props);
5
+ export const createTaskDefinition = (scope, id, props) => new FargateTaskDefinition(scope, id, props);
6
+ export const setLogs = (props) => LogDrivers.awsLogs({
7
+ logRetention: RetentionDays.ONE_WEEK,
8
+ ...props,
9
+ });
package/index.d.ts CHANGED
@@ -1,5 +1,14 @@
1
1
  export * as acm from './certificatemanager/index.js';
2
+ export * as apigateway from './apigateway/index.js';
2
3
  export * as cf from './cloudfront/index.js';
3
4
  export * as deployment from './deployment/index.js';
5
+ export * as dynamodb from './dynamodb/index.js';
6
+ export * as ec2 from './ec2/index.js';
7
+ export * as ecr from './ecr/index.js';
8
+ export * as ecs from './ecs/index.js';
9
+ export * as lambda from './lambda/index.js';
4
10
  export * as route53 from './route53/index.js';
5
11
  export * as s3 from './s3/index.js';
12
+ export * as sns from './sns/index.js';
13
+ export * as sqs from './sqs/index.js';
14
+ export * as ssm from './ssm/index.js';
package/index.js CHANGED
@@ -1,5 +1,14 @@
1
1
  export * as acm from './certificatemanager/index.js';
2
+ export * as apigateway from './apigateway/index.js';
2
3
  export * as cf from './cloudfront/index.js';
3
4
  export * as deployment from './deployment/index.js';
5
+ export * as dynamodb from './dynamodb/index.js';
6
+ export * as ec2 from './ec2/index.js';
7
+ export * as ecr from './ecr/index.js';
8
+ export * as ecs from './ecs/index.js';
9
+ export * as lambda from './lambda/index.js';
4
10
  export * as route53 from './route53/index.js';
5
11
  export * as s3 from './s3/index.js';
12
+ export * as sns from './sns/index.js';
13
+ export * as sqs from './sqs/index.js';
14
+ export * as ssm from './ssm/index.js';
@@ -0,0 +1,9 @@
1
+ import { Construct } from 'constructs';
2
+ import { Code, FunctionProps, FunctionUrl, FunctionUrlProps, Function as LambdaFunction, LayerVersion, Runtime } from 'aws-cdk-lib/aws-lambda';
3
+ export { SqsEventSource } from 'aws-cdk-lib/aws-lambda-event-sources';
4
+ export { Code, Runtime, LayerVersion };
5
+ export type { LambdaFunction, FunctionProps };
6
+ export declare const createLambda: (scope: Construct, id: string, props: Omit<FunctionProps, "runtime"> & {
7
+ runtime?: Runtime;
8
+ }) => LambdaFunction;
9
+ export declare const createFunctionUrl: (scope: Construct, id: string, props: FunctionUrlProps) => FunctionUrl;
@@ -0,0 +1,27 @@
1
+ import { Duration, RemovalPolicy } from 'aws-cdk-lib';
2
+ import { Code, FunctionUrl, Function as LambdaFunction, LayerVersion, Runtime, } from 'aws-cdk-lib/aws-lambda';
3
+ import { LogGroup, RetentionDays } from 'aws-cdk-lib/aws-logs';
4
+ export { SqsEventSource } from 'aws-cdk-lib/aws-lambda-event-sources';
5
+ export { Code, Runtime, LayerVersion };
6
+ export const createLambda = (scope, id, props) => {
7
+ const { functionName, code, handler, runtime = Runtime.NODEJS_24_X, timeout = Duration.seconds(29), memorySize = 128, environment = {}, ...rest } = props;
8
+ const lambdaFunction = new LambdaFunction(scope, id, {
9
+ functionName,
10
+ code,
11
+ handler,
12
+ runtime,
13
+ timeout,
14
+ memorySize,
15
+ environment: {
16
+ NODE_ENV: 'production',
17
+ ...environment,
18
+ },
19
+ logGroup: new LogGroup(scope, `${id}LogGroup`, {
20
+ retention: RetentionDays.ONE_WEEK,
21
+ removalPolicy: RemovalPolicy.DESTROY,
22
+ }),
23
+ ...rest,
24
+ });
25
+ return lambdaFunction;
26
+ };
27
+ export const createFunctionUrl = (scope, id, props) => new FunctionUrl(scope, id, props);
package/package.json CHANGED
@@ -1,13 +1,14 @@
1
1
  {
2
2
  "name": "@vyriy/stack",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "AWS CDK stack helpers for Vyriy infrastructure",
5
5
  "type": "module",
6
6
  "main": "./index.js",
7
7
  "dependencies": {
8
- "aws-cdk-lib": "^2.253.1",
8
+ "aws-cdk-lib": "^2.254.0",
9
9
  "constructs": "^10.6.0"
10
10
  },
11
+ "agents": "./AGENTS.md",
11
12
  "license": "MIT",
12
13
  "repository": {
13
14
  "type": "git",
@@ -21,6 +22,16 @@
21
22
  "import": "./index.js",
22
23
  "default": "./index.js"
23
24
  },
25
+ "./apigateway/index": {
26
+ "types": "./apigateway/index.d.ts",
27
+ "import": "./apigateway/index.js",
28
+ "default": "./apigateway/index.js"
29
+ },
30
+ "./apigateway/index.js": {
31
+ "types": "./apigateway/index.d.ts",
32
+ "import": "./apigateway/index.js",
33
+ "default": "./apigateway/index.js"
34
+ },
24
35
  "./certificatemanager/index": {
25
36
  "types": "./certificatemanager/index.d.ts",
26
37
  "import": "./certificatemanager/index.js",
@@ -51,6 +62,46 @@
51
62
  "import": "./deployment/index.js",
52
63
  "default": "./deployment/index.js"
53
64
  },
65
+ "./dynamodb/index": {
66
+ "types": "./dynamodb/index.d.ts",
67
+ "import": "./dynamodb/index.js",
68
+ "default": "./dynamodb/index.js"
69
+ },
70
+ "./dynamodb/index.js": {
71
+ "types": "./dynamodb/index.d.ts",
72
+ "import": "./dynamodb/index.js",
73
+ "default": "./dynamodb/index.js"
74
+ },
75
+ "./ec2/index": {
76
+ "types": "./ec2/index.d.ts",
77
+ "import": "./ec2/index.js",
78
+ "default": "./ec2/index.js"
79
+ },
80
+ "./ec2/index.js": {
81
+ "types": "./ec2/index.d.ts",
82
+ "import": "./ec2/index.js",
83
+ "default": "./ec2/index.js"
84
+ },
85
+ "./ecr/index": {
86
+ "types": "./ecr/index.d.ts",
87
+ "import": "./ecr/index.js",
88
+ "default": "./ecr/index.js"
89
+ },
90
+ "./ecr/index.js": {
91
+ "types": "./ecr/index.d.ts",
92
+ "import": "./ecr/index.js",
93
+ "default": "./ecr/index.js"
94
+ },
95
+ "./ecs/index": {
96
+ "types": "./ecs/index.d.ts",
97
+ "import": "./ecs/index.js",
98
+ "default": "./ecs/index.js"
99
+ },
100
+ "./ecs/index.js": {
101
+ "types": "./ecs/index.d.ts",
102
+ "import": "./ecs/index.js",
103
+ "default": "./ecs/index.js"
104
+ },
54
105
  "./index": {
55
106
  "types": "./index.d.ts",
56
107
  "import": "./index.js",
@@ -61,6 +112,16 @@
61
112
  "import": "./index.js",
62
113
  "default": "./index.js"
63
114
  },
115
+ "./lambda/index": {
116
+ "types": "./lambda/index.d.ts",
117
+ "import": "./lambda/index.js",
118
+ "default": "./lambda/index.js"
119
+ },
120
+ "./lambda/index.js": {
121
+ "types": "./lambda/index.d.ts",
122
+ "import": "./lambda/index.js",
123
+ "default": "./lambda/index.js"
124
+ },
64
125
  "./route53/index": {
65
126
  "types": "./route53/index.d.ts",
66
127
  "import": "./route53/index.js",
@@ -80,6 +141,36 @@
80
141
  "types": "./s3/index.d.ts",
81
142
  "import": "./s3/index.js",
82
143
  "default": "./s3/index.js"
144
+ },
145
+ "./sns/index": {
146
+ "types": "./sns/index.d.ts",
147
+ "import": "./sns/index.js",
148
+ "default": "./sns/index.js"
149
+ },
150
+ "./sns/index.js": {
151
+ "types": "./sns/index.d.ts",
152
+ "import": "./sns/index.js",
153
+ "default": "./sns/index.js"
154
+ },
155
+ "./sqs/index": {
156
+ "types": "./sqs/index.d.ts",
157
+ "import": "./sqs/index.js",
158
+ "default": "./sqs/index.js"
159
+ },
160
+ "./sqs/index.js": {
161
+ "types": "./sqs/index.d.ts",
162
+ "import": "./sqs/index.js",
163
+ "default": "./sqs/index.js"
164
+ },
165
+ "./ssm/index": {
166
+ "types": "./ssm/index.d.ts",
167
+ "import": "./ssm/index.js",
168
+ "default": "./ssm/index.js"
169
+ },
170
+ "./ssm/index.js": {
171
+ "types": "./ssm/index.d.ts",
172
+ "import": "./ssm/index.js",
173
+ "default": "./ssm/index.js"
83
174
  }
84
175
  }
85
176
  }
package/sns/index.d.ts ADDED
@@ -0,0 +1,5 @@
1
+ import { Construct } from 'constructs';
2
+ import { Topic, TopicProps, TopicAttributes } from 'aws-cdk-lib/aws-sns';
3
+ export declare const createTopic: (scope: Construct, id: string, props?: TopicProps) => Topic;
4
+ export declare const fromTopicArn: (scope: Construct, id: string, topicArn: string) => import("aws-cdk-lib/aws-sns").ITopic;
5
+ export declare const fromTopicAttributes: (scope: Construct, id: string, attrs: TopicAttributes) => import("aws-cdk-lib/aws-sns").ITopic;
package/sns/index.js ADDED
@@ -0,0 +1,4 @@
1
+ import { Topic } from 'aws-cdk-lib/aws-sns';
2
+ export const createTopic = (scope, id, props = {}) => new Topic(scope, id, props);
3
+ export const fromTopicArn = (scope, id, topicArn) => Topic.fromTopicArn(scope, id, topicArn);
4
+ export const fromTopicAttributes = (scope, id, attrs) => Topic.fromTopicAttributes(scope, id, attrs);
package/sqs/index.d.ts ADDED
@@ -0,0 +1,8 @@
1
+ import { Construct } from 'constructs';
2
+ import { Queue, QueueProps } from 'aws-cdk-lib/aws-sqs';
3
+ export declare const createQueue: (scope: Construct, id: string, props?: QueueProps) => Queue;
4
+ export declare const fromQueueArn: (scope: Construct, id: string, queueArn: string) => import("aws-cdk-lib/aws-sqs").IQueue;
5
+ export declare const fromQueueAttributes: (scope: Construct, id: string, attrs: {
6
+ queueArn: string;
7
+ queueUrl: string;
8
+ }) => import("aws-cdk-lib/aws-sqs").IQueue;
package/sqs/index.js ADDED
@@ -0,0 +1,4 @@
1
+ import { Queue } from 'aws-cdk-lib/aws-sqs';
2
+ export const createQueue = (scope, id, props = {}) => new Queue(scope, id, props);
3
+ export const fromQueueArn = (scope, id, queueArn) => Queue.fromQueueArn(scope, id, queueArn);
4
+ export const fromQueueAttributes = (scope, id, attrs) => Queue.fromQueueAttributes(scope, id, attrs);
package/ssm/index.d.ts ADDED
@@ -0,0 +1,7 @@
1
+ import { Construct } from 'constructs';
2
+ import { ParameterValueType, SecureStringParameterAttributes, StringParameterAttributes } from 'aws-cdk-lib/aws-ssm';
3
+ export type { ParameterValueType };
4
+ export declare const fromStringParameterName: (scope: Construct, id: string, stringParameterName: string) => import("aws-cdk-lib/aws-ssm").IStringParameter;
5
+ export declare const fromStringParameterAttributes: (scope: Construct, id: string, attrs: StringParameterAttributes) => import("aws-cdk-lib/aws-ssm").IStringParameter;
6
+ export declare const fromSecureStringParameterAttributes: (scope: Construct, id: string, attrs: SecureStringParameterAttributes) => import("aws-cdk-lib/aws-ssm").IStringParameter;
7
+ export declare const valueForStringParameter: (scope: Construct, stringParameterName: string) => string;
package/ssm/index.js ADDED
@@ -0,0 +1,5 @@
1
+ import { StringParameter, } from 'aws-cdk-lib/aws-ssm';
2
+ export const fromStringParameterName = (scope, id, stringParameterName) => StringParameter.fromStringParameterName(scope, id, stringParameterName);
3
+ export const fromStringParameterAttributes = (scope, id, attrs) => StringParameter.fromStringParameterAttributes(scope, id, attrs);
4
+ export const fromSecureStringParameterAttributes = (scope, id, attrs) => StringParameter.fromSecureStringParameterAttributes(scope, id, attrs);
5
+ export const valueForStringParameter = (scope, stringParameterName) => StringParameter.valueForStringParameter(scope, stringParameterName);