@aws/nx-plugin 1.1.1 → 1.2.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 (115) hide show
  1. package/README.md +30 -29
  2. package/generators.json +8 -0
  3. package/migrations.json +1 -1
  4. package/package.json +1 -1
  5. package/src/agentcore-harness/generator.d.ts +1 -1
  6. package/src/greengrass/component/common.d.ts +60 -0
  7. package/src/greengrass/component/common.js +191 -0
  8. package/src/greengrass/component/common.js.map +1 -0
  9. package/src/greengrass/component/dependencies.d.ts +101 -0
  10. package/src/greengrass/component/dependencies.js +37 -0
  11. package/src/greengrass/component/dependencies.js.map +1 -0
  12. package/src/greengrass/component/generator.d.ts +174 -0
  13. package/src/greengrass/component/generator.js +32 -0
  14. package/src/greengrass/component/generator.js.map +1 -0
  15. package/src/greengrass/component/metadata.d.ts +2 -0
  16. package/src/greengrass/component/metadata.js +14 -0
  17. package/src/greengrass/component/metadata.js.map +1 -0
  18. package/src/greengrass/component/python/__snapshots__/generator.spec.ts.snap +450 -0
  19. package/src/greengrass/component/python/files/component/main.py.template +60 -0
  20. package/src/greengrass/component/python/files/component/recipe.yaml.template +30 -0
  21. package/src/greengrass/component/python/files/gdk/gdk-config.json.template +13 -0
  22. package/src/greengrass/component/python/files/tests/test___componentSnakeCase__.py.template +37 -0
  23. package/src/greengrass/component/python/generator.d.ts +15 -0
  24. package/src/greengrass/component/python/generator.js +192 -0
  25. package/src/greengrass/component/python/generator.js.map +1 -0
  26. package/src/greengrass/component/schema.d.js +6 -0
  27. package/src/greengrass/component/schema.d.js.map +1 -0
  28. package/src/greengrass/component/schema.d.ts +18 -0
  29. package/src/greengrass/component/schema.json +82 -0
  30. package/src/greengrass/component/typescript/__snapshots__/generator.spec.ts.snap +275 -0
  31. package/src/greengrass/component/typescript/files/component/recipe.yaml.template +41 -0
  32. package/src/greengrass/component/typescript/files/entrypoint/main.ts.template +58 -0
  33. package/src/greengrass/component/typescript/files/gdk/gdk-config.json.template +13 -0
  34. package/src/greengrass/component/typescript/files/scripts/vendor-crt-addon.ts.template +115 -0
  35. package/src/greengrass/component/typescript/generator.d.ts +16 -0
  36. package/src/greengrass/component/typescript/generator.js +194 -0
  37. package/src/greengrass/component/typescript/generator.js.map +1 -0
  38. package/src/infra/app/generator.d.ts +1 -1
  39. package/src/init/generator.d.ts +1 -1
  40. package/src/internal/test-matrix/generator.js +42 -0
  41. package/src/internal/test-matrix/generator.js.map +1 -1
  42. package/src/license/dependency-check/pre-approved.js +2 -1
  43. package/src/license/dependency-check/pre-approved.js.map +1 -1
  44. package/src/open-api/py-client/generator.d.ts +1 -1
  45. package/src/preset/__snapshots__/generator.spec.ts.snap +2 -0
  46. package/src/preset/generator.d.ts +1 -1
  47. package/src/py/agent/a2a-connection/generator.d.ts +1 -1
  48. package/src/py/agent/gateway-connection/generator.d.ts +1 -1
  49. package/src/py/agent/mcp-connection/generator.d.ts +1 -1
  50. package/src/py/agent/react-connection/generator.d.ts +1 -1
  51. package/src/py/fast-api/react/generator.d.ts +1 -1
  52. package/src/py/project/generator.js +2 -0
  53. package/src/py/project/generator.js.map +1 -1
  54. package/src/sdk/greengrass.d.ts +6 -0
  55. package/src/sdk/greengrass.js +6 -0
  56. package/src/sdk/greengrass.js.map +1 -0
  57. package/src/smithy/project/generator.d.ts +1 -1
  58. package/src/smithy/react-connection/generator.d.ts +1 -1
  59. package/src/terraform/project/generator.d.ts +1 -1
  60. package/src/trpc/react/generator.d.ts +1 -1
  61. package/src/ts/agent/a2a-connection/generator.d.ts +1 -1
  62. package/src/ts/agent/gateway-connection/generator.d.ts +1 -1
  63. package/src/ts/agent/mcp-connection/generator.d.ts +1 -1
  64. package/src/ts/agent/react-connection/generator.d.ts +1 -1
  65. package/src/ts/astro-docs/generator.d.ts +1 -1
  66. package/src/ts/dcr-proxy/generator.d.ts +1 -1
  67. package/src/ts/dynamodb/generator.d.ts +1 -1
  68. package/src/ts/lambda-function/generator.d.ts +1 -1
  69. package/src/ts/lib/generator.d.ts +1 -1
  70. package/src/ts/nx-generator/generator.d.ts +1 -1
  71. package/src/ts/nx-migration/generator.d.ts +1 -1
  72. package/src/ts/nx-plugin/generator.d.ts +1 -1
  73. package/src/ts/rdb/generator.d.ts +1 -1
  74. package/src/ts/react-website/agui/generator.d.ts +1 -1
  75. package/src/utils/__snapshots__/shared-greengrass-scripts.spec.ts.snap +1279 -0
  76. package/src/utils/files/common/scripts/src/greengrass/build-artifact.ts.template +236 -0
  77. package/src/utils/files/common/scripts/src/greengrass/component-logs.ts.template +48 -0
  78. package/src/utils/files/common/scripts/src/greengrass/deploy-local.ts.template +497 -0
  79. package/src/utils/files/common/scripts/src/greengrass/recipe-utils.ts.template +356 -0
  80. package/src/utils/files/common/scripts/src/greengrass/zip-writer.ts.template +121 -0
  81. package/src/utils/files/terraform/src/core/runtime-config/read/read.tf.template +3 -3
  82. package/src/utils/files/terraform/src/metrics/metrics.tf.template +1 -1
  83. package/src/utils/greengrass/constants.d.ts +58 -0
  84. package/src/utils/greengrass/constants.js +63 -0
  85. package/src/utils/greengrass/constants.js.map +1 -0
  86. package/src/utils/greengrass/naming.d.ts +46 -0
  87. package/src/utils/greengrass/naming.js +67 -0
  88. package/src/utils/greengrass/naming.js.map +1 -0
  89. package/src/utils/greengrass/recipe.d.ts +143 -0
  90. package/src/utils/greengrass/recipe.js +119 -0
  91. package/src/utils/greengrass/recipe.js.map +1 -0
  92. package/src/utils/greengrass-constructs/files/cdk/app/greengrass-component/__componentDirName__.ts.template +42 -0
  93. package/src/utils/greengrass-constructs/files/cdk/core/greengrass/artifact-bucket.ts.template +82 -0
  94. package/src/utils/greengrass-constructs/files/cdk/core/greengrass/component-version.ts.template +370 -0
  95. package/src/utils/greengrass-constructs/files/cdk/core/greengrass/deployment.ts.template +276 -0
  96. package/src/utils/greengrass-constructs/files/cdk/core/greengrass/index.ts.template +5 -0
  97. package/src/utils/greengrass-constructs/files/cdk/core/greengrass/next-version.ts.template +119 -0
  98. package/src/utils/greengrass-constructs/files/cdk/core/greengrass/recipe.ts.template +90 -0
  99. package/src/utils/greengrass-constructs/files/next-version/__nextVersionFileName__.template +195 -0
  100. package/src/utils/greengrass-constructs/files/terraform/app/greengrass-component/__componentDirName__/__componentDirName__.tf.template +26 -0
  101. package/src/utils/greengrass-constructs/files/terraform/core/greengrass/artifact-bucket/main.tf.template +204 -0
  102. package/src/utils/greengrass-constructs/files/terraform/core/greengrass/component-version/main.tf.template +156 -0
  103. package/src/utils/greengrass-constructs/files/terraform/core/greengrass/deployment/main.tf.template +186 -0
  104. package/src/utils/greengrass-constructs/greengrass-constructs.d.ts +57 -0
  105. package/src/utils/greengrass-constructs/greengrass-constructs.js +154 -0
  106. package/src/utils/greengrass-constructs/greengrass-constructs.js.map +1 -0
  107. package/src/utils/nx.d.ts +15 -0
  108. package/src/utils/nx.js +32 -0
  109. package/src/utils/nx.js.map +1 -1
  110. package/src/utils/shared-greengrass-scripts.d.ts +21 -0
  111. package/src/utils/shared-greengrass-scripts.js +43 -0
  112. package/src/utils/shared-greengrass-scripts.js.map +1 -0
  113. package/src/utils/versions.d.ts +7 -0
  114. package/src/utils/versions.js +7 -0
  115. package/src/utils/versions.js.map +1 -1
