@77-zhike/app-sdk 0.2.0-d7b1.8 → 0.2.0-d7b1.9

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/README.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # 智客 App SDK 与 CLI
2
2
 
3
+ ## 获准依赖
4
+
5
+ 工具链从 `src/toolchain/allowed-packages.json` 读取平台维护的包白名单。目前允许 `@77-zhike/qiqi-openapi@0.1.0` 的服务端包根入口 `.`;前端不可导入。项目安装依赖后直接使用静态 ESM import,真实解析的包名、精确版本、入口及间接模块在打包时核对,代码合并进 Artifact。App 的 Manifest、Settings 或 `package.json` 不能扩展名单。
6
+
7
+ Node builtin、CommonJS、动态 import、原生模块、未获准包和路径越界仍禁止。项目内 `file:` 包可用,但同名同版本不是来源证明。白名单只控制构建兼容性;不替代运行时沙箱、网络策略、租户隔离及 API 权限,不进行运行时 npm 安装。
8
+
3
9
  ## 统一构建
4
10
 
5
11
  `zhike dev` 是监听、构建、上传和应用开发安装的快捷工作流,不是另一种运行时。
@@ -133,7 +139,7 @@ import {
133
139
  } from '@77-zhike/app-sdk/client'
134
140
  import {
135
141
  Card,
136
- Link,
142
+ ZhikeLink,
137
143
  Stack,
138
144
  TextBlock,
139
145
  } from '@77-zhike/app-sdk/ui'
@@ -144,9 +150,9 @@ function QueuePage() {
144
150
  <Card title="任务队列">
145
151
  <TextBlock>当前没有待处理任务。</TextBlock>
146
152
  </Card>
147
- <Link destination={Destinations.appPage('overview')}>
153
+ <ZhikeLink destination={Destinations.appPage('overview')}>
148
154
  返回总览
149
- </Link>
155
+ </ZhikeLink>
150
156
  </Stack>
151
157
  )
152
158
  }
