@ankhorage/infra 1.0.6 → 2.0.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 (60) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +4 -1
  3. package/dist/adapters/minikube/auth/index.d.ts.map +1 -1
  4. package/dist/adapters/minikube/auth/index.js +13 -1
  5. package/dist/adapters/minikube/auth/index.js.map +1 -1
  6. package/dist/adapters/minikube/auth/oauthRuntime.d.ts +4 -0
  7. package/dist/adapters/minikube/auth/oauthRuntime.d.ts.map +1 -0
  8. package/dist/adapters/minikube/auth/oauthRuntime.js +144 -0
  9. package/dist/adapters/minikube/auth/oauthRuntime.js.map +1 -0
  10. package/dist/adapters/minikube/index.d.ts.map +1 -1
  11. package/dist/adapters/minikube/index.js +15 -6
  12. package/dist/adapters/minikube/index.js.map +1 -1
  13. package/dist/authRedirects.d.ts +19 -0
  14. package/dist/authRedirects.d.ts.map +1 -0
  15. package/dist/authRedirects.js +80 -0
  16. package/dist/authRedirects.js.map +1 -0
  17. package/dist/generatedApiDatabase.d.ts +20 -0
  18. package/dist/generatedApiDatabase.d.ts.map +1 -0
  19. package/dist/generatedApiDatabase.js +343 -0
  20. package/dist/generatedApiDatabase.js.map +1 -0
  21. package/dist/index.d.ts +2 -2
  22. package/dist/index.d.ts.map +1 -1
  23. package/dist/index.js +2 -1
  24. package/dist/index.js.map +1 -1
  25. package/dist/project.d.ts +1 -1
  26. package/dist/project.d.ts.map +1 -1
  27. package/dist/project.js +3 -0
  28. package/dist/project.js.map +1 -1
  29. package/dist/testSupport.d.ts.map +1 -1
  30. package/dist/testSupport.js +1 -0
  31. package/dist/testSupport.js.map +1 -1
  32. package/dist/types.d.ts +1 -1
  33. package/dist/types.d.ts.map +1 -1
  34. package/dist/types.js.map +1 -1
  35. package/package.json +2 -2
  36. package/src/adapters/minikube/auth/index.ts +14 -1
  37. package/src/adapters/minikube/auth/oauthRuntime.ts +169 -0
  38. package/src/adapters/minikube/auth/supabase/oauthRuntime.test.ts +143 -0
  39. package/src/adapters/minikube/auth/supabase/providerAssignments.test.ts +36 -0
  40. package/src/adapters/minikube/index.ts +20 -6
  41. package/src/authRedirects.test.ts +63 -0
  42. package/src/authRedirects.ts +113 -0
  43. package/src/generatedApiDatabase.test.ts +355 -0
  44. package/src/generatedApiDatabase.ts +558 -0
  45. package/src/index.ts +14 -2
  46. package/src/project.ts +3 -1
  47. package/src/testSupport.ts +1 -0
  48. package/src/types.ts +1 -1
  49. package/dist/apiArtifacts.d.ts +0 -8
  50. package/dist/apiArtifacts.d.ts.map +0 -1
  51. package/dist/apiArtifacts.js +0 -35
  52. package/dist/apiArtifacts.js.map +0 -1
  53. package/dist/apis.d.ts +0 -11
  54. package/dist/apis.d.ts.map +0 -1
  55. package/dist/apis.js +0 -354
  56. package/dist/apis.js.map +0 -1
  57. package/src/apiArtifacts.test.ts +0 -54
  58. package/src/apiArtifacts.ts +0 -107
  59. package/src/apis.test.ts +0 -212
  60. package/src/apis.ts +0 -534
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # @ankhorage/infra
2
2
 
3
+ ## 2.0.0
4
+
5
+ ### Major Changes
6
+
7
+ - a4dda40: Consume the canonical generated API desired-state contract, generate deterministic Supabase/Postgres database artifacts, and remove the obsolete generated API handler/OpenAPI artifact surface.
8
+
9
+ ## 1.1.0
10
+
11
+ ### Minor Changes
12
+
13
+ - bd82fe0: Add canonical environment-aware Auth redirect configuration and reconcile Minikube GoTrue callback settings through a forced, bounded deployment rollout.
14
+
3
15
  ## 1.0.6
4
16
 
5
17
  ### Patch Changes
package/README.md CHANGED
@@ -3,7 +3,7 @@
3
3
 
4
4
  # INFRA
5
5
 
6
- ![license: MIT](././paradox/badges/license.svg) ![npm: v1.0.4](././paradox/badges/npm.svg) ![runtime: bun](././paradox/badges/runtime.svg) ![typescript: strict](././paradox/badges/typescript.svg) ![eslint: checked](././paradox/badges/eslint.svg) ![prettier: checked](././paradox/badges/prettier.svg) ![build: checked](././paradox/badges/build.svg) ![tests: checked](././paradox/badges/tests.svg) ![docs: paradox](././paradox/badges/docs.svg)
6
+ ![license: MIT](././paradox/badges/license.svg) ![npm: v1.1.0](././paradox/badges/npm.svg) ![runtime: bun](././paradox/badges/runtime.svg) ![typescript: strict](././paradox/badges/typescript.svg) ![eslint: checked](././paradox/badges/eslint.svg) ![prettier: checked](././paradox/badges/prettier.svg) ![build: checked](././paradox/badges/build.svg) ![tests: checked](././paradox/badges/tests.svg) ![docs: paradox](././paradox/badges/docs.svg)
7
7
 
8
8
  Executable infra provider and standalone CLI for Ankhorage project workflows.
9
9
 
@@ -57,3 +57,6 @@ bunx @ankhorage/infra
57
57
  - [Export graph](././paradox/diagrams/export-graph.mmd)
58
58
  - [ankhorage-infra sequence](././paradox/diagrams/sequences/ankhorage-infra.mmd)
59
59
  - [createInfraSecretStoreAdapter sequence](././paradox/diagrams/sequences/create-infra-secret-store-adapter.mmd)
60
+ - [getLocalAuthRedirectPatterns sequence](././paradox/diagrams/sequences/get-local-auth-redirect-patterns.mmd)
61
+ - [normalizeAuthCallbackRoute sequence](././paradox/diagrams/sequences/normalize-auth-callback-route.mmd)
62
+ - [resolveAuthRedirectConfiguration sequence](././paradox/diagrams/sequences/resolve-auth-redirect-configuration.mmd)
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/adapters/minikube/auth/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACzD,OAAO,EAA0B,KAAK,wBAAwB,EAAE,MAAM,cAAc,CAAC;AAGrF,wBAAgB,6BAA6B,CAAC,IAAI,EAAE;IAClD,QAAQ,EAAE,kBAAkB,CAAC;IAC7B,SAAS,EAAE,MAAM,CAAC;CACnB,GAAG,wBAAwB,CAe3B"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/adapters/minikube/auth/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACzD,OAAO,EAA0B,KAAK,wBAAwB,EAAE,MAAM,cAAc,CAAC;AAIrF,wBAAgB,6BAA6B,CAAC,IAAI,EAAE;IAClD,QAAQ,EAAE,kBAAkB,CAAC;IAC7B,SAAS,EAAE,MAAM,CAAC;CACnB,GAAG,wBAAwB,CA2B3B"}
@@ -1,4 +1,5 @@
1
1
  import { emptyMinikubeArtifacts } from '../contracts';
2
+ import { generateSupabaseOAuthRuntimeArtifacts } from './oauthRuntime';
2
3
  import { generateSupabaseAuthArtifacts } from './supabase';
