@quadnix/octo 0.1.0 → 0.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 (221) hide show
  1. package/README.md +108 -21
  2. package/dist/app.type.d.ts +141 -22
  3. package/dist/app.type.js.map +1 -1
  4. package/dist/decorators/model.decorator.d.ts +3 -5
  5. package/dist/decorators/model.decorator.js +1 -6
  6. package/dist/decorators/model.decorator.js.map +1 -1
  7. package/dist/decorators/on-event.decorator.d.ts +2 -2
  8. package/dist/decorators/on-event.decorator.js.map +1 -1
  9. package/dist/decorators/resource.decorator.d.ts +50 -1
  10. package/dist/decorators/resource.decorator.js +38 -1
  11. package/dist/decorators/resource.decorator.js.map +1 -1
  12. package/dist/errors/schema.error.d.ts +8 -1
  13. package/dist/errors/schema.error.js +5 -1
  14. package/dist/errors/schema.error.js.map +1 -1
  15. package/dist/errors/terraform.error.d.ts +4 -3
  16. package/dist/errors/terraform.error.js +4 -3
  17. package/dist/errors/terraform.error.js.map +1 -1
  18. package/dist/errors/transaction.error.d.ts +32 -2
  19. package/dist/errors/transaction.error.js +22 -0
  20. package/dist/errors/transaction.error.js.map +1 -1
  21. package/dist/events/action.event.d.ts +8 -2
  22. package/dist/events/action.event.js +2 -2
  23. package/dist/events/action.event.js.map +1 -1
  24. package/dist/events/command.event.d.ts +43 -0
  25. package/dist/events/command.event.js +33 -0
  26. package/dist/events/command.event.js.map +1 -0
  27. package/dist/events/event.model.d.ts +7 -5
  28. package/dist/events/event.model.js +5 -3
  29. package/dist/events/event.model.js.map +1 -1
  30. package/dist/events/hook/commit.hook.event.d.ts +1 -1
  31. package/dist/events/hook/commit.hook.event.js.map +1 -1
  32. package/dist/events/hook/hook.event.d.ts +1 -1
  33. package/dist/events/hook/hook.event.js.map +1 -1
  34. package/dist/events/hook/model.hook.event.d.ts +1 -1
  35. package/dist/events/hook/model.hook.event.js.map +1 -1
  36. package/dist/events/hook/resource.hook.event.d.ts +1 -1
  37. package/dist/events/hook/resource.hook.event.js.map +1 -1
  38. package/dist/events/index.d.ts +2 -0
  39. package/dist/events/index.js +2 -0
  40. package/dist/events/index.js.map +1 -1
  41. package/dist/events/mode-result.event.d.ts +1 -1
  42. package/dist/events/mode-result.event.js.map +1 -1
  43. package/dist/events/mode.event.d.ts +8 -4
  44. package/dist/events/mode.event.js.map +1 -1
  45. package/dist/events/module.event.d.ts +7 -3
  46. package/dist/events/module.event.js +3 -2
  47. package/dist/events/module.event.js.map +1 -1
  48. package/dist/events/registration.event.d.ts +1 -1
  49. package/dist/events/registration.event.js.map +1 -1
  50. package/dist/events/serialization.event.d.ts +1 -1
  51. package/dist/events/serialization.event.js.map +1 -1
  52. package/dist/events/state.event.d.ts +102 -0
  53. package/dist/events/state.event.js +69 -0
  54. package/dist/events/state.event.js.map +1 -0
  55. package/dist/events/terraform.event.d.ts +37 -1
  56. package/dist/events/terraform.event.js +24 -0
  57. package/dist/events/terraform.event.js.map +1 -1
  58. package/dist/events/transaction.event.d.ts +3 -3
  59. package/dist/events/transaction.event.js +1 -1
  60. package/dist/events/transaction.event.js.map +1 -1
  61. package/dist/functions/container/container.js +1 -1
  62. package/dist/functions/container/container.js.map +1 -1
  63. package/dist/functions/container/test-container.js +2 -2
  64. package/dist/functions/container/test-container.js.map +1 -1
  65. package/dist/functions/dependency/dependency.d.ts +9 -22
  66. package/dist/functions/dependency/dependency.js +5 -1
  67. package/dist/functions/dependency/dependency.js.map +1 -1
  68. package/dist/functions/diff/diff.d.ts +14 -7
  69. package/dist/functions/diff/diff.js.map +1 -1
  70. package/dist/functions/node/node-action.abstract.d.ts +8 -10
  71. package/dist/functions/node/node-action.abstract.js +10 -16
  72. package/dist/functions/node/node-action.abstract.js.map +1 -1
  73. package/dist/functions/node/node.abstract.js +21 -10
  74. package/dist/functions/node/node.abstract.js.map +1 -1
  75. package/dist/functions/node/node.interface.d.ts +2 -1
  76. package/dist/functions/schema/schema.js +1 -1
  77. package/dist/functions/schema/schema.js.map +1 -1
  78. package/dist/index.d.ts +8 -6
  79. package/dist/index.js +6 -4
  80. package/dist/index.js.map +1 -1
  81. package/dist/index.type.d.ts +5 -0
  82. package/dist/index.type.js +2 -0
  83. package/dist/index.type.js.map +1 -0
  84. package/dist/main.d.ts +4 -3
  85. package/dist/main.js +27 -11
  86. package/dist/main.js.map +1 -1
  87. package/dist/models/account/account.model.d.ts +6 -0
  88. package/dist/models/account/account.model.js +16 -0
  89. package/dist/models/account/account.model.js.map +1 -1
  90. package/dist/models/app/app.model.d.ts +0 -10
  91. package/dist/models/app/app.model.js +0 -30
  92. package/dist/models/app/app.model.js.map +1 -1
  93. package/dist/models/deployment/deployment.schema.d.ts +4 -0
  94. package/dist/models/deployment/deployment.schema.js +4 -0
  95. package/dist/models/deployment/deployment.schema.js.map +1 -1
  96. package/dist/models/environment/environment.model.d.ts +2 -2
  97. package/dist/models/environment/environment.model.js +2 -2
  98. package/dist/models/execution/execution.model.d.ts +1 -1
  99. package/dist/models/execution/execution.model.js +1 -1
  100. package/dist/models/image/image.model.d.ts +4 -3
  101. package/dist/models/image/image.model.js +7 -6
  102. package/dist/models/image/image.model.js.map +1 -1
  103. package/dist/models/model.abstract.js +1 -1
  104. package/dist/models/model.abstract.js.map +1 -1
  105. package/dist/models/pipeline/pipeline.model.d.ts +1 -1
  106. package/dist/models/pipeline/pipeline.model.js +1 -1
  107. package/dist/models/server/server.model.d.ts +2 -2
  108. package/dist/models/server/server.model.js +2 -2
  109. package/dist/models/service/service.model.d.ts +28 -11
  110. package/dist/models/service/service.model.js +56 -16
  111. package/dist/models/service/service.model.js.map +1 -1
  112. package/dist/models/service/service.schema.d.ts +46 -2
  113. package/dist/models/service/service.schema.js +54 -2
  114. package/dist/models/service/service.schema.js.map +1 -1
  115. package/dist/modes/commit.mode.d.ts +2 -2
  116. package/dist/modes/commit.mode.js +2 -2
  117. package/dist/modes/generate.mode.d.ts +2 -1
  118. package/dist/modes/generate.mode.js +3 -2
  119. package/dist/modes/generate.mode.js.map +1 -1
  120. package/dist/modes/run-action.mode.d.ts +1 -1
  121. package/dist/modes/run-action.mode.js +1 -1
  122. package/dist/modes/validate.mode.d.ts +24 -0
  123. package/dist/modes/validate.mode.js +89 -11
  124. package/dist/modes/validate.mode.js.map +1 -1
  125. package/dist/modules/module.container.d.ts +7 -1
  126. package/dist/modules/module.container.js +41 -5
  127. package/dist/modules/module.container.js.map +1 -1
  128. package/dist/modules/test-module.container.js +35 -83
  129. package/dist/modules/test-module.container.js.map +1 -1
  130. package/dist/overlays/overlay.abstract.js +1 -1
  131. package/dist/overlays/overlay.abstract.js.map +1 -1
  132. package/dist/resources/resource-action.interface.d.ts +4 -2
  133. package/dist/resources/resource.abstract.d.ts +50 -8
  134. package/dist/resources/resource.abstract.js +63 -32
  135. package/dist/resources/resource.abstract.js.map +1 -1
  136. package/dist/resources/resource.interface.d.ts +0 -2
  137. package/dist/resources/resource.schema.d.ts +11 -1
  138. package/dist/resources/resource.schema.js +11 -1
  139. package/dist/resources/resource.schema.js.map +1 -1
  140. package/dist/services/event/event.service.d.ts +2 -2
  141. package/dist/services/event/event.service.js.map +1 -1
  142. package/dist/services/input/input.service.d.ts +30 -2
  143. package/dist/services/input/input.service.js +71 -4
  144. package/dist/services/input/input.service.js.map +1 -1
  145. package/dist/services/serialization/model/model-serialization.service.d.ts +4 -6
  146. package/dist/services/serialization/model/model-serialization.service.js +20 -17
  147. package/dist/services/serialization/model/model-serialization.service.js.map +1 -1
  148. package/dist/services/serialization/resource/resource-serialization.service.d.ts +7 -6
  149. package/dist/services/serialization/resource/resource-serialization.service.js +25 -12
  150. package/dist/services/serialization/resource/resource-serialization.service.js.map +1 -1
  151. package/dist/services/state-management/local.state-provider.d.ts +25 -9
  152. package/dist/services/state-management/local.state-provider.js +127 -21
  153. package/dist/services/state-management/local.state-provider.js.map +1 -1
  154. package/dist/services/state-management/remote.state-provider.d.ts +216 -0
  155. package/dist/services/state-management/remote.state-provider.js +645 -0
  156. package/dist/services/state-management/remote.state-provider.js.map +1 -0
  157. package/dist/services/state-management/state-management.service.d.ts +83 -40
  158. package/dist/services/state-management/state-management.service.js +130 -26
  159. package/dist/services/state-management/state-management.service.js.map +1 -1
  160. package/dist/services/state-management/state-provider.interface.d.ts +50 -9
  161. package/dist/services/state-management/state-provider.interface.js +14 -1
  162. package/dist/services/state-management/state-provider.interface.js.map +1 -1
  163. package/dist/services/state-management/terraform-state.service.d.ts +32 -9
  164. package/dist/services/state-management/terraform-state.service.js +64 -21
  165. package/dist/services/state-management/terraform-state.service.js.map +1 -1
  166. package/dist/services/state-management/test.state-provider.d.ts +11 -10
  167. package/dist/services/state-management/test.state-provider.js +35 -14
  168. package/dist/services/state-management/test.state-provider.js.map +1 -1
  169. package/dist/services/terraform/terraform.service.d.ts +57 -3
  170. package/dist/services/terraform/terraform.service.js +95 -8
  171. package/dist/services/terraform/terraform.service.js.map +1 -1
  172. package/dist/services/terraform/terraform.type.js +1 -1
  173. package/dist/services/terraform/terraform.type.js.map +1 -1
  174. package/dist/services/transaction/transaction.service.d.ts +29 -5
  175. package/dist/services/transaction/transaction.service.js +198 -34
  176. package/dist/services/transaction/transaction.service.js.map +1 -1
  177. package/dist/services/validation/validation.service.d.ts +2 -2
  178. package/dist/{functions → utilities}/diff/diff.utility.d.ts +2 -1
  179. package/dist/{functions → utilities}/diff/diff.utility.js +4 -3
  180. package/dist/utilities/diff/diff.utility.js.map +1 -0
  181. package/dist/utilities/file/file.utility.d.ts +6 -7
  182. package/dist/utilities/file/file.utility.js +13 -68
  183. package/dist/utilities/file/file.utility.js.map +1 -1
  184. package/dist/utilities/hcl/hcl.utility.d.ts +83 -16
  185. package/dist/utilities/hcl/hcl.utility.js +200 -27
  186. package/dist/utilities/hcl/hcl.utility.js.map +1 -1
  187. package/dist/utilities/http/http.utility.d.ts +57 -0
  188. package/dist/utilities/http/http.utility.js +98 -0
  189. package/dist/utilities/http/http.utility.js.map +1 -0
  190. package/dist/utilities/string/string.utility.d.ts +23 -3
  191. package/dist/utilities/string/string.utility.js +29 -3
  192. package/dist/utilities/string/string.utility.js.map +1 -1
  193. package/dist/utilities/terraform/terraform.utility.d.ts +70 -21
  194. package/dist/utilities/terraform/terraform.utility.js +255 -66
  195. package/dist/utilities/terraform/terraform.utility.js.map +1 -1
  196. package/dist/utilities/test-helpers/test-classes.d.ts +19 -0
  197. package/dist/utilities/test-helpers/test-classes.js +22 -0
  198. package/dist/utilities/test-helpers/test-classes.js.map +1 -1
  199. package/dist/utilities/test-helpers/test-models.d.ts +8 -1
  200. package/dist/utilities/test-helpers/test-models.js +25 -12
  201. package/dist/utilities/test-helpers/test-models.js.map +1 -1
  202. package/dist/utilities/test-helpers/test-modes.d.ts +1 -1
  203. package/dist/utilities/test-helpers/test-modes.js +36 -13
  204. package/dist/utilities/test-helpers/test-modes.js.map +1 -1
  205. package/dist/utilities/test-helpers/test-modules.d.ts +6 -0
  206. package/dist/utilities/test-helpers/test-modules.js +6 -0
  207. package/dist/utilities/test-helpers/test-modules.js.map +1 -1
  208. package/dist/utilities/test-helpers/test-overlays.d.ts +3 -1
  209. package/dist/utilities/test-helpers/test-overlays.js +8 -2
  210. package/dist/utilities/test-helpers/test-overlays.js.map +1 -1
  211. package/dist/utilities/test-helpers/test-resources.d.ts +4 -2
  212. package/dist/utilities/test-helpers/test-resources.js +22 -20
  213. package/dist/utilities/test-helpers/test-resources.js.map +1 -1
  214. package/package.json +7 -2
  215. package/dist/functions/diff/diff.utility.js.map +0 -1
  216. package/dist/services/state-management/file-app-lock.utility.d.ts +0 -43
  217. package/dist/services/state-management/file-app-lock.utility.js +0 -124
  218. package/dist/services/state-management/file-app-lock.utility.js.map +0 -1
  219. package/dist/services/state-management/local-encryption.state-provider.d.ts +0 -71
  220. package/dist/services/state-management/local-encryption.state-provider.js +0 -116
  221. package/dist/services/state-management/local-encryption.state-provider.js.map +0 -1
