skedyul 1.6.0 → 1.7.1
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/cli/index.js +77 -0
- package/dist/config/app-config.d.ts +11 -1
- package/dist/config/define.d.ts +39 -0
- package/dist/config/index.d.ts +1 -1
- package/dist/config/types/entity.d.ts +67 -0
- package/dist/config/types/form.d.ts +1 -9
- package/dist/config/types/index.d.ts +2 -0
- package/dist/config/types/setup.d.ts +37 -0
- package/dist/core/client.d.ts +39 -0
- package/dist/dedicated/server.js +77 -0
- package/dist/esm/index.mjs +191 -9
- package/dist/index.d.ts +4 -4
- package/dist/index.js +199 -10
- package/dist/schemas.d.ts +254 -18
- package/dist/server/handlers/index.d.ts +1 -0
- package/dist/server/handlers/setup-revalidate-handler.d.ts +9 -0
- package/dist/server/handlers/types.d.ts +34 -0
- package/dist/server/route-handlers/handlers.d.ts +4 -0
- package/dist/server/route-handlers/index.d.ts +1 -1
- package/dist/server.js +77 -0
- package/dist/serverless/server.mjs +77 -0
- package/dist/types/handlers.d.ts +42 -0
- package/dist/types/index.d.ts +1 -1
- package/dist/types/invocation.d.ts +2 -2
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -3870,6 +3870,72 @@ async function handleProvision(body, hooks) {
|
|
|
3870
3870
|
}
|
|
3871
3871
|
}
|
|
3872
3872
|
|
|
3873
|
+
// src/server/handlers/setup-revalidate-handler.ts
|
|
3874
|
+
async function handleSetupRevalidate(body, hooks) {
|
|
3875
|
+
const revalidateHook = hooks?.setup?.revalidate;
|
|
3876
|
+
if (!revalidateHook) {
|
|
3877
|
+
return {
|
|
3878
|
+
status: 404,
|
|
3879
|
+
body: { error: "Setup revalidate handler not configured" }
|
|
3880
|
+
};
|
|
3881
|
+
}
|
|
3882
|
+
if (!body.context?.appInstallationId || !body.context?.workplace || !body.context?.app || !body.reason || !Array.isArray(body.steps)) {
|
|
3883
|
+
return {
|
|
3884
|
+
status: 400,
|
|
3885
|
+
body: {
|
|
3886
|
+
error: {
|
|
3887
|
+
code: -32602,
|
|
3888
|
+
message: "Missing context (appInstallationId, workplace, app, reason, and steps required)"
|
|
3889
|
+
}
|
|
3890
|
+
}
|
|
3891
|
+
};
|
|
3892
|
+
}
|
|
3893
|
+
const ctx = {
|
|
3894
|
+
env: body.env ?? {},
|
|
3895
|
+
workplace: body.context.workplace,
|
|
3896
|
+
appInstallationId: body.context.appInstallationId,
|
|
3897
|
+
app: body.context.app,
|
|
3898
|
+
reason: body.reason,
|
|
3899
|
+
steps: body.steps,
|
|
3900
|
+
crm: body.crm,
|
|
3901
|
+
envChange: body.envChange,
|
|
3902
|
+
invocation: body.invocation,
|
|
3903
|
+
log: createContextLogger()
|
|
3904
|
+
};
|
|
3905
|
+
const requestConfig = {
|
|
3906
|
+
baseUrl: body.env?.SKEDYUL_API_URL ?? process.env.SKEDYUL_API_URL ?? "",
|
|
3907
|
+
apiToken: body.env?.SKEDYUL_API_TOKEN ?? process.env.SKEDYUL_API_TOKEN ?? ""
|
|
3908
|
+
};
|
|
3909
|
+
try {
|
|
3910
|
+
const handler = typeof revalidateHook === "function" ? revalidateHook : revalidateHook.handler;
|
|
3911
|
+
const result = await runWithLogContext(
|
|
3912
|
+
{ invocation: body.invocation },
|
|
3913
|
+
async () => {
|
|
3914
|
+
return await runWithConfig(requestConfig, async () => {
|
|
3915
|
+
return await handler(ctx);
|
|
3916
|
+
});
|
|
3917
|
+
}
|
|
3918
|
+
);
|
|
3919
|
+
return {
|
|
3920
|
+
status: 200,
|
|
3921
|
+
body: {
|
|
3922
|
+
completed: result?.completed ?? [],
|
|
3923
|
+
invalidated: result?.invalidated ?? []
|
|
3924
|
+
}
|
|
3925
|
+
};
|
|
3926
|
+
} catch (err) {
|
|
3927
|
+
return {
|
|
3928
|
+
status: 500,
|
|
3929
|
+
body: {
|
|
3930
|
+
error: {
|
|
3931
|
+
code: -32603,
|
|
3932
|
+
message: err instanceof Error ? err.message : String(err ?? "")
|
|
3933
|
+
}
|
|
3934
|
+
}
|
|
3935
|
+
};
|
|
3936
|
+
}
|
|
3937
|
+
}
|
|
3938
|
+
|
|
3873
3939
|
// src/server/handler-helpers.ts
|
|
3874
3940
|
function parseHandlerEnvelope(parsedBody) {
|
|
3875
3941
|
if (typeof parsedBody !== "object" || parsedBody === null || Array.isArray(parsedBody) || !("env" in parsedBody) || !("request" in parsedBody)) {
|
|
@@ -4261,6 +4327,14 @@ async function handleProvisionRoute(req, ctx) {
|
|
|
4261
4327
|
const result = await handleProvision(parseResult.data, ctx.config.hooks);
|
|
4262
4328
|
return { status: result.status, body: result.body };
|
|
4263
4329
|
}
|
|
4330
|
+
async function handleSetupRevalidateRoute(req, ctx) {
|
|
4331
|
+
const parseResult = parseJsonBody(req);
|
|
4332
|
+
if (!parseResult.success) {
|
|
4333
|
+
return parseResult.error;
|
|
4334
|
+
}
|
|
4335
|
+
const result = await handleSetupRevalidate(parseResult.data, ctx.config.hooks);
|
|
4336
|
+
return { status: result.status, body: result.body };
|
|
4337
|
+
}
|
|
4264
4338
|
async function handleOAuthCallbackRoute(req, ctx) {
|
|
4265
4339
|
const parseResult = parseJsonBody(req);
|
|
4266
4340
|
if (!parseResult.success) {
|
|
@@ -4622,6 +4696,9 @@ async function routeRequest(req, ctx) {
|
|
|
4622
4696
|
if (req.path === "/provision" && req.method === "POST") {
|
|
4623
4697
|
return handleProvisionRoute(req, ctx);
|
|
4624
4698
|
}
|
|
4699
|
+
if (req.path === "/setup/revalidate" && req.method === "POST") {
|
|
4700
|
+
return handleSetupRevalidateRoute(req, ctx);
|
|
4701
|
+
}
|
|
4625
4702
|
if (req.path === "/oauth_callback" && req.method === "POST") {
|
|
4626
4703
|
return handleOAuthCallbackRoute(req, ctx);
|
|
4627
4704
|
}
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
import type { ToolRegistry, WebhookRegistry, ToolMetadata, WebhookMetadata } from '../types';
|
|
7
7
|
import type { ServerHooks } from '../types/handlers';
|
|
8
8
|
import type { CoreApiConfig } from '../core/types';
|
|
9
|
-
import type { EnvSchema, ComputeLayer, ModelDefinition, RelationshipDefinition, ChannelDefinition, WorkflowDefinition, PageDefinition, NavigationConfig, AgentDefinition, SignalDefinition } from './types';
|
|
9
|
+
import type { EnvSchema, ComputeLayer, ModelDefinition, EntityDefinition, RelationshipDefinition, ChannelDefinition, WorkflowDefinition, PageDefinition, NavigationConfig, AgentDefinition, SignalDefinition, SetupStepDefinition } from './types';
|
|
10
10
|
import type { AppEventDefinition } from './types/app-event';
|
|
11
11
|
import type { QueueRegistry, SerializableQueueConfig } from './queue-config';
|
|
12
12
|
import type { SequencerRegistry, SerializableSequencerConfig } from './sequencer-config';
|
|
@@ -33,6 +33,11 @@ export interface ProvisionConfig {
|
|
|
33
33
|
env?: EnvSchema;
|
|
34
34
|
/** INTERNAL model definitions (app-owned, not visible to users) */
|
|
35
35
|
models?: ModelDefinition[];
|
|
36
|
+
/**
|
|
37
|
+
* App entity contracts for install-time CRM maps (not shared models).
|
|
38
|
+
* Workplaces map these to CRM; workflows apply maps via app-handle Liquid filters.
|
|
39
|
+
*/
|
|
40
|
+
entities?: EntityDefinition[];
|
|
36
41
|
/** Relationship definitions between INTERNAL models */
|
|
37
42
|
relationships?: RelationshipDefinition[];
|
|
38
43
|
/** Communication channel definitions */
|
|
@@ -45,6 +50,11 @@ export interface ProvisionConfig {
|
|
|
45
50
|
pages?: PageDefinition[];
|
|
46
51
|
/** App signal definitions (event bus subscriptions created on install) */
|
|
47
52
|
signals?: SignalDefinition[];
|
|
53
|
+
/**
|
|
54
|
+
* Install setup checklist steps (opt-in).
|
|
55
|
+
* Seeded as AppInstallSetupStep rows; exposed via setup.* Core API.
|
|
56
|
+
*/
|
|
57
|
+
setup?: SetupStepDefinition[];
|
|
48
58
|
}
|
|
49
59
|
/**
|
|
50
60
|
* Build configuration - controls how the integration is bundled.
|
package/dist/config/define.d.ts
CHANGED
|
@@ -16,12 +16,14 @@
|
|
|
16
16
|
* })
|
|
17
17
|
*/
|
|
18
18
|
import type { ModelDefinition } from './types/model';
|
|
19
|
+
import type { EntityDefinition } from './types/entity';
|
|
19
20
|
import type { ChannelDefinition } from './types/channel';
|
|
20
21
|
import type { PageDefinition } from './types/page';
|
|
21
22
|
import type { WorkflowDefinition } from './types/workflow';
|
|
22
23
|
import type { AgentDefinition } from './types/agent';
|
|
23
24
|
import type { EnvSchema } from './types/env';
|
|
24
25
|
import type { NavigationConfig } from './types/navigation';
|
|
26
|
+
import type { SetupStepDefinition } from './types/setup';
|
|
25
27
|
/**
|
|
26
28
|
* Define a model with full type safety.
|
|
27
29
|
*
|
|
@@ -37,6 +39,28 @@ import type { NavigationConfig } from './types/navigation';
|
|
|
37
39
|
* })
|
|
38
40
|
*/
|
|
39
41
|
export declare function defineModel(model: ModelDefinition): ModelDefinition;
|
|
42
|
+
/**
|
|
43
|
+
* Define an app entity (CRM map contract) with full type safety.
|
|
44
|
+
*
|
|
45
|
+
* Entities describe external payload shapes that workplaces map to CRM at
|
|
46
|
+
* install time. They are not shared models — workflows apply maps via Liquid
|
|
47
|
+
* filters named after the app handle (e.g. `| bft: "format", "member"`).
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* export default defineEntity({
|
|
51
|
+
* handle: 'member',
|
|
52
|
+
* label: 'Glofox Member',
|
|
53
|
+
* fields: [
|
|
54
|
+
* { handle: 'glofox_id', label: 'Glofox ID', matchCandidate: true, required: true },
|
|
55
|
+
* { handle: 'first_name', label: 'First Name' },
|
|
56
|
+
* ],
|
|
57
|
+
* contextFields: [
|
|
58
|
+
* { handle: 'membership_status', label: 'Membership Status',
|
|
59
|
+
* options: ['prospect', 'trial_member', 'member', 'inactive_member'] },
|
|
60
|
+
* ],
|
|
61
|
+
* })
|
|
62
|
+
*/
|
|
63
|
+
export declare function defineEntity(entity: EntityDefinition): EntityDefinition;
|
|
40
64
|
/**
|
|
41
65
|
* Define a channel with full type safety.
|
|
42
66
|
*
|
|
@@ -127,3 +151,18 @@ export declare function defineEnv(env: EnvSchema): EnvSchema;
|
|
|
127
151
|
* })
|
|
128
152
|
*/
|
|
129
153
|
export declare function defineNavigation(navigation: NavigationConfig): NavigationConfig;
|
|
154
|
+
/**
|
|
155
|
+
* Define an install setup step with full type safety.
|
|
156
|
+
*
|
|
157
|
+
* @example
|
|
158
|
+
* export default defineSetupStep({
|
|
159
|
+
* handle: 'crm_members_bookings_events',
|
|
160
|
+
* label: 'Setup Members, Bookings and Events',
|
|
161
|
+
* kind: 'crm',
|
|
162
|
+
* requires: ['access_granted'],
|
|
163
|
+
* entities: ['member', 'booking', 'event'],
|
|
164
|
+
* listenToCrm: true,
|
|
165
|
+
* capabilities: ['crm.member', 'crm.booking', 'crm.event'],
|
|
166
|
+
* })
|
|
167
|
+
*/
|
|
168
|
+
export declare function defineSetupStep(step: SetupStepDefinition): SetupStepDefinition;
|
package/dist/config/index.d.ts
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
export * from './types';
|
|
12
12
|
export type { InstallConfig, ProvisionConfig, BuildConfig, CorsOptions, SkedyulConfig, SerializableSkedyulConfig, QueueScope, QueueConfig, SerializableQueueConfig, QueueRegistry, SequencerScope, SerializableSequencerConfig, SequencerRegistry, } from './app-config';
|
|
13
13
|
export { defineConfig } from './app-config';
|
|
14
|
-
export { defineModel, defineChannel, definePage, defineWorkflow, defineAgent, defineEnv, defineNavigation, } from './define';
|
|
14
|
+
export { defineModel, defineEntity, defineChannel, definePage, defineWorkflow, defineAgent, defineEnv, defineNavigation, defineSetupStep, } from './define';
|
|
15
15
|
export { SCHEMA_FILE_EXTENSIONS, loadSchema, saveSchema, serializeSchemaToJson, serializeSchemaToTypeScript, transformToBackendSchema, transformFromBackendSchema, type LoadSchemaOptions, type LoadSchemaResult, type SerializeSchemaOptions, type BackendModelDefinition, type BackendFieldDefinition, type BackendRelationshipDefinition, type BackendDesiredSchema, } from './schema-loader';
|
|
16
16
|
export { loadAndResolveConfig, serializeResolvedConfig, type ResolvedConfig } from './resolver';
|
|
17
17
|
export { getAllEnvKeys, getRequiredInstallEnvKeys } from './utils';
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* App entity definition types.
|
|
3
|
+
*
|
|
4
|
+
* Entities describe external/logical payload shapes (e.g. Glofox member) that
|
|
5
|
+
* workplaces map to CRM via install-time CRM maps. They are NOT shared models —
|
|
6
|
+
* the app does not own CRM writes; workflows/agents apply maps.
|
|
7
|
+
*/
|
|
8
|
+
import type { BaseDefinition, FieldOption } from './base';
|
|
9
|
+
/**
|
|
10
|
+
* Field on an app entity contract (maps to a path on tool/event payloads).
|
|
11
|
+
*/
|
|
12
|
+
export interface EntityFieldDefinition {
|
|
13
|
+
/** Unique field handle (snake_case), used as source path by default */
|
|
14
|
+
handle: string;
|
|
15
|
+
/** Human-readable label */
|
|
16
|
+
label: string;
|
|
17
|
+
/** Optional description */
|
|
18
|
+
description?: string;
|
|
19
|
+
/** Data type hint for the install mapper UI */
|
|
20
|
+
type?: 'string' | 'long_string' | 'number' | 'boolean' | 'date' | 'datetime' | 'object';
|
|
21
|
+
/**
|
|
22
|
+
* Whether this field uniquely identifies a record and can be used as an
|
|
23
|
+
* upsert match key (e.g. external id, email, phone).
|
|
24
|
+
*/
|
|
25
|
+
isUnique?: boolean;
|
|
26
|
+
/**
|
|
27
|
+
* @deprecated Prefer `isUnique`. Kept for backward compatibility —
|
|
28
|
+
* treated the same as `isUnique` by the CRM map editor.
|
|
29
|
+
*/
|
|
30
|
+
matchCandidate?: boolean;
|
|
31
|
+
/** Whether this field should be mapped for a complete configuration */
|
|
32
|
+
required?: boolean;
|
|
33
|
+
/** Enum options when the source value is constrained */
|
|
34
|
+
options?: FieldOption[] | string[];
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Relationship declared on an entity (for install relationship mapping UI).
|
|
38
|
+
*/
|
|
39
|
+
export interface EntityRelationshipDefinition {
|
|
40
|
+
/** Handle used when writing relationship ids (e.g. "customer", "plan") */
|
|
41
|
+
handle: string;
|
|
42
|
+
/** Human-readable label */
|
|
43
|
+
label: string;
|
|
44
|
+
/** Target entity handle this relates to (optional documentation) */
|
|
45
|
+
targetEntity?: string;
|
|
46
|
+
description?: string;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* App entity — mapping contract for install CRM maps + Liquid filters.
|
|
50
|
+
*/
|
|
51
|
+
export interface EntityDefinition extends BaseDefinition {
|
|
52
|
+
/** Unique entity handle (e.g. "member", "booking") */
|
|
53
|
+
handle: string;
|
|
54
|
+
/** Display label */
|
|
55
|
+
label: string;
|
|
56
|
+
labelPlural?: string;
|
|
57
|
+
description?: string;
|
|
58
|
+
/** Fields on the primary entity object */
|
|
59
|
+
fields: EntityFieldDefinition[];
|
|
60
|
+
/**
|
|
61
|
+
* Fields that live on the event/tool envelope alongside the entity
|
|
62
|
+
* (e.g. membership_status on member events).
|
|
63
|
+
*/
|
|
64
|
+
contextFields?: EntityFieldDefinition[];
|
|
65
|
+
/** Relationship handles that can be mapped to CRM relationship fields */
|
|
66
|
+
relationships?: EntityRelationshipDefinition[];
|
|
67
|
+
}
|
|
@@ -352,15 +352,7 @@ export interface ListBlock {
|
|
|
352
352
|
/** Message when no items */
|
|
353
353
|
emptyMessage?: string;
|
|
354
354
|
}
|
|
355
|
-
/**
|
|
356
|
-
* Model mapper block definition - for mapping SHARED models to workspace models.
|
|
357
|
-
*/
|
|
358
|
-
export interface ModelMapperBlock {
|
|
359
|
-
type: 'model_mapper';
|
|
360
|
-
/** The SHARED model handle from provision config */
|
|
361
|
-
model: string;
|
|
362
|
-
}
|
|
363
355
|
/**
|
|
364
356
|
* Union of all block types.
|
|
365
357
|
*/
|
|
366
|
-
export type BlockDefinition = CardBlock | ListBlock
|
|
358
|
+
export type BlockDefinition = CardBlock | ListBlock;
|
|
@@ -7,11 +7,13 @@ export * from './base';
|
|
|
7
7
|
export * from './env';
|
|
8
8
|
export * from './resource';
|
|
9
9
|
export * from './model';
|
|
10
|
+
export * from './entity';
|
|
10
11
|
export * from './channel';
|
|
11
12
|
export * from './workflow';
|
|
12
13
|
export * from './agent';
|
|
13
14
|
export * from './webhook';
|
|
14
15
|
export * from './signal';
|
|
16
|
+
export * from './setup';
|
|
15
17
|
export * from './app-event';
|
|
16
18
|
export * from './navigation';
|
|
17
19
|
export * from './context';
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* App install setup step definition for provision config.
|
|
3
|
+
*
|
|
4
|
+
* Declared steps are seeded onto each AppInstallation as AppInstallSetupStep
|
|
5
|
+
* rows. Apps and the platform UI read/update status via the setup.* Core API.
|
|
6
|
+
*/
|
|
7
|
+
export type SetupStepKind = 'app' | 'crm' | 'realtime' | 'env';
|
|
8
|
+
export interface SetupStepDefinition {
|
|
9
|
+
/** Stable step handle (unique within the app) */
|
|
10
|
+
handle: string;
|
|
11
|
+
/** UI label */
|
|
12
|
+
label: string;
|
|
13
|
+
/** Optional longer description */
|
|
14
|
+
description?: string;
|
|
15
|
+
/** Step kind — drives default CTAs and listeners */
|
|
16
|
+
kind: SetupStepKind;
|
|
17
|
+
/** Prerequisite step handles that must be READY */
|
|
18
|
+
requires?: string[];
|
|
19
|
+
/** CRM entity handles this step covers (kind: crm) */
|
|
20
|
+
entities?: string[];
|
|
21
|
+
/** Bundled workflow handles this step wires (kind: realtime) */
|
|
22
|
+
workflowHandles?: string[];
|
|
23
|
+
/** Env keys this step depends on (kind: env) */
|
|
24
|
+
envKeys?: string[];
|
|
25
|
+
/**
|
|
26
|
+
* When true, platform emits install.setup.crm_changed after CRM migrations
|
|
27
|
+
* and invokes hooks.setup.revalidate so the app can complete/invalidate.
|
|
28
|
+
*/
|
|
29
|
+
listenToCrm?: boolean;
|
|
30
|
+
/**
|
|
31
|
+
* When true, platform emits install.setup.env_changed when matching env
|
|
32
|
+
* keys are removed/cleared and invokes hooks.setup.revalidate.
|
|
33
|
+
*/
|
|
34
|
+
listenToEnv?: boolean;
|
|
35
|
+
/** Capability keys unlocked when this step is READY */
|
|
36
|
+
capabilities?: string[];
|
|
37
|
+
}
|
package/dist/core/client.d.ts
CHANGED
|
@@ -1241,4 +1241,43 @@ export declare const report: {
|
|
|
1241
1241
|
*/
|
|
1242
1242
|
get(handle: string): Promise<ReportDefinition | null>;
|
|
1243
1243
|
};
|
|
1244
|
+
export type SetupStepStatus = 'PENDING' | 'READY' | 'SKIPPED' | 'INVALIDATED' | 'BLOCKED';
|
|
1245
|
+
export type SetupStepKindApi = 'APP' | 'CRM' | 'REALTIME' | 'ENV';
|
|
1246
|
+
export type SetupStepView = {
|
|
1247
|
+
id: string;
|
|
1248
|
+
handle: string;
|
|
1249
|
+
kind: SetupStepKindApi;
|
|
1250
|
+
status: SetupStepStatus;
|
|
1251
|
+
sortOrder: number;
|
|
1252
|
+
label: string;
|
|
1253
|
+
description: string | null;
|
|
1254
|
+
requires: string[];
|
|
1255
|
+
config: {
|
|
1256
|
+
entities?: string[];
|
|
1257
|
+
workflowHandles?: string[];
|
|
1258
|
+
envKeys?: string[];
|
|
1259
|
+
listenToCrm?: boolean;
|
|
1260
|
+
listenToEnv?: boolean;
|
|
1261
|
+
capabilities?: string[];
|
|
1262
|
+
};
|
|
1263
|
+
completedAt: string | null;
|
|
1264
|
+
skippedAt: string | null;
|
|
1265
|
+
invalidatedAt: string | null;
|
|
1266
|
+
metadata: Record<string, unknown> | null;
|
|
1267
|
+
};
|
|
1268
|
+
export type SetupListResult = {
|
|
1269
|
+
steps: SetupStepView[];
|
|
1270
|
+
capabilities: Record<string, boolean>;
|
|
1271
|
+
};
|
|
1272
|
+
/**
|
|
1273
|
+
* Install setup checklist API (requires sk_wkp_ token).
|
|
1274
|
+
*/
|
|
1275
|
+
export declare const setup: {
|
|
1276
|
+
list(): Promise<SetupListResult>;
|
|
1277
|
+
get(handle: string): Promise<SetupStepView | null>;
|
|
1278
|
+
complete(handle: string, metadata?: Record<string, unknown>): Promise<SetupStepView>;
|
|
1279
|
+
skip(handle: string, metadata?: Record<string, unknown>): Promise<SetupStepView>;
|
|
1280
|
+
invalidate(handle: string, reason?: string, metadata?: Record<string, unknown>): Promise<SetupStepView>;
|
|
1281
|
+
capabilities(): Promise<Record<string, boolean>>;
|
|
1282
|
+
};
|
|
1244
1283
|
export {};
|
package/dist/dedicated/server.js
CHANGED
|
@@ -1200,6 +1200,72 @@ async function handleProvision(body, hooks) {
|
|
|
1200
1200
|
}
|
|
1201
1201
|
}
|
|
1202
1202
|
|
|
1203
|
+
// src/server/handlers/setup-revalidate-handler.ts
|
|
1204
|
+
async function handleSetupRevalidate(body, hooks) {
|
|
1205
|
+
const revalidateHook = hooks?.setup?.revalidate;
|
|
1206
|
+
if (!revalidateHook) {
|
|
1207
|
+
return {
|
|
1208
|
+
status: 404,
|
|
1209
|
+
body: { error: "Setup revalidate handler not configured" }
|
|
1210
|
+
};
|
|
1211
|
+
}
|
|
1212
|
+
if (!body.context?.appInstallationId || !body.context?.workplace || !body.context?.app || !body.reason || !Array.isArray(body.steps)) {
|
|
1213
|
+
return {
|
|
1214
|
+
status: 400,
|
|
1215
|
+
body: {
|
|
1216
|
+
error: {
|
|
1217
|
+
code: -32602,
|
|
1218
|
+
message: "Missing context (appInstallationId, workplace, app, reason, and steps required)"
|
|
1219
|
+
}
|
|
1220
|
+
}
|
|
1221
|
+
};
|
|
1222
|
+
}
|
|
1223
|
+
const ctx = {
|
|
1224
|
+
env: body.env ?? {},
|
|
1225
|
+
workplace: body.context.workplace,
|
|
1226
|
+
appInstallationId: body.context.appInstallationId,
|
|
1227
|
+
app: body.context.app,
|
|
1228
|
+
reason: body.reason,
|
|
1229
|
+
steps: body.steps,
|
|
1230
|
+
crm: body.crm,
|
|
1231
|
+
envChange: body.envChange,
|
|
1232
|
+
invocation: body.invocation,
|
|
1233
|
+
log: createContextLogger()
|
|
1234
|
+
};
|
|
1235
|
+
const requestConfig = {
|
|
1236
|
+
baseUrl: body.env?.SKEDYUL_API_URL ?? process.env.SKEDYUL_API_URL ?? "",
|
|
1237
|
+
apiToken: body.env?.SKEDYUL_API_TOKEN ?? process.env.SKEDYUL_API_TOKEN ?? ""
|
|
1238
|
+
};
|
|
1239
|
+
try {
|
|
1240
|
+
const handler = typeof revalidateHook === "function" ? revalidateHook : revalidateHook.handler;
|
|
1241
|
+
const result = await runWithLogContext(
|
|
1242
|
+
{ invocation: body.invocation },
|
|
1243
|
+
async () => {
|
|
1244
|
+
return await runWithConfig(requestConfig, async () => {
|
|
1245
|
+
return await handler(ctx);
|
|
1246
|
+
});
|
|
1247
|
+
}
|
|
1248
|
+
);
|
|
1249
|
+
return {
|
|
1250
|
+
status: 200,
|
|
1251
|
+
body: {
|
|
1252
|
+
completed: result?.completed ?? [],
|
|
1253
|
+
invalidated: result?.invalidated ?? []
|
|
1254
|
+
}
|
|
1255
|
+
};
|
|
1256
|
+
} catch (err) {
|
|
1257
|
+
return {
|
|
1258
|
+
status: 500,
|
|
1259
|
+
body: {
|
|
1260
|
+
error: {
|
|
1261
|
+
code: -32603,
|
|
1262
|
+
message: err instanceof Error ? err.message : String(err ?? "")
|
|
1263
|
+
}
|
|
1264
|
+
}
|
|
1265
|
+
};
|
|
1266
|
+
}
|
|
1267
|
+
}
|
|
1268
|
+
|
|
1203
1269
|
// src/server/handler-helpers.ts
|
|
1204
1270
|
function parseHandlerEnvelope(parsedBody) {
|
|
1205
1271
|
if (typeof parsedBody !== "object" || parsedBody === null || Array.isArray(parsedBody) || !("env" in parsedBody) || !("request" in parsedBody)) {
|
|
@@ -1591,6 +1657,14 @@ async function handleProvisionRoute(req, ctx) {
|
|
|
1591
1657
|
const result = await handleProvision(parseResult.data, ctx.config.hooks);
|
|
1592
1658
|
return { status: result.status, body: result.body };
|
|
1593
1659
|
}
|
|
1660
|
+
async function handleSetupRevalidateRoute(req, ctx) {
|
|
1661
|
+
const parseResult = parseJsonBody(req);
|
|
1662
|
+
if (!parseResult.success) {
|
|
1663
|
+
return parseResult.error;
|
|
1664
|
+
}
|
|
1665
|
+
const result = await handleSetupRevalidate(parseResult.data, ctx.config.hooks);
|
|
1666
|
+
return { status: result.status, body: result.body };
|
|
1667
|
+
}
|
|
1594
1668
|
async function handleOAuthCallbackRoute(req, ctx) {
|
|
1595
1669
|
const parseResult = parseJsonBody(req);
|
|
1596
1670
|
if (!parseResult.success) {
|
|
@@ -1952,6 +2026,9 @@ async function routeRequest(req, ctx) {
|
|
|
1952
2026
|
if (req.path === "/provision" && req.method === "POST") {
|
|
1953
2027
|
return handleProvisionRoute(req, ctx);
|
|
1954
2028
|
}
|
|
2029
|
+
if (req.path === "/setup/revalidate" && req.method === "POST") {
|
|
2030
|
+
return handleSetupRevalidateRoute(req, ctx);
|
|
2031
|
+
}
|
|
1955
2032
|
if (req.path === "/oauth_callback" && req.method === "POST") {
|
|
1956
2033
|
return handleOAuthCallbackRoute(req, ctx);
|
|
1957
2034
|
}
|