3
4
  export function generateAuthProviderArtifacts(args) {
4
5
  const { manifest, namespace } = args;
@@ -9,6 +10,17 @@ export function generateAuthProviderArtifacts(args) {
9
10
  if (auth.provider !== 'supabase') {
10
11
  throw new Error(`Unsupported auth provider for minikube adapter: "${auth.provider}". Only "supabase" is currently supported.`);
11
12
  }
12
- return generateSupabaseAuthArtifacts({ manifest, namespace });
13
+ const providerArtifacts = generateSupabaseAuthArtifacts({ manifest, namespace });
14
+ const oauthArtifacts = generateSupabaseOAuthRuntimeArtifacts(manifest);
15
+ return {
16
+ files: [...providerArtifacts.files, ...oauthArtifacts.files],
17
+ resources: [...providerArtifacts.resources, ...oauthArtifacts.resources],
18
+ providerLifecycle: [
19
+ ...providerArtifacts.providerLifecycle,
20
+ ...oauthArtifacts.providerLifecycle,
21
+ ],
22
+ envEntries: [...providerArtifacts.envEntries, ...oauthArtifacts.envEntries],
23
+ warnings: [...providerArtifacts.warnings, ...oauthArtifacts.warnings],
24
+ };
13
25
  }
14
26
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/adapters/minikube/auth/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,sBAAsB,EAAiC,MAAM,cAAc,CAAC;AACrF,OAAO,EAAE,6BAA6B,EAAE,MAAM,YAAY,CAAC;AAE3D,MAAM,UAAU,6BAA6B,CAAC,IAG7C;IACC,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,IAAI,CAAC;IACrC,MAAM,EAAE,IAAI,EAAE,GAAG,QAAQ,CAAC;IAE1B,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,OAAO,sBAAsB,EAAE,CAAC;IAClC,CAAC;IAED,IAAI,IAAI,CAAC,QAAQ,KAAK,UAAU,EAAE,CAAC;QACjC,MAAM,IAAI,KAAK,CACb,oDAAoD,IAAI,CAAC,QAAQ,4CAA4C,CAC9G,CAAC;IACJ,CAAC;IAED,OAAO,6BAA6B,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,CAAC;AAChE,CAAC","sourcesContent":["import type { InfraManifestInput } from '../../../types';\nimport { emptyMinikubeArtifacts, type MinikubeAdapterArtifacts } from '../contracts';\nimport { generateSupabaseAuthArtifacts } from './supabase';\n\nexport function generateAuthProviderArtifacts(args: {\n manifest: InfraManifestInput;\n namespace: string;\n}): MinikubeAdapterArtifacts {\n const { manifest, namespace } = args;\n const { auth } = manifest;\n\n if (!auth) {\n return emptyMinikubeArtifacts();\n }\n\n if (auth.provider !== 'supabase') {\n throw new Error(\n `Unsupported auth provider for minikube adapter: \"${auth.provider}\". Only \"supabase\" is currently supported.`,\n );\n }\n\n return generateSupabaseAuthArtifacts({ manifest, namespace });\n}\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/adapters/minikube/auth/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,sBAAsB,EAAiC,MAAM,cAAc,CAAC;AACrF,OAAO,EAAE,qCAAqC,EAAE,MAAM,gBAAgB,CAAC;AACvE,OAAO,EAAE,6BAA6B,EAAE,MAAM,YAAY,CAAC;AAE3D,MAAM,UAAU,6BAA6B,CAAC,IAG7C;IACC,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,IAAI,CAAC;IACrC,MAAM,EAAE,IAAI,EAAE,GAAG,QAAQ,CAAC;IAE1B,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,OAAO,sBAAsB,EAAE,CAAC;IAClC,CAAC;IAED,IAAI,IAAI,CAAC,QAAQ,KAAK,UAAU,EAAE,CAAC;QACjC,MAAM,IAAI,KAAK,CACb,oDAAoD,IAAI,CAAC,QAAQ,4CAA4C,CAC9G,CAAC;IACJ,CAAC;IAED,MAAM,iBAAiB,GAAG,6BAA6B,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,CAAC;IACjF,MAAM,cAAc,GAAG,qCAAqC,CAAC,QAAQ,CAAC,CAAC;IAEvE,OAAO;QACL,KAAK,EAAE,CAAC,GAAG,iBAAiB,CAAC,KAAK,EAAE,GAAG,cAAc,CAAC,KAAK,CAAC;QAC5D,SAAS,EAAE,CAAC,GAAG,iBAAiB,CAAC,SAAS,EAAE,GAAG,cAAc,CAAC,SAAS,CAAC;QACxE,iBAAiB,EAAE;YACjB,GAAG,iBAAiB,CAAC,iBAAiB;YACtC,GAAG,cAAc,CAAC,iBAAiB;SACpC;QACD,UAAU,EAAE,CAAC,GAAG,iBAAiB,CAAC,UAAU,EAAE,GAAG,cAAc,CAAC,UAAU,CAAC;QAC3E,QAAQ,EAAE,CAAC,GAAG,iBAAiB,CAAC,QAAQ,EAAE,GAAG,cAAc,CAAC,QAAQ,CAAC;KACtE,CAAC;AACJ,CAAC","sourcesContent":["import type { InfraManifestInput } from '../../../types';\nimport { emptyMinikubeArtifacts, type MinikubeAdapterArtifacts } from '../contracts';\nimport { generateSupabaseOAuthRuntimeArtifacts } from './oauthRuntime';\nimport { generateSupabaseAuthArtifacts } from './supabase';\n\nexport function generateAuthProviderArtifacts(args: {\n manifest: InfraManifestInput;\n namespace: string;\n}): MinikubeAdapterArtifacts {\n const { manifest, namespace } = args;\n const { auth } = manifest;\n\n if (!auth) {\n return emptyMinikubeArtifacts();\n }\n\n if (auth.provider !== 'supabase') {\n throw new Error(\n `Unsupported auth provider for minikube adapter: \"${auth.provider}\". Only \"supabase\" is currently supported.`,\n );\n }\n\n const providerArtifacts = generateSupabaseAuthArtifacts({ manifest, namespace });\n const oauthArtifacts = generateSupabaseOAuthRuntimeArtifacts(manifest);\n\n return {\n files: [...providerArtifacts.files, ...oauthArtifacts.files],\n resources: [...providerArtifacts.resources, ...oauthArtifacts.resources],\n providerLifecycle: [\n ...providerArtifacts.providerLifecycle,\n ...oauthArtifacts.providerLifecycle,\n ],\n envEntries: [...providerArtifacts.envEntries, ...oauthArtifacts.envEntries],\n warnings: [...providerArtifacts.warnings, ...oauthArtifacts.warnings],\n };\n}\n"]}
@@ -0,0 +1,4 @@
1
+ import type { InfraManifestInput } from '../../../types';
2
+ import type { MinikubeAdapterArtifacts } from '../contracts';
3
+ export declare function generateSupabaseOAuthRuntimeArtifacts(manifest: InfraManifestInput): MinikubeAdapterArtifacts;
4
+ //# sourceMappingURL=oauthRuntime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oauthRuntime.d.ts","sourceRoot":"","sources":["../../../../src/adapters/minikube/auth/oauthRuntime.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACzD,OAAO,KAAK,EAAE,wBAAwB,EAA6B,MAAM,cAAc,CAAC;AAQxF,wBAAgB,qCAAqC,CACnD,QAAQ,EAAE,kBAAkB,GAC3B,wBAAwB,CAwB1B"}
@@ -0,0 +1,144 @@
1
+ import { getLocalAuthRedirectPatterns, normalizeAuthCallbackRoute } from '../../../authRedirects';
2
+ export function generateSupabaseOAuthRuntimeArtifacts(manifest) {
3
+ const oauthRuntime = resolveOAuthRuntimeModel(manifest);
4
+ if (!oauthRuntime) {
5
+ return {
6
+ files: [],
7
+ resources: [],
8
+ providerLifecycle: [],
9
+ envEntries: [],
10
+ warnings: [],
11
+ };
12
+ }
13
+ return {
14
+ files: [
15
+ {
16
+ path: 'infra/minikube/auth/oauth-runtime.md',
17
+ content: getOAuthRuntimeGuide(oauthRuntime),
18
+ },
19
+ ],
20
+ resources: [],
21
+ providerLifecycle: [getOAuthProviderLifecycle(oauthRuntime)],
22
+ envEntries: [],
23
+ warnings: [],
24
+ };
25
+ }
26
+ function resolveOAuthRuntimeModel(manifest) {
27
+ const oauth = manifest.auth?.oauth;
28
+ if (!oauth?.enabled)
29
+ return null;
30
+ const providers = oauth.providers.filter((provider) => provider.enabled !== false);
31
+ if (providers.length === 0)
32
+ return null;
33
+ const callbackRoute = normalizeAuthCallbackRoute(oauth.callbackRoute);
34
+ const envPrefixes = providers.map((provider) => {
35
+ const prefix = provider.id
36
+ .trim()
37
+ .toUpperCase()
38
+ .replace(/[^A-Z0-9]+/gu, '_')
39
+ .replace(/^_+|_+$/gu, '');
40
+ if (!prefix) {
41
+ throw new Error(`OAuth provider "${provider.id}" cannot be mapped to GoTrue environment keys.`);
42
+ }
43
+ return prefix;
44
+ });
45
+ return {
46
+ callbackRoute,
47
+ envPrefixes,
48
+ localRedirectPatterns: getLocalAuthRedirectPatterns(callbackRoute),
49
+ };
50
+ }
51
+ function getOAuthProviderLifecycle(oauthRuntime) {
52
+ return {
53
+ id: 'supabase-auth',
54
+ namespace: 'supabase',
55
+ endpoints: [],
56
+ readinessChecks: [
57
+ {
58
+ label: 'GoTrue',
59
+ namespace: 'supabase',
60
+ resource: 'deployment/auth',
61
+ timeoutSeconds: 600,
62
+ },
63
+ ],
64
+ migrationCommands: [],
65
+ reconciliationCommands: [
66
+ {
67
+ label: 'OAuth redirect and runtime rollout reconciliation',
68
+ command: getOAuthRuntimeReconciliationCommand(oauthRuntime),
69
+ },
70
+ ],
71
+ statusChecks: [
72
+ {
73
+ label: 'OAuth redirect configuration',
74
+ command: getOAuthRuntimeStatusCommand(oauthRuntime),
75
+ },
76
+ ],
77
+ };
78
+ }
79
+ function getOAuthRuntimeReconciliationCommand(oauthRuntime) {
80
+ const localPatterns = oauthRuntime.localRedirectPatterns.join(',');
81
+ const providerRedirectAssignments = oauthRuntime.envPrefixes
82
+ .map((prefix) => `GOTRUE_EXTERNAL_${prefix}_REDIRECT_URI="\${oauth_provider_callback}"`)
83
+ .join(' ');
84
+ const providerExports = oauthRuntime.envPrefixes
85
+ .map((prefix) => `export GOTRUE_EXTERNAL_${prefix}_REDIRECT_URI="\${oauth_provider_callback}"
86
+ write_env_value GOTRUE_EXTERNAL_${prefix}_REDIRECT_URI "\${oauth_provider_callback}"`)
87
+ .join('\n');
88
+ return `oauth_callback_route='${oauthRuntime.callbackRoute}'
89
+ oauth_callback_path="\${oauth_callback_route#/}"
90
+ oauth_site_url="\${SITE_URL%/}"
91
+ oauth_provider_callback="\${API_EXTERNAL_URL%/}/callback"
92
+ oauth_redirect_allow_list="\${oauth_site_url},\${oauth_site_url}/\${oauth_callback_path},${localPatterns}"
93
+ if [[ -n "\${OAUTH_NATIVE_REDIRECT_URLS:-}" ]]; then
94
+ oauth_redirect_allow_list="\${oauth_redirect_allow_list},\${OAUTH_NATIVE_REDIRECT_URLS}"
95
+ fi
96
+ export ADDITIONAL_REDIRECT_URLS="\${oauth_redirect_allow_list}"
97
+ write_env_value ADDITIONAL_REDIRECT_URLS "\${oauth_redirect_allow_list}"
98
+ ${providerExports}
99
+ kubectl --context "\${PROFILE}" -n supabase set env deployment/auth \\
100
+ API_EXTERNAL_URL="\${API_EXTERNAL_URL}" \\
101
+ GOTRUE_SITE_URL="\${SITE_URL}" \\
102
+ GOTRUE_URI_ALLOW_LIST="\${oauth_redirect_allow_list}" \\
103
+ GOTRUE_JWT_ISSUER="\${API_EXTERNAL_URL}" \\
104
+ ${providerRedirectAssignments} >/dev/null
105
+ kubectl --context "\${PROFILE}" -n supabase rollout restart deployment/auth >/dev/null
106
+ kubectl --context "\${PROFILE}" -n supabase rollout status deployment/auth --timeout=600s`;
107
+ }
108
+ function getOAuthRuntimeStatusCommand(oauthRuntime) {
109
+ return `oauth_callback_route='${oauthRuntime.callbackRoute}'
110
+ oauth_callback_path="\${oauth_callback_route#/}"
111
+ if [[ -n "\${API_EXTERNAL_URL:-}" ]]; then
112
+ echo "- provider supabase-auth/provider-callback: \${API_EXTERNAL_URL%/}/callback"
113
+ else
114
+ echo "- provider supabase-auth/provider-callback: unavailable"
115
+ fi
116
+ if [[ -n "\${SITE_URL:-}" ]]; then
117
+ echo "- provider supabase-auth/app-callback: \${SITE_URL%/}/\${oauth_callback_path}"
118
+ else
119
+ echo "- provider supabase-auth/app-callback: unavailable"
120
+ fi
121
+ echo "- provider supabase-auth/local-callback-patterns: ${oauthRuntime.localRedirectPatterns.join(',')}"`;
122
+ }
123
+ function getOAuthRuntimeGuide(oauthRuntime) {
124
+ const localPatterns = oauthRuntime.localRedirectPatterns
125
+ .map((pattern) => `- \`${pattern}\``)
126
+ .join('\n');
127
+ return `# Supabase OAuth Runtime Reconciliation
128
+
129
+ The provider callback is derived from the active project gateway as
130
+ \`\${API_EXTERNAL_URL%/}/callback\`, which resolves to the project-owned
131
+ \`/auth/v1/callback\` endpoint. GoTrue-to-app redirects use the configured callback route
132
+ \`${oauthRuntime.callbackRoute}\`.
133
+
134
+ Local Minikube reconciliation adds only callback-scoped loopback patterns:
135
+
136
+ ${localPatterns}
137
+
138
+ Native callback URIs may be supplied through \`OAUTH_NATIVE_REDIRECT_URLS\`. The generated
139
+ provider lifecycle writes only redirect metadata, never OAuth client secrets. It updates the
140
+ GoTrue deployment environment, forces \`deployment/auth\` to restart, and waits up to 600
141
+ seconds for the rollout. A failed rollout stops Infra Up before its success message.
142
+ `;
143
+ }
144
+ //# sourceMappingURL=oauthRuntime.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oauthRuntime.js","sourceRoot":"","sources":["../../../../src/adapters/minikube/auth/oauthRuntime.ts"],"names":[],"mappings":"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","sourcesContent":["import { getLocalAuthRedirectPatterns, normalizeAuthCallbackRoute } from '../../../authRedirects';\nimport type { InfraManifestInput } from '../../../types';\nimport type { MinikubeAdapterArtifacts, MinikubeProviderLifecycle } from '../contracts';\n\ninterface SupabaseOAuthRuntimeModel {\n callbackRoute: string;\n envPrefixes: readonly string[];\n localRedirectPatterns: readonly string[];\n}\n\nexport function generateSupabaseOAuthRuntimeArtifacts(\n manifest: InfraManifestInput,\n): MinikubeAdapterArtifacts {\n const oauthRuntime = resolveOAuthRuntimeModel(manifest);\n if (!oauthRuntime) {\n return {\n files: [],\n resources: [],\n providerLifecycle: [],\n envEntries: [],\n warnings: [],\n };\n }\n\n return {\n files: [\n {\n path: 'infra/minikube/auth/oauth-runtime.md',\n content: getOAuthRuntimeGuide(oauthRuntime),\n },\n ],\n resources: [],\n providerLifecycle: [getOAuthProviderLifecycle(oauthRuntime)],\n envEntries: [],\n warnings: [],\n };\n}\n\nfunction resolveOAuthRuntimeModel(manifest: InfraManifestInput): SupabaseOAuthRuntimeModel | null {\n const oauth = manifest.auth?.oauth;\n if (!oauth?.enabled) return null;\n\n const providers = oauth.providers.filter((provider) => provider.enabled !== false);\n if (providers.length === 0) return null;\n\n const callbackRoute = normalizeAuthCallbackRoute(oauth.callbackRoute);\n const envPrefixes = providers.map((provider) => {\n const prefix = provider.id\n .trim()\n .toUpperCase()\n .replace(/[^A-Z0-9]+/gu, '_')\n .replace(/^_+|_+$/gu, '');\n if (!prefix) {\n throw new Error(\n `OAuth provider \"${provider.id}\" cannot be mapped to GoTrue environment keys.`,\n );\n }\n return prefix;\n });\n\n return {\n callbackRoute,\n envPrefixes,\n localRedirectPatterns: getLocalAuthRedirectPatterns(callbackRoute),\n };\n}\n\nfunction getOAuthProviderLifecycle(\n oauthRuntime: SupabaseOAuthRuntimeModel,\n): MinikubeProviderLifecycle {\n return {\n id: 'supabase-auth',\n namespace: 'supabase',\n endpoints: [],\n readinessChecks: [\n {\n label: 'GoTrue',\n namespace: 'supabase',\n resource: 'deployment/auth',\n timeoutSeconds: 600,\n },\n ],\n migrationCommands: [],\n reconciliationCommands: [\n {\n label: 'OAuth redirect and runtime rollout reconciliation',\n command: getOAuthRuntimeReconciliationCommand(oauthRuntime),\n },\n ],\n statusChecks: [\n {\n label: 'OAuth redirect configuration',\n command: getOAuthRuntimeStatusCommand(oauthRuntime),\n },\n ],\n };\n}\n\nfunction getOAuthRuntimeReconciliationCommand(oauthRuntime: SupabaseOAuthRuntimeModel): string {\n const localPatterns = oauthRuntime.localRedirectPatterns.join(',');\n const providerRedirectAssignments = oauthRuntime.envPrefixes\n .map((prefix) => `GOTRUE_EXTERNAL_${prefix}_REDIRECT_URI=\"\\${oauth_provider_callback}\"`)\n .join(' ');\n const providerExports = oauthRuntime.envPrefixes\n .map(\n (prefix) => `export GOTRUE_EXTERNAL_${prefix}_REDIRECT_URI=\"\\${oauth_provider_callback}\"\nwrite_env_value GOTRUE_EXTERNAL_${prefix}_REDIRECT_URI \"\\${oauth_provider_callback}\"`,\n )\n .join('\\n');\n\n return `oauth_callback_route='${oauthRuntime.callbackRoute}'\noauth_callback_path=\"\\${oauth_callback_route#/}\"\noauth_site_url=\"\\${SITE_URL%/}\"\noauth_provider_callback=\"\\${API_EXTERNAL_URL%/}/callback\"\noauth_redirect_allow_list=\"\\${oauth_site_url},\\${oauth_site_url}/\\${oauth_callback_path},${localPatterns}\"\nif [[ -n \"\\${OAUTH_NATIVE_REDIRECT_URLS:-}\" ]]; then\n oauth_redirect_allow_list=\"\\${oauth_redirect_allow_list},\\${OAUTH_NATIVE_REDIRECT_URLS}\"\nfi\nexport ADDITIONAL_REDIRECT_URLS=\"\\${oauth_redirect_allow_list}\"\nwrite_env_value ADDITIONAL_REDIRECT_URLS \"\\${oauth_redirect_allow_list}\"\n${providerExports}\nkubectl --context \"\\${PROFILE}\" -n supabase set env deployment/auth \\\\\n API_EXTERNAL_URL=\"\\${API_EXTERNAL_URL}\" \\\\\n GOTRUE_SITE_URL=\"\\${SITE_URL}\" \\\\\n GOTRUE_URI_ALLOW_LIST=\"\\${oauth_redirect_allow_list}\" \\\\\n GOTRUE_JWT_ISSUER=\"\\${API_EXTERNAL_URL}\" \\\\\n ${providerRedirectAssignments} >/dev/null\nkubectl --context \"\\${PROFILE}\" -n supabase rollout restart deployment/auth >/dev/null\nkubectl --context \"\\${PROFILE}\" -n supabase rollout status deployment/auth --timeout=600s`;\n}\n\nfunction getOAuthRuntimeStatusCommand(oauthRuntime: SupabaseOAuthRuntimeModel): string {\n return `oauth_callback_route='${oauthRuntime.callbackRoute}'\noauth_callback_path=\"\\${oauth_callback_route#/}\"\nif [[ -n \"\\${API_EXTERNAL_URL:-}\" ]]; then\n echo \"- provider supabase-auth/provider-callback: \\${API_EXTERNAL_URL%/}/callback\"\nelse\n echo \"- provider supabase-auth/provider-callback: unavailable\"\nfi\nif [[ -n \"\\${SITE_URL:-}\" ]]; then\n echo \"- provider supabase-auth/app-callback: \\${SITE_URL%/}/\\${oauth_callback_path}\"\nelse\n echo \"- provider supabase-auth/app-callback: unavailable\"\nfi\necho \"- provider supabase-auth/local-callback-patterns: ${oauthRuntime.localRedirectPatterns.join(',')}\"`;\n}\n\nfunction getOAuthRuntimeGuide(oauthRuntime: SupabaseOAuthRuntimeModel): string {\n const localPatterns = oauthRuntime.localRedirectPatterns\n .map((pattern) => `- \\`${pattern}\\``)\n .join('\\n');\n\n return `# Supabase OAuth Runtime Reconciliation\n\nThe provider callback is derived from the active project gateway as\n\\`\\${API_EXTERNAL_URL%/}/callback\\`, which resolves to the project-owned\n\\`/auth/v1/callback\\` endpoint. GoTrue-to-app redirects use the configured callback route\n\\`${oauthRuntime.callbackRoute}\\`.\n\nLocal Minikube reconciliation adds only callback-scoped loopback patterns:\n\n${localPatterns}\n\nNative callback URIs may be supplied through \\`OAUTH_NATIVE_REDIRECT_URLS\\`. The generated\nprovider lifecycle writes only redirect metadata, never OAuth client secrets. It updates the\nGoTrue deployment environment, forces \\`deployment/auth\\` to restart, and waits up to 600\nseconds for the rollout. A failed rollout stops Infra Up before its success message.\n`;\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/adapters/minikube/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAEV,kBAAkB,EAClB,+BAA+B,EAC/B,8BAA8B,EAC/B,MAAM,aAAa,CAAC;AASrB,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE,kBAAkB,EAC5B,OAAO,GAAE,+BAAoC,GAC5C,8BAA8B,CAqFhC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/adapters/minikube/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAEV,kBAAkB,EAClB,+BAA+B,EAC/B,8BAA8B,EAC/B,MAAM,aAAa,CAAC;AAUrB,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE,kBAAkB,EAC5B,OAAO,GAAE,+BAAoC,GAC5C,8BAA8B,CAkGhC"}
@@ -1,10 +1,11 @@
1
- import { generateApiInfrastructureArtifacts } from '../../apiArtifacts';
1
+ import { generateGeneratedApiDatabaseArtifacts } from '../../generatedApiDatabase';
2
2
  import { generateAuthProviderArtifacts } from './auth';
3
3
  import { generateAuthorizationArtifacts } from './authz';
4
4
  import { APP_NAMESPACE, generateMinikubeBaseArtifacts } from './base';
5
5
  import { generateSecretStoreArtifacts } from './secrets';
6
6
  import { generateStorageArtifacts } from './storage';
7
7
  const CANONICAL_PROJECT_SLUG_RE = /^[a-z0-9](?:[a-z0-9-]{0,38}[a-z0-9])?$/;
8
+ const BUILT_IN_NAMESPACES = new Set([APP_NAMESPACE, 'supabase']);
8
9
  export function generateMinikubeInfra(manifest, options = {}) {
9
10
  if (manifest.deployment?.target !== 'minikube') {
10
11
  throw new Error(`Minikube adapter only supports deployment target "minikube" (received "${manifest.deployment?.target ?? 'undefined'}").`);
@@ -22,10 +23,16 @@ export function generateMinikubeInfra(manifest, options = {}) {
22
23
  });
23
24
  const storageArtifacts = generateStorageArtifacts({ manifest, namespace });
24
25
  const secretStoreArtifacts = generateSecretStoreArtifacts({ manifest, namespace });
25
- const apiArtifacts = generateApiInfrastructureArtifacts({
26
- data: options.appManifest?.data,
26
+ const generatedApiDatabaseArtifacts = generateGeneratedApiDatabaseArtifacts({
27
+ generatedApis: options.appManifest?.generatedApis,
27
28
  databaseProvider: manifest.database?.provider,
28
29
  });
30
+ const generatedApiErrors = generatedApiDatabaseArtifacts.diagnostics.filter((diagnostic) => diagnostic.severity === 'error');
31
+ if (generatedApiErrors.length > 0) {
32
+ throw new Error(`Generated API database definition is invalid:\n${generatedApiErrors
33
+ .map((diagnostic) => `- ${diagnostic.path ?? diagnostic.apiId}: ${diagnostic.message}`)
34
+ .join('\n')}`);
35
+ }
29
36
  const extraResources = unique([
30
37
  ...authArtifacts.resources,
31
38
  ...authzArtifacts.resources,
@@ -40,7 +47,7 @@ export function generateMinikubeInfra(manifest, options = {}) {
40
47
  ];
41
48
  const providerNamespaces = unique([
42
49
  ...providerLifecycle.map((contribution) => contribution.namespace),
43
- ]);
50
+ ]).filter((providerNamespace) => !BUILT_IN_NAMESPACES.has(providerNamespace));
44
51
  const extraEnvEntries = unique([
45
52
  ...authArtifacts.envEntries,
46
53
  ...authzArtifacts.envEntries,
@@ -61,7 +68,9 @@ export function generateMinikubeInfra(manifest, options = {}) {
61
68
  ...authzArtifacts.warnings,
62
69
  ...storageArtifacts.warnings,
63
70
  ...secretStoreArtifacts.warnings,
64
- ...apiArtifacts.warnings,
71
+ ...generatedApiDatabaseArtifacts.diagnostics
72
+ .filter((diagnostic) => diagnostic.severity === 'warning')
73
+ .map((diagnostic) => diagnostic.message),
65
74
  ]);
66
75
  return {
67
76
  files: [
@@ -70,7 +79,7 @@ export function generateMinikubeInfra(manifest, options = {}) {
70
79
  ...authzArtifacts.files,
71
80
  ...storageArtifacts.files,
72
81
  ...secretStoreArtifacts.files,
73
- ...apiArtifacts.files,
82
+ ...generatedApiDatabaseArtifacts.files,
74
83
  ],
75
84
  warnings,
76
85
  meta: {
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/adapters/minikube/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kCAAkC,EAAE,MAAM,oBAAoB,CAAC;AAOxE,OAAO,EAAE,6BAA6B,EAAE,MAAM,QAAQ,CAAC;AACvD,OAAO,EAAE,8BAA8B,EAAE,MAAM,SAAS,CAAC;AACzD,OAAO,EAAE,aAAa,EAAE,6BAA6B,EAAE,MAAM,QAAQ,CAAC;AACtE,OAAO,EAAE,4BAA4B,EAAE,MAAM,WAAW,CAAC;AACzD,OAAO,EAAE,wBAAwB,EAAE,MAAM,WAAW,CAAC;AAErD,MAAM,yBAAyB,GAAG,wCAAwC,CAAC;AAE3E,MAAM,UAAU,qBAAqB,CACnC,QAA4B,EAC5B,UAA2C,EAAE;IAE7C,IAAI,QAAQ,CAAC,UAAU,EAAE,MAAM,KAAK,UAAU,EAAE,CAAC;QAC/C,MAAM,IAAI,KAAK,CACb,0EAA0E,QAAQ,CAAC,UAAU,EAAE,MAAM,IAAI,WAAW,KAAK,CAC1H,CAAC;IACJ,CAAC;IAED,IAAI,QAAQ,CAAC,QAAQ,EAAE,QAAQ,IAAI,QAAQ,CAAC,QAAQ,CAAC,QAAQ,KAAK,UAAU,EAAE,CAAC;QAC7E,MAAM,IAAI,KAAK,CACb,wDAAwD,QAAQ,CAAC,QAAQ,CAAC,QAAQ,oCAAoC,CACvH,CAAC;IACJ,CAAC;IAED,MAAM,OAAO,GAAG,wBAAwB,CAAC,OAAO,CAAC,WAAW,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC;IAC7E,MAAM,SAAS,GAAG,aAAa,CAAC;IAEhC,MAAM,aAAa,GAAG,6BAA6B,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,CAAC;IAC7E,MAAM,cAAc,GAAG,8BAA8B,CAAC;QACpD,QAAQ;QACR,SAAS;QACT,WAAW,EAAE,OAAO,CAAC,WAAW;KACjC,CAAC,CAAC;IACH,MAAM,gBAAgB,GAAG,wBAAwB,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,CAAC;IAC3E,MAAM,oBAAoB,GAAG,4BAA4B,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,CAAC;IACnF,MAAM,YAAY,GAAG,kCAAkC,CAAC;QACtD,IAAI,EAAE,OAAO,CAAC,WAAW,EAAE,IAAI;QAC/B,gBAAgB,EAAE,QAAQ,CAAC,QAAQ,EAAE,QAAQ;KAC9C,CAAC,CAAC;IAEH,MAAM,cAAc,GAAG,MAAM,CAAC;QAC5B,GAAG,aAAa,CAAC,SAAS;QAC1B,GAAG,cAAc,CAAC,SAAS;QAC3B,GAAG,gBAAgB,CAAC,SAAS;QAC7B,GAAG,oBAAoB,CAAC,SAAS;KAClC,CAAC,CAAC;IACH,MAAM,iBAAiB,GAAG;QACxB,GAAG,aAAa,CAAC,iBAAiB;QAClC,GAAG,cAAc,CAAC,iBAAiB;QACnC,GAAG,gBAAgB,CAAC,iBAAiB;QACrC,GAAG,oBAAoB,CAAC,iBAAiB;KAC1C,CAAC;IACF,MAAM,kBAAkB,GAAG,MAAM,CAAC;QAChC,GAAG,iBAAiB,CAAC,GAAG,CAAC,CAAC,YAAY,EAAE,EAAE,CAAC,YAAY,CAAC,SAAS,CAAC;KACnE,CAAC,CAAC;IACH,MAAM,eAAe,GAAG,MAAM,CAAC;QAC7B,GAAG,aAAa,CAAC,UAAU;QAC3B,GAAG,cAAc,CAAC,UAAU;QAC5B,GAAG,gBAAgB,CAAC,UAAU;QAC9B,GAAG,oBAAoB,CAAC,UAAU;KACnC,CAAC,CAAC;IAEH,MAAM,SAAS,GAAG,6BAA6B,CAAC;QAC9C,QAAQ;QACR,OAAO;QACP,cAAc;QACd,kBAAkB;QAClB,iBAAiB;QACjB,eAAe;KAChB,CAAC,CAAC;IAEH,MAAM,QAAQ,GAAG,MAAM,CAAC;QACtB,GAAG,eAAe,CAAC,QAAQ,CAAC;QAC5B,GAAG,aAAa,CAAC,QAAQ;QACzB,GAAG,cAAc,CAAC,QAAQ;QAC1B,GAAG,gBAAgB,CAAC,QAAQ;QAC5B,GAAG,oBAAoB,CAAC,QAAQ;QAChC,GAAG,YAAY,CAAC,QAAQ;KACzB,CAAC,CAAC;IAEH,OAAO;QACL,KAAK,EAAE;YACL,GAAG,SAAS;YACZ,GAAG,aAAa,CAAC,KAAK;YACtB,GAAG,cAAc,CAAC,KAAK;YACvB,GAAG,gBAAgB,CAAC,KAAK;YACzB,GAAG,oBAAoB,CAAC,KAAK;YAC7B,GAAG,YAAY,CAAC,KAAK;SACtB;QACD,QAAQ;QACR,IAAI,EAAE;YACJ,MAAM,EAAE,UAAU;YAClB,SAAS,EAAE,gBAAgB,CAAC,QAAQ,CAAC;SACtC;QACD,YAAY,EAAE,mBAAmB,CAAC,QAAQ,CAAC;KAC5C,CAAC;AACJ,CAAC;AAED,SAAS,gBAAgB,CAAC,QAA4B;IACpD,MAAM,SAAS,GAAG,IAAI,GAAG,EAAU,CAAC;IAEpC,IAAI,QAAQ,CAAC,IAAI,EAAE,QAAQ;QAAE,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACnE,IAAI,QAAQ,CAAC,IAAI,EAAE,aAAa,EAAE,MAAM,EAAE,CAAC;QACzC,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;IACpD,CAAC;IACD,IAAI,QAAQ,CAAC,QAAQ,EAAE,QAAQ;QAAE,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAC3E,IAAI,QAAQ,CAAC,OAAO,EAAE,QAAQ;QAAE,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACzE,IAAI,QAAQ,CAAC,WAAW,EAAE,QAAQ;QAAE,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;IACjF,IAAI,QAAQ,CAAC,KAAK,EAAE,QAAQ;QAAE,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IAErE,OAAO,CAAC,GAAG,SAAS,CAAC,CAAC,IAAI,EAAE,CAAC;AAC/B,CAAC;AAED,SAAS,mBAAmB,CAAC,QAA4B;IACvD,IAAI,QAAQ,CAAC,KAAK,EAAE,QAAQ,KAAK,QAAQ,EAAE,CAAC;QAC1C,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,OAAO;QACL;YACE,IAAI,EAAE,yBAAyB;YAC/B,OAAO,EAAE,QAAQ;YACjB,MAAM,EAAE,0CAA0C;SACnD;KACF,CAAC;AACJ,CAAC;AAED,SAAS,eAAe,CAAC,QAA4B;IACnD,MAAM,QAAQ,GAAa,EAAE,CAAC;IAE9B,IAAI,QAAQ,CAAC,UAAU,EAAE,UAAU,EAAE,CAAC;QACpC,QAAQ,CAAC,IAAI,CACX,0FAA0F,CAC3F,CAAC;IACJ,CAAC;IAED,IAAI,QAAQ,CAAC,UAAU,EAAE,GAAG,EAAE,CAAC;QAC7B,QAAQ,CAAC,IAAI,CAAC,+EAA+E,CAAC,CAAC;IACjG,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,SAAS,wBAAwB,CAAC,IAAwB;IACxD,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,MAAM,IAAI,KAAK,CACb,iFAAiF,CAClF,CAAC;IACJ,CAAC;IAED,IAAI,IAAI,CAAC,IAAI,EAAE,KAAK,IAAI,IAAI,CAAC,yBAAyB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QAClE,MAAM,IAAI,KAAK,CACb,kMAAkM,CACnM,CAAC;IACJ,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,MAAM,CAAC,MAAgB;IAC9B,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;AAC9B,CAAC","sourcesContent":["import { generateApiInfrastructureArtifacts } from '../../apiArtifacts';\nimport type {\n GeneratedPackageDependency,\n InfraManifestInput,\n InfrastructureGenerationOptions,\n InfrastructureGenerationResult,\n} from '../../types';\nimport { generateAuthProviderArtifacts } from './auth';\nimport { generateAuthorizationArtifacts } from './authz';\nimport { APP_NAMESPACE, generateMinikubeBaseArtifacts } from './base';\nimport { generateSecretStoreArtifacts } from './secrets';\nimport { generateStorageArtifacts } from './storage';\n\nconst CANONICAL_PROJECT_SLUG_RE = /^[a-z0-9](?:[a-z0-9-]{0,38}[a-z0-9])?$/;\n\nexport function generateMinikubeInfra(\n manifest: InfraManifestInput,\n options: InfrastructureGenerationOptions = {},\n): InfrastructureGenerationResult {\n if (manifest.deployment?.target !== 'minikube') {\n throw new Error(\n `Minikube adapter only supports deployment target \"minikube\" (received \"${manifest.deployment?.target ?? 'undefined'}\").`,\n );\n }\n\n if (manifest.database?.provider && manifest.database.provider !== 'supabase') {\n throw new Error(\n `Unsupported database provider for minikube adapter: \"${manifest.database.provider}\". Only \"supabase\" is implemented.`,\n );\n }\n\n const appSlug = validateCanonicalAppSlug(options.appManifest?.metadata.slug);\n const namespace = APP_NAMESPACE;\n\n const authArtifacts = generateAuthProviderArtifacts({ manifest, namespace });\n const authzArtifacts = generateAuthorizationArtifacts({\n manifest,\n namespace,\n appManifest: options.appManifest,\n });\n const storageArtifacts = generateStorageArtifacts({ manifest, namespace });\n const secretStoreArtifacts = generateSecretStoreArtifacts({ manifest, namespace });\n const apiArtifacts = generateApiInfrastructureArtifacts({\n data: options.appManifest?.data,\n databaseProvider: manifest.database?.provider,\n });\n\n const extraResources = unique([\n ...authArtifacts.resources,\n ...authzArtifacts.resources,\n ...storageArtifacts.resources,\n ...secretStoreArtifacts.resources,\n ]);\n const providerLifecycle = [\n ...authArtifacts.providerLifecycle,\n ...authzArtifacts.providerLifecycle,\n ...storageArtifacts.providerLifecycle,\n ...secretStoreArtifacts.providerLifecycle,\n ];\n const providerNamespaces = unique([\n ...providerLifecycle.map((contribution) => contribution.namespace),\n ]);\n const extraEnvEntries = unique([\n ...authArtifacts.envEntries,\n ...authzArtifacts.envEntries,\n ...storageArtifacts.envEntries,\n ...secretStoreArtifacts.envEntries,\n ]);\n\n const baseFiles = generateMinikubeBaseArtifacts({\n manifest,\n appSlug,\n extraResources,\n providerNamespaces,\n providerLifecycle,\n extraEnvEntries,\n });\n\n const warnings = unique([\n ...collectWarnings(manifest),\n ...authArtifacts.warnings,\n ...authzArtifacts.warnings,\n ...storageArtifacts.warnings,\n ...secretStoreArtifacts.warnings,\n ...apiArtifacts.warnings,\n ]);\n\n return {\n files: [\n ...baseFiles,\n ...authArtifacts.files,\n ...authzArtifacts.files,\n ...storageArtifacts.files,\n ...secretStoreArtifacts.files,\n ...apiArtifacts.files,\n ],\n warnings,\n meta: {\n target: 'minikube',\n providers: collectProviders(manifest),\n },\n dependencies: collectDependencies(manifest),\n };\n}\n\nfunction collectProviders(manifest: InfraManifestInput): string[] {\n const providers = new Set<string>();\n\n if (manifest.auth?.provider) providers.add(manifest.auth.provider);\n if (manifest.auth?.authorization?.engine) {\n providers.add(manifest.auth.authorization.engine);\n }\n if (manifest.database?.provider) providers.add(manifest.database.provider);\n if (manifest.storage?.provider) providers.add(manifest.storage.provider);\n if (manifest.secretStore?.provider) providers.add(manifest.secretStore.provider);\n if (manifest.state?.provider) providers.add(manifest.state.provider);\n\n return [...providers].sort();\n}\n\nfunction collectDependencies(manifest: InfraManifestInput): readonly GeneratedPackageDependency[] {\n if (manifest.state?.provider !== 'legend') {\n return [];\n }\n\n return [\n {\n name: '@ankhorage/state-legend',\n version: '^0.1.0',\n reason: 'Selected by infra.state.provider=legend.',\n },\n ];\n}\n\nfunction collectWarnings(manifest: InfraManifestInput): string[] {\n const warnings: string[] = [];\n\n if (manifest.deployment?.monitoring) {\n warnings.push(\n 'Monitoring is enabled in manifest, but monitoring stack resources are not generated yet.',\n );\n }\n\n if (manifest.networking?.cdn) {\n warnings.push('CDN is enabled in manifest, but CDN resources are not generated for minikube.');\n }\n\n return warnings;\n}\n\nfunction validateCanonicalAppSlug(slug: string | undefined): string {\n if (!slug) {\n throw new Error(\n 'Cannot generate Minikube infrastructure: appManifest.metadata.slug is required.',\n );\n }\n\n if (slug.trim() !== slug || !CANONICAL_PROJECT_SLUG_RE.test(slug)) {\n throw new Error(\n 'Cannot generate Minikube infrastructure: appManifest.metadata.slug must be a canonical lowercase slug up to 40 characters using only a-z, 0-9, and hyphens, without leading or trailing hyphens.',\n );\n }\n\n return slug;\n}\n\nfunction unique(values: string[]): string[] {\n return [...new Set(values)];\n}\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/adapters/minikube/index.ts"],"names":[],"mappings":"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","sourcesContent":["import { generateGeneratedApiDatabaseArtifacts } from '../../generatedApiDatabase';\nimport type {\n GeneratedPackageDependency,\n InfraManifestInput,\n InfrastructureGenerationOptions,\n InfrastructureGenerationResult,\n} from '../../types';\nimport { generateAuthProviderArtifacts } from './auth';\nimport { generateAuthorizationArtifacts } from './authz';\nimport { APP_NAMESPACE, generateMinikubeBaseArtifacts } from './base';\nimport { generateSecretStoreArtifacts } from './secrets';\nimport { generateStorageArtifacts } from './storage';\n\nconst CANONICAL_PROJECT_SLUG_RE = /^[a-z0-9](?:[a-z0-9-]{0,38}[a-z0-9])?$/;\nconst BUILT_IN_NAMESPACES = new Set([APP_NAMESPACE, 'supabase']);\n\nexport function generateMinikubeInfra(\n manifest: InfraManifestInput,\n options: InfrastructureGenerationOptions = {},\n): InfrastructureGenerationResult {\n if (manifest.deployment?.target !== 'minikube') {\n throw new Error(\n `Minikube adapter only supports deployment target \"minikube\" (received \"${manifest.deployment?.target ?? 'undefined'}\").`,\n );\n }\n\n if (manifest.database?.provider && manifest.database.provider !== 'supabase') {\n throw new Error(\n `Unsupported database provider for minikube adapter: \"${manifest.database.provider}\". Only \"supabase\" is implemented.`,\n );\n }\n\n const appSlug = validateCanonicalAppSlug(options.appManifest?.metadata.slug);\n const namespace = APP_NAMESPACE;\n\n const authArtifacts = generateAuthProviderArtifacts({ manifest, namespace });\n const authzArtifacts = generateAuthorizationArtifacts({\n manifest,\n namespace,\n appManifest: options.appManifest,\n });\n const storageArtifacts = generateStorageArtifacts({ manifest, namespace });\n const secretStoreArtifacts = generateSecretStoreArtifacts({ manifest, namespace });\n const generatedApiDatabaseArtifacts = generateGeneratedApiDatabaseArtifacts({\n generatedApis: options.appManifest?.generatedApis,\n databaseProvider: manifest.database?.provider,\n });\n const generatedApiErrors = generatedApiDatabaseArtifacts.diagnostics.filter(\n (diagnostic) => diagnostic.severity === 'error',\n );\n\n if (generatedApiErrors.length > 0) {\n throw new Error(\n `Generated API database definition is invalid:\\n${generatedApiErrors\n .map((diagnostic) => `- ${diagnostic.path ?? diagnostic.apiId}: ${diagnostic.message}`)\n .join('\\n')}`,\n );\n }\n\n const extraResources = unique([\n ...authArtifacts.resources,\n ...authzArtifacts.resources,\n ...storageArtifacts.resources,\n ...secretStoreArtifacts.resources,\n ]);\n const providerLifecycle = [\n ...authArtifacts.providerLifecycle,\n ...authzArtifacts.providerLifecycle,\n ...storageArtifacts.providerLifecycle,\n ...secretStoreArtifacts.providerLifecycle,\n ];\n const providerNamespaces = unique([\n ...providerLifecycle.map((contribution) => contribution.namespace),\n ]).filter((providerNamespace) => !BUILT_IN_NAMESPACES.has(providerNamespace));\n const extraEnvEntries = unique([\n ...authArtifacts.envEntries,\n ...authzArtifacts.envEntries,\n ...storageArtifacts.envEntries,\n ...secretStoreArtifacts.envEntries,\n ]);\n\n const baseFiles = generateMinikubeBaseArtifacts({\n manifest,\n appSlug,\n extraResources,\n providerNamespaces,\n providerLifecycle,\n extraEnvEntries,\n });\n\n const warnings = unique([\n ...collectWarnings(manifest),\n ...authArtifacts.warnings,\n ...authzArtifacts.warnings,\n ...storageArtifacts.warnings,\n ...secretStoreArtifacts.warnings,\n ...generatedApiDatabaseArtifacts.diagnostics\n .filter((diagnostic) => diagnostic.severity === 'warning')\n .map((diagnostic) => diagnostic.message),\n ]);\n\n return {\n files: [\n ...baseFiles,\n ...authArtifacts.files,\n ...authzArtifacts.files,\n ...storageArtifacts.files,\n ...secretStoreArtifacts.files,\n ...generatedApiDatabaseArtifacts.files,\n ],\n warnings,\n meta: {\n target: 'minikube',\n providers: collectProviders(manifest),\n },\n dependencies: collectDependencies(manifest),\n };\n}\n\nfunction collectProviders(manifest: InfraManifestInput): string[] {\n const providers = new Set<string>();\n\n if (manifest.auth?.provider) providers.add(manifest.auth.provider);\n if (manifest.auth?.authorization?.engine) {\n providers.add(manifest.auth.authorization.engine);\n }\n if (manifest.database?.provider) providers.add(manifest.database.provider);\n if (manifest.storage?.provider) providers.add(manifest.storage.provider);\n if (manifest.secretStore?.provider) providers.add(manifest.secretStore.provider);\n if (manifest.state?.provider) providers.add(manifest.state.provider);\n\n return [...providers].sort();\n}\n\nfunction collectDependencies(manifest: InfraManifestInput): readonly GeneratedPackageDependency[] {\n if (manifest.state?.provider !== 'legend') {\n return [];\n }\n\n return [\n {\n name: '@ankhorage/state-legend',\n version: '^0.1.0',\n reason: 'Selected by infra.state.provider=legend.',\n },\n ];\n}\n\nfunction collectWarnings(manifest: InfraManifestInput): string[] {\n const warnings: string[] = [];\n\n if (manifest.deployment?.monitoring) {\n warnings.push(\n 'Monitoring is enabled in manifest, but monitoring stack resources are not generated yet.',\n );\n }\n\n if (manifest.networking?.cdn) {\n warnings.push('CDN is enabled in manifest, but CDN resources are not generated for minikube.');\n }\n\n return warnings;\n}\n\nfunction validateCanonicalAppSlug(slug: string | undefined): string {\n if (!slug) {\n throw new Error(\n 'Cannot generate Minikube infrastructure: appManifest.metadata.slug is required.',\n );\n }\n\n if (slug.trim() !== slug || !CANONICAL_PROJECT_SLUG_RE.test(slug)) {\n throw new Error(\n 'Cannot generate Minikube infrastructure: appManifest.metadata.slug must be a canonical lowercase slug up to 40 characters using only a-z, 0-9, and hyphens, without leading or trailing hyphens.',\n );\n }\n\n return slug;\n}\n\nfunction unique(values: string[]): string[] {\n return [...new Set(values)];\n}\n"]}
@@ -0,0 +1,19 @@
1
+ export type AuthRedirectEnvironment = 'local' | 'preview' | 'production';
2
+ export interface ResolveAuthRedirectConfigurationInput {
3
+ environment: AuthRedirectEnvironment;
4
+ gatewayOrigin: string;
5
+ siteOrigin: string;
6
+ callbackRoute: string;
7
+ webOrigins?: readonly string[];
8
+ nativeRedirectUris?: readonly string[];
9
+ }
10
+ export interface AuthRedirectConfiguration {
11
+ providerCallbackUrl: string;
12
+ siteUrl: string;
13
+ redirectAllowList: readonly string[];
14
+ serializedRedirectAllowList: string;
15
+ }
16
+ export declare function resolveAuthRedirectConfiguration(input: ResolveAuthRedirectConfigurationInput): AuthRedirectConfiguration;
17
+ export declare function getLocalAuthRedirectPatterns(callbackRoute: string): readonly string[];
18
+ export declare function normalizeAuthCallbackRoute(callbackRoute: string): string;
19
+ //# sourceMappingURL=authRedirects.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"authRedirects.d.ts","sourceRoot":"","sources":["../src/authRedirects.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,uBAAuB,GAAG,OAAO,GAAG,SAAS,GAAG,YAAY,CAAC;AAEzE,MAAM,WAAW,qCAAqC;IACpD,WAAW,EAAE,uBAAuB,CAAC;IACrC,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC/B,kBAAkB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACxC;AAED,MAAM,WAAW,yBAAyB;IACxC,mBAAmB,EAAE,MAAM,CAAC;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,iBAAiB,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,2BAA2B,EAAE,MAAM,CAAC;CACrC;AAED,wBAAgB,gCAAgC,CAC9C,KAAK,EAAE,qCAAqC,GAC3C,yBAAyB,CAyB3B;AAED,wBAAgB,4BAA4B,CAAC,aAAa,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,CAGrF;AAED,wBAAgB,0BAA0B,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,CAExE"}
@@ -0,0 +1,80 @@
1
+ export function resolveAuthRedirectConfiguration(input) {
2
+ const gatewayOrigin = normalizeWebOrigin(input.gatewayOrigin, 'gatewayOrigin');
3
+ const siteUrl = normalizeWebOrigin(input.siteOrigin, 'siteOrigin');
4
+ const callbackRoute = normalizeCallbackRoute(input.callbackRoute);
5
+ const webOrigins = unique([
6
+ siteUrl,
7
+ ...(input.webOrigins ?? []).map((origin) => normalizeWebOrigin(origin, 'webOrigins')),
8
+ ]);
9
+ const nativeRedirectUris = unique((input.nativeRedirectUris ?? []).map((uri) => normalizeNativeRedirectUri(uri)));
10
+ const redirectAllowList = unique([
11
+ ...webOrigins,
12
+ ...webOrigins.map((origin) => `${origin}${callbackRoute}`),
13
+ ...(input.environment === 'local' ? getLocalAuthRedirectPatterns(callbackRoute) : []),
14
+ ...nativeRedirectUris,
15
+ ]);
16
+ return {
17
+ providerCallbackUrl: `${gatewayOrigin}/auth/v1/callback`,
18
+ siteUrl,
19
+ redirectAllowList,
20
+ serializedRedirectAllowList: redirectAllowList.join(','),
21
+ };
22
+ }
23
+ export function getLocalAuthRedirectPatterns(callbackRoute) {
24
+ const normalizedRoute = normalizeCallbackRoute(callbackRoute);
25
+ return [`http://127.0.0.1:*${normalizedRoute}`, `http://localhost:*${normalizedRoute}`];
26
+ }
27
+ export function normalizeAuthCallbackRoute(callbackRoute) {
28
+ return normalizeCallbackRoute(callbackRoute);
29
+ }
30
+ function normalizeCallbackRoute(callbackRoute) {
31
+ const trimmed = callbackRoute.trim();
32
+ if (!trimmed) {
33
+ throw new Error('Auth callback route must not be empty.');
34
+ }
35
+ const withLeadingSlash = trimmed.startsWith('/') ? trimmed : `/${trimmed}`;
36
+ const normalized = withLeadingSlash.replace(/\/{2,}/gu, '/');
37
+ if (normalized.includes('?') || normalized.includes('#')) {
38
+ throw new Error('Auth callback route must not include a query string or fragment.');
39
+ }
40
+ return normalized;
41
+ }
42
+ function normalizeWebOrigin(value, field) {
43
+ const parsed = parseUrl(value, field);
44
+ if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') {
45
+ throw new Error(`${field} must use http or https.`);
46
+ }
47
+ if (parsed.username || parsed.password || parsed.search || parsed.hash) {
48
+ throw new Error(`${field} must be a canonical origin without credentials, query, or fragment.`);
49
+ }
50
+ if (parsed.pathname !== '/' && parsed.pathname !== '') {
51
+ throw new Error(`${field} must not include a path.`);
52
+ }
53
+ return parsed.origin;
54
+ }
55
+ function normalizeNativeRedirectUri(value) {
56
+ const parsed = parseUrl(value, 'nativeRedirectUris');
57
+ if (parsed.protocol === 'http:' || parsed.protocol === 'https:') {
58
+ throw new Error('nativeRedirectUris must use a non-HTTP application scheme.');
59
+ }
60
+ if (parsed.username || parsed.password || parsed.search || parsed.hash) {
61
+ throw new Error('nativeRedirectUris must not include credentials, query strings, or fragments.');
62
+ }
63
+ return parsed.toString();
64
+ }
65
+ function parseUrl(value, field) {
66
+ const trimmed = value.trim();
67
+ if (!trimmed) {
68
+ throw new Error(`${field} must not contain empty values.`);
69
+ }
70
+ try {
71
+ return new URL(trimmed);
72
+ }
73
+ catch {
74
+ throw new Error(`${field} contains an invalid URL.`);
75
+ }
76
+ }
77
+ function unique(values) {
78
+ return [...new Set(values)];
79
+ }
80
+ //# sourceMappingURL=authRedirects.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"authRedirects.js","sourceRoot":"","sources":["../src/authRedirects.ts"],"names":[],"mappings":"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","sourcesContent":["export type AuthRedirectEnvironment = 'local' | 'preview' | 'production';\n\nexport interface ResolveAuthRedirectConfigurationInput {\n environment: AuthRedirectEnvironment;\n gatewayOrigin: string;\n siteOrigin: string;\n callbackRoute: string;\n webOrigins?: readonly string[];\n nativeRedirectUris?: readonly string[];\n}\n\nexport interface AuthRedirectConfiguration {\n providerCallbackUrl: string;\n siteUrl: string;\n redirectAllowList: readonly string[];\n serializedRedirectAllowList: string;\n}\n\nexport function resolveAuthRedirectConfiguration(\n input: ResolveAuthRedirectConfigurationInput,\n): AuthRedirectConfiguration {\n const gatewayOrigin = normalizeWebOrigin(input.gatewayOrigin, 'gatewayOrigin');\n const siteUrl = normalizeWebOrigin(input.siteOrigin, 'siteOrigin');\n const callbackRoute = normalizeCallbackRoute(input.callbackRoute);\n const webOrigins = unique([\n siteUrl,\n ...(input.webOrigins ?? []).map((origin) => normalizeWebOrigin(origin, 'webOrigins')),\n ]);\n const nativeRedirectUris = unique(\n (input.nativeRedirectUris ?? []).map((uri) => normalizeNativeRedirectUri(uri)),\n );\n\n const redirectAllowList = unique([\n ...webOrigins,\n ...webOrigins.map((origin) => `${origin}${callbackRoute}`),\n ...(input.environment === 'local' ? getLocalAuthRedirectPatterns(callbackRoute) : []),\n ...nativeRedirectUris,\n ]);\n\n return {\n providerCallbackUrl: `${gatewayOrigin}/auth/v1/callback`,\n siteUrl,\n redirectAllowList,\n serializedRedirectAllowList: redirectAllowList.join(','),\n };\n}\n\nexport function getLocalAuthRedirectPatterns(callbackRoute: string): readonly string[] {\n const normalizedRoute = normalizeCallbackRoute(callbackRoute);\n return [`http://127.0.0.1:*${normalizedRoute}`, `http://localhost:*${normalizedRoute}`];\n}\n\nexport function normalizeAuthCallbackRoute(callbackRoute: string): string {\n return normalizeCallbackRoute(callbackRoute);\n}\n\nfunction normalizeCallbackRoute(callbackRoute: string): string {\n const trimmed = callbackRoute.trim();\n if (!trimmed) {\n throw new Error('Auth callback route must not be empty.');\n }\n\n const withLeadingSlash = trimmed.startsWith('/') ? trimmed : `/${trimmed}`;\n const normalized = withLeadingSlash.replace(/\\/{2,}/gu, '/');\n if (normalized.includes('?') || normalized.includes('#')) {\n throw new Error('Auth callback route must not include a query string or fragment.');\n }\n return normalized;\n}\n\nfunction normalizeWebOrigin(value: string, field: string): string {\n const parsed = parseUrl(value, field);\n if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') {\n throw new Error(`${field} must use http or https.`);\n }\n if (parsed.username || parsed.password || parsed.search || parsed.hash) {\n throw new Error(`${field} must be a canonical origin without credentials, query, or fragment.`);\n }\n if (parsed.pathname !== '/' && parsed.pathname !== '') {\n throw new Error(`${field} must not include a path.`);\n }\n return parsed.origin;\n}\n\nfunction normalizeNativeRedirectUri(value: string): string {\n const parsed = parseUrl(value, 'nativeRedirectUris');\n if (parsed.protocol === 'http:' || parsed.protocol === 'https:') {\n throw new Error('nativeRedirectUris must use a non-HTTP application scheme.');\n }\n if (parsed.username || parsed.password || parsed.search || parsed.hash) {\n throw new Error(\n 'nativeRedirectUris must not include credentials, query strings, or fragments.',\n );\n }\n return parsed.toString();\n}\n\nfunction parseUrl(value: string, field: string): URL {\n const trimmed = value.trim();\n if (!trimmed) {\n throw new Error(`${field} must not contain empty values.`);\n }\n\n try {\n return new URL(trimmed);\n } catch {\n throw new Error(`${field} contains an invalid URL.`);\n }\n}\n\nfunction unique(values: readonly string[]): string[] {\n return [...new Set(values)];\n}\n"]}
@@ -0,0 +1,20 @@
1
+ import type { GeneratedApiRegistry } from '@ankhorage/contracts';
2
+ import type { GeneratedInfrastructureFile } from './types';
3
+ export type GeneratedApiDatabaseDiagnosticCode = 'duplicate-field' | 'duplicate-resource-id' | 'duplicate-target' | 'invalid-default' | 'invalid-identifier' | 'invalid-primary-key' | 'invalid-seed' | 'registry-id-mismatch' | 'unsupported-policy' | 'unsupported-provider';
4
+ export interface GeneratedApiDatabaseDiagnostic {
5
+ readonly code: GeneratedApiDatabaseDiagnosticCode;
6
+ readonly severity: 'error' | 'warning';
7
+ readonly apiId: string;
8
+ readonly resourceId?: string;
9
+ readonly path?: string;
10
+ readonly message: string;
11
+ }
12
+ export interface GeneratedApiDatabaseArtifacts {
13
+ readonly files: readonly GeneratedInfrastructureFile[];
14
+ readonly diagnostics: readonly GeneratedApiDatabaseDiagnostic[];
15
+ }
16
+ export declare function generateGeneratedApiDatabaseArtifacts(args: {
17
+ readonly generatedApis: GeneratedApiRegistry | undefined;
18
+ readonly databaseProvider: string | undefined;
19
+ }): GeneratedApiDatabaseArtifacts;
20
+ //# sourceMappingURL=generatedApiDatabase.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generatedApiDatabase.d.ts","sourceRoot":"","sources":["../src/generatedApiDatabase.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAKV,oBAAoB,EAGrB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,SAAS,CAAC;AAE3D,MAAM,MAAM,kCAAkC,GAC1C,iBAAiB,GACjB,uBAAuB,GACvB,kBAAkB,GAClB,iBAAiB,GACjB,oBAAoB,GACpB,qBAAqB,GACrB,cAAc,GACd,sBAAsB,GACtB,oBAAoB,GACpB,sBAAsB,CAAC;AAE3B,MAAM,WAAW,8BAA8B;IAC7C,QAAQ,CAAC,IAAI,EAAE,kCAAkC,CAAC;IAClD,QAAQ,CAAC,QAAQ,EAAE,OAAO,GAAG,SAAS,CAAC;IACvC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,6BAA6B;IAC5C,QAAQ,CAAC,KAAK,EAAE,SAAS,2BAA2B,EAAE,CAAC;IACvD,QAAQ,CAAC,WAAW,EAAE,SAAS,8BAA8B,EAAE,CAAC;CACjE;AAmBD,wBAAgB,qCAAqC,CAAC,IAAI,EAAE;IAC1D,QAAQ,CAAC,aAAa,EAAE,oBAAoB,GAAG,SAAS,CAAC;IACzD,QAAQ,CAAC,gBAAgB,EAAE,MAAM,GAAG,SAAS,CAAC;CAC/C,GAAG,6BAA6B,CA2ChC"}