@aws/nx-plugin 1.0.0-rc.33 → 1.0.0-rc.35

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 (114) hide show
  1. package/LICENSE-THIRD-PARTY +28 -41
  2. package/generators.json +27 -0
  3. package/package.json +6 -6
  4. package/src/connection/generator.js +12 -1
  5. package/src/connection/generator.js.map +1 -1
  6. package/src/connection/supported-connections.d.ts +10 -1
  7. package/src/connection/supported-connections.js +13 -0
  8. package/src/connection/supported-connections.js.map +1 -1
  9. package/src/infra/app/__snapshots__/generator.spec.ts.snap +6 -6
  10. package/src/open-api/ts-client/__snapshots__/generator.complex-types.spec.ts.snap +12 -12
  11. package/src/open-api/ts-client/__snapshots__/generator.composite-types.spec.ts.snap +74 -10
  12. package/src/open-api/ts-client/__snapshots__/generator.content-type.spec.ts.snap +22 -4
  13. package/src/open-api/ts-client/__snapshots__/generator.duplicate-types.spec.ts.snap +53 -8
  14. package/src/open-api/ts-client/__snapshots__/generator.edge-cases.spec.ts.snap +32 -4
  15. package/src/open-api/ts-client/__snapshots__/generator.fast-api-gaps.spec.ts.snap +736 -0
  16. package/src/open-api/ts-client/__snapshots__/generator.fast-api.spec.ts.snap +86 -11
  17. package/src/open-api/ts-client/__snapshots__/generator.multipart.spec.ts.snap +21 -3
  18. package/src/open-api/ts-client/__snapshots__/generator.primitive-types.spec.ts.snap +2 -2
  19. package/src/open-api/ts-client/__snapshots__/generator.request.spec.ts.snap +6 -6
  20. package/src/open-api/ts-client/__snapshots__/generator.reserved-keywords.spec.ts.snap +2 -2
  21. package/src/open-api/ts-client/__snapshots__/generator.spec-compliance.spec.ts.snap +1883 -0
  22. package/src/open-api/ts-client/__snapshots__/generator.tags.spec.ts.snap +4 -4
  23. package/src/open-api/ts-client/files/client.gen.ts.template +195 -12
  24. package/src/open-api/ts-client/files/types.gen.ts.template +2 -0
  25. package/src/open-api/ts-client/generator.js +22 -1
  26. package/src/open-api/ts-client/generator.js.map +1 -1
  27. package/src/open-api/utils/codegen-data/languages.js +6 -0
  28. package/src/open-api/utils/codegen-data/languages.js.map +1 -1
  29. package/src/open-api/utils/codegen-data/types.d.ts +16 -1
  30. package/src/open-api/utils/codegen-data/types.js.map +1 -1
  31. package/src/open-api/utils/codegen-data.js +71 -0
  32. package/src/open-api/utils/codegen-data.js.map +1 -1
  33. package/src/open-api/utils/normalise.js +53 -8
  34. package/src/open-api/utils/normalise.js.map +1 -1
  35. package/src/open-api/utils/parser.js +48 -15
  36. package/src/open-api/utils/parser.js.map +1 -1
  37. package/src/preset/__snapshots__/generator.spec.ts.snap +4 -2
  38. package/src/py/agent/__snapshots__/generator.frameworks.spec.ts.snap +1 -1
  39. package/src/py/fast-api/__snapshots__/generator.terraform.spec.ts.snap +186 -18
  40. package/src/py/rdb/__snapshots__/generator.spec.ts.snap +2038 -0
  41. package/src/py/rdb/agent-connection/__snapshots__/generator.spec.ts.snap +104 -0
  42. package/src/py/rdb/agent-connection/generator.d.ts +10 -0
  43. package/src/py/rdb/agent-connection/generator.js +46 -0
  44. package/src/py/rdb/agent-connection/generator.js.map +1 -0
  45. package/src/py/rdb/agent-connection/schema.d.js +8 -0
  46. package/src/py/rdb/agent-connection/schema.d.js.map +1 -0
  47. package/src/py/rdb/agent-connection/schema.d.ts +15 -0
  48. package/src/py/rdb/agent-connection/schema.json +27 -0
  49. package/src/py/rdb/fast-api-connection/__snapshots__/generator.spec.ts.snap +44 -0
  50. package/src/py/rdb/fast-api-connection/files/__apiModuleName__/dependencies/__rdbNameSnake__.py.template +14 -0
  51. package/src/py/rdb/fast-api-connection/generator.d.ts +10 -0
  52. package/src/py/rdb/fast-api-connection/generator.js +54 -0
  53. package/src/py/rdb/fast-api-connection/generator.js.map +1 -0
  54. package/src/py/rdb/fast-api-connection/schema.d.js +8 -0
  55. package/src/py/rdb/fast-api-connection/schema.d.js.map +1 -0
  56. package/src/py/rdb/fast-api-connection/schema.d.ts +13 -0
  57. package/src/py/rdb/fast-api-connection/schema.json +23 -0
  58. package/src/py/rdb/files/Dockerfile.create-db-user.template +10 -0
  59. package/src/py/rdb/files/Dockerfile.migration.template +10 -0
  60. package/src/py/rdb/files/__name__/__init__.py.template +3 -0
  61. package/src/py/rdb/files/__name__/connection.py.template +55 -0
  62. package/src/py/rdb/files/__name__/create_db_user_handler.py.template +97 -0
  63. package/src/py/rdb/files/__name__/migration_handler.py.template +36 -0
  64. package/src/py/rdb/files/__name__/models/__init__.py.template +3 -0
  65. package/src/py/rdb/files/__name__/models/example.py.template +8 -0
  66. package/src/py/rdb/files/__name__/utils.py.template +104 -0
  67. package/src/py/rdb/files/alembic.ini.template +38 -0
  68. package/src/py/rdb/files/config.json.template +14 -0
  69. package/src/py/rdb/files/migrations/env.py.template +80 -0
  70. package/src/py/rdb/files/migrations/script.py.mako.template +28 -0
  71. package/src/py/rdb/generator.d.ts +6 -0
  72. package/src/py/rdb/generator.js +263 -0
  73. package/src/py/rdb/generator.js.map +1 -0
  74. package/src/py/rdb/mcp-server-connection/__snapshots__/generator.spec.ts.snap +101 -0
  75. package/src/py/rdb/mcp-server-connection/generator.d.ts +10 -0
  76. package/src/py/rdb/mcp-server-connection/generator.js +46 -0
  77. package/src/py/rdb/mcp-server-connection/generator.js.map +1 -0
  78. package/src/py/rdb/mcp-server-connection/schema.d.js +8 -0
  79. package/src/py/rdb/mcp-server-connection/schema.d.js.map +1 -0
  80. package/src/py/rdb/mcp-server-connection/schema.d.ts +15 -0
  81. package/src/py/rdb/mcp-server-connection/schema.json +27 -0
  82. package/src/py/rdb/schema.d.js +6 -0
  83. package/src/py/rdb/schema.d.js.map +1 -0
  84. package/src/py/rdb/schema.d.ts +16 -0
  85. package/src/py/rdb/schema.json +77 -0
  86. package/src/py/rdb/utils.d.ts +6 -0
  87. package/src/py/rdb/utils.js +16 -0
  88. package/src/py/rdb/utils.js.map +1 -0
  89. package/src/sdk/py.d.ts +2 -0
  90. package/src/sdk/py.js +1 -0
  91. package/src/sdk/py.js.map +1 -1
  92. package/src/smithy/ts/api/__snapshots__/generator.spec.ts.snap +124 -12
  93. package/src/trpc/backend/__snapshots__/generator.spec.ts.snap +186 -18
  94. package/src/ts/rdb/__snapshots__/generator.spec.ts.snap +145 -173
  95. package/src/ts/rdb/generator.js +4 -3
  96. package/src/ts/rdb/generator.js.map +1 -1
  97. package/src/ts/rdb/schema.json +1 -1
  98. package/src/ts/react-website/app/__snapshots__/generator.spec.ts.snap +16 -16
  99. package/src/utils/api-constructs/files/terraform/app/apis/http/__apiNameKebabCase__/__apiNameKebabCase__.tf.template +31 -3
  100. package/src/utils/api-constructs/files/terraform/app/apis/rest/__apiNameKebabCase__/__apiNameKebabCase__.tf.template +31 -3
  101. package/src/utils/rdb-constructs/files/cdk/app/dbs/__nameKebabCase__.ts.template +58 -14
  102. package/src/utils/rdb-constructs/files/cdk/core/rdb/aurora.ts.template +68 -78
  103. package/src/utils/rdb-constructs/files/terraform/app/dbs/__nameKebabCase__/__nameKebabCase__.tf.template +88 -8
  104. package/src/utils/rdb-constructs/files/terraform/core/rdb/aurora/aurora.tf.template +5 -32
  105. package/src/utils/rdb-constructs/rdb-constructs.d.ts +11 -1
  106. package/src/utils/rdb-constructs/rdb-constructs.js.map +1 -1
  107. package/src/utils/shared-constructs.js +9 -21
  108. package/src/utils/shared-constructs.js.map +1 -1
  109. package/src/utils/shared-rdb-scripts.js +5 -1
  110. package/src/utils/shared-rdb-scripts.js.map +1 -1
  111. package/src/utils/versions.d.ts +34 -30
  112. package/src/utils/versions.js +34 -30
  113. package/src/utils/versions.js.map +1 -1
  114. package/src/utils/files/terraform/scripts/reset-runtime-config.ts.template +0 -25
