@ankhorage/infra 1.1.0 → 2.0.1

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 (47) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +4 -1
  3. package/dist/adapters/minikube/auth/oauthRuntime.js +6 -12
  4. package/dist/adapters/minikube/auth/oauthRuntime.js.map +1 -1
  5. package/dist/adapters/minikube/index.d.ts.map +1 -1
  6. package/dist/adapters/minikube/index.js +13 -5
  7. package/dist/adapters/minikube/index.js.map +1 -1
  8. package/dist/generatedApiDatabase.d.ts +20 -0
  9. package/dist/generatedApiDatabase.d.ts.map +1 -0
  10. package/dist/generatedApiDatabase.js +343 -0
  11. package/dist/generatedApiDatabase.js.map +1 -0
  12. package/dist/index.d.ts +1 -2
  13. package/dist/index.d.ts.map +1 -1
  14. package/dist/index.js +1 -1
  15. package/dist/index.js.map +1 -1
  16. package/dist/project.d.ts +1 -1
  17. package/dist/project.d.ts.map +1 -1
  18. package/dist/project.js +3 -0
  19. package/dist/project.js.map +1 -1
  20. package/dist/testSupport.d.ts.map +1 -1
  21. package/dist/testSupport.js +1 -0
  22. package/dist/testSupport.js.map +1 -1
  23. package/dist/types.d.ts +1 -1
  24. package/dist/types.d.ts.map +1 -1
  25. package/dist/types.js.map +1 -1
  26. package/package.json +2 -2
  27. package/src/adapters/minikube/auth/oauthRuntime.ts +6 -12
  28. package/src/adapters/minikube/auth/supabase/oauthRuntime.test.ts +17 -6
  29. package/src/adapters/minikube/index.ts +18 -5
  30. package/src/generatedApiDatabase.test.ts +355 -0
  31. package/src/generatedApiDatabase.ts +558 -0
  32. package/src/index.ts +6 -2
  33. package/src/project.ts +3 -1
  34. package/src/testSupport.ts +1 -0
  35. package/src/types.ts +1 -1
  36. package/dist/apiArtifacts.d.ts +0 -8
  37. package/dist/apiArtifacts.d.ts.map +0 -1
  38. package/dist/apiArtifacts.js +0 -35
  39. package/dist/apiArtifacts.js.map +0 -1
  40. package/dist/apis.d.ts +0 -11
  41. package/dist/apis.d.ts.map +0 -1
  42. package/dist/apis.js +0 -354
  43. package/dist/apis.js.map +0 -1
  44. package/src/apiArtifacts.test.ts +0 -54
  45. package/src/apiArtifacts.ts +0 -107
  46. package/src/apis.test.ts +0 -212
  47. package/src/apis.ts +0 -534
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generatedApiDatabase.js","sourceRoot":"","sources":["../src/generatedApiDatabase.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n DataContractValue,\n DbCollectionDefinition,\n DbFieldDefinition,\n GeneratedApiDefinition,\n GeneratedApiRegistry,\n GeneratedApiResourceDefinition,\n GeneratedApiSeedRecord,\n} from '@ankhorage/contracts';\n\nimport type { GeneratedInfrastructureFile } from './types';\n\nexport type GeneratedApiDatabaseDiagnosticCode =\n | 'duplicate-field'\n | 'duplicate-resource-id'\n | 'duplicate-target'\n | 'invalid-default'\n | 'invalid-identifier'\n | 'invalid-primary-key'\n | 'invalid-seed'\n | 'registry-id-mismatch'\n | 'unsupported-policy'\n | 'unsupported-provider';\n\nexport interface GeneratedApiDatabaseDiagnostic {\n readonly code: GeneratedApiDatabaseDiagnosticCode;\n readonly severity: 'error' | 'warning';\n readonly apiId: string;\n readonly resourceId?: string;\n readonly path?: string;\n readonly message: string;\n}\n\nexport interface GeneratedApiDatabaseArtifacts {\n readonly files: readonly GeneratedInfrastructureFile[];\n readonly diagnostics: readonly GeneratedApiDatabaseDiagnostic[];\n}\n\ninterface GeneratedResourceContext {\n readonly api: GeneratedApiDefinition;\n readonly resource: GeneratedApiResourceDefinition;\n readonly seed: readonly GeneratedApiSeedRecord[];\n}\n\ninterface GeneratedSeedEntry {\n readonly apiId: string;\n readonly resourceId: string;\n readonly collection: DbCollectionDefinition;\n readonly records: readonly GeneratedApiSeedRecord[];\n}\n\nconst DEFAULT_DATABASE_SCHEMA = 'public';\nconst SQL_IDENTIFIER_RE = /^[A-Za-z_][A-Za-z0-9_]*$/;\nconst UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\n\nexport function generateGeneratedApiDatabaseArtifacts(args: {\n readonly generatedApis: GeneratedApiRegistry | undefined;\n readonly databaseProvider: string | undefined;\n}): GeneratedApiDatabaseArtifacts {\n const contexts = listGeneratedResources(args.generatedApis);\n if (contexts.length === 0) return { files: [], diagnostics: [] };\n\n const diagnostics = validateGeneratedApiDatabaseState(\n args.generatedApis ?? {},\n contexts,\n args.databaseProvider,\n );\n if (diagnostics.some((diagnostic) => diagnostic.severity === 'error')) {\n return { files: [], diagnostics };\n }\n\n const seedEntries = contexts.map(createSeedEntry);\n const metadata = contexts.map((context) => ({\n apiId: context.api.id,\n database: context.api.database,\n auth: context.api.auth ?? null,\n resourceId: context.resource.id,\n operations: context.resource.operations,\n collection: context.resource.collection,\n policies: context.resource.policies ?? [],\n }));\n\n return {\n files: [\n jsonFile('infra/minikube/db/generated-api-resources.json', metadata),\n jsonFile('infra/minikube/db/generated-api-seed.json', seedEntries),\n {\n path: 'infra/minikube/db/migrations/001_generated_api_resources.sql',\n content: generateMigrationSql(contexts),\n },\n {\n path: 'infra/minikube/db/seeds/001_generated_api_seed.sql',\n content: generateSeedSql(seedEntries),\n },\n {\n path: 'infra/minikube/db/README.md',\n content: generateReadme(contexts),\n },\n ],\n diagnostics,\n };\n}\n\nfunction listGeneratedResources(\n registry: GeneratedApiRegistry | undefined,\n): readonly GeneratedResourceContext[] {\n return Object.values(registry ?? {})\n .sort((left, right) => left.id.localeCompare(right.id))\n .flatMap((api) =>\n [...api.resources]\n .sort((left, right) => left.id.localeCompare(right.id))\n .map((resource) => ({ api, resource, seed: resource.seed ?? [] })),\n );\n}\n\nfunction validateGeneratedApiDatabaseState(\n registry: GeneratedApiRegistry,\n contexts: readonly GeneratedResourceContext[],\n databaseProvider: string | undefined,\n): readonly GeneratedApiDatabaseDiagnostic[] {\n const diagnostics: GeneratedApiDatabaseDiagnostic[] = [];\n const targets = new Map<string, GeneratedResourceContext>();\n const resourceIdsByApi = new Map<string, Set<string>>();\n\n if (databaseProvider !== 'supabase') {\n diagnostics.push({\n code: 'unsupported-provider',\n severity: 'error',\n apiId: contexts[0]?.api.id ?? 'generated-api',\n path: 'infra.database.provider',\n message: 'Generated API database resources currently require the supabase provider.',\n });\n }\n\n for (const [registryId, api] of Object.entries(registry)) {\n if (registryId !== api.id) {\n diagnostics.push({\n code: 'registry-id-mismatch',\n severity: 'error',\n apiId: api.id,\n path: `generatedApis.${registryId}.id`,\n message: `Generated API registry key '${registryId}' does not match definition id '${api.id}'.`,\n });\n }\n }\n\n for (const context of contexts) {\n const { api, resource } = context;\n const resourceIds = resourceIdsByApi.get(api.id) ?? new Set<string>();\n if (resourceIds.has(resource.id)) {\n diagnostics.push(\n resourceDiagnostic(\n context,\n 'duplicate-resource-id',\n 'id',\n `Resource ID '${resource.id}' is duplicated.`,\n ),\n );\n }\n resourceIds.add(resource.id);\n resourceIdsByApi.set(api.id, resourceIds);\n\n validateIdentifier(context, 'collection.name', resource.collection.name, diagnostics);\n validateIdentifier(\n context,\n 'collection.schema',\n resource.collection.schema ?? DEFAULT_DATABASE_SCHEMA,\n diagnostics,\n );\n validateFields(context, diagnostics);\n validatePrimaryKey(context, diagnostics);\n validateSeeds(context, diagnostics);\n\n const target = `${resource.collection.schema ?? DEFAULT_DATABASE_SCHEMA}.${resource.collection.name}`;\n const previous = targets.get(target);\n if (previous !== undefined) {\n diagnostics.push(\n resourceDiagnostic(\n context,\n 'duplicate-target',\n 'collection',\n `Database target '${target}' is already owned by ${previous.api.id}/${previous.resource.id}.`,\n ),\n );\n } else {\n targets.set(target, context);\n }\n\n if ((resource.policies?.length ?? 0) > 0) {\n diagnostics.push(\n resourceDiagnostic(\n context,\n 'unsupported-policy',\n 'policies',\n 'Policy references enable RLS, but the canonical contract does not yet contain provider-owned SQL policy expressions; no CREATE POLICY statement is emitted.',\n 'warning',\n ),\n );\n }\n }\n\n return diagnostics;\n}\n\nfunction validateFields(\n context: GeneratedResourceContext,\n diagnostics: GeneratedApiDatabaseDiagnostic[],\n): void {\n const fieldNames = new Set<string>();\n for (const field of context.resource.collection.fields) {\n validateIdentifier(context, `collection.fields.${field.name}.name`, field.name, diagnostics);\n if (fieldNames.has(field.name)) {\n diagnostics.push(\n resourceDiagnostic(\n context,\n 'duplicate-field',\n `collection.fields.${field.name}`,\n `Field '${field.name}' is duplicated.`,\n ),\n );\n }\n fieldNames.add(field.name);\n\n if (!isCompatibleDefault(field)) {\n diagnostics.push(\n resourceDiagnostic(\n context,\n 'invalid-default',\n `collection.fields.${field.name}.defaultValue`,\n `Default value for '${field.name}' is incompatible with field type '${field.type}'.`,\n ),\n );\n }\n }\n}\n\nfunction validatePrimaryKey(\n context: GeneratedResourceContext,\n diagnostics: GeneratedApiDatabaseDiagnostic[],\n): void {\n const { primaryKey } = context.resource.collection;\n if (primaryKey === undefined) return;\n\n validateIdentifier(context, 'collection.primaryKey', primaryKey, diagnostics);\n if (!context.resource.collection.fields.some((field) => field.name === primaryKey)) {\n diagnostics.push(\n resourceDiagnostic(\n context,\n 'invalid-primary-key',\n 'collection.primaryKey',\n `Primary key '${primaryKey}' must reference a declared field.`,\n ),\n );\n }\n}\n\nfunction validateSeeds(\n context: GeneratedResourceContext,\n diagnostics: GeneratedApiDatabaseDiagnostic[],\n): void {\n const fields = new Map(context.resource.collection.fields.map((field) => [field.name, field]));\n const { primaryKey } = context.resource.collection;\n\n context.seed.forEach((record, index) => {\n for (const key of Object.keys(record)) {\n if (!fields.has(key)) {\n diagnostics.push(\n resourceDiagnostic(\n context,\n 'invalid-seed',\n `seed.${index}.${key}`,\n `Seed field '${key}' is not declared by the collection.`,\n ),\n );\n }\n }\n\n for (const field of fields.values()) {\n const value = record[field.name];\n const generatedUuidPrimaryKey =\n field.name === primaryKey && field.type === 'uuid' && value === undefined;\n const requiresNonNullValue = field.required === true || field.name === primaryKey;\n\n if (value === undefined) {\n if (requiresNonNullValue && field.defaultValue === undefined && !generatedUuidPrimaryKey) {\n diagnostics.push(\n resourceDiagnostic(\n context,\n 'invalid-seed',\n `seed.${index}.${field.name}`,\n `Seed record is missing required field '${field.name}'.`,\n ),\n );\n }\n continue;\n }\n\n if (value === null) {\n if (requiresNonNullValue) {\n diagnostics.push(\n resourceDiagnostic(\n context,\n 'invalid-seed',\n `seed.${index}.${field.name}`,\n `Seed field '${field.name}' cannot be null.`,\n ),\n );\n }\n continue;\n }\n\n if (!isCompatibleFieldValue(field, value)) {\n diagnostics.push(\n resourceDiagnostic(\n context,\n 'invalid-seed',\n `seed.${index}.${field.name}`,\n `Seed value for '${field.name}' is incompatible with field type '${field.type}'.`,\n ),\n );\n }\n }\n });\n}\n\nfunction validateIdentifier(\n context: GeneratedResourceContext,\n path: string,\n value: string,\n diagnostics: GeneratedApiDatabaseDiagnostic[],\n): void {\n if (SQL_IDENTIFIER_RE.test(value)) return;\n diagnostics.push(\n resourceDiagnostic(\n context,\n 'invalid-identifier',\n path,\n `Database identifier '${value}' must match ${SQL_IDENTIFIER_RE.source}.`,\n ),\n );\n}\n\nfunction resourceDiagnostic(\n context: GeneratedResourceContext,\n code: GeneratedApiDatabaseDiagnosticCode,\n path: string,\n message: string,\n severity: GeneratedApiDatabaseDiagnostic['severity'] = 'error',\n): GeneratedApiDatabaseDiagnostic {\n return {\n code,\n severity,\n apiId: context.api.id,\n resourceId: context.resource.id,\n path: `generatedApis.${context.api.id}.resources.${context.resource.id}.${path}`,\n message,\n };\n}\n\nfunction isCompatibleDefault(field: DbFieldDefinition): boolean {\n const value = field.defaultValue;\n if (value === undefined || value === null) return true;\n return isCompatibleFieldValue(field, value);\n}\n\nfunction isCompatibleFieldValue(field: DbFieldDefinition, value: DataContractValue): boolean {\n switch (field.type) {\n case 'boolean':\n return typeof value === 'boolean';\n case 'number':\n return typeof value === 'number' && Number.isFinite(value);\n case 'text':\n return typeof value === 'string';\n case 'datetime':\n return typeof value === 'string' && Number.isFinite(Date.parse(value));\n case 'uuid':\n return typeof value === 'string' && UUID_RE.test(value);\n case 'json':\n return true;\n }\n}\n\nfunction createSeedEntry(context: GeneratedResourceContext): GeneratedSeedEntry {\n return {\n apiId: context.api.id,\n resourceId: context.resource.id,\n collection: context.resource.collection,\n records: context.seed.map((record, index) => materializeSeedRecord(context, record, index)),\n };\n}\n\nfunction materializeSeedRecord(\n context: GeneratedResourceContext,\n record: GeneratedApiSeedRecord,\n index: number,\n): GeneratedApiSeedRecord {\n const { primaryKey } = context.resource.collection;\n if (primaryKey === undefined || record[primaryKey] !== undefined) return record;\n\n const primaryKeyField = context.resource.collection.fields.find(\n (field) => field.name === primaryKey,\n );\n if (primaryKeyField?.type !== 'uuid') return record;\n\n return {\n ...record,\n [primaryKey]: createDeterministicSeedUuid(context.api.id, context.resource.id, index),\n };\n}\n\nfunction generateMigrationSql(contexts: readonly GeneratedResourceContext[]): string {\n const statements = contexts.flatMap((context) => {\n const schema = quoteIdentifier(context.resource.collection.schema ?? DEFAULT_DATABASE_SCHEMA);\n const table = quoteIdentifier(context.resource.collection.name);\n const columns = context.resource.collection.fields.map((field) =>\n formatColumn(field, field.name === context.resource.collection.primaryKey),\n );\n const rls =\n (context.resource.policies?.length ?? 0) > 0\n ? [`alter table ${schema}.${table} enable row level security;`]\n : [];\n\n return [\n `create schema if not exists ${schema};`,\n `create table if not exists ${schema}.${table} (\\n ${columns.join(',\\n ')}\\n);`,\n ...rls,\n ];\n });\n\n return [\n '-- Generated from canonical GeneratedApiDefinition resources.',\n '-- No HTTP/GraphQL service or Kubernetes API workload is generated here.',\n 'create extension if not exists pgcrypto;',\n '',\n ...statements,\n '',\n ].join('\\n');\n}\n\nfunction generateSeedSql(entries: readonly GeneratedSeedEntry[]): string {\n const statements = entries.flatMap((entry) => createSeedStatements(entry));\n return [\n '-- Generated from canonical generated API seed records.',\n ...(statements.length === 0 ? ['-- No generated API seed records configured.'] : statements),\n '',\n ].join('\\n');\n}\n\nfunction createSeedStatements(entry: GeneratedSeedEntry): readonly string[] {\n if (entry.records.length === 0) return [];\n\n const fields = entry.collection.fields.filter((field) =>\n entry.records.some((record) => record[field.name] !== undefined),\n );\n if (fields.length === 0) return [];\n\n const schema = quoteIdentifier(entry.collection.schema ?? DEFAULT_DATABASE_SCHEMA);\n const table = quoteIdentifier(entry.collection.name);\n const values = entry.records\n .map(\n (record) =>\n `(${fields.map((field) => formatSeedValue(field, record[field.name])).join(', ')})`,\n )\n .join(',\\n ');\n const conflict =\n entry.collection.primaryKey === undefined\n ? 'on conflict do nothing'\n : `on conflict (${quoteIdentifier(entry.collection.primaryKey)}) do nothing`;\n\n return [\n `insert into ${schema}.${table} (${fields.map((field) => quoteIdentifier(field.name)).join(', ')}) values\\n ${values}\\n${conflict};`,\n ];\n}\n\nfunction formatSeedValue(field: DbFieldDefinition, value: DataContractValue | undefined): string {\n if (value === undefined) return 'default';\n return formatFieldValue(field, value);\n}\n\nfunction formatColumn(field: DbFieldDefinition, primaryKey: boolean): string {\n const defaultValue = formatDefault(field, primaryKey);\n const primaryKeyClause = primaryKey ? ' primary key' : '';\n const required = field.required === true && !primaryKey ? ' not null' : '';\n const unique = field.unique === true && !primaryKey ? ' unique' : '';\n return `${quoteIdentifier(field.name)} ${mapFieldType(field.type)}${defaultValue}${primaryKeyClause}${required}${unique}`;\n}\n\nfunction mapFieldType(type: DbFieldDefinition['type']): string {\n if (type === 'uuid') return 'uuid';\n if (type === 'text') return 'text';\n if (type === 'number') return 'numeric';\n if (type === 'boolean') return 'boolean';\n if (type === 'datetime') return 'timestamptz';\n return 'jsonb';\n}\n\nfunction formatDefault(field: DbFieldDefinition, primaryKey: boolean): string {\n if (primaryKey && field.type === 'uuid' && field.defaultValue === undefined) {\n return ' default gen_random_uuid()';\n }\n if (field.defaultValue === undefined) return '';\n return ` default ${formatFieldValue(field, field.defaultValue)}`;\n}\n\nfunction formatFieldValue(field: DbFieldDefinition, value: DataContractValue): string {\n if (value === null) return 'null';\n if (field.type === 'json') {\n return `'${escapeString(JSON.stringify(value))}'::jsonb`;\n }\n return formatValue(value);\n}\n\nfunction formatValue(value: DataContractValue): string {\n if (value === null) return 'null';\n if (typeof value === 'string') return `'${escapeString(value)}'`;\n if (typeof value === 'number') return Number.isFinite(value) ? String(value) : 'null';\n if (typeof value === 'boolean') return value ? 'true' : 'false';\n return `'${escapeString(JSON.stringify(value))}'::jsonb`;\n}\n\nfunction generateReadme(contexts: readonly GeneratedResourceContext[]): string {\n const resources = contexts\n .map((context) => {\n const { collection } = context.resource;\n return `- \\`${context.api.id}/${context.resource.id}\\` -> \\`${collection.schema ?? DEFAULT_DATABASE_SCHEMA}.${collection.name}\\``;\n })\n .join('\\n');\n\n return `# Generated API Database Artifacts\\n\\nThese files materialize canonical generated API resources into Supabase/Postgres database infrastructure.\\n\\n${resources}\\n\\nNo HTTP/GraphQL server, Docker image, application handler, OpenAPI document, Kubernetes Deployment or Service is generated by this bridge.\\n`;\n}\n\nfunction jsonFile(path: string, value: unknown): GeneratedInfrastructureFile {\n return { path, content: `${JSON.stringify(value, null, 2)}\\n` };\n}\n\nfunction quoteIdentifier(identifier: string): string {\n return `\"${identifier.replaceAll('\"', '\"\"')}\"`;\n}\n\nfunction escapeString(value: string): string {\n return value.replaceAll(\"'\", \"''\");\n}\n\nfunction createDeterministicSeedUuid(apiId: string, resourceId: string, index: number): string {\n const input = `${apiId}:${resourceId}:${index}`;\n const hex = `${hashHex(input, 0)}${hashHex(input, 1)}${hashHex(input, 2)}${hashHex(input, 3)}`;\n const variant = ((Number.parseInt(hex.charAt(16), 16) & 0x3) | 0x8).toString(16);\n return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-4${hex.slice(13, 16)}-${variant}${hex.slice(17, 20)}-${hex.slice(20, 32)}`;\n}\n\nfunction hashHex(input: string, salt: number): string {\n let hash = 2166136261 ^ salt;\n for (const char of input) {\n hash ^= char.charCodeAt(0);\n hash = Math.imul(hash, 16777619);\n }\n return (hash >>> 0).toString(16).padStart(8, '0');\n}\n"]}
package/dist/index.d.ts CHANGED
@@ -1,7 +1,6 @@
1
1
  import type { InfraGenerationInput, InfraManifestInput, InfrastructureGenerationOptions, InfrastructureGenerationResult } from './types';