package/README.md CHANGED
@@ -1,35 +1,122 @@
1
1
  # Octo
2
2
 
3
- https://octo.quadnix.com/
3
+ Infrastructure as code written as intent: you describe an app and what it needs, modules turn that
4
+ into Terraform, and your own Terragrunt applies it. Users start at
5
+ [octo.quadnix.com](https://octo.quadnix.com/).
4
6
 
5
- The open-source infrastructure management and CICD tool.
7
+ > Octo is in `0.x`. Version `1.x` will mark it ready for production.
6
8
 
7
- > Disclaimer,
8
- > This library is still under development and is currently in version `0.x.x`.
9
- > We plan to release version `1.x.x` when it is deemed ready for production use.
9
+ **This README is a set of procedures for working on the repository.** `docs/ARCHITECTURE.md`
10
+ explains what exists, and `docs/CODING-STANDARDS.md` how to add to it.
10
11
 
11
- # Local Setup
12
+ Requires Node 20 or newer, Terraform or OpenTofu 1.6 or newer, and Terragrunt 0.78 or newer. The
13
+ integration suites also need Docker, and the e2e suites AWS credentials.
12
14
 
13
- ## Prerequisites
15
+ ---
14
16
 
15
- - [Node.js](https://nodejs.org) 22 (LTS). This ships with Corepack, which provisions the
16
- exact package manager the project expects — you do **not** need to install pnpm yourself.
17
+ ## A — Set up this machine
17
18
 
18
- ## Install
19
-
20
- This repository is a [pnpm](https://pnpm.io) workspace. Corepack reads the `packageManager`
21
- field in the root `package.json` and uses the pnpm version pinned there, so everyone (and CI)
22
- runs the same version.
19
+ Once.
23
20
 
24
21
  ```sh
25
- # One-time per machine: activate Corepack so the `pnpm` command uses the pinned version.
26
22
  corepack enable
27
-
28
- # Install all workspace dependencies (packages/*).
29
23
  pnpm install
24
+ pnpm run prepare
30
25
  ```
31
26
 
32
- > **Note:** The documentation site under `apps/octo-docs` is an intentionally separate
33
- > project — it consumes the published `@quadnix/*` packages from the registry rather than the
34
- > local source. It is not part of the root workspace and is only installed (with its own
35
- > `pnpm install`, run from inside that directory) when you are working on the docs.
27
+ `prepare` installs the pre-commit hook, which runs the format check, lint, the build with its type
28
+ check, the circular-dependency check, the secrets spec and the docs code-block check.
29
+
30
+ ## B — Build, lint and test
31
+
32
+ ```sh
33
+ pnpm run build
34
+ pnpm run lint
35
+ pnpm test
36
+ ```
37
+
38
+ `octo-aws-cdk`, `octo-event-listeners`, `octo-build` and `octo-templates` import `octo` from its
39
+ `dist`, and `octo-templates` imports `octo-aws-cdk` the same way. **Rebuild what you changed before
40
+ testing what depends on it**, or the suite runs against the old code and still passes.
41
+
42
+ `pnpm run build` also type-checks every package, tests included, through each package's
43
+ `check:types`.
44
+
45
+ `pnpm run format` writes what `pnpm run format:check` checks. Lint does not check formatting.
46
+
47
+ `pnpm run lint:fix` sorts imports, members and keys. A flag passed through `pnpm run` is written
48
+ without `--`: pnpm forwards the separator, and the script then drops the flag.
49
+
50
+ ## C — Run integration tests
51
+
52
+ Integration specs run real Terraform; `octo-templates`' start LocalStack in Docker.
53
+
54
+ ```sh
55
+ pnpm run test:integration
56
+ ```
57
+
58
+ ## D — Run an e2e suite
59
+
60
+ **Every e2e suite reaches a live AWS account.** `octo-aws-cdk`'s plan and apply nothing;
61
+ `octo-templates`' create real resources and tear them down.
62
+
63
+ 1. Copy the `.env.defaults` beside the suite to `.env` and fill in real values. `.env` is ignored.
64
+ 2. Build the packages the suite imports:
65
+
66
+ ```sh
67
+ npx nx run-many -t build --projects=octo,octo-event-listeners,octo-aws-cdk
68
+ ```
69
+
70
+ 3. Run one spec, by path, from its package:
71
+
72
+ ```sh
73
+ cd packages/octo-templates
74
+ NODE_OPTIONS=--experimental-vm-modules npx jest --runTestsByPath src/<template>/main.e2e-spec.ts
75
+ ```
76
+
77
+ Never `pnpm run test:e2e` — it runs every suite live at once. Never combine `-u` with `-t`: jest then
78
+ deletes the snapshots of every test it skipped. A template's own `README.md`, where it has one,
79
+ holds what is particular to it.
80
+
81
+ ## E — Work in a worktree
82
+
83
+ For a large change or a hands-free agent run:
84
+
85
+ ```sh
86
+ git worktree add ../ai-worktrees/octo-worktree-<branch> -b ai/<branch>
87
+ WORKTREE=../ai-worktrees/octo-worktree-<branch>
88
+ find . -maxdepth 4 -name node_modules -type d ! -path "*/node_modules/*/node_modules" | \
89
+ while read src; do
90
+ mkdir -p "$WORKTREE/$(dirname $src)"
91
+ ln -s "$(pwd)/$src" "$WORKTREE/$src"
92
+ done
93
+ ```
94
+
95
+ The symlinks let Nx and Jest resolve packages. Run lint and tests from inside the worktree.
96
+
97
+ ## F — Release
98
+
99
+ 1. Merge to `main` with PR titles per `.github/jobs/validate-pr-title.job.sh`. The commit type sets
100
+ the bump: `chore` releases nothing.
101
+ 2. Run the **Manual Release** workflow on `main`. It versions every changed package, tags, writes
102
+ the changelog, and publishes to npm.
103
+
104
+ ## Environment variables
105
+
106
+ Everything outside the code that governs how this repository behaves. A suite's `.env` is read
107
+ through `env-smart`, falling back to the `.env.defaults` beside it.
108
+
109
+ | Variable | Set by | What it does |
110
+ |-----------------------------------------------------------------------------------------------------|-----------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
111
+ | `AWS_ACCOUNT_ID` | a suite's `.env` | The account every e2e suite plans or applies into. |
112
+ | `AWS_REGION_ID` | `packages/octo-aws-cdk/test/.env` | The region the module e2es plan into. Template suites hardcode `us-east-1`. |
113
+ | `OCTO_DEFINITION_FILE_PATH` | the user, or a `create-app` project's scripts | The `octo.yaml` every lifecycle command boots from. `OctoCliUtility` sets it for the CLI-driven template suites. A relative path is resolved once against the working directory, so `run-action` callbacks find it. |
114
+ | `OCTO_JOURNAL_COMMAND_ID` | `JournalEventListener` | The running command's id, set for every process it starts, so a `run-action` that Terraform starts mid-apply names that apply as `parentCommandId` in its journal. |
115
+ | `TF_VAR_OCTO_PROJECT_ROOT` | `TerraformUtility`, unless already set | The working directory, so `terraform.localPath()` paths resolve inside Terragrunt's cache copy of a folder. |
116
+ | `TG_LOG_CUSTOM_FORMAT` | `TerraformUtility`, always | Terragrunt's log line layout, its default without the time, since the journal records when each line arrived. |
117
+ | `TG_LOG_FORMAT` | `TerraformUtility`, always unset | Unset for every Terragrunt process, so it cannot override `TG_LOG_CUSTOM_FORMAT`. |
118
+ | `TG_PROVIDER_CACHE` | `TerraformUtility`, unless already set | `1`, so Terragrunt shares one provider cache across folders. |
119
+ | `TG_TF_PATH` | `TerraformUtility`, from `--terraformBinary` | Which Terraform or OpenTofu binary Terragrunt runs. |
120
+ | `NODE_OPTIONS` | every package's test scripts | `--experimental-vm-modules`, which Jest needs to run ESM. Set it yourself when running `jest` directly. |
121
+ | `OCTO_STAGE`, `OCTO_PHASE`, `OCTO_NAT`, `OCTO_TARGET`, `OCTO_WORK`, `OCTO_CASE`, `OCTO_PROBE_STATE` | you, by hand | Drive the `aws-ecs-server` debugging harnesses; that template's `README.md` describes each. |
122
+ | `GH_TOKEN` | a repository secret | Checkout and push in **Manual Release**, and the tags and GitHub releases `nx release` creates. |
@@ -1,8 +1,20 @@
1
1
  import type { IDependency } from './functions/dependency/dependency.js';
2
2
  import type { ANode } from './functions/node/node.abstract.js';
3
+ import type { AccountSchema } from './models/account/account.schema.js';
4
+ import type { AppSchema } from './models/app/app.schema.js';
5
+ import type { DeploymentSchema } from './models/deployment/deployment.schema.js';
6
+ import type { EnvironmentSchema } from './models/environment/environment.schema.js';
7
+ import type { ExecutionSchema } from './models/execution/execution.schema.js';
8
+ import type { FilesystemSchema } from './models/filesystem/filesystem.schema.js';
9
+ import type { ImageSchema } from './models/image/image.schema.js';
3
10
  import type { IModelAction } from './models/model-action.interface.js';
4
11
  import type { AModel } from './models/model.abstract.js';
5
- import type { IModel, IModelReference } from './models/model.interface.js';
12
+ import type { IModel } from './models/model.interface.js';
13
+ import type { PipelineSchema } from './models/pipeline/pipeline.schema.js';
14
+ import type { RegionSchema } from './models/region/region.schema.js';
15
+ import type { ServerSchema } from './models/server/server.schema.js';
16
+ import type { ServiceSchema } from './models/service/service.schema.js';
17
+ import type { SubnetSchema } from './models/subnet/subnet.schema.js';
6
18
  import type { AModule } from './modules/module.abstract.js';
7
19
  import type { AAnchor } from './overlays/anchor.abstract.js';
8
20
  import type { BaseAnchorSchema } from './overlays/anchor.schema.js';
@@ -230,42 +242,136 @@ export type ObjectKeyValue<T> = {
230
242
  */
231
243
  export type Constructable<T> = new (...args: any[]) => T;
232
244
  /**
233
- * The model graph as written to state.
245
+ * A class of `T`, abstract or not, i.e. what you pass to name a family of classes.
246
+ *
247
+ * @group Types
248
+ */
249
+ export type AbstractConstructable<T> = abstract new (...args: any[]) => T;
250
+ /**
251
+ * An anchor as written to state.
252
+ *
253
+ * @group Types
254
+ */
255
+ export type AnchorSerializedOutput = {
256
+ anchorId: string;
257
+ parent: {
258
+ context: string;
259
+ type: `${NodeType}`;
260
+ };
261
+ properties: {
262
+ [key: string]: unknown;
263
+ };
264
+ };
265
+ /**
266
+ * The schema of each base model, by the name it registers with `@Model`.
267
+ */
268
+ type BaseModelSchemas = {
269
+ account: AccountSchema;
270
+ app: AppSchema;
271
+ deployment: DeploymentSchema;
272
+ environment: EnvironmentSchema;
273
+ execution: ExecutionSchema;
274
+ filesystem: FilesystemSchema;
275
+ image: ImageSchema;
276
+ pipeline: PipelineSchema;
277
+ region: RegionSchema;
278
+ server: ServerSchema;
279
+ service: ServiceSchema;
280
+ subnet: SubnetSchema;
281
+ };
282
+ /**
283
+ * @internal
284
+ */
285
+ export type ModelName = keyof BaseModelSchemas;
286
+ /**
287
+ * The model graph as written to `models.json`.
288
+ * * `nodeName` names the base model an entry extends, and types its `model` as that base model's
289
+ * schema. A model's own fields beyond it are not typed.
290
+ * * `modules` record inputs before references resolve.
234
291
  *
235
292
  * @group Types
236
293
  */
237
294
  export type ModelSerializedOutput = {
238
- anchors: (AnchorSchema<UnknownAnchor> & {
295
+ anchors: (AnchorSerializedOutput & {
239
296
  className: string;
240
- location: IModelReference & {
241
- type: NodeType;
297
+ location: {
298
+ context: string;
299
+ type: `${NodeType}`;
242
300
  };
243
301
  })[];
244
302
  dependencies: IDependency[];
245
303
  models: {
246
- [p: string]: {
304
+ [context: string]: {
305
+ [N in ModelName]: {
306
+ className: string;
307
+ model: BaseModelSchemas[N];
308
+ moduleId: string;
309
+ nodeName: N;
310
+ };
311
+ }[ModelName];
312
+ };
313
+ modules: {
314
+ [moduleId: string]: {
247
315
  className: string;
248
- model: IUnknownModel;
249
- moduleId?: string;
316
+ inputs: {
317
+ [key: string]: unknown;
318
+ };
250
319
  };
251
320
  };
252
321
  overlays: {
253
322
  className: string;
254
- overlay: OverlaySchema<UnknownOverlay>;
323
+ context: string;
324
+ moduleId: string;
325
+ overlay: {
326
+ anchors: AnchorSerializedOutput[];
327
+ overlayId: string;
328
+ properties: {
329
+ [key: string]: unknown;
330
+ };
331
+ };
255
332
  }[];
256
333
  };
257
334
  /**
258
- * The resource graph as written to state.
335
+ * A resource as written to state.
336
+ * * `parentSchemaTranslator` is the source of the function a child reads that parent through.
337
+ *
338
+ * @group Types
339
+ */
340
+ export type ResourceSerializedSchema = {
341
+ localResourceId: string;
342
+ parents: {
343
+ context: string;
344
+ parentSchemaTranslator?: string;
345
+ }[];
346
+ properties: {
347
+ [key: string]: unknown;
348
+ };
349
+ resourceId: string;
350
+ response: {
351
+ [key: string]: string;
352
+ };
353
+ scope: string[];
354
+ tags: {
355
+ [key: string]: string;
356
+ };
357
+ };
358
+ /**
359
+ * The resource graph as written to `resources-actual.json` and `resources-old.json`.
360
+ * * `createdBy` is the context of the model or overlay whose action created the resource.
361
+ * * `models` record the context of every model and overlay whose action produced the resource.
259
362
  *
260
363
  * @group Types
261
364
  */
262
365
  export type ResourceSerializedOutput = {
263
366
  dependencies: IDependency[];
264
367
  resources: {
265
- [p: string]: {
368
+ [context: string]: {
266
369
  className: string;
267
- moduleId?: string;
268
- resource: BaseResourceSchema;
370
+ createdBy?: string;
371
+ kind: 'external' | 'terraform';
372
+ models: string[];
373
+ moduleId: string;
374
+ resource: ResourceSerializedSchema;
269
375
  };
270
376
  };
271
377
  };
@@ -278,6 +384,22 @@ export type ResourceSerializedOutput = {
278
384
  export type TerraformFolderOutput = {
279
385
  hasExternalResources: boolean;
280
386
  moduleId: string;
387
+ /**
388
+ * The resources whose terraform state moves into this folder from another before terraform runs,
389
+ * each with the addresses and output names it moves from and to.
390
+ */
391
+ moves?: {
392
+ addresses: {
393
+ from: string;
394
+ to: string;
395
+ }[];
396
+ fromModuleId: string;
397
+ outputs: {
398
+ from: string;
399
+ to: string;
400
+ }[];
401
+ resourceId: string;
402
+ }[];
281
403
  providers: {
282
404
  accountId: string;
283
405
  blockHcl: string;
@@ -296,6 +418,10 @@ export type TerraformFolderOutput = {
296
418
  * @group Types
297
419
  */
298
420
  export type TerraformResourceOutput = {
421
+ /**
422
+ * Set when destroying the resource loses data, as its class declares.
423
+ */
424
+ destroyLosesData?: true;
299
425
  moduleId: string;
300
426
  resourceContext: string;
301
427
  resourceId: string;
@@ -314,10 +440,6 @@ export type TransactionOptions = {
314
440
  yieldResourceDiffs?: boolean;
315
441
  yieldResourceTransaction?: boolean;
316
442
  };
317
- /**
318
- * @internal
319
- */
320
- export type ModifyInterface<T, R> = Omit<T, keyof R> & R;
321
443
  /**
322
444
  * The schema of an anchor class.
323
445
  *
@@ -344,15 +466,11 @@ export type EnhancedModuleSchema<T extends UnknownModule> = {
344
466
  /**
345
467
  * @internal
346
468
  */
347
- export type GeneratorYieldType<T extends (...args: any) => AsyncGenerator<any, any, any>> = ReturnType<T> extends AsyncGenerator<infer Y, any, any> ? Y : never;
469
+ export type GeneratorYieldType<T extends (...args: any) => AsyncGenerator<any>> = ReturnType<T> extends AsyncGenerator<infer Y> ? Y : never;
348
470
  /**
349
471
  * @internal
350
472
  */
351
473
  export type ModelSchema<T> = T extends AModel<infer S, any> ? S : never;
352
- /**
353
- * @internal
354
- */
355
- export type ModuleOutput<M> = M extends AModule<any, infer T> ? T : never;
356
474
  /**
357
475
  * The schema of a module class.
358
476
  *
@@ -422,3 +540,4 @@ export type UnknownOverlay = AOverlay<BaseOverlaySchema, any>;
422
540
  * @internal
423
541
  */
424
542
  export type UnknownResource = AResource<any, any>;
543
+ export {};
@@ -1 +1 @@
1
- {"version":3,"file":"app.type.js","sourceRoot":"","sources":["../src/app.type.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"app.type.js","sourceRoot":"","sources":["../src/app.type.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { type Constructable, type ModelSchema, type UnknownModel } from '../app.type.js';
1
+ import { type Constructable, type ModelName, type ModelSchema, type UnknownModel } from '../app.type.js';
2
2
  /**
3
3
  * A `@Model` is a class decorator and must be placed on top of a class representing a model.
4
4
  * - A model must also extend a base model class.
@@ -15,9 +15,7 @@ import { type Constructable, type ModelSchema, type UnknownModel } from '../app.
15
15
  * @param packageName - The name of the package under which the model is registered.
16
16
  * Selecting a unique package name helps avoid collisions between same model class names across different libraries.
17
17
  * You will reuse the same package name throughout your library for different Octo components you create.
18
- * @param modelName - a string that uniquely represents the base model you are extending.
19
- * Octo provides names for each of the base models, and you must use the same name.
20
- * E.g. for region base model, the model name is `region`.
18
+ * @param modelName - The name of the base model you are extending, e.g. `region` for {@link Region}.
21
19
  * @param schema - The schema of the model.
22
20
  *
23
21
  * @returns The decorated class.
@@ -25,4 +23,4 @@ import { type Constructable, type ModelSchema, type UnknownModel } from '../app.
25
23
  * @see Definition of [Models](/docs/fundamentals/models).
26
24
  * @see {@link App}, {@link Region}, and {@link Server} for the base models you can extend.
27
25
  */
28
- export declare function Model<T extends UnknownModel>(packageName: string, modelName: string, schema: Constructable<ModelSchema<T>>): (constructor: any) => void;
26
+ export declare function Model<T extends UnknownModel>(packageName: string, modelName: ModelName, schema: Constructable<ModelSchema<T>>): (constructor: any) => void;
@@ -20,9 +20,7 @@ import { ValidationUtility } from '../utilities/validation/validation.utility.js
20
20
  * @param packageName - The name of the package under which the model is registered.
21
21
  * Selecting a unique package name helps avoid collisions between same model class names across different libraries.
22
22
  * You will reuse the same package name throughout your library for different Octo components you create.
23
- * @param modelName - a string that uniquely represents the base model you are extending.
24
- * Octo provides names for each of the base models, and you must use the same name.
25
- * E.g. for region base model, the model name is `region`.
23
+ * @param modelName - The name of the base model you are extending, e.g. `region` for {@link Region}.
26
24
  * @param schema - The schema of the model.
27
25
  *
28
26
  * @returns The decorated class.
@@ -36,9 +34,6 @@ export function Model(packageName, modelName, schema) {
36
34
  if (!ValidationUtility.validateRegex(packageName, /^[@A-Za-z][\w-]+[A-Za-z]$/)) {
37
35
  throw new Error(`Invalid package name: ${packageName}`);
38
36
  }
39
- if (!ValidationUtility.validateRegex(modelName, /^[A-Za-z][\w-]+[A-Za-z]$/)) {
40
- throw new Error(`Invalid model name: ${modelName}`);
41
- }
42
37
  if (!(constructor.prototype instanceof AModel) || constructor.prototype instanceof AOverlay) {
43
38
  throw new Error(`Class "${constructor.name}" must extend the AModel class!`);
44
39
  }
@@ -1 +1 @@
1
- {"version":3,"file":"model.decorator.js","sourceRoot":"","sources":["../../src/decorators/model.decorator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAwC,QAAQ,EAAqB,MAAM,gBAAgB,CAAC;AACnG,OAAO,EAAE,SAAS,EAAE,MAAM,qCAAqC,CAAC;AAChE,OAAO,EAAE,MAAM,EAAE,MAAM,6BAA6B,CAAC;AACrD,OAAO,EAAE,QAAQ,EAAE,MAAM,iCAAiC,CAAC;AAC3D,OAAO,EAAE,yBAAyB,EAAE,MAAM,gEAAgE,CAAC;AAC3G,OAAO,EAAE,iBAAiB,EAAE,MAAM,+CAA+C,CAAC;AAElF;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,UAAU,KAAK,CACnB,WAAmB,EACnB,SAAiB,EACjB,MAAqC;IAErC,MAAM,SAAS,GAAG,SAAS,CAAC,WAAW,EAAE,CAAC;IAE1C,OAAO,UAAU,WAAgB;QAC/B,IAAI,CAAC,iBAAiB,CAAC,aAAa,CAAC,WAAW,EAAE,2BAA2B,CAAC,EAAE,CAAC;YAC/E,MAAM,IAAI,KAAK,CAAC,yBAAyB,WAAW,EAAE,CAAC,CAAC;QAC1D,CAAC;QACD,IAAI,CAAC,iBAAiB,CAAC,aAAa,CAAC,SAAS,EAAE,0BAA0B,CAAC,EAAE,CAAC;YAC5E,MAAM,IAAI,KAAK,CAAC,uBAAuB,SAAS,EAAE,CAAC,CAAC;QACtD,CAAC;QACD,IAAI,CAAC,CAAC,WAAW,CAAC,SAAS,YAAY,MAAM,CAAC,IAAI,WAAW,CAAC,SAAS,YAAY,QAAQ,EAAE,CAAC;YAC5F,MAAM,IAAI,KAAK,CAAC,UAAU,WAAW,CAAC,IAAI,iCAAiC,CAAC,CAAC;QAC/E,CAAC;QAED,WAAW,CAAC,SAAS,GAAG,SAAS,CAAC;QAClC,WAAW,CAAC,YAAY,GAAG,WAAW,CAAC;QACvC,WAAW,CAAC,WAAW,GAAG,MAAM,CAAC;QACjC,WAAW,CAAC,SAAS,GAAG,QAAQ,CAAC,KAAK,CAAC;QAEvC,MAAM,OAAO,GAAG,SAAS,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC,IAAI,CAAC,CAAC,yBAAyB,EAAE,EAAE;YAC1F,yBAAyB,CAAC,aAAa,CAAC,GAAG,WAAW,IAAI,WAAW,CAAC,IAAI,EAAE,EAAE,WAAW,CAAC,CAAC;QAC7F,CAAC,CAAC,CAAC;QACH,SAAS,CAAC,+BAA+B,CAAC,OAAO,CAAC,CAAC;IACrD,CAAC,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"model.decorator.js","sourceRoot":"","sources":["../../src/decorators/model.decorator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAwD,QAAQ,EAAqB,MAAM,gBAAgB,CAAC;AACnH,OAAO,EAAE,SAAS,EAAE,MAAM,qCAAqC,CAAC;AAChE,OAAO,EAAE,MAAM,EAAE,MAAM,6BAA6B,CAAC;AACrD,OAAO,EAAE,QAAQ,EAAE,MAAM,iCAAiC,CAAC;AAC3D,OAAO,EAAE,yBAAyB,EAAE,MAAM,gEAAgE,CAAC;AAC3G,OAAO,EAAE,iBAAiB,EAAE,MAAM,+CAA+C,CAAC;AAElF;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,UAAU,KAAK,CACnB,WAAmB,EACnB,SAAoB,EACpB,MAAqC;IAErC,MAAM,SAAS,GAAG,SAAS,CAAC,WAAW,EAAE,CAAC;IAE1C,OAAO,UAAU,WAAgB;QAC/B,IAAI,CAAC,iBAAiB,CAAC,aAAa,CAAC,WAAW,EAAE,2BAA2B,CAAC,EAAE,CAAC;YAC/E,MAAM,IAAI,KAAK,CAAC,yBAAyB,WAAW,EAAE,CAAC,CAAC;QAC1D,CAAC;QACD,IAAI,CAAC,CAAC,WAAW,CAAC,SAAS,YAAY,MAAM,CAAC,IAAI,WAAW,CAAC,SAAS,YAAY,QAAQ,EAAE,CAAC;YAC5F,MAAM,IAAI,KAAK,CAAC,UAAU,WAAW,CAAC,IAAI,iCAAiC,CAAC,CAAC;QAC/E,CAAC;QAED,WAAW,CAAC,SAAS,GAAG,SAAS,CAAC;QAClC,WAAW,CAAC,YAAY,GAAG,WAAW,CAAC;QACvC,WAAW,CAAC,WAAW,GAAG,MAAM,CAAC;QACjC,WAAW,CAAC,SAAS,GAAG,QAAQ,CAAC,KAAK,CAAC;QAEvC,MAAM,OAAO,GAAG,SAAS,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC,IAAI,CAAC,CAAC,yBAAyB,EAAE,EAAE;YAC1F,yBAAyB,CAAC,aAAa,CAAC,GAAG,WAAW,IAAI,WAAW,CAAC,IAAI,EAAE,EAAE,WAAW,CAAC,CAAC;QAC7F,CAAC,CAAC,CAAC;QACH,SAAS,CAAC,+BAA+B,CAAC,OAAO,CAAC,CAAC;IACrD,CAAC,CAAC;AACJ,CAAC"}
@@ -1,4 +1,4 @@
1
- import type { Constructable } from '../app.type.js';
1
+ import type { AbstractConstructable } from '../app.type.js';
2
2
  import type { Event } from '../events/index.js';
3
3
  /**
4
4
  * An `@OnEvent` is a method decorator to listen to an event.
@@ -22,4 +22,4 @@ import type { Event } from '../events/index.js';
22
22
  * @param ofType The type of event being listened to.
23
23
  * @returns The decorated method.
24
24
  */
25
- export declare function OnEvent(ofType: Constructable<Event<unknown>>): (target: any, propertyKey: string, descriptor: PropertyDescriptor) => void;
25
+ export declare function OnEvent(ofType: AbstractConstructable<Event<unknown>>): (target: any, propertyKey: string, descriptor: PropertyDescriptor) => void;
@@ -1 +1 @@
1
- {"version":3,"file":"on-event.decorator.js","sourceRoot":"","sources":["../../src/decorators/on-event.decorator.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,oCAAoC,CAAC;AAElE;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,UAAU,OAAO,CACrB,MAAqC;IAErC,OAAO,UAAU,MAAW,EAAE,YAAoB,EAAE,UAA8B;QAChF,YAAY,CAAC,WAAW,EAAE,CAAC,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,CAAC,CAAC;IAC3E,CAAC,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"on-event.decorator.js","sourceRoot":"","sources":["../../src/decorators/on-event.decorator.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,oCAAoC,CAAC;AAElE;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,UAAU,OAAO,CACrB,MAA6C;IAE7C,OAAO,UAAU,MAAW,EAAE,YAAoB,EAAE,UAA8B;QAChF,YAAY,CAAC,WAAW,EAAE,CAAC,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,CAAC,CAAC;IAC3E,CAAC,CAAC;AACJ,CAAC"}
@@ -1,4 +1,11 @@
1
1
  import { type Constructable, type ResourceSchema, type UnknownResource } from '../app.type.js';
2
+ /**
3
+ * Every dot path through `T` that ends at a string, with `[]` after a key holding an array. Below a key
4
+ * typed `unknown` any path is accepted.
5
+ */
6
+ type NamePath<T, Depth extends unknown[] = []> = Depth['length'] extends 6 ? never : {
7
+ [K in keyof T & string]-?: unknown extends T[K] ? K | `${K}.${string}` | `${K}[]` | `${K}[].${string}` : NonNullable<T[K]> extends readonly (infer E)[] ? (NonNullable<E> extends string ? `${K}[]` : never) | (NonNullable<E> extends object ? `${K}[].${NamePath<NonNullable<E>, [...Depth, unknown]>}` : never) : NonNullable<T[K]> extends string ? K : NonNullable<T[K]> extends object ? `${K}.${NamePath<NonNullable<T[K]>, [...Depth, unknown]>}` : never;
8
+ }[keyof T & string];
2
9
  /**
3
10
  * A `@Resource` is a class decorator and must be placed on top of a class representing a resource.
4
11
  * - A resource must also extend the {@link AResource} class.
@@ -10,6 +17,30 @@ import { type Constructable, type ResourceSchema, type UnknownResource } from '.
10
17
  * export class MyResource extends AResource<MyResourceSchema, MyResource> { ... }
11
18
  * ```
12
19
  *
20
+ * A resource whose properties hold a name the cloud requires unique declares it in `options.uniqueProperties`, and
21
+ * generate refuses two values of `path` that share the values of `within`, whether they come from two
22
+ * resources of the class or from one.
23
+ *
24
+ * @example
25
+ * ```ts
26
+ * @Resource<MyTable>('@example', 'my-table', MyTableSchema, {
27
+ * uniqueProperties: [
28
+ * { path: 'tableName', within: ['accountId', 'regionId'] },
29
+ * { path: 'indexes[].name', within: ['accountId', 'regionId'] },
30
+ * ],
31
+ * })
32
+ * export class MyTable extends AResource<MyTableSchema, MyTable> { ... }
33
+ * ```
34
+ *
35
+ * A resource holding data octo cannot put back from its inputs - a table's rows, a filesystem's files -
36
+ * sets `options.destroyLosesData`, and every destroy terraform plans of it is reported as losing data.
37
+ *
38
+ * @example
39
+ * ```ts
40
+ * @Resource<MyTable>('@example', 'my-table', MyTableSchema, { destroyLosesData: true })
41
+ * export class MyTable extends AResource<MyTableSchema, MyTable> { ... }
42
+ * ```
43
+ *
13
44
  * @group Decorators
14
45
  *
15
46
  * @param packageName - The name of the package under which the resource is registered.
@@ -17,9 +48,27 @@ import { type Constructable, type ResourceSchema, type UnknownResource } from '.
17
48
  * You will reuse the same package name throughout your library for different Octo components you create.
18
49
  * @param resourceName - a string that uniquely represents the name of the resource.
19
50
  * @param schema - The schema of the resource.
51
+ * @param options - Optional settings of the resource.
52
+ * `destroyLosesData` marks the resource as holding data that is lost when it is destroyed. Validate,
53
+ * and apply's check for destroys, add a message to each destroy of it, whatever the cause.
54
+ *
55
+ * `uniqueProperties` lists the names the cloud requires unique, one entry per name.
56
+ * - `path` is a dot path through the resource's properties, with `[]` after a key holding an array.
57
+ * A resource with no value at `path` is not checked.
58
+ * - `within` names the properties whose values form the name's domain. A resource missing one is refused.
59
+ * An empty `within` makes the name unique across the app.
60
+ *
61
+ * Only resources of one class are compared with each other, and a class declaring no names is not checked.
20
62
  *
21
63
  * @returns The decorated class.
22
64
  *
23
65
  * @see Definition of [Resources](/docs/fundamentals/resources).
24
66
  */
25
- export declare function Resource<T extends UnknownResource>(packageName: string, resourceName: string, schema: Constructable<ResourceSchema<T>>): (constructor: any) => void;
67
+ export declare function Resource<T extends UnknownResource>(packageName: string, resourceName: string, schema: Constructable<ResourceSchema<T>>, { destroyLosesData, uniqueProperties, }?: {
68
+ destroyLosesData?: boolean;
69
+ uniqueProperties?: {
70
+ path: NamePath<ResourceSchema<T>['properties']>;
71
+ within: (keyof ResourceSchema<T>['properties'] & string)[];
72
+ }[];
73
+ }): (constructor: any) => void;
74
+ export {};
@@ -14,6 +14,30 @@ import { ValidationUtility } from '../utilities/validation/validation.utility.js
14
14
  * export class MyResource extends AResource<MyResourceSchema, MyResource> { ... }
15
15
  * ```
16
16
  *
17
+ * A resource whose properties hold a name the cloud requires unique declares it in `options.uniqueProperties`, and
18
+ * generate refuses two values of `path` that share the values of `within`, whether they come from two
19
+ * resources of the class or from one.
20
+ *
21
+ * @example
22
+ * ```ts
23
+ * @Resource<MyTable>('@example', 'my-table', MyTableSchema, {
24
+ * uniqueProperties: [
25
+ * { path: 'tableName', within: ['accountId', 'regionId'] },
26
+ * { path: 'indexes[].name', within: ['accountId', 'regionId'] },
27
+ * ],
28
+ * })
29
+ * export class MyTable extends AResource<MyTableSchema, MyTable> { ... }
30
+ * ```
31
+ *
32
+ * A resource holding data octo cannot put back from its inputs - a table's rows, a filesystem's files -
33
+ * sets `options.destroyLosesData`, and every destroy terraform plans of it is reported as losing data.
34
+ *
35
+ * @example
36
+ * ```ts
37
+ * @Resource<MyTable>('@example', 'my-table', MyTableSchema, { destroyLosesData: true })
38
+ * export class MyTable extends AResource<MyTableSchema, MyTable> { ... }
39
+ * ```
40
+ *
17
41
  * @group Decorators
18
42
  *
19
43
  * @param packageName - The name of the package under which the resource is registered.
@@ -21,12 +45,23 @@ import { ValidationUtility } from '../utilities/validation/validation.utility.js
21
45
  * You will reuse the same package name throughout your library for different Octo components you create.
22
46
  * @param resourceName - a string that uniquely represents the name of the resource.
23
47
  * @param schema - The schema of the resource.
48
+ * @param options - Optional settings of the resource.
49
+ * `destroyLosesData` marks the resource as holding data that is lost when it is destroyed. Validate,
50
+ * and apply's check for destroys, add a message to each destroy of it, whatever the cause.
51
+ *
52
+ * `uniqueProperties` lists the names the cloud requires unique, one entry per name.
53
+ * - `path` is a dot path through the resource's properties, with `[]` after a key holding an array.
54
+ * A resource with no value at `path` is not checked.
55
+ * - `within` names the properties whose values form the name's domain. A resource missing one is refused.
56
+ * An empty `within` makes the name unique across the app.
57
+ *
58
+ * Only resources of one class are compared with each other, and a class declaring no names is not checked.
24
59
  *
25
60
  * @returns The decorated class.
26
61
  *
27
62
  * @see Definition of [Resources](/docs/fundamentals/resources).
28
63
  */
29
- export function Resource(packageName, resourceName, schema) {
64
+ export function Resource(packageName, resourceName, schema, { destroyLosesData = false, uniqueProperties = [], } = {}) {
30
65
  const container = Container.getInstance();
31
66
  return function (constructor) {
32
67
  if (!ValidationUtility.validateRegex(packageName, /^[@A-Za-z][\w-]+[A-Za-z]$/)) {
@@ -38,10 +73,12 @@ export function Resource(packageName, resourceName, schema) {
38
73
  if (!(constructor.prototype instanceof AResource)) {
39
74
  throw new Error(`Class "${constructor.name}" must extend the AResource class!`);
40
75
  }
76
+ constructor.DESTROY_LOSES_DATA = destroyLosesData;
41
77
  constructor.NODE_NAME = resourceName;
42
78
  constructor.NODE_PACKAGE = packageName;
43
79
  constructor.NODE_SCHEMA = schema;
44
80
  constructor.NODE_TYPE = NodeType.RESOURCE;
81
+ constructor.UNIQUE_PROPERTIES = uniqueProperties.map(({ path, within }) => ({ path, within: [...within] }));
45
82
  const promise = container.get(ResourceSerializationService).then((resourceSerializationService) => {
46
83
  resourceSerializationService.registerClass(`${packageName}/${constructor.name}`, constructor);
47
84
  });
@@ -1 +1 @@
1
- {"version":3,"file":"resource.decorator.js","sourceRoot":"","sources":["../../src/decorators/resource.decorator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsB,QAAQ,EAA6C,MAAM,gBAAgB,CAAC;AACzG,OAAO,EAAE,SAAS,EAAE,MAAM,qCAAqC,CAAC;AAChE,OAAO,EAAE,SAAS,EAAE,MAAM,mCAAmC,CAAC;AAC9D,OAAO,EAAE,4BAA4B,EAAE,MAAM,sEAAsE,CAAC;AACpH,OAAO,EAAE,iBAAiB,EAAE,MAAM,+CAA+C,CAAC;AAElF;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,UAAU,QAAQ,CACtB,WAAmB,EACnB,YAAoB,EACpB,MAAwC;IAExC,MAAM,SAAS,GAAG,SAAS,CAAC,WAAW,EAAE,CAAC;IAE1C,OAAO,UAAU,WAAgB;QAC/B,IAAI,CAAC,iBAAiB,CAAC,aAAa,CAAC,WAAW,EAAE,2BAA2B,CAAC,EAAE,CAAC;YAC/E,MAAM,IAAI,KAAK,CAAC,yBAAyB,WAAW,EAAE,CAAC,CAAC;QAC1D,CAAC;QACD,IAAI,CAAC,iBAAiB,CAAC,aAAa,CAAC,YAAY,EAAE,0BAA0B,CAAC,EAAE,CAAC;YAC/E,MAAM,IAAI,KAAK,CAAC,0BAA0B,YAAY,EAAE,CAAC,CAAC;QAC5D,CAAC;QACD,IAAI,CAAC,CAAC,WAAW,CAAC,SAAS,YAAY,SAAS,CAAC,EAAE,CAAC;YAClD,MAAM,IAAI,KAAK,CAAC,UAAU,WAAW,CAAC,IAAI,oCAAoC,CAAC,CAAC;QAClF,CAAC;QAED,WAAW,CAAC,SAAS,GAAG,YAAY,CAAC;QACrC,WAAW,CAAC,YAAY,GAAG,WAAW,CAAC;QACvC,WAAW,CAAC,WAAW,GAAG,MAAM,CAAC;QACjC,WAAW,CAAC,SAAS,GAAG,QAAQ,CAAC,QAAQ,CAAC;QAE1C,MAAM,OAAO,GAAG,SAAS,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAC,IAAI,CAAC,CAAC,4BAA4B,EAAE,EAAE;YAChG,4BAA4B,CAAC,aAAa,CAAC,GAAG,WAAW,IAAI,WAAW,CAAC,IAAI,EAAE,EAAE,WAAW,CAAC,CAAC;QAChG,CAAC,CAAC,CAAC;QACH,SAAS,CAAC,+BAA+B,CAAC,OAAO,CAAC,CAAC;IACrD,CAAC,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"resource.decorator.js","sourceRoot":"","sources":["../../src/decorators/resource.decorator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsB,QAAQ,EAA6C,MAAM,gBAAgB,CAAC;AACzG,OAAO,EAAE,SAAS,EAAE,MAAM,qCAAqC,CAAC;AAChE,OAAO,EAAE,SAAS,EAAE,MAAM,mCAAmC,CAAC;AAC9D,OAAO,EAAE,4BAA4B,EAAE,MAAM,sEAAsE,CAAC;AACpH,OAAO,EAAE,iBAAiB,EAAE,MAAM,+CAA+C,CAAC;AAsBlF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyDG;AACH,MAAM,UAAU,QAAQ,CACtB,WAAmB,EACnB,YAAoB,EACpB,MAAwC,EACxC,EACE,gBAAgB,GAAG,KAAK,EACxB,gBAAgB,GAAG,EAAE,MAOnB,EAAE;IAEN,MAAM,SAAS,GAAG,SAAS,CAAC,WAAW,EAAE,CAAC;IAE1C,OAAO,UAAU,WAAgB;QAC/B,IAAI,CAAC,iBAAiB,CAAC,aAAa,CAAC,WAAW,EAAE,2BAA2B,CAAC,EAAE,CAAC;YAC/E,MAAM,IAAI,KAAK,CAAC,yBAAyB,WAAW,EAAE,CAAC,CAAC;QAC1D,CAAC;QACD,IAAI,CAAC,iBAAiB,CAAC,aAAa,CAAC,YAAY,EAAE,0BAA0B,CAAC,EAAE,CAAC;YAC/E,MAAM,IAAI,KAAK,CAAC,0BAA0B,YAAY,EAAE,CAAC,CAAC;QAC5D,CAAC;QACD,IAAI,CAAC,CAAC,WAAW,CAAC,SAAS,YAAY,SAAS,CAAC,EAAE,CAAC;YAClD,MAAM,IAAI,KAAK,CAAC,UAAU,WAAW,CAAC,IAAI,oCAAoC,CAAC,CAAC;QAClF,CAAC;QAED,WAAW,CAAC,kBAAkB,GAAG,gBAAgB,CAAC;QAClD,WAAW,CAAC,SAAS,GAAG,YAAY,CAAC;QACrC,WAAW,CAAC,YAAY,GAAG,WAAW,CAAC;QACvC,WAAW,CAAC,WAAW,GAAG,MAAM,CAAC;QACjC,WAAW,CAAC,SAAS,GAAG,QAAQ,CAAC,QAAQ,CAAC;QAC1C,WAAW,CAAC,iBAAiB,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,GAAG,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;QAE5G,MAAM,OAAO,GAAG,SAAS,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAC,IAAI,CAAC,CAAC,4BAA4B,EAAE,EAAE;YAChG,4BAA4B,CAAC,aAAa,CAAC,GAAG,WAAW,IAAI,WAAW,CAAC,IAAI,EAAE,EAAE,WAAW,CAAC,CAAC;QAChG,CAAC,CAAC,CAAC;QACH,SAAS,CAAC,+BAA+B,CAAC,OAAO,CAAC,CAAC;IACrD,CAAC,CAAC;AACJ,CAAC"}
@@ -5,9 +5,16 @@
5
5
  */
6
6
  export declare class SchemaError extends Error {
7
7
  readonly schemaClassName: string;
8
+ /**
9
+ * What a validator threw underneath, where this error is wrapping one. Carried as a property of
10
+ * its own rather than as the `Error` cause: without it a nested property's failure reads only as
11
+ * the name of the top-level input it arrived under, and which value failed is the whole question.
12
+ */
13
+ readonly validationError?: unknown;
8
14
  /**
9
15
  * @param message The error message.
10
16
  * @param schemaClassName The schema the value was being read as.
17
+ * @param validationError What a validator threw underneath, where there is one.
11
18
  */
12
- constructor(message: string, schemaClassName: string);
19
+ constructor(message: string, schemaClassName: string, validationError?: unknown);
13
20
  }