@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,450 @@
1
+ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2
+
3
+ exports[`greengrass#component generator (python) > multi-architecture (platform: linux-amd64-arm64) > should match snapshot for a multi-architecture component > multi-arch-snapshot 1`] = `
4
+ {
5
+ "apps/test_project/greengrass/my-component/main.py": "import logging
6
+ import time
7
+
8
+ logging.basicConfig(level=logging.INFO)
9
+ logger = logging.getLogger("com.proj.MyComponent")
10
+
11
+ RUN_INTERVAL_SECONDS = 30
12
+
13
+
14
+ def run_once(sequence: int) -> None:
15
+ logger.info("com.proj.MyComponent heartbeat %s", sequence)
16
+
17
+
18
+ def main() -> None:
19
+ sequence = 0
20
+ while True:
21
+ run_once(sequence)
22
+ sequence += 1
23
+ time.sleep(RUN_INTERVAL_SECONDS)
24
+
25
+
26
+ if __name__ == "__main__":
27
+ main()
28
+ ",
29
+ "apps/test_project/greengrass/my-component/recipe.yaml": "RecipeFormatVersion: '2020-01-25'
30
+ ComponentName: com.proj.MyComponent
31
+ ComponentVersion: 1.0.0
32
+ ComponentDescription: com.proj.MyComponent Greengrass component using Python 3.14, generated by greengrass#component.
33
+ ComponentPublisher: proj
34
+ Manifests:
35
+ - Platform:
36
+ os: linux
37
+ architecture: amd64
38
+ Artifacts:
39
+ # Placeholders are substituted at publish time. The basename must stay
40
+ # my-component-amd64.zip, which is what the Run script below unarchives to.
41
+ - Uri: s3://BUCKET_NAME/COMPONENT_NAME/COMPONENT_VERSION/my-component-amd64.zip
42
+ Unarchive: ZIP
43
+ Lifecycle:
44
+ Run: python3.14 {artifacts:decompressedPath}/my-component-amd64/main.py
45
+ - Platform:
46
+ os: linux
47
+ architecture: aarch64
48
+ Artifacts:
49
+ # Placeholders are substituted at publish time. The basename must stay
50
+ # my-component-aarch64.zip, which is what the Run script below unarchives to.
51
+ - Uri: s3://BUCKET_NAME/COMPONENT_NAME/COMPONENT_VERSION/my-component-aarch64.zip
52
+ Unarchive: ZIP
53
+ Lifecycle:
54
+ Run: python3.14 {artifacts:decompressedPath}/my-component-aarch64/main.py
55
+ ",
56
+ "apps/test_project/project.json": "{
57
+ "name": "test-project",
58
+ "$schema": "../../node_modules/nx/schemas/project-schema.json",
59
+ "sourceRoot": "apps/test_project/test_project",
60
+ "metadata": {
61
+ "components": [
62
+ {
63
+ "generator": "greengrass#component",
64
+ "path": "greengrass/my-component/main.py",
65
+ "name": "my-component",
66
+ "language": "python",
67
+ "componentName": "com.proj.MyComponent",
68
+ "componentVersion": "1.0.0",
69
+ "platform": "linux-amd64-arm64",
70
+ "ipc": false,
71
+ "gdkConfig": false
72
+ }
73
+ ]
74
+ },
75
+ "targets": {
76
+ "assemble": {
77
+ "dependsOn": ["my-component-artifact"]
78
+ },
79
+ "build": {
80
+ "dependsOn": ["my-component-artifact"]
81
+ },
82
+ "my-component-artifact": {
83
+ "executor": "nx:run-commands",
84
+ "dependsOn": ["my-component-vendor"],
85
+ "cache": true,
86
+ "inputs": [
87
+ "production",
88
+ "^production",
89
+ "{workspaceRoot}/packages/common/scripts/src/greengrass/**/*"
90
+ ],
91
+ "outputs": [
92
+ "{workspaceRoot}/dist/{projectRoot}/greengrass/my-component/greengrass-build"
93
+ ],
94
+ "options": {
95
+ "command": "tsx packages/common/scripts/src/greengrass/build-artifact.ts {projectRoot} my-component dist/{projectRoot}/greengrass/my-component --platforms=amd64,aarch64"
96
+ }
97
+ },
98
+ "my-component-deploy-local": {
99
+ "executor": "nx:run-commands",
100
+ "dependsOn": ["my-component-artifact"],
101
+ "options": {
102
+ "command": "tsx packages/common/scripts/src/greengrass/deploy-local.ts dist/{projectRoot}/greengrass/my-component"
103
+ }
104
+ },
105
+ "my-component-logs": {
106
+ "executor": "nx:run-commands",
107
+ "continuous": true,
108
+ "options": {
109
+ "command": "tsx packages/common/scripts/src/greengrass/component-logs.ts com.proj.MyComponent"
110
+ }
111
+ },
112
+ "my-component-vendor": {
113
+ "executor": "nx:run-commands",
114
+ "dependsOn": ["compile"],
115
+ "cache": true,
116
+ "inputs": ["production", "^production"],
117
+ "outputs": [
118
+ "{workspaceRoot}/dist/{projectRoot}/greengrass/my-component/vendor"
119
+ ],
120
+ "options": {
121
+ "commands": [
122
+ "shx rm -rf dist/{projectRoot}/greengrass/my-component/vendor",
123
+ "shx mkdir -p dist/{projectRoot}/greengrass/my-component/vendor",
124
+ "uv export --frozen --no-dev --no-editable --no-emit-project --project {projectRoot} --package test-project -o dist/{projectRoot}/greengrass/my-component/vendor/requirements.txt",
125
+ "uv pip install -n --no-deps --no-installer-metadata --no-compile-bytecode --only-binary :all: --python-platform x86_64-manylinux_2_28 --python-version 3.14 --target dist/{projectRoot}/greengrass/my-component/vendor/amd64 -r dist/{projectRoot}/greengrass/my-component/vendor/requirements.txt",
126
+ "uv pip install -n --no-deps --no-installer-metadata --no-compile-bytecode --only-binary :all: --python-platform aarch64-manylinux_2_28 --python-version 3.14 --target dist/{projectRoot}/greengrass/my-component/vendor/aarch64 -r dist/{projectRoot}/greengrass/my-component/vendor/requirements.txt"
127
+ ],
128
+ "parallel": false
129
+ }
130
+ }
131
+ }
132
+ }
133
+ ",
134
+ "apps/test_project/tests/greengrass/test_my_component.py": "import importlib.util
135
+ from pathlib import Path
136
+
137
+ # main.py lives beside recipe.yaml under greengrass/<component>/, outside this
138
+ # project's importable package, so it is loaded directly by file path.
139
+ PROJECT_ROOT = Path(__file__).resolve().parents[2]
140
+ MAIN_PATH = PROJECT_ROOT / "greengrass" / "my-component" / "main.py"
141
+
142
+
143
+ def _load_main():
144
+ spec = importlib.util.spec_from_file_location("my_component_main", MAIN_PATH)
145
+ assert spec is not None and spec.loader is not None
146
+ module = importlib.util.module_from_spec(spec)
147
+ spec.loader.exec_module(module)
148
+ return module
149
+
150
+
151
+ def test_run_once_does_not_raise():
152
+ module = _load_main()
153
+ module.run_once(1)
154
+ ",
155
+ "packages/common/scripts/project.json": "{
156
+ "name": "@proj/common-scripts",
157
+ "$schema": "../../../node_modules/nx/schemas/project-schema.json",
158
+ "sourceRoot": "packages/common/scripts/src",
159
+ "projectType": "library",
160
+ "tags": [],
161
+ "metadata": {
162
+ "generator": "ts#project"
163
+ },
164
+ "targets": {
165
+ "assemble": {
166
+ "dependsOn": ["compile"]
167
+ },
168
+ "build": {
169
+ "dependsOn": ["lint", "compile", "test"]
170
+ },
171
+ "compile": {
172
+ "executor": "nx:run-commands",
173
+ "outputs": ["{workspaceRoot}/dist/{projectRoot}/tsc"],
174
+ "options": {
175
+ "command": "tsc --build tsconfig.lib.json",
176
+ "cwd": "{projectRoot}"
177
+ }
178
+ },
179
+ "format": {
180
+ "executor": "nx:run-commands",
181
+ "cache": true,
182
+ "inputs": ["biome"],
183
+ "options": {
184
+ "command": "biome format {projectRoot}"
185
+ },
186
+ "configurations": {
187
+ "fix": {
188
+ "command": "biome format --write {projectRoot}"
189
+ },
190
+ "skip-lint": {
191
+ "command": "node -e \\"\\""
192
+ }
193
+ }
194
+ },
195
+ "lint": {
196
+ "executor": "nx:run-commands",
197
+ "cache": true,
198
+ "inputs": ["biome"],
199
+ "dependsOn": ["format"],
200
+ "options": {
201
+ "command": "biome lint {projectRoot}"
202
+ },
203
+ "configurations": {
204
+ "fix": {
205
+ "command": "biome check --write {projectRoot}"
206
+ },
207
+ "skip-lint": {
208
+ "command": "node -e \\"\\""
209
+ }
210
+ }
211
+ }
212
+ }
213
+ }
214
+ ",
215
+ "pnpm-workspace.yaml": "packages:
216
+ - packages/*
217
+ - packages/common/*
218
+ catalog:
219
+ '@types/node': 26.6.5
220
+ vite: 8.3.4
221
+ vitest: 5.0.4
222
+ '@vitest/coverage-v8': 5.0.4
223
+ jsdom: 29.1.1
224
+ '@nx/vitest': 23.3.0
225
+ js-yaml: 4.3.2
226
+ '@types/js-yaml': 4.0.9
227
+ tsx: 4.23.15
228
+ shx: 0.4.0
229
+ ",
230
+ }
231
+ `;
232
+
233
+ exports[`greengrass#component generator (python) > should match snapshot > main-snapshot 1`] = `
234
+ {
235
+ "apps/test_project/greengrass/my-component/main.py": "import logging
236
+ import time
237
+
238
+ logging.basicConfig(level=logging.INFO)
239
+ logger = logging.getLogger("com.proj.MyComponent")
240
+
241
+ RUN_INTERVAL_SECONDS = 30
242
+
243
+
244
+ def run_once(sequence: int) -> None:
245
+ logger.info("com.proj.MyComponent heartbeat %s", sequence)
246
+
247
+
248
+ def main() -> None:
249
+ sequence = 0
250
+ while True:
251
+ run_once(sequence)
252
+ sequence += 1
253
+ time.sleep(RUN_INTERVAL_SECONDS)
254
+
255
+
256
+ if __name__ == "__main__":
257
+ main()
258
+ ",
259
+ "apps/test_project/greengrass/my-component/recipe.yaml": "RecipeFormatVersion: '2020-01-25'
260
+ ComponentName: com.proj.MyComponent
261
+ ComponentVersion: 1.0.0
262
+ ComponentDescription: com.proj.MyComponent Greengrass component using Python 3.14, generated by greengrass#component.
263
+ ComponentPublisher: proj
264
+ Manifests:
265
+ - Platform:
266
+ os: linux
267
+ architecture: aarch64
268
+ Artifacts:
269
+ # Placeholders are substituted at publish time. The basename must stay
270
+ # my-component.zip, which is what the Run script below unarchives to.
271
+ - Uri: s3://BUCKET_NAME/COMPONENT_NAME/COMPONENT_VERSION/my-component.zip
272
+ Unarchive: ZIP
273
+ Lifecycle:
274
+ Run: python3.14 {artifacts:decompressedPath}/my-component/main.py
275
+ ",
276
+ "apps/test_project/project.json": "{
277
+ "name": "test-project",
278
+ "$schema": "../../node_modules/nx/schemas/project-schema.json",
279
+ "sourceRoot": "apps/test_project/test_project",
280
+ "metadata": {
281
+ "components": [
282
+ {
283
+ "generator": "greengrass#component",
284
+ "path": "greengrass/my-component/main.py",
285
+ "name": "my-component",
286
+ "language": "python",
287
+ "componentName": "com.proj.MyComponent",
288
+ "componentVersion": "1.0.0",
289
+ "platform": "linux-arm64",
290
+ "ipc": false,
291
+ "gdkConfig": false
292
+ }
293
+ ]
294
+ },
295
+ "targets": {
296
+ "assemble": {
297
+ "dependsOn": ["my-component-artifact"]
298
+ },
299
+ "build": {
300
+ "dependsOn": ["my-component-artifact"]
301
+ },
302
+ "my-component-artifact": {
303
+ "executor": "nx:run-commands",
304
+ "dependsOn": ["my-component-vendor"],
305
+ "cache": true,
306
+ "inputs": [
307
+ "production",
308
+ "^production",
309
+ "{workspaceRoot}/packages/common/scripts/src/greengrass/**/*"
310
+ ],
311
+ "outputs": [
312
+ "{workspaceRoot}/dist/{projectRoot}/greengrass/my-component/greengrass-build"
313
+ ],
314
+ "options": {
315
+ "command": "tsx packages/common/scripts/src/greengrass/build-artifact.ts {projectRoot} my-component dist/{projectRoot}/greengrass/my-component"
316
+ }
317
+ },
318
+ "my-component-deploy-local": {
319
+ "executor": "nx:run-commands",
320
+ "dependsOn": ["my-component-artifact"],
321
+ "options": {
322
+ "command": "tsx packages/common/scripts/src/greengrass/deploy-local.ts dist/{projectRoot}/greengrass/my-component"
323
+ }
324
+ },
325
+ "my-component-logs": {
326
+ "executor": "nx:run-commands",
327
+ "continuous": true,
328
+ "options": {
329
+ "command": "tsx packages/common/scripts/src/greengrass/component-logs.ts com.proj.MyComponent"
330
+ }
331
+ },
332
+ "my-component-vendor": {
333
+ "executor": "nx:run-commands",
334
+ "dependsOn": ["compile"],
335
+ "cache": true,
336
+ "inputs": ["production", "^production"],
337
+ "outputs": [
338
+ "{workspaceRoot}/dist/{projectRoot}/greengrass/my-component/vendor"
339
+ ],
340
+ "options": {
341
+ "commands": [
342
+ "shx rm -rf dist/{projectRoot}/greengrass/my-component/vendor",
343
+ "shx mkdir -p dist/{projectRoot}/greengrass/my-component/vendor",
344
+ "uv export --frozen --no-dev --no-editable --no-emit-project --project {projectRoot} --package test-project -o dist/{projectRoot}/greengrass/my-component/vendor/requirements.txt",
345
+ "uv pip install -n --no-deps --no-installer-metadata --no-compile-bytecode --only-binary :all: --python-platform aarch64-manylinux_2_28 --python-version 3.14 --target dist/{projectRoot}/greengrass/my-component/vendor -r dist/{projectRoot}/greengrass/my-component/vendor/requirements.txt"
346
+ ],
347
+ "parallel": false
348
+ }
349
+ }
350
+ }
351
+ }
352
+ ",
353
+ "apps/test_project/tests/greengrass/test_my_component.py": "import importlib.util
354
+ from pathlib import Path
355
+
356
+ # main.py lives beside recipe.yaml under greengrass/<component>/, outside this
357
+ # project's importable package, so it is loaded directly by file path.
358
+ PROJECT_ROOT = Path(__file__).resolve().parents[2]
359
+ MAIN_PATH = PROJECT_ROOT / "greengrass" / "my-component" / "main.py"
360
+
361
+
362
+ def _load_main():
363
+ spec = importlib.util.spec_from_file_location("my_component_main", MAIN_PATH)
364
+ assert spec is not None and spec.loader is not None
365
+ module = importlib.util.module_from_spec(spec)
366
+ spec.loader.exec_module(module)
367
+ return module
368
+
369
+
370
+ def test_run_once_does_not_raise():
371
+ module = _load_main()
372
+ module.run_once(1)
373
+ ",
374
+ "packages/common/scripts/project.json": "{
375
+ "name": "@proj/common-scripts",
376
+ "$schema": "../../../node_modules/nx/schemas/project-schema.json",
377
+ "sourceRoot": "packages/common/scripts/src",
378
+ "projectType": "library",
379
+ "tags": [],
380
+ "metadata": {
381
+ "generator": "ts#project"
382
+ },
383
+ "targets": {
384
+ "assemble": {
385
+ "dependsOn": ["compile"]
386
+ },
387
+ "build": {
388
+ "dependsOn": ["lint", "compile", "test"]
389
+ },
390
+ "compile": {
391
+ "executor": "nx:run-commands",
392
+ "outputs": ["{workspaceRoot}/dist/{projectRoot}/tsc"],
393
+ "options": {
394
+ "command": "tsc --build tsconfig.lib.json",
395
+ "cwd": "{projectRoot}"
396
+ }
397
+ },
398
+ "format": {
399
+ "executor": "nx:run-commands",
400
+ "cache": true,
401
+ "inputs": ["biome"],
402
+ "options": {
403
+ "command": "biome format {projectRoot}"
404
+ },
405
+ "configurations": {
406
+ "fix": {
407
+ "command": "biome format --write {projectRoot}"
408
+ },
409
+ "skip-lint": {
410
+ "command": "node -e \\"\\""
411
+ }
412
+ }
413
+ },
414
+ "lint": {
415
+ "executor": "nx:run-commands",
416
+ "cache": true,
417
+ "inputs": ["biome"],
418
+ "dependsOn": ["format"],
419
+ "options": {
420
+ "command": "biome lint {projectRoot}"
421
+ },
422
+ "configurations": {
423
+ "fix": {
424
+ "command": "biome check --write {projectRoot}"
425
+ },
426
+ "skip-lint": {
427
+ "command": "node -e \\"\\""
428
+ }
429
+ }
430
+ }
431
+ }
432
+ }
433
+ ",
434
+ "pnpm-workspace.yaml": "packages:
435
+ - packages/*
436
+ - packages/common/*
437
+ catalog:
438
+ '@types/node': 26.6.5
439
+ vite: 8.3.4
440
+ vitest: 5.0.4
441
+ '@vitest/coverage-v8': 5.0.4
442
+ jsdom: 29.1.1
443
+ '@nx/vitest': 23.3.0
444
+ js-yaml: 4.3.2
445
+ '@types/js-yaml': 4.0.9
446
+ tsx: 4.23.15
447
+ shx: 0.4.0
448
+ ",
449
+ }
450
+ `;
@@ -0,0 +1,60 @@
1
+ <%_ if (ipc) { _%>
2
+ import logging
3
+ import time
4
+
5
+ from awsiot.greengrasscoreipc.clientv2 import GreengrassCoreIPCClientV2
6
+ from awsiot.greengrasscoreipc.model import JsonMessage, PublishMessage
7
+
8
+ logging.basicConfig(level=logging.INFO)
9
+ logger = logging.getLogger("<%- componentName %>")
10
+
11
+ TOPIC = "<%- componentName %>/heartbeat"
12
+ PUBLISH_INTERVAL_SECONDS = 30
13
+
14
+
15
+ def publish_heartbeat(client: GreengrassCoreIPCClientV2, sequence: int) -> None:
16
+ client.publish_to_topic(
17
+ topic=TOPIC,
18
+ publish_message=PublishMessage(
19
+ json_message=JsonMessage(message={"sequence": sequence})
20
+ ),
21
+ )
22
+ logger.info("Published heartbeat %s to %s", sequence, TOPIC)
23
+
24
+
25
+ def main() -> None:
26
+ client = GreengrassCoreIPCClientV2()
27
+ sequence = 0
28
+ while True:
29
+ publish_heartbeat(client, sequence)
30
+ sequence += 1
31
+ time.sleep(PUBLISH_INTERVAL_SECONDS)
32
+
33
+
34
+ if __name__ == "__main__":
35
+ main()
36
+ <%_ } else { _%>
37
+ import logging
38
+ import time
39
+
40
+ logging.basicConfig(level=logging.INFO)
41
+ logger = logging.getLogger("<%- componentName %>")
42
+
43
+ RUN_INTERVAL_SECONDS = 30
44
+
45
+
46
+ def run_once(sequence: int) -> None:
47
+ logger.info("<%- componentName %> heartbeat %s", sequence)
48
+
49
+
50
+ def main() -> None:
51
+ sequence = 0
52
+ while True:
53
+ run_once(sequence)
54
+ sequence += 1
55
+ time.sleep(RUN_INTERVAL_SECONDS)
56
+
57
+
58
+ if __name__ == "__main__":
59
+ main()
60
+ <%_ } _%>
@@ -0,0 +1,30 @@
1
+ RecipeFormatVersion: '<%- recipeFormat %>'
2
+ ComponentName: <%- componentName %>
3
+ ComponentVersion: <%- version %>
4
+ ComponentDescription: <%- componentDescription %>
5
+ ComponentPublisher: <%- publisher %>
6
+ <%_ if (ipc) { _%>
7
+ ComponentConfiguration:
8
+ DefaultConfiguration:
9
+ accessControl:
10
+ aws.greengrass.ipc.pubsub:
11
+ <%- componentName %>:pubsub:1:
12
+ policyDescription: Allow publishing heartbeat messages to this component's own topic.
13
+ operations:
14
+ - aws.greengrass#PublishToTopic
15
+ resources:
16
+ - <%- componentName %>/heartbeat
17
+ <%_ } _%>
18
+ Manifests:
19
+ <%_ manifests.forEach((m) => { _%>
20
+ - Platform:
21
+ os: <%- m.os %>
22
+ architecture: <%- m.architecture %>
23
+ Artifacts:
24
+ # Placeholders are substituted at publish time. The basename must stay
25
+ # <%- m.artifactBaseName %>.zip, which is what the Run script below unarchives to.
26
+ - Uri: s3://BUCKET_NAME/COMPONENT_NAME/COMPONENT_VERSION/<%- m.artifactBaseName %>.zip
27
+ Unarchive: ZIP
28
+ Lifecycle:
29
+ Run: python<%- pythonFloor %> {artifacts:decompressedPath}/<%- m.artifactBaseName %>/main.py
30
+ <%_ }); _%>
@@ -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,37 @@
1
+ import importlib.util
2
+ from pathlib import Path
3
+
4
+ # main.py lives beside recipe.yaml under greengrass/<component>/, outside this
5
+ # project's importable package, so it is loaded directly by file path.
6
+ PROJECT_ROOT = Path(__file__).resolve().parents[2]
7
+ MAIN_PATH = PROJECT_ROOT / "greengrass" / "<%- componentDirName %>" / "main.py"
8
+
9
+
10
+ def _load_main():
11
+ spec = importlib.util.spec_from_file_location("<%- componentSnakeCase %>_main", MAIN_PATH)
12
+ assert spec is not None and spec.loader is not None
13
+ module = importlib.util.module_from_spec(spec)
14
+ spec.loader.exec_module(module)
15
+ return module
16
+
17
+ <%_ if (ipc) { _%>
18
+
19
+ def test_publish_heartbeat_publishes_to_own_topic():
20
+ module = _load_main()
21
+ calls = []
22
+
23
+ class FakeClient:
24
+ def publish_to_topic(self, **kwargs):
25
+ calls.append(kwargs)
26
+
27
+ module.publish_heartbeat(FakeClient(), 1)
28
+
29
+ assert len(calls) == 1
30
+ assert calls[0]["topic"] == module.TOPIC
31
+ assert module.TOPIC == "<%- componentName %>/heartbeat"
32
+ <%_ } else { _%>
33
+
34
+ def test_run_once_does_not_raise():
35
+ module = _load_main()
36
+ module.run_once(1)
37
+ <%_ } _%>
@@ -0,0 +1,15 @@
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 Python project:
9
+ * packaging and local-deployment targets (`<c>-vendor`, `<c>-artifact`,
10
+ * `<c>-deploy-local`, `<c>-logs`), plus, unless `--infra none`, a
11
+ * `GreengrassComponentVersion` CDK construct (or Terraform module, via the
12
+ * `hashicorp/awscc` provider) that publishes the built artifact.
13
+ */
14
+ export declare const pythonGreengrassComponentGenerator: (tree: Tree, component: NormalizedComponent) => Promise<GeneratorCallback>;
15
+ export default pythonGreengrassComponentGenerator;