This is an automated email from the ASF dual-hosted git repository.
jason810496 pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/airflow.git
The following commit(s) were added to refs/heads/main by this push:
new 6f36bac6e6d Improve TypeScript SDK API reference navigation (#71833)
6f36bac6e6d is described below
commit 6f36bac6e6d32078e666dd6ca693a4f3b2541e75
Author: Jason(Zhe-You) Liu <[email protected]>
AuthorDate: Thu Aug 20 17:04:47 2026 +0800
Improve TypeScript SDK API reference navigation (#71833)
---
.../language-sdks/typescript.rst | 10 ++++---
dev/breeze/doc/ci/04_selective_checks.md | 4 +--
.../src/airflow_breeze/utils/selective_checks.py | 22 +++++++++------
dev/breeze/tests/test_selective_checks.py | 14 ++++++++++
.../dag-authoring-api.ts} | 32 +++++++++-------------
.../{eslint.config.js => api-docs/exceptions.ts} | 21 ++------------
.../internal-runtime-details.ts} | 21 ++------------
.../supporting-types.ts} | 21 ++------------
ts-sdk/docs/tsconfig.json | 8 +++---
ts-sdk/docs/typedoc.json | 2 +-
ts-sdk/eslint.config.js | 2 +-
ts-sdk/package.json | 8 +++---
ts-sdk/src/sdk/client.ts | 4 +--
13 files changed, 66 insertions(+), 103 deletions(-)
diff --git
a/airflow-core/docs/authoring-and-scheduling/language-sdks/typescript.rst
b/airflow-core/docs/authoring-and-scheduling/language-sdks/typescript.rst
index 5953c501ed0..266aad2d0c4 100644
--- a/airflow-core/docs/authoring-and-scheduling/language-sdks/typescript.rst
+++ b/airflow-core/docs/authoring-and-scheduling/language-sdks/typescript.rst
@@ -22,9 +22,10 @@ TypeScript SDK
|experimental|
-The TypeScript SDK lets you implement Airflow task logic in TypeScript (or
plain JavaScript), running on
-Node.js. The Dag and its scheduling remain in Python; individual tasks
delegate to a Node.js subprocess that
-is spawned by :class:`~airflow.sdk.coordinators.node.NodeCoordinator` for each
task instance.
+The TypeScript SDK lets you group task handlers in a ``Dag`` and implement
their logic in TypeScript (or
+plain JavaScript), running on Node.js. A matching Python stub Dag still
declares the scheduling shape and
+dependencies; individual tasks delegate to a Node.js subprocess that is
spawned by
+:class:`~airflow.sdk.coordinators.node.NodeCoordinator` for each task instance.
The SDK is an ESM-only package that ships from the ``ts-sdk/`` directory of
the Airflow repository. It is currently in **beta** and its API may change.
@@ -36,7 +37,8 @@ The SDK is an ESM-only package that ships from the
``ts-sdk/`` directory of the
.. seealso::
- For the full TypeScript API reference (task handlers, ``TaskClient``, and
the coordinator runtime),
+ For the full TypeScript API reference (``Dag``, ``DagRegistry``,
``serveDags``, task handlers,
+ ``TaskClient``, supporting types, and exceptions),
see the `TypeScript SDK API reference
<https://airflow.apache.org/docs/ts-sdk/stable/>`__.
.. contents:: Contents
diff --git a/dev/breeze/doc/ci/04_selective_checks.md
b/dev/breeze/doc/ci/04_selective_checks.md
index 1a034f862c9..283d36636f9 100644
--- a/dev/breeze/doc/ci/04_selective_checks.md
+++ b/dev/breeze/doc/ci/04_selective_checks.md
@@ -595,8 +595,8 @@ GitHub Actions to pass the list of parameters to a command
to execute
| run-mypy | Whether mypy check
is supposed to run in this build
| true | |
| run-system-tests | Whether system
tests should be run ("true"/"false")
| true | |
| run-task-sdk-tests | Whether Task SDK
tests should be run ("true"/"false")
| true | |
-| run-ts-sdk-docs | Whether the
TypeScript SDK API reference should be built — on `ts-sdk/docs/` or
`ts-sdk/src/` changes, including Markdown ("true"/"false") | true
| |
-| run-ts-sdk-e2e-tests | Whether TypeScript
SDK e2e tests should be run — on `ts-sdk/`, TS e2e test, or Node coordinator
changes ("true"/"false") | true |
|
+| run-ts-sdk-docs | Whether the
TypeScript SDK API reference should be built — on `ts-sdk/api-docs/`,
`ts-sdk/docs/`, or `ts-sdk/src/` changes, including Markdown ("true"/"false")
| true | |
+| run-ts-sdk-e2e-tests | Whether TypeScript
SDK e2e tests should be run — on runtime-affecting `ts-sdk/`, TS e2e test, or
Node coordinator changes ("true"/"false") | true
| |
| run-ui-tests | Whether UI tests
should be run ("true"/"false")
| true | |
| run-unit-tests | Whether unit tests
should be run ("true"/"false")
| true | |
| run-www-tests | Whether Legacy WWW
tests should be run ("true"/"false")
| true | |
diff --git a/dev/breeze/src/airflow_breeze/utils/selective_checks.py
b/dev/breeze/src/airflow_breeze/utils/selective_checks.py
index ccc80c7fb7d..33dbaffc35c 100644
--- a/dev/breeze/src/airflow_breeze/utils/selective_checks.py
+++ b/dev/breeze/src/airflow_breeze/utils/selective_checks.py
@@ -276,7 +276,8 @@ CI_FILE_GROUP_MATCHES: HashableDict[FileGroupForCi] =
HashableDict(
r"^airflow-e2e-tests/docker/openlineage-compat\.Dockerfile$",
],
FileGroupForCi.TS_SDK_E2E_FILES: [
- r"^ts-sdk/(?!.*\.md$).*",
+ # API documentation entry points and Markdown do not affect
runtime e2e tests.
+ r"^ts-sdk/(?!api-docs/)(?!.*\.md$).*",
r"^airflow-e2e-tests/tests/airflow_e2e_tests/ts_sdk_tests/.*",
r"^airflow-e2e-tests/docker/ts\.yml$",
r"^task-sdk/src/airflow/sdk/coordinators/_subprocess\.py$",
@@ -486,20 +487,23 @@ CI_FILE_GROUP_MATCHES: HashableDict[FileGroupForCi] =
HashableDict(
r"^java-sdk/(?!.*\.md$).*",
],
FileGroupForCi.TS_SDK_DOCS_FILES: [
- # TypeDoc renders the reference from the SDK sources, and the
landing page is
- # authored in ts-sdk/docs — unlike TS_SDK_FILES, `.md` counts
here. tsconfig.json
- # and package.json are included too: docs/tsconfig.json `extends`
the former, and
- # the latter pins the `@msgpack/msgpack` version the checked
program depends on.
+ # TypeDoc renders the reference from the SDK sources and category
entry points,
+ # and the landing page is authored in ts-sdk/docs — unlike
TS_SDK_FILES, `.md`
+ # counts here. tsconfig.json and package.json are included too:
docs/tsconfig.json
+ # `extends` the former, and the latter pins the `@msgpack/msgpack`
version the
+ # checked program depends on.
+ r"^ts-sdk/api-docs/.*",
r"^ts-sdk/docs/.*",
r"^ts-sdk/src/.*",
r"^ts-sdk/tsconfig\.json$",
r"^ts-sdk/package\.json$",
],
FileGroupForCi.TS_SDK_FILES: [
- # `.md` excluded — doc-only edits do not affect the generated
supervisor schema.
- # `ts-sdk/docs/package.json` and its lock file excluded too — they
pin the docs
- # toolchain's own dependencies and do not affect the SDK build.
- r"^ts-sdk/(?!.*\.md$)(?!docs/package(-lock)?\.json$).*",
+ # Documentation entry points and `.md` files do not affect the
generated
+ # supervisor schema. `ts-sdk/docs/package.json` and its lock file
are excluded
+ # too — they pin the docs toolchain's own dependencies and do not
affect the SDK
+ # build.
+
r"^ts-sdk/(?!api-docs/)(?!.*\.md$)(?!docs/package(-lock)?\.json$).*",
],
FileGroupForCi.ASSET_FILES: [
r"^airflow-core/src/airflow/assets/",
diff --git a/dev/breeze/tests/test_selective_checks.py
b/dev/breeze/tests/test_selective_checks.py
index 8f4e9382d29..a91804ff4e8 100644
--- a/dev/breeze/tests/test_selective_checks.py
+++ b/dev/breeze/tests/test_selective_checks.py
@@ -1509,6 +1509,15 @@ def assert_outputs_are_printed(expected_outputs:
dict[str, str], stderr: str):
},
id="Build ts-sdk docs for a docs-only Markdown change that skips
ts-sdk tests",
),
+ pytest.param(
+ ("ts-sdk/api-docs/dag-authoring-api.ts",),
+ {
+ "run-ts-sdk-docs": "true",
+ "run-ts-sdk-e2e-tests": "false",
+ "prod-image-build": "false",
+ },
+ id="Build only ts-sdk docs when a TypeDoc category entry point
changes",
+ ),
pytest.param(
("ts-sdk/tsconfig.json",),
{
@@ -1873,6 +1882,11 @@ def
test_ktlint_hook_only_runs_for_java_sdk_changes(files: tuple[str, ...], ktli
True,
id="skipped when only the docs toolchain's lock file changes",
),
+ pytest.param(
+ ("ts-sdk/api-docs/dag-authoring-api.ts",),
+ True,
+ id="skipped when only a TypeDoc category entry point changes",
+ ),
],
)
def test_check_ts_sdk_supervisor_schema_hook_only_runs_for_relevant_changes(
diff --git a/ts-sdk/eslint.config.js b/ts-sdk/api-docs/dag-authoring-api.ts
similarity index 62%
copy from ts-sdk/eslint.config.js
copy to ts-sdk/api-docs/dag-authoring-api.ts
index 4d1f851d186..f91f824eabd 100644
--- a/ts-sdk/eslint.config.js
+++ b/ts-sdk/api-docs/dag-authoring-api.ts
@@ -17,23 +17,17 @@
* under the License.
*/
-import js from "@eslint/js";
-import tseslint from "typescript-eslint";
+/** @module Authoring */
-export default tseslint.config(
- {
- ignores: ["dist/**", "node_modules/**", "coverage/**", "src/generated/**"],
- },
- js.configs.recommended,
- ...tseslint.configs.recommended,
- {
- files: ["src/**/*.ts", "tests/**/*.ts"],
- rules: {
- "@typescript-eslint/no-explicit-any": "error",
- "@typescript-eslint/no-unused-vars": [
- "error",
- { argsIgnorePattern: "^_" },
- ],
- },
- },
-);
+export { Dag, DagRegistry, serveDags } from "../src/index.js";
+export type {
+ DagSpec,
+ TaskClient,
+ TaskContext,
+ TaskHandler,
+ TaskHandlerArgs,
+ TaskInputs,
+ TaskOptions,
+ TaskRef,
+ TaskSpec,
+} from "../src/index.js";
diff --git a/ts-sdk/eslint.config.js b/ts-sdk/api-docs/exceptions.ts
similarity index 62%
copy from ts-sdk/eslint.config.js
copy to ts-sdk/api-docs/exceptions.ts
index 4d1f851d186..5e0399299c9 100644
--- a/ts-sdk/eslint.config.js
+++ b/ts-sdk/api-docs/exceptions.ts
@@ -17,23 +17,6 @@
* under the License.
*/
-import js from "@eslint/js";
-import tseslint from "typescript-eslint";
+/** @module Exceptions */
-export default tseslint.config(
- {
- ignores: ["dist/**", "node_modules/**", "coverage/**", "src/generated/**"],
- },
- js.configs.recommended,
- ...tseslint.configs.recommended,
- {
- files: ["src/**/*.ts", "tests/**/*.ts"],
- rules: {
- "@typescript-eslint/no-explicit-any": "error",
- "@typescript-eslint/no-unused-vars": [
- "error",
- { argsIgnorePattern: "^_" },
- ],
- },
- },
-);
+export { ConnectionNotFoundError, VariableNotFoundError } from
"../src/index.js";
diff --git a/ts-sdk/eslint.config.js
b/ts-sdk/api-docs/internal-runtime-details.ts
similarity index 62%
copy from ts-sdk/eslint.config.js
copy to ts-sdk/api-docs/internal-runtime-details.ts
index 4d1f851d186..8be97ac6a13 100644
--- a/ts-sdk/eslint.config.js
+++ b/ts-sdk/api-docs/internal-runtime-details.ts
@@ -17,23 +17,6 @@
* under the License.
*/
-import js from "@eslint/js";
-import tseslint from "typescript-eslint";
+/** @module Internals */
-export default tseslint.config(
- {
- ignores: ["dist/**", "node_modules/**", "coverage/**", "src/generated/**"],
- },
- js.configs.recommended,
- ...tseslint.configs.recommended,
- {
- files: ["src/**/*.ts", "tests/**/*.ts"],
- rules: {
- "@typescript-eslint/no-explicit-any": "error",
- "@typescript-eslint/no-unused-vars": [
- "error",
- { argsIgnorePattern: "^_" },
- ],
- },
- },
-);
+export { SUPERVISOR_API_VERSION } from "../src/index.js";
diff --git a/ts-sdk/eslint.config.js b/ts-sdk/api-docs/supporting-types.ts
similarity index 62%
copy from ts-sdk/eslint.config.js
copy to ts-sdk/api-docs/supporting-types.ts
index 4d1f851d186..f928752d91d 100644
--- a/ts-sdk/eslint.config.js
+++ b/ts-sdk/api-docs/supporting-types.ts
@@ -17,23 +17,6 @@
* under the License.
*/
-import js from "@eslint/js";
-import tseslint from "typescript-eslint";
+/** @module Types */
-export default tseslint.config(
- {
- ignores: ["dist/**", "node_modules/**", "coverage/**", "src/generated/**"],
- },
- js.configs.recommended,
- ...tseslint.configs.recommended,
- {
- files: ["src/**/*.ts", "tests/**/*.ts"],
- rules: {
- "@typescript-eslint/no-explicit-any": "error",
- "@typescript-eslint/no-unused-vars": [
- "error",
- { argsIgnorePattern: "^_" },
- ],
- },
- },
-);
+export type { ConnectionResult, GetXComOpts, JsonValue, SetXComOpts } from
"../src/index.js";
diff --git a/ts-sdk/docs/tsconfig.json b/ts-sdk/docs/tsconfig.json
index e971de7cb96..caaf9009d31 100644
--- a/ts-sdk/docs/tsconfig.json
+++ b/ts-sdk/docs/tsconfig.json
@@ -1,13 +1,13 @@
{
"//": [
"Docs-only tsconfig for the TypeDoc analysis pass. It inherits the SDK's
compiler",
- "settings verbatim and roots the program at the public entry point only:
TypeScript",
- "pulls in whatever that entry point transitively imports, but a glob like",
+ "settings verbatim and roots the program at the docs-only API category
entry points: TypeScript",
+ "pulls in whatever those entry points transitively import, but a glob
like",
"`../src/**/*.ts` would also root unreachable internal modules (e.g. the
`cli/` bin,",
"which needs the optional `esbuild` peer dependency) that the docs
toolchain has no",
"reason to install. `paths` below redirects `@msgpack/msgpack`, a real
transitive",
"dependency of the checked program (coordinator/frames.ts, reachable from
the public",
- "startCoordinator export): Node module resolution walks up node_modules
from the",
+ "serveDags export): Node module resolution walks up node_modules from the",
"*importing file* (ts-sdk/src/coordinator/), never sideways into this
package's own",
"node_modules, so the bare specifier would otherwise never resolve here."
],
@@ -17,5 +17,5 @@
"@msgpack/msgpack":
["./node_modules/@msgpack/msgpack/dist.esm/index.d.ts"]
}
},
- "include": ["../src/index.ts"]
+ "include": ["../api-docs/*.ts"]
}
diff --git a/ts-sdk/docs/typedoc.json b/ts-sdk/docs/typedoc.json
index 6efc7c4e7d9..feed7d21ac0 100644
--- a/ts-sdk/docs/typedoc.json
+++ b/ts-sdk/docs/typedoc.json
@@ -2,7 +2,7 @@
"$schema": "https://typedoc.org/schema.json",
"plugin": ["@clean-jsdoc-theme/typedoc"],
"outputs": [{ "name": "clean-jsdoc-theme", "path": "_build/html" }],
- "entryPoints": ["../src/index.ts"],
+ "entryPoints": ["../api-docs/*.ts"],
"tsconfig": "./tsconfig.json",
"name": "Apache Airflow TypeScript SDK",
"readme": ".typedoc/readme.md",
diff --git a/ts-sdk/eslint.config.js b/ts-sdk/eslint.config.js
index 4d1f851d186..f4ae01d7d9d 100644
--- a/ts-sdk/eslint.config.js
+++ b/ts-sdk/eslint.config.js
@@ -27,7 +27,7 @@ export default tseslint.config(
js.configs.recommended,
...tseslint.configs.recommended,
{
- files: ["src/**/*.ts", "tests/**/*.ts"],
+ files: ["api-docs/**/*.ts", "src/**/*.ts", "tests/**/*.ts"],
rules: {
"@typescript-eslint/no-explicit-any": "error",
"@typescript-eslint/no-unused-vars": [
diff --git a/ts-sdk/package.json b/ts-sdk/package.json
index 8bc9560f17b..1d182c23215 100644
--- a/ts-sdk/package.json
+++ b/ts-sdk/package.json
@@ -40,10 +40,10 @@
],
"scripts": {
"clean": "node -e \"require('node:fs').rmSync('dist', { recursive: true,
force: true })\"",
- "lint": "eslint src tests",
- "lint:fix": "eslint src tests --fix",
- "format:check": "prettier --check src tests",
- "format": "prettier --write src tests",
+ "lint": "eslint api-docs src tests",
+ "lint:fix": "eslint api-docs src tests --fix",
+ "format:check": "prettier --check api-docs src tests",
+ "format": "prettier --write api-docs src tests",
"typecheck": "tsc --noEmit",
"test": "vitest run",
"test:watch": "vitest",
diff --git a/ts-sdk/src/sdk/client.ts b/ts-sdk/src/sdk/client.ts
index a0a9a48bd8d..8d63eee49c3 100644
--- a/ts-sdk/src/sdk/client.ts
+++ b/ts-sdk/src/sdk/client.ts
@@ -43,7 +43,7 @@ export interface TaskClient {
* This matches Python `Variable.get` behavior when no default value is
* supplied.
*
- * @throws {@link VariableNotFoundError} when the key is missing.
+ * @throws {@link Exceptions!VariableNotFoundError | VariableNotFoundError}
when the key is missing.
*/
getVariableOrThrow(key: string): Promise<string>;
@@ -86,7 +86,7 @@ export interface TaskClient {
*
* This matches Python `BaseHook.get_connection` behavior.
*
- * @throws {@link ConnectionNotFoundError} when the connection does not
exist.
+ * @throws {@link Exceptions!ConnectionNotFoundError |
ConnectionNotFoundError} when the connection does not exist.
*/
getConnectionOrThrow(connId: string): Promise<ConnectionResult>;
}