@@ -0,0 +1,8 @@
1
+ from sqlalchemy import Column, String
2
+ from sqlmodel import Field, SQLModel
3
+
4
+
5
+ class ExampleModel(SQLModel, table=True):
6
+ id: int | None = Field(default=None, primary_key=True)
7
+ name: str = Field(sa_column=Column(String(255), nullable=False))
8
+ description: str | None = Field(default=None, sa_column=Column(String(255), nullable=True))
@@ -0,0 +1,104 @@
1
+ import json
2
+ import os
3
+ import time
4
+ from collections.abc import Callable
5
+ from typing import Any
6
+
7
+ import boto3
8
+ from aws_lambda_powertools.utilities.parameters import AppConfigProvider
9
+ from sqlalchemy import URL
10
+
11
+ DatabaseConfig = dict[str, Any]
12
+ DatabaseSecret = dict[str, Any]
13
+
14
+ def build_database_url(
15
+ username: str,
16
+ host: str,
17
+ port: int,
18
+ database: str,
19
+ password: str | None = None,
20
+ ) -> URL:
21
+ return URL.create(
22
+ drivername='<%= engine === "mysql" ? "mysql+aiomysql" : "postgresql+asyncpg" %>',
23
+ username=username,
24
+ password=password,
25
+ host=host,
26
+ port=port,
27
+ database=database,
28
+ )
29
+
30
+
31
+ def is_local_dev() -> bool:
32
+ return os.environ.get('LOCAL_DEV') == 'true'
33
+
34
+
35
+ def get_local_dev_config() -> dict:
36
+ config_path = os.path.join(os.path.dirname(__file__), '..', 'config.json')
37
+ with open(config_path) as f:
38
+ return json.load(f)['localDev']
39
+
40
+
41
+ def get_database_secret() -> DatabaseSecret:
42
+ secret_arn = os.environ.get('DATABASE_SECRET_ARN')
43
+ if not secret_arn:
44
+ raise ValueError('Missing required environment variable DATABASE_SECRET_ARN.')
45
+ client = boto3.client('secretsmanager')
46
+ response = client.get_secret_value(SecretId=secret_arn)
47
+ return json.loads(response['SecretString'])
48
+
49
+
50
+ _database_config: dict[str, DatabaseConfig] = {}
51
+
52
+
53
+ def get_database_config(runtime_config_key: str) -> DatabaseConfig:
54
+ if runtime_config_key not in _database_config:
55
+ app_id = os.environ.get('RUNTIME_CONFIG_APP_ID')
56
+ if not app_id:
57
+ raise ValueError('Missing required environment variable RUNTIME_CONFIG_APP_ID.')
58
+ provider = AppConfigProvider(application=app_id, environment='default')
59
+ config = provider.get('database', transform='json')
60
+ if not isinstance(config, dict):
61
+ raise ValueError('Unexpected RuntimeConfig format: expected JSON object.')
62
+ db_config = config.get(runtime_config_key)
63
+ if not db_config:
64
+ raise ValueError(f'RuntimeConfig is missing database.{runtime_config_key}.')
65
+ _database_config[runtime_config_key] = db_config
66
+ return _database_config[runtime_config_key]
67
+
68
+
69
+ _TRANSIENT_ERROR_PATTERNS = [
70
+ 'timeout',
71
+ 'connection refused',
72
+ 'could not connect',
73
+ 'connection reset',
74
+ 'connection timed out',
75
+ 'operationalerror',
76
+ 'password authentication failed',
77
+ 'access denied',
78
+ 'temporary failure',
79
+ ]
80
+
81
+
82
+ def is_transient_connection_error(error: Exception) -> bool:
83
+ error_str = str(error).lower()
84
+ return any(p in error_str for p in _TRANSIENT_ERROR_PATTERNS)
85
+
86
+
87
+ def with_connection_retry[T](
88
+ fn: Callable[[], T],
89
+ max_attempts: int = 6,
90
+ delay_seconds: float = 10.0,
91
+ ) -> T:
92
+ for attempt in range(1, max_attempts + 1):
93
+ try:
94
+ return fn()
95
+ except Exception as e:
96
+ if attempt == max_attempts or not is_transient_connection_error(e):
97
+ raise
98
+ wait = delay_seconds * attempt
99
+ print(
100
+ f'Transient connection error (attempt {attempt}/{max_attempts}), '
101
+ f'retrying in {wait:.0f}s: {e}'
102
+ )
103
+ time.sleep(wait)
104
+ raise RuntimeError('unreachable')
@@ -0,0 +1,38 @@
1
+ [alembic]
2
+ script_location = migrations
3
+ file_template = %%(year)d%%(month).2d%%(day).2d_%%(hour).2d%%(minute).2d_%%(rev)s_%%(slug)s
4
+ prepend_sys_path = .
5
+
6
+ [loggers]
7
+ keys = root,sqlalchemy,alembic
8
+
9
+ [handlers]
10
+ keys = console
11
+
12
+ [formatters]
13
+ keys = generic
14
+
15
+ [logger_root]
16
+ level = WARN
17
+ handlers = console
18
+ qualname =
19
+
20
+ [logger_sqlalchemy]
21
+ level = WARN
22
+ handlers =
23
+ qualname = sqlalchemy.engine
24
+
25
+ [logger_alembic]
26
+ level = INFO
27
+ handlers =
28
+ qualname = alembic
29
+
30
+ [handler_console]
31
+ class = StreamHandler
32
+ args = (sys.stderr,)
33
+ level = NOTSET
34
+ formatter = generic
35
+
36
+ [formatter_generic]
37
+ format = %(levelname)-5.5s [%(name)s] %(message)s
38
+ datefmt = %H:%M:%S
@@ -0,0 +1,14 @@
1
+ {
2
+ "runtimeConfigKey": "<%= runtimeConfigKey %>",
3
+ "localDev": {
4
+ "containerEngine": "<%= containerEngine %>",
5
+ "containerName": "<%= containerName %>",
6
+ "image": "<%= dockerImage %>",
7
+ "port": <%= localDbPort %>,
8
+ "host": "<%= localDbHost %>",
9
+ "dbName": "<%= localDbName %>",
10
+ "dbUser": "<%= localDbUser %>",
11
+ "dbPassword": "<%= localDbPassword %>",
12
+ "dbEngine": "<%= engine %>"
13
+ }
14
+ }
@@ -0,0 +1,80 @@
1
+ import asyncio
2
+ import json
3
+ import os
4
+ from logging.config import fileConfig
5
+
6
+ from alembic import context
7
+ from sqlalchemy import URL
8
+ from sqlalchemy.ext.asyncio import create_async_engine
9
+ from sqlmodel import SQLModel
10
+
11
+ # Import all models to register them in SQLModel.metadata
12
+ from <%= name %>.models import * # noqa: F401, F403
13
+
14
+ config = context.config
15
+
16
+ if config.config_file_name is not None:
17
+ fileConfig(config.config_file_name)
18
+
19
+ target_metadata = SQLModel.metadata
20
+
21
+
22
+ def _get_local_url():
23
+ if os.environ.get('LOCAL_DEV') == 'true':
24
+ config_path = os.path.join(os.path.dirname(__file__), '..', 'config.json')
25
+ with open(config_path) as f:
26
+ cfg = json.load(f)['localDev']
27
+ engine = cfg['dbEngine']
28
+ driver = 'mysql+aiomysql' if engine == 'mysql' else 'postgresql+asyncpg'
29
+ return URL.create(
30
+ driver,
31
+ username=cfg['dbUser'],
32
+ password=cfg['dbPassword'],
33
+ host=cfg['host'],
34
+ port=cfg['port'],
35
+ database=cfg['dbName'],
36
+ )
37
+
38
+ raise RuntimeError('Run alembic via nx run <project>:alembic')
39
+
40
+
41
+ # Generates SQL script without a live DB connection (alembic upgrade head --sql)
42
+ def run_migrations_offline() -> None:
43
+ context.configure(
44
+ url=_get_local_url(),
45
+ target_metadata=target_metadata,
46
+ literal_binds=True,
47
+ dialect_opts={'paramstyle': 'named'},
48
+ )
49
+ with context.begin_transaction():
50
+ context.run_migrations()
51
+
52
+
53
+ def _run_migrations_sync(sync_conn) -> None:
54
+ context.configure(connection=sync_conn, target_metadata=target_metadata)
55
+ with context.begin_transaction():
56
+ context.run_migrations()
57
+
58
+
59
+ # Runs migrations against a live DB connection
60
+ def run_migrations_online() -> None:
61
+ supplied_connection = config.attributes.get('connection')
62
+ # Connection injected by migration_handler.py (Lambda)
63
+ if supplied_connection is not None:
64
+ _run_migrations_sync(supplied_connection)
65
+ return
66
+
67
+ # Local alembic commands run via nx run <project>:alembic
68
+ async def _run_async() -> None:
69
+ engine = create_async_engine(_get_local_url())
70
+ async with engine.begin() as conn:
71
+ await conn.run_sync(_run_migrations_sync)
72
+ await engine.dispose()
73
+
74
+ asyncio.run(_run_async())
75
+
76
+
77
+ if context.is_offline_mode():
78
+ run_migrations_offline()
79
+ else:
80
+ run_migrations_online()
@@ -0,0 +1,28 @@
1
+ """${message}
2
+
3
+ Revision ID: ${up_revision}
4
+ Revises: ${down_revision | comma,n}
5
+ Create Date: ${create_date}
6
+
7
+ """
8
+ from typing import Sequence, Union
9
+
10
+ from alembic import op
11
+ import sqlalchemy as sa
12
+ ${imports if imports else ""}
13
+
14
+ # revision identifiers, used by Alembic.
15
+ revision: str = ${repr(up_revision)}
16
+ down_revision: Union[str, Sequence[str], None] = ${repr(down_revision)}
17
+ branch_labels: Union[str, Sequence[str], None] = ${repr(branch_labels)}
18
+ depends_on: Union[str, Sequence[str], None] = ${repr(depends_on)}
19
+
20
+
21
+ def upgrade() -> None:
22
+ """Upgrade schema."""
23
+ ${upgrades if upgrades else "pass"}
24
+
25
+
26
+ def downgrade() -> None:
27
+ """Downgrade schema."""
28
+ ${downgrades if downgrades else "pass"}
@@ -0,0 +1,6 @@
1
+ import { type GeneratorCallback, type Tree } from '@nx/devkit';
2
+ import { type NxGeneratorInfo } from '../../utils/nx';
3
+ import type { PyRdbGeneratorSchema } from './schema';
4
+ export declare const PY_RDB_GENERATOR_INFO: NxGeneratorInfo;
5
+ export declare const pyRdbGenerator: (tree: Tree, options: PyRdbGeneratorSchema) => Promise<GeneratorCallback>;
6
+ export default pyRdbGenerator;
@@ -0,0 +1,263 @@
1
+ /**
2
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */ import { relative } from "node:path";
5
+ import { addDependenciesToPackageJson, generateFiles, joinPathFragments, readProjectConfiguration, updateProjectConfiguration } from "@nx/devkit";
6
+ import { addPythonBundleTarget } from "../../utils/bundle/bundle.js";
7
+ import { resolveContainers } from "../../utils/containers.js";
8
+ import { formatFilesInSubtree } from "../../utils/format.js";
9
+ import { FsCommands } from "../../utils/fs.js";
10
+ import { resolveIac } from "../../utils/iac.js";
11
+ import { installDependencies } from "../../utils/install.js";
12
+ import { addGeneratorMetricsIfApplicable } from "../../utils/metrics.js";
13
+ import { kebabCase, snakeCase, toClassName } from "../../utils/names.js";
14
+ import { getNpmScope } from "../../utils/npm-scope.js";
15
+ import { addDependencyToTargetIfNotPresent, addGeneratorMetadata, getGeneratorInfo, projectExists } from "../../utils/nx.js";
16
+ import { assignPort } from "../../utils/port.js";
17
+ import { addDependenciesToPyProjectToml } from "../../utils/py.js";
18
+ import { addRdbInfra } from "../../utils/rdb-constructs/rdb-constructs.js";
19
+ import { sharedConstructsGenerator } from "../../utils/shared-constructs.js";
20
+ import { PACKAGES_DIR, SHARED_SCRIPTS_DIR } from "../../utils/shared-constructs-constants.js";
21
+ import { sharedRdbScriptsGenerator } from "../../utils/shared-rdb-scripts.js";
22
+ import { PY_VERSIONS, withVersions } from "../../utils/versions.js";
23
+ import pyProjectGenerator, { getPyProjectDetails } from "../project/generator.js";
24
+ export const PY_RDB_GENERATOR_INFO = getGeneratorInfo(import.meta.filename);
25
+ export const pyRdbGenerator = async (tree, options)=>{
26
+ const nameClassName = toClassName(options.name);
27
+ const databaseUser = options.databaseUser ?? 'dbadmin';
28
+ const databaseName = snakeCase(options.databaseName ?? options.name);
29
+ const containerEngine = await resolveContainers(tree, 'inherit');
30
+ const { fullyQualifiedName, dir, normalizedModuleName } = getPyProjectDetails(tree, {
31
+ name: options.name,
32
+ directory: options.directory,
33
+ subDirectory: options.subDirectory
34
+ });
35
+ if (!projectExists(tree, fullyQualifiedName)) {
36
+ await pyProjectGenerator(tree, {
37
+ name: options.name,
38
+ directory: options.directory,
39
+ subDirectory: options.subDirectory,
40
+ type: 'library'
41
+ });
42
+ }
43
+ const projectConfig = readProjectConfiguration(tree, fullyQualifiedName);
44
+ const { engine } = options;
45
+ const localDbPort = assignPort(tree, projectConfig, engine === 'mysql' ? 3306 : 5432);
46
+ const localDbHost = 'localhost';
47
+ const localDbUser = engine === 'mysql' ? 'root' : 'dbadmin';
48
+ const localDbPassword = 'password';
49
+ const containerName = `${getNpmScope(tree)}-${databaseName}`;
50
+ const dockerImage = engine === 'mysql' ? 'public.ecr.aws/docker/library/mysql:8.0.44' : 'public.ecr.aws/docker/library/postgres:17.7';
51
+ const templateOptions = {
52
+ name: normalizedModuleName,
53
+ runtimeConfigKey: nameClassName,
54
+ engine,
55
+ localDbPort,
56
+ localDbHost,
57
+ localDbName: databaseName,
58
+ localDbUser,
59
+ localDbPassword,
60
+ containerEngine,
61
+ containerName,
62
+ dockerImage,
63
+ sqlmodelVersion: PY_VERSIONS.sqlmodel,
64
+ alembicVersion: PY_VERSIONS.alembic,
65
+ aiomysqlVersion: PY_VERSIONS.aiomysql,
66
+ asyncpgVersion: PY_VERSIONS.asyncpg,
67
+ boto3Version: PY_VERSIONS.boto3,
68
+ awsLambdaPowertoolsVersion: PY_VERSIONS['aws-lambda-powertools']
69
+ };
70
+ generateFiles(tree, joinPathFragments(import.meta.dirname, 'files'), dir, templateOptions);
71
+ await sharedRdbScriptsGenerator(tree, engine);
72
+ // Used by local dev script wait-for-*-db.ts
73
+ addDependenciesToPackageJson(tree, withVersions([
74
+ engine === 'mysql' ? 'mariadb' : 'pg'
75
+ ]), engine === 'mysql' ? {} : withVersions([
76
+ '@types/pg'
77
+ ]));
78
+ const scriptsDir = relative(dir, joinPathFragments(PACKAGES_DIR, SHARED_SCRIPTS_DIR, 'src', 'rdb'));
79
+ const fs = new FsCommands(tree);
80
+ const migrationBundleDir = joinPathFragments('dist', projectConfig.root, 'docker', 'migration');
81
+ const createDbUserBundleDir = joinPathFragments('dist', projectConfig.root, 'docker', 'create-db-user');
82
+ const migrationDockerImageTag = `${getNpmScope(tree)}-${kebabCase(options.name)}-migration:latest`;
83
+ const createDbUserDockerImageTag = `${getNpmScope(tree)}-${kebabCase(options.name)}-create-db-user:latest`;
84
+ if (options.infra !== 'none') {
85
+ const { bundleTargetName, bundleOutputDir } = addPythonBundleTarget(projectConfig, {
86
+ pythonPlatform: 'aarch64-manylinux_2_28'
87
+ });
88
+ projectConfig.targets['bundle-migration'] = {
89
+ cache: true,
90
+ outputs: [
91
+ '{workspaceRoot}/dist/{projectRoot}/docker/migration'
92
+ ],
93
+ executor: 'nx:run-commands',
94
+ options: {
95
+ commands: [
96
+ fs.rm(migrationBundleDir),
97
+ fs.mkdir(migrationBundleDir),
98
+ fs.cp(bundleOutputDir, migrationBundleDir),
99
+ fs.cp(joinPathFragments(dir, 'migrations'), joinPathFragments(migrationBundleDir, 'migrations')),
100
+ fs.cp(joinPathFragments(dir, 'alembic.ini'), joinPathFragments(migrationBundleDir, 'alembic.ini')),
101
+ fs.cp(joinPathFragments(dir, 'Dockerfile.migration'), joinPathFragments(migrationBundleDir, 'Dockerfile'))
102
+ ],
103
+ parallel: false
104
+ },
105
+ dependsOn: [
106
+ bundleTargetName
107
+ ]
108
+ };
109
+ projectConfig.targets['bundle-create-db-user'] = {
110
+ cache: true,
111
+ outputs: [
112
+ '{workspaceRoot}/dist/{projectRoot}/docker/create-db-user'
113
+ ],
114
+ executor: 'nx:run-commands',
115
+ options: {
116
+ commands: [
117
+ fs.rm(createDbUserBundleDir),
118
+ fs.mkdir(createDbUserBundleDir),
119
+ fs.cp(bundleOutputDir, createDbUserBundleDir),
120
+ fs.cp(joinPathFragments(dir, 'Dockerfile.create-db-user'), joinPathFragments(createDbUserBundleDir, 'Dockerfile'))
121
+ ],
122
+ parallel: false
123
+ },
124
+ dependsOn: [
125
+ bundleTargetName
126
+ ]
127
+ };
128
+ addDependencyToTargetIfNotPresent(projectConfig, 'bundle', 'bundle-migration');
129
+ addDependencyToTargetIfNotPresent(projectConfig, 'bundle', 'bundle-create-db-user');
130
+ }
131
+ projectConfig.targets['pull-image'] = {
132
+ executor: 'nx:run-commands',
133
+ options: {
134
+ command: `tsx ${scriptsDir}/pull-image.ts`,
135
+ cwd: '{projectRoot}'
136
+ }
137
+ };
138
+ projectConfig.targets['dev'] = {
139
+ executor: 'nx:run-commands',
140
+ continuous: true,
141
+ options: {
142
+ command: `tsx ${scriptsDir}/start-container.ts`,
143
+ cwd: '{projectRoot}'
144
+ },
145
+ dependsOn: [
146
+ 'pull-image'
147
+ ]
148
+ };
149
+ projectConfig.targets['wait-for-db'] = {
150
+ executor: 'nx:run-commands',
151
+ dependsOn: [
152
+ 'dev'
153
+ ],
154
+ options: {
155
+ command: `tsx ${scriptsDir}/wait-for-${engine}-db.ts`,
156
+ cwd: '{projectRoot}'
157
+ }
158
+ };
159
+ projectConfig.targets.migrate = {
160
+ executor: 'nx:run-commands',
161
+ dependsOn: [
162
+ 'dev',
163
+ 'wait-for-db'
164
+ ],
165
+ options: {
166
+ command: 'uv run alembic upgrade head',
167
+ cwd: '{projectRoot}',
168
+ env: {
169
+ LOCAL_DEV: 'true'
170
+ }
171
+ }
172
+ };
173
+ projectConfig.targets.alembic = {
174
+ executor: 'nx:run-commands',
175
+ dependsOn: [
176
+ 'dev',
177
+ 'wait-for-db'
178
+ ],
179
+ options: {
180
+ command: 'uv run alembic',
181
+ cwd: '{projectRoot}',
182
+ env: {
183
+ LOCAL_DEV: 'true'
184
+ }
185
+ }
186
+ };
187
+ if (options.infra !== 'none') {
188
+ const iac = await resolveIac(tree, options.iac);
189
+ if (iac === 'terraform') {
190
+ projectConfig.targets.docker = {
191
+ cache: true,
192
+ executor: 'nx:run-commands',
193
+ options: {
194
+ commands: [
195
+ `${containerEngine} build --platform linux/arm64 --provenance=false -t ${migrationDockerImageTag} ${migrationBundleDir}`,
196
+ `${containerEngine} build --platform linux/arm64 --provenance=false -t ${createDbUserDockerImageTag} ${createDbUserBundleDir}`
197
+ ],
198
+ parallel: false
199
+ },
200
+ dependsOn: [
201
+ 'bundle-migration',
202
+ 'bundle-create-db-user'
203
+ ]
204
+ };
205
+ addDependencyToTargetIfNotPresent(projectConfig, 'build', 'docker');
206
+ }
207
+ addDependencyToTargetIfNotPresent(projectConfig, 'build', 'bundle-migration');
208
+ addDependencyToTargetIfNotPresent(projectConfig, 'build', 'bundle-create-db-user');
209
+ }
210
+ updateProjectConfiguration(tree, fullyQualifiedName, projectConfig);
211
+ addGeneratorMetadata(tree, fullyQualifiedName, PY_RDB_GENERATOR_INFO, {
212
+ engine
213
+ });
214
+ if (options.infra !== 'none') {
215
+ const iac = await resolveIac(tree, options.iac);
216
+ await sharedConstructsGenerator(tree, {
217
+ iac
218
+ });
219
+ await addRdbInfra(tree, {
220
+ iac,
221
+ projectName: fullyQualifiedName,
222
+ projectRoot: dir,
223
+ nameClassName,
224
+ nameKebabCase: kebabCase(options.name),
225
+ databasePackageAlias: normalizedModuleName,
226
+ databaseName,
227
+ adminUser: databaseUser,
228
+ engine,
229
+ migrationBundleDir,
230
+ createDbUserBundleDir,
231
+ framework: 'sqlmodel',
232
+ createDbUserDockerImageTag,
233
+ migrationDockerImageTag,
234
+ containerEngine
235
+ });
236
+ }
237
+ addDependenciesToPyProjectToml(tree, dir, [
238
+ 'sqlmodel',
239
+ 'alembic',
240
+ ...engine === 'mysql' ? [
241
+ 'aiomysql',
242
+ 'boto3',
243
+ 'aws-lambda-powertools'
244
+ ] : [
245
+ 'asyncpg',
246
+ 'boto3',
247
+ 'aws-lambda-powertools'
248
+ ]
249
+ ]);
250
+ await addGeneratorMetricsIfApplicable(tree, [
251
+ PY_RDB_GENERATOR_INFO
252
+ ]);
253
+ await formatFilesInSubtree(tree);
254
+ return ()=>installDependencies(tree, options.preferInstallDependencies, {
255
+ languages: [
256
+ 'typescript',
257
+ 'python'
258
+ ]
259
+ });
260
+ };
261
+ export default pyRdbGenerator;
262
+
263
+ //# sourceMappingURL=generator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../packages/nx-plugin/src/py/rdb/generator.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport { relative } from 'node:path';\nimport {\n addDependenciesToPackageJson,\n type GeneratorCallback,\n generateFiles,\n joinPathFragments,\n readProjectConfiguration,\n type Tree,\n updateProjectConfiguration,\n} from '@nx/devkit';\nimport { addPythonBundleTarget } from '../../utils/bundle/bundle';\nimport { resolveContainers } from '../../utils/containers';\nimport { formatFilesInSubtree } from '../../utils/format';\nimport { FsCommands } from '../../utils/fs';\nimport { resolveIac } from '../../utils/iac';\nimport { installDependencies } from '../../utils/install';\nimport { addGeneratorMetricsIfApplicable } from '../../utils/metrics';\nimport { kebabCase, snakeCase, toClassName } from '../../utils/names';\nimport { getNpmScope } from '../../utils/npm-scope';\nimport {\n addDependencyToTargetIfNotPresent,\n addGeneratorMetadata,\n getGeneratorInfo,\n type NxGeneratorInfo,\n projectExists,\n} from '../../utils/nx';\nimport { assignPort } from '../../utils/port';\nimport { addDependenciesToPyProjectToml } from '../../utils/py';\nimport { addRdbInfra } from '../../utils/rdb-constructs/rdb-constructs';\nimport { sharedConstructsGenerator } from '../../utils/shared-constructs';\nimport {\n PACKAGES_DIR,\n SHARED_SCRIPTS_DIR,\n} from '../../utils/shared-constructs-constants';\nimport { sharedRdbScriptsGenerator } from '../../utils/shared-rdb-scripts';\nimport { PY_VERSIONS, withVersions } from '../../utils/versions';\nimport pyProjectGenerator, { getPyProjectDetails } from '../project/generator';\nimport type { PyRdbGeneratorSchema } from './schema';\n\nexport const PY_RDB_GENERATOR_INFO: NxGeneratorInfo = getGeneratorInfo(\n import.meta.filename,\n);\n\nexport const pyRdbGenerator = async (\n tree: Tree,\n options: PyRdbGeneratorSchema,\n): Promise<GeneratorCallback> => {\n const nameClassName = toClassName(options.name);\n const databaseUser = options.databaseUser ?? 'dbadmin';\n const databaseName = snakeCase(options.databaseName ?? options.name);\n const containerEngine = await resolveContainers(tree, 'inherit');\n\n const { fullyQualifiedName, dir, normalizedModuleName } = getPyProjectDetails(\n tree,\n {\n name: options.name,\n directory: options.directory,\n subDirectory: options.subDirectory,\n },\n );\n\n if (!projectExists(tree, fullyQualifiedName)) {\n await pyProjectGenerator(tree, {\n name: options.name,\n directory: options.directory,\n subDirectory: options.subDirectory,\n type: 'library',\n });\n }\n\n const projectConfig = readProjectConfiguration(tree, fullyQualifiedName);\n\n const { engine } = options;\n const localDbPort = assignPort(\n tree,\n projectConfig,\n engine === 'mysql' ? 3306 : 5432,\n );\n const localDbHost = 'localhost';\n const localDbUser = engine === 'mysql' ? 'root' : 'dbadmin';\n const localDbPassword = 'password';\n const containerName = `${getNpmScope(tree)}-${databaseName}`;\n const dockerImage =\n engine === 'mysql'\n ? 'public.ecr.aws/docker/library/mysql:8.0.44'\n : 'public.ecr.aws/docker/library/postgres:17.7';\n\n const templateOptions = {\n name: normalizedModuleName,\n runtimeConfigKey: nameClassName,\n engine,\n localDbPort,\n localDbHost,\n localDbName: databaseName,\n localDbUser,\n localDbPassword,\n containerEngine,\n containerName,\n dockerImage,\n sqlmodelVersion: PY_VERSIONS.sqlmodel,\n alembicVersion: PY_VERSIONS.alembic,\n aiomysqlVersion: PY_VERSIONS.aiomysql,\n asyncpgVersion: PY_VERSIONS.asyncpg,\n boto3Version: PY_VERSIONS.boto3,\n awsLambdaPowertoolsVersion: PY_VERSIONS['aws-lambda-powertools'],\n };\n\n generateFiles(\n tree,\n joinPathFragments(import.meta.dirname, 'files'),\n dir,\n templateOptions,\n );\n\n await sharedRdbScriptsGenerator(tree, engine);\n // Used by local dev script wait-for-*-db.ts\n addDependenciesToPackageJson(\n tree,\n withVersions([engine === 'mysql' ? 'mariadb' : 'pg']),\n engine === 'mysql' ? {} : withVersions(['@types/pg']),\n );\n const scriptsDir = relative(\n dir,\n joinPathFragments(PACKAGES_DIR, SHARED_SCRIPTS_DIR, 'src', 'rdb'),\n );\n const fs = new FsCommands(tree);\n\n const migrationBundleDir = joinPathFragments(\n 'dist',\n projectConfig.root,\n 'docker',\n 'migration',\n );\n const createDbUserBundleDir = joinPathFragments(\n 'dist',\n projectConfig.root,\n 'docker',\n 'create-db-user',\n );\n const migrationDockerImageTag = `${getNpmScope(tree)}-${kebabCase(options.name)}-migration:latest`;\n const createDbUserDockerImageTag = `${getNpmScope(tree)}-${kebabCase(\n options.name,\n )}-create-db-user:latest`;\n\n if (options.infra !== 'none') {\n const { bundleTargetName, bundleOutputDir } = addPythonBundleTarget(\n projectConfig,\n { pythonPlatform: 'aarch64-manylinux_2_28' },\n );\n\n projectConfig.targets['bundle-migration'] = {\n cache: true,\n outputs: ['{workspaceRoot}/dist/{projectRoot}/docker/migration'],\n executor: 'nx:run-commands',\n options: {\n commands: [\n fs.rm(migrationBundleDir),\n fs.mkdir(migrationBundleDir),\n fs.cp(bundleOutputDir, migrationBundleDir),\n fs.cp(\n joinPathFragments(dir, 'migrations'),\n joinPathFragments(migrationBundleDir, 'migrations'),\n ),\n fs.cp(\n joinPathFragments(dir, 'alembic.ini'),\n joinPathFragments(migrationBundleDir, 'alembic.ini'),\n ),\n fs.cp(\n joinPathFragments(dir, 'Dockerfile.migration'),\n joinPathFragments(migrationBundleDir, 'Dockerfile'),\n ),\n ],\n parallel: false,\n },\n dependsOn: [bundleTargetName],\n };\n projectConfig.targets['bundle-create-db-user'] = {\n cache: true,\n outputs: ['{workspaceRoot}/dist/{projectRoot}/docker/create-db-user'],\n executor: 'nx:run-commands',\n options: {\n commands: [\n fs.rm(createDbUserBundleDir),\n fs.mkdir(createDbUserBundleDir),\n fs.cp(bundleOutputDir, createDbUserBundleDir),\n fs.cp(\n joinPathFragments(dir, 'Dockerfile.create-db-user'),\n joinPathFragments(createDbUserBundleDir, 'Dockerfile'),\n ),\n ],\n parallel: false,\n },\n dependsOn: [bundleTargetName],\n };\n addDependencyToTargetIfNotPresent(\n projectConfig,\n 'bundle',\n 'bundle-migration',\n );\n addDependencyToTargetIfNotPresent(\n projectConfig,\n 'bundle',\n 'bundle-create-db-user',\n );\n }\n\n projectConfig.targets['pull-image'] = {\n executor: 'nx:run-commands',\n options: {\n command: `tsx ${scriptsDir}/pull-image.ts`,\n cwd: '{projectRoot}',\n },\n };\n projectConfig.targets['dev'] = {\n executor: 'nx:run-commands',\n continuous: true,\n options: {\n command: `tsx ${scriptsDir}/start-container.ts`,\n cwd: '{projectRoot}',\n },\n dependsOn: ['pull-image'],\n };\n projectConfig.targets['wait-for-db'] = {\n executor: 'nx:run-commands',\n dependsOn: ['dev'],\n options: {\n command: `tsx ${scriptsDir}/wait-for-${engine}-db.ts`,\n cwd: '{projectRoot}',\n },\n };\n projectConfig.targets.migrate = {\n executor: 'nx:run-commands',\n dependsOn: ['dev', 'wait-for-db'],\n options: {\n command: 'uv run alembic upgrade head',\n cwd: '{projectRoot}',\n env: {\n LOCAL_DEV: 'true',\n },\n },\n };\n projectConfig.targets.alembic = {\n executor: 'nx:run-commands',\n dependsOn: ['dev', 'wait-for-db'],\n options: {\n command: 'uv run alembic',\n cwd: '{projectRoot}',\n env: {\n LOCAL_DEV: 'true',\n },\n },\n };\n\n if (options.infra !== 'none') {\n const iac = await resolveIac(tree, options.iac);\n if (iac === 'terraform') {\n projectConfig.targets.docker = {\n cache: true,\n executor: 'nx:run-commands',\n options: {\n commands: [\n `${containerEngine} build --platform linux/arm64 --provenance=false -t ${migrationDockerImageTag} ${migrationBundleDir}`,\n `${containerEngine} build --platform linux/arm64 --provenance=false -t ${createDbUserDockerImageTag} ${createDbUserBundleDir}`,\n ],\n parallel: false,\n },\n dependsOn: ['bundle-migration', 'bundle-create-db-user'],\n };\n addDependencyToTargetIfNotPresent(projectConfig, 'build', 'docker');\n }\n addDependencyToTargetIfNotPresent(\n projectConfig,\n 'build',\n 'bundle-migration',\n );\n addDependencyToTargetIfNotPresent(\n projectConfig,\n 'build',\n 'bundle-create-db-user',\n );\n }\n\n updateProjectConfiguration(tree, fullyQualifiedName, projectConfig);\n addGeneratorMetadata(tree, fullyQualifiedName, PY_RDB_GENERATOR_INFO, {\n engine,\n });\n\n if (options.infra !== 'none') {\n const iac = await resolveIac(tree, options.iac);\n await sharedConstructsGenerator(tree, { iac });\n await addRdbInfra(tree, {\n iac,\n projectName: fullyQualifiedName,\n projectRoot: dir,\n nameClassName,\n nameKebabCase: kebabCase(options.name),\n databasePackageAlias: normalizedModuleName,\n databaseName,\n adminUser: databaseUser,\n engine,\n migrationBundleDir,\n createDbUserBundleDir,\n framework: 'sqlmodel',\n createDbUserDockerImageTag,\n migrationDockerImageTag,\n containerEngine,\n });\n }\n\n addDependenciesToPyProjectToml(tree, dir, [\n 'sqlmodel',\n 'alembic',\n ...(engine === 'mysql'\n ? (['aiomysql', 'boto3', 'aws-lambda-powertools'] as const)\n : (['asyncpg', 'boto3', 'aws-lambda-powertools'] as const)),\n ]);\n\n await addGeneratorMetricsIfApplicable(tree, [PY_RDB_GENERATOR_INFO]);\n\n await formatFilesInSubtree(tree);\n return () =>\n installDependencies(tree, options.preferInstallDependencies, {\n languages: ['typescript', 'python'],\n });\n};\n\nexport default pyRdbGenerator;\n"],"names":["relative","addDependenciesToPackageJson","generateFiles","joinPathFragments","readProjectConfiguration","updateProjectConfiguration","addPythonBundleTarget","resolveContainers","formatFilesInSubtree","FsCommands","resolveIac","installDependencies","addGeneratorMetricsIfApplicable","kebabCase","snakeCase","toClassName","getNpmScope","addDependencyToTargetIfNotPresent","addGeneratorMetadata","getGeneratorInfo","projectExists","assignPort","addDependenciesToPyProjectToml","addRdbInfra","sharedConstructsGenerator","PACKAGES_DIR","SHARED_SCRIPTS_DIR","sharedRdbScriptsGenerator","PY_VERSIONS","withVersions","pyProjectGenerator","getPyProjectDetails","PY_RDB_GENERATOR_INFO","filename","pyRdbGenerator","tree","options","nameClassName","name","databaseUser","databaseName","containerEngine","fullyQualifiedName","dir","normalizedModuleName","directory","subDirectory","type","projectConfig","engine","localDbPort","localDbHost","localDbUser","localDbPassword","containerName","dockerImage","templateOptions","runtimeConfigKey","localDbName","sqlmodelVersion","sqlmodel","alembicVersion","alembic","aiomysqlVersion","aiomysql","asyncpgVersion","asyncpg","boto3Version","boto3","awsLambdaPowertoolsVersion","dirname","scriptsDir","fs","migrationBundleDir","root","createDbUserBundleDir","migrationDockerImageTag","createDbUserDockerImageTag","infra","bundleTargetName","bundleOutputDir","pythonPlatform","targets","cache","outputs","executor","commands","rm","mkdir","cp","parallel","dependsOn","command","cwd","continuous","migrate","env","LOCAL_DEV","iac","docker","projectName","projectRoot","nameKebabCase","databasePackageAlias","adminUser","framework","preferInstallDependencies","languages"],"mappings":"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"}