@@ -161,13 +167,13 @@ export default definePage({
161
167
 
162
168
  同一 App 内,有 `order` 的 Page 排在前面并按 `order + slug` 稳定排序;未声明 `order` 的 Page 排在后面并按 slug 排序。`name` trim 后长度为 1~80 个 Unicode code points。`variant: 'full' | 'centered'` 只表达布局语义,Desktop 与 H5 分别决定具体页面壳。
163
169
 
164
- Page UI 必须使用 `@77-zhike/app-sdk/ui` 和 `@77-zhike/app-sdk/forms` 的公开组件,不能依赖 DOM、React Router 或自行复制产品控件。当前 Desktop 支持 Components 与 Forms;H5 支持 TextBlock、布局、反馈、Button、Tabs、Table、Card、Grid、EmptyState、Link 等 portable Components,并支持 Forms,暂不支持 `LookupCell`。含有不支持能力的 Page 在 H5 会整体显示“不支持”,不会静默丢节点或部分提交。
170
+ Page UI 必须使用 `@77-zhike/app-sdk/ui` 和 `@77-zhike/app-sdk/forms` 的公开组件,不能依赖 DOM、React Router 或自行复制产品控件。当前 Desktop 支持 Components 与 Forms;H5 支持 TextBlock、布局、反馈、Button、Tabs、Table、Card、Grid、EmptyState、Link、ZhikeLink 等 portable Components,并支持 Forms,暂不支持 `LookupCell`。含有不支持能力的 Page 在 H5 会整体显示“不支持”,不会静默丢节点或部分提交。
165
171
 
166
172
  导航只提交结构化 Destination:
167
173
 
168
174
  - `Destinations.appPage(slug)` 打开当前 App 的另一个 Page。
169
175
  - `Destinations.record({ object, recordId })` 支持 `accounts`、`contacts`、`opportunities`、`tasks`、`activities` 和当前 Workspace 可见的 `custom_*` 公开 API slug。
170
- - `Link` 保留普通链接、复制地址和新标签行为;普通点击仍会在跳转前重验当前 Page 身份。
176
+ - `ZhikeLink` 保留普通链接、复制地址和新标签行为;普通点击仍会在跳转前重验当前 Page 身份。外部 HTTPS 使用 `Link`。
171
177
  - `navigate()` 当前只允许从已挂载的 Page 调用,三类 Action 都不具备该能力。
172
178
 
173
179
  目录展示不会启动 Worker。首次打开 Page 时,宿主才会下载并校验 Manifest/Bundle、启动 Installation Worker;因此“Apps 菜单可见”不等于代码已经验证可运行。页面数据读写仍应通过受控 Server Function 完成。
@@ -196,9 +202,9 @@ export default async function readForCurrentMember() {
196
202
 
197
203
  ## 基础UI组件扩展
198
204
 
199
- 新增Avatar、DescriptionList、Divider、Json、ExternalLink、StatusBadge、TextBlock与Typography,补齐Banner动作、Badge颜色、Card呈现、Grid容器模式、EmptyState操作编排和Table.HeaderCell。原flat exports与默认调用保留,复合写法使用同一节点。
205
+ 新增Avatar、DescriptionList、Divider、Json、外部Link、StatusBadge、TextBlock与Typography,补齐Banner动作、Badge颜色、Card呈现、Grid容器模式、EmptyState操作编排和Table.HeaderCell。复合写法使用同一节点。
200
206
 
201
- Desktop注册42项,H5注册41项(不含LookupCell),其中包括 `Widget.TextWidget`、`Widget.Title`、`Widget.Text.Primary`、`Widget.Text.Secondary`、`Widget.Loading` 与 `Widget.Decoration` 六个 Widget 语义节点。Link仍仅限Page;H5支持Forms,仍不开放Settings入口。新包要求`remote-react.v3`,发布前必须先部署对应Host及Bundle准入合同。
207
+ Desktop与H5注册的组件合同中,`ZhikeLink` 仍仅限Page,`Link` 是受治理的外部HTTPS链接;H5支持Forms,仍不开放Settings入口。新包要求`remote-react.v3`,发布前必须先部署对应Host及Bundle准入合同。
202
208
 
203
209
  新增组件的日常验证:修改Core `components/contracts.mjs`后执行`npm run generate:components --workspace @77-zhike/app-sdk`和`npm run check:components --workspace @77-zhike/app-sdk`,同步双端manifest与adapter。App项目运行`zhike dev --workspace <workspace-id>`,从对应Workspace的Apps入口打开Page;Desktop Settings仅验证其允许的子集。
204
210
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@77-zhike/app-sdk",
3
- "version": "0.2.0-d7b1.8",
3
+ "version": "0.2.0-d7b1.9",
4
4
  "description": "智客 Integration App 一期 SDK 与本地 Toolchain",
5
5
  "repository": {
6
6
  "type": "git",
@@ -59,5 +59,5 @@
59
59
  "optional": true
60
60
  }
61
61
  },
62
- "gitHead": "5ebb33176120cba2e1c70440cc56dc041e1cf924"
62
+ "gitHead": "d820fb6f04634518f062b82cf214d3b08d00c481"
63
63
  }
@@ -32,9 +32,12 @@ export function formatAppLog(app, entry, {
32
32
  const levelLabel = { log: "INFO ", warn: "WARN ", error: "ERROR" }[level];
33
33
  const levelColor = { log: colors.cyan, warn: colors.yellow, error: colors.red }[level];
34
34
  const timestamp = formatTimestamp(entry.received_at);
35
+ const version = entry.app_version_id ? safe(entry.app_version_id).replace(/\n/g, " ").slice(0, 64) : "";
36
+ const request = entry.invocation_id ? safe(entry.invocation_id).replace(/\n/g, " ").slice(0, 64) : "";
37
+ const identity = version || request ? ` [${[version, request].filter(Boolean).join(" · ")}]` : "";
35
38
  const prefix = color
36
- ? `${colors.dim}${timestamp}${colors.reset} ${levelColor}${levelLabel}${colors.reset} ${colors.bold}${label}${colors.reset}`
37
- : `${timestamp} ${levelLabel} ${label}`;
39
+ ? `${colors.dim}${timestamp}${colors.reset} ${levelColor}${levelLabel}${colors.reset} ${colors.bold}${label}${colors.reset}${identity}`
40
+ : `${timestamp} ${levelLabel} ${label}${identity}`;
38
41
  return safe(entry.message).split("\n").map((line) => `${prefix} ${line}`).join("\n");
39
42
  }
40
43
 
package/src/cli/index.js CHANGED
@@ -2,7 +2,7 @@ import { resolve } from "node:path";
2
2
 
3
3
  import { loadCliConfig } from "../config.js";
4
4
  import { asSafeCliError, ZhikeCliError } from "../errors.js";
5
- import { buildAppBundle, buildMockArtifact } from "../toolchain/index.js";
5
+ import { buildAppBundle } from "../toolchain/index.js";
6
6
  import { authenticateCli, openSystemBrowser } from "./browser-auth.js";
7
7
  import { createSystemCredentialStore } from "./credential-store.js";
8
8
  import {
@@ -10,7 +10,6 @@ import {
10
10
  initializeProject,
11
11
  validateAppSlug,
12
12
  } from "./project-init.js";
13
- import { validateBundleUpload } from "./validate-bundle.js";
14
13
  import { uploadAppBundle } from "./upload-bundle.js";
15
14
  import { watchDevelopmentApp } from "./development-watch.js";
16
15
  import { runLocalCommand } from "./local-commands.js";
@@ -60,6 +59,16 @@ export async function runCli(
60
59
  );
61
60
  return result;
62
61
  }
62
+ if (command === "validate") {
63
+ _rejectArguments(rest);
64
+ const result = await buildAppBundle({
65
+ projectDirectory: cwd,
66
+ });
67
+ output.write(
68
+ `真实 App 源码校验通过:${result.artifacts.length} Artifacts,Bundle ${result.sha256} (${result.size} bytes);未写入 dist\n`,
69
+ );
70
+ return result;
71
+ }
63
72
 
64
73
  const onProgress = (message) => output.write(`${message}\n`);
65
74
  let remoteContext = null;
@@ -186,26 +195,6 @@ export async function runCli(
186
195
  if (result && !ready) await onReady(result);
187
196
  return result;
188
197
  }
189
- if (command === "experimental" && rest[0] === "validate-bundle") {
190
- _rejectArguments(rest.slice(1));
191
- const { config, store } = getRemoteContext();
192
- const authenticatedApi = await authenticate({
193
- ...config,
194
- credentialStore: store,
195
- fetchImpl,
196
- openBrowser,
197
- onProgress,
198
- });
199
- const result = await validateBundleUpload({
200
- projectDirectory: cwd,
201
- apiBaseUrl: config.apiBaseUrl,
202
- authenticatedApi,
203
- });
204
- output.write(
205
- `${result.upload.status === "accepted" ? "Bundle 已受理" : "Bundle 校验失败"}:${result.upload.id}\n`,
206
- );
207
- return result;
208
- }
209
198
  throw new ZhikeCliError(
210
199
  "zhike_command_unknown",
211
200
  `未知命令:${command}`,
@@ -260,5 +249,4 @@ export {
260
249
  initializeProject,
261
250
  scaffoldProject,
262
251
  } from "./project-init.js";
263
- export { validateBundleUpload } from "./validate-bundle.js";
264
252
  export { uploadAppBundle } from "./upload-bundle.js";
@@ -13,6 +13,7 @@ export const commandHelp = {
13
13
  doctor: "doctor [--json]",
14
14
  login: "login",
15
15
  init: "init <app-slug>",
16
+ validate: "validate",
16
17
  build: "build",
17
18
  upload: "upload",
18
19
  dev: "dev [--workspace <workspace-id>]",
@@ -100,6 +100,7 @@ export async function scaffoldProject({ targetDirectory, binding }) {
100
100
  - 开发文档:${docsUrl}
101
101
 
102
102
  先读取文档索引,再按当前任务读取相关的 App SDK、CLI、扩展、连接和 API 文档;不要仅凭记忆猜测接口、参数或运行时能力。
103
+ 每使用一个复合 UI 或 Form 组件,必须打开该组件的专属文档,核对允许的直属子节点、嵌套顺序和入口限制。TypeScript、zhike validate、zhike build 或上传成功,不代表组件树已经符合运行时合同。
103
104
  索引中的相对链接以开发文档地址为基准解析。若无法访问文档,请明确说明访问失败,请用户提供相关文档,不要把猜测当作已确认能力。
104
105
  项目绑定环境与 App 身份见 .zhike/project.json;切换平台环境后应同步更新上述文档地址。
105
106
  `;
@@ -137,10 +138,10 @@ export async function scaffoldProject({ targetDirectory, binding }) {
137
138
  type: "module",
138
139
  scripts: {
139
140
  zhike: "zhike",
141
+ validate: "zhike validate",
140
142
  build: "zhike build",
141
143
  dev: "zhike dev",
142
144
  upload: "zhike upload",
143
- "validate:mock": "zhike experimental validate-bundle",
144
145
  },
145
146
  devDependencies: {
146
147
  "@77-zhike/app-sdk": TOOLING_VERSION,
@@ -1,4 +1,20 @@
1
1
  import type { JsonValue } from "../index.js";
2
+ export { defineWorkflowStep, defineWorkflowStepExecute } from "./steps/index.js";
3
+ export type { WorkflowObjectSchema, WorkflowScalarSchema, WorkflowStepDefinition, WorkflowStepOutcome, WorkflowStepResult, WorkflowSchemaValue } from "./steps/index.js";
4
+ export { defineWorkflowTrigger, defineWorkflowTriggerActivate, defineWorkflowTriggerOnEvent, defineWorkflowTriggerDeactivate } from "./triggers/index.js";
5
+ export type { WorkflowTriggerDefinition, WorkflowTriggerOutcome, WorkflowTriggerEventResult } from "./triggers/index.js";
6
+ export {
7
+ defineWorkflowBlock,
8
+ defineWorkflowBlockExecute,
9
+ defineWorkflowBlockActivate,
10
+ defineWorkflowBlockTrigger,
11
+ defineWorkflowBlockDeactivate,
12
+ } from "./workflow-blocks/index.js";
13
+ export type {
14
+ WorkflowBlockDefinition,
15
+ WorkflowStepBlockDefinition,
16
+ WorkflowTriggerBlockDefinition,
17
+ } from "./workflow-blocks/index.js";
2
18
 
3
19
  /** 当前执行的 App API Token;由可信 Runtime Module 在服务端模块求值前注入。 */
4
20
  export const ZHIKE_API_TOKEN: string;
@@ -206,18 +222,37 @@ export interface WorkspaceWebhookBody {
206
222
  events: WorkspaceWebhookEvent[];
207
223
  }
208
224
 
209
- /** 当前服务端执行可使用的 Workspace 外部系统连接。 */
210
- export interface WorkspaceConnection {
225
+ interface WorkspaceConnectionBase {
211
226
  /** 当前 Workspace Connection 的稳定 ID。 */
212
227
  id: string;
213
228
  /** 当前 Connect/Reconnect generation 的非敏感稳定表示。 */
214
229
  generation: string;
215
- /** 当前凭据类型。 */
216
- type: "secret" | "oauth2";
217
- /** Secret 或当前 OAuth access token,仅存在于本次服务端执行内存。 */
230
+ /** Secret 或当前 OAuth/OIDC access token,仅存在于本次服务端执行内存。 */
218
231
  value: string;
219
232
  }
220
233
 
234
+ /** 当前服务端执行可使用的 Workspace 外部系统连接。 */
235
+ export type WorkspaceConnection = WorkspaceConnectionBase & (
236
+ | {
237
+ type: "secret";
238
+ protocol: "secret";
239
+ }
240
+ | {
241
+ type: "oauth2";
242
+ protocol: "oauth2";
243
+ /** OAuth 2.0 access token;等同 value。 */
244
+ accessToken: string;
245
+ }
246
+ | {
247
+ type: "oauth2";
248
+ protocol: "oidc";
249
+ /** OIDC access token;等同 value。 */
250
+ accessToken: string;
251
+ /** OIDC ID token;仅存在于当前服务端执行内存。 */
252
+ idToken: string;
253
+ }
254
+ );
255
+
221
256
  /** 同步读取当前执行的连接快照;未连接或暂不可用时抛出安全错误,不在 getter 内刷新。 */
222
257
  export function getWorkspaceConnection(): Readonly<WorkspaceConnection>;
223
258
 
@@ -1,4 +1,13 @@
1
1
  const SERVER_FUNCTION_MARKER = Symbol.for("zhike.server-function.v1");
2
+ export { defineWorkflowStep, defineWorkflowStepExecute } from "./steps/index.js";
3
+ export { defineWorkflowTrigger, defineWorkflowTriggerActivate, defineWorkflowTriggerOnEvent, defineWorkflowTriggerDeactivate } from "./triggers/index.js";
4
+ export {
5
+ defineWorkflowBlock,
6
+ defineWorkflowBlockExecute,
7
+ defineWorkflowBlockActivate,
8
+ defineWorkflowBlockTrigger,
9
+ defineWorkflowBlockDeactivate,
10
+ } from "./workflow-blocks/index.js";
2
11
  const LIFECYCLE_EVENT_MARKER = Symbol.for("zhike.lifecycle-event.v1");
3
12
  const WEBHOOK_HANDLER_MARKER = Symbol.for("zhike.webhook-handler.v1");
4
13
  const WORKSPACE_CONNECTION_EVENTS = new Set([
@@ -145,11 +154,23 @@ export function getWorkspaceConnection() {
145
154
  error.code = code;
146
155
  throw error;
147
156
  }
157
+ if (connection.protocol === "oidc" && (typeof connection.idToken !== "string" || !connection.idToken)) {
158
+ const error = new Error("connection_credential_unavailable");
159
+ error.code = "connection_credential_unavailable";
160
+ throw error;
161
+ }
162
+ const protocol = connection.type === "secret"
163
+ ? "secret"
164
+ : (connection.protocol === "oidc" && typeof connection.idToken === "string" && connection.idToken
165
+ ? "oidc" : "oauth2");
148
166
  return Object.freeze({
149
167
  id: connection.id,
150
168
  generation: connection.generation,
151
169
  type: connection.type,
170
+ protocol,
152
171
  value: connection.value,
172
+ ...(connection.type === "oauth2" ? { accessToken: connection.value } : {}),
173
+ ...(protocol === "oidc" ? { idToken: connection.idToken } : {}),
153
174
  });
154
175
  }
155
176
 
@@ -0,0 +1,71 @@
1
+ export type WorkflowScalarSchema =
2
+ | { readonly type: "string"; readonly minLength?: number; readonly enum?: readonly string[]; readonly title?: string; readonly description?: string; readonly examples?: readonly string[] }
3
+ | { readonly type: "number"; readonly title?: string; readonly description?: string; readonly examples?: readonly number[] }
4
+ | { readonly type: "boolean"; readonly title?: string; readonly description?: string; readonly examples?: readonly boolean[] };
5
+
6
+ export interface WorkflowObjectSchema {
7
+ readonly type: "object";
8
+ readonly properties: Readonly<Record<string, WorkflowScalarSchema>>;
9
+ readonly required?: readonly string[];
10
+ readonly additionalProperties: false;
11
+ readonly title?: string;
12
+ readonly description?: string;
13
+ readonly examples?: readonly (string | number | boolean)[];
14
+ }
15
+
16
+ export interface WorkflowStepOutcome {
17
+ readonly id: string;
18
+ readonly label: string;
19
+ readonly dataSchema: WorkflowObjectSchema | null;
20
+ }
21
+
22
+ export interface WorkflowStepDefinition<
23
+ Config extends WorkflowObjectSchema = WorkflowObjectSchema,
24
+ Outcomes extends readonly WorkflowStepOutcome[] = readonly WorkflowStepOutcome[],
25
+ > {
26
+ readonly key: string;
27
+ readonly title: string;
28
+ readonly description?: string;
29
+ readonly connection: "workspace" | "none";
30
+ readonly configSchema: Config;
31
+ readonly outcomes: Outcomes;
32
+ }
33
+
34
+ type ScalarValue<S> = S extends { readonly enum: readonly (infer E)[] } ? E
35
+ : S extends { readonly type: "string" } ? string
36
+ : S extends { readonly type: "number" } ? number
37
+ : S extends { readonly type: "boolean" } ? boolean
38
+ : never;
39
+
40
+ type RequiredNames<S extends WorkflowObjectSchema> = S["required"] extends readonly string[]
41
+ ? S["required"][number] : never;
42
+
43
+ export type WorkflowSchemaValue<S extends WorkflowObjectSchema> = {
44
+ [K in keyof S["properties"] as K extends RequiredNames<S> ? K : never]-?: ScalarValue<S["properties"][K]>;
45
+ } & {
46
+ [K in keyof S["properties"] as K extends RequiredNames<S> ? never : K]?: ScalarValue<S["properties"][K]>;
47
+ };
48
+
49
+ type OutcomeResult<O extends WorkflowStepOutcome> = O extends WorkflowStepOutcome
50
+ ? O["dataSchema"] extends WorkflowObjectSchema
51
+ ? { readonly outcome: O["id"]; readonly data: WorkflowSchemaValue<O["dataSchema"]> }
52
+ : { readonly outcome: O["id"]; readonly data: null }
53
+ : never;
54
+
55
+ export type WorkflowStepResult<Outcomes extends readonly WorkflowStepOutcome[]> =
56
+ OutcomeResult<Outcomes[number]>;
57
+
58
+ export function defineWorkflowStep<
59
+ const Config extends WorkflowObjectSchema,
60
+ const Outcomes extends readonly [WorkflowStepOutcome, ...WorkflowStepOutcome[]],
61
+ >(definition: WorkflowStepDefinition<Config, Outcomes>): WorkflowStepDefinition<Config, Outcomes>;
62
+
63
+ export function defineWorkflowStepExecute<
64
+ Config extends WorkflowObjectSchema,
65
+ Outcomes extends readonly WorkflowStepOutcome[],
66
+ >(
67
+ step: WorkflowStepDefinition<Config, Outcomes>,
68
+ execute: (params: Readonly<{ config: WorkflowSchemaValue<Config> }>) =>
69
+ WorkflowStepResult<Outcomes> | Promise<WorkflowStepResult<Outcomes>>,
70
+ ): (params: Readonly<{ config: WorkflowSchemaValue<Config> }>) =>
71
+ WorkflowStepResult<Outcomes> | Promise<WorkflowStepResult<Outcomes>>;
@@ -0,0 +1,15 @@
1
+ const STEP_MARKER = Symbol.for("zhike.workflow-step.v1");
2
+
3
+ export function defineWorkflowStep(definition) {
4
+ if (!definition || typeof definition !== "object") {
5
+ throw new TypeError("workflow_step_definition_invalid");
6
+ }
7
+ return Object.freeze({ ...definition, [STEP_MARKER]: true });
8
+ }
9
+
10
+ export function defineWorkflowStepExecute(step, execute) {
11
+ if (!step?.[STEP_MARKER] || typeof execute !== "function") {
12
+ throw new TypeError("workflow_step_execute_invalid");
13
+ }
14
+ return execute;
15
+ }
@@ -0,0 +1,68 @@
1
+ import type { WorkflowObjectSchema, WorkflowSchemaValue } from "../steps/index.js";
2
+
3
+ export interface WorkflowTriggerOutcome {
4
+ readonly id: string;
5
+ readonly label: string;
6
+ readonly dataSchema: WorkflowObjectSchema;
7
+ }
8
+
9
+ export interface WorkflowTriggerDefinition<
10
+ Config extends WorkflowObjectSchema = WorkflowObjectSchema,
11
+ Outcomes extends readonly WorkflowTriggerOutcome[] = readonly WorkflowTriggerOutcome[],
12
+ > {
13
+ readonly key: string;
14
+ readonly title: string;
15
+ readonly description?: string;
16
+ readonly connection: "workspace" | "none";
17
+ readonly requestHeaders?: readonly string[];
18
+ readonly configSchema: Config;
19
+ readonly outcomes: Outcomes;
20
+ }
21
+
22
+ type OutcomeResult<O extends WorkflowTriggerOutcome> = O extends WorkflowTriggerOutcome
23
+ ? {
24
+ readonly type: "outcome";
25
+ readonly id: O["id"];
26
+ readonly eventKey: string;
27
+ readonly data: WorkflowSchemaValue<O["dataSchema"]>;
28
+ }
29
+ : never;
30
+
31
+ export type WorkflowTriggerEventResult<Outcomes extends readonly WorkflowTriggerOutcome[]> =
32
+ | { readonly type: "no-op" }
33
+ | { readonly type: "error"; readonly code: "invalid_signature"; readonly retryable: false }
34
+ | OutcomeResult<Outcomes[number]>;
35
+
36
+ export function defineWorkflowTrigger<
37
+ const Config extends WorkflowObjectSchema,
38
+ const Outcomes extends readonly [WorkflowTriggerOutcome, ...WorkflowTriggerOutcome[]],
39
+ >(definition: WorkflowTriggerDefinition<Config, Outcomes>): WorkflowTriggerDefinition<Config, Outcomes>;
40
+
41
+ export function defineWorkflowTriggerActivate<Config extends WorkflowObjectSchema>(
42
+ trigger: WorkflowTriggerDefinition<Config>,
43
+ handler: (params: Readonly<{
44
+ config: WorkflowSchemaValue<Config>;
45
+ activationId: string;
46
+ triggerCallbackUrl: string;
47
+ }>) => Promise<Readonly<{ subscriptionRef: string | null }>>,
48
+ ): typeof handler;
49
+
50
+ export function defineWorkflowTriggerOnEvent<
51
+ Config extends WorkflowObjectSchema,
52
+ Outcomes extends readonly WorkflowTriggerOutcome[],
53
+ >(
54
+ trigger: WorkflowTriggerDefinition<Config, Outcomes>,
55
+ handler: (params: Readonly<{
56
+ config: WorkflowSchemaValue<Config>;
57
+ body: string;
58
+ headers: Readonly<Record<string, string>>;
59
+ }>) => Promise<WorkflowTriggerEventResult<Outcomes>>,
60
+ ): typeof handler;
61
+
62
+ export function defineWorkflowTriggerDeactivate(
63
+ trigger: WorkflowTriggerDefinition,
64
+ handler: (params: Readonly<{
65
+ activationId: string;
66
+ subscriptionRef: string | null;
67
+ }>) => Promise<void>,
68
+ ): typeof handler;
@@ -0,0 +1,27 @@
1
+ const TRIGGER_MARKER = Symbol.for("zhike.workflow-trigger.v1");
2
+
3
+ export function defineWorkflowTrigger(definition) {
4
+ if (!definition || typeof definition !== "object" || Array.isArray(definition)) {
5
+ throw new TypeError("workflow_trigger_definition_invalid");
6
+ }
7
+ return Object.freeze({ ...definition, [TRIGGER_MARKER]: true });
8
+ }
9
+
10
+ function bindTriggerHandler(trigger, handler, kind) {
11
+ if (!trigger?.[TRIGGER_MARKER] || typeof handler !== "function") {
12
+ throw new TypeError(`workflow_trigger_${kind}_invalid`);
13
+ }
14
+ return handler;
15
+ }
16
+
17
+ export function defineWorkflowTriggerActivate(trigger, handler) {
18
+ return bindTriggerHandler(trigger, handler, "activate");
19
+ }
20
+
21
+ export function defineWorkflowTriggerOnEvent(trigger, handler) {
22
+ return bindTriggerHandler(trigger, handler, "on_event");
23
+ }
24
+
25
+ export function defineWorkflowTriggerDeactivate(trigger, handler) {
26
+ return bindTriggerHandler(trigger, handler, "deactivate");
27
+ }
@@ -0,0 +1,72 @@
1
+ import type {
2
+ WorkflowObjectSchema,
3
+ WorkflowSchemaValue,
4
+ WorkflowStepDefinition,
5
+ WorkflowStepOutcome,
6
+ WorkflowStepResult,
7
+ } from "../steps/index.js";
8
+ import type {
9
+ WorkflowTriggerDefinition,
10
+ WorkflowTriggerEventResult,
11
+ WorkflowTriggerOutcome,
12
+ } from "../triggers/index.js";
13
+
14
+ export type WorkflowStepBlockDefinition<
15
+ Config extends WorkflowObjectSchema = WorkflowObjectSchema,
16
+ Outcomes extends readonly WorkflowStepOutcome[] = readonly WorkflowStepOutcome[],
17
+ > = WorkflowStepDefinition<Config, Outcomes> & { readonly type: "step" };
18
+
19
+ export type WorkflowTriggerBlockDefinition<
20
+ Config extends WorkflowObjectSchema = WorkflowObjectSchema,
21
+ Outcomes extends readonly WorkflowTriggerOutcome[] = readonly WorkflowTriggerOutcome[],
22
+ > = WorkflowTriggerDefinition<Config, Outcomes> & { readonly type: "trigger" };
23
+
24
+ export type WorkflowBlockDefinition = WorkflowStepBlockDefinition | WorkflowTriggerBlockDefinition;
25
+
26
+ export function defineWorkflowBlock<
27
+ const Config extends WorkflowObjectSchema,
28
+ const Outcomes extends readonly [WorkflowStepOutcome, ...WorkflowStepOutcome[]],
29
+ >(definition: WorkflowStepBlockDefinition<Config, Outcomes>): WorkflowStepBlockDefinition<Config, Outcomes>;
30
+
31
+ export function defineWorkflowBlock<
32
+ const Config extends WorkflowObjectSchema,
33
+ const Outcomes extends readonly [WorkflowTriggerOutcome, ...WorkflowTriggerOutcome[]],
34
+ >(definition: WorkflowTriggerBlockDefinition<Config, Outcomes>): WorkflowTriggerBlockDefinition<Config, Outcomes>;
35
+
36
+ export function defineWorkflowBlockExecute<
37
+ Config extends WorkflowObjectSchema,
38
+ Outcomes extends readonly WorkflowStepOutcome[],
39
+ >(
40
+ block: WorkflowStepBlockDefinition<Config, Outcomes>,
41
+ execute: (params: Readonly<{ config: WorkflowSchemaValue<Config> }>) =>
42
+ WorkflowStepResult<Outcomes> | Promise<WorkflowStepResult<Outcomes>>,
43
+ ): typeof execute;
44
+
45
+ export function defineWorkflowBlockActivate<Config extends WorkflowObjectSchema>(
46
+ block: WorkflowTriggerBlockDefinition<Config>,
47
+ handler: (params: Readonly<{
48
+ config: WorkflowSchemaValue<Config>;
49
+ activationId: string;
50
+ triggerCallbackUrl: string;
51
+ }>) => Promise<Readonly<{ subscriptionRef: string | null }>>,
52
+ ): typeof handler;
53
+
54
+ export function defineWorkflowBlockTrigger<
55
+ Config extends WorkflowObjectSchema,
56
+ Outcomes extends readonly WorkflowTriggerOutcome[],
57
+ >(
58
+ block: WorkflowTriggerBlockDefinition<Config, Outcomes>,
59
+ handler: (params: Readonly<{
60
+ config: WorkflowSchemaValue<Config>;
61
+ body: string;
62
+ headers: Readonly<Record<string, string>>;
63
+ }>) => Promise<WorkflowTriggerEventResult<Outcomes>>,
64
+ ): typeof handler;
65
+
66
+ export function defineWorkflowBlockDeactivate(
67
+ block: WorkflowTriggerBlockDefinition,
68
+ handler: (params: Readonly<{
69
+ activationId: string;
70
+ subscriptionRef: string | null;
71
+ }>) => Promise<void>,
72
+ ): typeof handler;
@@ -0,0 +1,32 @@
1
+ const WORKFLOW_BLOCK_MARKER = Symbol.for("zhike.workflow-block.v1");
2
+
3
+ export function defineWorkflowBlock(definition) {
4
+ if (!definition || typeof definition !== "object" || Array.isArray(definition) ||
5
+ !["step", "trigger"].includes(definition.type)) {
6
+ throw new TypeError("workflow_block_definition_invalid");
7
+ }
8
+ return Object.freeze({ ...definition, [WORKFLOW_BLOCK_MARKER]: true });
9
+ }
10
+
11
+ function bindWorkflowBlockHandler(block, handler, type, kind) {
12
+ if (!block?.[WORKFLOW_BLOCK_MARKER] || block.type !== type || typeof handler !== "function") {
13
+ throw new TypeError(`workflow_block_${kind}_invalid`);
14
+ }
15
+ return handler;
16
+ }
17
+
18
+ export function defineWorkflowBlockExecute(block, handler) {
19
+ return bindWorkflowBlockHandler(block, handler, "step", "execute");
20
+ }
21
+
22
+ export function defineWorkflowBlockActivate(block, handler) {
23
+ return bindWorkflowBlockHandler(block, handler, "trigger", "activate");
24
+ }
25
+
26
+ export function defineWorkflowBlockTrigger(block, handler) {
27
+ return bindWorkflowBlockHandler(block, handler, "trigger", "trigger");
28
+ }
29
+
30
+ export function defineWorkflowBlockDeactivate(block, handler) {
31
+ return bindWorkflowBlockHandler(block, handler, "trigger", "deactivate");
32
+ }
@@ -0,0 +1,7 @@
1
+ {
2
+ "@77-zhike/qiqi-openapi": {
3
+ "versions": ["0.1.0"],
4
+ "targets": ["server"],
5
+ "subpaths": ["."]
6
+ }
7
+ }