2
- export type { ApiInfrastructureArtifacts } from './apiArtifacts';
3
- export { generateApiInfrastructureArtifacts } from './apiArtifacts';
4
2
  export { type AuthRedirectConfiguration, type AuthRedirectEnvironment, getLocalAuthRedirectPatterns, normalizeAuthCallbackRoute, resolveAuthRedirectConfiguration, type ResolveAuthRedirectConfigurationInput, } from './authRedirects';
3
+ export { type GeneratedApiDatabaseArtifacts, type GeneratedApiDatabaseDiagnostic, type GeneratedApiDatabaseDiagnosticCode, generateGeneratedApiDatabaseArtifacts, } from './generatedApiDatabase';
5
4
  export { createInfraSecretStoreAdapter, type CreateInfraSecretStoreAdapterInput, type InfraSecretStoreProviders, } from './secretStore';
6
5
  export type { GeneratedFile, GeneratedInfrastructureFile, GeneratedPackageDependency, InfraDiagnostic, InfraGenerationInput, InfraGenerationOptions, InfraGenerationResult, InfraManifestInput, InfrastructureGenerationMeta, InfrastructureGenerationOptions, InfrastructureGenerationResult, PackageDependency, } from './types';
7
6
  export declare function generateInfra(input: InfraGenerationInput): InfrastructureGenerationResult;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,oBAAoB,EACpB,kBAAkB,EAClB,+BAA+B,EAC/B,8BAA8B,EAC/B,MAAM,SAAS,CAAC;AAEjB,YAAY,EAAE,0BAA0B,EAAE,MAAM,gBAAgB,CAAC;AACjE,OAAO,EAAE,kCAAkC,EAAE,MAAM,gBAAgB,CAAC;AACpE,OAAO,EACL,KAAK,yBAAyB,EAC9B,KAAK,uBAAuB,EAC5B,4BAA4B,EAC5B,0BAA0B,EAC1B,gCAAgC,EAChC,KAAK,qCAAqC,GAC3C,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,6BAA6B,EAC7B,KAAK,kCAAkC,EACvC,KAAK,yBAAyB,GAC/B,MAAM,eAAe,CAAC;AACvB,YAAY,EACV,aAAa,EACb,2BAA2B,EAC3B,0BAA0B,EAC1B,eAAe,EACf,oBAAoB,EACpB,sBAAsB,EACtB,qBAAqB,EACrB,kBAAkB,EAClB,4BAA4B,EAC5B,+BAA+B,EAC/B,8BAA8B,EAC9B,iBAAiB,GAClB,MAAM,SAAS,CAAC;AAEjB,wBAAgB,aAAa,CAAC,KAAK,EAAE,oBAAoB,GAAG,8BAA8B,CAEzF;AAED,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,kBAAkB,EAC5B,OAAO,GAAE,+BAAoC,GAC5C,8BAA8B,CAUhC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,oBAAoB,EACpB,kBAAkB,EAClB,+BAA+B,EAC/B,8BAA8B,EAC/B,MAAM,SAAS,CAAC;AAEjB,OAAO,EACL,KAAK,yBAAyB,EAC9B,KAAK,uBAAuB,EAC5B,4BAA4B,EAC5B,0BAA0B,EAC1B,gCAAgC,EAChC,KAAK,qCAAqC,GAC3C,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,KAAK,6BAA6B,EAClC,KAAK,8BAA8B,EACnC,KAAK,kCAAkC,EACvC,qCAAqC,GACtC,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACL,6BAA6B,EAC7B,KAAK,kCAAkC,EACvC,KAAK,yBAAyB,GAC/B,MAAM,eAAe,CAAC;AACvB,YAAY,EACV,aAAa,EACb,2BAA2B,EAC3B,0BAA0B,EAC1B,eAAe,EACf,oBAAoB,EACpB,sBAAsB,EACtB,qBAAqB,EACrB,kBAAkB,EAClB,4BAA4B,EAC5B,+BAA+B,EAC/B,8BAA8B,EAC9B,iBAAiB,GAClB,MAAM,SAAS,CAAC;AAEjB,wBAAgB,aAAa,CAAC,KAAK,EAAE,oBAAoB,GAAG,8BAA8B,CAEzF;AAED,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,kBAAkB,EAC5B,OAAO,GAAE,+BAAoC,GAC5C,8BAA8B,CAUhC"}
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { generateMinikubeInfra } from './adapters/minikube';
2
- export { generateApiInfrastructureArtifacts } from './apiArtifacts';
3
2
  export { getLocalAuthRedirectPatterns, normalizeAuthCallbackRoute, resolveAuthRedirectConfiguration, } from './authRedirects';
