@oomol-lab/open-flow 0.1.0-beta.57 → 0.1.0-beta.59
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/dist/browser/event-sources.d.ts +1 -0
- package/dist/browser/{flowChanges-fBiAeTzR.js → flowChanges-DL0Njlg6.js} +129 -122
- package/dist/browser/{flowWorkspace-MqcEfg7T.js → flowWorkspace-Cp5CcEGu.js} +3 -2
- package/dist/browser/preview.css +91 -0
- package/dist/browser/preview.js +121 -120
- package/dist/browser/ui.css +91 -0
- package/dist/browser/ui.d.ts +17 -0
- package/dist/browser/ui.js +1412 -9
- package/dist/browser/workbench.css +91 -0
- package/dist/browser/workbench.js +2 -2
- package/dist/common/control-requests.js +1 -1
- package/dist/common/event-source-definition.d.ts +39 -0
- package/dist/common/event-source-feishu.d.ts +3 -0
- package/dist/common/event-source.d.ts +6 -0
- package/dist/common/event-source.js +289 -0
- package/dist/common/feishu-events.d.ts +1 -1
- package/dist/common/flow-semantics.js +4 -4
- package/package.json +5 -1
|
@@ -4172,6 +4172,60 @@ html[data-overlayscrollbars-viewport~=scrollbarHidden] > body::-webkit-scrollbar
|
|
|
4172
4172
|
background-color: #0000;
|
|
4173
4173
|
}
|
|
4174
4174
|
|
|
4175
|
+
:where(.open-flow-theme, .open-flow-workbench, .open-flow-canvas-root) .group-data-\[variant\=navigation\]\/tabs-list\:h-auto:is(:where(.group\/tabs-list)[data-variant="navigation"] *) {
|
|
4176
|
+
height: auto;
|
|
4177
|
+
}
|
|
4178
|
+
|
|
4179
|
+
:where(.open-flow-theme, .open-flow-workbench, .open-flow-canvas-root) .group-data-\[variant\=navigation\]\/tabs-list\:flex-none:is(:where(.group\/tabs-list)[data-variant="navigation"] *) {
|
|
4180
|
+
flex: none;
|
|
4181
|
+
}
|
|
4182
|
+
|
|
4183
|
+
:where(.open-flow-theme, .open-flow-workbench, .open-flow-canvas-root) .group-data-\[variant\=navigation\]\/tabs-list\:rounded-\[6px\]:is(:where(.group\/tabs-list)[data-variant="navigation"] *) {
|
|
4184
|
+
border-radius: 6px;
|
|
4185
|
+
}
|
|
4186
|
+
|
|
4187
|
+
:where(.open-flow-theme, .open-flow-workbench, .open-flow-canvas-root) .group-data-\[variant\=navigation\]\/tabs-list\:border-0:is(:where(.group\/tabs-list)[data-variant="navigation"] *) {
|
|
4188
|
+
border-style: var(--tw-border-style);
|
|
4189
|
+
border-width: 0;
|
|
4190
|
+
}
|
|
4191
|
+
|
|
4192
|
+
:where(.open-flow-theme, .open-flow-workbench, .open-flow-canvas-root) .group-data-\[variant\=navigation\]\/tabs-list\:px-3:is(:where(.group\/tabs-list)[data-variant="navigation"] *) {
|
|
4193
|
+
padding-inline: calc(var(--spacing) * 3);
|
|
4194
|
+
}
|
|
4195
|
+
|
|
4196
|
+
:where(.open-flow-theme, .open-flow-workbench, .open-flow-canvas-root) .group-data-\[variant\=navigation\]\/tabs-list\:py-2:is(:where(.group\/tabs-list)[data-variant="navigation"] *) {
|
|
4197
|
+
padding-block: calc(var(--spacing) * 2);
|
|
4198
|
+
}
|
|
4199
|
+
|
|
4200
|
+
:where(.open-flow-theme, .open-flow-workbench, .open-flow-canvas-root) .group-data-\[variant\=navigation\]\/tabs-list\:text-\[13px\]:is(:where(.group\/tabs-list)[data-variant="navigation"] *) {
|
|
4201
|
+
font-size: 13px;
|
|
4202
|
+
}
|
|
4203
|
+
|
|
4204
|
+
:where(.open-flow-theme, .open-flow-workbench, .open-flow-canvas-root) .group-data-\[variant\=navigation\]\/tabs-list\:font-normal:is(:where(.group\/tabs-list)[data-variant="navigation"] *) {
|
|
4205
|
+
--tw-font-weight: var(--font-weight-normal);
|
|
4206
|
+
font-weight: var(--font-weight-normal);
|
|
4207
|
+
}
|
|
4208
|
+
|
|
4209
|
+
:where(.open-flow-theme, .open-flow-workbench, .open-flow-canvas-root) .group-data-\[variant\=navigation\]\/tabs-list\:text-muted-foreground:is(:where(.group\/tabs-list)[data-variant="navigation"] *) {
|
|
4210
|
+
color: var(--ui-muted-foreground);
|
|
4211
|
+
}
|
|
4212
|
+
|
|
4213
|
+
:where(.open-flow-theme, .open-flow-workbench, .open-flow-canvas-root) .group-data-\[variant\=navigation\]\/tabs-list\:group-data-\[size\=sm\]\/tabs-list\:rounded-\[4px\]:is(:where(.group\/tabs-list)[data-variant="navigation"] *):is(:where(.group\/tabs-list)[data-size="sm"] *) {
|
|
4214
|
+
border-radius: 4px;
|
|
4215
|
+
}
|
|
4216
|
+
|
|
4217
|
+
:where(.open-flow-theme, .open-flow-workbench, .open-flow-canvas-root) .group-data-\[variant\=navigation\]\/tabs-list\:group-data-\[size\=sm\]\/tabs-list\:px-2:is(:where(.group\/tabs-list)[data-variant="navigation"] *):is(:where(.group\/tabs-list)[data-size="sm"] *) {
|
|
4218
|
+
padding-inline: calc(var(--spacing) * 2);
|
|
4219
|
+
}
|
|
4220
|
+
|
|
4221
|
+
:where(.open-flow-theme, .open-flow-workbench, .open-flow-canvas-root) .group-data-\[variant\=navigation\]\/tabs-list\:group-data-\[size\=sm\]\/tabs-list\:py-1:is(:where(.group\/tabs-list)[data-variant="navigation"] *):is(:where(.group\/tabs-list)[data-size="sm"] *) {
|
|
4222
|
+
padding-block: var(--spacing);
|
|
4223
|
+
}
|
|
4224
|
+
|
|
4225
|
+
:where(.open-flow-theme, .open-flow-workbench, .open-flow-canvas-root) .group-data-\[variant\=navigation\]\/tabs-list\:group-data-\[size\=sm\]\/tabs-list\:text-\[12px\]:is(:where(.group\/tabs-list)[data-variant="navigation"] *):is(:where(.group\/tabs-list)[data-size="sm"] *) {
|
|
4226
|
+
font-size: 12px;
|
|
4227
|
+
}
|
|
4228
|
+
|
|
4175
4229
|
:where(.open-flow-theme, .open-flow-workbench, .open-flow-canvas-root) .peer-disabled\:cursor-not-allowed:is(:where(.peer):disabled ~ *) {
|
|
4176
4230
|
cursor: not-allowed;
|
|
4177
4231
|
}
|
|
@@ -4492,6 +4546,14 @@ html[data-overlayscrollbars-viewport~=scrollbarHidden] > body::-webkit-scrollbar
|
|
|
4492
4546
|
box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
|
|
4493
4547
|
}
|
|
4494
4548
|
|
|
4549
|
+
:where(.open-flow-theme, .open-flow-workbench, .open-flow-canvas-root) .group-data-\[variant\=navigation\]\/tabs-list\:hover\:bg-muted:is(:where(.group\/tabs-list)[data-variant="navigation"] *):hover {
|
|
4550
|
+
background-color: var(--ui-muted);
|
|
4551
|
+
}
|
|
4552
|
+
|
|
4553
|
+
:where(.open-flow-theme, .open-flow-workbench, .open-flow-canvas-root) .group-data-\[variant\=navigation\]\/tabs-list\:hover\:text-foreground:is(:where(.group\/tabs-list)[data-variant="navigation"] *):hover {
|
|
4554
|
+
color: var(--ui-foreground);
|
|
4555
|
+
}
|
|
4556
|
+
|
|
4495
4557
|
:where(.open-flow-theme, .open-flow-workbench, .open-flow-canvas-root) .hover\:placeholder\:opacity-50:hover::placeholder {
|
|
4496
4558
|
opacity: .5;
|
|
4497
4559
|
}
|
|
@@ -5035,6 +5097,19 @@ html[data-overlayscrollbars-viewport~=scrollbarHidden] > body::-webkit-scrollbar
|
|
|
5035
5097
|
box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
|
|
5036
5098
|
}
|
|
5037
5099
|
|
|
5100
|
+
:where(.open-flow-theme, .open-flow-workbench, .open-flow-canvas-root) .group-data-\[variant\=navigation\]\/tabs-list\:data-active\:bg-muted:is(:where(.group\/tabs-list)[data-variant="navigation"] *)[data-active] {
|
|
5101
|
+
background-color: var(--ui-muted);
|
|
5102
|
+
}
|
|
5103
|
+
|
|
5104
|
+
:where(.open-flow-theme, .open-flow-workbench, .open-flow-canvas-root) .group-data-\[variant\=navigation\]\/tabs-list\:data-active\:font-semibold:is(:where(.group\/tabs-list)[data-variant="navigation"] *)[data-active] {
|
|
5105
|
+
--tw-font-weight: var(--font-weight-semibold);
|
|
5106
|
+
font-weight: var(--font-weight-semibold);
|
|
5107
|
+
}
|
|
5108
|
+
|
|
5109
|
+
:where(.open-flow-theme, .open-flow-workbench, .open-flow-canvas-root) .group-data-\[variant\=navigation\]\/tabs-list\:data-active\:text-foreground:is(:where(.group\/tabs-list)[data-variant="navigation"] *)[data-active] {
|
|
5110
|
+
color: var(--ui-foreground);
|
|
5111
|
+
}
|
|
5112
|
+
|
|
5038
5113
|
:where(.open-flow-theme, .open-flow-workbench, .open-flow-canvas-root) .group-data-\[variant\=line\]\/tabs-list\:data-active\:after\:opacity-100:is(:where(.group\/tabs-list)[data-variant="line"] *)[data-active]:after {
|
|
5039
5114
|
content: var(--tw-content);
|
|
5040
5115
|
opacity: 1;
|
|
@@ -5577,6 +5652,14 @@ html[data-overlayscrollbars-viewport~=scrollbarHidden] > body::-webkit-scrollbar
|
|
|
5577
5652
|
border-radius: 0;
|
|
5578
5653
|
}
|
|
5579
5654
|
|
|
5655
|
+
:where(.open-flow-theme, .open-flow-workbench, .open-flow-canvas-root) .data-\[variant\=navigation\]\:p-0[data-variant="navigation"] {
|
|
5656
|
+
padding: 0;
|
|
5657
|
+
}
|
|
5658
|
+
|
|
5659
|
+
:where(.open-flow-theme, .open-flow-workbench, .open-flow-canvas-root) .group-data-\[orientation\=horizontal\]\/tabs\:data-\[variant\=navigation\]\:h-auto:is(:where(.group\/tabs)[data-orientation="horizontal"] *)[data-variant="navigation"] {
|
|
5660
|
+
height: auto;
|
|
5661
|
+
}
|
|
5662
|
+
|
|
5580
5663
|
:where(.open-flow-theme, .open-flow-workbench, .open-flow-canvas-root) .data-\[variant\=outline\]\:bg-background[data-variant="outline"] {
|
|
5581
5664
|
background-color: var(--ui-background);
|
|
5582
5665
|
}
|
|
@@ -6011,6 +6094,14 @@ html[data-overlayscrollbars-viewport~=scrollbarHidden] > body::-webkit-scrollbar
|
|
|
6011
6094
|
background-color: #0000;
|
|
6012
6095
|
}
|
|
6013
6096
|
|
|
6097
|
+
:where(.open-flow-theme, .open-flow-workbench, .open-flow-canvas-root) .dark\:group-data-\[variant\=navigation\]\/tabs-list\:data-active\:bg-muted:where([data-theme="dark"], [data-theme="dark"] *):is(:where(.group\/tabs-list)[data-variant="navigation"] *)[data-active] {
|
|
6098
|
+
background-color: var(--ui-muted);
|
|
6099
|
+
}
|
|
6100
|
+
|
|
6101
|
+
:where(.open-flow-theme, .open-flow-workbench, .open-flow-canvas-root) .dark\:group-data-\[variant\=navigation\]\/tabs-list\:data-active\:text-foreground:where([data-theme="dark"], [data-theme="dark"] *):is(:where(.group\/tabs-list)[data-variant="navigation"] *)[data-active] {
|
|
6102
|
+
color: var(--ui-foreground);
|
|
6103
|
+
}
|
|
6104
|
+
|
|
6014
6105
|
:where(.open-flow-theme, .open-flow-workbench, .open-flow-canvas-root) .dark\:data-checked\:bg-primary-foreground:where([data-theme="dark"], [data-theme="dark"] *)[data-checked] {
|
|
6015
6106
|
background-color: var(--ui-primary-foreground);
|
|
6016
6107
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { $ as RunStore, $t as EventSourcesPage, An as providerIconAppearance, At as followWorkbenchLink, B as CacheResource, Bn as invalidResponse, Cn as sampleErrorOutputs, Ct as setCodeActions, Dt as updateTriggerConfig, Et as setTriggerConnection, F as feishuResourceKind, Gn as controlErrorCode, Gt as InputGroupAddon, H as resourceData, Hn as record, I as supportsFeishuChatFilter, J as providerIcon, Jt as EmptyContent, Kt as InputGroupInput, L as combineSources, Lt as PopoverTitle, M as addNodeIntent, Mt as Popover, N as deriveAddNodeOptions, Nt as PopoverContent, On as connection, Ot as updateTriggerSchedule, Qt as EmptyTitle, Rt as PopoverTrigger, St as resetInputValues, Tn as isJsonObject, Tt as setInputSources, U as resourceValue, Un as string, Vn as jsonValue, W as designerGraph, Wn as ApiError, Wt as InputGroup, Xt as EmptyHeader, Yt as EmptyDescription, Zt as EmptyMedia, _ as updateValue, _n as randomId, _t as setComment, a as nameCreatedNodes, at as deriveInspectorDiagnostics, bn as decodeTriggerCatalog, bt as setNodePositions, c as updateCondition, d as updateNodeName, dt as connectionCatalog, f as updateNodeSettings, ft as canvasPresentationChange, g as updateTaskPorts, gn as WorkbenchClient, gt as restoreCanvasPresentation, h as updateTaskAdditionalInputs, hn as errorNotice, ht as removeComments, i as deleteSelection, it as Latest, jt as Switch, kn as connectorActionMetadata, kt as IdTooltip, l as updateNodeDescription, m as updateTask, mt as flowPresentation, nn as createI18n, nt as revisionView, o as setInputValue, ot as diagnosticItems, p as updateResolution, pt as commentIds, qn as IconThemeContext, qt as Empty, r as applyFlowChanges, rt as flowResourceReferences, s as setInputVariable, t as addNode, u as updateNodeIcon, ut as actionWithConnections, v as updateWebhook, vn as allConnectorConnectionsQuery, vt as setFlowViewport, wn as triggerOutputDefinitions, wt as setConnectorConnection, xt as repairNodeNames, yt as setNodeContentHidden, z as scopedValue, zn as inputValue } from "./flowChanges-
|
|
1
|
+
import { $ as RunStore, $t as EventSourcesPage, An as providerIconAppearance, At as followWorkbenchLink, B as CacheResource, Bn as invalidResponse, Cn as sampleErrorOutputs, Ct as setCodeActions, Dt as updateTriggerConfig, Et as setTriggerConnection, F as feishuResourceKind, Gn as controlErrorCode, Gt as InputGroupAddon, H as resourceData, Hn as record, I as supportsFeishuChatFilter, J as providerIcon, Jt as EmptyContent, Kt as InputGroupInput, L as combineSources, Lt as PopoverTitle, M as addNodeIntent, Mt as Popover, N as deriveAddNodeOptions, Nt as PopoverContent, On as connection, Ot as updateTriggerSchedule, Qt as EmptyTitle, Rt as PopoverTrigger, St as resetInputValues, Tn as isJsonObject, Tt as setInputSources, U as resourceValue, Un as string, Vn as jsonValue, W as designerGraph, Wn as ApiError, Wt as InputGroup, Xt as EmptyHeader, Yt as EmptyDescription, Zt as EmptyMedia, _ as updateValue, _n as randomId, _t as setComment, a as nameCreatedNodes, at as deriveInspectorDiagnostics, bn as decodeTriggerCatalog, bt as setNodePositions, c as updateCondition, d as updateNodeName, dt as connectionCatalog, f as updateNodeSettings, ft as canvasPresentationChange, g as updateTaskPorts, gn as WorkbenchClient, gt as restoreCanvasPresentation, h as updateTaskAdditionalInputs, hn as errorNotice, ht as removeComments, i as deleteSelection, it as Latest, jt as Switch, kn as connectorActionMetadata, kt as IdTooltip, l as updateNodeDescription, m as updateTask, mt as flowPresentation, nn as createI18n, nt as revisionView, o as setInputValue, ot as diagnosticItems, p as updateResolution, pt as commentIds, qn as IconThemeContext, qt as Empty, r as applyFlowChanges, rt as flowResourceReferences, s as setInputVariable, t as addNode, u as updateNodeIcon, ut as actionWithConnections, v as updateWebhook, vn as allConnectorConnectionsQuery, vt as setFlowViewport, wn as triggerOutputDefinitions, wt as setConnectorConnection, xt as repairNodeNames, yt as setNodeContentHidden, z as scopedValue, zn as inputValue } from "./flowChanges-DL0Njlg6.js";
|
|
2
2
|
import { a as derive, i as compute, l as val } from "./dist-bO8nvHFH.js";
|
|
3
3
|
import { a as toPlainObject, c as useLang, l as useTranslate, o as I18nProvider, u as useVal } from "./dist-BFmpkX4P.js";
|
|
4
4
|
import { E as FieldLabel, H as applyFlowChanges$1, J as resourceNameIssue, Q as nodeInputMappings, S as Field, T as FieldGroup, V as FlowChangeError, Z as mapConditionSources, a as DialogDescription, at as dequal$1, bi as cn, c as DialogTitle, d as TooltipContent, i as DialogContent, n as Dialog, o as DialogFooter, or as Input, p as TooltipTrigger, r as DialogClose, s as DialogHeader, t as Icon, u as Tooltip, vi as Button, w as FieldError, x as Spinner } from "./icons-6oQ8Q9Wm.js";
|
|
@@ -6735,7 +6735,7 @@ var WorkbenchStore = class {
|
|
|
6735
6735
|
};
|
|
6736
6736
|
//#endregion
|
|
6737
6737
|
//#region src/workbench/browser/runtime/openFlowWorkbench.tsx
|
|
6738
|
-
var FlowWorkspace = lazy(() => import("./flowWorkspace-
|
|
6738
|
+
var FlowWorkspace = lazy(() => import("./flowWorkspace-Cp5CcEGu.js"));
|
|
6739
6739
|
function OpenFlowSessionGate({ action, description, error, onSubmit, onTokenChange, pending = false, title, token, tokenLabel }) {
|
|
6740
6740
|
const hasToken = token != null && tokenLabel != null && onTokenChange != null;
|
|
6741
6741
|
const tokenValue = token ?? "";
|
|
@@ -14062,7 +14062,7 @@ var schemas = {
|
|
|
14062
14062
|
comment: waitCommentSchema,
|
|
14063
14063
|
version
|
|
14064
14064
|
}),
|
|
14065
|
-
putVariable: strictObject({ value: string().refine((value) => new TextEncoder().encode(value).byteLength <= 65536, "
|
|
14065
|
+
putVariable: strictObject({ value: string().refine((value) => new TextEncoder().encode(value).byteLength <= 65536, "Variable value is too large.") }),
|
|
14066
14066
|
queryConnectorAccessCandidates: strictObject({
|
|
14067
14067
|
providerIds: array(id.max(256)).min(1).refine((ids) => new Set(ids).size == ids.length, "Duplicate provider IDs."),
|
|
14068
14068
|
version
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { JsonValue } from '../browser/flow-change.js';
|
|
2
|
+
export interface SourceConfiguration {
|
|
3
|
+
readonly identity: string;
|
|
4
|
+
readonly eventTypes: string[];
|
|
5
|
+
readonly config: Readonly<Record<string, JsonValue>>;
|
|
6
|
+
readonly secrets: Readonly<Record<string, JsonValue>>;
|
|
7
|
+
readonly state: Readonly<Record<string, JsonValue>>;
|
|
8
|
+
}
|
|
9
|
+
export interface SourceEvent {
|
|
10
|
+
readonly id: string;
|
|
11
|
+
readonly type: string;
|
|
12
|
+
readonly payload: Readonly<Record<string, JsonValue>>;
|
|
13
|
+
}
|
|
14
|
+
export interface SourceSubscription {
|
|
15
|
+
readonly key: string;
|
|
16
|
+
readonly config: Readonly<Record<string, JsonValue>>;
|
|
17
|
+
}
|
|
18
|
+
export interface EventSourceDefinition<Create, Update, View> {
|
|
19
|
+
readonly kind: string;
|
|
20
|
+
readonly provider: string;
|
|
21
|
+
readonly maximumBodyBytes: number;
|
|
22
|
+
readonly initialize: (input: Create, accountId: string | undefined) => SourceConfiguration;
|
|
23
|
+
readonly update: (source: SourceConfiguration, input: Update) => SourceConfiguration;
|
|
24
|
+
readonly view: (source: SourceConfiguration) => View;
|
|
25
|
+
readonly ready: (source: SourceConfiguration) => boolean;
|
|
26
|
+
readonly receive: (source: SourceConfiguration, bytes: Uint8Array, headers: Headers, now: number) => Promise<{
|
|
27
|
+
readonly response: Response;
|
|
28
|
+
readonly state: SourceConfiguration['state'];
|
|
29
|
+
} | {
|
|
30
|
+
readonly event: SourceEvent;
|
|
31
|
+
}>;
|
|
32
|
+
readonly matches: (config: Readonly<Record<string, JsonValue>>, event: SourceEvent) => boolean;
|
|
33
|
+
readonly resources: {
|
|
34
|
+
readonly triggerId: string;
|
|
35
|
+
readonly requests: (source: SourceConfiguration, provider: string, config: Readonly<Record<string, JsonValue>>) => readonly SourceSubscription[];
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
export declare class SourceIdentityError extends Error {
|
|
39
|
+
}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { CreateEventSource, EventSource, UpdateEventSource } from './event-sources.js';
|
|
2
|
+
import type { EventSourceDefinition } from './event-source-definition.js';
|
|
3
|
+
export declare const feishuApplication: EventSourceDefinition<CreateEventSource, UpdateEventSource, Pick<EventSource, 'appId' | 'manageSubscriptions' | 'verificationTokenConfigured' | 'encryptKeyConfigured' | 'verifiedAt'>>;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { feishuApplication } from './event-source-feishu.js';
|
|
2
|
+
export type { EventSourceDefinition, SourceConfiguration, SourceEvent, SourceSubscription } from './event-source-definition.js';
|
|
3
|
+
export { SourceIdentityError } from './event-source-definition.js';
|
|
4
|
+
export { feishuApplication } from './event-source-feishu.js';
|
|
5
|
+
declare const definitions: readonly (typeof feishuApplication)[];
|
|
6
|
+
export declare function eventSourceDefinition(kind: string): (typeof definitions)[number];
|
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
import { PermanentIntegrationError } from "./integration-trigger.js";
|
|
2
|
+
//#region src/base/common/json.ts
|
|
3
|
+
function hasJsonShape(root) {
|
|
4
|
+
if (root === null || typeof root == "boolean" || typeof root == "string") return true;
|
|
5
|
+
if (typeof root == "number") return Number.isFinite(root);
|
|
6
|
+
if (typeof root != "object") return false;
|
|
7
|
+
const ancestors = /* @__PURE__ */ new Set();
|
|
8
|
+
const pending = [];
|
|
9
|
+
let value = root;
|
|
10
|
+
traversal: while (true) {
|
|
11
|
+
let keys;
|
|
12
|
+
let arrayLength;
|
|
13
|
+
if (Array.isArray(value)) {
|
|
14
|
+
arrayLength = value.length;
|
|
15
|
+
keys = Reflect.ownKeys(value);
|
|
16
|
+
if (keys.length != arrayLength + 1) return false;
|
|
17
|
+
} else {
|
|
18
|
+
const prototype = Reflect.getPrototypeOf(value);
|
|
19
|
+
if (prototype != Object.prototype && prototype != null) return false;
|
|
20
|
+
keys = Reflect.ownKeys(value);
|
|
21
|
+
arrayLength = void 0;
|
|
22
|
+
}
|
|
23
|
+
ancestors.add(value);
|
|
24
|
+
let index = 0;
|
|
25
|
+
while (true) {
|
|
26
|
+
if (index >= keys.length) {
|
|
27
|
+
ancestors.delete(value);
|
|
28
|
+
const parent = pending.pop();
|
|
29
|
+
if (parent === void 0) return true;
|
|
30
|
+
value = parent.value;
|
|
31
|
+
keys = parent.keys;
|
|
32
|
+
arrayLength = parent.arrayLength;
|
|
33
|
+
index = parent.index;
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
const key = keys[index++];
|
|
37
|
+
if (arrayLength !== void 0) {
|
|
38
|
+
if (key == "length") continue;
|
|
39
|
+
if (typeof key != "string") return false;
|
|
40
|
+
const arrayIndex = Number(key);
|
|
41
|
+
if (!Number.isSafeInteger(arrayIndex) || arrayIndex < 0 || arrayIndex >= arrayLength || String(arrayIndex) != key) return false;
|
|
42
|
+
} else if (typeof key != "string") return false;
|
|
43
|
+
const descriptor = Reflect.getOwnPropertyDescriptor(value, key);
|
|
44
|
+
if (descriptor?.enumerable != true || !Object.hasOwn(descriptor, "value")) return false;
|
|
45
|
+
const child = descriptor.value;
|
|
46
|
+
if (child === null || typeof child == "boolean" || typeof child == "string") continue;
|
|
47
|
+
if (typeof child == "number") {
|
|
48
|
+
if (!Number.isFinite(child)) return false;
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
if (typeof child != "object" || ancestors.has(child)) return false;
|
|
52
|
+
pending.push({
|
|
53
|
+
value,
|
|
54
|
+
keys,
|
|
55
|
+
arrayLength,
|
|
56
|
+
index
|
|
57
|
+
});
|
|
58
|
+
value = child;
|
|
59
|
+
continue traversal;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
function isJsonObject(value) {
|
|
64
|
+
try {
|
|
65
|
+
return value != null && typeof value == "object" && !Array.isArray(value) && hasJsonShape(value);
|
|
66
|
+
} catch {
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
//#endregion
|
|
71
|
+
//#region src/trigger/providers/feishu/events.ts
|
|
72
|
+
var encoder = new TextEncoder();
|
|
73
|
+
var decoder = new TextDecoder("utf-8", { fatal: true });
|
|
74
|
+
async function receiveFeishuEvent(rawBody, headers, source, now) {
|
|
75
|
+
const envelope = JSON.parse(decoder.decode(rawBody));
|
|
76
|
+
if (!isJsonObject(envelope) || typeof envelope.encrypt != "string" || !/^[A-Za-z0-9+/]+={0,2}$/.test(envelope.encrypt)) throw new TypeError("An encrypted Feishu envelope is required.");
|
|
77
|
+
const bytes = Uint8Array.from(atob(envelope.encrypt), (character) => character.charCodeAt(0));
|
|
78
|
+
if (bytes.length < 32 || bytes.length % 16 != 0) throw new TypeError("Invalid encrypted Feishu envelope.");
|
|
79
|
+
const key = await crypto.subtle.importKey("raw", await crypto.subtle.digest("SHA-256", encoder.encode(source.encryptKey)), "AES-CBC", false, ["decrypt"]);
|
|
80
|
+
const value = JSON.parse(decoder.decode(await crypto.subtle.decrypt({
|
|
81
|
+
name: "AES-CBC",
|
|
82
|
+
iv: bytes.slice(0, 16)
|
|
83
|
+
}, key, bytes.slice(16))));
|
|
84
|
+
if (!isJsonObject(value)) throw new TypeError("Invalid Feishu event.");
|
|
85
|
+
const header = isJsonObject(value.header) ? value.header : void 0;
|
|
86
|
+
if (!sameSecret(header?.token ?? value.token, source.verificationToken)) throw new TypeError("Invalid Feishu verification token.");
|
|
87
|
+
if (value.type == "url_verification") {
|
|
88
|
+
if (typeof value.challenge != "string" || value.challenge.length == 0 || value.challenge.length > 1024) throw new TypeError("Invalid challenge.");
|
|
89
|
+
return { challenge: value.challenge };
|
|
90
|
+
}
|
|
91
|
+
const timestamp = headers.get("x-lark-request-timestamp") ?? "";
|
|
92
|
+
const nonce = headers.get("x-lark-request-nonce") ?? "";
|
|
93
|
+
const signature = headers.get("x-lark-signature") ?? "";
|
|
94
|
+
if (!/^\d{10}$/.test(timestamp) || Math.abs(now - Number(timestamp) * 1e3) > 864e5 || nonce.length == 0 || nonce.length > 256) throw new TypeError("Invalid Feishu request identity.");
|
|
95
|
+
const prefix = encoder.encode(timestamp + nonce + source.encryptKey);
|
|
96
|
+
const signed = new Uint8Array(prefix.length + rawBody.length);
|
|
97
|
+
signed.set(prefix);
|
|
98
|
+
signed.set(rawBody, prefix.length);
|
|
99
|
+
const digest = new Uint8Array(await crypto.subtle.digest("SHA-256", signed));
|
|
100
|
+
if (!sameSecret(signature, Array.from(digest, (byte) => byte.toString(16).padStart(2, "0")).join(""))) throw new TypeError("Invalid Feishu signature.");
|
|
101
|
+
const body = value.event;
|
|
102
|
+
if (!isJsonObject(body)) throw new TypeError("Missing Feishu event body.");
|
|
103
|
+
if (value.schema != null && value.schema != "2.0") throw new TypeError("Unsupported Feishu event schema.");
|
|
104
|
+
const type = header?.event_type ?? body.type;
|
|
105
|
+
const appId = header?.app_id ?? body.app_id ?? value.app_id;
|
|
106
|
+
const tenantKey = header?.tenant_key ?? body.tenant_key ?? value.tenant_key;
|
|
107
|
+
let id = header?.event_id ?? value.uuid;
|
|
108
|
+
if (type == "im.message.receive_v1" && isJsonObject(body.message)) id = body.message.message_id;
|
|
109
|
+
if (typeof id != "string" || id.length == 0 || id.length > 256 || typeof type != "string" || !/^[a-z][a-z0-9_.]{0,127}$/.test(type)) throw new TypeError("Missing Feishu event identity.");
|
|
110
|
+
if (appId != source.appId) throw new TypeError("Feishu event source does not match.");
|
|
111
|
+
if (typeof tenantKey != "string" || tenantKey.length == 0 || tenantKey.length > 256) throw new TypeError("Invalid Feishu event tenant.");
|
|
112
|
+
if (type == "card.action.trigger" || type == "app_ticket") throw new TypeError("This callback is not an asynchronous business event.");
|
|
113
|
+
const { token: _token, ...business } = body;
|
|
114
|
+
const occurredAt = header?.create_time ?? value.ts;
|
|
115
|
+
return { event: {
|
|
116
|
+
id: `${type}:${id}`,
|
|
117
|
+
type,
|
|
118
|
+
appId: source.appId,
|
|
119
|
+
tenantKey,
|
|
120
|
+
occurredAt: typeof occurredAt == "string" ? occurredAt : null,
|
|
121
|
+
body: business
|
|
122
|
+
} };
|
|
123
|
+
}
|
|
124
|
+
function sameSecret(value, expected) {
|
|
125
|
+
if (typeof value != "string" || value.length != expected.length) return false;
|
|
126
|
+
let difference = 0;
|
|
127
|
+
for (let index = 0; index < expected.length; index += 1) difference |= value.charCodeAt(index) ^ expected.charCodeAt(index);
|
|
128
|
+
return difference == 0;
|
|
129
|
+
}
|
|
130
|
+
function matchesFeishuEvent(config, event) {
|
|
131
|
+
if (!Array.isArray(config.eventTypes) || !config.eventTypes.includes(event.type)) return false;
|
|
132
|
+
const chatIds = config.chatIds;
|
|
133
|
+
if (Array.isArray(chatIds) && chatIds.length > 0) {
|
|
134
|
+
const chatId = isJsonObject(event.body.message) ? event.body.message.chat_id : event.body.chat_id;
|
|
135
|
+
if (typeof chatId != "string" || !chatIds.includes(chatId)) return false;
|
|
136
|
+
}
|
|
137
|
+
const resource = config.resource;
|
|
138
|
+
if (isJsonObject(resource)) {
|
|
139
|
+
if ((resource.kind == "document" ? event.body.file_token : resource.kind == "calendar" ? event.body.calendar_id : event.body.approval_code) != resource.id) return false;
|
|
140
|
+
}
|
|
141
|
+
return true;
|
|
142
|
+
}
|
|
143
|
+
//#endregion
|
|
144
|
+
//#region src/trigger/providers/feishu/config.ts
|
|
145
|
+
function feishuResourceKind(events) {
|
|
146
|
+
if (events.length == 0) return;
|
|
147
|
+
if (events.every((event) => event.startsWith("drive.file."))) return "document";
|
|
148
|
+
if (events.every((event) => event == "calendar.calendar.event.changed_v4")) return "calendar";
|
|
149
|
+
if (events.every((event) => [
|
|
150
|
+
"approval_instance",
|
|
151
|
+
"approval_task",
|
|
152
|
+
"approval_cc",
|
|
153
|
+
"approval"
|
|
154
|
+
].includes(event))) return "approval";
|
|
155
|
+
}
|
|
156
|
+
//#endregion
|
|
157
|
+
//#region src/trigger/providers/feishu/subscriptions.ts
|
|
158
|
+
function feishuSubscriptions(config, provider) {
|
|
159
|
+
if (config.resource == null) return [];
|
|
160
|
+
if (!isJsonObject(config.resource)) throw new PermanentIntegrationError("Invalid Feishu resource.");
|
|
161
|
+
const { kind, id, documentType } = config.resource;
|
|
162
|
+
if (typeof id != "string" || id.length == 0 || kind != feishuResourceKind(config.eventTypes)) throw new PermanentIntegrationError("Invalid resource subscription.");
|
|
163
|
+
if (kind == "document") {
|
|
164
|
+
if (typeof documentType != "string" || ![
|
|
165
|
+
"doc",
|
|
166
|
+
"docx",
|
|
167
|
+
"sheet",
|
|
168
|
+
"bitable",
|
|
169
|
+
"file",
|
|
170
|
+
"folder",
|
|
171
|
+
"slides"
|
|
172
|
+
].includes(documentType)) throw new PermanentIntegrationError("A supported document type is required.");
|
|
173
|
+
return config.eventTypes.map((eventType) => ({
|
|
174
|
+
key: JSON.stringify([
|
|
175
|
+
"document",
|
|
176
|
+
documentType,
|
|
177
|
+
id,
|
|
178
|
+
eventType
|
|
179
|
+
]),
|
|
180
|
+
config: {
|
|
181
|
+
...config,
|
|
182
|
+
eventTypes: [eventType]
|
|
183
|
+
}
|
|
184
|
+
}));
|
|
185
|
+
}
|
|
186
|
+
if (kind == "calendar" || kind == "approval" && provider == "feishu_app_bot") return [{
|
|
187
|
+
key: JSON.stringify([kind, id]),
|
|
188
|
+
config
|
|
189
|
+
}];
|
|
190
|
+
throw new PermanentIntegrationError("Unsupported Feishu resource subscription.");
|
|
191
|
+
}
|
|
192
|
+
//#endregion
|
|
193
|
+
//#region src/event-source/common/definition.ts
|
|
194
|
+
var SourceIdentityError = class extends Error {};
|
|
195
|
+
//#endregion
|
|
196
|
+
//#region src/event-source/common/feishu.ts
|
|
197
|
+
var feishuApplication = {
|
|
198
|
+
kind: "feishu",
|
|
199
|
+
provider: "feishu_app_bot",
|
|
200
|
+
maximumBodyBytes: 65536,
|
|
201
|
+
initialize(input, accountId) {
|
|
202
|
+
if (accountId == null || !/^cli_[a-zA-Z0-9]+$/.test(accountId)) throw new SourceIdentityError("Connector must provide the verified application identity.");
|
|
203
|
+
return {
|
|
204
|
+
identity: accountId,
|
|
205
|
+
eventTypes: input.eventTypes,
|
|
206
|
+
config: { manageSubscriptions: input.manageSubscriptions },
|
|
207
|
+
secrets: {
|
|
208
|
+
verificationToken: input.verificationToken,
|
|
209
|
+
encryptKey: input.encryptKey
|
|
210
|
+
},
|
|
211
|
+
state: {}
|
|
212
|
+
};
|
|
213
|
+
},
|
|
214
|
+
update(source, input) {
|
|
215
|
+
const secrets = {
|
|
216
|
+
verificationToken: input.verificationToken ?? source.secrets.verificationToken,
|
|
217
|
+
encryptKey: input.encryptKey ?? source.secrets.encryptKey
|
|
218
|
+
};
|
|
219
|
+
const changed = secrets.verificationToken != source.secrets.verificationToken || secrets.encryptKey != source.secrets.encryptKey;
|
|
220
|
+
return {
|
|
221
|
+
identity: source.identity,
|
|
222
|
+
eventTypes: input.eventTypes,
|
|
223
|
+
config: source.config,
|
|
224
|
+
secrets,
|
|
225
|
+
state: changed ? {} : source.state
|
|
226
|
+
};
|
|
227
|
+
},
|
|
228
|
+
view(source) {
|
|
229
|
+
return {
|
|
230
|
+
appId: source.identity,
|
|
231
|
+
manageSubscriptions: source.config.manageSubscriptions === true,
|
|
232
|
+
verificationTokenConfigured: true,
|
|
233
|
+
encryptKeyConfigured: true,
|
|
234
|
+
verifiedAt: typeof source.state.verifiedAt == "number" ? new Date(source.state.verifiedAt).toISOString() : null
|
|
235
|
+
};
|
|
236
|
+
},
|
|
237
|
+
ready: (source) => typeof source.state.verifiedAt == "number",
|
|
238
|
+
async receive(source, bytes, headers, now) {
|
|
239
|
+
const received = await receiveFeishuEvent(bytes, headers, {
|
|
240
|
+
appId: source.identity,
|
|
241
|
+
verificationToken: source.secrets.verificationToken,
|
|
242
|
+
encryptKey: source.secrets.encryptKey
|
|
243
|
+
}, now);
|
|
244
|
+
if ("challenge" in received) return {
|
|
245
|
+
response: Response.json(received),
|
|
246
|
+
state: {
|
|
247
|
+
...source.state,
|
|
248
|
+
verifiedAt: now
|
|
249
|
+
}
|
|
250
|
+
};
|
|
251
|
+
const event = received.event;
|
|
252
|
+
return { event: {
|
|
253
|
+
id: event.id,
|
|
254
|
+
type: event.type,
|
|
255
|
+
payload: {
|
|
256
|
+
event: event.type,
|
|
257
|
+
deliveryId: event.id,
|
|
258
|
+
appId: event.appId,
|
|
259
|
+
tenantKey: event.tenantKey,
|
|
260
|
+
occurredAt: event.occurredAt,
|
|
261
|
+
body: event.body
|
|
262
|
+
}
|
|
263
|
+
} };
|
|
264
|
+
},
|
|
265
|
+
matches(config, event) {
|
|
266
|
+
return matchesFeishuEvent(config, {
|
|
267
|
+
type: event.type,
|
|
268
|
+
body: event.payload.body
|
|
269
|
+
});
|
|
270
|
+
},
|
|
271
|
+
resources: {
|
|
272
|
+
triggerId: "feishu_app_bot.on_event",
|
|
273
|
+
requests(source, provider, config) {
|
|
274
|
+
const subscriptions = feishuSubscriptions(config, provider);
|
|
275
|
+
if (subscriptions.length > 0 && source.config.manageSubscriptions !== true) throw new PermanentIntegrationError("This source does not manage resource subscriptions.");
|
|
276
|
+
return subscriptions;
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
};
|
|
280
|
+
//#endregion
|
|
281
|
+
//#region src/event-source/common/index.ts
|
|
282
|
+
var definitions = [feishuApplication];
|
|
283
|
+
function eventSourceDefinition(kind) {
|
|
284
|
+
const definition = definitions.find((item) => item.kind == kind);
|
|
285
|
+
if (definition == null) throw new Error(`Unknown event source kind: ${kind}`);
|
|
286
|
+
return definition;
|
|
287
|
+
}
|
|
288
|
+
//#endregion
|
|
289
|
+
export { SourceIdentityError, eventSourceDefinition, feishuApplication };
|
|
@@ -16,4 +16,4 @@ export declare function receiveFeishuEvent(rawBody: Uint8Array, headers: Headers
|
|
|
16
16
|
} | {
|
|
17
17
|
readonly event: FeishuEvent;
|
|
18
18
|
}>;
|
|
19
|
-
export declare function matchesFeishuEvent(config: Readonly<Record<string, JsonValue>>, event: FeishuEvent): boolean;
|
|
19
|
+
export declare function matchesFeishuEvent(config: Readonly<Record<string, JsonValue>>, event: Pick<FeishuEvent, 'type' | 'body'>): boolean;
|
|
@@ -12052,8 +12052,8 @@ function checkSource(source, graph, document, targetInput, path, diagnostics) {
|
|
|
12052
12052
|
switch (source.kind) {
|
|
12053
12053
|
case "binding":
|
|
12054
12054
|
if (document.bindings[source.bindingId] == null) diagnostics.push(graphDiagnostic("graph.binding-missing", `Binding "${source.bindingId}" does not exist.`, path, { bindingId: source.bindingId }));
|
|
12055
|
-
else if (document.bindings[source.bindingId].kind != "variable") diagnostics.push(graphDiagnostic("graph.binding-invalid", `Binding "${source.bindingId}" must be
|
|
12056
|
-
else if (targetInput != null && !variableInputCompatible(targetInput.jsonSchema)) diagnostics.push(graphDiagnostic("graph.variable-incompatible", `
|
|
12055
|
+
else if (document.bindings[source.bindingId].kind != "variable") diagnostics.push(graphDiagnostic("graph.binding-invalid", `Binding "${source.bindingId}" must be a variable.`, path, { bindingId: source.bindingId }));
|
|
12056
|
+
else if (targetInput != null && !variableInputCompatible(targetInput.jsonSchema)) diagnostics.push(graphDiagnostic("graph.variable-incompatible", `Variable binding "${source.bindingId}" is not compatible with this input.`, path, { bindingId: source.bindingId }));
|
|
12057
12057
|
return;
|
|
12058
12058
|
case "node": {
|
|
12059
12059
|
const upstream = graph.nodes[source.nodeId];
|
|
@@ -12302,7 +12302,7 @@ function validateGraph(graph, document, path, diagnostics) {
|
|
|
12302
12302
|
}));
|
|
12303
12303
|
if (mapping.kind == "sources") {
|
|
12304
12304
|
const variableSources = mapping.sources.filter((source) => source.kind == "binding" && document.bindings[source.bindingId]?.kind == "variable");
|
|
12305
|
-
if (variableSources.length > 0 && (variableSources.length != 1 || mapping.sources.length != 1)) diagnostics.push(graphDiagnostic("graph.variable-source-mixed", "
|
|
12305
|
+
if (variableSources.length > 0 && (variableSources.length != 1 || mapping.sources.length != 1)) diagnostics.push(graphDiagnostic("graph.variable-source-mixed", "A variable must be the only source for an input.", mappingPath));
|
|
12306
12306
|
for (const source of mapping.sources) checkSource(source, graph, document, inputPorts[handle], mappingPath, diagnostics);
|
|
12307
12307
|
}
|
|
12308
12308
|
}
|
|
@@ -12345,7 +12345,7 @@ function validateGraph(graph, document, path, diagnostics) {
|
|
|
12345
12345
|
}
|
|
12346
12346
|
function validateFlowGraph(revision) {
|
|
12347
12347
|
const diagnostics = [];
|
|
12348
|
-
for (const [bindingId, binding] of Object.entries(revision.document.bindings)) if (binding.kind == "variable" && !validVariableName(binding.target)) diagnostics.push(graphDiagnostic("binding.variable-invalid", `
|
|
12348
|
+
for (const [bindingId, binding] of Object.entries(revision.document.bindings)) if (binding.kind == "variable" && !validVariableName(binding.target)) diagnostics.push(graphDiagnostic("binding.variable-invalid", `Variable binding "${bindingId}" has an invalid target.`, `/document/bindings/${bindingId}/target`, { bindingId }));
|
|
12349
12349
|
validateGraph(revision.document.graph, revision.document, "/document/graph", diagnostics);
|
|
12350
12350
|
return diagnostics;
|
|
12351
12351
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oomol-lab/open-flow",
|
|
3
|
-
"version": "0.1.0-beta.
|
|
3
|
+
"version": "0.1.0-beta.59",
|
|
4
4
|
"description": "TypeScript contracts and Browser runtime for Open Flow.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
@@ -53,6 +53,10 @@
|
|
|
53
53
|
"types": "./dist/common/cron-trigger.d.ts",
|
|
54
54
|
"import": "./dist/common/cron-trigger.js"
|
|
55
55
|
},
|
|
56
|
+
"./event-source": {
|
|
57
|
+
"types": "./dist/common/event-source.d.ts",
|
|
58
|
+
"import": "./dist/common/event-source.js"
|
|
59
|
+
},
|
|
56
60
|
"./integration-trigger": {
|
|
57
61
|
"types": "./dist/common/integration-trigger.d.ts",
|
|
58
62
|
"import": "./dist/common/integration-trigger.js"
|