@@ -0,0 +1,58 @@
1
+ <%_ if (ipc) { _%>
2
+ import { greengrasscoreipc } from 'aws-iot-device-sdk-v2';
3
+
4
+ const TOPIC = '<%- componentName %>/heartbeat';
5
+ const PUBLISH_INTERVAL_MS = 30_000;
6
+
7
+ async function getIpcClient(): Promise<greengrasscoreipc.Client> {
8
+ const client = greengrasscoreipc.createClient();
9
+ await client.connect();
10
+ return client;
11
+ }
12
+
13
+ export async function publishHeartbeat(
14
+ client: greengrasscoreipc.Client,
15
+ sequence: number,
16
+ ): Promise<void> {
17
+ const request: greengrasscoreipc.model.PublishToTopicRequest = {
18
+ topic: TOPIC,
19
+ publishMessage: { jsonMessage: { message: { sequence } } },
20
+ };
21
+ await client.publishToTopic(request);
22
+ console.log(`Published heartbeat ${sequence} to ${TOPIC}`);
23
+ }
24
+
25
+ async function main(): Promise<void> {
26
+ const client = await getIpcClient();
27
+ let sequence = 0;
28
+ for (;;) {
29
+ await publishHeartbeat(client, sequence);
30
+ sequence += 1;
31
+ await new Promise((resolve) => setTimeout(resolve, PUBLISH_INTERVAL_MS));
32
+ }
33
+ }
34
+
35
+ main().catch((error) => {
36
+ console.error(error);
37
+ process.exit(1);
38
+ });
39
+ <%_ } else { _%>
40
+ const RUN_INTERVAL_MS = 30_000;
41
+
42
+ export function runOnce(sequence: number): void {
43
+ console.log(
44
+ `[<%- componentName %>] heartbeat ${sequence} at ${new Date().toISOString()}`,
45
+ );
46
+ }
47
+
48
+ async function main(): Promise<void> {
49
+ let sequence = 0;
50
+ for (;;) {
51
+ runOnce(sequence);
52
+ sequence += 1;
53
+ await new Promise((resolve) => setTimeout(resolve, RUN_INTERVAL_MS));
54
+ }
55
+ }
56
+
57
+ main();
58
+ <%_ } _%>
@@ -0,0 +1,13 @@
1
+ {
2
+ "component": {
3
+ "<%- componentName %>": {
4
+ "author": "<%- publisher %>",
5
+ "version": "<%- version %>",
6
+ "build": {
7
+ "build_system": "custom",
8
+ "custom_build_command": ["nx", "run", "<%- project %>:<%- componentDirName %>-artifact"]
9
+ }
10
+ }
11
+ },
12
+ "gdk_version": "1.0.0"
13
+ }
@@ -0,0 +1,115 @@
1
+ import { cpSync, existsSync, mkdirSync, readdirSync, rmSync } from 'node:fs';
2
+ import { createRequire } from 'node:module';
3
+ import { dirname, join, resolve } from 'node:path';
4
+
5
+ /*
6
+ * Usage: vendor-crt-addon.ts <project-root> <bundle-dir> <stage-dir> <addon-dir>[,<addon-dir>]
7
+ *
8
+ * Writes the deployable tree for an ipc=true TypeScript Greengrass component:
9
+ * every file from <bundle-dir> at the tree root, plus
10
+ * native/aws-crt/<addon-dir>/aws-crt-nodejs.node for each requested addon dir,
11
+ * copied out of the installed aws-crt. <stage-dir> is then the `bundle-dir`
12
+ * build-artifact.ts zips, so build-artifact.ts needs no knowledge of any of
13
+ * this. <addon-dir> is aws-crt's own
14
+ * `<platform>-<arch>-<cRuntime>` directory name, e.g. linux-arm64-glibc.
15
+ *
16
+ * aws-crt publishes its addon prebuilt for every platform it supports, so this
17
+ * is a file copy, never a compile, and the device never installs anything.
18
+ */
19
+
20
+ const log = (msg: string): void => console.error(`[vendor-crt-addon] ${msg}`);
21
+
22
+ function usage(): never {
23
+ log(
24
+ 'Usage: vendor-crt-addon.ts <project-root> <bundle-dir> <stage-dir> <addon-dir>[,<addon-dir>]',
25
+ );
26
+ process.exit(1);
27
+ }
28
+
29
+ /**
30
+ * The directory of `specifier`'s package.json, resolved from `fromPath`. Falls
31
+ * back to walking up from the resolved entry point, because a package with an
32
+ * `exports` map need not expose its own package.json. Both the subpath
33
+ * resolve and the fallback can throw - a missing package fails the first and
34
+ * would otherwise crash uncaught out of the second - so both are covered by
35
+ * one exit path with one diagnostic.
36
+ *
37
+ * `fromPath` is made absolute first: `createRequire` accepts only an absolute
38
+ * path or a file URL, and Nx expands `{projectRoot}` to a workspace-relative
39
+ * path, so passing it through unchanged throws ERR_INVALID_ARG_VALUE before
40
+ * either branch below can run.
41
+ */
42
+ function packageRoot(fromPath: string, specifier: string): string {
43
+ const from = resolve(fromPath);
44
+ const req = createRequire(from);
45
+ try {
46
+ return dirname(req.resolve(`${specifier}/package.json`));
47
+ } catch {
48
+ // Falls through to the walk-up fallback below.
49
+ }
50
+ try {
51
+ let dir = dirname(req.resolve(specifier));
52
+ while (!existsSync(join(dir, 'package.json'))) {
53
+ const parent = dirname(dir);
54
+ if (parent === dir) {
55
+ throw new Error('reached the filesystem root');
56
+ }
57
+ dir = parent;
58
+ }
59
+ return dir;
60
+ } catch {
61
+ log(`Cannot locate the package root of "${specifier}" from "${from}"`);
62
+ process.exit(1);
63
+ }
64
+ }
65
+
66
+ function main(): void {
67
+ const [projectRoot, bundleDir, stageDir, addonDirList] = process.argv.slice(2);
68
+ if (!projectRoot || !bundleDir || !stageDir || !addonDirList) usage();
69
+
70
+ const addonDirs = addonDirList
71
+ .split(',')
72
+ .map((a) => a.trim())
73
+ .filter((a) => a.length > 0);
74
+ if (addonDirs.length === 0) usage();
75
+
76
+ if (!existsSync(bundleDir)) {
77
+ log(`Bundle output "${bundleDir}" does not exist - run this project's "bundle" target first.`);
78
+ process.exit(1);
79
+ }
80
+
81
+ // Started empty every run: a stale addon dir from a deliberate platform
82
+ // change must never survive into the next artifact, because artifact bytes
83
+ // must depend only on the current source and the current pin.
84
+ rmSync(stageDir, { recursive: true, force: true });
85
+ mkdirSync(stageDir, { recursive: true });
86
+ cpSync(bundleDir, stageDir, { recursive: true });
87
+
88
+ // Two hops: pnpm's default isolated linker does not expose a transitive
89
+ // dependency to the host project, so aws-crt resolves from the SDK that
90
+ // pins it, never from here.
91
+ const sdkRoot = packageRoot(join(projectRoot, 'package.json'), 'aws-iot-device-sdk-v2');
92
+ const crtRoot = packageRoot(join(sdkRoot, 'package.json'), 'aws-crt');
93
+ const binDir = join(crtRoot, 'dist', 'bin');
94
+
95
+ for (const addonDir of addonDirs) {
96
+ const source = join(binDir, addonDir, 'aws-crt-nodejs.node');
97
+ if (!existsSync(source)) {
98
+ const available = existsSync(binDir) ? readdirSync(binDir).join(', ') : '<missing>';
99
+ log(
100
+ `aws-crt at "${crtRoot}" ships no prebuilt addon for "${addonDir}" (looked for "${source}"). Available: ${available}`,
101
+ );
102
+ process.exit(1);
103
+ }
104
+ const dest = join(stageDir, 'native', 'aws-crt', addonDir, 'aws-crt-nodejs.node');
105
+ if (existsSync(dest)) {
106
+ log(`Refusing to overwrite "${dest}" - the bundle already writes that path.`);
107
+ process.exit(1);
108
+ }
109
+ mkdirSync(dirname(dest), { recursive: true });
110
+ cpSync(source, dest);
111
+ log(`vendored ${addonDir}/aws-crt-nodejs.node`);
112
+ }
113
+ }
114
+
115
+ main();
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+ import { type GeneratorCallback, type Tree } from '@nx/devkit';
6
+ import type { NormalizedComponent } from '../common.js';
7
+ /**
8
+ * Generates an AWS IoT Greengrass v2 component on an existing TypeScript
9
+ * project: a single-file rolldown bundle plus packaging and local-deployment
10
+ * targets (`<c>-artifact`, `<c>-deploy-local`, `<c>-logs`), plus, unless
11
+ * `--infra none`, a `GreengrassComponentVersion` CDK construct (or Terraform
12
+ * module, via the `hashicorp/awscc` provider) that publishes the built
13
+ * artifact.
14
+ */
15
+ export declare const typescriptGreengrassComponentGenerator: (tree: Tree, component: NormalizedComponent) => Promise<GeneratorCallback>;
16
+ export default typescriptGreengrassComponentGenerator;
@@ -0,0 +1,194 @@
1
+ /**
2
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */ import { generateFiles, joinPathFragments, logger, OverwriteStrategy, updateProjectConfiguration } from "@nx/devkit";
5
+ import { addTypeScriptBundleTarget } from "../../../utils/bundle/bundle.js";
6
+ import { GREENGRASS_PLATFORM_MAPPINGS, RECIPE_FORMAT_VERSION } from "../../../utils/greengrass/constants.js";
7
+ import { addArtifactDependencyToTargets, normalizeTargetKeyOrder } from "../../../utils/nx.js";
8
+ import { sortObjectKeys } from "../../../utils/object.js";
9
+ import { toProjectRelativePath } from "../../../utils/paths.js";
10
+ import { registerPnpmBuiltDependencies } from "../../../utils/pnpm-workspace.js";
11
+ import { sharedGreengrassScriptsGenerator } from "../../../utils/shared-greengrass-scripts.js";
12
+ import { assertUnchangedPlatform, finalizeComponent, GREENGRASS_SCRIPTS_DIR, sharedComponentTargets } from "../common.js";
13
+ import { TYPESCRIPT_DEPENDENCIES as DEPENDENCIES } from "../dependencies.js";
14
+ /**
15
+ * Generates an AWS IoT Greengrass v2 component on an existing TypeScript
16
+ * project: a single-file rolldown bundle plus packaging and local-deployment
17
+ * targets (`<c>-artifact`, `<c>-deploy-local`, `<c>-logs`), plus, unless
18
+ * `--infra none`, a `GreengrassComponentVersion` CDK construct (or Terraform
19
+ * module, via the `hashicorp/awscc` provider) that publishes the built
20
+ * artifact.
21
+ */ export const typescriptGreengrassComponentGenerator = async (tree, component)=>{
22
+ const { project: projectConfig } = component;
23
+ const componentDirName = component.componentDirName;
24
+ const componentName = component.componentName;
25
+ const componentVersion = component.componentVersion;
26
+ const publisher = component.publisher;
27
+ const ipc = component.ipc;
28
+ const gdkConfig = component.gdkConfig;
29
+ const platforms = component.platforms;
30
+ // A rolldown bundle is pure JavaScript over every architecture, and with
31
+ // `ipc=true` one zip carries every targeted architecture's own vendored
32
+ // addon - each manifest's Setenv selects only its own - so, unlike the
33
+ // Python component, this generator has ONE artifact over N manifests, never
34
+ // N artifacts.
35
+ const manifests = platforms.map((p)=>{
36
+ const { manifestPlatform, nodeCrtAddonDir } = GREENGRASS_PLATFORM_MAPPINGS[p];
37
+ return {
38
+ os: manifestPlatform.os,
39
+ architecture: manifestPlatform.architecture,
40
+ artifactBaseName: componentDirName,
41
+ nodeCrtAddonDir
42
+ };
43
+ });
44
+ const componentDir = joinPathFragments(projectConfig.root, 'greengrass', componentDirName);
45
+ const entrypointDir = joinPathFragments(projectConfig.sourceRoot, 'greengrass', componentDirName);
46
+ const mainPath = joinPathFragments(entrypointDir, 'main.ts');
47
+ const mainPathFromProjectRoot = joinPathFragments(toProjectRelativePath(projectConfig, mainPath));
48
+ const gdkConfigPath = joinPathFragments(componentDir, 'gdk-config.json');
49
+ const manifestPreview = manifests.map((m)=>` - Platform:\n os: ${m.os}\n architecture: ${m.architecture}\n Artifacts:\n - Uri: s3://BUCKET_NAME/COMPONENT_NAME/COMPONENT_VERSION/${m.artifactBaseName}.zip\n Unarchive: ZIP\n Lifecycle:\n${// The Setenv block is per-manifest and names this architecture's
50
+ // vendored addon, so a preview without it is not paste-ready for an
51
+ // ipc=true component.
52
+ ipc ? ` Setenv:\n AWS_CRT_NODEJS_BINARY_RELATIVE_PATH: native/aws-crt/${m.nodeCrtAddonDir}/aws-crt-nodejs.node\n` : ''} Run: node {artifacts:decompressedPath}/${m.artifactBaseName}/index.js`).join('\n');
53
+ assertUnchangedPlatform(component, manifestPreview);
54
+ const templateOptions = {
55
+ componentName,
56
+ // Named `version` / `recipeFormat`, not `componentVersion` /
57
+ // `recipeFormatVersion`: a `*Version` template variable is how a template
58
+ // names a vended dependency pin (see `VENDED_TEMPLATE_VARS` in
59
+ // `version-upgrade-migration/real-templates.spec.ts`), which neither a
60
+ // user-owned option nor a fixed protocol constant is.
61
+ version: componentVersion,
62
+ recipeFormat: RECIPE_FORMAT_VERSION,
63
+ componentDescription: `${componentName} Greengrass component, generated by greengrass#component.`,
64
+ publisher,
65
+ ipc,
66
+ manifests,
67
+ componentDirName,
68
+ project: projectConfig.name
69
+ };
70
+ // recipe.yaml is user-owned from first generation onward, so `ipc` shapes it
71
+ // only on the first run: a later run that flips `ipc` to true adds the vendor
72
+ // target and stages the addon, but leaves the recipe without the `Setenv` that
73
+ // points aws-crt's loader at it, and the component then fails on the device
74
+ // with "AWS CRT binary not present". Add that block by hand - the guide's
75
+ // migration note carries the exact shape.
76
+ generateFiles(tree, joinPathFragments(import.meta.dirname, 'files', 'component'), componentDir, templateOptions, {
77
+ overwriteStrategy: OverwriteStrategy.KeepExisting
78
+ });
79
+ // main.ts is user-owned from first generation onward. It lives under the
80
+ // project's own source tree (not beside recipe.yaml, unlike Python components)
81
+ // so it participates in the project's normal TypeScript compile/lint/test targets.
82
+ generateFiles(tree, joinPathFragments(import.meta.dirname, 'files', 'entrypoint'), entrypointDir, templateOptions, {
83
+ overwriteStrategy: OverwriteStrategy.KeepExisting
84
+ });
85
+ if (gdkConfig) {
86
+ generateFiles(tree, joinPathFragments(import.meta.dirname, 'files', 'gdk'), componentDir, templateOptions, {
87
+ overwriteStrategy: OverwriteStrategy.Overwrite
88
+ });
89
+ } else if (tree.exists(gdkConfigPath)) {
90
+ tree.delete(gdkConfigPath);
91
+ logger.info(`Removed ${gdkConfigPath}; pass --gdkConfig to keep it.`);
92
+ }
93
+ await sharedGreengrassScriptsGenerator(tree, DEPENDENCIES);
94
+ if (ipc) {
95
+ // aws-crt ships an install script that builds its native addon from
96
+ // source. Recorded as `false`: this component vendors the prebuilt addon at
97
+ // build time, so the script must not run - and pnpm 11 fails the install
98
+ // outright with ERR_PNPM_IGNORED_BUILDS unless the decision is explicit.
99
+ registerPnpmBuiltDependencies(tree, {
100
+ 'aws-crt': false
101
+ });
102
+ }
103
+ if (ipc) {
104
+ // AFTER sharedGreengrassScriptsGenerator, never before: in a workspace with
105
+ // no shared scripts project yet, that generator creates one and deletes the
106
+ // whole `src` tree it scaffolded, which would take this script with it and
107
+ // leave the `-vendor` target invoking a file that does not exist.
108
+ //
109
+ // Vended here rather than by that generator, and only when ipc is true,
110
+ // because it vends its whole directory into every workspace - putting this
111
+ // script there would change what an ipc=false run produces. KeepExisting
112
+ // like every other vended script, so a user's patches survive.
113
+ generateFiles(tree, joinPathFragments(import.meta.dirname, 'files', 'scripts'), GREENGRASS_SCRIPTS_DIR, templateOptions, {
114
+ overwriteStrategy: OverwriteStrategy.KeepExisting
115
+ });
116
+ }
117
+ const bundleOutputDir = joinPathFragments('greengrass', componentDirName);
118
+ await addTypeScriptBundleTarget(tree, projectConfig, {
119
+ targetFilePath: mainPathFromProjectRoot,
120
+ bundleOutputDir,
121
+ platform: 'node'
122
+ }, DEPENDENCIES);
123
+ const artifactTarget = `${componentDirName}-artifact`;
124
+ const vendorTarget = `${componentDirName}-vendor`;
125
+ const distDir = `dist/{projectRoot}/greengrass/${componentDirName}`;
126
+ const bundleDir = `dist/{projectRoot}/bundle/${bundleOutputDir}`;
127
+ // Named `stage`, not `vendor`, so it cannot be confused with the
128
+ // `<dist>/vendor` path build-artifact.ts reads in Python (non-bundle) mode.
129
+ const stageDir = `${distDir}/stage`;
130
+ projectConfig.targets ??= {};
131
+ if (ipc) {
132
+ projectConfig.targets[vendorTarget] = normalizeTargetKeyOrder({
133
+ cache: true,
134
+ inputs: [
135
+ 'production',
136
+ '^production',
137
+ `{workspaceRoot}/${GREENGRASS_SCRIPTS_DIR}/**/*`,
138
+ // The addon bytes come from the installed aws-crt, not from any file
139
+ // in this project, so without this the target would serve the
140
+ // previous SDK's addon from cache after a version bump.
141
+ {
142
+ externalDependencies: [
143
+ 'aws-iot-device-sdk-v2'
144
+ ]
145
+ }
146
+ ],
147
+ outputs: [
148
+ `{workspaceRoot}/${stageDir}`
149
+ ],
150
+ executor: 'nx:run-commands',
151
+ dependsOn: [
152
+ 'bundle'
153
+ ],
154
+ options: {
155
+ command: `tsx ${GREENGRASS_SCRIPTS_DIR}/vendor-crt-addon.ts {projectRoot} ${bundleDir} ${stageDir} ${manifests.map((m)=>m.nodeCrtAddonDir).join(',')}`
156
+ }
157
+ });
158
+ }
159
+ projectConfig.targets[artifactTarget] = normalizeTargetKeyOrder({
160
+ cache: true,
161
+ // The vended scripts live outside this project, so the cache key must
162
+ // name them explicitly or a refreshed script serves a stale artifact.
163
+ inputs: [
164
+ 'production',
165
+ '^production',
166
+ `{workspaceRoot}/${GREENGRASS_SCRIPTS_DIR}/**/*`
167
+ ],
168
+ outputs: [
169
+ `{workspaceRoot}/${distDir}/greengrass-build`
170
+ ],
171
+ executor: 'nx:run-commands',
172
+ dependsOn: [
173
+ ipc ? vendorTarget : 'bundle'
174
+ ],
175
+ options: {
176
+ command: `tsx ${GREENGRASS_SCRIPTS_DIR}/build-artifact.ts {projectRoot} ${componentDirName} ${distDir} ${ipc ? stageDir : bundleDir}`
177
+ }
178
+ });
179
+ addArtifactDependencyToTargets(projectConfig, artifactTarget);
180
+ Object.assign(projectConfig.targets, sharedComponentTargets({
181
+ artifactTarget,
182
+ componentDirName,
183
+ componentName,
184
+ distDir
185
+ }));
186
+ // py#project and ts#project sort targets on every run, including re-runs,
187
+ // so append in the same order or a later project re-run reorders the file.
188
+ projectConfig.targets = sortObjectKeys(projectConfig.targets);
189
+ updateProjectConfiguration(tree, projectConfig.name, projectConfig);
190
+ return finalizeComponent(tree, component, mainPathFromProjectRoot, DEPENDENCIES);
191
+ };
192
+ export default typescriptGreengrassComponentGenerator;
193
+
194
+ //# sourceMappingURL=generator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../../packages/nx-plugin/src/greengrass/component/typescript/generator.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport {\n type GeneratorCallback,\n generateFiles,\n joinPathFragments,\n logger,\n OverwriteStrategy,\n type Tree,\n updateProjectConfiguration,\n} from '@nx/devkit';\nimport { addTypeScriptBundleTarget } from '../../../utils/bundle/bundle.js';\nimport {\n GREENGRASS_PLATFORM_MAPPINGS,\n RECIPE_FORMAT_VERSION,\n} from '../../../utils/greengrass/constants.js';\nimport {\n addArtifactDependencyToTargets,\n normalizeTargetKeyOrder,\n} from '../../../utils/nx.js';\nimport { sortObjectKeys } from '../../../utils/object.js';\nimport { toProjectRelativePath } from '../../../utils/paths.js';\nimport { registerPnpmBuiltDependencies } from '../../../utils/pnpm-workspace.js';\nimport { sharedGreengrassScriptsGenerator } from '../../../utils/shared-greengrass-scripts.js';\nimport type { NormalizedComponent } from '../common.js';\nimport {\n assertUnchangedPlatform,\n finalizeComponent,\n GREENGRASS_SCRIPTS_DIR,\n sharedComponentTargets,\n} from '../common.js';\nimport { TYPESCRIPT_DEPENDENCIES as DEPENDENCIES } from '../dependencies.js';\n\n/**\n * Generates an AWS IoT Greengrass v2 component on an existing TypeScript\n * project: a single-file rolldown bundle plus packaging and local-deployment\n * targets (`<c>-artifact`, `<c>-deploy-local`, `<c>-logs`), plus, unless\n * `--infra none`, a `GreengrassComponentVersion` CDK construct (or Terraform\n * module, via the `hashicorp/awscc` provider) that publishes the built\n * artifact.\n */\nexport const typescriptGreengrassComponentGenerator = async (\n tree: Tree,\n component: NormalizedComponent,\n): Promise<GeneratorCallback> => {\n const { project: projectConfig } = component;\n\n const componentDirName = component.componentDirName;\n const componentName = component.componentName;\n const componentVersion = component.componentVersion;\n const publisher = component.publisher;\n const ipc = component.ipc;\n const gdkConfig = component.gdkConfig;\n const platforms = component.platforms;\n // A rolldown bundle is pure JavaScript over every architecture, and with\n // `ipc=true` one zip carries every targeted architecture's own vendored\n // addon - each manifest's Setenv selects only its own - so, unlike the\n // Python component, this generator has ONE artifact over N manifests, never\n // N artifacts.\n const manifests = platforms.map((p) => {\n const { manifestPlatform, nodeCrtAddonDir } =\n GREENGRASS_PLATFORM_MAPPINGS[p];\n return {\n os: manifestPlatform.os,\n architecture: manifestPlatform.architecture,\n artifactBaseName: componentDirName,\n nodeCrtAddonDir,\n };\n });\n\n const componentDir = joinPathFragments(\n projectConfig.root,\n 'greengrass',\n componentDirName,\n );\n const entrypointDir = joinPathFragments(\n projectConfig.sourceRoot!,\n 'greengrass',\n componentDirName,\n );\n const mainPath = joinPathFragments(entrypointDir, 'main.ts');\n const mainPathFromProjectRoot = joinPathFragments(\n toProjectRelativePath(projectConfig, mainPath),\n );\n const gdkConfigPath = joinPathFragments(componentDir, 'gdk-config.json');\n\n const manifestPreview = manifests\n .map(\n (m) =>\n ` - Platform:\\n os: ${m.os}\\n architecture: ${m.architecture}\\n Artifacts:\\n - Uri: s3://BUCKET_NAME/COMPONENT_NAME/COMPONENT_VERSION/${m.artifactBaseName}.zip\\n Unarchive: ZIP\\n Lifecycle:\\n${\n // The Setenv block is per-manifest and names this architecture's\n // vendored addon, so a preview without it is not paste-ready for an\n // ipc=true component.\n ipc\n ? ` Setenv:\\n AWS_CRT_NODEJS_BINARY_RELATIVE_PATH: native/aws-crt/${m.nodeCrtAddonDir}/aws-crt-nodejs.node\\n`\n : ''\n } Run: node {artifacts:decompressedPath}/${m.artifactBaseName}/index.js`,\n )\n .join('\\n');\n assertUnchangedPlatform(component, manifestPreview);\n\n const templateOptions = {\n componentName,\n // Named `version` / `recipeFormat`, not `componentVersion` /\n // `recipeFormatVersion`: a `*Version` template variable is how a template\n // names a vended dependency pin (see `VENDED_TEMPLATE_VARS` in\n // `version-upgrade-migration/real-templates.spec.ts`), which neither a\n // user-owned option nor a fixed protocol constant is.\n version: componentVersion,\n recipeFormat: RECIPE_FORMAT_VERSION,\n componentDescription: `${componentName} Greengrass component, generated by greengrass#component.`,\n publisher,\n ipc,\n manifests,\n componentDirName,\n project: projectConfig.name,\n };\n\n // recipe.yaml is user-owned from first generation onward, so `ipc` shapes it\n // only on the first run: a later run that flips `ipc` to true adds the vendor\n // target and stages the addon, but leaves the recipe without the `Setenv` that\n // points aws-crt's loader at it, and the component then fails on the device\n // with \"AWS CRT binary not present\". Add that block by hand - the guide's\n // migration note carries the exact shape.\n generateFiles(\n tree,\n joinPathFragments(import.meta.dirname, 'files', 'component'),\n componentDir,\n templateOptions,\n { overwriteStrategy: OverwriteStrategy.KeepExisting },\n );\n\n // main.ts is user-owned from first generation onward. It lives under the\n // project's own source tree (not beside recipe.yaml, unlike Python components)\n // so it participates in the project's normal TypeScript compile/lint/test targets.\n generateFiles(\n tree,\n joinPathFragments(import.meta.dirname, 'files', 'entrypoint'),\n entrypointDir,\n templateOptions,\n { overwriteStrategy: OverwriteStrategy.KeepExisting },\n );\n\n if (gdkConfig) {\n generateFiles(\n tree,\n joinPathFragments(import.meta.dirname, 'files', 'gdk'),\n componentDir,\n templateOptions,\n { overwriteStrategy: OverwriteStrategy.Overwrite },\n );\n } else if (tree.exists(gdkConfigPath)) {\n tree.delete(gdkConfigPath);\n logger.info(`Removed ${gdkConfigPath}; pass --gdkConfig to keep it.`);\n }\n\n await sharedGreengrassScriptsGenerator(tree, DEPENDENCIES);\n\n if (ipc) {\n // aws-crt ships an install script that builds its native addon from\n // source. Recorded as `false`: this component vendors the prebuilt addon at\n // build time, so the script must not run - and pnpm 11 fails the install\n // outright with ERR_PNPM_IGNORED_BUILDS unless the decision is explicit.\n registerPnpmBuiltDependencies(tree, { 'aws-crt': false });\n }\n\n if (ipc) {\n // AFTER sharedGreengrassScriptsGenerator, never before: in a workspace with\n // no shared scripts project yet, that generator creates one and deletes the\n // whole `src` tree it scaffolded, which would take this script with it and\n // leave the `-vendor` target invoking a file that does not exist.\n //\n // Vended here rather than by that generator, and only when ipc is true,\n // because it vends its whole directory into every workspace - putting this\n // script there would change what an ipc=false run produces. KeepExisting\n // like every other vended script, so a user's patches survive.\n generateFiles(\n tree,\n joinPathFragments(import.meta.dirname, 'files', 'scripts'),\n GREENGRASS_SCRIPTS_DIR,\n templateOptions,\n { overwriteStrategy: OverwriteStrategy.KeepExisting },\n );\n }\n\n const bundleOutputDir = joinPathFragments('greengrass', componentDirName);\n await addTypeScriptBundleTarget(\n tree,\n projectConfig,\n {\n targetFilePath: mainPathFromProjectRoot,\n bundleOutputDir,\n platform: 'node',\n },\n DEPENDENCIES,\n );\n\n const artifactTarget = `${componentDirName}-artifact`;\n const vendorTarget = `${componentDirName}-vendor`;\n const distDir = `dist/{projectRoot}/greengrass/${componentDirName}`;\n const bundleDir = `dist/{projectRoot}/bundle/${bundleOutputDir}`;\n // Named `stage`, not `vendor`, so it cannot be confused with the\n // `<dist>/vendor` path build-artifact.ts reads in Python (non-bundle) mode.\n const stageDir = `${distDir}/stage`;\n\n projectConfig.targets ??= {};\n\n if (ipc) {\n projectConfig.targets[vendorTarget] = normalizeTargetKeyOrder({\n cache: true,\n inputs: [\n 'production',\n '^production',\n `{workspaceRoot}/${GREENGRASS_SCRIPTS_DIR}/**/*`,\n // The addon bytes come from the installed aws-crt, not from any file\n // in this project, so without this the target would serve the\n // previous SDK's addon from cache after a version bump.\n { externalDependencies: ['aws-iot-device-sdk-v2'] },\n ],\n outputs: [`{workspaceRoot}/${stageDir}`],\n executor: 'nx:run-commands',\n dependsOn: ['bundle'],\n options: {\n command: `tsx ${GREENGRASS_SCRIPTS_DIR}/vendor-crt-addon.ts {projectRoot} ${bundleDir} ${stageDir} ${manifests\n .map((m) => m.nodeCrtAddonDir)\n .join(',')}`,\n },\n });\n }\n\n projectConfig.targets[artifactTarget] = normalizeTargetKeyOrder({\n cache: true,\n // The vended scripts live outside this project, so the cache key must\n // name them explicitly or a refreshed script serves a stale artifact.\n inputs: [\n 'production',\n '^production',\n `{workspaceRoot}/${GREENGRASS_SCRIPTS_DIR}/**/*`,\n ],\n outputs: [`{workspaceRoot}/${distDir}/greengrass-build`],\n executor: 'nx:run-commands',\n dependsOn: [ipc ? vendorTarget : 'bundle'],\n options: {\n command: `tsx ${GREENGRASS_SCRIPTS_DIR}/build-artifact.ts {projectRoot} ${componentDirName} ${distDir} ${ipc ? stageDir : bundleDir}`,\n },\n });\n addArtifactDependencyToTargets(projectConfig, artifactTarget);\n\n Object.assign(\n projectConfig.targets,\n sharedComponentTargets({\n artifactTarget,\n componentDirName,\n componentName,\n distDir,\n }),\n );\n\n // py#project and ts#project sort targets on every run, including re-runs,\n // so append in the same order or a later project re-run reorders the file.\n projectConfig.targets = sortObjectKeys(projectConfig.targets);\n updateProjectConfiguration(tree, projectConfig.name, projectConfig);\n\n return finalizeComponent(\n tree,\n component,\n mainPathFromProjectRoot,\n DEPENDENCIES,\n );\n};\n\nexport default typescriptGreengrassComponentGenerator;\n"],"names":["generateFiles","joinPathFragments","logger","OverwriteStrategy","updateProjectConfiguration","addTypeScriptBundleTarget","GREENGRASS_PLATFORM_MAPPINGS","RECIPE_FORMAT_VERSION","addArtifactDependencyToTargets","normalizeTargetKeyOrder","sortObjectKeys","toProjectRelativePath","registerPnpmBuiltDependencies","sharedGreengrassScriptsGenerator","assertUnchangedPlatform","finalizeComponent","GREENGRASS_SCRIPTS_DIR","sharedComponentTargets","TYPESCRIPT_DEPENDENCIES","DEPENDENCIES","typescriptGreengrassComponentGenerator","tree","component","project","projectConfig","componentDirName","componentName","componentVersion","publisher","ipc","gdkConfig","platforms","manifests","map","p","manifestPlatform","nodeCrtAddonDir","os","architecture","artifactBaseName","componentDir","root","entrypointDir","sourceRoot","mainPath","mainPathFromProjectRoot","gdkConfigPath","manifestPreview","m","join","templateOptions","version","recipeFormat","componentDescription","name","dirname","overwriteStrategy","KeepExisting","Overwrite","exists","delete","info","bundleOutputDir","targetFilePath","platform","artifactTarget","vendorTarget","distDir","bundleDir","stageDir","targets","cache","inputs","externalDependencies","outputs","executor","dependsOn","options","command","Object","assign"],"mappings":"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"}
@@ -47,7 +47,7 @@ export declare const DEPENDENCIES: import("../../utils/declared-dependencies.js"
47
47
  readonly when: (m: import("../../utils/shared-constructs-constants.js").IacMetadata) => boolean;
48
48
  } & {
49
49
  versionOnly: true;
50
- }], readonly import("../../utils/declared-dependencies.js").DeclaredPyDependency<"ruff" | "a2a-sdk" | "ag-ui-langgraph" | "ag-ui-protocol" | "ag-ui-strands" | "aiosqlite" | "aws-lambda-powertools" | "aws-lambda-powertools[tracer]" | "aws-lambda-powertools[parser]" | "aws-opentelemetry-distro" | "bedrock-agentcore" | "boto3" | "checkov" | "fastapi" | "fastapi[standard]" | "httpx" | "langchain" | "langchain-aws" | "langchain-mcp-adapters" | "langgraph" | "langgraph-checkpoint-aws" | "langgraph-checkpoint-sqlite" | "mcp" | "pip-check-updates" | "pip-licenses" | "pydantic" | "strands-agents" | "strands-agents[a2a]" | "strands-agents-tools" | "ty" | "pynamodb" | "uvicorn" | "sqlmodel" | "alembic" | "aiomysql" | "asyncpg" | "greenlet", Record<string, never>>[]>;
50
+ }], readonly import("../../utils/declared-dependencies.js").DeclaredPyDependency<"ruff" | "a2a-sdk" | "ag-ui-langgraph" | "ag-ui-protocol" | "ag-ui-strands" | "aiosqlite" | "aws-lambda-powertools" | "aws-lambda-powertools[tracer]" | "aws-lambda-powertools[parser]" | "aws-opentelemetry-distro" | "awsiotsdk" | "bedrock-agentcore" | "boto3" | "checkov" | "fastapi" | "fastapi[standard]" | "httpx" | "langchain" | "langchain-aws" | "langchain-mcp-adapters" | "langgraph" | "langgraph-checkpoint-aws" | "langgraph-checkpoint-sqlite" | "mcp" | "pip-check-updates" | "pip-licenses" | "pydantic" | "strands-agents" | "strands-agents[a2a]" | "strands-agents-tools" | "ty" | "pynamodb" | "uvicorn" | "sqlmodel" | "alembic" | "aiomysql" | "asyncpg" | "greenlet", Record<string, never>>[]>;
51
51
  export declare const INFRA_APP_GENERATOR_INFO: NxGeneratorInfo;
