@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,155 @@
|
|
|
1
|
+
// render.yaml parser + typed shape extractor.
|
|
2
|
+
//
|
|
3
|
+
// render.yaml is YAML (not TOML, not JSONC), so we use the `yaml` package
|
|
4
|
+
// (already a devDependency). This module maps the raw YAML tree into a
|
|
5
|
+
// typed RenderConfig shape that render.ts consumes — keeping the parser
|
|
6
|
+
// logic and the graph builder cleanly separated (same pattern as
|
|
7
|
+
// fly-parse.ts ↔ fly.ts).
|
|
8
|
+
//
|
|
9
|
+
// Covered top-level sections:
|
|
10
|
+
// services[] — type: web | worker | cron | pserv | static
|
|
11
|
+
// name, type, runtime, buildCommand, startCommand, plan, branch, autoDeploy
|
|
12
|
+
// envVars[] — fromDatabase, fromService, value, generateValue
|
|
13
|
+
// routes[] — for static sites
|
|
14
|
+
// databases[] — managed Postgres: name, plan, region, postgresMajorVersion
|
|
15
|
+
// redis[] — managed Redis/KeyValue: name, plan, region
|
|
16
|
+
//
|
|
17
|
+
// render.yaml reference:
|
|
18
|
+
// https://docs.render.com/blueprint-spec
|
|
19
|
+
import { parse as parseYaml } from 'yaml';
|
|
20
|
+
// ---------------------------------------------------------------------------
|
|
21
|
+
// Helpers
|
|
22
|
+
function str(v) {
|
|
23
|
+
return typeof v === 'string' && v ? v : undefined;
|
|
24
|
+
}
|
|
25
|
+
function bool(v) {
|
|
26
|
+
return typeof v === 'boolean' ? v : undefined;
|
|
27
|
+
}
|
|
28
|
+
function numOrStr(v) {
|
|
29
|
+
if (typeof v === 'number')
|
|
30
|
+
return v;
|
|
31
|
+
if (typeof v === 'string' && v)
|
|
32
|
+
return v;
|
|
33
|
+
return undefined;
|
|
34
|
+
}
|
|
35
|
+
function arr(tree, key) {
|
|
36
|
+
const v = tree[key];
|
|
37
|
+
return Array.isArray(v) ? v.filter((x) => x && typeof x === 'object') : [];
|
|
38
|
+
}
|
|
39
|
+
function obj(v) {
|
|
40
|
+
return v && typeof v === 'object' && !Array.isArray(v) ? v : undefined;
|
|
41
|
+
}
|
|
42
|
+
const SERVICE_TYPES = ['web', 'worker', 'cron', 'pserv', 'static'];
|
|
43
|
+
function parseServiceType(v) {
|
|
44
|
+
const s = str(v);
|
|
45
|
+
if (s && SERVICE_TYPES.includes(s))
|
|
46
|
+
return s;
|
|
47
|
+
if (s)
|
|
48
|
+
console.warn('[render] unknown service type', s);
|
|
49
|
+
return 'web'; // safe fallback
|
|
50
|
+
}
|
|
51
|
+
function parseEnvVar(raw) {
|
|
52
|
+
const ev = {};
|
|
53
|
+
const key = str(raw.key);
|
|
54
|
+
if (key)
|
|
55
|
+
ev.key = key;
|
|
56
|
+
const value = str(raw.value);
|
|
57
|
+
if (value !== undefined)
|
|
58
|
+
ev.value = value;
|
|
59
|
+
const gen = bool(raw.generateValue);
|
|
60
|
+
if (gen !== undefined)
|
|
61
|
+
ev.generateValue = gen;
|
|
62
|
+
// fromDatabase: { name, property }
|
|
63
|
+
const fromDb = obj(raw.fromDatabase);
|
|
64
|
+
if (fromDb) {
|
|
65
|
+
ev.fromDatabase = { name: str(fromDb.name), property: str(fromDb.property) };
|
|
66
|
+
}
|
|
67
|
+
// fromService: { name, type, property }
|
|
68
|
+
const fromSvc = obj(raw.fromService);
|
|
69
|
+
if (fromSvc) {
|
|
70
|
+
ev.fromService = {
|
|
71
|
+
name: str(fromSvc.name),
|
|
72
|
+
type: str(fromSvc.type),
|
|
73
|
+
property: str(fromSvc.property),
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
return ev;
|
|
77
|
+
}
|
|
78
|
+
function parseService(raw) {
|
|
79
|
+
const name = str(raw.name);
|
|
80
|
+
if (!name)
|
|
81
|
+
return null; // name is load-bearing; skip nameless entries
|
|
82
|
+
const rawType = str(raw.type) ?? 'web';
|
|
83
|
+
const type = parseServiceType(raw.type);
|
|
84
|
+
const envVars = arr(raw, 'envVars').map(parseEnvVar);
|
|
85
|
+
const routes = arr(raw, 'routes').map((r) => ({
|
|
86
|
+
type: str(r.type),
|
|
87
|
+
source: str(r.source),
|
|
88
|
+
destination: str(r.destination),
|
|
89
|
+
}));
|
|
90
|
+
return {
|
|
91
|
+
name,
|
|
92
|
+
type,
|
|
93
|
+
rawType,
|
|
94
|
+
runtime: str(raw.runtime),
|
|
95
|
+
buildCommand: str(raw.buildCommand),
|
|
96
|
+
startCommand: str(raw.startCommand),
|
|
97
|
+
plan: str(raw.plan),
|
|
98
|
+
branch: str(raw.branch),
|
|
99
|
+
autoDeploy: bool(raw.autoDeploy),
|
|
100
|
+
rootDir: str(raw.rootDir),
|
|
101
|
+
dockerfilePath: str(raw.dockerfilePath),
|
|
102
|
+
dockerContext: str(raw.dockerContext),
|
|
103
|
+
envVars,
|
|
104
|
+
routes: routes.length > 0 ? routes : undefined,
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
function parseDatabase(raw) {
|
|
108
|
+
const name = str(raw.name);
|
|
109
|
+
if (!name)
|
|
110
|
+
return null;
|
|
111
|
+
return {
|
|
112
|
+
name,
|
|
113
|
+
plan: str(raw.plan),
|
|
114
|
+
region: str(raw.region),
|
|
115
|
+
postgresMajorVersion: numOrStr(raw.postgresMajorVersion),
|
|
116
|
+
databaseName: str(raw.databaseName),
|
|
117
|
+
user: str(raw.user),
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
function parseRedis(raw) {
|
|
121
|
+
const name = str(raw.name);
|
|
122
|
+
if (!name)
|
|
123
|
+
return null;
|
|
124
|
+
return {
|
|
125
|
+
name,
|
|
126
|
+
plan: str(raw.plan),
|
|
127
|
+
region: str(raw.region),
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
// ---------------------------------------------------------------------------
|
|
131
|
+
// Main parse function: raw YAML string → RenderConfig.
|
|
132
|
+
// Throws on YAML syntax errors (caller wraps in try/catch + warns).
|
|
133
|
+
export function parseRenderConfig(yamlText) {
|
|
134
|
+
const raw = parseYaml(yamlText);
|
|
135
|
+
if (raw === null || typeof raw !== 'object' || Array.isArray(raw)) {
|
|
136
|
+
throw new Error('render.yaml: top-level value must be a mapping');
|
|
137
|
+
}
|
|
138
|
+
const tree = raw;
|
|
139
|
+
const services = arr(tree, 'services')
|
|
140
|
+
.map(parseService)
|
|
141
|
+
.filter((s) => s !== null);
|
|
142
|
+
const databases = arr(tree, 'databases')
|
|
143
|
+
.map(parseDatabase)
|
|
144
|
+
.filter((d) => d !== null);
|
|
145
|
+
// Render uses both 'redis' (newer) and 'keyValueStores' (alias) in the spec.
|
|
146
|
+
const redisRaw = [
|
|
147
|
+
...arr(tree, 'redis'),
|
|
148
|
+
...arr(tree, 'keyValueStores'),
|
|
149
|
+
];
|
|
150
|
+
const redis = redisRaw
|
|
151
|
+
.map(parseRedis)
|
|
152
|
+
.filter((r) => r !== null);
|
|
153
|
+
return { services, databases, redis };
|
|
154
|
+
}
|
|
155
|
+
//# sourceMappingURL=render-parse.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render-parse.js","sourceRoot":"","sources":["../../../src/infra/render/render-parse.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { InfraAdapter, InfraGraph } from '../types.js';
|
|
2
|
+
import { type RenderConfig } from './render-parse.js';
|
|
3
|
+
export interface RenderConfigEntry {
|
|
4
|
+
config: RenderConfig;
|
|
5
|
+
file: string;
|
|
6
|
+
dockerfilePath?: string;
|
|
7
|
+
packageJsonBuild?: string;
|
|
8
|
+
}
|
|
9
|
+
export declare function buildRenderGraph(configs: RenderConfigEntry[], root: string): InfraGraph;
|
|
10
|
+
export declare const renderAdapter: InfraAdapter;
|
|
11
|
+
//# sourceMappingURL=render.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../../../src/infra/render/render.ts"],"names":[],"mappings":"AA2BA,OAAO,KAAK,EAAE,YAAY,EAAa,UAAU,EAAa,MAAM,aAAa,CAAC;AAElF,OAAO,EAAqB,KAAK,YAAY,EAAsB,MAAM,mBAAmB,CAAC;AA+F7F,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,YAAY,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,iBAAiB,EAAE,EAAE,IAAI,EAAE,MAAM,GAAG,UAAU,CA6KvF;AAKD,eAAO,MAAM,aAAa,EAAE,YA2B3B,CAAC"}
|
|
@@ -0,0 +1,303 @@
|
|
|
1
|
+
// the Render InfraAdapter (v0).
|
|
2
|
+
//
|
|
3
|
+
// Surfaces the Render PaaS deployment topology from `render.yaml` (the
|
|
4
|
+
// Render Blueprint Spec). Entirely declared provenance — render.yaml names
|
|
5
|
+
// every service, database, and Redis instance explicitly. No LLM needed
|
|
6
|
+
// (classificationsNeeded: []).
|
|
7
|
+
//
|
|
8
|
+
// Kind mapping (locked 8-kind InfraModuleKind enum — never weaken):
|
|
9
|
+
// render.yaml services[].type:
|
|
10
|
+
// web / pserv / worker / cron → `worker` (serverless/long-running compute)
|
|
11
|
+
// static → `static-site`
|
|
12
|
+
// render.yaml databases[] → `datastore` (managed Postgres)
|
|
13
|
+
// render.yaml redis[] → `datastore` (managed Redis/KeyValue)
|
|
14
|
+
//
|
|
15
|
+
// Edge taxonomy (8-verb EdgeKind — FORBIDDEN: imports/depends-on/uses):
|
|
16
|
+
// service → datastore : stores-in (via envVars[].fromDatabase)
|
|
17
|
+
// service → service : calls (via envVars[].fromService)
|
|
18
|
+
//
|
|
19
|
+
// v0 scope:
|
|
20
|
+
// * envVars with fromDatabase → edge service `stores-in` the named datastore.
|
|
21
|
+
// * envVars with fromService → edge service `calls` the named peer service.
|
|
22
|
+
// * Dockerfile presence noted in metadata only.
|
|
23
|
+
// * package.json buildCommand noted in metadata only.
|
|
24
|
+
// * PaaS model is tight/static — no LLM needed.
|
|
25
|
+
import { readFileSync, existsSync } from 'node:fs';
|
|
26
|
+
import { join, relative, dirname } from 'node:path';
|
|
27
|
+
import { findFiles } from '../walk.js';
|
|
28
|
+
import { parseRenderConfig } from './render-parse.js';
|
|
29
|
+
/**
|
|
30
|
+
* Locate every `render.yaml` in the repo (bounded recursive walk).
|
|
31
|
+
* render.yaml is almost always at the repo root, but monorepos can have one
|
|
32
|
+
* per sub-project, so we walk the full tree.
|
|
33
|
+
*/
|
|
34
|
+
function findRenderConfigs(repoDir) {
|
|
35
|
+
return findFiles(repoDir, (_abs, e) => e.name === 'render.yaml' || e.name === 'render.yml', { maxDepth: 5 });
|
|
36
|
+
}
|
|
37
|
+
// ---------------------------------------------------------------------------
|
|
38
|
+
// Source-root helpers. Repo-relative, normalized — same idiom as
|
|
39
|
+
// netlify.ts / compose.ts.
|
|
40
|
+
/** Normalize a repo-relative path: backslashes→/, collapse `.`/`./`, strip trailing `/`. */
|
|
41
|
+
function normalizeRoot(p) {
|
|
42
|
+
return p.replace(/\\/g, '/').replace(/^\.(?:\/|$)/, '').replace(/\/+$/, '');
|
|
43
|
+
}
|
|
44
|
+
/** The repo-relative directory of a repo-relative file path ('' = repo root). */
|
|
45
|
+
function dirOf(relPath) {
|
|
46
|
+
const i = relPath.lastIndexOf('/');
|
|
47
|
+
return i === -1 ? '' : relPath.slice(0, i);
|
|
48
|
+
}
|
|
49
|
+
/** Resolve `rel` (may contain `./`/`../`) against repo-relative `baseDir` → normalized. */
|
|
50
|
+
function resolveRel(baseDir, rel) {
|
|
51
|
+
const parts = (baseDir ? baseDir.split('/') : []).concat(rel.split('/'));
|
|
52
|
+
const out = [];
|
|
53
|
+
for (const p of parts) {
|
|
54
|
+
if (p === '' || p === '.')
|
|
55
|
+
continue;
|
|
56
|
+
if (p === '..')
|
|
57
|
+
out.pop();
|
|
58
|
+
else
|
|
59
|
+
out.push(p);
|
|
60
|
+
}
|
|
61
|
+
return out.join('/');
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* a Render service's source root, resolved repo-relative against the
|
|
65
|
+
* render.yaml dir. Priority: explicit `rootDir` (the monorepo base dir) → Docker
|
|
66
|
+
* `dockerContext` → the dir of `dockerfilePath` → the render.yaml dir itself.
|
|
67
|
+
* Returns '' (→ no source root) when the best signal is the bare repo root, so a
|
|
68
|
+
* root-level service never becomes a catch-all swallowing its siblings.
|
|
69
|
+
*/
|
|
70
|
+
function serviceSourceRoot(svc, configDir) {
|
|
71
|
+
if (svc.rootDir)
|
|
72
|
+
return resolveRel(configDir, svc.rootDir);
|
|
73
|
+
if (svc.dockerContext)
|
|
74
|
+
return resolveRel(configDir, svc.dockerContext);
|
|
75
|
+
if (svc.dockerfilePath)
|
|
76
|
+
return dirOf(resolveRel(configDir, svc.dockerfilePath));
|
|
77
|
+
return normalizeRoot(configDir);
|
|
78
|
+
}
|
|
79
|
+
// ---------------------------------------------------------------------------
|
|
80
|
+
// Node-id helpers (adapter-local; registry prefixes `render:` at merge time).
|
|
81
|
+
const serviceId = (name) => `service:${name}`;
|
|
82
|
+
const databaseId = (name) => `database:${name}`;
|
|
83
|
+
const redisId = (name) => `redis:${name}`;
|
|
84
|
+
// ---------------------------------------------------------------------------
|
|
85
|
+
// Dockerfile probe — existence check only (like fly.ts).
|
|
86
|
+
function findDockerfile(repoDir, configFile) {
|
|
87
|
+
// Look adjacent to the render.yaml first, then at repo root.
|
|
88
|
+
const configDir = dirname(configFile);
|
|
89
|
+
for (const candidate of [join(configDir, 'Dockerfile'), join(repoDir, 'Dockerfile')]) {
|
|
90
|
+
if (existsSync(candidate))
|
|
91
|
+
return relative(repoDir, candidate);
|
|
92
|
+
}
|
|
93
|
+
return undefined;
|
|
94
|
+
}
|
|
95
|
+
// ---------------------------------------------------------------------------
|
|
96
|
+
// Read package.json build command (metadata only, no graph impact).
|
|
97
|
+
function readPackageJsonBuild(repoDir) {
|
|
98
|
+
const pkgPath = join(repoDir, 'package.json');
|
|
99
|
+
if (!existsSync(pkgPath))
|
|
100
|
+
return undefined;
|
|
101
|
+
try {
|
|
102
|
+
const pkg = JSON.parse(readFileSync(pkgPath, 'utf8'));
|
|
103
|
+
const scripts = pkg.scripts;
|
|
104
|
+
if (scripts && typeof scripts === 'object' && !Array.isArray(scripts)) {
|
|
105
|
+
return typeof scripts.build === 'string'
|
|
106
|
+
? scripts.build
|
|
107
|
+
: undefined;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
catch {
|
|
111
|
+
/* not parseable — skip */
|
|
112
|
+
}
|
|
113
|
+
return undefined;
|
|
114
|
+
}
|
|
115
|
+
export function buildRenderGraph(configs, root) {
|
|
116
|
+
const nodes = new Map();
|
|
117
|
+
const edges = [];
|
|
118
|
+
const addNode = (n) => {
|
|
119
|
+
// First declaration wins (same pattern as cloudflare.ts).
|
|
120
|
+
if (!nodes.has(n.id))
|
|
121
|
+
nodes.set(n.id, n);
|
|
122
|
+
};
|
|
123
|
+
// Two-pass approach: emit all nodes first, then emit edges.
|
|
124
|
+
// This ensures that when service A references service B via fromService,
|
|
125
|
+
// B's full node (with metadata) is already registered — no placeholder
|
|
126
|
+
// needed, no risk of the placeholder winning the "first declaration" race.
|
|
127
|
+
for (const { config, file, dockerfilePath, packageJsonBuild } of configs) {
|
|
128
|
+
const rel = relative(root, file) || file;
|
|
129
|
+
// -------------------------------------------------------------------
|
|
130
|
+
// Pass 1a: Database nodes (managed Postgres).
|
|
131
|
+
for (const db of config.databases) {
|
|
132
|
+
addNode({
|
|
133
|
+
id: databaseId(db.name),
|
|
134
|
+
label: db.name,
|
|
135
|
+
kind: 'datastore',
|
|
136
|
+
provenance: 'declared',
|
|
137
|
+
metadata: {
|
|
138
|
+
provider: 'render',
|
|
139
|
+
subtype: 'postgres',
|
|
140
|
+
plan: db.plan,
|
|
141
|
+
region: db.region,
|
|
142
|
+
postgresMajorVersion: db.postgresMajorVersion,
|
|
143
|
+
databaseName: db.databaseName,
|
|
144
|
+
user: db.user,
|
|
145
|
+
config: rel,
|
|
146
|
+
},
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
// -------------------------------------------------------------------
|
|
150
|
+
// Pass 1b: Redis nodes (managed Redis / KeyValue).
|
|
151
|
+
for (const r of config.redis) {
|
|
152
|
+
addNode({
|
|
153
|
+
id: redisId(r.name),
|
|
154
|
+
label: r.name,
|
|
155
|
+
kind: 'datastore',
|
|
156
|
+
provenance: 'declared',
|
|
157
|
+
metadata: {
|
|
158
|
+
provider: 'render',
|
|
159
|
+
subtype: 'redis',
|
|
160
|
+
plan: r.plan,
|
|
161
|
+
region: r.region,
|
|
162
|
+
config: rel,
|
|
163
|
+
},
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
// -------------------------------------------------------------------
|
|
167
|
+
// Pass 1c: Service nodes.
|
|
168
|
+
// web / worker / cron / pserv → `worker`
|
|
169
|
+
// static → `static-site`
|
|
170
|
+
const configDir = dirOf(rel);
|
|
171
|
+
for (const svc of config.services) {
|
|
172
|
+
const id = serviceId(svc.name);
|
|
173
|
+
const isStatic = svc.type === 'static';
|
|
174
|
+
// per-service source root from rootDir / dockerContext /
|
|
175
|
+
// dockerfilePath / the render.yaml dir; dropped if it resolves to the bare
|
|
176
|
+
// repo root (no catch-all). Datastores (Postgres/Redis) run no code → none.
|
|
177
|
+
const srcRoot = serviceSourceRoot(svc, configDir);
|
|
178
|
+
addNode({
|
|
179
|
+
id,
|
|
180
|
+
label: svc.name,
|
|
181
|
+
kind: isStatic ? 'static-site' : 'worker',
|
|
182
|
+
provenance: 'declared',
|
|
183
|
+
metadata: {
|
|
184
|
+
provider: 'render',
|
|
185
|
+
serviceType: svc.rawType,
|
|
186
|
+
runtime: svc.runtime,
|
|
187
|
+
plan: svc.plan,
|
|
188
|
+
branch: svc.branch,
|
|
189
|
+
autoDeploy: svc.autoDeploy,
|
|
190
|
+
buildCommand: svc.buildCommand ?? packageJsonBuild,
|
|
191
|
+
startCommand: svc.startCommand,
|
|
192
|
+
...(dockerfilePath ? { dockerfile: dockerfilePath } : {}),
|
|
193
|
+
config: rel,
|
|
194
|
+
},
|
|
195
|
+
...(srcRoot ? { sourceRoots: [srcRoot] } : {}),
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
// -------------------------------------------------------------------
|
|
200
|
+
// Pass 2: Edges from envVars (all nodes are registered, no placeholders needed).
|
|
201
|
+
for (const { config, file } of configs) {
|
|
202
|
+
const rel = relative(root, file) || file;
|
|
203
|
+
for (const svc of config.services) {
|
|
204
|
+
const id = serviceId(svc.name);
|
|
205
|
+
for (const ev of svc.envVars) {
|
|
206
|
+
// fromDatabase → service stores-in the named database (Postgres or Redis).
|
|
207
|
+
if (ev.fromDatabase?.name) {
|
|
208
|
+
const dbName = ev.fromDatabase.name;
|
|
209
|
+
const isPostgres = config.databases.some((d) => d.name === dbName);
|
|
210
|
+
const isRedis = config.redis.some((r) => r.name === dbName);
|
|
211
|
+
let targetId;
|
|
212
|
+
if (isPostgres) {
|
|
213
|
+
targetId = databaseId(dbName);
|
|
214
|
+
}
|
|
215
|
+
else if (isRedis) {
|
|
216
|
+
targetId = redisId(dbName);
|
|
217
|
+
}
|
|
218
|
+
else {
|
|
219
|
+
// Name doesn't match any declared datastore in this config.
|
|
220
|
+
// Emit a minimal placeholder so the edge endpoint is never phantom.
|
|
221
|
+
// (Could be declared in a sibling config or added manually later.)
|
|
222
|
+
targetId = databaseId(dbName);
|
|
223
|
+
if (!nodes.has(targetId)) {
|
|
224
|
+
addNode({
|
|
225
|
+
id: targetId,
|
|
226
|
+
label: dbName,
|
|
227
|
+
kind: 'datastore',
|
|
228
|
+
provenance: 'declared',
|
|
229
|
+
metadata: { provider: 'render', subtype: 'postgres', config: rel, placeholder: true },
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
edges.push({
|
|
234
|
+
source: id,
|
|
235
|
+
target: targetId,
|
|
236
|
+
kind: 'stores-in',
|
|
237
|
+
metadata: { envKey: ev.key, property: ev.fromDatabase.property, config: rel },
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
// fromService → service calls the named peer service.
|
|
241
|
+
if (ev.fromService?.name) {
|
|
242
|
+
const peerId = serviceId(ev.fromService.name);
|
|
243
|
+
// If the peer isn't already in the node map (it's in a different config
|
|
244
|
+
// file or declared only here), add a minimal placeholder so the edge
|
|
245
|
+
// endpoint resolves post-merge (same approach as cloudflare.ts service bindings).
|
|
246
|
+
if (!nodes.has(peerId)) {
|
|
247
|
+
addNode({
|
|
248
|
+
id: peerId,
|
|
249
|
+
label: ev.fromService.name,
|
|
250
|
+
kind: 'worker',
|
|
251
|
+
provenance: 'declared',
|
|
252
|
+
metadata: { provider: 'render', config: rel },
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
edges.push({
|
|
256
|
+
source: id,
|
|
257
|
+
target: peerId,
|
|
258
|
+
kind: 'calls',
|
|
259
|
+
metadata: { envKey: ev.key, property: ev.fromService.property, config: rel },
|
|
260
|
+
});
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
return {
|
|
266
|
+
root,
|
|
267
|
+
adapter: 'render',
|
|
268
|
+
nodes: [...nodes.values()],
|
|
269
|
+
edges,
|
|
270
|
+
classificationsNeeded: [], // Render's PaaS model is tight/static — no LLM needed
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
// ---------------------------------------------------------------------------
|
|
274
|
+
// Adapter
|
|
275
|
+
export const renderAdapter = {
|
|
276
|
+
name: 'render',
|
|
277
|
+
async detect(repoDir) {
|
|
278
|
+
// Cheap: just check if render.yaml exists anywhere (bounded walk).
|
|
279
|
+
return findRenderConfigs(repoDir).length > 0;
|
|
280
|
+
},
|
|
281
|
+
async extract(repoDir) {
|
|
282
|
+
const files = findRenderConfigs(repoDir);
|
|
283
|
+
const entries = [];
|
|
284
|
+
const packageJsonBuild = readPackageJsonBuild(repoDir);
|
|
285
|
+
for (const file of files) {
|
|
286
|
+
try {
|
|
287
|
+
const text = readFileSync(file, 'utf8');
|
|
288
|
+
const config = parseRenderConfig(text);
|
|
289
|
+
const dockerfilePath = findDockerfile(repoDir, file);
|
|
290
|
+
entries.push({ config, file, dockerfilePath, packageJsonBuild });
|
|
291
|
+
}
|
|
292
|
+
catch (err) {
|
|
293
|
+
// A single malformed config shouldn't sink the whole infra layer.
|
|
294
|
+
console.warn(` [render] skipping unparseable ${file}: ${String(err)}`);
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
return buildRenderGraph(entries, repoDir);
|
|
298
|
+
},
|
|
299
|
+
};
|
|
300
|
+
// ---------------------------------------------------------------------------
|
|
301
|
+
// Re-export the pure builder for testing without fs IO.
|
|
302
|
+
// (The adapter's extract() is exercised via the fs-backed detect+extract tests.)
|
|
303
|
+
//# sourceMappingURL=render.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render.js","sourceRoot":"","sources":["../../../src/infra/render/render.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,EAAE;AACF,uEAAuE;AACvE,2EAA2E;AAC3E,wEAAwE;AACxE,+BAA+B;AAC/B,EAAE;AACF,oEAAoE;AACpE,iCAAiC;AACjC,gFAAgF;AAChF,kDAAkD;AAClD,mEAAmE;AACnE,0EAA0E;AAC1E,EAAE;AACF,wEAAwE;AACxE,qEAAqE;AACrE,oEAAoE;AACpE,EAAE;AACF,YAAY;AACZ,gFAAgF;AAChF,+EAA+E;AAC/E,kDAAkD;AAClD,wDAAwD;AACxD,kDAAkD;AAElD,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpD,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,EAAE,iBAAiB,EAAyC,MAAM,mBAAmB,CAAC;AAE7F;;;;GAIG;AACH,SAAS,iBAAiB,CAAC,OAAe;IACxC,OAAO,SAAS,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,aAAa,IAAI,CAAC,CAAC,IAAI,KAAK,YAAY,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC,CAAC;AAC/G,CAAC;AAED,8EAA8E;AAC9E,iEAAiE;AACjE,2BAA2B;AAE3B,4FAA4F;AAC5F,SAAS,aAAa,CAAC,CAAS;IAC9B,OAAO,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,aAAa,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;AAC9E,CAAC;AAED,iFAAiF;AACjF,SAAS,KAAK,CAAC,OAAe;IAC5B,MAAM,CAAC,GAAG,OAAO,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IACnC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AAC7C,CAAC;AAED,2FAA2F;AAC3F,SAAS,UAAU,CAAC,OAAe,EAAE,GAAW;IAC9C,MAAM,KAAK,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;IACzE,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;QACtB,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,GAAG;YAAE,SAAS;QACpC,IAAI,CAAC,KAAK,IAAI;YAAE,GAAG,CAAC,GAAG,EAAE,CAAC;;YACrB,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACnB,CAAC;IACD,OAAO,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACvB,CAAC;AAED;;;;;;GAMG;AACH,SAAS,iBAAiB,CAAC,GAAkB,EAAE,SAAiB;IAC9D,IAAI,GAAG,CAAC,OAAO;QAAE,OAAO,UAAU,CAAC,SAAS,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;IAC3D,IAAI,GAAG,CAAC,aAAa;QAAE,OAAO,UAAU,CAAC,SAAS,EAAE,GAAG,CAAC,aAAa,CAAC,CAAC;IACvE,IAAI,GAAG,CAAC,cAAc;QAAE,OAAO,KAAK,CAAC,UAAU,CAAC,SAAS,EAAE,GAAG,CAAC,cAAc,CAAC,CAAC,CAAC;IAChF,OAAO,aAAa,CAAC,SAAS,CAAC,CAAC;AAClC,CAAC;AAED,8EAA8E;AAC9E,8EAA8E;AAE9E,MAAM,SAAS,GAAG,CAAC,IAAY,EAAE,EAAE,CAAC,WAAW,IAAI,EAAE,CAAC;AACtD,MAAM,UAAU,GAAG,CAAC,IAAY,EAAE,EAAE,CAAC,YAAY,IAAI,EAAE,CAAC;AACxD,MAAM,OAAO,GAAG,CAAC,IAAY,EAAE,EAAE,CAAC,SAAS,IAAI,EAAE,CAAC;AAElD,8EAA8E;AAC9E,yDAAyD;AAEzD,SAAS,cAAc,CAAC,OAAe,EAAE,UAAkB;IACzD,6DAA6D;IAC7D,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IACtC,KAAK,MAAM,SAAS,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,YAAY,CAAC,EAAE,IAAI,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC,EAAE,CAAC;QACrF,IAAI,UAAU,CAAC,SAAS,CAAC;YAAE,OAAO,QAAQ,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;IACjE,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,8EAA8E;AAC9E,oEAAoE;AAEpE,SAAS,oBAAoB,CAAC,OAAe;IAC3C,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,EAAE,cAAc,CAAC,CAAC;IAC9C,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC;QAAE,OAAO,SAAS,CAAC;IAC3C,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,OAAO,EAAE,MAAM,CAAC,CAA4B,CAAC;QACjF,MAAM,OAAO,GAAG,GAAG,CAAC,OAAO,CAAC;QAC5B,IAAI,OAAO,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;YACtE,OAAO,OAAQ,OAAmC,CAAC,KAAK,KAAK,QAAQ;gBACnE,CAAC,CAAG,OAAmC,CAAC,KAAgB;gBACxD,CAAC,CAAC,SAAS,CAAC;QAChB,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,0BAA0B;IAC5B,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAaD,MAAM,UAAU,gBAAgB,CAAC,OAA4B,EAAE,IAAY;IACzE,MAAM,KAAK,GAAG,IAAI,GAAG,EAAqB,CAAC;IAC3C,MAAM,KAAK,GAAgB,EAAE,CAAC;IAE9B,MAAM,OAAO,GAAG,CAAC,CAAY,EAAE,EAAE;QAC/B,0DAA0D;QAC1D,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;YAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;IAC3C,CAAC,CAAC;IAEF,4DAA4D;IAC5D,yEAAyE;IACzE,uEAAuE;IACvE,2EAA2E;IAE3E,KAAK,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,cAAc,EAAE,gBAAgB,EAAE,IAAI,OAAO,EAAE,CAAC;QACzE,MAAM,GAAG,GAAG,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,IAAI,CAAC;QAEzC,sEAAsE;QACtE,8CAA8C;QAE9C,KAAK,MAAM,EAAE,IAAI,MAAM,CAAC,SAAS,EAAE,CAAC;YAClC,OAAO,CAAC;gBACN,EAAE,EAAE,UAAU,CAAC,EAAE,CAAC,IAAI,CAAC;gBACvB,KAAK,EAAE,EAAE,CAAC,IAAI;gBACd,IAAI,EAAE,WAAW;gBACjB,UAAU,EAAE,UAAU;gBACtB,QAAQ,EAAE;oBACR,QAAQ,EAAE,QAAQ;oBAClB,OAAO,EAAE,UAAU;oBACnB,IAAI,EAAE,EAAE,CAAC,IAAI;oBACb,MAAM,EAAE,EAAE,CAAC,MAAM;oBACjB,oBAAoB,EAAE,EAAE,CAAC,oBAAoB;oBAC7C,YAAY,EAAE,EAAE,CAAC,YAAY;oBAC7B,IAAI,EAAE,EAAE,CAAC,IAAI;oBACb,MAAM,EAAE,GAAG;iBACZ;aACF,CAAC,CAAC;QACL,CAAC;QAED,sEAAsE;QACtE,mDAAmD;QAEnD,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;YAC7B,OAAO,CAAC;gBACN,EAAE,EAAE,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC;gBACnB,KAAK,EAAE,CAAC,CAAC,IAAI;gBACb,IAAI,EAAE,WAAW;gBACjB,UAAU,EAAE,UAAU;gBACtB,QAAQ,EAAE;oBACR,QAAQ,EAAE,QAAQ;oBAClB,OAAO,EAAE,OAAO;oBAChB,IAAI,EAAE,CAAC,CAAC,IAAI;oBACZ,MAAM,EAAE,CAAC,CAAC,MAAM;oBAChB,MAAM,EAAE,GAAG;iBACZ;aACF,CAAC,CAAC;QACL,CAAC;QAED,sEAAsE;QACtE,0BAA0B;QAC1B,4CAA4C;QAC5C,4BAA4B;QAE5B,MAAM,SAAS,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC;QAE7B,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;YAClC,MAAM,EAAE,GAAG,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YAC/B,MAAM,QAAQ,GAAG,GAAG,CAAC,IAAI,KAAK,QAAQ,CAAC;YAEvC,yDAAyD;YACzD,2EAA2E;YAC3E,4EAA4E;YAC5E,MAAM,OAAO,GAAG,iBAAiB,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;YAElD,OAAO,CAAC;gBACN,EAAE;gBACF,KAAK,EAAE,GAAG,CAAC,IAAI;gBACf,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,QAAQ;gBACzC,UAAU,EAAE,UAAU;gBACtB,QAAQ,EAAE;oBACR,QAAQ,EAAE,QAAQ;oBAClB,WAAW,EAAE,GAAG,CAAC,OAAO;oBACxB,OAAO,EAAE,GAAG,CAAC,OAAO;oBACpB,IAAI,EAAE,GAAG,CAAC,IAAI;oBACd,MAAM,EAAE,GAAG,CAAC,MAAM;oBAClB,UAAU,EAAE,GAAG,CAAC,UAAU;oBAC1B,YAAY,EAAE,GAAG,CAAC,YAAY,IAAI,gBAAgB;oBAClD,YAAY,EAAE,GAAG,CAAC,YAAY;oBAC9B,GAAG,CAAC,cAAc,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,cAAc,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;oBACzD,MAAM,EAAE,GAAG;iBACZ;gBACD,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aAC/C,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,sEAAsE;IACtE,iFAAiF;IAEjF,KAAK,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,OAAO,EAAE,CAAC;QACvC,MAAM,GAAG,GAAG,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,IAAI,CAAC;QAEzC,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;YAClC,MAAM,EAAE,GAAG,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YAE/B,KAAK,MAAM,EAAE,IAAI,GAAG,CAAC,OAAO,EAAE,CAAC;gBAC7B,2EAA2E;gBAC3E,IAAI,EAAE,CAAC,YAAY,EAAE,IAAI,EAAE,CAAC;oBAC1B,MAAM,MAAM,GAAG,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC;oBACpC,MAAM,UAAU,GAAG,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC;oBACnE,MAAM,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC;oBAE5D,IAAI,QAAgB,CAAC;oBACrB,IAAI,UAAU,EAAE,CAAC;wBACf,QAAQ,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC;oBAChC,CAAC;yBAAM,IAAI,OAAO,EAAE,CAAC;wBACnB,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;oBAC7B,CAAC;yBAAM,CAAC;wBACN,4DAA4D;wBAC5D,oEAAoE;wBACpE,mEAAmE;wBACnE,QAAQ,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC;wBAC9B,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;4BACzB,OAAO,CAAC;gCACN,EAAE,EAAE,QAAQ;gCACZ,KAAK,EAAE,MAAM;gCACb,IAAI,EAAE,WAAW;gCACjB,UAAU,EAAE,UAAU;gCACtB,QAAQ,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,GAAG,EAAE,WAAW,EAAE,IAAI,EAAE;6BACtF,CAAC,CAAC;wBACL,CAAC;oBACH,CAAC;oBACD,KAAK,CAAC,IAAI,CAAC;wBACT,MAAM,EAAE,EAAE;wBACV,MAAM,EAAE,QAAQ;wBAChB,IAAI,EAAE,WAAW;wBACjB,QAAQ,EAAE,EAAE,MAAM,EAAE,EAAE,CAAC,GAAG,EAAE,QAAQ,EAAE,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE;qBAC9E,CAAC,CAAC;gBACL,CAAC;gBAED,sDAAsD;gBACtD,IAAI,EAAE,CAAC,WAAW,EAAE,IAAI,EAAE,CAAC;oBACzB,MAAM,MAAM,GAAG,SAAS,CAAC,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;oBAC9C,wEAAwE;oBACxE,qEAAqE;oBACrE,kFAAkF;oBAClF,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;wBACvB,OAAO,CAAC;4BACN,EAAE,EAAE,MAAM;4BACV,KAAK,EAAE,EAAE,CAAC,WAAW,CAAC,IAAI;4BAC1B,IAAI,EAAE,QAAQ;4BACd,UAAU,EAAE,UAAU;4BACtB,QAAQ,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE;yBAC9C,CAAC,CAAC;oBACL,CAAC;oBACD,KAAK,CAAC,IAAI,CAAC;wBACT,MAAM,EAAE,EAAE;wBACV,MAAM,EAAE,MAAM;wBACd,IAAI,EAAE,OAAO;wBACb,QAAQ,EAAE,EAAE,MAAM,EAAE,EAAE,CAAC,GAAG,EAAE,QAAQ,EAAE,EAAE,CAAC,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE;qBAC7E,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO;QACL,IAAI;QACJ,OAAO,EAAE,QAAQ;QACjB,KAAK,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC;QAC1B,KAAK;QACL,qBAAqB,EAAE,EAAE,EAAE,sDAAsD;KAClF,CAAC;AACJ,CAAC;AAED,8EAA8E;AAC9E,UAAU;AAEV,MAAM,CAAC,MAAM,aAAa,GAAiB;IACzC,IAAI,EAAE,QAAQ;IAEd,KAAK,CAAC,MAAM,CAAC,OAAe;QAC1B,mEAAmE;QACnE,OAAO,iBAAiB,CAAC,OAAO,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;IAC/C,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,OAAe;QAC3B,MAAM,KAAK,GAAG,iBAAiB,CAAC,OAAO,CAAC,CAAC;QACzC,MAAM,OAAO,GAAwB,EAAE,CAAC;QACxC,MAAM,gBAAgB,GAAG,oBAAoB,CAAC,OAAO,CAAC,CAAC;QAEvD,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,IAAI,CAAC;gBACH,MAAM,IAAI,GAAG,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;gBACxC,MAAM,MAAM,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;gBACvC,MAAM,cAAc,GAAG,cAAc,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;gBACrD,OAAO,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,cAAc,EAAE,gBAAgB,EAAE,CAAC,CAAC;YACnE,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,kEAAkE;gBAClE,OAAO,CAAC,IAAI,CAAC,mCAAmC,IAAI,KAAK,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YAC1E,CAAC;QACH,CAAC;QAED,OAAO,gBAAgB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAC5C,CAAC;CACF,CAAC;AAEF,8EAA8E;AAC9E,wDAAwD;AACxD,iFAAiF"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export interface SstConstruct {
|
|
2
|
+
/** Full dotted construct path as written: `sst.aws.Function`, `sst.aws.Nextjs`. */
|
|
3
|
+
construct: string;
|
|
4
|
+
/** Last segment of the construct path: `Function`, `Nextjs`, `Bucket`. */
|
|
5
|
+
constructType: string;
|
|
6
|
+
/** The construct's logical name — its first string-literal arg (`"MyApi"`). */
|
|
7
|
+
name: string;
|
|
8
|
+
/** Adapter-local node-id source: the Pulumi `refAddr` = `<construct>.<name>`. */
|
|
9
|
+
refAddr: string;
|
|
10
|
+
/** Variable the `new` is assigned to (powers link/ref edges), if any. */
|
|
11
|
+
varName?: string;
|
|
12
|
+
/** Identifiers referenced in the args (`link: [bucket]`, `{ cluster }`) — for edges. */
|
|
13
|
+
referencedIdentifiers: string[];
|
|
14
|
+
/** Raw props-args text after the logical name — for deterministic source-signal
|
|
15
|
+
* extraction (`handler:`, `path:`, `image:`/`context:`), NEVER for edges. */
|
|
16
|
+
argsText: string;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Every `new sst.*(...)` construct in an SST config source. Reuses the generic
|
|
20
|
+
* ts-morph extractor and keeps only the `sst` namespace (so an app-code
|
|
21
|
+
* `new Foo.Bar()` or a `new other.aws.X()` is ignored). Tolerant: returns [] on
|
|
22
|
+
* unparseable/empty source (the underlying extractor never throws).
|
|
23
|
+
*/
|
|
24
|
+
export declare function extractSstConstructs(sourceText: string, file: string): SstConstruct[];
|
|
25
|
+
//# sourceMappingURL=sst-parse.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sst-parse.d.ts","sourceRoot":"","sources":["../../../src/infra/sst/sst-parse.ts"],"names":[],"mappings":"AAoBA,MAAM,WAAW,YAAY;IAC3B,mFAAmF;IACnF,SAAS,EAAE,MAAM,CAAC;IAClB,0EAA0E;IAC1E,aAAa,EAAE,MAAM,CAAC;IACtB,+EAA+E;IAC/E,IAAI,EAAE,MAAM,CAAC;IACb,iFAAiF;IACjF,OAAO,EAAE,MAAM,CAAC;IAChB,yEAAyE;IACzE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,wFAAwF;IACxF,qBAAqB,EAAE,MAAM,EAAE,CAAC;IAChC;iFAC6E;IAC7E,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,YAAY,EAAE,CAoBrF"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
// SST config parser (ts-morph construct extraction).
|
|
2
|
+
//
|
|
3
|
+
// SST v3 ("Ion") declares infrastructure as code in `sst.config.ts` — inside
|
|
4
|
+
// `async run()` you write `new sst.aws.Function("MyApi", { handler: "…" })`,
|
|
5
|
+
// `new sst.aws.Bucket("Uploads")`, `new sst.aws.Nextjs("Web", { path: "…" })`,
|
|
6
|
+
// etc. That's the SAME `new <A.B.C>(name, args)` call-site shape the Pulumi
|
|
7
|
+
// adapter already walks with ts-morph — so this REUSES `extractPulumiResources`
|
|
8
|
+
// (a generic property-access-chain `new`-expression extractor) and filters to the
|
|
9
|
+
// `sst.*` namespace, rather than re-implementing the AST walk.
|
|
10
|
+
//
|
|
11
|
+
// v0 scope: the `sst.config.ts` entry file (the v3 Ion convention). SST v2's
|
|
12
|
+
// single-segment construct classes imported into a `stacks/**` dir (`new Api(stack,
|
|
13
|
+
// …)`, no `sst.` namespace) are NOT matched — deferred, the same coarse v0 bound
|
|
14
|
+
// the Pulumi adapter notes. Pure (string in, data out); no fs, no LLM.
|
|
15
|
+
import { extractPulumiResources, providerOf } from '../pulumi/pulumi-parse.js';
|
|
16
|
+
/** The `sst` provider namespace — `new sst.aws.Function(...)` / `new sst.Foo(...)`. */
|
|
17
|
+
const SST_PROVIDER = 'sst';
|
|
18
|
+
/**
|
|
19
|
+
* Every `new sst.*(...)` construct in an SST config source. Reuses the generic
|
|
20
|
+
* ts-morph extractor and keeps only the `sst` namespace (so an app-code
|
|
21
|
+
* `new Foo.Bar()` or a `new other.aws.X()` is ignored). Tolerant: returns [] on
|
|
22
|
+
* unparseable/empty source (the underlying extractor never throws).
|
|
23
|
+
*/
|
|
24
|
+
export function extractSstConstructs(sourceText, file) {
|
|
25
|
+
return extractPulumiResources(sourceText, file)
|
|
26
|
+
.filter((r) => providerOf(r.resourceType) === SST_PROVIDER)
|
|
27
|
+
.map((r) => {
|
|
28
|
+
const construct = r.resourceType;
|
|
29
|
+
const lastDot = construct.lastIndexOf('.');
|
|
30
|
+
const constructType = lastDot === -1 ? construct : construct.slice(lastDot + 1);
|
|
31
|
+
// refAddr = `${construct}.${logicalName}` → recover the logical name (which
|
|
32
|
+
// may itself contain ':' in the non-literal-name fallback, so slice, not split).
|
|
33
|
+
const name = r.refAddr.slice(construct.length + 1);
|
|
34
|
+
return {
|
|
35
|
+
construct,
|
|
36
|
+
constructType,
|
|
37
|
+
name,
|
|
38
|
+
refAddr: r.refAddr,
|
|
39
|
+
...(r.varName ? { varName: r.varName } : {}),
|
|
40
|
+
referencedIdentifiers: r.referencedIdentifiers,
|
|
41
|
+
argsText: r.argsText,
|
|
42
|
+
};
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=sst-parse.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sst-parse.js","sourceRoot":"","sources":["../../../src/infra/sst/sst-parse.ts"],"names":[],"mappings":"AAAA,qDAAqD;AACrD,EAAE;AACF,6EAA6E;AAC7E,6EAA6E;AAC7E,+EAA+E;AAC/E,4EAA4E;AAC5E,gFAAgF;AAChF,kFAAkF;AAClF,+DAA+D;AAC/D,EAAE;AACF,6EAA6E;AAC7E,oFAAoF;AACpF,iFAAiF;AACjF,uEAAuE;AAEvE,OAAO,EAAE,sBAAsB,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAE/E,uFAAuF;AACvF,MAAM,YAAY,GAAG,KAAK,CAAC;AAoB3B;;;;;GAKG;AACH,MAAM,UAAU,oBAAoB,CAAC,UAAkB,EAAE,IAAY;IACnE,OAAO,sBAAsB,CAAC,UAAU,EAAE,IAAI,CAAC;SAC5C,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,YAAY,CAAC,KAAK,YAAY,CAAC;SAC1D,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;QACT,MAAM,SAAS,GAAG,CAAC,CAAC,YAAY,CAAC;QACjC,MAAM,OAAO,GAAG,SAAS,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;QAC3C,MAAM,aAAa,GAAG,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC;QAChF,4EAA4E;QAC5E,iFAAiF;QACjF,MAAM,IAAI,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QACnD,OAAO;YACL,SAAS;YACT,aAAa;YACb,IAAI;YACJ,OAAO,EAAE,CAAC,CAAC,OAAO;YAClB,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC5C,qBAAqB,EAAE,CAAC,CAAC,qBAAqB;YAC9C,QAAQ,EAAE,CAAC,CAAC,QAAQ;SACrB,CAAC;IACJ,CAAC,CAAC,CAAC;AACP,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { InfraAdapter, InfraGraph } from '../types.js';
|
|
2
|
+
import type { InfraModuleKind } from '../../types.js';
|
|
3
|
+
import { type DockerfileIndex } from '../image-resolve.js';
|
|
4
|
+
import { type SstConstruct } from './sst-parse.js';
|
|
5
|
+
/** The InfraModuleKind for an SST construct type, or null when unrecognized. */
|
|
6
|
+
export declare function sstKind(constructType: string): InfraModuleKind | null;
|
|
7
|
+
/**
|
|
8
|
+
* The repo-relative source roots an SST construct deploys, from its props-args
|
|
9
|
+
* text. Kind-aware so a static-site's `path:` and a route's `path:` can't
|
|
10
|
+
* cross-contaminate. `dockerfileIndex` powers the image→source resolver. Pure.
|
|
11
|
+
*/
|
|
12
|
+
export declare function sstSourceRoots(kind: InfraModuleKind, argsText: string, dockerfileIndex?: DockerfileIndex): string[];
|
|
13
|
+
export declare function buildSstGraph({ constructs, root, dockerfileIndex, }: {
|
|
14
|
+
constructs: SstConstruct[];
|
|
15
|
+
root: string;
|
|
16
|
+
dockerfileIndex?: DockerfileIndex;
|
|
17
|
+
}): InfraGraph;
|
|
18
|
+
export declare const sstAdapter: InfraAdapter;
|
|
19
|
+
//# sourceMappingURL=sst.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sst.d.ts","sourceRoot":"","sources":["../../../src/infra/sst/sst.ts"],"names":[],"mappings":"AA0CA,OAAO,KAAK,EAAE,YAAY,EAAa,UAAU,EAAa,MAAM,aAAa,CAAC;AAClF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACtD,OAAO,EAAmD,KAAK,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAC5G,OAAO,EAAwB,KAAK,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAwBzE,gFAAgF;AAChF,wBAAgB,OAAO,CAAC,aAAa,EAAE,MAAM,GAAG,eAAe,GAAG,IAAI,CAGrE;AAiCD;;;;GAIG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,eAAe,EACrB,QAAQ,EAAE,MAAM,EAChB,eAAe,CAAC,EAAE,eAAe,GAChC,MAAM,EAAE,CAgCV;AAcD,wBAAgB,aAAa,CAAC,EAC5B,UAAU,EACV,IAAI,EACJ,eAAe,GAChB,EAAE;IACD,UAAU,EAAE,YAAY,EAAE,CAAC;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,eAAe,CAAC,EAAE,eAAe,CAAC;CACnC,GAAG,UAAU,CAoDb;AAaD,eAAO,MAAM,UAAU,EAAE,YAmBxB,CAAC"}
|