@backthread/extractor 0.1.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.
- package/LICENSE +21 -0
- package/README.md +83 -0
- package/dist/cluster/domain-grouping.d.ts +113 -0
- package/dist/cluster/domain-grouping.d.ts.map +1 -0
- package/dist/cluster/domain-grouping.js +277 -0
- package/dist/cluster/domain-grouping.js.map +1 -0
- package/dist/cluster/grouping-gate.d.ts +54 -0
- package/dist/cluster/grouping-gate.d.ts.map +1 -0
- package/dist/cluster/grouping-gate.js +0 -0
- package/dist/cluster/grouping-gate.js.map +1 -0
- package/dist/cluster/louvain.d.ts +88 -0
- package/dist/cluster/louvain.d.ts.map +1 -0
- package/dist/cluster/louvain.js +674 -0
- package/dist/cluster/louvain.js.map +1 -0
- package/dist/cluster/overrides.d.ts +19 -0
- package/dist/cluster/overrides.d.ts.map +1 -0
- package/dist/cluster/overrides.js +32 -0
- package/dist/cluster/overrides.js.map +1 -0
- package/dist/cluster/subsystem.d.ts +45 -0
- package/dist/cluster/subsystem.d.ts.map +1 -0
- package/dist/cluster/subsystem.js +299 -0
- package/dist/cluster/subsystem.js.map +1 -0
- package/dist/cluster/workspaces.d.ts +64 -0
- package/dist/cluster/workspaces.d.ts.map +1 -0
- package/dist/cluster/workspaces.js +739 -0
- package/dist/cluster/workspaces.js.map +1 -0
- package/dist/extract.d.ts +52 -0
- package/dist/extract.d.ts.map +1 -0
- package/dist/extract.js +48 -0
- package/dist/extract.js.map +1 -0
- package/dist/framework/celery/celery.d.ts +17 -0
- package/dist/framework/celery/celery.d.ts.map +1 -0
- package/dist/framework/celery/celery.js +524 -0
- package/dist/framework/celery/celery.js.map +1 -0
- package/dist/framework/contribute-step.d.ts +38 -0
- package/dist/framework/contribute-step.d.ts.map +1 -0
- package/dist/framework/contribute-step.js +403 -0
- package/dist/framework/contribute-step.js.map +1 -0
- package/dist/framework/detect-step.d.ts +8 -0
- package/dist/framework/detect-step.d.ts.map +1 -0
- package/dist/framework/detect-step.js +54 -0
- package/dist/framework/detect-step.js.map +1 -0
- package/dist/framework/detect-util.d.ts +24 -0
- package/dist/framework/detect-util.d.ts.map +1 -0
- package/dist/framework/detect-util.js +59 -0
- package/dist/framework/detect-util.js.map +1 -0
- package/dist/framework/django/django.d.ts +22 -0
- package/dist/framework/django/django.d.ts.map +1 -0
- package/dist/framework/django/django.js +940 -0
- package/dist/framework/django/django.js.map +1 -0
- package/dist/framework/fastapi/fastapi.d.ts +27 -0
- package/dist/framework/fastapi/fastapi.d.ts.map +1 -0
- package/dist/framework/fastapi/fastapi.js +477 -0
- package/dist/framework/fastapi/fastapi.js.map +1 -0
- package/dist/framework/faststream/faststream.d.ts +19 -0
- package/dist/framework/faststream/faststream.d.ts.map +1 -0
- package/dist/framework/faststream/faststream.js +765 -0
- package/dist/framework/faststream/faststream.js.map +1 -0
- package/dist/framework/flask/flask.d.ts +17 -0
- package/dist/framework/flask/flask.d.ts.map +1 -0
- package/dist/framework/flask/flask.js +507 -0
- package/dist/framework/flask/flask.js.map +1 -0
- package/dist/framework/graphql/graphql.d.ts +17 -0
- package/dist/framework/graphql/graphql.d.ts.map +1 -0
- package/dist/framework/graphql/graphql.js +708 -0
- package/dist/framework/graphql/graphql.js.map +1 -0
- package/dist/framework/grpc/grpc.d.ts +22 -0
- package/dist/framework/grpc/grpc.d.ts.map +1 -0
- package/dist/framework/grpc/grpc.js +618 -0
- package/dist/framework/grpc/grpc.js.map +1 -0
- package/dist/framework/litestar/litestar.d.ts +17 -0
- package/dist/framework/litestar/litestar.d.ts.map +1 -0
- package/dist/framework/litestar/litestar.js +536 -0
- package/dist/framework/litestar/litestar.js.map +1 -0
- package/dist/framework/nest/nest.d.ts +19 -0
- package/dist/framework/nest/nest.d.ts.map +1 -0
- package/dist/framework/nest/nest.js +613 -0
- package/dist/framework/nest/nest.js.map +1 -0
- package/dist/framework/next/next.d.ts +22 -0
- package/dist/framework/next/next.d.ts.map +1 -0
- package/dist/framework/next/next.js +449 -0
- package/dist/framework/next/next.js.map +1 -0
- package/dist/framework/node/node.d.ts +24 -0
- package/dist/framework/node/node.d.ts.map +1 -0
- package/dist/framework/node/node.js +1009 -0
- package/dist/framework/node/node.js.map +1 -0
- package/dist/framework/orchestrator/orchestrator.d.ts +34 -0
- package/dist/framework/orchestrator/orchestrator.d.ts.map +1 -0
- package/dist/framework/orchestrator/orchestrator.js +691 -0
- package/dist/framework/orchestrator/orchestrator.js.map +1 -0
- package/dist/framework/orm/orm.d.ts +61 -0
- package/dist/framework/orm/orm.d.ts.map +1 -0
- package/dist/framework/orm/orm.js +620 -0
- package/dist/framework/orm/orm.js.map +1 -0
- package/dist/framework/python/analyze.d.ts +38 -0
- package/dist/framework/python/analyze.d.ts.map +1 -0
- package/dist/framework/python/analyze.js +98 -0
- package/dist/framework/python/analyze.js.map +1 -0
- package/dist/framework/python/py-ast.d.ts +130 -0
- package/dist/framework/python/py-ast.d.ts.map +1 -0
- package/dist/framework/python/py-ast.js +344 -0
- package/dist/framework/python/py-ast.js.map +1 -0
- package/dist/framework/python-orm/python-orm.d.ts +19 -0
- package/dist/framework/python-orm/python-orm.d.ts.map +1 -0
- package/dist/framework/python-orm/python-orm.js +516 -0
- package/dist/framework/python-orm/python-orm.js.map +1 -0
- package/dist/framework/react-native/react-native.d.ts +35 -0
- package/dist/framework/react-native/react-native.d.ts.map +1 -0
- package/dist/framework/react-native/react-native.js +1181 -0
- package/dist/framework/react-native/react-native.js.map +1 -0
- package/dist/framework/register.d.ts +2 -0
- package/dist/framework/register.d.ts.map +1 -0
- package/dist/framework/register.js +59 -0
- package/dist/framework/register.js.map +1 -0
- package/dist/framework/registry.d.ts +31 -0
- package/dist/framework/registry.d.ts.map +1 -0
- package/dist/framework/registry.js +70 -0
- package/dist/framework/registry.js.map +1 -0
- package/dist/framework/routing/expo-router.d.ts +31 -0
- package/dist/framework/routing/expo-router.d.ts.map +1 -0
- package/dist/framework/routing/expo-router.js +356 -0
- package/dist/framework/routing/expo-router.js.map +1 -0
- package/dist/framework/routing/index.d.ts +4 -0
- package/dist/framework/routing/index.d.ts.map +1 -0
- package/dist/framework/routing/index.js +16 -0
- package/dist/framework/routing/index.js.map +1 -0
- package/dist/framework/routing/next-router.d.ts +45 -0
- package/dist/framework/routing/next-router.d.ts.map +1 -0
- package/dist/framework/routing/next-router.js +378 -0
- package/dist/framework/routing/next-router.js.map +1 -0
- package/dist/framework/routing/route-tree.d.ts +73 -0
- package/dist/framework/routing/route-tree.d.ts.map +1 -0
- package/dist/framework/routing/route-tree.js +120 -0
- package/dist/framework/routing/route-tree.js.map +1 -0
- package/dist/framework/types.d.ts +230 -0
- package/dist/framework/types.d.ts.map +1 -0
- package/dist/framework/types.js +25 -0
- package/dist/framework/types.js.map +1 -0
- package/dist/graph/cross-language.d.ts +11 -0
- package/dist/graph/cross-language.d.ts.map +1 -0
- package/dist/graph/cross-language.js +123 -0
- package/dist/graph/cross-language.js.map +1 -0
- package/dist/graph/extract.d.ts +13 -0
- package/dist/graph/extract.d.ts.map +1 -0
- package/dist/graph/extract.js +79 -0
- package/dist/graph/extract.js.map +1 -0
- package/dist/graph/file-graph.d.ts +186 -0
- package/dist/graph/file-graph.d.ts.map +1 -0
- package/dist/graph/file-graph.js +427 -0
- package/dist/graph/file-graph.js.map +1 -0
- package/dist/graph/http-callsites.d.ts +14 -0
- package/dist/graph/http-callsites.d.ts.map +1 -0
- package/dist/graph/http-callsites.js +107 -0
- package/dist/graph/http-callsites.js.map +1 -0
- package/dist/graph/incremental.d.ts +122 -0
- package/dist/graph/incremental.d.ts.map +1 -0
- package/dist/graph/incremental.js +448 -0
- package/dist/graph/incremental.js.map +1 -0
- package/dist/graph/language.d.ts +31 -0
- package/dist/graph/language.d.ts.map +1 -0
- package/dist/graph/language.js +146 -0
- package/dist/graph/language.js.map +1 -0
- package/dist/graph/noise-filter.d.ts +46 -0
- package/dist/graph/noise-filter.d.ts.map +1 -0
- package/dist/graph/noise-filter.js +199 -0
- package/dist/graph/noise-filter.js.map +1 -0
- package/dist/graph/python-adapter.d.ts +36 -0
- package/dist/graph/python-adapter.d.ts.map +1 -0
- package/dist/graph/python-adapter.js +402 -0
- package/dist/graph/python-adapter.js.map +1 -0
- package/dist/graph/python-manifest.d.ts +22 -0
- package/dist/graph/python-manifest.d.ts.map +1 -0
- package/dist/graph/python-manifest.js +137 -0
- package/dist/graph/python-manifest.js.map +1 -0
- package/dist/graph/python-stdlib.d.ts +2 -0
- package/dist/graph/python-stdlib.d.ts.map +1 -0
- package/dist/graph/python-stdlib.js +53 -0
- package/dist/graph/python-stdlib.js.map +1 -0
- package/dist/graph/ts-morph-adapter.d.ts +65 -0
- package/dist/graph/ts-morph-adapter.d.ts.map +1 -0
- package/dist/graph/ts-morph-adapter.js +265 -0
- package/dist/graph/ts-morph-adapter.js.map +1 -0
- package/dist/graph/types.d.ts +37 -0
- package/dist/graph/types.d.ts.map +1 -0
- package/dist/graph/types.js +50 -0
- package/dist/graph/types.js.map +1 -0
- package/dist/index.d.ts +45 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +51 -0
- package/dist/index.js.map +1 -0
- package/dist/infra/aws/aws-parse.d.ts +39 -0
- package/dist/infra/aws/aws-parse.d.ts.map +1 -0
- package/dist/infra/aws/aws-parse.js +149 -0
- package/dist/infra/aws/aws-parse.js.map +1 -0
- package/dist/infra/aws/aws.d.ts +6 -0
- package/dist/infra/aws/aws.d.ts.map +1 -0
- package/dist/infra/aws/aws.js +425 -0
- package/dist/infra/aws/aws.js.map +1 -0
- package/dist/infra/azure/azure-parse.d.ts +73 -0
- package/dist/infra/azure/azure-parse.d.ts.map +1 -0
- package/dist/infra/azure/azure-parse.js +178 -0
- package/dist/infra/azure/azure-parse.js.map +1 -0
- package/dist/infra/azure/azure.d.ts +12 -0
- package/dist/infra/azure/azure.d.ts.map +1 -0
- package/dist/infra/azure/azure.js +673 -0
- package/dist/infra/azure/azure.js.map +1 -0
- package/dist/infra/cloudflare/cloudflare.d.ts +50 -0
- package/dist/infra/cloudflare/cloudflare.d.ts.map +1 -0
- package/dist/infra/cloudflare/cloudflare.js +382 -0
- package/dist/infra/cloudflare/cloudflare.js.map +1 -0
- package/dist/infra/cloudflare/wrangler-parse.d.ts +6 -0
- package/dist/infra/cloudflare/wrangler-parse.d.ts.map +1 -0
- package/dist/infra/cloudflare/wrangler-parse.js +278 -0
- package/dist/infra/cloudflare/wrangler-parse.js.map +1 -0
- package/dist/infra/compose/compose-parse.d.ts +24 -0
- package/dist/infra/compose/compose-parse.d.ts.map +1 -0
- package/dist/infra/compose/compose-parse.js +77 -0
- package/dist/infra/compose/compose-parse.js.map +1 -0
- package/dist/infra/compose/compose.d.ts +12 -0
- package/dist/infra/compose/compose.d.ts.map +1 -0
- package/dist/infra/compose/compose.js +201 -0
- package/dist/infra/compose/compose.js.map +1 -0
- package/dist/infra/convex/convex-parse.d.ts +28 -0
- package/dist/infra/convex/convex-parse.d.ts.map +1 -0
- package/dist/infra/convex/convex-parse.js +74 -0
- package/dist/infra/convex/convex-parse.js.map +1 -0
- package/dist/infra/convex/convex.d.ts +18 -0
- package/dist/infra/convex/convex.d.ts.map +1 -0
- package/dist/infra/convex/convex.js +199 -0
- package/dist/infra/convex/convex.js.map +1 -0
- package/dist/infra/digitalocean/digitalocean.d.ts +33 -0
- package/dist/infra/digitalocean/digitalocean.d.ts.map +1 -0
- package/dist/infra/digitalocean/digitalocean.js +204 -0
- package/dist/infra/digitalocean/digitalocean.js.map +1 -0
- package/dist/infra/firebase/firebase.d.ts +43 -0
- package/dist/infra/firebase/firebase.d.ts.map +1 -0
- package/dist/infra/firebase/firebase.js +271 -0
- package/dist/infra/firebase/firebase.js.map +1 -0
- package/dist/infra/fly/fly-parse.d.ts +52 -0
- package/dist/infra/fly/fly-parse.d.ts.map +1 -0
- package/dist/infra/fly/fly-parse.js +114 -0
- package/dist/infra/fly/fly-parse.js.map +1 -0
- package/dist/infra/fly/fly.d.ts +15 -0
- package/dist/infra/fly/fly.d.ts.map +1 -0
- package/dist/infra/fly/fly.js +265 -0
- package/dist/infra/fly/fly.js.map +1 -0
- package/dist/infra/gcp/gcp-parse.d.ts +24 -0
- package/dist/infra/gcp/gcp-parse.d.ts.map +1 -0
- package/dist/infra/gcp/gcp-parse.js +123 -0
- package/dist/infra/gcp/gcp-parse.js.map +1 -0
- package/dist/infra/gcp/gcp.d.ts +10 -0
- package/dist/infra/gcp/gcp.d.ts.map +1 -0
- package/dist/infra/gcp/gcp.js +502 -0
- package/dist/infra/gcp/gcp.js.map +1 -0
- package/dist/infra/heroku/heroku-parse.d.ts +33 -0
- package/dist/infra/heroku/heroku-parse.d.ts.map +1 -0
- package/dist/infra/heroku/heroku-parse.js +63 -0
- package/dist/infra/heroku/heroku-parse.js.map +1 -0
- package/dist/infra/heroku/heroku.d.ts +24 -0
- package/dist/infra/heroku/heroku.d.ts.map +1 -0
- package/dist/infra/heroku/heroku.js +253 -0
- package/dist/infra/heroku/heroku.js.map +1 -0
- package/dist/infra/image-resolve.d.ts +56 -0
- package/dist/infra/image-resolve.d.ts.map +1 -0
- package/dist/infra/image-resolve.js +229 -0
- package/dist/infra/image-resolve.js.map +1 -0
- package/dist/infra/infra-step.d.ts +39 -0
- package/dist/infra/infra-step.d.ts.map +1 -0
- package/dist/infra/infra-step.js +57 -0
- package/dist/infra/infra-step.js.map +1 -0
- package/dist/infra/k8s/index.d.ts +78 -0
- package/dist/infra/k8s/index.d.ts.map +1 -0
- package/dist/infra/k8s/index.js +251 -0
- package/dist/infra/k8s/index.js.map +1 -0
- package/dist/infra/kamal/kamal-parse.d.ts +23 -0
- package/dist/infra/kamal/kamal-parse.d.ts.map +1 -0
- package/dist/infra/kamal/kamal-parse.js +66 -0
- package/dist/infra/kamal/kamal-parse.js.map +1 -0
- package/dist/infra/kamal/kamal.d.ts +17 -0
- package/dist/infra/kamal/kamal.d.ts.map +1 -0
- package/dist/infra/kamal/kamal.js +162 -0
- package/dist/infra/kamal/kamal.js.map +1 -0
- package/dist/infra/netlify/netlify.d.ts +33 -0
- package/dist/infra/netlify/netlify.d.ts.map +1 -0
- package/dist/infra/netlify/netlify.js +247 -0
- package/dist/infra/netlify/netlify.js.map +1 -0
- package/dist/infra/opentofu/opentofu.d.ts +3 -0
- package/dist/infra/opentofu/opentofu.d.ts.map +1 -0
- package/dist/infra/opentofu/opentofu.js +157 -0
- package/dist/infra/opentofu/opentofu.js.map +1 -0
- package/dist/infra/pulumi/pulumi-parse.d.ts +60 -0
- package/dist/infra/pulumi/pulumi-parse.d.ts.map +1 -0
- package/dist/infra/pulumi/pulumi-parse.js +155 -0
- package/dist/infra/pulumi/pulumi-parse.js.map +1 -0
- package/dist/infra/pulumi/pulumi.d.ts +23 -0
- package/dist/infra/pulumi/pulumi.d.ts.map +1 -0
- package/dist/infra/pulumi/pulumi.js +260 -0
- package/dist/infra/pulumi/pulumi.js.map +1 -0
- package/dist/infra/railway/railway-parse.d.ts +54 -0
- package/dist/infra/railway/railway-parse.d.ts.map +1 -0
- package/dist/infra/railway/railway-parse.js +200 -0
- package/dist/infra/railway/railway-parse.js.map +1 -0
- package/dist/infra/railway/railway.d.ts +19 -0
- package/dist/infra/railway/railway.d.ts.map +1 -0
- package/dist/infra/railway/railway.js +397 -0
- package/dist/infra/railway/railway.js.map +1 -0
- package/dist/infra/register.d.ts +2 -0
- package/dist/infra/register.d.ts.map +1 -0
- package/dist/infra/register.js +81 -0
- package/dist/infra/register.js.map +1 -0
- package/dist/infra/registry.d.ts +64 -0
- package/dist/infra/registry.d.ts.map +1 -0
- package/dist/infra/registry.js +205 -0
- package/dist/infra/registry.js.map +1 -0
- package/dist/infra/relevance.d.ts +16 -0
- package/dist/infra/relevance.d.ts.map +1 -0
- package/dist/infra/relevance.js +132 -0
- package/dist/infra/relevance.js.map +1 -0
- package/dist/infra/render/render-parse.d.ts +76 -0
- package/dist/infra/render/render-parse.d.ts.map +1 -0
- package/dist/infra/render/render-parse.js +155 -0
- package/dist/infra/render/render-parse.js.map +1 -0
- package/dist/infra/render/render.d.ts +11 -0
- package/dist/infra/render/render.d.ts.map +1 -0
- package/dist/infra/render/render.js +303 -0
- package/dist/infra/render/render.js.map +1 -0
- package/dist/infra/sst/sst-parse.d.ts +25 -0
- package/dist/infra/sst/sst-parse.d.ts.map +1 -0
- package/dist/infra/sst/sst-parse.js +45 -0
- package/dist/infra/sst/sst-parse.js.map +1 -0
- package/dist/infra/sst/sst.d.ts +19 -0
- package/dist/infra/sst/sst.d.ts.map +1 -0
- package/dist/infra/sst/sst.js +236 -0
- package/dist/infra/sst/sst.js.map +1 -0
- package/dist/infra/supabase/supabase-parse.d.ts +34 -0
- package/dist/infra/supabase/supabase-parse.d.ts.map +1 -0
- package/dist/infra/supabase/supabase-parse.js +113 -0
- package/dist/infra/supabase/supabase-parse.js.map +1 -0
- package/dist/infra/supabase/supabase.d.ts +15 -0
- package/dist/infra/supabase/supabase.d.ts.map +1 -0
- package/dist/infra/supabase/supabase.js +198 -0
- package/dist/infra/supabase/supabase.js.map +1 -0
- package/dist/infra/terraform/hcl-parse.d.ts +34 -0
- package/dist/infra/terraform/hcl-parse.d.ts.map +1 -0
- package/dist/infra/terraform/hcl-parse.js +203 -0
- package/dist/infra/terraform/hcl-parse.js.map +1 -0
- package/dist/infra/terraform/terraform.d.ts +14 -0
- package/dist/infra/terraform/terraform.d.ts.map +1 -0
- package/dist/infra/terraform/terraform.js +264 -0
- package/dist/infra/terraform/terraform.js.map +1 -0
- package/dist/infra/types.d.ts +151 -0
- package/dist/infra/types.d.ts.map +1 -0
- package/dist/infra/types.js +14 -0
- package/dist/infra/types.js.map +1 -0
- package/dist/infra/vercel/vercel-parse.d.ts +70 -0
- package/dist/infra/vercel/vercel-parse.d.ts.map +1 -0
- package/dist/infra/vercel/vercel-parse.js +194 -0
- package/dist/infra/vercel/vercel-parse.js.map +1 -0
- package/dist/infra/vercel/vercel.d.ts +30 -0
- package/dist/infra/vercel/vercel.d.ts.map +1 -0
- package/dist/infra/vercel/vercel.js +523 -0
- package/dist/infra/vercel/vercel.js.map +1 -0
- package/dist/infra/walk.d.ts +36 -0
- package/dist/infra/walk.d.ts.map +1 -0
- package/dist/infra/walk.js +85 -0
- package/dist/infra/walk.js.map +1 -0
- package/dist/safety.d.ts +13 -0
- package/dist/safety.d.ts.map +1 -0
- package/dist/safety.js +67 -0
- package/dist/safety.js.map +1 -0
- package/dist/types.d.ts +47 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +111 -0
- package/dist/types.js.map +1 -0
- package/dist/version.d.ts +2 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +35 -0
- package/dist/version.js.map +1 -0
- package/package.json +65 -0
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
// The infra extraction step: the assemble-join seam.
|
|
2
|
+
//
|
|
3
|
+
// Sequence (mirrors the externals step):
|
|
4
|
+
//
|
|
5
|
+
// registerBuiltinInfraAdapters() — CF / Supabase / Terraform / …
|
|
6
|
+
// → runInfraAdapters(repoDir) — detect + extract + merge
|
|
7
|
+
// → classifyResourceTypes(refs)? — OPTIONAL, injected: label open-ended IaC
|
|
8
|
+
// → patch each node's kind in place — declared → llm-classified
|
|
9
|
+
//
|
|
10
|
+
// The deterministic adapters (CF, Supabase) emit no `classificationsNeeded`, so
|
|
11
|
+
// the injected classifier only fires when an IaC repo carried an unrecognised
|
|
12
|
+
// `resource "x" "y"` block. When no classifier is injected (the default, e.g.
|
|
13
|
+
// local / offline extraction) the classification-pending nodes keep their
|
|
14
|
+
// adapter-emitted placeholder kind. The result feeds the host's assemble step as
|
|
15
|
+
// a MergedInfraGraph alongside the code graph + externals.
|
|
16
|
+
//
|
|
17
|
+
// Dependency inversion: the LLM classifier lives in the host application (it
|
|
18
|
+
// needs network + a model). This package stays pure — the host injects a
|
|
19
|
+
// `classifyResourceTypes` callback (which owns its own token accounting).
|
|
20
|
+
import { runInfraAdapters } from './registry.js';
|
|
21
|
+
import { registerBuiltinInfraAdapters } from './register.js';
|
|
22
|
+
export async function extractInfra(args) {
|
|
23
|
+
registerBuiltinInfraAdapters();
|
|
24
|
+
const graph = await runInfraAdapters(args.repoDir);
|
|
25
|
+
let classified = 0;
|
|
26
|
+
if (args.classifyResourceTypes && graph.classificationsNeeded.length > 0) {
|
|
27
|
+
// Dedupe to unique (provider, resourceType) pairs — a single label can fan
|
|
28
|
+
// out to many forNodeIds.
|
|
29
|
+
const key = (p, rt) => `${p}\x1f${rt}`;
|
|
30
|
+
const uniqueRefs = new Map();
|
|
31
|
+
for (const c of graph.classificationsNeeded) {
|
|
32
|
+
uniqueRefs.set(key(c.provider, c.resourceType), {
|
|
33
|
+
provider: c.provider,
|
|
34
|
+
resourceType: c.resourceType,
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
const refs = [...uniqueRefs.values()];
|
|
38
|
+
const results = await args.classifyResourceTypes(refs);
|
|
39
|
+
const byKey = new Map();
|
|
40
|
+
results.forEach((r) => byKey.set(key(r.provider, r.resourceType), r));
|
|
41
|
+
const nodeById = new Map(graph.nodes.map((n) => [n.id, n]));
|
|
42
|
+
for (const c of graph.classificationsNeeded) {
|
|
43
|
+
const r = byKey.get(key(c.provider, c.resourceType));
|
|
44
|
+
const node = nodeById.get(c.forNodeId);
|
|
45
|
+
if (!r || !node)
|
|
46
|
+
continue;
|
|
47
|
+
node.kind = r.nodeKind;
|
|
48
|
+
node.provenance = 'llm-classified';
|
|
49
|
+
classified++;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return {
|
|
53
|
+
graph,
|
|
54
|
+
counts: { nodes: graph.nodes.length, edges: graph.edges.length, classified },
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=infra-step.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"infra-step.js","sourceRoot":"","sources":["../../src/infra/infra-step.ts"],"names":[],"mappings":"AAAA,qDAAqD;AACrD,EAAE;AACF,yCAAyC;AACzC,EAAE;AACF,6EAA6E;AAC7E,wEAAwE;AACxE,wFAAwF;AACxF,yEAAyE;AACzE,EAAE;AACF,gFAAgF;AAChF,8EAA8E;AAC9E,8EAA8E;AAC9E,0EAA0E;AAC1E,iFAAiF;AACjF,2DAA2D;AAC3D,EAAE;AACF,6EAA6E;AAC7E,yEAAyE;AACzE,0EAA0E;AAE1E,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EAAE,4BAA4B,EAAE,MAAM,eAAe,CAAC;AAgC7D,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,IASlC;IACC,4BAA4B,EAAE,CAAC;IAC/B,MAAM,KAAK,GAAG,MAAM,gBAAgB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAEnD,IAAI,UAAU,GAAG,CAAC,CAAC;IACnB,IAAI,IAAI,CAAC,qBAAqB,IAAI,KAAK,CAAC,qBAAqB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACzE,2EAA2E;QAC3E,0BAA0B;QAC1B,MAAM,GAAG,GAAG,CAAC,CAAS,EAAE,EAAU,EAAE,EAAE,CAAC,GAAG,CAAC,OAAO,EAAE,EAAE,CAAC;QACvD,MAAM,UAAU,GAAG,IAAI,GAAG,EAA2B,CAAC;QACtD,KAAK,MAAM,CAAC,IAAI,KAAK,CAAC,qBAAqB,EAAE,CAAC;YAC5C,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,YAAY,CAAC,EAAE;gBAC9C,QAAQ,EAAE,CAAC,CAAC,QAAQ;gBACpB,YAAY,EAAE,CAAC,CAAC,YAAY;aAC7B,CAAC,CAAC;QACL,CAAC;QACD,MAAM,IAAI,GAAG,CAAC,GAAG,UAAU,CAAC,MAAM,EAAE,CAAC,CAAC;QACtC,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,CAAC;QACvD,MAAM,KAAK,GAAG,IAAI,GAAG,EAA8B,CAAC;QACpD,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QAEtE,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QAC5D,KAAK,MAAM,CAAC,IAAI,KAAK,CAAC,qBAAqB,EAAE,CAAC;YAC5C,MAAM,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC;YACrD,MAAM,IAAI,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;YACvC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI;gBAAE,SAAS;YAC1B,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC,QAAQ,CAAC;YACvB,IAAI,CAAC,UAAU,GAAG,gBAAgB,CAAC;YACnC,UAAU,EAAE,CAAC;QACf,CAAC;IACH,CAAC;IAED,OAAO;QACL,KAAK;QACL,MAAM,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,EAAE,UAAU,EAAE;KAC7E,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { type DockerfileIndex } from '../image-resolve.js';
|
|
2
|
+
/**
|
|
3
|
+
* Workload kinds — every adapter models these as `container` InfraModuleKind
|
|
4
|
+
* nodes. Note GCP's v0 scope omits DaemonSet while Azure includes it; each
|
|
5
|
+
* adapter decides its own workload set, so this is the documented SUPERSET and
|
|
6
|
+
* adapters intersect it with what they support rather than relying on it.
|
|
7
|
+
*/
|
|
8
|
+
export declare const K8S_WORKLOAD_KINDS: readonly ["Deployment", "StatefulSet", "DaemonSet", "Job", "CronJob"];
|
|
9
|
+
/**
|
|
10
|
+
* Routing kinds — NEVER a node-with-a-module-kind. A Service/Ingress is modelled
|
|
11
|
+
* as edges (and, for an external entrypoint, a `cdn` node). Centralised here so
|
|
12
|
+
* the "no bogus module kind for routing" rule has one home.
|
|
13
|
+
*/
|
|
14
|
+
export declare const K8S_ROUTING_KINDS: readonly ["Service", "Ingress"];
|
|
15
|
+
export type K8sWorkloadKind = (typeof K8S_WORKLOAD_KINDS)[number];
|
|
16
|
+
export type K8sRoutingKind = (typeof K8S_ROUTING_KINDS)[number];
|
|
17
|
+
export type K8sKind = K8sWorkloadKind | K8sRoutingKind | string;
|
|
18
|
+
/**
|
|
19
|
+
* Recognise a standard Kubernetes `apiVersion`. Mirrors the prefix set the GCP
|
|
20
|
+
* adapter has always used: core `v1`, plus the `apps/`, `batch/`,
|
|
21
|
+
* `networking.k8s.io/`, and `extensions/` groups.
|
|
22
|
+
*/
|
|
23
|
+
export declare function isK8sApiVersion(apiVersion: string | undefined): boolean;
|
|
24
|
+
export interface K8sManifest {
|
|
25
|
+
kind: K8sKind;
|
|
26
|
+
apiVersion?: string;
|
|
27
|
+
name: string;
|
|
28
|
+
namespace?: string;
|
|
29
|
+
/** For Service: spec.selector labels (for matching Deployments). */
|
|
30
|
+
selector?: Record<string, string>;
|
|
31
|
+
/** For Ingress: list of backend service names extracted from rules. */
|
|
32
|
+
ingressBackends?: string[];
|
|
33
|
+
rawObj: Record<string, unknown>;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Detect a Kubernetes manifest: must have 'apiVersion' and 'kind' and
|
|
37
|
+
* 'metadata' at the top level. Guards against firing on arbitrary YAML.
|
|
38
|
+
*/
|
|
39
|
+
export declare function isK8sManifest(doc: unknown): doc is Record<string, unknown>;
|
|
40
|
+
/**
|
|
41
|
+
* Extract selector labels from a manifest `spec`. Handles both shapes:
|
|
42
|
+
* * `spec.selector.matchLabels` (Deployment / StatefulSet style)
|
|
43
|
+
* * `spec.selector` as a plain label map (Service style)
|
|
44
|
+
* Returns the raw label map (cast, NOT filtered — preserving Azure's original
|
|
45
|
+
* behavior verbatim), or `undefined` when there is no selector. (Azure keeps
|
|
46
|
+
* the `undefined` to gate selector-less Services out of routing; GCP wraps this
|
|
47
|
+
* with its own string-filter + `?? {}` for its overlap matcher — see
|
|
48
|
+
* gcp.ts selectorLabels.) Deliberately NOT string-filtered here so the shared
|
|
49
|
+
* primitive is a no-behavior-change drop-in for the old per-adapter code.
|
|
50
|
+
*/
|
|
51
|
+
export declare function extractSelector(spec: unknown): Record<string, string> | undefined;
|
|
52
|
+
/**
|
|
53
|
+
* Extract the backend Service names an Ingress routes to, across both backend
|
|
54
|
+
* encodings: k8s 1.19+ (`backend.service.name`) and legacy
|
|
55
|
+
* extensions/v1beta1 (`backend.serviceName`). Deduplicated, source order.
|
|
56
|
+
*/
|
|
57
|
+
export declare function extractIngressBackends(spec: unknown): string[];
|
|
58
|
+
/** True when two selector label maps share at least one identical key/value pair. */
|
|
59
|
+
export declare function labelsOverlap(a: Record<string, string>, b: Record<string, string>): boolean;
|
|
60
|
+
/**
|
|
61
|
+
* Every container image ref a workload manifest declares (containers +
|
|
62
|
+
* initContainers, across the workload nesting variants). Deduped, source order.
|
|
63
|
+
*/
|
|
64
|
+
export declare function extractWorkloadImages(raw: Record<string, unknown>): string[];
|
|
65
|
+
/**
|
|
66
|
+
* The repo-relative source roots a k8s workload deploys: each container image
|
|
67
|
+
* resolved via the image→source resolver, unioned. Returns [] when no
|
|
68
|
+
* image resolves to an in-repo Dockerfile (honest "Other"). Deterministic.
|
|
69
|
+
*/
|
|
70
|
+
export declare function workloadSourceRoots(raw: Record<string, unknown>, index: DockerfileIndex): string[];
|
|
71
|
+
/**
|
|
72
|
+
* Parse a YAML file potentially containing multiple Kubernetes manifest
|
|
73
|
+
* documents into normalized {@link K8sManifest} descriptors. Returns `[]` on any
|
|
74
|
+
* parse error; non-k8s documents within a multi-doc file are silently skipped.
|
|
75
|
+
* Selector labels are populated for Services and backend names for Ingresses.
|
|
76
|
+
*/
|
|
77
|
+
export declare function parseK8sManifests(text: string): K8sManifest[];
|
|
78
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/infra/k8s/index.ts"],"names":[],"mappings":"AAuBA,OAAO,EAA6B,KAAK,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAKtF;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB,uEAAwE,CAAC;AAExG;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,iCAAkC,CAAC;AAEjE,MAAM,MAAM,eAAe,GAAG,CAAC,OAAO,kBAAkB,CAAC,CAAC,MAAM,CAAC,CAAC;AAClE,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,iBAAiB,CAAC,CAAC,MAAM,CAAC,CAAC;AAChE,MAAM,MAAM,OAAO,GAAG,eAAe,GAAG,cAAc,GAAG,MAAM,CAAC;AAEhE;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CASvE;AAKD,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,OAAO,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,oEAAoE;IACpE,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAClC,uEAAuE;IACvE,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACjC;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,OAAO,GAAG,GAAG,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAS1E;AAKD;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,CASjF;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,EAAE,CA6B9D;AAED,qFAAqF;AACrF,wBAAgB,aAAa,CAAC,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAK3F;AAoCD;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,EAAE,CAa5E;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,KAAK,EAAE,eAAe,GAAG,MAAM,EAAE,CAMlG;AAKD;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,EAAE,CA+B7D"}
|
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
// shared Kubernetes manifest parsing for the cloud adapters.
|
|
2
|
+
//
|
|
3
|
+
// GCP (GKE), Azure (AKS) — and any future EKS-style adapter — all read the same
|
|
4
|
+
// Kubernetes manifest YAML: Deployment / StatefulSet / Job / CronJob workloads,
|
|
5
|
+
// plus Service / Ingress routing objects. Before this module each adapter shipped
|
|
6
|
+
// its own copy of the manifest-parsing primitives (multi-doc YAML parse, the
|
|
7
|
+
// apiVersion/kind recognisers, selector-label extraction with matchLabels
|
|
8
|
+
// fallback, and ingress-backend resolution across the 1.19+/legacy backend
|
|
9
|
+
// shapes). This is that one copy.
|
|
10
|
+
//
|
|
11
|
+
// SCOPE — parsing primitives ONLY. The two adapters deliberately model the
|
|
12
|
+
// *graph* differently and their tests lock those differences in:
|
|
13
|
+
// * GCP keys workloads `k8s:workload:<name>` and emits Service/Ingress as
|
|
14
|
+
// `cdn` nodes (earn-a-box routing layer), matching via label OVERLAP.
|
|
15
|
+
// * Azure keys workloads `k8s:deployment:<name>`, never emits a routing node,
|
|
16
|
+
// matches via a name heuristic, and treats DaemonSet as a workload.
|
|
17
|
+
// Those divergences are graph-assembly policy, not parsing, so they stay in the
|
|
18
|
+
// adapters. What's centralised here is the genuinely-identical parse layer plus
|
|
19
|
+
// the one convention that must never drift: a k8s Service/Ingress is ROUTING —
|
|
20
|
+
// it becomes edges (and, where an entrypoint must earn a box, a `cdn` node),
|
|
21
|
+
// never a bogus InfraModuleKind. See K8S_ROUTING_KINDS below.
|
|
22
|
+
import { parseAllDocuments } from 'yaml';
|
|
23
|
+
import { resolveImageToSourceRoots } from '../image-resolve.js';
|
|
24
|
+
// ---------------------------------------------------------------------------
|
|
25
|
+
// Kind taxonomy.
|
|
26
|
+
/**
|
|
27
|
+
* Workload kinds — every adapter models these as `container` InfraModuleKind
|
|
28
|
+
* nodes. Note GCP's v0 scope omits DaemonSet while Azure includes it; each
|
|
29
|
+
* adapter decides its own workload set, so this is the documented SUPERSET and
|
|
30
|
+
* adapters intersect it with what they support rather than relying on it.
|
|
31
|
+
*/
|
|
32
|
+
export const K8S_WORKLOAD_KINDS = ['Deployment', 'StatefulSet', 'DaemonSet', 'Job', 'CronJob'];
|
|
33
|
+
/**
|
|
34
|
+
* Routing kinds — NEVER a node-with-a-module-kind. A Service/Ingress is modelled
|
|
35
|
+
* as edges (and, for an external entrypoint, a `cdn` node). Centralised here so
|
|
36
|
+
* the "no bogus module kind for routing" rule has one home.
|
|
37
|
+
*/
|
|
38
|
+
export const K8S_ROUTING_KINDS = ['Service', 'Ingress'];
|
|
39
|
+
/**
|
|
40
|
+
* Recognise a standard Kubernetes `apiVersion`. Mirrors the prefix set the GCP
|
|
41
|
+
* adapter has always used: core `v1`, plus the `apps/`, `batch/`,
|
|
42
|
+
* `networking.k8s.io/`, and `extensions/` groups.
|
|
43
|
+
*/
|
|
44
|
+
export function isK8sApiVersion(apiVersion) {
|
|
45
|
+
if (!apiVersion)
|
|
46
|
+
return false;
|
|
47
|
+
return (apiVersion === 'v1' ||
|
|
48
|
+
apiVersion.startsWith('apps/') ||
|
|
49
|
+
apiVersion.startsWith('batch/') ||
|
|
50
|
+
apiVersion.startsWith('networking.k8s.io/') ||
|
|
51
|
+
apiVersion.startsWith('extensions/'));
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Detect a Kubernetes manifest: must have 'apiVersion' and 'kind' and
|
|
55
|
+
* 'metadata' at the top level. Guards against firing on arbitrary YAML.
|
|
56
|
+
*/
|
|
57
|
+
export function isK8sManifest(doc) {
|
|
58
|
+
if (typeof doc !== 'object' || doc === null)
|
|
59
|
+
return false;
|
|
60
|
+
const obj = doc;
|
|
61
|
+
return (typeof obj['apiVersion'] === 'string' &&
|
|
62
|
+
typeof obj['kind'] === 'string' &&
|
|
63
|
+
typeof obj['metadata'] === 'object' &&
|
|
64
|
+
obj['metadata'] !== null);
|
|
65
|
+
}
|
|
66
|
+
// ---------------------------------------------------------------------------
|
|
67
|
+
// Selector & routing primitives.
|
|
68
|
+
/**
|
|
69
|
+
* Extract selector labels from a manifest `spec`. Handles both shapes:
|
|
70
|
+
* * `spec.selector.matchLabels` (Deployment / StatefulSet style)
|
|
71
|
+
* * `spec.selector` as a plain label map (Service style)
|
|
72
|
+
* Returns the raw label map (cast, NOT filtered — preserving Azure's original
|
|
73
|
+
* behavior verbatim), or `undefined` when there is no selector. (Azure keeps
|
|
74
|
+
* the `undefined` to gate selector-less Services out of routing; GCP wraps this
|
|
75
|
+
* with its own string-filter + `?? {}` for its overlap matcher — see
|
|
76
|
+
* gcp.ts selectorLabels.) Deliberately NOT string-filtered here so the shared
|
|
77
|
+
* primitive is a no-behavior-change drop-in for the old per-adapter code.
|
|
78
|
+
*/
|
|
79
|
+
export function extractSelector(spec) {
|
|
80
|
+
if (typeof spec !== 'object' || spec === null)
|
|
81
|
+
return undefined;
|
|
82
|
+
const sel = spec['selector'];
|
|
83
|
+
if (typeof sel !== 'object' || sel === null)
|
|
84
|
+
return undefined;
|
|
85
|
+
const ml = sel['matchLabels'];
|
|
86
|
+
if (typeof ml === 'object' && ml !== null) {
|
|
87
|
+
return ml;
|
|
88
|
+
}
|
|
89
|
+
return sel;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Extract the backend Service names an Ingress routes to, across both backend
|
|
93
|
+
* encodings: k8s 1.19+ (`backend.service.name`) and legacy
|
|
94
|
+
* extensions/v1beta1 (`backend.serviceName`). Deduplicated, source order.
|
|
95
|
+
*/
|
|
96
|
+
export function extractIngressBackends(spec) {
|
|
97
|
+
if (typeof spec !== 'object' || spec === null)
|
|
98
|
+
return [];
|
|
99
|
+
const rules = Array.isArray(spec['rules'])
|
|
100
|
+
? spec['rules']
|
|
101
|
+
: [];
|
|
102
|
+
const names = [];
|
|
103
|
+
for (const rule of rules) {
|
|
104
|
+
if (typeof rule !== 'object' || rule === null)
|
|
105
|
+
continue;
|
|
106
|
+
const http = rule['http'];
|
|
107
|
+
if (typeof http !== 'object' || http === null)
|
|
108
|
+
continue;
|
|
109
|
+
const paths = Array.isArray(http['paths'])
|
|
110
|
+
? http['paths']
|
|
111
|
+
: [];
|
|
112
|
+
for (const p of paths) {
|
|
113
|
+
if (typeof p !== 'object' || p === null)
|
|
114
|
+
continue;
|
|
115
|
+
const backend = p['backend'];
|
|
116
|
+
if (typeof backend !== 'object' || backend === null)
|
|
117
|
+
continue;
|
|
118
|
+
// k8s 1.19+ networking.k8s.io style:
|
|
119
|
+
const svc = backend['service'];
|
|
120
|
+
if (typeof svc === 'object' && svc !== null) {
|
|
121
|
+
const svcName = svc['name'];
|
|
122
|
+
if (typeof svcName === 'string')
|
|
123
|
+
names.push(svcName);
|
|
124
|
+
}
|
|
125
|
+
// Legacy extensions/v1beta1 style:
|
|
126
|
+
const legacySvcName = backend['serviceName'];
|
|
127
|
+
if (typeof legacySvcName === 'string')
|
|
128
|
+
names.push(legacySvcName);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
return [...new Set(names)];
|
|
132
|
+
}
|
|
133
|
+
/** True when two selector label maps share at least one identical key/value pair. */
|
|
134
|
+
export function labelsOverlap(a, b) {
|
|
135
|
+
for (const [k, v] of Object.entries(a)) {
|
|
136
|
+
if (b[k] === v)
|
|
137
|
+
return true;
|
|
138
|
+
}
|
|
139
|
+
return false;
|
|
140
|
+
}
|
|
141
|
+
// ---------------------------------------------------------------------------
|
|
142
|
+
// Workload image → source-root resolution.
|
|
143
|
+
//
|
|
144
|
+
// k8s references PRE-BUILT images (`image: ghcr.io/acme/api:1.2`), never source
|
|
145
|
+
// dirs — so a workload's code can only attribute to a deployment unit by mapping
|
|
146
|
+
// its container image(s) back to the in-repo Dockerfile that builds them. That's
|
|
147
|
+
// the resolver. These helpers find a workload's images and union the
|
|
148
|
+
// resolved roots; the GCP (GKE) + Azure (AKS) adapters call them on their
|
|
149
|
+
// `container` workload nodes.
|
|
150
|
+
function asRecord(v) {
|
|
151
|
+
return v && typeof v === 'object' && !Array.isArray(v) ? v : undefined;
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* The Pod spec inside a workload manifest, across the nesting variants:
|
|
155
|
+
* * Deployment / StatefulSet / DaemonSet / Job → `spec.template.spec`
|
|
156
|
+
* * CronJob → `spec.jobTemplate.spec.template.spec`
|
|
157
|
+
* * bare Pod → `spec`
|
|
158
|
+
*/
|
|
159
|
+
function podSpecOf(raw) {
|
|
160
|
+
const spec = asRecord(raw['spec']);
|
|
161
|
+
if (!spec)
|
|
162
|
+
return undefined;
|
|
163
|
+
const jobTemplate = asRecord(spec['jobTemplate']); // CronJob
|
|
164
|
+
if (jobTemplate) {
|
|
165
|
+
const jspec = asRecord(jobTemplate['spec']);
|
|
166
|
+
const tmpl = asRecord(jspec?.['template']);
|
|
167
|
+
return asRecord(tmpl?.['spec']);
|
|
168
|
+
}
|
|
169
|
+
const tmpl = asRecord(spec['template']); // Deployment/StatefulSet/DaemonSet/Job
|
|
170
|
+
if (tmpl)
|
|
171
|
+
return asRecord(tmpl['spec']);
|
|
172
|
+
return spec; // bare Pod
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Every container image ref a workload manifest declares (containers +
|
|
176
|
+
* initContainers, across the workload nesting variants). Deduped, source order.
|
|
177
|
+
*/
|
|
178
|
+
export function extractWorkloadImages(raw) {
|
|
179
|
+
const podSpec = podSpecOf(raw);
|
|
180
|
+
if (!podSpec)
|
|
181
|
+
return [];
|
|
182
|
+
const images = [];
|
|
183
|
+
for (const key of ['initContainers', 'containers']) {
|
|
184
|
+
const list = podSpec[key];
|
|
185
|
+
if (!Array.isArray(list))
|
|
186
|
+
continue;
|
|
187
|
+
for (const c of list) {
|
|
188
|
+
const image = asRecord(c)?.['image'];
|
|
189
|
+
if (typeof image === 'string' && image)
|
|
190
|
+
images.push(image);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
return [...new Set(images)];
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* The repo-relative source roots a k8s workload deploys: each container image
|
|
197
|
+
* resolved via the image→source resolver, unioned. Returns [] when no
|
|
198
|
+
* image resolves to an in-repo Dockerfile (honest "Other"). Deterministic.
|
|
199
|
+
*/
|
|
200
|
+
export function workloadSourceRoots(raw, index) {
|
|
201
|
+
const roots = new Set();
|
|
202
|
+
for (const image of extractWorkloadImages(raw)) {
|
|
203
|
+
for (const r of resolveImageToSourceRoots(image, index))
|
|
204
|
+
roots.add(r);
|
|
205
|
+
}
|
|
206
|
+
return [...roots].sort();
|
|
207
|
+
}
|
|
208
|
+
// ---------------------------------------------------------------------------
|
|
209
|
+
// Multi-document parse.
|
|
210
|
+
/**
|
|
211
|
+
* Parse a YAML file potentially containing multiple Kubernetes manifest
|
|
212
|
+
* documents into normalized {@link K8sManifest} descriptors. Returns `[]` on any
|
|
213
|
+
* parse error; non-k8s documents within a multi-doc file are silently skipped.
|
|
214
|
+
* Selector labels are populated for Services and backend names for Ingresses.
|
|
215
|
+
*/
|
|
216
|
+
export function parseK8sManifests(text) {
|
|
217
|
+
try {
|
|
218
|
+
const docs = parseAllDocuments(text);
|
|
219
|
+
const results = [];
|
|
220
|
+
for (const doc of docs) {
|
|
221
|
+
if (doc.errors && doc.errors.length > 0)
|
|
222
|
+
continue; // skip bad doc
|
|
223
|
+
const obj = doc.toJS();
|
|
224
|
+
if (!isK8sManifest(obj))
|
|
225
|
+
continue;
|
|
226
|
+
const meta = obj['metadata'];
|
|
227
|
+
const name = typeof meta['name'] === 'string' ? meta['name'] : '';
|
|
228
|
+
const namespace = typeof meta['namespace'] === 'string' ? meta['namespace'] : undefined;
|
|
229
|
+
const kind = obj['kind'];
|
|
230
|
+
const manifest = {
|
|
231
|
+
kind,
|
|
232
|
+
apiVersion: typeof obj['apiVersion'] === 'string' ? obj['apiVersion'] : undefined,
|
|
233
|
+
name,
|
|
234
|
+
namespace,
|
|
235
|
+
rawObj: obj,
|
|
236
|
+
};
|
|
237
|
+
if (kind === 'Service') {
|
|
238
|
+
manifest.selector = extractSelector(obj['spec']);
|
|
239
|
+
}
|
|
240
|
+
if (kind === 'Ingress') {
|
|
241
|
+
manifest.ingressBackends = extractIngressBackends(obj['spec']);
|
|
242
|
+
}
|
|
243
|
+
results.push(manifest);
|
|
244
|
+
}
|
|
245
|
+
return results;
|
|
246
|
+
}
|
|
247
|
+
catch {
|
|
248
|
+
return [];
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/infra/k8s/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export interface KamalBuilder {
|
|
2
|
+
/** `builder.context` — the build context dir (the app's source). */
|
|
3
|
+
context?: string;
|
|
4
|
+
/** `builder.dockerfile` — path to the Dockerfile (its dir is the source). */
|
|
5
|
+
dockerfile?: string;
|
|
6
|
+
}
|
|
7
|
+
export interface KamalAccessory {
|
|
8
|
+
name: string;
|
|
9
|
+
/** The accessory's image ref (`postgres:16`, `redis:7`) — classified by role. */
|
|
10
|
+
image?: string;
|
|
11
|
+
}
|
|
12
|
+
export interface KamalConfig {
|
|
13
|
+
/** `service:` — the app name. */
|
|
14
|
+
service?: string;
|
|
15
|
+
/** `image:` — the app image ref Kamal builds + deploys. */
|
|
16
|
+
image?: string;
|
|
17
|
+
/** `builder:` — direct build-source signals, when present. */
|
|
18
|
+
builder?: KamalBuilder;
|
|
19
|
+
/** `accessories:` — the side services, in declaration order. */
|
|
20
|
+
accessories: KamalAccessory[];
|
|
21
|
+
}
|
|
22
|
+
export declare function parseKamalConfig(yamlText: string): KamalConfig;
|
|
23
|
+
//# sourceMappingURL=kamal-parse.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kamal-parse.d.ts","sourceRoot":"","sources":["../../../src/infra/kamal/kamal-parse.ts"],"names":[],"mappings":"AAoBA,MAAM,WAAW,YAAY;IAC3B,oEAAoE;IACpE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,6EAA6E;IAC7E,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,iFAAiF;IACjF,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,WAAW;IAC1B,iCAAiC;IACjC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,2DAA2D;IAC3D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,8DAA8D;IAC9D,OAAO,CAAC,EAAE,YAAY,CAAC;IACvB,gEAAgE;IAChE,WAAW,EAAE,cAAc,EAAE,CAAC;CAC/B;AAiBD,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,WAAW,CAoC9D"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
// Kamal config parser + typed shape extractor.
|
|
2
|
+
//
|
|
3
|
+
// Kamal (Basecamp/DHH) deploys a Docker image to one or more VPS hosts. Its
|
|
4
|
+
// config is `config/deploy.yml` (YAML) — so this reuses the `yaml` package and
|
|
5
|
+
// mirrors the render-parse.ts ↔ render.ts parse/builder split.
|
|
6
|
+
//
|
|
7
|
+
// Covered top-level keys:
|
|
8
|
+
// service — the app's name (the app container's label/id)
|
|
9
|
+
// image — the app image ref (`myorg/app`) — resolved to a build context
|
|
10
|
+
// builder — { context, dockerfile } — a DIRECT source signal when present
|
|
11
|
+
// accessories — name → { image } — the side services (db/redis/…), classified
|
|
12
|
+
// from their image by role (the compose image-role token map)
|
|
13
|
+
//
|
|
14
|
+
// Kamal reference: https://kamal-deploy.org/docs/configuration/
|
|
15
|
+
import { parse as parseYaml } from 'yaml';
|
|
16
|
+
// ---------------------------------------------------------------------------
|
|
17
|
+
// Helpers
|
|
18
|
+
function str(v) {
|
|
19
|
+
return typeof v === 'string' && v ? v : undefined;
|
|
20
|
+
}
|
|
21
|
+
function obj(v) {
|
|
22
|
+
return v && typeof v === 'object' && !Array.isArray(v) ? v : undefined;
|
|
23
|
+
}
|
|
24
|
+
// ---------------------------------------------------------------------------
|
|
25
|
+
// Main parse function: raw YAML string → KamalConfig.
|
|
26
|
+
// Throws on YAML syntax errors (caller wraps in try/catch + warns).
|
|
27
|
+
export function parseKamalConfig(yamlText) {
|
|
28
|
+
const raw = parseYaml(yamlText, { logLevel: 'silent' });
|
|
29
|
+
if (raw === null || typeof raw !== 'object' || Array.isArray(raw)) {
|
|
30
|
+
throw new Error('kamal deploy.yml: top-level value must be a mapping');
|
|
31
|
+
}
|
|
32
|
+
const tree = raw;
|
|
33
|
+
const config = { accessories: [] };
|
|
34
|
+
const service = str(tree.service);
|
|
35
|
+
if (service)
|
|
36
|
+
config.service = service;
|
|
37
|
+
const image = str(tree.image);
|
|
38
|
+
if (image)
|
|
39
|
+
config.image = image;
|
|
40
|
+
const builderRaw = obj(tree.builder);
|
|
41
|
+
if (builderRaw) {
|
|
42
|
+
const builder = {};
|
|
43
|
+
const context = str(builderRaw.context);
|
|
44
|
+
if (context)
|
|
45
|
+
builder.context = context;
|
|
46
|
+
const dockerfile = str(builderRaw.dockerfile);
|
|
47
|
+
if (dockerfile)
|
|
48
|
+
builder.dockerfile = dockerfile;
|
|
49
|
+
config.builder = builder;
|
|
50
|
+
}
|
|
51
|
+
const accessoriesRaw = obj(tree.accessories);
|
|
52
|
+
if (accessoriesRaw) {
|
|
53
|
+
for (const [name, value] of Object.entries(accessoriesRaw)) {
|
|
54
|
+
const accRaw = obj(value);
|
|
55
|
+
if (!name || !accRaw)
|
|
56
|
+
continue; // skip nameless / non-mapping entries
|
|
57
|
+
const accessory = { name };
|
|
58
|
+
const accImage = str(accRaw.image);
|
|
59
|
+
if (accImage)
|
|
60
|
+
accessory.image = accImage;
|
|
61
|
+
config.accessories.push(accessory);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return config;
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=kamal-parse.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kamal-parse.js","sourceRoot":"","sources":["../../../src/infra/kamal/kamal-parse.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { InfraAdapter, InfraGraph } from '../types.js';
|
|
2
|
+
import { type DockerfileIndex } from '../image-resolve.js';
|
|
3
|
+
import { type KamalConfig } from './kamal-parse.js';
|
|
4
|
+
/**
|
|
5
|
+
* The repo-relative source roots the Kamal app deploys. builder.context /
|
|
6
|
+
* builder.dockerfile are DIRECT signals (preferred); else the image ref is run
|
|
7
|
+
* through the resolver. Repo-root resolutions are dropped (never a
|
|
8
|
+
* catch-all). Pure (the resolver index is injected). Deterministic + sorted.
|
|
9
|
+
*/
|
|
10
|
+
export declare function kamalAppSourceRoots(config: KamalConfig, dockerfileIndex?: DockerfileIndex): string[];
|
|
11
|
+
export declare function buildKamalGraph(args: {
|
|
12
|
+
config: KamalConfig;
|
|
13
|
+
configFile: string;
|
|
14
|
+
dockerfileIndex?: DockerfileIndex;
|
|
15
|
+
}, root: string): InfraGraph;
|
|
16
|
+
export declare const kamalAdapter: InfraAdapter;
|
|
17
|
+
//# sourceMappingURL=kamal.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kamal.d.ts","sourceRoot":"","sources":["../../../src/infra/kamal/kamal.ts"],"names":[],"mappings":"AAgCA,OAAO,KAAK,EAAE,YAAY,EAAa,UAAU,EAAa,MAAM,aAAa,CAAC;AAGlF,OAAO,EAAmD,KAAK,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAC5G,OAAO,EAAoB,KAAK,WAAW,EAAE,MAAM,kBAAkB,CAAC;AA6BtE;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,WAAW,EAAE,eAAe,CAAC,EAAE,eAAe,GAAG,MAAM,EAAE,CAgBpG;AAaD,wBAAgB,eAAe,CAC7B,IAAI,EAAE;IAAE,MAAM,EAAE,WAAW,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,eAAe,CAAC,EAAE,eAAe,CAAA;CAAE,EACpF,IAAI,EAAE,MAAM,GACX,UAAU,CAiCZ;AAgBD,eAAO,MAAM,YAAY,EAAE,YA+B1B,CAAC"}
|