@intentius/chant-lexicon-azure 0.124.31 → 0.124.32

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 (117) hide show
  1. package/dist/actions/appservice.js +7 -0
  2. package/dist/actions/compute.js +9 -0
  3. package/dist/actions/container.js +14 -0
  4. package/dist/actions/identity.js +11 -0
  5. package/dist/actions/index.js +11 -0
  6. package/dist/actions/keyvault.js +12 -0
  7. package/dist/actions/network.js +9 -0
  8. package/dist/actions/sql.js +9 -0
  9. package/dist/actions/storage.js +15 -0
  10. package/dist/api/read-client.js +146 -0
  11. package/dist/codegen/docs-cli.js +2 -0
  12. package/dist/codegen/docs.js +83 -0
  13. package/dist/codegen/generate-cli.js +11 -0
  14. package/dist/codegen/generate-lexicon.js +77 -0
  15. package/dist/codegen/generate-typescript.js +163 -0
  16. package/dist/codegen/generate.js +106 -0
  17. package/dist/codegen/naming.js +139 -0
  18. package/dist/codegen/package.js +64 -0
  19. package/dist/composites/aks-cluster.js +68 -0
  20. package/dist/composites/app-service.js +62 -0
  21. package/dist/composites/application-gateway.js +107 -0
  22. package/dist/composites/catalog.js +856 -0
  23. package/dist/composites/container-instance.js +36 -0
  24. package/dist/composites/container-registry.js +62 -0
  25. package/dist/composites/cosmos-database.js +56 -0
  26. package/dist/composites/from-arm.js +47 -0
  27. package/dist/composites/function-app.js +57 -0
  28. package/dist/composites/index.js +16 -0
  29. package/dist/composites/keyvault.js +69 -0
  30. package/dist/composites/landing-zone.js +119 -0
  31. package/dist/composites/private-endpoint.js +61 -0
  32. package/dist/composites/redis-cache.js +21 -0
  33. package/dist/composites/service-bus-pipeline.js +54 -0
  34. package/dist/composites/sql-database.js +62 -0
  35. package/dist/composites/storage-account.js +59 -0
  36. package/dist/composites/vm-linux.js +139 -0
  37. package/dist/composites/vnet-default.js +102 -0
  38. package/dist/coverage.js +28 -0
  39. package/dist/deep-observe.js +356 -0
  40. package/dist/default-tags.js +50 -0
  41. package/dist/deploy-scopes.d.ts.map +1 -1
  42. package/dist/deploy-scopes.js +157 -0
  43. package/dist/describe-resources.js +187 -0
  44. package/dist/detect.js +17 -0
  45. package/dist/export-resources.js +108 -0
  46. package/dist/generated/index.js +16598 -0
  47. package/dist/generated/runtime.js +4 -0
  48. package/dist/governance.js +144 -0
  49. package/dist/import/generator.js +140 -0
  50. package/dist/import/live-export.js +39 -0
  51. package/dist/import/parser.js +192 -0
  52. package/dist/index.js +44 -0
  53. package/dist/integrity.json +2 -2
  54. package/dist/intrinsics.js +179 -0
  55. package/dist/lint/audit-catalog.js +36 -0
  56. package/dist/lint/audit-lineage.js +71 -0
  57. package/dist/lint/post-synth/arm-refs.js +94 -0
  58. package/dist/lint/post-synth/azr010.js +45 -0
  59. package/dist/lint/post-synth/azr011.js +43 -0
  60. package/dist/lint/post-synth/azr012.js +41 -0
  61. package/dist/lint/post-synth/azr013.js +50 -0
  62. package/dist/lint/post-synth/azr014.js +49 -0
  63. package/dist/lint/post-synth/azr015.js +66 -0
  64. package/dist/lint/post-synth/azr016.js +37 -0
  65. package/dist/lint/post-synth/azr017.js +37 -0
  66. package/dist/lint/post-synth/azr018.js +42 -0
  67. package/dist/lint/post-synth/azr019.js +41 -0
  68. package/dist/lint/post-synth/azr020.js +37 -0
  69. package/dist/lint/post-synth/azr021.js +36 -0
  70. package/dist/lint/post-synth/azr022.js +39 -0
  71. package/dist/lint/post-synth/azr023.js +39 -0
  72. package/dist/lint/post-synth/azr024.js +39 -0
  73. package/dist/lint/post-synth/azr025.js +37 -0
  74. package/dist/lint/post-synth/azr026.js +38 -0
  75. package/dist/lint/post-synth/azr027.js +37 -0
  76. package/dist/lint/post-synth/azr028.js +37 -0
  77. package/dist/lint/post-synth/azr029.js +38 -0
  78. package/dist/lint/post-synth/azr030.js +44 -0
  79. package/dist/lint/post-synth/azr031.js +36 -0
  80. package/dist/lint/post-synth/azr032.js +53 -0
  81. package/dist/lint/post-synth/azr033.js +35 -0
  82. package/dist/lint/post-synth/index.js +50 -0
  83. package/dist/lint/rules/hardcoded-location.js +82 -0
  84. package/dist/lint/rules/index.js +6 -0
  85. package/dist/lint/rules/nsg-wildcard.js +44 -0
  86. package/dist/lint/rules/storage-https.js +62 -0
  87. package/dist/lsp/completions.d.ts.map +1 -1
  88. package/dist/lsp/completions.js +18 -0
  89. package/dist/lsp/hover.d.ts.map +1 -1
  90. package/dist/lsp/hover.js +44 -0
  91. package/dist/manifest.json +1 -1
  92. package/dist/op/activities/az-apply.js +563 -0
  93. package/dist/op/activities/azure.js +48 -0
  94. package/dist/op/activities/floci-az.js +37 -0
  95. package/dist/op/activities/index.js +10 -0
  96. package/dist/op/builders.js +70 -0
  97. package/dist/ownership.js +13 -0
  98. package/dist/package-cli.js +21 -0
  99. package/dist/parameter.js +13 -0
  100. package/dist/plugin.d.ts.map +1 -1
  101. package/dist/plugin.js +472 -0
  102. package/dist/pseudo.js +40 -0
  103. package/dist/serializer.js +457 -0
  104. package/dist/spec/api-versions.js +130 -0
  105. package/dist/spec/fetch.js +196 -0
  106. package/dist/spec/parse.js +308 -0
  107. package/dist/taggable.js +34 -0
  108. package/dist/validate-cli.js +16 -0
  109. package/dist/validate.js +53 -0
  110. package/package.json +8 -8
  111. package/src/codegen/package.ts +2 -2
  112. package/src/deploy-scopes.ts +2 -1
  113. package/src/lsp/completions.ts +2 -1
  114. package/src/lsp/hover.ts +2 -1
  115. package/src/plugin.ts +3 -2
  116. package/src/serializer.ts +2 -2
  117. package/src/taggable.ts +2 -2
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Typed step-builder wrappers for this lexicon's activities (chant #1288
3
+ * Stage 2). See `lexicons/k8s/src/op/builders.ts`'s module doc for why these
4
+ * live beside their `*Args` interfaces rather than in core: core cannot
5
+ * import a lexicon's types, so a wrapper whose `opts` IS the activity's own
6
+ * `*Args` interface can only sit in the lexicon that declares that
7
+ * interface. `opts`'s type in each wrapper below IS the activity's own
8
+ * `*Args` interface (via `Omit`/`WithStepRefs`) — never restated. `core`'s own
9
+ * `azApply`/`azDelete`/`azGroupEnsure`/`azGroupDelete`/`flociAzUp`/
10
+ * `flociAzDown` are unchanged and produce byte-identical `ActivityStep`
11
+ * output; these are purely additive.
12
+ */
13
+ import { activity, takeProfileAndId, } from "@intentius/chant/op";
14
+ /**
15
+ * Ensure an Azure resource group exists before an ARM apply — the fully
16
+ * typed twin of core's `azGroupEnsure`. `opts` is {@link AzGroupEnsureArgs}
17
+ * itself, minus the positional `resourceGroup`. Defaults to the
18
+ * `fastIdempotent` profile.
19
+ */
20
+ export const azGroupEnsure = (resourceGroup, opts) => {
21
+ const { args, profile, id } = takeProfileAndId(opts);
22
+ return activity("azGroupEnsure", { resourceGroup, ...args }, { profile: profile ?? "fastIdempotent", ...(id ? { id } : {}) });
23
+ };
24
+ /**
25
+ * Delete an Azure resource group and its contents — the fully typed twin of
26
+ * core's `azGroupDelete`. `opts` is {@link AzGroupDeleteArgs} itself, minus
27
+ * the positional `resourceGroup`. Defaults to the `fastIdempotent` profile.
28
+ */
29
+ export const azGroupDelete = (resourceGroup, opts) => {
30
+ const { args, profile, id } = takeProfileAndId(opts);
31
+ return activity("azGroupDelete", { resourceGroup, ...args }, { profile: profile ?? "fastIdempotent", ...(id ? { id } : {}) });
32
+ };
33
+ /**
34
+ * Apply a built ARM template directly to the ARM resource API — the fully
35
+ * typed twin of core's `azApply`. `opts` is {@link AzApplyArgs} itself,
36
+ * minus the positional `templatePath` (`resourceGroup` remains required).
37
+ * Defaults to the `longInfra` profile.
38
+ */
39
+ export const azApply = (templatePath, opts) => {
40
+ const { args, profile, id } = takeProfileAndId(opts);
41
+ return activity("azApply", { templatePath, ...args }, { profile: profile ?? "longInfra", ...(id ? { id } : {}) });
42
+ };
43
+ /**
44
+ * Delete the Azure (ARM) resources in a built template — the inverse of
45
+ * {@link azApply}, fully typed twin of core's `azDelete`. `opts` is
46
+ * {@link AzApplyArgs} itself (the activity reuses it), minus the positional
47
+ * `templatePath`. Defaults to the `longInfra` profile.
48
+ */
49
+ export const azDelete = (templatePath, opts) => {
50
+ const { args, profile, id } = takeProfileAndId(opts);
51
+ return activity("azDelete", { templatePath, ...args }, { profile: profile ?? "longInfra", ...(id ? { id } : {}) });
52
+ };
53
+ /**
54
+ * Boot a local floci-az (Azure emulator) — the fully typed twin of core's
55
+ * `flociAzUp`. `opts` is {@link FlociAzUpArgs} itself. Defaults to the
56
+ * `longInfra` profile.
57
+ */
58
+ export const flociAzUp = (opts) => {
59
+ const { args, profile, id } = takeProfileAndId(opts);
60
+ return activity("flociAzUp", args, { profile: profile ?? "longInfra", ...(id ? { id } : {}) });
61
+ };
62
+ /**
63
+ * Stop and remove the local floci-az container — the fully typed twin of
64
+ * core's `flociAzDown`. `opts` is {@link FlociAzDownArgs} itself. Defaults
65
+ * to the `fastIdempotent` profile.
66
+ */
67
+ export const flociAzDown = (opts) => {
68
+ const { args, profile, id } = takeProfileAndId(opts);
69
+ return activity("flociAzDown", args, { profile: profile ?? "fastIdempotent", ...(id ? { id } : {}) });
70
+ };
@@ -0,0 +1,13 @@
1
+ /**
2
+ * The azure lexicon's ownership tag convention. Azure tag keys forbid `/`, so
3
+ * chant's markers use a hyphenated `chant-<name>` form (distinct from the
4
+ * label-based convention core keeps for k8s/gcp, and from AWS's `chant:<name>`).
5
+ * Core owns the generic stamp/detect logic (@intentius/chant/ownership); this is
6
+ * the azure-specific key naming it stamps.
7
+ */
8
+ /** Azure tag keys for chant's ownership markers. */
9
+ export const AZURE_TAG_OWNERSHIP_KEYS = {
10
+ managedBy: "chant-managed-by",
11
+ stack: "chant-stack",
12
+ env: "chant-env",
13
+ };
@@ -0,0 +1,21 @@
1
+ #!/usr/bin/env tsx
2
+ /**
3
+ * Thin entry point for `npm run bundle` in lexicon-azure.
4
+ * Generates src/generated/ files and writes dist/ bundle.
5
+ */
6
+ import { generate, writeGeneratedFiles } from "./codegen/generate.js";
7
+ import { packageLexicon } from "./codegen/package.js";
8
+ import { writeBundleSpec } from "@intentius/chant/codegen/package";
9
+ import { join, dirname } from "path";
10
+ import { fileURLToPath } from "url";
11
+ const pkgDir = dirname(dirname(fileURLToPath(import.meta.url)));
12
+ // 1. Generate src/generated/ files
13
+ const genResult = await generate({ verbose: true });
14
+ writeGeneratedFiles(genResult, pkgDir);
15
+ console.error(`Generated ${genResult.resources} resources, ${genResult.properties} property types, ${genResult.enums} enums`);
16
+ // 2. Run package pipeline and write dist/
17
+ const { spec, stats } = await packageLexicon({ verbose: true });
18
+ const distDir = join(pkgDir, "dist");
19
+ writeBundleSpec(spec, distDir);
20
+ console.error(`Packaged ${stats.resources} resources, ${stats.ruleCount} rules, ${stats.skillCount} skills`);
21
+ console.error(`dist/ written to ${distDir}`);
@@ -0,0 +1,13 @@
1
+ var _a;
2
+ import { DECLARABLE_MARKER } from "@intentius/chant/declarable";
3
+ export class Parameter {
4
+ constructor(type, options) {
5
+ this[_a] = true;
6
+ this.lexicon = "azure";
7
+ this.entityType = "Microsoft.Resources/deployments/parameter";
8
+ this.parameterType = type;
9
+ this.description = options?.description;
10
+ this.defaultValue = options?.defaultValue;
11
+ }
12
+ }
13
+ _a = DECLARABLE_MARKER;
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAgB,MAAM,0BAA0B,CAAC;AAyB5E;;;;;GAKG;AACH,eAAO,MAAM,WAAW,EAAE,aAodzB,CAAC"}
1
+ {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAgB,MAAM,0BAA0B,CAAC;AA0B5E;;;;;GAKG;AACH,eAAO,MAAM,WAAW,EAAE,aAodzB,CAAC"}
package/dist/plugin.js ADDED
@@ -0,0 +1,472 @@
1
+ import { compositeCatalog } from "./composites/catalog.js";
2
+ import { detectTemplate } from "./detect.js";
3
+ import { postSynthChecks as postSynthCheckList } from "./lint/post-synth/index.js";
4
+ import { azureAuditCatalog } from "./lint/audit-catalog.js";
5
+ import { FLOCI_AZ_EMULATOR } from "./op/activities/floci-az.js";
6
+ import { createSkillsLoader } from "@intentius/chant/lexicon-plugin-helpers";
7
+ import { readFileSync, readdirSync, existsSync } from "fs";
8
+ import { join, dirname } from "path";
9
+ import { fileURLToPath } from "url";
10
+ import { moduleSourceDir } from "@intentius/chant/module-source";
11
+ import { azureSerializer } from "./serializer.js";
12
+ import { hardcodedLocationRule } from "./lint/rules/hardcoded-location.js";
13
+ import { storageHttpsRule } from "./lint/rules/storage-https.js";
14
+ import { nsgWildcardRule } from "./lint/rules/nsg-wildcard.js";
15
+ import { ArmParser } from "./import/parser.js";
16
+ import { ArmGenerator } from "./import/generator.js";
17
+ import { azureCompletions } from "./lsp/completions.js";
18
+ import { azureHover } from "./lsp/hover.js";
19
+ import { azureDeepNormalizationHooks, observeResourcesDeepAzure } from "./deep-observe.js";
20
+ import { AZURE_TAG_OWNERSHIP_KEYS } from "./ownership.js";
21
+ /**
22
+ * Azure Resource Manager lexicon plugin.
23
+ *
24
+ * Provides serializer, lint rules, template detection,
25
+ * import parsing, and code generation for Azure ARM templates.
26
+ */
27
+ export const azurePlugin = {
28
+ name: "azure",
29
+ ownershipChannel: { keys: AZURE_TAG_OWNERSHIP_KEYS, reads: ["exportResources"] },
30
+ emulator: FLOCI_AZ_EMULATOR,
31
+ auditCatalog: () => azureAuditCatalog,
32
+ serializer: azureSerializer,
33
+ lintRules() {
34
+ return [hardcodedLocationRule, storageHttpsRule, nsgWildcardRule];
35
+ },
36
+ /**
37
+ * chant #1044 — azure has no tagged templates at all, so before this every
38
+ * intrinsic use fell the whole file back to the run path. All nine opt
39
+ * their call form in.
40
+ *
41
+ * Audited against `IntrinsicDef.foldsAsCall` (core's lexicon.ts): each one
42
+ * stores its arguments and renders an ARM bracket expression at
43
+ * serialization time (../intrinsics.ts). Nothing is evaluated locally —
44
+ * `UniqueString(x)` emits `[uniqueString(x)]` for ARM to hash at deployment
45
+ * (it does not hash anything at build time), and `Reference`/`ListKeys`
46
+ * name a deployment-time read rather than performing one. Every call is a
47
+ * pure function of its arguments, so calling it while folding is
48
+ * indistinguishable from calling it during a real run of the file.
49
+ */
50
+ intrinsics() {
51
+ return [
52
+ { name: "ResourceId", description: "Generate a resource ID for an Azure resource", isTag: false, foldsAsCall: true },
53
+ { name: "Reference", description: "Get the runtime state of a deployed resource", isTag: false, foldsAsCall: true },
54
+ { name: "Concat", description: "Concatenate multiple string values", isTag: false, foldsAsCall: true },
55
+ { name: "ResourceGroup", description: "Get the current resource group object", isTag: false, foldsAsCall: true },
56
+ { name: "Subscription", description: "Get the current subscription object", isTag: false, foldsAsCall: true },
57
+ { name: "UniqueString", description: "Generate a deterministic hash string", isTag: false, foldsAsCall: true },
58
+ { name: "Format", description: "Format a string with arguments", isTag: false, foldsAsCall: true },
59
+ { name: "If", description: "Conditional expression", isTag: false, foldsAsCall: true },
60
+ { name: "ListKeys", description: "List access keys for a resource", isTag: false, foldsAsCall: true },
61
+ ];
62
+ },
63
+ pseudoParameters() {
64
+ return [
65
+ "Azure.ResourceGroupName",
66
+ "Azure.ResourceGroupLocation",
67
+ "Azure.ResourceGroupId",
68
+ "Azure.SubscriptionId",
69
+ "Azure.TenantId",
70
+ "Azure.DeploymentName",
71
+ ];
72
+ },
73
+ initTemplates(template) {
74
+ if (template === "web-app") {
75
+ return {
76
+ src: {
77
+ "main.ts": `/**
78
+ * Azure infrastructure — App Service web application
79
+ *
80
+ * Deploys an App Service Plan + Web App with:
81
+ * - Managed identity (SystemAssigned)
82
+ * - HTTPS-only traffic
83
+ * - Minimum TLS 1.2
84
+ * - FTPS disabled
85
+ */
86
+
87
+ import { AppService } from "@intentius/chant-lexicon-azure";
88
+ import { CoreParameter, StackOutput } from "@intentius/chant";
89
+
90
+ export const environment = new CoreParameter({
91
+ name: "environment",
92
+ type: "string",
93
+ default: "dev",
94
+ });
95
+
96
+ const { plan, webApp } = AppService({
97
+ name: "my-web-app",
98
+ sku: "B1",
99
+ runtime: "NODE|18-lts",
100
+ tags: { environment: "dev" },
101
+ });
102
+
103
+ export { plan, webApp };
104
+
105
+ export const appUrl = new StackOutput({
106
+ name: "appUrl",
107
+ value: \`https://my-web-app.azurewebsites.net\`,
108
+ });
109
+ `,
110
+ "tags.ts": `import { defaultTags } from "@intentius/chant-lexicon-azure";
111
+
112
+ export const tags = defaultTags([
113
+ { key: "Project", value: "my-web-app" },
114
+ { key: "Environment", value: "dev" },
115
+ ]);
116
+ `,
117
+ },
118
+ };
119
+ }
120
+ if (template === "aks-cluster") {
121
+ return {
122
+ src: {
123
+ "main.ts": `/**
124
+ * Azure infrastructure — AKS Kubernetes cluster
125
+ *
126
+ * Deploys an AKS cluster with:
127
+ * - Managed identity
128
+ * - RBAC enabled
129
+ * - Standard load balancer
130
+ * - Azure CNI networking
131
+ */
132
+
133
+ import { AksCluster, VnetDefault, ContainerRegistrySecure } from "@intentius/chant-lexicon-azure";
134
+ import { CoreParameter, StackOutput } from "@intentius/chant";
135
+
136
+ export const kubernetesVersion = new CoreParameter({
137
+ name: "kubernetesVersion",
138
+ type: "string",
139
+ default: "1.28",
140
+ });
141
+
142
+ const { virtualNetwork, subnet1, subnet2, nsg, routeTable } = VnetDefault({
143
+ name: "aks-vnet",
144
+ });
145
+
146
+ const { cluster } = AksCluster({
147
+ name: "my-aks",
148
+ nodeCount: 3,
149
+ vmSize: "Standard_D2s_v5",
150
+ tags: { workload: "kubernetes" },
151
+ });
152
+
153
+ const { registry } = ContainerRegistrySecure({
154
+ name: "myaksacr",
155
+ });
156
+
157
+ export { virtualNetwork, subnet1, subnet2, nsg, routeTable, cluster, registry };
158
+
159
+ export const clusterName = new StackOutput({
160
+ name: "clusterName",
161
+ value: "my-aks",
162
+ });
163
+ `,
164
+ "tags.ts": `import { defaultTags } from "@intentius/chant-lexicon-azure";
165
+
166
+ export const tags = defaultTags([
167
+ { key: "Project", value: "my-aks-cluster" },
168
+ { key: "Environment", value: "dev" },
169
+ ]);
170
+ `,
171
+ },
172
+ };
173
+ }
174
+ if (template === "function-app") {
175
+ return {
176
+ src: {
177
+ "main.ts": `/**
178
+ * Azure infrastructure — Consumption Function App
179
+ *
180
+ * Deploys a Function App with:
181
+ * - Consumption (Y1) App Service Plan
182
+ * - Storage Account for function runtime
183
+ * - Managed identity (SystemAssigned)
184
+ * - HTTPS-only traffic
185
+ * - Minimum TLS 1.2
186
+ * - FTPS disabled
187
+ */
188
+
189
+ import { FunctionApp } from "@intentius/chant-lexicon-azure";
190
+ import { CoreParameter, StackOutput } from "@intentius/chant";
191
+
192
+ export const environment = new CoreParameter({
193
+ name: "environment",
194
+ type: "string",
195
+ default: "dev",
196
+ });
197
+
198
+ const { plan, functionApp, storageAccount } = FunctionApp({
199
+ name: "my-function-app",
200
+ runtime: "node",
201
+ tags: { environment: "dev" },
202
+ });
203
+
204
+ export { plan, functionApp, storageAccount };
205
+
206
+ export const functionAppUrl = new StackOutput({
207
+ name: "functionAppUrl",
208
+ value: \`https://my-function-app.azurewebsites.net\`,
209
+ });
210
+ `,
211
+ "tags.ts": `import { defaultTags } from "@intentius/chant-lexicon-azure";
212
+
213
+ export const tags = defaultTags([
214
+ { key: "Project", value: "my-function-app" },
215
+ { key: "Environment", value: "dev" },
216
+ ]);
217
+ `,
218
+ },
219
+ };
220
+ }
221
+ // Default template — basic storage account
222
+ return {
223
+ src: {
224
+ "main.ts": `/**
225
+ * Azure infrastructure — Storage Account with secure defaults
226
+ */
227
+
228
+ import { StorageAccount, Azure } from "@intentius/chant-lexicon-azure";
229
+
230
+ export const storage = new StorageAccount({
231
+ name: "mystorageaccount",
232
+ location: Azure.ResourceGroupLocation,
233
+ kind: "StorageV2",
234
+ sku: { name: "Standard_LRS" },
235
+ supportsHttpsTrafficOnly: true,
236
+ minimumTlsVersion: "TLS1_2",
237
+ allowBlobPublicAccess: false,
238
+ });
239
+ `,
240
+ "tags.ts": `import { defaultTags } from "@intentius/chant-lexicon-azure";
241
+
242
+ export const tags = defaultTags([
243
+ { key: "Project", value: "my-app" },
244
+ { key: "Environment", value: "dev" },
245
+ ]);
246
+ `,
247
+ },
248
+ };
249
+ },
250
+ detectTemplate,
251
+ templateParser() {
252
+ return new ArmParser();
253
+ },
254
+ templateGenerator() {
255
+ return new ArmGenerator();
256
+ },
257
+ postSynthChecks() {
258
+ return postSynthCheckList;
259
+ },
260
+ skills: createSkillsLoader(import.meta.url, [
261
+ {
262
+ file: "chant-azure.md",
263
+ name: "chant-azure",
264
+ description: "Azure Resource Manager infrastructure generation with chant",
265
+ triggers: [
266
+ { type: "file-pattern", value: "*.azure.ts" },
267
+ { type: "context", value: "azure" },
268
+ ],
269
+ parameters: [
270
+ { name: "resourceType", type: "string", description: "Azure resource type to generate" },
271
+ ],
272
+ examples: [
273
+ {
274
+ title: "Storage Account",
275
+ input: "Create an Azure storage account with secure defaults",
276
+ output: 'import { StorageAccount } from "@intentius/chant-lexicon-azure";\n\nexport const storage = new StorageAccount({ ... });',
277
+ },
278
+ ],
279
+ },
280
+ {
281
+ file: "chant-azure-security.md",
282
+ name: "chant-azure-security",
283
+ description: "Azure security best practices for infrastructure",
284
+ triggers: [
285
+ { type: "context", value: "azure security" },
286
+ { type: "context", value: "azure identity" },
287
+ ],
288
+ parameters: [],
289
+ examples: [
290
+ {
291
+ title: "Secure Storage Account",
292
+ input: "Create a storage account with encryption and no public access",
293
+ output: 'import { StorageAccountSecure } from "@intentius/chant-lexicon-azure";\n\nconst { storageAccount } = StorageAccountSecure({ name: "mystorage" });',
294
+ },
295
+ ],
296
+ },
297
+ {
298
+ file: "chant-azure-patterns.md",
299
+ name: "chant-azure-patterns",
300
+ description: "Advanced Azure ARM template patterns",
301
+ triggers: [
302
+ { type: "context", value: "azure patterns" },
303
+ { type: "context", value: "azure composites" },
304
+ ],
305
+ parameters: [],
306
+ examples: [
307
+ {
308
+ title: "Linked Deployment",
309
+ input: "Deploy a child project as a linked template",
310
+ output: 'import { ChildProjectInstance } from "@intentius/chant";\n\nexport const deploy = new ChildProjectInstance({ project: "../network" });',
311
+ },
312
+ ],
313
+ },
314
+ {
315
+ file: "chant-azure-aks.md",
316
+ name: "chant-azure-aks",
317
+ description: "AKS end-to-end workflow — deploy ARM template, configure kubectl, deploy K8s workloads",
318
+ triggers: [
319
+ { type: "context", value: "aks" },
320
+ { type: "context", value: "azure kubernetes" },
321
+ { type: "context", value: "agic" },
322
+ ],
323
+ parameters: [],
324
+ examples: [
325
+ {
326
+ title: "Deploy AKS microservice",
327
+ input: "Deploy an AKS project end-to-end",
328
+ output: "npm run deploy",
329
+ },
330
+ ],
331
+ },
332
+ ]),
333
+ completionProvider(ctx) {
334
+ return azureCompletions(ctx);
335
+ },
336
+ hoverProvider(ctx) {
337
+ return azureHover(ctx);
338
+ },
339
+ composites() {
340
+ return compositeCatalog;
341
+ },
342
+ mcpTools() {
343
+ return [{
344
+ name: "azure:lookup-resource",
345
+ description: "Look up an Azure resource type by name",
346
+ inputSchema: {
347
+ type: "object",
348
+ properties: {
349
+ query: { type: "string", description: "Resource name to search for (e.g. 'StorageAccount', 'VirtualMachine')" },
350
+ },
351
+ required: ["query"],
352
+ },
353
+ handler: async (args) => {
354
+ const dir = moduleSourceDir(import.meta.url);
355
+ try {
356
+ const lexicon = JSON.parse(readFileSync(join(dir, "generated", "lexicon-azure.json"), "utf-8"));
357
+ const query = args.query.toLowerCase();
358
+ const matches = Object.entries(lexicon)
359
+ .filter(([name]) => name.toLowerCase().includes(query))
360
+ .slice(0, 10);
361
+ return JSON.stringify(matches, null, 2);
362
+ }
363
+ catch {
364
+ return "Lexicon not available — run `npm run generate` first.";
365
+ }
366
+ },
367
+ }];
368
+ },
369
+ mcpResources() {
370
+ return [
371
+ {
372
+ uri: "resource-catalog",
373
+ name: "Azure Resource Catalog",
374
+ description: "All available Azure resource types",
375
+ mimeType: "application/json",
376
+ handler: async () => {
377
+ const dir = moduleSourceDir(import.meta.url);
378
+ try {
379
+ return readFileSync(join(dir, "generated", "lexicon-azure.json"), "utf-8");
380
+ }
381
+ catch {
382
+ return "{}";
383
+ }
384
+ },
385
+ },
386
+ {
387
+ uri: "examples",
388
+ name: "Azure Example Projects",
389
+ description: "Example project summaries with code snippets for Azure ARM templates",
390
+ mimeType: "application/json",
391
+ handler: async () => {
392
+ const pkgDir = dirname(dirname(fileURLToPath(import.meta.url)));
393
+ const examplesDir = join(pkgDir, "examples");
394
+ const examples = [];
395
+ try {
396
+ if (!existsSync(examplesDir))
397
+ return "[]";
398
+ const dirs = readdirSync(examplesDir, { withFileTypes: true })
399
+ .filter((e) => e.isDirectory());
400
+ for (const dir of dirs) {
401
+ const exDir = join(examplesDir, dir.name);
402
+ const srcDir = join(exDir, "src");
403
+ const files = {};
404
+ const scanDir = existsSync(srcDir) ? srcDir : exDir;
405
+ const entries = readdirSync(scanDir).filter((f) => f.endsWith(".ts"));
406
+ for (const f of entries) {
407
+ try {
408
+ files[f] = readFileSync(join(scanDir, f), "utf-8");
409
+ }
410
+ catch { /* skip unreadable */ }
411
+ }
412
+ if (Object.keys(files).length > 0) {
413
+ examples.push({ name: dir.name, files });
414
+ }
415
+ }
416
+ return JSON.stringify(examples, null, 2);
417
+ }
418
+ catch {
419
+ return "[]";
420
+ }
421
+ },
422
+ },
423
+ ];
424
+ },
425
+ async generate(opts) {
426
+ const { generate: gen, writeGeneratedFiles } = await import("./codegen/generate.js");
427
+ const result = await gen(opts);
428
+ writeGeneratedFiles(result, dirname(dirname(fileURLToPath(import.meta.url))));
429
+ },
430
+ async validate() {
431
+ const { validate } = await import("./validate.js");
432
+ await validate();
433
+ },
434
+ async coverage(options) {
435
+ const { analyzeAzureCoverage } = await import("./coverage.js");
436
+ await analyzeAzureCoverage({ verbose: options?.verbose, minOverall: options?.minOverall });
437
+ },
438
+ async package(opts) {
439
+ const { packageLexicon } = await import("./codegen/package.js");
440
+ await packageLexicon(opts);
441
+ },
442
+ async describeResources(options) {
443
+ const { describeResources } = await import("./describe-resources.js");
444
+ return describeResources(options);
445
+ },
446
+ /**
447
+ * Property-level live read (#1086) — `az resource show` already returns
448
+ * the full ARM resource; this normalizes it. Implementation in
449
+ * ./deep-observe.ts.
450
+ */
451
+ async observeResourcesDeep(options) {
452
+ return observeResourcesDeepAzure({
453
+ environment: options.environment,
454
+ entityNames: options.entityNames,
455
+ entities: options.entities,
456
+ });
457
+ },
458
+ /** The noise rules the deep pass applies to both the live and declared trees. */
459
+ deepNormalizationHooks: azureDeepNormalizationHooks,
460
+ async exportResources(options) {
461
+ const { exportResources } = await import("./export-resources.js");
462
+ return exportResources(options);
463
+ },
464
+ /**
465
+ * The generator has always existed in src/codegen/docs.ts; only the package
466
+ * script reached it, so `plugin.docs()` was a no-op for azure alone (#1342).
467
+ */
468
+ async docs(options) {
469
+ const { generateDocs } = await import("./codegen/docs.js");
470
+ await generateDocs(options);
471
+ },
472
+ };
package/dist/pseudo.js ADDED
@@ -0,0 +1,40 @@
1
+ /**
2
+ * ARM pseudo-parameters — references to deployment-time values.
3
+ *
4
+ * These serialize to ARM template expressions:
5
+ * Azure.ResourceGroupName → "[resourceGroup().name]"
6
+ * Azure.SubscriptionId → "[subscription().subscriptionId]"
7
+ */
8
+ var _a;
9
+ import { INTRINSIC_MARKER } from "@intentius/chant/intrinsic";
10
+ class ArmPseudoParameter {
11
+ constructor(expression, displayName) {
12
+ this[_a] = true;
13
+ this.expression = expression;
14
+ this.displayName = displayName;
15
+ }
16
+ toJSON() {
17
+ return this.expression;
18
+ }
19
+ toString() {
20
+ return this.displayName;
21
+ }
22
+ }
23
+ _a = INTRINSIC_MARKER;
24
+ export const ResourceGroupName = new ArmPseudoParameter("[resourceGroup().name]", "Azure.ResourceGroupName");
25
+ export const ResourceGroupLocation = new ArmPseudoParameter("[resourceGroup().location]", "Azure.ResourceGroupLocation");
26
+ export const ResourceGroupId = new ArmPseudoParameter("[resourceGroup().id]", "Azure.ResourceGroupId");
27
+ export const SubscriptionId = new ArmPseudoParameter("[subscription().subscriptionId]", "Azure.SubscriptionId");
28
+ export const TenantId = new ArmPseudoParameter("[subscription().tenantId]", "Azure.TenantId");
29
+ export const DeploymentName = new ArmPseudoParameter("[deployment().name]", "Azure.DeploymentName");
30
+ /**
31
+ * Azure namespace containing all pseudo-parameters.
32
+ */
33
+ export const Azure = {
34
+ ResourceGroupName,
35
+ ResourceGroupLocation,
36
+ ResourceGroupId,
37
+ SubscriptionId,
38
+ TenantId,
39
+ DeploymentName,
40
+ };