chore: import upstream snapshot with attribution
CI / build (push) Has been cancelled

This commit is contained in:
wehub-resource-sync
2026-07-13 13:09:51 +08:00
commit 0232b4e2bb
3528 changed files with 291404 additions and 0 deletions
+41
View File
@@ -0,0 +1,41 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.*
.yarn/*
!.yarn/patches
!.yarn/plugins
!.yarn/releases
!.yarn/versions
# testing
/coverage
# next.js
/.next/
/out/
# production
/build
# misc
.DS_Store
*.pem
# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.pnpm-debug.log*
# env files (can opt-in for committing if needed)
.env*
# vercel
.vercel
# typescript
*.tsbuildinfo
next-env.d.ts
+16
View File
@@ -0,0 +1,16 @@
# FlowGram Runtime NodeJS
## Starting the server
```bash
pnpm dev
```
## Building the server
```bash
pnpm build
```
## Running the server
```bash
node dist/index.js
```
+34
View File
@@ -0,0 +1,34 @@
/**
* Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
* SPDX-License-Identifier: MIT
*/
import { defineFlatConfig } from '@flowgram.ai/eslint-config';
import path from 'path';
import { fileURLToPath } from 'url';
const __dirname = path.dirname(fileURLToPath(import.meta.url));
export default defineFlatConfig({
parser: '@typescript-eslint/parser',
preset: 'node',
packageRoot: __dirname,
ignore: ['.eslintrc.cjs'],
parserOptions: {
requireConfigFile: false,
ecmaVersion: 2017,
sourceType: 'module',
ecmaFeatures: {
modules: true,
},
},
rules: {
'no-console': 'off',
},
plugins: ['json', '@typescript-eslint'],
settings: {
react: {
version: '18',
},
},
});
+61
View File
@@ -0,0 +1,61 @@
{
"name": "@flowgram.ai/runtime-nodejs",
"version": "0.1.8",
"homepage": "https://flowgram.ai/",
"repository": "https://github.com/bytedance/flowgram.ai",
"license": "MIT",
"type": "module",
"exports": {
"types": "./dist/index.d.ts",
"import": "./dist/index.js"
},
"module": "./dist/index.js",
"types": "./dist/index.d.ts",
"files": [
"dist"
],
"scripts": {
"dev": "tsx watch src",
"build": "npm run build:fast -- --dts-resolve",
"build:fast": "tsup src/index.ts --format esm --sourcemap --out-dir dist",
"build:watch": "npm run build:fast -- --dts-resolve",
"lint": "eslint --cache src",
"lint-fix": "eslint --fix src",
"type-check": "tsc",
"start": "node dist/index.js",
"test": "exit 0",
"test:cov": "exit 0"
},
"dependencies": {
"@flowgram.ai/runtime-js": "workspace:*",
"@flowgram.ai/runtime-interface": "workspace:*",
"@fastify/cors": "^8.2.1",
"@fastify/swagger": "^8.5.1",
"@fastify/swagger-ui": "4.1.0",
"@fastify/websocket": "^10.0.1",
"@trpc/server": "^10.27.1",
"trpc-openapi": "^1.2.0",
"fastify": "^4.17.0",
"zod": "^3.24.4"
},
"devDependencies": {
"@flowgram.ai/ts-config": "workspace:*",
"@flowgram.ai/eslint-config": "workspace:*",
"@types/cors": "^2.8.13",
"dotenv": "~16.5.0",
"@types/node": "^18",
"eslint": "^9.0.0",
"typescript": "^5.8.3",
"tsup": "^8.0.1",
"tsx": "~4.19.4",
"eslint-plugin-json": "^4.0.1",
"@typescript-eslint/eslint-plugin": "^8.0.0",
"@typescript-eslint/parser": "^8.0.0",
"@vitest/coverage-v8": "^3.2.4",
"vitest": "^3.2.4"
},
"publishConfig": {
"access": "public",
"registry": "https://registry.npmjs.org/"
}
}
@@ -0,0 +1,68 @@
/**
* Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
* SPDX-License-Identifier: MIT
*/
import z from 'zod';
import { WorkflowRuntimeAPIs } from '@flowgram.ai/runtime-js';
import { FlowGramAPIMethod, FlowGramAPIName, FlowGramAPIs } from '@flowgram.ai/runtime-interface';
import { APIHandler } from './type';
import { publicProcedure } from './trpc';
export const createAPI = (apiName: FlowGramAPIName): APIHandler => {
const define = FlowGramAPIs[apiName];
const caller = WorkflowRuntimeAPIs[apiName];
if (define.method === FlowGramAPIMethod.GET) {
const procedure = publicProcedure
.meta({
openapi: {
method: define.method,
path: define.path,
summary: define.name,
tags: [define.module],
},
})
.input(define.schema.input)
.output(z.union([define.schema.output, z.undefined()]))
.query(async (opts) => {
const input = opts.input;
try {
const output = await caller(input);
return output;
} catch {
return undefined;
}
});
return {
define,
procedure: procedure as any,
};
}
const procedure = publicProcedure
.meta({
openapi: {
method: define.method,
path: define.path,
summary: define.name,
tags: [define.module],
},
})
.input(define.schema.input)
.output(z.union([define.schema.output, z.undefined()]))
.mutation(async (opts) => {
const input = opts.input;
try {
const output = await caller(input);
return output;
} catch {
return undefined;
}
});
return {
define,
procedure: procedure as any,
};
};
+21
View File
@@ -0,0 +1,21 @@
/**
* Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
* SPDX-License-Identifier: MIT
*/
import { FlowGramAPINames } from '@flowgram.ai/runtime-interface';
import { APIRouter } from './type';
import { router } from './trpc';
import { createAPI } from './create-api';
const APIS = FlowGramAPINames.map((apiName) => createAPI(apiName));
export const routers = APIS.reduce((acc, api) => {
acc[api.define.path] = api.procedure;
return acc;
}, {} as APIRouter);
export const appRouter = router(routers);
export type AppRouter = typeof appRouter;
+21
View File
@@ -0,0 +1,21 @@
/**
* Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
* SPDX-License-Identifier: MIT
*/
import { OpenApiMeta } from 'trpc-openapi';
import { initTRPC } from '@trpc/server';
import type { Context } from '../server/context';
const t = initTRPC
.context<Context>()
.meta<OpenApiMeta>()
.create({
errorFormatter({ shape }) {
return shape;
},
});
export const router = t.router;
export const publicProcedure = t.procedure;
+14
View File
@@ -0,0 +1,14 @@
/**
* Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
* SPDX-License-Identifier: MIT
*/
import { BuildProcedure } from '@trpc/server';
import { FlowGramAPIDefine } from '@flowgram.ai/runtime-interface';
export interface APIHandler {
define: FlowGramAPIDefine;
procedure: BuildProcedure<any, any, any>;
}
export type APIRouter = Record<FlowGramAPIDefine['path'], APIHandler['procedure']>;
@@ -0,0 +1,18 @@
/**
* Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
* SPDX-License-Identifier: MIT
*/
import type { ServerParams } from '@server/type';
export const ServerConfig: ServerParams = {
name: 'flowgram-runtime',
title: 'FlowGram Runtime',
description: 'FlowGram Runtime Demo',
runtime: 'nodejs',
version: '0.0.1',
dev: false,
port: 4000,
basePath: '/api',
docsPath: '/docs',
};
+13
View File
@@ -0,0 +1,13 @@
/**
* Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
* SPDX-License-Identifier: MIT
*/
import { createServer } from '@server/index';
async function main() {
const server = await createServer();
server.start();
}
main();
@@ -0,0 +1,13 @@
/**
* Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
* SPDX-License-Identifier: MIT
*/
import type { CreateFastifyContextOptions } from '@trpc/server/adapters/fastify';
export function createContext(ctx: CreateFastifyContextOptions) {
const { req, res } = ctx;
return { req, res };
}
export type Context = Awaited<ReturnType<typeof createContext>>;
@@ -0,0 +1,19 @@
/**
* Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
* SPDX-License-Identifier: MIT
*/
import { generateOpenApiDocument } from 'trpc-openapi';
import { ServerConfig } from '@config/index';
import { appRouter } from '@api/index';
// Generate OpenAPI schema document
export const serverDocument = generateOpenApiDocument(appRouter, {
title: ServerConfig.title,
description: ServerConfig.description,
version: ServerConfig.version,
baseUrl: `http://localhost:${ServerConfig.port}${ServerConfig.basePath}`,
docsUrl: 'https://flowgram.ai',
tags: ['Task'],
});
@@ -0,0 +1,94 @@
/**
* Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
* SPDX-License-Identifier: MIT
*/
import { fastifyTRPCOpenApiPlugin } from 'trpc-openapi';
import fastify from 'fastify';
import { fastifyTRPCPlugin } from '@trpc/server/adapters/fastify';
import { ServerInfoDefine, type ServerInfoOutput } from '@flowgram.ai/runtime-interface';
import ws from '@fastify/websocket';
import fastifySwaggerUI from '@fastify/swagger-ui';
import fastifySwagger from '@fastify/swagger';
import cors from '@fastify/cors';
import { ServerConfig } from '@config/index';
import { appRouter } from '@api/index';
import { serverDocument } from './docs';
import { createContext } from './context';
export async function createServer() {
const server = fastify({ logger: ServerConfig.dev });
await server.register(cors);
await server.register(ws);
await server.register(fastifyTRPCPlugin, {
prefix: '/trpc',
useWss: false,
trpcOptions: { router: appRouter, createContext },
});
await server.register(fastifyTRPCOpenApiPlugin, {
basePath: ServerConfig.basePath,
router: appRouter,
createContext,
} as any);
await server.register(fastifySwagger, {
mode: 'static',
specification: { document: serverDocument },
uiConfig: { displayOperationId: true },
exposeRoute: true,
} as any);
await server.register(fastifySwaggerUI, {
routePrefix: ServerConfig.docsPath,
uiConfig: {
docExpansion: 'full',
deepLinking: false,
},
uiHooks: {
onRequest: function (request, reply, next) {
next();
},
preHandler: function (request, reply, next) {
next();
},
},
staticCSP: true,
transformStaticCSP: (header) => header,
transformSpecification: (swaggerObject, request, reply) => swaggerObject,
transformSpecificationClone: true,
});
server.get(ServerInfoDefine.path, async (): Promise<ServerInfoOutput> => {
const serverTime = new Date();
const output: ServerInfoOutput = {
name: ServerConfig.name,
title: ServerConfig.title,
description: ServerConfig.description,
runtime: ServerConfig.runtime,
version: ServerConfig.version,
time: serverTime.toISOString(),
};
return output;
});
const stop = async () => {
await server.close();
};
const start = async () => {
try {
const address = await server.listen({ port: ServerConfig.port });
await server.ready();
server.swagger();
console.log(
`> Listen Port: ${ServerConfig.port}\n> Server Address: ${address}\n> API Docs: http://localhost:4000/docs`
);
} catch (err) {
server.log.error(err);
process.exit(1);
}
};
return { server, start, stop };
}
@@ -0,0 +1,13 @@
/**
* Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
* SPDX-License-Identifier: MIT
*/
import { ServerInfoOutput } from '@flowgram.ai/runtime-interface';
export interface ServerParams extends Omit<ServerInfoOutput, 'time'> {
dev: boolean;
port: number;
basePath: string;
docsPath: string;
}
+47
View File
@@ -0,0 +1,47 @@
{
"extends": "@flowgram.ai/ts-config/tsconfig.flow.path.json",
"compilerOptions": {
"target": "esnext",
"lib": [
"dom",
"dom.iterable",
"esnext"
],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"plugins": [],
"baseUrl": "src",
"paths": {
"@api/*": [
"api/*"
],
"@application/*": [
"application/*"
],
"@server/*": [
"server/*"
],
"@config/*": [
"config/*"
],
"@workflow/*": [
"workflow/*"
]
}
},
"include": [
"**/*.ts",
"**/*.tsx",
"src/workflow/executor/condition/constant.ts"
],
"exclude": [
"node_modules"
]
}
+45
View File
@@ -0,0 +1,45 @@
/**
* Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
* SPDX-License-Identifier: MIT
*/
import { config } from "dotenv";
import path from 'path';
import { defineConfig } from 'vitest/config';
export default defineConfig({
build: {
commonjsOptions: {
transformMixedEsModules: true,
},
},
resolve: {
alias: [
{find: "@api", replacement: path.resolve(__dirname, './src/api') },
{find: "@application", replacement: path.resolve(__dirname, './src/application') },
{find: "@server", replacement: path.resolve(__dirname, './src/server') },
{find: "@config", replacement: path.resolve(__dirname, './src/config') },
{find: "@workflow", replacement: path.resolve(__dirname, './src/workflow') },
],
},
test: {
globals: true,
mockReset: false,
environment: 'jsdom',
testTimeout: 15000,
setupFiles: [path.resolve(__dirname, './src/workflow/__tests__/setup.ts')],
include: ['**/?(*.){test,spec}.?(c|m)[jt]s?(x)'],
exclude: [
'**/__mocks__**',
'**/node_modules/**',
'**/dist/**',
'**/lib/**', // lib 编译结果忽略掉
'**/cypress/**',
'**/.{idea,git,cache,output,temp}/**',
'**/{karma,rollup,webpack,vite,vitest,jest,ava,babel,nyc,cypress,tsup,build}.config.*',
],
env: {
...config({ path: path.resolve(__dirname, './.env/.env.test') }).parsed
}
},
});