diff --git a/PLACEMENT-MAP.md b/PLACEMENT-MAP.md index 64fe4014e..7cf882dcd 100644 --- a/PLACEMENT-MAP.md +++ b/PLACEMENT-MAP.md @@ -10,7 +10,7 @@ Coverage: **175/175** dev pages mapped (161 high / 13 med / 1 flag). Source: `de | section | why | |---|---| | **Core concepts** (`/concepts/`) | Jordan (Jul-15): jobs, components-as-concept, multi-project are concepts, not features; today they hide under Management/Catalog. Start with `/concepts/jobs/` (+ api-basics if approved). | -| **Components › Development** (`/components/development/`) | topic home for build-a-component, Common Interface, publishing, encryption — peers of the components they produce. | +| ~~**Components › Development** (`/components/development/`)~~ **superseded** → **Extending Keboola** (`/extend/`) | Jordan approved `/extend/` as its own top-level section instead (#1046, merged 2026-07-29, commit `8504c9dd`). Dev `/extend/**` paths are preserved 1:1, so these are identity redirects across domains. | | **Storage › Storage API** (`/storage/api/`) | Storage owns its API reference + clients. | | **CLI › Keboola as Code CLI** (`/cli/keboola-as-code/`) | dev CLI relabelled, `:::caution[Deprecated]` → kbagent; content untouched. | @@ -93,44 +93,44 @@ Coverage: **175/175** dev pages mapped (161 high / 13 med / 1 flag). Source: `de | `cli/index.md` | `/cli/` | CLI → Keboola as Code CLI | `/cli/keboola-as-code/` | reference | high | — — rename only + :::caution[Deprecated] → kbagent CLI on index | | `cli/installation/index.md` | `/cli/installation/` | CLI → Keboola as Code CLI | `/cli/keboola-as-code/installation/` | reference | high | — — rename only + :::caution[Deprecated] → kbagent CLI on index | | `cli/structure/index.md` | `/cli/structure/` | CLI → Keboola as Code CLI | `/cli/keboola-as-code/structure/` | reference | high | — — rename only + :::caution[Deprecated] → kbagent CLI on index | -| `extend/common-interface/actions.md` | `/extend/common-interface/actions/` | Components › Development | `/components/development/common-interface/actions/` | reference | high | — | -| `extend/common-interface/config-file.md` | `/extend/common-interface/config-file/` | Components › Development | `/components/development/common-interface/config-file/` | reference | high | — | -| `extend/common-interface/development-branches.md` | `/extend/common-interface/development-branches/` | Components › Development | `/components/development/common-interface/development-branches/` | reference | high | — | -| `extend/common-interface/environment.md` | `/extend/common-interface/environment/` | Components › Development | `/components/development/common-interface/environment/` | reference | high | — | -| `extend/common-interface/folders.md` | `/extend/common-interface/folders/` | Components › Development | `/components/development/common-interface/folders/` | reference | high | — | -| `extend/common-interface/index.md` | `/extend/common-interface/` | Components › Development | `/components/development/common-interface/` | reference | high | — | -| `extend/common-interface/logging.md` | `/extend/common-interface/logging/` | Components › Development | `/components/development/common-interface/logging/` | reference | high | — | -| `extend/common-interface/manifest-files/in-files-abs-staging.md` | `/extend/common-interface/manifest-files/in-files-abs-staging/` | Components › Development | `/components/development/common-interface/manifest-files/in-files-abs-staging/` | reference | high | — | -| `extend/common-interface/manifest-files/in-files-manifests.md` | `/extend/common-interface/manifest-files/in-files-manifests/` | Components › Development | `/components/development/common-interface/manifest-files/in-files-manifests/` | reference | high | — | -| `extend/common-interface/manifest-files/in-files-s3-staging.md` | `/extend/common-interface/manifest-files/in-files-s3-staging/` | Components › Development | `/components/development/common-interface/manifest-files/in-files-s3-staging/` | reference | high | — | -| `extend/common-interface/manifest-files/in-tables-manifests.md` | `/extend/common-interface/manifest-files/in-tables-manifests/` | Components › Development | `/components/development/common-interface/manifest-files/in-tables-manifests/` | reference | high | — | -| `extend/common-interface/manifest-files/out-files-manifests.md` | `/extend/common-interface/manifest-files/out-files-manifests/` | Components › Development | `/components/development/common-interface/manifest-files/out-files-manifests/` | reference | high | — | -| `extend/common-interface/manifest-files/out-tables-manifests-native-types.md` | `/extend/common-interface/manifest-files/out-tables-manifests-native-types/` | Components › Development | `/components/development/common-interface/manifest-files/out-tables-manifests-native-types/` | reference | high | — | -| `extend/common-interface/manifest-files/out-tables-manifests.md` | `/extend/common-interface/manifest-files/out-tables-manifests/` | Components › Development | `/components/development/common-interface/manifest-files/out-tables-manifests/` | reference | high | — | -| `extend/common-interface/manifest-files.md` | `/extend/common-interface/manifest-files/` | Components › Development | `/components/development/common-interface/manifest-files/` | reference | high | — | -| `extend/common-interface/oauth.md` | `/extend/common-interface/oauth/` | Components › Development | `/components/development/common-interface/oauth/` | reference | high | — | -| `extend/component/code-patterns/index.md` | `/extend/component/code-patterns/` | Components › Development | `/components/development/component/code-patterns/` | mixed (tutorial+ref) | high | — — build-a-component tree | -| `extend/component/code-patterns/interface.md` | `/extend/component/code-patterns/interface/` | Components › Development | `/components/development/component/code-patterns/interface/` | mixed (tutorial+ref) | high | — — build-a-component tree | -| `extend/component/code-patterns/tutorial.md` | `/extend/component/code-patterns/tutorial/` | Components › Development | `/components/development/component/code-patterns/tutorial/` | mixed (tutorial+ref) | high | — — build-a-component tree | -| `extend/component/deployment/index.md` | `/extend/component/deployment/` | Components › Development | `/components/development/component/deployment/` | mixed (tutorial+ref) | high | — — build-a-component tree | -| `extend/component/implementation/index.md` | `/extend/component/implementation/` | Components › Development | `/components/development/component/implementation/` | mixed (tutorial+ref) | high | — — build-a-component tree | -| `extend/component/implementation/php.md` | `/extend/component/implementation/php/` | Components › Development | `/components/development/component/implementation/php/` | mixed (tutorial+ref) | high | — — build-a-component tree | -| `extend/component/implementation/python.md` | `/extend/component/implementation/python/` | Components › Development | `/components/development/component/implementation/python/` | mixed (tutorial+ref) | high | — — build-a-component tree | -| `extend/component/implementation/r.md` | `/extend/component/implementation/r/` | Components › Development | `/components/development/component/implementation/r/` | mixed (tutorial+ref) | high | — — build-a-component tree | -| `extend/component/index.md` | `/extend/component/` | Components › Development | `/components/development/component/` | mixed (tutorial+ref) | high | — — build-a-component tree | -| `extend/component/processors.md` | `/extend/component/processors/` | Components › Development | `/components/development/component/processors/` | mixed (tutorial+ref) | high | — — build-a-component tree | -| `extend/component/running/index.md` | `/extend/component/running/` | Components › Development | `/components/development/component/running/` | mixed (tutorial+ref) | high | — — build-a-component tree | -| `extend/component/tutorial/configuration.md` | `/extend/component/tutorial/configuration/` | Components › Development | `/components/development/component/tutorial/configuration/` | mixed (tutorial+ref) | high | — — build-a-component tree | -| `extend/component/tutorial/debugging.md` | `/extend/component/tutorial/debugging/` | Components › Development | `/components/development/component/tutorial/debugging/` | mixed (tutorial+ref) | high | — — build-a-component tree | -| `extend/component/tutorial/index.md` | `/extend/component/tutorial/` | Components › Development | `/components/development/component/tutorial/` | mixed (tutorial+ref) | high | — — build-a-component tree | -| `extend/component/tutorial/input-mapping.md` | `/extend/component/tutorial/input-mapping/` | Components › Development | `/components/development/component/tutorial/input-mapping/` | mixed (tutorial+ref) | high | — — build-a-component tree | -| `extend/component/tutorial/output-mapping.md` | `/extend/component/tutorial/output-mapping/` | Components › Development | `/components/development/component/tutorial/output-mapping/` | mixed (tutorial+ref) | high | — — build-a-component tree | -| `extend/component/tutorial/processors.md` | `/extend/component/tutorial/processors/` | Components › Development | `/components/development/component/tutorial/processors/` | mixed (tutorial+ref) | high | — — build-a-component tree | -| `extend/component/ui-options/configuration-schema.md` | `/extend/component/ui-options/configuration-schema/` | Components › Development | `/components/development/component/ui-options/configuration-schema/` | mixed (tutorial+ref) | high | — — build-a-component tree | -| `extend/component/ui-options/default-configuration/index.md` | `/extend/component/ui-options/default-configuration/` | Components › Development | `/components/development/component/ui-options/default-configuration/` | mixed (tutorial+ref) | high | — — build-a-component tree | -| `extend/component/ui-options/index.md` | `/extend/component/ui-options/` | Components › Development | `/components/development/component/ui-options/` | mixed (tutorial+ref) | high | — — build-a-component tree | -| `extend/component/ui-options/ui-examples/configuration-schema-examples.md` | `/extend/component/ui-options/configuration-schema/examples/` | Components › Development | `/components/development/component/ui-options/configuration-schema/examples/` | mixed (tutorial+ref) | high | — — build-a-component tree | -| `extend/component/ui-options/ui-examples/sync-action-examples.md` | `/extend/component/ui-options/configuration-schema/sync-action-examples/` | Components › Development | `/components/development/component/ui-options/configuration-schema/sync-action-examples/` | mixed (tutorial+ref) | high | — — build-a-component tree | +| `extend/common-interface/actions.md` | `/extend/common-interface/actions/` | Extending Keboola | `/extend/common-interface/actions/` | reference | high | — | +| `extend/common-interface/config-file.md` | `/extend/common-interface/config-file/` | Extending Keboola | `/extend/common-interface/config-file/` | reference | high | — | +| `extend/common-interface/development-branches.md` | `/extend/common-interface/development-branches/` | Extending Keboola | `/extend/common-interface/development-branches/` | reference | high | — | +| `extend/common-interface/environment.md` | `/extend/common-interface/environment/` | Extending Keboola | `/extend/common-interface/environment/` | reference | high | — | +| `extend/common-interface/folders.md` | `/extend/common-interface/folders/` | Extending Keboola | `/extend/common-interface/folders/` | reference | high | — | +| `extend/common-interface/index.md` | `/extend/common-interface/` | Extending Keboola | `/extend/common-interface/` | reference | high | — | +| `extend/common-interface/logging.md` | `/extend/common-interface/logging/` | Extending Keboola | `/extend/common-interface/logging/` | reference | high | — | +| `extend/common-interface/manifest-files/in-files-abs-staging.md` | `/extend/common-interface/manifest-files/in-files-abs-staging/` | Extending Keboola | `/extend/common-interface/manifest-files/in-files-abs-staging/` | reference | high | — | +| `extend/common-interface/manifest-files/in-files-manifests.md` | `/extend/common-interface/manifest-files/in-files-manifests/` | Extending Keboola | `/extend/common-interface/manifest-files/in-files-manifests/` | reference | high | — | +| `extend/common-interface/manifest-files/in-files-s3-staging.md` | `/extend/common-interface/manifest-files/in-files-s3-staging/` | Extending Keboola | `/extend/common-interface/manifest-files/in-files-s3-staging/` | reference | high | — | +| `extend/common-interface/manifest-files/in-tables-manifests.md` | `/extend/common-interface/manifest-files/in-tables-manifests/` | Extending Keboola | `/extend/common-interface/manifest-files/in-tables-manifests/` | reference | high | — | +| `extend/common-interface/manifest-files/out-files-manifests.md` | `/extend/common-interface/manifest-files/out-files-manifests/` | Extending Keboola | `/extend/common-interface/manifest-files/out-files-manifests/` | reference | high | — | +| `extend/common-interface/manifest-files/out-tables-manifests-native-types.md` | `/extend/common-interface/manifest-files/out-tables-manifests-native-types/` | Extending Keboola | `/extend/common-interface/manifest-files/out-tables-manifests-native-types/` | reference | high | — | +| `extend/common-interface/manifest-files/out-tables-manifests.md` | `/extend/common-interface/manifest-files/out-tables-manifests/` | Extending Keboola | `/extend/common-interface/manifest-files/out-tables-manifests/` | reference | high | — | +| `extend/common-interface/manifest-files.md` | `/extend/common-interface/manifest-files/` | Extending Keboola | `/extend/common-interface/manifest-files/` | reference | high | — | +| `extend/common-interface/oauth.md` | `/extend/common-interface/oauth/` | Extending Keboola | `/extend/common-interface/oauth/` | reference | high | — | +| `extend/component/code-patterns/index.md` | `/extend/component/code-patterns/` | Extending Keboola | `/extend/component/code-patterns/` | mixed (tutorial+ref) | high | — — build-a-component tree | +| `extend/component/code-patterns/interface.md` | `/extend/component/code-patterns/interface/` | Extending Keboola | `/extend/component/code-patterns/interface/` | mixed (tutorial+ref) | high | — — build-a-component tree | +| `extend/component/code-patterns/tutorial.md` | `/extend/component/code-patterns/tutorial/` | Extending Keboola | `/extend/component/code-patterns/tutorial/` | mixed (tutorial+ref) | high | — — build-a-component tree | +| `extend/component/deployment/index.md` | `/extend/component/deployment/` | Extending Keboola | `/extend/component/deployment/` | mixed (tutorial+ref) | high | — — build-a-component tree | +| `extend/component/implementation/index.md` | `/extend/component/implementation/` | Extending Keboola | `/extend/component/implementation/` | mixed (tutorial+ref) | high | — — build-a-component tree | +| `extend/component/implementation/php.md` | `/extend/component/implementation/php/` | Extending Keboola | `/extend/component/implementation/php/` | mixed (tutorial+ref) | high | — — build-a-component tree | +| `extend/component/implementation/python.md` | `/extend/component/implementation/python/` | Extending Keboola | `/extend/component/implementation/python/` | mixed (tutorial+ref) | high | — — build-a-component tree | +| `extend/component/implementation/r.md` | `/extend/component/implementation/r/` | Extending Keboola | `/extend/component/implementation/r/` | mixed (tutorial+ref) | high | — — build-a-component tree | +| `extend/component/index.md` | `/extend/component/` | Extending Keboola | `/extend/component/` | mixed (tutorial+ref) | high | — — build-a-component tree | +| `extend/component/processors.md` | `/extend/component/processors/` | Extending Keboola | `/extend/component/processors/` | mixed (tutorial+ref) | high | — — build-a-component tree | +| `extend/component/running/index.md` | `/extend/component/running/` | Extending Keboola | `/extend/component/running/` | mixed (tutorial+ref) | high | — — build-a-component tree | +| `extend/component/tutorial/configuration.md` | `/extend/component/tutorial/configuration/` | Extending Keboola | `/extend/component/tutorial/configuration/` | mixed (tutorial+ref) | high | — — build-a-component tree | +| `extend/component/tutorial/debugging.md` | `/extend/component/tutorial/debugging/` | Extending Keboola | `/extend/component/tutorial/debugging/` | mixed (tutorial+ref) | high | — — build-a-component tree | +| `extend/component/tutorial/index.md` | `/extend/component/tutorial/` | Extending Keboola | `/extend/component/tutorial/` | mixed (tutorial+ref) | high | — — build-a-component tree | +| `extend/component/tutorial/input-mapping.md` | `/extend/component/tutorial/input-mapping/` | Extending Keboola | `/extend/component/tutorial/input-mapping/` | mixed (tutorial+ref) | high | — — build-a-component tree | +| `extend/component/tutorial/output-mapping.md` | `/extend/component/tutorial/output-mapping/` | Extending Keboola | `/extend/component/tutorial/output-mapping/` | mixed (tutorial+ref) | high | — — build-a-component tree | +| `extend/component/tutorial/processors.md` | `/extend/component/tutorial/processors/` | Extending Keboola | `/extend/component/tutorial/processors/` | mixed (tutorial+ref) | high | — — build-a-component tree | +| `extend/component/ui-options/configuration-schema.md` | `/extend/component/ui-options/configuration-schema/` | Extending Keboola | `/extend/component/ui-options/configuration-schema/` | mixed (tutorial+ref) | high | — — build-a-component tree | +| `extend/component/ui-options/default-configuration/index.md` | `/extend/component/ui-options/default-configuration/` | Extending Keboola | `/extend/component/ui-options/default-configuration/` | mixed (tutorial+ref) | high | — — build-a-component tree | +| `extend/component/ui-options/index.md` | `/extend/component/ui-options/` | Extending Keboola | `/extend/component/ui-options/` | mixed (tutorial+ref) | high | — — build-a-component tree | +| `extend/component/ui-options/ui-examples/configuration-schema-examples.md` | `/extend/component/ui-options/configuration-schema/examples/` | Extending Keboola | `/extend/component/ui-options/configuration-schema/examples/` | mixed (tutorial+ref) | high | — — build-a-component tree | +| `extend/component/ui-options/ui-examples/sync-action-examples.md` | `/extend/component/ui-options/configuration-schema/sync-action-examples/` | Extending Keboola | `/extend/component/ui-options/configuration-schema/sync-action-examples/` | mixed (tutorial+ref) | high | — — build-a-component tree | | `extend/generic-extractor/configuration/api/authentication/api_key.md` | `/extend/generic-extractor/configuration/api/authentication/api_key/` | Components › Data Source Connectors | `/components/extractors/generic-extractor/configuration/api/authentication/api_key/` | reference | high | — — GE is a component; lives with extractors | | `extend/generic-extractor/configuration/api/authentication/basic.md` | `/extend/generic-extractor/configuration/api/authentication/basic/` | Components › Data Source Connectors | `/components/extractors/generic-extractor/configuration/api/authentication/basic/` | reference | high | — — GE is a component; lives with extractors | | `extend/generic-extractor/configuration/api/authentication/bearer_token.md` | `/extend/generic-extractor/configuration/api/authentication/bearer_token/` | Components › Data Source Connectors | `/components/extractors/generic-extractor/configuration/api/authentication/bearer_token/` | reference | high | — — GE is a component; lives with extractors | @@ -173,10 +173,10 @@ Coverage: **175/175** dev pages mapped (161 high / 13 med / 1 flag). Source: `de | `extend/generic-writer/configuration/configuration-examples.md` | `/extend/generic-writer/configuration-examples/` | Components › Data Destination Connectors | `/components/writers/generic-writer/configuration-examples/` | reference | high | — | | `extend/generic-writer/configuration/configuration.md` | `/extend/generic-writer/configuration/` | Components › Data Destination Connectors | `/components/writers/generic-writer/configuration/` | reference | high | — | | `extend/generic-writer/index.md` | `/extend/generic-writer/` | Components › Data Destination Connectors | `/components/writers/generic-writer/` | reference | high | — | -| `extend/index.md` | `/extend/` | Components › Development | `/components/development/` | explanation | high | — — section landing | -| `extend/job-queue/index.md` | `/extend/job-queue/` | Components › Development | `/components/development/job-queue/` | reference | med | — — UNSURE: could live under Core concepts › Jobs instead | -| `extend/publish/checklist.md` | `/extend/publish/checklist/` | Components › Development | `/components/development/publish/checklist/` | how-to | high | — — marketplace publishing | -| `extend/publish/index.md` | `/extend/publish/` | Components › Development | `/components/development/publish/` | how-to | high | — — marketplace publishing | +| `extend/index.md` | `/extend/` | Extending Keboola | `/extend/` | explanation | high | — — section landing | +| `extend/job-queue/index.md` | `/extend/job-queue/` | Extending Keboola | `/extend/job-queue/` | reference | med | — — UNSURE: could live under Core concepts › Jobs instead | +| `extend/publish/checklist.md` | `/extend/publish/checklist/` | Extending Keboola | `/extend/publish/checklist/` | how-to | high | — — marketplace publishing | +| `extend/publish/index.md` | `/extend/publish/` | Extending Keboola | `/extend/publish/` | how-to | high | — — marketplace publishing | | `index.md` | `/` | — (weave done: PR #1022) | `/` | explanation | high | MERGED → help home — home combined in #1022 | | `integrate/artifacts/index.md` | `/integrate/artifacts/` | Components › Development | `/components/development/artifacts/` | reference | med | — — UNSURE: artifacts = component-level feature; alt: /storage/files/ | | `integrate/artifacts/tutorial.md` | `/integrate/artifacts/tutorial/` | Components › Development | `/components/development/artifacts/tutorial/` | reference | med | — — UNSURE: artifacts = component-level feature; alt: /storage/files/ | diff --git a/_data/redirects/dev-to-help.tsv b/_data/redirects/dev-to-help.tsv new file mode 100644 index 000000000..b655a8c0b --- /dev/null +++ b/_data/redirects/dev-to-help.tsv @@ -0,0 +1,177 @@ +# generated by scripts/check-redirects.mjs --gen from PLACEMENT-MAP.md — do not hand-edit +# dev_path final_help_path status +/404.html dies +/automate/ /flows/ redirect +/automate/run-job/ /concepts/jobs/run-a-job/ unsure +/automate/run-orchestration/ /flows/run-via-api/ moved +/automate/set-schedule/ /flows/set-schedule-api/ unsure +/cli/commands/ci/ /cli/keboola-as-code/commands/ci/ moved +/cli/commands/ci/workflows/ /cli/keboola-as-code/commands/ci/workflows/ moved +/cli/commands/dbt/generate/env/ /cli/keboola-as-code/commands/dbt/generate/env/ moved +/cli/commands/dbt/generate/ /cli/keboola-as-code/commands/dbt/generate/ moved +/cli/commands/dbt/generate/profile/ /cli/keboola-as-code/commands/dbt/generate/profile/ moved +/cli/commands/dbt/generate/sources/ /cli/keboola-as-code/commands/dbt/generate/sources/ moved +/cli/commands/dbt/ /cli/keboola-as-code/commands/dbt/ moved +/cli/commands/dbt/init/ /cli/keboola-as-code/commands/dbt/init/ moved +/cli/commands/help/ /cli/keboola-as-code/commands/help/ moved +/cli/commands/ /cli/keboola-as-code/commands/ moved +/cli/commands/llm/export/ /cli/keboola-as-code/commands/llm/export/ moved +/cli/commands/llm/ /cli/keboola-as-code/commands/llm/ moved +/cli/commands/llm/init/ /cli/keboola-as-code/commands/llm/init/ moved +/cli/commands/local/create/config/ /cli/keboola-as-code/commands/local/create/config/ moved +/cli/commands/local/create/ /cli/keboola-as-code/commands/local/create/ moved +/cli/commands/local/create/row/ /cli/keboola-as-code/commands/local/create/row/ moved +/cli/commands/local/encrypt/ /cli/keboola-as-code/commands/local/encrypt/ moved +/cli/commands/local/fix-paths/ /cli/keboola-as-code/commands/local/fix-paths/ moved +/cli/commands/local/ /cli/keboola-as-code/commands/local/ moved +/cli/commands/local/persist/ /cli/keboola-as-code/commands/local/persist/ moved +/cli/commands/local/validate/config/ /cli/keboola-as-code/commands/local/validate/config/ moved +/cli/commands/local/validate/ /cli/keboola-as-code/commands/local/validate/ moved +/cli/commands/local/validate/row/ /cli/keboola-as-code/commands/local/validate/row/ moved +/cli/commands/local/validate/schema/ /cli/keboola-as-code/commands/local/validate/schema/ moved +/cli/commands/remote/create/branch/ /cli/keboola-as-code/commands/remote/create/branch/ moved +/cli/commands/remote/create/bucket/ /cli/keboola-as-code/commands/remote/create/bucket/ moved +/cli/commands/remote/create/ /cli/keboola-as-code/commands/remote/create/ moved +/cli/commands/remote/file/download/ /cli/keboola-as-code/commands/remote/file/download/ moved +/cli/commands/remote/file/ /cli/keboola-as-code/commands/remote/file/ moved +/cli/commands/remote/file/upload/ /cli/keboola-as-code/commands/remote/file/upload/ moved +/cli/commands/remote/ /cli/keboola-as-code/commands/remote/ moved +/cli/commands/remote/job/ /cli/keboola-as-code/commands/remote/job/ moved +/cli/commands/remote/job/run/ /cli/keboola-as-code/commands/remote/job/run/ moved +/cli/commands/remote/table/create/ /cli/keboola-as-code/commands/remote/table/create/ moved +/cli/commands/remote/table/detail/ /cli/keboola-as-code/commands/remote/table/detail/ moved +/cli/commands/remote/table/download/ /cli/keboola-as-code/commands/remote/table/download/ moved +/cli/commands/remote/table/import/ /cli/keboola-as-code/commands/remote/table/import/ moved +/cli/commands/remote/table/ /cli/keboola-as-code/commands/remote/table/ moved +/cli/commands/remote/table/preview/ /cli/keboola-as-code/commands/remote/table/preview/ moved +/cli/commands/remote/table/unload/ /cli/keboola-as-code/commands/remote/table/unload/ moved +/cli/commands/remote/table/upload/ /cli/keboola-as-code/commands/remote/table/upload/ moved +/cli/commands/remote/workspace/create/ /cli/keboola-as-code/commands/remote/workspace/create/ moved +/cli/commands/remote/workspace/delete/ /cli/keboola-as-code/commands/remote/workspace/delete/ moved +/cli/commands/remote/workspace/detail/ /cli/keboola-as-code/commands/remote/workspace/detail/ moved +/cli/commands/remote/workspace/ /cli/keboola-as-code/commands/remote/workspace/ moved +/cli/commands/remote/workspace/list/ /cli/keboola-as-code/commands/remote/workspace/list/ moved +/cli/commands/status/ /cli/keboola-as-code/commands/status/ moved +/cli/commands/sync/diff/ /cli/keboola-as-code/commands/sync/diff/ moved +/cli/commands/sync/ /cli/keboola-as-code/commands/sync/ moved +/cli/commands/sync/init/ /cli/keboola-as-code/commands/sync/init/ moved +/cli/commands/sync/pull/ /cli/keboola-as-code/commands/sync/pull/ moved +/cli/commands/sync/push/ /cli/keboola-as-code/commands/sync/push/ moved +/cli/dbt/ /cli/keboola-as-code/dbt/ moved +/cli/devops-use-cases/ /cli/keboola-as-code/devops-use-cases/ moved +/cli/getting-started/ /cli/keboola-as-code/getting-started/ moved +/cli/github-integration/ /cli/keboola-as-code/github-integration/ moved +/cli/ /cli/keboola-as-code/ moved +/cli/installation/ /cli/keboola-as-code/installation/ moved +/cli/structure/ /cli/keboola-as-code/structure/ moved +/extend/common-interface/actions/ /extend/common-interface/actions/ moved +/extend/common-interface/config-file/ /extend/common-interface/config-file/ moved +/extend/common-interface/development-branches/ /extend/common-interface/development-branches/ moved +/extend/common-interface/environment/ /extend/common-interface/environment/ moved +/extend/common-interface/folders/ /extend/common-interface/folders/ moved +/extend/common-interface/ /extend/common-interface/ moved +/extend/common-interface/logging/ /extend/common-interface/logging/ moved +/extend/common-interface/manifest-files/in-files-abs-staging/ /extend/common-interface/manifest-files/in-files-abs-staging/ moved +/extend/common-interface/manifest-files/in-files-manifests/ /extend/common-interface/manifest-files/in-files-manifests/ moved +/extend/common-interface/manifest-files/in-files-s3-staging/ /extend/common-interface/manifest-files/in-files-s3-staging/ moved +/extend/common-interface/manifest-files/in-tables-manifests/ /extend/common-interface/manifest-files/in-tables-manifests/ moved +/extend/common-interface/manifest-files/out-files-manifests/ /extend/common-interface/manifest-files/out-files-manifests/ moved +/extend/common-interface/manifest-files/out-tables-manifests-native-types/ /extend/common-interface/manifest-files/out-tables-manifests-native-types/ moved +/extend/common-interface/manifest-files/out-tables-manifests/ /extend/common-interface/manifest-files/out-tables-manifests/ moved +/extend/common-interface/manifest-files/ /extend/common-interface/manifest-files/ moved +/extend/common-interface/oauth/ /extend/common-interface/oauth/ moved +/extend/component/code-patterns/ /extend/component/code-patterns/ moved +/extend/component/code-patterns/interface/ /extend/component/code-patterns/interface/ moved +/extend/component/code-patterns/tutorial/ /extend/component/code-patterns/tutorial/ moved +/extend/component/deployment/ /extend/component/deployment/ moved +/extend/component/implementation/ /extend/component/implementation/ moved +/extend/component/implementation/php/ /extend/component/implementation/php/ moved +/extend/component/implementation/python/ /extend/component/implementation/python/ moved +/extend/component/implementation/r/ /extend/component/implementation/r/ moved +/extend/component/ /extend/component/ moved +/extend/component/processors/ /extend/component/processors/ moved +/extend/component/running/ /extend/component/running/ moved +/extend/component/tutorial/configuration/ /extend/component/tutorial/configuration/ moved +/extend/component/tutorial/debugging/ /extend/component/tutorial/debugging/ moved +/extend/component/tutorial/ /extend/component/tutorial/ moved +/extend/component/tutorial/input-mapping/ /extend/component/tutorial/input-mapping/ moved +/extend/component/tutorial/output-mapping/ /extend/component/tutorial/output-mapping/ moved +/extend/component/tutorial/processors/ /extend/component/tutorial/processors/ moved +/extend/component/ui-options/configuration-schema/ /extend/component/ui-options/configuration-schema/ moved +/extend/component/ui-options/default-configuration/ /extend/component/ui-options/default-configuration/ moved +/extend/component/ui-options/ /extend/component/ui-options/ moved +/extend/component/ui-options/configuration-schema/examples/ /extend/component/ui-options/configuration-schema/examples/ moved +/extend/component/ui-options/configuration-schema/sync-action-examples/ /extend/component/ui-options/configuration-schema/sync-action-examples/ moved +/extend/generic-extractor/configuration/api/authentication/api_key/ /components/extractors/generic-extractor/configuration/api/authentication/api_key/ moved +/extend/generic-extractor/configuration/api/authentication/basic/ /components/extractors/generic-extractor/configuration/api/authentication/basic/ moved +/extend/generic-extractor/configuration/api/authentication/bearer_token/ /components/extractors/generic-extractor/configuration/api/authentication/bearer_token/ moved +/extend/generic-extractor/configuration/api/authentication/ /components/extractors/generic-extractor/configuration/api/authentication/ moved +/extend/generic-extractor/configuration/api/authentication/login/ /components/extractors/generic-extractor/configuration/api/authentication/login/ moved +/extend/generic-extractor/configuration/api/authentication/oauth10/ /components/extractors/generic-extractor/configuration/api/authentication/oauth10/ moved +/extend/generic-extractor/configuration/api/authentication/oauth20-login/ /components/extractors/generic-extractor/configuration/api/authentication/oauth20-login/ moved +/extend/generic-extractor/configuration/api/authentication/oauth20/ /components/extractors/generic-extractor/configuration/api/authentication/oauth20/ moved +/extend/generic-extractor/configuration/api/authentication/oauth_cc/ /components/extractors/generic-extractor/configuration/api/authentication/oauth_cc/ moved +/extend/generic-extractor/configuration/api/authentication/query/ /components/extractors/generic-extractor/configuration/api/authentication/query/ moved +/extend/generic-extractor/configuration/api/ /components/extractors/generic-extractor/configuration/api/ moved +/extend/generic-extractor/configuration/api/pagination/cursor/ /components/extractors/generic-extractor/configuration/api/pagination/cursor/ moved +/extend/generic-extractor/configuration/api/pagination/ /components/extractors/generic-extractor/configuration/api/pagination/ moved +/extend/generic-extractor/configuration/api/pagination/multiple/ /components/extractors/generic-extractor/configuration/api/pagination/multiple/ moved +/extend/generic-extractor/configuration/api/pagination/offset/ /components/extractors/generic-extractor/configuration/api/pagination/offset/ moved +/extend/generic-extractor/configuration/api/pagination/pagenum/ /components/extractors/generic-extractor/configuration/api/pagination/pagenum/ moved +/extend/generic-extractor/configuration/api/pagination/response-param/ /components/extractors/generic-extractor/configuration/api/pagination/response-param/ moved +/extend/generic-extractor/configuration/api/pagination/response-url/ /components/extractors/generic-extractor/configuration/api/pagination/response-url/ moved +/extend/generic-extractor/configuration/aws-signature/ /components/extractors/generic-extractor/configuration/aws-signature/ moved +/extend/generic-extractor/configuration/config/ /components/extractors/generic-extractor/configuration/config/ moved +/extend/generic-extractor/configuration/config/jobs/children/ /components/extractors/generic-extractor/configuration/config/jobs/children/ moved +/extend/generic-extractor/configuration/config/jobs/ /components/extractors/generic-extractor/configuration/config/jobs/ moved +/extend/generic-extractor/configuration/config/mappings/ /components/extractors/generic-extractor/configuration/config/mappings/ moved +/extend/generic-extractor/configuration/ /components/extractors/generic-extractor/configuration/ moved +/extend/generic-extractor/configuration/iterations/ /components/extractors/generic-extractor/configuration/iterations/ moved +/extend/generic-extractor/configuration/ssh-proxy/ /components/extractors/generic-extractor/configuration/ssh-proxy/ moved +/extend/generic-extractor/functions/ /components/extractors/generic-extractor/functions/ moved +/extend/generic-extractor/incremental/ /components/extractors/generic-extractor/incremental/ moved +/extend/generic-extractor/ /components/extractors/generic-extractor/ moved +/extend/generic-extractor/map/ /components/extractors/generic-extractor/map/ moved +/extend/generic-extractor/publish/ /components/extractors/generic-extractor/publish/ moved +/extend/generic-extractor/running/ /components/extractors/generic-extractor/running/ moved +/extend/generic-extractor/tutorial/basic/ /components/extractors/generic-extractor/tutorial/basic/ moved +/extend/generic-extractor/tutorial/ /components/extractors/generic-extractor/tutorial/ moved +/extend/generic-extractor/tutorial/jobs/ /components/extractors/generic-extractor/tutorial/jobs/ moved +/extend/generic-extractor/tutorial/json/ /components/extractors/generic-extractor/tutorial/json/ moved +/extend/generic-extractor/tutorial/mapping/ /components/extractors/generic-extractor/tutorial/mapping/ moved +/extend/generic-extractor/tutorial/pagination/ /components/extractors/generic-extractor/tutorial/pagination/ moved +/extend/generic-extractor/tutorial/rest/ /components/extractors/generic-extractor/tutorial/rest/ moved +/extend/generic-writer/configuration-examples/ /components/writers/generic-writer/configuration-examples/ moved +/extend/generic-writer/configuration/ /components/writers/generic-writer/configuration/ moved +/extend/generic-writer/ /components/writers/generic-writer/ moved +/extend/ /extend/ moved +/extend/job-queue/ /extend/job-queue/ unsure +/extend/publish/checklist/ /extend/publish/checklist/ moved +/extend/publish/ /extend/publish/ moved +/ / redirect +/integrate/artifacts/ /components/development/artifacts/ unsure +/integrate/artifacts/tutorial/ /components/development/artifacts/tutorial/ unsure +/integrate/data-streams/ /storage/data-streams/ redirect +/integrate/data-streams/overview/ /storage/data-streams/reference/ redirect +/integrate/data-streams/tutorial/ /storage/data-streams/tutorial/ redirect +/integrate/database/ /components/extractors/database/ redirect +/integrate/ /overview/ redirect +/integrate/jobs/ /concepts/jobs/ moved +/integrate/mcp/ /ai/mcp-server/ redirect +/integrate/orchestrator/ /flows/ redirect +/integrate/storage/api/configurations/ /storage/api/configurations/ moved +/integrate/storage/api/import-export/ /storage/api/import-export/ moved +/integrate/storage/api/importer/ /storage/api/importer/ moved +/integrate/storage/api/ /storage/api/ moved +/integrate/storage/api/tde-exporter/ /storage/api/tde-exporter/ moved +/integrate/storage/docker-cli-client/ /storage/api/clients/docker-cli/ moved +/integrate/storage/ /storage/ moved +/integrate/storage/php-client/ /storage/api/clients/php-client/ moved +/integrate/storage/python-client/ /storage/api/clients/python-client/ moved +/integrate/storage/r-client/ /storage/api/clients/r-client/ moved +/integrate/variables/ /transformations/variables/api/ moved +/integrate/variables/tutorial/ /transformations/variables/api/tutorial/ moved +/overview/api/ /concepts/api-basics/ redirect +/overview/encryption/ /components/development/encryption/ unsure +/overview/ /overview/ redirect +/overview/repositories/ /overview/ redirect diff --git a/scripts/check-redirects.mjs b/scripts/check-redirects.mjs new file mode 100644 index 000000000..23ae4b938 --- /dev/null +++ b/scripts/check-redirects.mjs @@ -0,0 +1,156 @@ +#!/usr/bin/env node +// check-redirects.mjs — the dev→help URL contract, as a checkable artifact. +// +// WHY +// developers.keboola.com retirement (PRDCT-565) needs one consolidated +// "every dev URL → final help URL" table; today that truth is split across +// PLACEMENT-MAP.md, MIGRATION-REPORT(.md/-phase2.md) and batch PRs, and the +// in-build redirects are meta-refresh pages, not 301 rules. This script makes +// the table a build artifact and checks it three ways. +// +// USAGE +// node scripts/check-redirects.mjs --gen # (re)generate _data/redirects/dev-to-help.tsv from PLACEMENT-MAP.md +// node scripts/check-redirects.mjs --build # verify against dist/ (run `npm run build` first): +// # every dev path must resolve (real page or redirect page) — else FAIL +// node scripts/check-redirects.mjs --flippable # absolute developers.keboola.com links in content whose target already lives on help +// node scripts/check-redirects.mjs --live # cutover day: HTTP developers.keboola.com/ must 301 to the mapped help URL +// +// TSV columns: dev_path final_help_path status +// moved — page gets a topic home on help (final_help_path) +// redirect — dev landing/duplicate; 301 straight to the canonical +// dies — site chrome (404, homepage) — no mapping required, listed for completeness +// unsure — PLACEMENT-MAP row awaiting a PRDCT-550 call; final path is the proposal + +import fs from 'node:fs'; +import path from 'node:path'; + +const ROOT = process.cwd(); +const MAP_MD = path.join(ROOT, 'PLACEMENT-MAP.md'); +const TSV = path.join(ROOT, '_data', 'redirects', 'dev-to-help.tsv'); +const DIST = path.join(ROOT, 'dist'); +const DEV_HOST = 'https://developers.keboola.com'; +const HELP_HOST = 'https://help.keboola.com'; + +const mode = process.argv[2]; +const clean = (p) => { + if (!p || p === '—' || p === '-') return null; + let s = p.replace(/`/g, '').trim(); + if (!s.startsWith('/')) return null; + if (!s.endsWith('/') && !/\.[a-z]+$/.test(s)) s += '/'; + return s; +}; + +function parsePlacementMap() { + const rows = []; + for (const line of fs.readFileSync(MAP_MD, 'utf8').split('\n')) { + const m = line.match(/^\| `([^`]+\.md)` \| `([^`]+)` \| ([^|]+) \| ([^|]*) \|([^|]*)\|([^|]*)\|(.*)\|?\s*$/); + if (!m) continue; + const [, , oldUrl, section, target, , conf, dedup] = m; + const dev = clean(oldUrl); // clean() keeps .html forms as-is + if (!dev) continue; + const tgt = clean(target); + let status; + if (/NOT MIGRATED/i.test(dedup) && !tgt) status = 'dies'; + else if (/REDIRECT/i.test(dedup) || section.trim().startsWith('—')) status = 'redirect'; + else status = 'moved'; + if (/UNSURE/i.test(dedup) || /UNSURE/i.test(section)) status = 'unsure'; + rows.push({ dev, tgt: tgt ?? '', status, conf: conf.trim() }); + } + return rows; +} + +function gen() { + const rows = parsePlacementMap(); + // PLACEMENT-MAP asserts 175/175 coverage — any parse below that is silent row loss + if (rows.length < 175) fail(`parsed only ${rows.length}/175 rows from PLACEMENT-MAP.md — format drifted, refusing to write a lossy map`); + fs.mkdirSync(path.dirname(TSV), { recursive: true }); + const body = rows.map((r) => `${r.dev}\t${r.tgt}\t${r.status}`).join('\n'); + fs.writeFileSync(TSV, `# generated by scripts/check-redirects.mjs --gen from PLACEMENT-MAP.md — do not hand-edit\n# dev_path\tfinal_help_path\tstatus\n${body}\n`); + const c = count(rows.map((r) => r.status)); + console.log(`✓ ${TSV.replace(ROOT + '/', '')}: ${rows.length} rows (${fmt(c)})`); +} + +function readTsv() { + if (!fs.existsSync(TSV)) fail('map missing — run --gen first'); + return fs.readFileSync(TSV, 'utf8').split('\n') + .filter((l) => l && !l.startsWith('#')) + .map((l) => { const [dev, tgt, status] = l.split('\t'); return { dev, tgt, status }; }); +} + +// a path "resolves" in dist if a page (real or redirect stub) exists there +const inDist = (p) => { + if (!p) return false; + const c = p.replace(/^\//, '').replace(/\/$/, ''); + return ['index.html', '.html'].some((suf) => + fs.existsSync(path.join(DIST, suf === 'index.html' ? path.join(c, 'index.html') : c + suf))) || + fs.existsSync(path.join(DIST, c)); // literal (e.g. 404.html) +}; + +function checkBuild() { + if (!fs.existsSync(DIST)) fail('dist/ missing — run `npm run build` first'); + const rows = readTsv(); + const lost = [], pending = []; + for (const r of rows) { + if (r.status === 'dies') continue; + const devServes = inDist(r.dev); + const finalServes = inDist(r.tgt); + if (!devServes && !finalServes) lost.push(r.dev); + else if (r.tgt && !finalServes) pending.push(`${r.dev} → ${r.tgt} (final target not built yet)`); + } + if (pending.length) { + console.log(`… ${pending.length} pending (final home not merged yet — expected until batches land):`); + pending.slice(0, 15).forEach((p) => console.log(` ${p}`)); + } + if (lost.length) { + console.error(`✗ ${lost.length} dev URL(s) resolve NOWHERE in dist — conservation broken:`); + lost.forEach((p) => console.error(` ${p}`)); + process.exit(1); + } + console.log(`✓ conservation holds: ${rows.length} mapped URLs all reachable in dist (or explicitly dying chrome)`); +} + +function flippable() { + const rows = readTsv(); + const byDev = new Map(rows.map((r) => [r.dev, r])); + const hits = []; + walk(path.join(ROOT, 'src', 'content', 'docs'), (f) => { + if (!/\.(md|mdx)$/.test(f)) return; + const text = fs.readFileSync(f, 'utf8'); + for (const m of text.matchAll(/https?:\/\/developers\.keboola\.com(\/[^\s)"'<>\]]*)/g)) { + const p = clean(m[1].split('#')[0]); + if (!p || p === '/') continue; // bare-domain links are a homepage-cutover call, not a mechanical flip + const row = byDev.get(p); + const target = row?.status === 'moved' || row?.status === 'redirect' ? row.tgt || p : null; + if (target && inDist(target)) + hits.push(`${f.replace(ROOT + '/', '')}: ${m[0]} → ${target}`); + } + }); + if (!hits.length) return console.log('✓ no flippable dev-domain links (all remaining targets not migrated yet)'); + console.log(`${hits.length} link(s) can flip to internal now:`); + hits.forEach((h) => console.log(` ${h}`)); +} + +async function live() { + const rows = readTsv().filter((r) => r.status !== 'dies'); + let bad = 0; + for (const r of rows) { + const res = await fetch(DEV_HOST + r.dev, { redirect: 'manual' }).catch(() => null); + const loc = res?.headers.get('location') ?? ''; + const expected = HELP_HOST + (r.tgt || r.dev); + const ok = res && [301, 308].includes(res.status) && (loc === expected || loc.replace(/\/$/, '') === expected.replace(/\/$/, '')); + if (!ok) { bad++; console.error(`✗ ${r.dev}: got ${res?.status ?? 'ERR'} ${loc || ''} — want 301 ${expected}`); } + } + console.log(bad ? `✗ ${bad}/${rows.length} mismatches` : `✓ all ${rows.length} URLs 301 correctly`); + if (bad) process.exit(1); +} + +function walk(dir, fn) { for (const e of fs.readdirSync(dir, { withFileTypes: true })) { const p = path.join(dir, e.name); e.isDirectory() ? walk(p, fn) : fn(p); } } +function count(a) { return a.reduce((m, x) => (m[x] = (m[x] ?? 0) + 1, m), {}); } +function fmt(o) { return Object.entries(o).map(([k, v]) => `${v} ${k}`).join(', '); } +function fail(msg) { console.error(`✗ ${msg}`); process.exit(1); } + +if (mode === '--gen') gen(); +else if (mode === '--build') checkBuild(); +else if (mode === '--flippable') flippable(); +else if (mode === '--live') await live(); +else fail('usage: check-redirects.mjs --gen | --build | --flippable | --live');