52
52
  export declare function tsInfraGenerator(tree: Tree, schema: TsInfraGeneratorSchema): Promise<GeneratorCallback>;
53
53
  export default tsInfraGenerator;
@@ -17,7 +17,7 @@ export declare const DEPENDENCIES: import("../utils/declared-dependencies.js").D
17
17
  readonly name: "typescript";
18
18
  }, {
19
19
  readonly name: "@biomejs/biome";
20
- }], readonly import("../utils/declared-dependencies.js").DeclaredPyDependency<"ruff" | "a2a-sdk" | "ag-ui-langgraph" | "ag-ui-protocol" | "ag-ui-strands" | "aiosqlite" | "aws-lambda-powertools" | "aws-lambda-powertools[tracer]" | "aws-lambda-powertools[parser]" | "aws-opentelemetry-distro" | "bedrock-agentcore" | "boto3" | "checkov" | "fastapi" | "fastapi[standard]" | "httpx" | "langchain" | "langchain-aws" | "langchain-mcp-adapters" | "langgraph" | "langgraph-checkpoint-aws" | "langgraph-checkpoint-sqlite" | "mcp" | "pip-check-updates" | "pip-licenses" | "pydantic" | "strands-agents" | "strands-agents[a2a]" | "strands-agents-tools" | "ty" | "pynamodb" | "uvicorn" | "sqlmodel" | "alembic" | "aiomysql" | "asyncpg" | "greenlet", Record<string, never>>[]>;
20
+ }], readonly import("../utils/declared-dependencies.js").DeclaredPyDependency<"ruff" | "a2a-sdk" | "ag-ui-langgraph" | "ag-ui-protocol" | "ag-ui-strands" | "aiosqlite" | "aws-lambda-powertools" | "aws-lambda-powertools[tracer]" | "aws-lambda-powertools[parser]" | "aws-opentelemetry-distro" | "awsiotsdk" | "bedrock-agentcore" | "boto3" | "checkov" | "fastapi" | "fastapi[standard]" | "httpx" | "langchain" | "langchain-aws" | "langchain-mcp-adapters" | "langgraph" | "langgraph-checkpoint-aws" | "langgraph-checkpoint-sqlite" | "mcp" | "pip-check-updates" | "pip-licenses" | "pydantic" | "strands-agents" | "strands-agents[a2a]" | "strands-agents-tools" | "ty" | "pynamodb" | "uvicorn" | "sqlmodel" | "alembic" | "aiomysql" | "asyncpg" | "greenlet", Record<string, never>>[]>;
21
21
  export declare const INIT_GENERATOR_INFO: NxGeneratorInfo;