3
+ export { generateGeneratedApiDatabaseArtifacts, } from './generatedApiDatabase';
4
4
  export { createInfraSecretStoreAdapter, } from './secretStore';
5
5
  export function generateInfra(input) {
6
6
  return generateInfrastructure(input.manifest, input.options ?? {});
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAS5D,OAAO,EAAE,kCAAkC,EAAE,MAAM,gBAAgB,CAAC;AACpE,OAAO,EAGL,4BAA4B,EAC5B,0BAA0B,EAC1B,gCAAgC,GAEjC,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,6BAA6B,GAG9B,MAAM,eAAe,CAAC;AAgBvB,MAAM,UAAU,aAAa,CAAC,KAA2B;IACvD,OAAO,sBAAsB,CAAC,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC;AACrE,CAAC;AAED,MAAM,UAAU,sBAAsB,CACpC,QAA4B,EAC5B,UAA2C,EAAE;IAE7C,IAAI,CAAC,QAAQ,CAAC,UAAU,EAAE,CAAC;QACzB,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAC;IAC1D,CAAC;IAED,IAAI,QAAQ,CAAC,UAAU,CAAC,MAAM,KAAK,UAAU,EAAE,CAAC;QAC9C,MAAM,IAAI,KAAK,CAAC,kCAAkC,QAAQ,CAAC,UAAU,CAAC,MAAM,EAAE,CAAC,CAAC;IAClF,CAAC;IAED,OAAO,qBAAqB,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;AAClD,CAAC","sourcesContent":["import { generateMinikubeInfra } from './adapters/minikube';\nimport type {\n InfraGenerationInput,\n InfraManifestInput,\n InfrastructureGenerationOptions,\n InfrastructureGenerationResult,\n} from './types';\n\nexport type { ApiInfrastructureArtifacts } from './apiArtifacts';\nexport { generateApiInfrastructureArtifacts } from './apiArtifacts';\nexport {\n type AuthRedirectConfiguration,\n type AuthRedirectEnvironment,\n getLocalAuthRedirectPatterns,\n normalizeAuthCallbackRoute,\n resolveAuthRedirectConfiguration,\n type ResolveAuthRedirectConfigurationInput,\n} from './authRedirects';\nexport {\n createInfraSecretStoreAdapter,\n type CreateInfraSecretStoreAdapterInput,\n type InfraSecretStoreProviders,\n} from './secretStore';\nexport type {\n GeneratedFile,\n GeneratedInfrastructureFile,\n GeneratedPackageDependency,\n InfraDiagnostic,\n InfraGenerationInput,\n InfraGenerationOptions,\n InfraGenerationResult,\n InfraManifestInput,\n InfrastructureGenerationMeta,\n InfrastructureGenerationOptions,\n InfrastructureGenerationResult,\n PackageDependency,\n} from './types';\n\nexport function generateInfra(input: InfraGenerationInput): InfrastructureGenerationResult {\n return generateInfrastructure(input.manifest, input.options ?? {});\n}\n\nexport function generateInfrastructure(\n manifest: InfraManifestInput,\n options: InfrastructureGenerationOptions = {},\n): InfrastructureGenerationResult {\n if (!manifest.deployment) {\n throw new Error('Deployment configuration is missing.');\n }\n\n if (manifest.deployment.target !== 'minikube') {\n throw new Error(`Unsupported deployment target: ${manifest.deployment.target}`);\n }\n\n return generateMinikubeInfra(manifest, options);\n}\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAQ5D,OAAO,EAGL,4BAA4B,EAC5B,0BAA0B,EAC1B,gCAAgC,GAEjC,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAIL,qCAAqC,GACtC,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACL,6BAA6B,GAG9B,MAAM,eAAe,CAAC;AAgBvB,MAAM,UAAU,aAAa,CAAC,KAA2B;IACvD,OAAO,sBAAsB,CAAC,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC;AACrE,CAAC;AAED,MAAM,UAAU,sBAAsB,CACpC,QAA4B,EAC5B,UAA2C,EAAE;IAE7C,IAAI,CAAC,QAAQ,CAAC,UAAU,EAAE,CAAC;QACzB,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAC;IAC1D,CAAC;IAED,IAAI,QAAQ,CAAC,UAAU,CAAC,MAAM,KAAK,UAAU,EAAE,CAAC;QAC9C,MAAM,IAAI,KAAK,CAAC,kCAAkC,QAAQ,CAAC,UAAU,CAAC,MAAM,EAAE,CAAC,CAAC;IAClF,CAAC;IAED,OAAO,qBAAqB,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;AAClD,CAAC","sourcesContent":["import { generateMinikubeInfra } from './adapters/minikube';\nimport type {\n InfraGenerationInput,\n InfraManifestInput,\n InfrastructureGenerationOptions,\n InfrastructureGenerationResult,\n} from './types';\n\nexport {\n type AuthRedirectConfiguration,\n type AuthRedirectEnvironment,\n getLocalAuthRedirectPatterns,\n normalizeAuthCallbackRoute,\n resolveAuthRedirectConfiguration,\n type ResolveAuthRedirectConfigurationInput,\n} from './authRedirects';\nexport {\n type GeneratedApiDatabaseArtifacts,\n type GeneratedApiDatabaseDiagnostic,\n type GeneratedApiDatabaseDiagnosticCode,\n generateGeneratedApiDatabaseArtifacts,\n} from './generatedApiDatabase';\nexport {\n createInfraSecretStoreAdapter,\n type CreateInfraSecretStoreAdapterInput,\n type InfraSecretStoreProviders,\n} from './secretStore';\nexport type {\n GeneratedFile,\n GeneratedInfrastructureFile,\n GeneratedPackageDependency,\n InfraDiagnostic,\n InfraGenerationInput,\n InfraGenerationOptions,\n InfraGenerationResult,\n InfraManifestInput,\n InfrastructureGenerationMeta,\n InfrastructureGenerationOptions,\n InfrastructureGenerationResult,\n PackageDependency,\n} from './types';\n\nexport function generateInfra(input: InfraGenerationInput): InfrastructureGenerationResult {\n return generateInfrastructure(input.manifest, input.options ?? {});\n}\n\nexport function generateInfrastructure(\n manifest: InfraManifestInput,\n options: InfrastructureGenerationOptions = {},\n): InfrastructureGenerationResult {\n if (!manifest.deployment) {\n throw new Error('Deployment configuration is missing.');\n }\n\n if (manifest.deployment.target !== 'minikube') {\n throw new Error(`Unsupported deployment target: ${manifest.deployment.target}`);\n }\n\n return generateMinikubeInfra(manifest, options);\n}\n"]}
package/dist/project.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { AppManifest } from '@ankhorage/contracts';
1
+ import { type AppManifest } from '@ankhorage/contracts';
2
2
  export interface ResolvedInfraProject {
3
3
  readonly appsRoot: string;
4
4
  readonly manifest: AppManifest;
@@ -1 +1 @@
1
- {"version":3,"file":"project.d.ts","sourceRoot":"","sources":["../src/project.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAiB,MAAM,sBAAsB,CAAC;AAIvE,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC;IAC/B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;CAChC;AAED,wBAAsB,mBAAmB,CAAC,OAAO,EAAE;IACjD,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC7B,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAqChC"}
1
+ {"version":3,"file":"project.d.ts","sourceRoot":"","sources":["../src/project.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,KAAK,WAAW,EAAsB,MAAM,sBAAsB,CAAC;AAI5F,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC;IAC/B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;CAChC;AAED,wBAAsB,mBAAmB,CAAC,OAAO,EAAE;IACjD,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC7B,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAqChC"}
package/dist/project.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { APP_CATEGORIES } from '@ankhorage/contracts';
1
2
  import { promises as fs } from 'fs';
2
3
  import path from 'path';
3
4
  export async function resolveInfraProject(options) {
@@ -45,6 +46,7 @@ function createFallbackManifest(projectId) {
45
46
  name: projectId,
46
47
  slug: projectId,
47
48
  version: '0.0.0',
49
+ category: 'developer_tools',
48
50
  themeId: 'default',
49
51
  },
50
52
  themes: [],
@@ -134,6 +136,7 @@ function isAppManifestMetadata(value) {
134
136
  typeof value.name === 'string' &&
135
137
  typeof value.slug === 'string' &&
136
138
  typeof value.version === 'string' &&
139
+ APP_CATEGORIES.some((category) => category === value.category) &&
137
140
  typeof value.themeId === 'string' &&
138
141
  (value.created === undefined || typeof value.created === 'string') &&
139
142
  (value.updated === undefined || typeof value.updated === 'string'));
@@ -1 +1 @@
1
- {"version":3,"file":"project.js","sourceRoot":"","sources":["../src/project.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AppManifest, NavigatorSpec } from '@ankhorage/contracts';\nimport { promises as fs } from 'fs';\nimport path from 'path';\n\nexport interface ResolvedInfraProject {\n readonly appsRoot: string;\n readonly manifest: AppManifest;\n readonly manifestPath: string;\n readonly projectId: string;\n readonly projectPath: string;\n readonly workspaceRoot: string;\n}\n\nexport async function resolveInfraProject(options: {\n readonly cwd: string;\n readonly projectId?: string;\n}): Promise<ResolvedInfraProject> {\n const workspaceRoot = await findWorkspaceRoot(options.cwd);\n if (workspaceRoot === null) {\n throw new Error(`Could not find an Ankh workspace root from cwd: ${options.cwd}`);\n }\n\n const appsRoot = path.join(workspaceRoot, 'apps');\n const projectId =\n options.projectId === undefined\n ? inferProjectId(options.cwd, appsRoot)\n : validateExplicitProjectId(options.projectId);\n if (projectId === null) {\n throw new Error(\n 'Could not infer a project from cwd. Pass a project id or run the command inside apps/<project>.',\n );\n }\n\n const projectPath = resolveProjectPath(appsRoot, projectId);\n if (!(await pathExists(projectPath))) {\n throw new Error(`Project '${projectId}' not found.`);\n }\n\n const manifestPath = path.join(projectPath, 'ankh.config.json');\n const manifest = await readProjectManifest({\n manifestPath,\n projectId,\n projectPath,\n });\n\n return {\n appsRoot,\n manifest,\n manifestPath,\n projectId,\n projectPath,\n workspaceRoot,\n };\n}\n\nfunction resolveProjectPath(appsRoot: string, projectId: string): string {\n const projectPath = path.resolve(appsRoot, projectId);\n const appsRootPath = `${path.resolve(appsRoot)}${path.sep}`;\n\n if (!projectPath.startsWith(appsRootPath)) {\n throw new Error('Security check failed while resolving the project path.');\n }\n\n return projectPath;\n}\n\nfunction createFallbackManifest(projectId: string): AppManifest {\n return {\n metadata: {\n name: projectId,\n slug: projectId,\n version: '0.0.0',\n themeId: 'default',\n },\n themes: [],\n activeThemeId: 'default',\n infra: {\n plugins: [],\n },\n navigator: {\n type: 'stack',\n routes: [{ name: 'index', screenId: 'index' }],\n },\n screens: {},\n settings: {\n localization: {\n defaultLocale: 'en',\n locales: ['en'],\n },\n },\n };\n}\n\nasync function readProjectManifest(args: {\n readonly manifestPath: string;\n readonly projectId: string;\n readonly projectPath: string;\n}): Promise<AppManifest> {\n if (!(await pathExists(args.manifestPath))) {\n return createFallbackManifest(args.projectId);\n }\n\n const rawManifest = await fs.readFile(args.manifestPath, 'utf8');\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(rawManifest);\n } catch (error) {\n throw new Error(\n `Project manifest is not valid JSON: ${args.manifestPath}: ${getErrorMessage(error)}`,\n { cause: error },\n );\n }\n\n if (!isAppManifest(parsed)) {\n throw new Error(`Project manifest has an invalid shape: ${args.manifestPath}`);\n }\n\n return parsed;\n}\n\nasync function findWorkspaceRoot(startPath: string): Promise<string | null> {\n let currentPath = path.resolve(startPath);\n\n for (;;) {\n const appsRoot = path.join(currentPath, 'apps');\n if (await isDirectory(appsRoot)) {\n return currentPath;\n }\n\n const parentPath = path.dirname(currentPath);\n if (parentPath === currentPath) {\n return null;\n }\n\n currentPath = parentPath;\n }\n}\n\nfunction inferProjectId(cwd: string, appsRoot: string): string | null {\n const relativePath = path.relative(path.resolve(appsRoot), path.resolve(cwd));\n if (relativePath === '' || relativePath.startsWith('..') || path.isAbsolute(relativePath)) {\n return null;\n }\n\n const [projectId] = relativePath.split(path.sep);\n return projectId === undefined || projectId.length === 0 ? null : path.basename(projectId);\n}\n\nfunction validateExplicitProjectId(projectId: string): string {\n if (projectId.trim().length === 0) {\n throw new Error('Invalid project id: expected a single safe project segment.');\n }\n\n if (\n projectId === '.' ||\n projectId === '..' ||\n path.isAbsolute(projectId) ||\n projectId.includes('/') ||\n projectId.includes('\\\\')\n ) {\n throw new Error(`Invalid project id: ${projectId}. Expected a single safe project segment.`);\n }\n\n return projectId;\n}\n\nfunction isAppManifest(value: unknown): value is AppManifest {\n if (!isRecord(value)) {\n return false;\n }\n\n return (\n isAppManifestMetadata(value.metadata) &&\n Array.isArray(value.themes) &&\n typeof value.activeThemeId === 'string' &&\n isInfraManifestRecord(value.infra) &&\n isNavigatorSpec(value.navigator) &&\n isRecord(value.screens) &&\n isSettingsRecord(value.settings)\n );\n}\n\nfunction isAppManifestMetadata(value: unknown): value is AppManifest['metadata'] {\n return (\n isRecord(value) &&\n typeof value.name === 'string' &&\n typeof value.slug === 'string' &&\n typeof value.version === 'string' &&\n typeof value.themeId === 'string' &&\n (value.created === undefined || typeof value.created === 'string') &&\n (value.updated === undefined || typeof value.updated === 'string')\n );\n}\n\nfunction isInfraManifestRecord(value: unknown): value is AppManifest['infra'] {\n return isRecord(value) && Array.isArray(value.plugins);\n}\n\nfunction isNavigatorSpec(value: unknown): value is NavigatorSpec {\n return (\n isRecord(value) &&\n typeof value.type === 'string' &&\n Array.isArray(value.routes) &&\n (value.initialRouteName === undefined || typeof value.initialRouteName === 'string')\n );\n}\n\nfunction isSettingsRecord(value: unknown): value is AppManifest['settings'] {\n return (\n isRecord(value) &&\n (value.apiBaseUrl === undefined || typeof value.apiBaseUrl === 'string') &&\n isLocalizationRecord(value.localization)\n );\n}\n\nfunction isLocalizationRecord(value: unknown): value is AppManifest['settings']['localization'] {\n return (\n isRecord(value) &&\n typeof value.defaultLocale === 'string' &&\n Array.isArray(value.locales) &&\n value.locales.every((locale) => typeof locale === 'string')\n );\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null;\n}\n\nasync function isDirectory(filePath: string): Promise<boolean> {\n try {\n const stat = await fs.stat(filePath);\n return stat.isDirectory();\n } catch {\n return false;\n }\n}\n\nasync function pathExists(filePath: string): Promise<boolean> {\n try {\n await fs.access(filePath);\n return true;\n } catch {\n return false;\n }\n}\n\nfunction getErrorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n"]}
1
+ {"version":3,"file":"project.js","sourceRoot":"","sources":["../src/project.ts"],"names":[],"mappings":"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","sourcesContent":["import { APP_CATEGORIES, type AppManifest, type NavigatorSpec } from '@ankhorage/contracts';\nimport { promises as fs } from 'fs';\nimport path from 'path';\n\nexport interface ResolvedInfraProject {\n readonly appsRoot: string;\n readonly manifest: AppManifest;\n readonly manifestPath: string;\n readonly projectId: string;\n readonly projectPath: string;\n readonly workspaceRoot: string;\n}\n\nexport async function resolveInfraProject(options: {\n readonly cwd: string;\n readonly projectId?: string;\n}): Promise<ResolvedInfraProject> {\n const workspaceRoot = await findWorkspaceRoot(options.cwd);\n if (workspaceRoot === null) {\n throw new Error(`Could not find an Ankh workspace root from cwd: ${options.cwd}`);\n }\n\n const appsRoot = path.join(workspaceRoot, 'apps');\n const projectId =\n options.projectId === undefined\n ? inferProjectId(options.cwd, appsRoot)\n : validateExplicitProjectId(options.projectId);\n if (projectId === null) {\n throw new Error(\n 'Could not infer a project from cwd. Pass a project id or run the command inside apps/<project>.',\n );\n }\n\n const projectPath = resolveProjectPath(appsRoot, projectId);\n if (!(await pathExists(projectPath))) {\n throw new Error(`Project '${projectId}' not found.`);\n }\n\n const manifestPath = path.join(projectPath, 'ankh.config.json');\n const manifest = await readProjectManifest({\n manifestPath,\n projectId,\n projectPath,\n });\n\n return {\n appsRoot,\n manifest,\n manifestPath,\n projectId,\n projectPath,\n workspaceRoot,\n };\n}\n\nfunction resolveProjectPath(appsRoot: string, projectId: string): string {\n const projectPath = path.resolve(appsRoot, projectId);\n const appsRootPath = `${path.resolve(appsRoot)}${path.sep}`;\n\n if (!projectPath.startsWith(appsRootPath)) {\n throw new Error('Security check failed while resolving the project path.');\n }\n\n return projectPath;\n}\n\nfunction createFallbackManifest(projectId: string): AppManifest {\n return {\n metadata: {\n name: projectId,\n slug: projectId,\n version: '0.0.0',\n category: 'developer_tools',\n themeId: 'default',\n },\n themes: [],\n activeThemeId: 'default',\n infra: {\n plugins: [],\n },\n navigator: {\n type: 'stack',\n routes: [{ name: 'index', screenId: 'index' }],\n },\n screens: {},\n settings: {\n localization: {\n defaultLocale: 'en',\n locales: ['en'],\n },\n },\n };\n}\n\nasync function readProjectManifest(args: {\n readonly manifestPath: string;\n readonly projectId: string;\n readonly projectPath: string;\n}): Promise<AppManifest> {\n if (!(await pathExists(args.manifestPath))) {\n return createFallbackManifest(args.projectId);\n }\n\n const rawManifest = await fs.readFile(args.manifestPath, 'utf8');\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(rawManifest);\n } catch (error) {\n throw new Error(\n `Project manifest is not valid JSON: ${args.manifestPath}: ${getErrorMessage(error)}`,\n { cause: error },\n );\n }\n\n if (!isAppManifest(parsed)) {\n throw new Error(`Project manifest has an invalid shape: ${args.manifestPath}`);\n }\n\n return parsed;\n}\n\nasync function findWorkspaceRoot(startPath: string): Promise<string | null> {\n let currentPath = path.resolve(startPath);\n\n for (;;) {\n const appsRoot = path.join(currentPath, 'apps');\n if (await isDirectory(appsRoot)) {\n return currentPath;\n }\n\n const parentPath = path.dirname(currentPath);\n if (parentPath === currentPath) {\n return null;\n }\n\n currentPath = parentPath;\n }\n}\n\nfunction inferProjectId(cwd: string, appsRoot: string): string | null {\n const relativePath = path.relative(path.resolve(appsRoot), path.resolve(cwd));\n if (relativePath === '' || relativePath.startsWith('..') || path.isAbsolute(relativePath)) {\n return null;\n }\n\n const [projectId] = relativePath.split(path.sep);\n return projectId === undefined || projectId.length === 0 ? null : path.basename(projectId);\n}\n\nfunction validateExplicitProjectId(projectId: string): string {\n if (projectId.trim().length === 0) {\n throw new Error('Invalid project id: expected a single safe project segment.');\n }\n\n if (\n projectId === '.' ||\n projectId === '..' ||\n path.isAbsolute(projectId) ||\n projectId.includes('/') ||\n projectId.includes('\\\\')\n ) {\n throw new Error(`Invalid project id: ${projectId}. Expected a single safe project segment.`);\n }\n\n return projectId;\n}\n\nfunction isAppManifest(value: unknown): value is AppManifest {\n if (!isRecord(value)) {\n return false;\n }\n\n return (\n isAppManifestMetadata(value.metadata) &&\n Array.isArray(value.themes) &&\n typeof value.activeThemeId === 'string' &&\n isInfraManifestRecord(value.infra) &&\n isNavigatorSpec(value.navigator) &&\n isRecord(value.screens) &&\n isSettingsRecord(value.settings)\n );\n}\n\nfunction isAppManifestMetadata(value: unknown): value is AppManifest['metadata'] {\n return (\n isRecord(value) &&\n typeof value.name === 'string' &&\n typeof value.slug === 'string' &&\n typeof value.version === 'string' &&\n APP_CATEGORIES.some((category) => category === value.category) &&\n typeof value.themeId === 'string' &&\n (value.created === undefined || typeof value.created === 'string') &&\n (value.updated === undefined || typeof value.updated === 'string')\n );\n}\n\nfunction isInfraManifestRecord(value: unknown): value is AppManifest['infra'] {\n return isRecord(value) && Array.isArray(value.plugins);\n}\n\nfunction isNavigatorSpec(value: unknown): value is NavigatorSpec {\n return (\n isRecord(value) &&\n typeof value.type === 'string' &&\n Array.isArray(value.routes) &&\n (value.initialRouteName === undefined || typeof value.initialRouteName === 'string')\n );\n}\n\nfunction isSettingsRecord(value: unknown): value is AppManifest['settings'] {\n return (\n isRecord(value) &&\n (value.apiBaseUrl === undefined || typeof value.apiBaseUrl === 'string') &&\n isLocalizationRecord(value.localization)\n );\n}\n\nfunction isLocalizationRecord(value: unknown): value is AppManifest['settings']['localization'] {\n return (\n isRecord(value) &&\n typeof value.defaultLocale === 'string' &&\n Array.isArray(value.locales) &&\n value.locales.every((locale) => typeof locale === 'string')\n );\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null;\n}\n\nasync function isDirectory(filePath: string): Promise<boolean> {\n try {\n const stat = await fs.stat(filePath);\n return stat.isDirectory();\n } catch {\n return false;\n }\n}\n\nasync function pathExists(filePath: string): Promise<boolean> {\n try {\n await fs.access(filePath);\n return true;\n } catch {\n return false;\n }\n}\n\nfunction getErrorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"testSupport.d.ts","sourceRoot":"","sources":["../src/testSupport.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAKxD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAE/D,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,OAAO,EAAE,mBAAmB,CAAC;IACtC,QAAQ,CAAC,MAAM,EAAE;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IACnC,QAAQ,CAAC,MAAM,EAAE;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;CACpC;AAED,wBAAgB,4BAA4B,CAC1C,GAAG,EAAE,MAAM,EACX,OAAO,SAAU,GAChB,sBAAsB,CAmBxB;AAED,wBAAsB,sBAAsB,CAC1C,IAAI,GAAE;IACJ,QAAQ,CAAC,QAAQ,CAAC,EAAE,WAAW,CAAC;IAChC,QAAQ,CAAC,YAAY,CAAC,EAAE,cAAc,GAAG,SAAS,CAAC;IACnD,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CACxB,GACL,OAAO,CAAC;IACT,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B,CAAC,CA6BD;AAED,wBAAgB,iBAAiB,CAC/B,SAAS,EAAE,MAAM,EACjB,KAAK,GAAE,WAAW,CAAC,OAAO,CAAmB,GAC5C,WAAW,CAuBb"}
1
+ {"version":3,"file":"testSupport.d.ts","sourceRoot":"","sources":["../src/testSupport.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAKxD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAE/D,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,OAAO,EAAE,mBAAmB,CAAC;IACtC,QAAQ,CAAC,MAAM,EAAE;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IACnC,QAAQ,CAAC,MAAM,EAAE;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;CACpC;AAED,wBAAgB,4BAA4B,CAC1C,GAAG,EAAE,MAAM,EACX,OAAO,SAAU,GAChB,sBAAsB,CAmBxB;AAED,wBAAsB,sBAAsB,CAC1C,IAAI,GAAE;IACJ,QAAQ,CAAC,QAAQ,CAAC,EAAE,WAAW,CAAC;IAChC,QAAQ,CAAC,YAAY,CAAC,EAAE,cAAc,GAAG,SAAS,CAAC;IACnD,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CACxB,GACL,OAAO,CAAC;IACT,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B,CAAC,CA6BD;AAED,wBAAgB,iBAAiB,CAC/B,SAAS,EAAE,MAAM,EACjB,KAAK,GAAE,WAAW,CAAC,OAAO,CAAmB,GAC5C,WAAW,CAwBb"}
@@ -46,6 +46,7 @@ export function createAppManifest(projectId, infra = { plugins: [] }) {
46
46
  name: projectId,
47
47
  slug: projectId,
48
48
  version: '1.0.0',
49
+ category: 'developer_tools',
49
50
  themeId: 'default',
50
51
  },
51
52
  themes: [],
@@ -1 +1 @@
1
- {"version":3,"file":"testSupport.js","sourceRoot":"","sources":["../src/testSupport.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AppManifest } from '@ankhorage/contracts';\nimport { promises as fs } from 'fs';\nimport os from 'os';\nimport path from 'path';\n\nimport type { InfraCommandContext } from './commandContext.js';\n\nexport interface CapturedCommandContext {\n readonly context: InfraCommandContext;\n readonly stderr: { value: string };\n readonly stdout: { value: string };\n}\n\nexport function createCapturedCommandContext(\n cwd: string,\n version = '0.2.1',\n): CapturedCommandContext {\n const stdout = { value: '' };\n const stderr = { value: '' };\n\n return {\n stdout,\n stderr,\n context: {\n cwd,\n env: process.env,\n version,\n writeStdout(text: string) {\n stdout.value += text;\n },\n writeStderr(text: string) {\n stderr.value += text;\n },\n },\n };\n}\n\nexport async function createWorkspaceFixture(\n args: {\n readonly manifest?: AppManifest;\n readonly manifestFile?: 'invalid-json' | 'missing';\n readonly projectId?: string;\n } = {},\n): Promise<{\n readonly appsRoot: string;\n readonly projectId: string;\n readonly projectPath: string;\n readonly rootPath: string;\n}> {\n const rootPath = await fs.mkdtemp(path.join(os.tmpdir(), 'ankhorage-infra-'));\n const appsRoot = path.join(rootPath, 'apps');\n const projectId = args.projectId ?? 'shop';\n const projectPath = path.join(appsRoot, projectId);\n\n await fs.mkdir(projectPath, { recursive: true });\n await fs.writeFile(\n path.join(projectPath, 'package.json'),\n JSON.stringify({ name: projectId, version: '1.0.0' }, null, 2),\n 'utf8',\n );\n\n if (args.manifestFile === 'invalid-json') {\n await fs.writeFile(path.join(projectPath, 'ankh.config.json'), '{invalid', 'utf8');\n } else if (args.manifestFile !== 'missing') {\n await fs.writeFile(\n path.join(projectPath, 'ankh.config.json'),\n `${JSON.stringify(args.manifest ?? createAppManifest(projectId), null, 2)}\\n`,\n 'utf8',\n );\n }\n\n return {\n appsRoot,\n projectId,\n projectPath,\n rootPath,\n };\n}\n\nexport function createAppManifest(\n projectId: string,\n infra: AppManifest['infra'] = { plugins: [] },\n): AppManifest {\n return {\n metadata: {\n name: projectId,\n slug: projectId,\n version: '1.0.0',\n themeId: 'default',\n },\n themes: [],\n activeThemeId: 'default',\n infra,\n navigator: {\n type: 'stack',\n routes: [{ name: 'index', screenId: 'index' }],\n },\n screens: {},\n settings: {\n localization: {\n defaultLocale: 'en',\n locales: ['en'],\n },\n },\n };\n}\n"]}
1
+ {"version":3,"file":"testSupport.js","sourceRoot":"","sources":["../src/testSupport.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AppManifest } from '@ankhorage/contracts';\nimport { promises as fs } from 'fs';\nimport os from 'os';\nimport path from 'path';\n\nimport type { InfraCommandContext } from './commandContext.js';\n\nexport interface CapturedCommandContext {\n readonly context: InfraCommandContext;\n readonly stderr: { value: string };\n readonly stdout: { value: string };\n}\n\nexport function createCapturedCommandContext(\n cwd: string,\n version = '0.2.1',\n): CapturedCommandContext {\n const stdout = { value: '' };\n const stderr = { value: '' };\n\n return {\n stdout,\n stderr,\n context: {\n cwd,\n env: process.env,\n version,\n writeStdout(text: string) {\n stdout.value += text;\n },\n writeStderr(text: string) {\n stderr.value += text;\n },\n },\n };\n}\n\nexport async function createWorkspaceFixture(\n args: {\n readonly manifest?: AppManifest;\n readonly manifestFile?: 'invalid-json' | 'missing';\n readonly projectId?: string;\n } = {},\n): Promise<{\n readonly appsRoot: string;\n readonly projectId: string;\n readonly projectPath: string;\n readonly rootPath: string;\n}> {\n const rootPath = await fs.mkdtemp(path.join(os.tmpdir(), 'ankhorage-infra-'));\n const appsRoot = path.join(rootPath, 'apps');\n const projectId = args.projectId ?? 'shop';\n const projectPath = path.join(appsRoot, projectId);\n\n await fs.mkdir(projectPath, { recursive: true });\n await fs.writeFile(\n path.join(projectPath, 'package.json'),\n JSON.stringify({ name: projectId, version: '1.0.0' }, null, 2),\n 'utf8',\n );\n\n if (args.manifestFile === 'invalid-json') {\n await fs.writeFile(path.join(projectPath, 'ankh.config.json'), '{invalid', 'utf8');\n } else if (args.manifestFile !== 'missing') {\n await fs.writeFile(\n path.join(projectPath, 'ankh.config.json'),\n `${JSON.stringify(args.manifest ?? createAppManifest(projectId), null, 2)}\\n`,\n 'utf8',\n );\n }\n\n return {\n appsRoot,\n projectId,\n projectPath,\n rootPath,\n };\n}\n\nexport function createAppManifest(\n projectId: string,\n infra: AppManifest['infra'] = { plugins: [] },\n): AppManifest {\n return {\n metadata: {\n name: projectId,\n slug: projectId,\n version: '1.0.0',\n category: 'developer_tools',\n themeId: 'default',\n },\n themes: [],\n activeThemeId: 'default',\n infra,\n navigator: {\n type: 'stack',\n routes: [{ name: 'index', screenId: 'index' }],\n },\n screens: {},\n settings: {\n localization: {\n defaultLocale: 'en',\n locales: ['en'],\n },\n },\n };\n}\n"]}
package/dist/types.d.ts CHANGED
@@ -30,7 +30,7 @@ export interface InfrastructureGenerationOptions {
30
30
  /**
31
31
  * Optional app-level context used by provider/engine-specific generators.
32
32
  */
33
- readonly appManifest?: Pick<AppManifest, 'data' | 'infra' | 'metadata' | 'navigator' | 'screens' | 'settings'>;
33
+ readonly appManifest?: Pick<AppManifest, 'generatedApis' | 'infra' | 'metadata' | 'navigator' | 'screens' | 'settings'>;
34
34
  }
35
35
  export interface InfraGenerationInput {
36
36
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAEvE,MAAM,WAAW,2BAA2B;IAC1C;;OAEG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,UAAU,CAAC,EAAE,OAAO,CAAC;CAC/B;AAED,MAAM,WAAW,0BAA0B;IACzC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,4BAA4B;IAC3C,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC,aAAa,CAAC,YAAY,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;IACpE,QAAQ,CAAC,SAAS,EAAE,SAAS,MAAM,EAAE,CAAC;CACvC;AAED,MAAM,WAAW,8BAA8B;IAC7C,QAAQ,CAAC,KAAK,EAAE,SAAS,2BAA2B,EAAE,CAAC;IACvD,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,QAAQ,CAAC,IAAI,EAAE,4BAA4B,CAAC;IAC5C,QAAQ,CAAC,YAAY,EAAE,SAAS,0BAA0B,EAAE,CAAC;CAC9D;AAED,MAAM,WAAW,+BAA+B;IAC9C;;OAEG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC;;OAEG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,IAAI,CACzB,WAAW,EACX,MAAM,GAAG,OAAO,GAAG,UAAU,GAAG,WAAW,GAAG,SAAS,GAAG,UAAU,CACrE,CAAC;CACH;AAED,MAAM,WAAW,oBAAoB;IACnC;;OAEG;IACH,QAAQ,CAAC,QAAQ,EAAE,kBAAkB,CAAC;IACtC;;;OAGG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,OAAO,CAAC,EAAE,+BAA+B,CAAC;CACpD;AAED,MAAM,MAAM,sBAAsB,GAAG,+BAA+B,CAAC;AACrE,MAAM,MAAM,qBAAqB,GAAG,8BAA8B,CAAC;AACnE,MAAM,MAAM,aAAa,GAAG,2BAA2B,CAAC;AACxD,MAAM,MAAM,iBAAiB,GAAG,0BAA0B,CAAC;AAE3D,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,QAAQ,EAAE,SAAS,CAAC;IAC7B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED,KAAK,oBAAoB,GAAG,WAAW,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,UAAU,CAAC;AAE3F,UAAU,qBAAqB;IAC7B,QAAQ,CAAC,QAAQ,EAAE,oBAAoB,CAAC;IACxC,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;CACrC;AAED;;;;;GAKG;AACH,MAAM,MAAM,kBAAkB,GAAG,IAAI,CAAC,aAAa,EAAE,SAAS,CAAC,GAAG;IAChE,QAAQ,CAAC,OAAO,CAAC,EAAE,qBAAqB,CAAC;CAC1C,CAAC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAEvE,MAAM,WAAW,2BAA2B;IAC1C;;OAEG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,UAAU,CAAC,EAAE,OAAO,CAAC;CAC/B;AAED,MAAM,WAAW,0BAA0B;IACzC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,4BAA4B;IAC3C,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC,aAAa,CAAC,YAAY,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;IACpE,QAAQ,CAAC,SAAS,EAAE,SAAS,MAAM,EAAE,CAAC;CACvC;AAED,MAAM,WAAW,8BAA8B;IAC7C,QAAQ,CAAC,KAAK,EAAE,SAAS,2BAA2B,EAAE,CAAC;IACvD,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,QAAQ,CAAC,IAAI,EAAE,4BAA4B,CAAC;IAC5C,QAAQ,CAAC,YAAY,EAAE,SAAS,0BAA0B,EAAE,CAAC;CAC9D;AAED,MAAM,WAAW,+BAA+B;IAC9C;;OAEG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC;;OAEG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,IAAI,CACzB,WAAW,EACX,eAAe,GAAG,OAAO,GAAG,UAAU,GAAG,WAAW,GAAG,SAAS,GAAG,UAAU,CAC9E,CAAC;CACH;AAED,MAAM,WAAW,oBAAoB;IACnC;;OAEG;IACH,QAAQ,CAAC,QAAQ,EAAE,kBAAkB,CAAC;IACtC;;;OAGG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,OAAO,CAAC,EAAE,+BAA+B,CAAC;CACpD;AAED,MAAM,MAAM,sBAAsB,GAAG,+BAA+B,CAAC;AACrE,MAAM,MAAM,qBAAqB,GAAG,8BAA8B,CAAC;AACnE,MAAM,MAAM,aAAa,GAAG,2BAA2B,CAAC;AACxD,MAAM,MAAM,iBAAiB,GAAG,0BAA0B,CAAC;AAE3D,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,QAAQ,EAAE,SAAS,CAAC;IAC7B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED,KAAK,oBAAoB,GAAG,WAAW,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,UAAU,CAAC;AAE3F,UAAU,qBAAqB;IAC7B,QAAQ,CAAC,QAAQ,EAAE,oBAAoB,CAAC;IACxC,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;CACrC;AAED;;;;;GAKG;AACH,MAAM,MAAM,kBAAkB,GAAG,IAAI,CAAC,aAAa,EAAE,SAAS,CAAC,GAAG;IAChE,QAAQ,CAAC,OAAO,CAAC,EAAE,qBAAqB,CAAC;CAC1C,CAAC"}
package/dist/types.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"","sourcesContent":["import type { AppManifest, InfraManifest } from '@ankhorage/contracts';\n\nexport interface GeneratedInfrastructureFile {\n /**\n * Path relative to the target app root.\n */\n readonly path: string;\n readonly content: string;\n readonly executable?: boolean;\n}\n\nexport interface GeneratedPackageDependency {\n readonly name: string;\n readonly version: string;\n readonly reason: string;\n}\n\nexport interface InfrastructureGenerationMeta {\n readonly target: NonNullable<InfraManifest['deployment']>['target'];\n readonly providers: readonly string[];\n}\n\nexport interface InfrastructureGenerationResult {\n readonly files: readonly GeneratedInfrastructureFile[];\n readonly warnings: readonly string[];\n readonly meta: InfrastructureGenerationMeta;\n readonly dependencies: readonly GeneratedPackageDependency[];\n}\n\nexport interface InfrastructureGenerationOptions {\n /**\n * Optional namespace hint from caller context, such as app slug or project id.\n */\n readonly namespaceHint?: string;\n /**\n * Optional app-level context used by provider/engine-specific generators.\n */\n readonly appManifest?: Pick<\n AppManifest,\n 'data' | 'infra' | 'metadata' | 'navigator' | 'screens' | 'settings'\n >;\n}\n\nexport interface InfraGenerationInput {\n /**\n * Infra manifest section from an app manifest.\n */\n readonly manifest: InfraManifestInput;\n /**\n * Optional root used by callers that want to keep output intent alongside generation.\n * The generator itself still returns relative file paths and does not write to disk.\n */\n readonly outputRoot?: string;\n readonly options?: InfrastructureGenerationOptions;\n}\n\nexport type InfraGenerationOptions = InfrastructureGenerationOptions;\nexport type InfraGenerationResult = InfrastructureGenerationResult;\nexport type GeneratedFile = GeneratedInfrastructureFile;\nexport type PackageDependency = GeneratedPackageDependency;\n\nexport interface InfraDiagnostic {\n readonly severity: 'warning';\n readonly message: string;\n}\n\ntype InfraStorageProvider = NonNullable<InfraManifest['storage']>['provider'] | 'supabase';\n\ninterface InfraStorageSpecInput {\n readonly provider: InfraStorageProvider;\n readonly buckets: readonly string[];\n}\n\n/**\n * Infra-local manifest input type.\n *\n * This is intentionally broader than `@ankhorage/contracts` to allow adapters to support\n * additional providers before the shared contracts package officially includes them.\n */\nexport type InfraManifestInput = Omit<InfraManifest, 'storage'> & {\n readonly storage?: InfraStorageSpecInput;\n};\n"]}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"","sourcesContent":["import type { AppManifest, InfraManifest } from '@ankhorage/contracts';\n\nexport interface GeneratedInfrastructureFile {\n /**\n * Path relative to the target app root.\n */\n readonly path: string;\n readonly content: string;\n readonly executable?: boolean;\n}\n\nexport interface GeneratedPackageDependency {\n readonly name: string;\n readonly version: string;\n readonly reason: string;\n}\n\nexport interface InfrastructureGenerationMeta {\n readonly target: NonNullable<InfraManifest['deployment']>['target'];\n readonly providers: readonly string[];\n}\n\nexport interface InfrastructureGenerationResult {\n readonly files: readonly GeneratedInfrastructureFile[];\n readonly warnings: readonly string[];\n readonly meta: InfrastructureGenerationMeta;\n readonly dependencies: readonly GeneratedPackageDependency[];\n}\n\nexport interface InfrastructureGenerationOptions {\n /**\n * Optional namespace hint from caller context, such as app slug or project id.\n */\n readonly namespaceHint?: string;\n /**\n * Optional app-level context used by provider/engine-specific generators.\n */\n readonly appManifest?: Pick<\n AppManifest,\n 'generatedApis' | 'infra' | 'metadata' | 'navigator' | 'screens' | 'settings'\n >;\n}\n\nexport interface InfraGenerationInput {\n /**\n * Infra manifest section from an app manifest.\n */\n readonly manifest: InfraManifestInput;\n /**\n * Optional root used by callers that want to keep output intent alongside generation.\n * The generator itself still returns relative file paths and does not write to disk.\n */\n readonly outputRoot?: string;\n readonly options?: InfrastructureGenerationOptions;\n}\n\nexport type InfraGenerationOptions = InfrastructureGenerationOptions;\nexport type InfraGenerationResult = InfrastructureGenerationResult;\nexport type GeneratedFile = GeneratedInfrastructureFile;\nexport type PackageDependency = GeneratedPackageDependency;\n\nexport interface InfraDiagnostic {\n readonly severity: 'warning';\n readonly message: string;\n}\n\ntype InfraStorageProvider = NonNullable<InfraManifest['storage']>['provider'] | 'supabase';\n\ninterface InfraStorageSpecInput {\n readonly provider: InfraStorageProvider;\n readonly buckets: readonly string[];\n}\n\n/**\n * Infra-local manifest input type.\n *\n * This is intentionally broader than `@ankhorage/contracts` to allow adapters to support\n * additional providers before the shared contracts package officially includes them.\n */\nexport type InfraManifestInput = Omit<InfraManifest, 'storage'> & {\n readonly storage?: InfraStorageSpecInput;\n};\n"]}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@ankhorage/infra",
3
3
  "type": "module",
4
- "version": "1.1.0",
4
+ "version": "2.0.1",
5
5
  "description": "Project-aware infrastructure generation library and executable Ankh provider for Ankhorage.",
6
6
  "homepage": "https://github.com/ankhorage/infra#readme",
7
7
  "bugs": {
@@ -35,7 +35,7 @@
35
35
  "openapi"
36
36
  ],
37
37
  "dependencies": {
38
- "@ankhorage/contracts": "^2.1.0",
38
+ "@ankhorage/contracts": "^4.0.2",
39
39
  "@ankhorage/supabase-vault": "^0.2.4"
40
40
  },
41
41
  "files": [
@@ -98,9 +98,6 @@ function getOAuthProviderLifecycle(
98
98
 
99
99
  function getOAuthRuntimeReconciliationCommand(oauthRuntime: SupabaseOAuthRuntimeModel): string {
100
100
  const localPatterns = oauthRuntime.localRedirectPatterns.join(',');
101
- const providerRedirectAssignments = oauthRuntime.envPrefixes
102
- .map((prefix) => `GOTRUE_EXTERNAL_${prefix}_REDIRECT_URI="\${oauth_provider_callback}"`)
103
- .join(' ');
104
101
  const providerExports = oauthRuntime.envPrefixes
105
102
  .map(
106
103
  (prefix) => `export GOTRUE_EXTERNAL_${prefix}_REDIRECT_URI="\${oauth_provider_callback}"
@@ -119,12 +116,7 @@ fi
119
116
  export ADDITIONAL_REDIRECT_URLS="\${oauth_redirect_allow_list}"
120
117
  write_env_value ADDITIONAL_REDIRECT_URLS "\${oauth_redirect_allow_list}"
121
118
  ${providerExports}
122
- kubectl --context "\${PROFILE}" -n supabase set env deployment/auth \\
123
- API_EXTERNAL_URL="\${API_EXTERNAL_URL}" \\
124
- GOTRUE_SITE_URL="\${SITE_URL}" \\
125
- GOTRUE_URI_ALLOW_LIST="\${oauth_redirect_allow_list}" \\
126
- GOTRUE_JWT_ISSUER="\${API_EXTERNAL_URL}" \\
127
- ${providerRedirectAssignments} >/dev/null
119
+ sync_supabase_secrets
128
120
  kubectl --context "\${PROFILE}" -n supabase rollout restart deployment/auth >/dev/null
129
121
  kubectl --context "\${PROFILE}" -n supabase rollout status deployment/auth --timeout=600s`;
130
122
  }
@@ -162,8 +154,10 @@ Local Minikube reconciliation adds only callback-scoped loopback patterns:
162
154
  ${localPatterns}
163
155
 
164
156
  Native callback URIs may be supplied through \`OAUTH_NATIVE_REDIRECT_URLS\`. The generated
165
- provider lifecycle writes only redirect metadata, never OAuth client secrets. It updates the
166
- GoTrue deployment environment, forces \`deployment/auth\` to restart, and waits up to 600
167
- seconds for the rollout. A failed rollout stops Infra Up before its success message.
157
+ provider lifecycle persists redirect metadata, re-syncs the canonical Supabase runtime
158
+ ConfigMap and Secret sources, then forces \`deployment/auth\` to restart and waits up to 600
159
+ seconds for the rollout. OAuth credential values remain sourced from trusted secret resolution
160
+ and are never embedded in generated files. A failed rollout stops Infra Up before its success
161
+ message.
168
162
  `;
169
163
  }
@@ -12,6 +12,7 @@ describe('Supabase OAuth runtime reconciliation', () => {
12
12
  const command = lifecycle?.reconciliationCommands[0]?.command ?? '';
13
13
  const statusCommand = lifecycle?.statusChecks[0]?.command ?? '';
14
14
  const guide = getFile(artifacts.files, 'infra/minikube/auth/oauth-runtime.md');
15
+ const normalizedGuide = guide.replace(/\s+/gu, ' ');
15
16
 
16
17
  expect(lifecycle?.id).toBe('supabase-auth');
17
18
  expect(lifecycle?.namespace).toBe('supabase');
@@ -28,10 +29,11 @@ describe('Supabase OAuth runtime reconciliation', () => {
28
29
  expect(command).toContain('http://localhost:*/auth/callback');
29
30
  expect(command).toContain('OAUTH_NATIVE_REDIRECT_URLS');
30
31
  expect(command).toContain('GOTRUE_EXTERNAL_GOOGLE_REDIRECT_URI="${oauth_provider_callback}"');
31
- expect(command).toContain('GOTRUE_URI_ALLOW_LIST="${oauth_redirect_allow_list}"');
32
+ expect(command).toContain('sync_supabase_secrets');
33
+ expect(command).not.toContain('set env deployment/auth');
32
34
  expect(command).toContain('rollout restart deployment/auth');
33
35
  expect(command).toContain('rollout status deployment/auth --timeout=600s');
34
- expect(command.indexOf('set env deployment/auth')).toBeLessThan(
36
+ expect(command.indexOf('sync_supabase_secrets')).toBeLessThan(
35
37
  command.indexOf('rollout restart deployment/auth'),
36
38
  );
37
39
  expect(command.indexOf('rollout restart deployment/auth')).toBeLessThan(
@@ -41,15 +43,19 @@ describe('Supabase OAuth runtime reconciliation', () => {
41
43
  expect(command).not.toContain('GOTRUE_EXTERNAL_GOOGLE_SECRET=');
42
44
  expect(statusCommand).toContain('provider supabase-auth/provider-callback');
43
45
  expect(statusCommand).toContain('provider supabase-auth/app-callback');
44
- expect(guide).toContain('Supabase OAuth Runtime Reconciliation');
45
- expect(guide).toContain('A failed rollout stops Infra Up before its success message.');
46
+ expect(normalizedGuide).toContain('Supabase OAuth Runtime Reconciliation');
47
+ expect(normalizedGuide).toContain('re-syncs the canonical Supabase runtime');
48
+ expect(normalizedGuide).toContain(
49
+ 'A failed rollout stops Infra Up before its success message.',
50
+ );
46
51
  });
47
52
 
48
- test('integrates reconciliation after generated runtime resources without duplicate namespaces', () => {
53
+ test('keeps Auth deployment environment declarative across reconciliation', () => {
49
54
  const result = generateInfrastructure(createOAuthManifest(), {
50
55
  appManifest: createAppManifest('oauth-app'),
51
56
  });
52
57
  const upScript = getFile(result.files, 'infra/minikube/scripts/up.sh');
58
+ const authManifest = getFile(result.files, 'infra/minikube/k8s/supabase/auth.yaml');
53
59
  const kustomization = getFile(result.files, 'infra/minikube/k8s/kustomization.yaml');
54
60
  const statusScript = getFile(result.files, 'infra/minikube/scripts/status.sh');
55
61
 
@@ -57,15 +63,20 @@ describe('Supabase OAuth runtime reconciliation', () => {
57
63
  expect(upScript).toContain(
58
64
  'Running provider supabase-auth OAuth redirect and runtime rollout reconciliation.',
59
65
  );
60
- expect(upScript).toContain(
66
+ expect(upScript).not.toContain(
61
67
  'kubectl --context "${PROFILE}" -n supabase set env deployment/auth',
62
68
  );
69
+ expect(upScript).toContain('sync_supabase_secrets');
63
70
  expect(upScript).toContain(
64
71
  'kubectl --context "${PROFILE}" -n supabase rollout restart deployment/auth',
65
72
  );
66
73
  expect(upScript).toContain(
67
74
  'kubectl --context "${PROFILE}" -n supabase rollout status deployment/auth --timeout=600s',
68
75
  );
76
+ expect(authManifest).toContain('name: API_EXTERNAL_URL\n valueFrom:');
77
+ expect(authManifest).toContain('name: GOTRUE_SITE_URL\n valueFrom:');
78
+ expect(authManifest).toContain('name: GOTRUE_URI_ALLOW_LIST\n valueFrom:');
79
+ expect(authManifest).toContain('name: GOTRUE_JWT_ISSUER\n valueFrom:');
69
80
  expect(upScript.lastIndexOf('run_provider_reconciliation')).toBeLessThan(
70
81
  upScript.lastIndexOf('echo "Minikube infrastructure for \'${PROFILE}\' is running."'),
71
82
  );
@@ -1,4 +1,4 @@
1
- import { generateApiInfrastructureArtifacts } from '../../apiArtifacts';
1
+ import { generateGeneratedApiDatabaseArtifacts } from '../../generatedApiDatabase';
2
2
  import type {
3
3
  GeneratedPackageDependency,
4
4
  InfraManifestInput,
@@ -41,10 +41,21 @@ export function generateMinikubeInfra(
41
41
  });
42
42
  const storageArtifacts = generateStorageArtifacts({ manifest, namespace });
43
43
  const secretStoreArtifacts = generateSecretStoreArtifacts({ manifest, namespace });
44
- const apiArtifacts = generateApiInfrastructureArtifacts({
45
- data: options.appManifest?.data,
44
+ const generatedApiDatabaseArtifacts = generateGeneratedApiDatabaseArtifacts({
45
+ generatedApis: options.appManifest?.generatedApis,
46
46
  databaseProvider: manifest.database?.provider,
47
47
  });
48
+ const generatedApiErrors = generatedApiDatabaseArtifacts.diagnostics.filter(
49
+ (diagnostic) => diagnostic.severity === 'error',
50
+ );
51
+
52
+ if (generatedApiErrors.length > 0) {
53
+ throw new Error(
54
+ `Generated API database definition is invalid:\n${generatedApiErrors
55
+ .map((diagnostic) => `- ${diagnostic.path ?? diagnostic.apiId}: ${diagnostic.message}`)
56
+ .join('\n')}`,
57
+ );
58
+ }
48
59
 
49
60
  const extraResources = unique([
50
61
  ...authArtifacts.resources,
@@ -83,7 +94,9 @@ export function generateMinikubeInfra(
83
94
  ...authzArtifacts.warnings,
84
95
  ...storageArtifacts.warnings,
85
96
  ...secretStoreArtifacts.warnings,
86
- ...apiArtifacts.warnings,
97
+ ...generatedApiDatabaseArtifacts.diagnostics
98
+ .filter((diagnostic) => diagnostic.severity === 'warning')
99
+ .map((diagnostic) => diagnostic.message),
87
100
  ]);
88
101
 
89
102
  return {
@@ -93,7 +106,7 @@ export function generateMinikubeInfra(
93
106
  ...authzArtifacts.files,
94
107
  ...storageArtifacts.files,
95
108
  ...secretStoreArtifacts.files,
96
- ...apiArtifacts.files,
109
+ ...generatedApiDatabaseArtifacts.files,
97
110
  ],
98
111
  warnings,
99
112
  meta: {