22
22
  /**
23
23
  * Configure an existing Nx workspace to use the @aws/nx-plugin.
@@ -4,6 +4,7 @@
4
4
  */ import { agentcoreGatewayGenerator } from "../../sdk/agentcore-gateway.js";
5
5
  import { agentcoreHarnessGenerator } from "../../sdk/agentcore-harness.js";
6
6
  import { connectionGenerator } from "../../sdk/connection.js";
7
+ import { greengrassComponentGenerator } from "../../sdk/greengrass.js";
7
8
  import { licenseGenerator } from "../../sdk/license.js";
8
9
  import { pyAgentGenerator, pyApiGenerator, pyDynamoDBGenerator, pyLambdaFunctionGenerator, pyMcpServerGenerator, pyProjectGenerator, pyRdbGenerator } from "../../sdk/py.js";
9
10
  import { smithyProjectGenerator } from "../../sdk/smithy.js";
@@ -216,6 +217,47 @@ import { getNpmScope, getNpmScopePrefix } from "../../utils/npm-scope.js";
216
217
  iac: 'inherit',
217
218
  ...defaults
218
219
  });
220
+ // Greengrass: the `AWS::GreengrassV2` resources exist in the
221
+ // `hashicorp/awscc` Terraform provider (this workspace pins it), so both
222
+ // `--iac cdk` and `--iac terraform` are exercised here via `iac: 'inherit'`.
223
+ //
224
+ // A component with publication infrastructure and an app wrapper in the
225
+ // workspace's infrastructure project. Hosted on a dedicated project:
226
+ // vendoring's `--only-binary :all:` refuses the source-built workspace
227
+ // members other entries add to py-project, and one component per project is
228
+ // the documented production default.
229
+ await pyProjectGenerator(tree, {
230
+ name: 'py-greengrass-project',
231
+ type: 'application',
232
+ ...projectDefaults
233
+ });
234
+ await greengrassComponentGenerator(tree, {
235
+ project: py('py-greengrass-project'),
236
+ name: 'my-greengrass-component',
237
+ language: 'python',
238
+ platform: 'linux-amd64-arm64',
239
+ gdkConfig: true,
240
+ iac: 'inherit',
241
+ ...defaults
242
+ });
243
+ // The TypeScript component gets a dedicated host project for the same
244
+ // reason: the shared `bundle` target this generator wires rebuilds every
245
+ // bundled entrypoint in its project together, so hosting it alongside
246
+ // `ts-project`'s Lambda function would couple this device-oriented
247
+ // bundle's cache invalidation to an unrelated Lambda bundle's.
248
+ await tsProjectGenerator(tree, {
249
+ name: 'ts-greengrass-project',
250
+ ...projectDefaults
251
+ });
252
+ await greengrassComponentGenerator(tree, {
253
+ project: 'ts-greengrass-project',
254
+ name: 'my-ts-greengrass-component',
255
+ language: 'typescript',
256
+ ipc: true,
257
+ componentVersion: '1.0.0',
258
+ iac: 'inherit',
259
+ ...defaults
260
+ });
219
261
  // MCP servers — uninfra'd and hosted on AgentCore.
220
262
  await pyMcpServerGenerator(tree, {
221
263
  project: 'py_project',