skedyul 1.7.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/index.js CHANGED
@@ -155,7 +155,6 @@ __export(index_exports, {
155
155
  ModelDefinitionSchema: () => ModelDefinitionSchema,
156
156
  ModelDependencySchema: () => ModelDependencySchema,
157
157
  ModelFieldDefinitionSchema: () => ModelFieldDefinitionSchema,
158
- ModelMapperBlockDefinitionSchema: () => ModelMapperBlockDefinitionSchema,
159
158
  MoneyMinorRangeSchema: () => MoneyMinorRangeSchema,
160
159
  NavigationBreadcrumbSchema: () => NavigationBreadcrumbSchema,
161
160
  NavigationConfigSchema: () => NavigationConfigSchema,
@@ -206,6 +205,8 @@ __export(index_exports, {
206
205
  SequencerContextError: () => SequencerContextError,
207
206
  SequencerLockError: () => SequencerLockError,
208
207
  SequencerNotFoundError: () => SequencerNotFoundError,
208
+ SetupStepDefinitionSchema: () => SetupStepDefinitionSchema,
209
+ SetupStepKindSchema: () => SetupStepKindSchema,
209
210
  SkedyulConfigSchema: () => SkedyulConfigSchema,
210
211
  SkillExampleSchema: () => SkillExampleSchema,
211
212
  SkillMetadataSchema: () => SkillMetadataSchema,
@@ -301,6 +302,7 @@ __export(index_exports, {
301
302
  defineNavigation: () => defineNavigation,
302
303
  definePage: () => definePage,
303
304
  defineSchema: () => defineSchema,
305
+ defineSetupStep: () => defineSetupStep,
304
306
  defineSkill: () => defineSkill,
305
307
  defineWorkflow: () => defineWorkflow,
306
308
  defineWorkflowYAML: () => defineWorkflowYAML,
@@ -362,6 +364,7 @@ __export(index_exports, {
362
364
  sequencerAllow: () => allow,
363
365
  sequencerRelease: () => release,
364
366
  server: () => server,
367
+ setup: () => setup,
365
368
  toGsm7: () => toGsm7,
366
369
  token: () => token,
367
370
  validateCRMSchema: () => validateCRMSchema,
@@ -1674,6 +1677,8 @@ var EntityFieldDefinitionSchema = import_v48.z.object({
1674
1677
  "datetime",
1675
1678
  "object"
1676
1679
  ]).optional(),
1680
+ isUnique: import_v48.z.boolean().optional(),
1681
+ /** @deprecated Prefer isUnique */
1677
1682
  matchCandidate: import_v48.z.boolean().optional(),
1678
1683
  required: import_v48.z.boolean().optional(),
1679
1684
  options: import_v48.z.array(
@@ -2114,16 +2119,10 @@ var ListBlockDefinitionSchema = import_v48.z.object({
2114
2119
  icon: import_v48.z.string().optional(),
2115
2120
  emptyMessage: import_v48.z.string().optional()
2116
2121
  });
2117
- var ModelMapperBlockDefinitionSchema = import_v48.z.object({
2118
- type: import_v48.z.literal("model_mapper"),
2119
- /** The SHARED model handle from install config (e.g., "client", "patient") */
2120
- model: import_v48.z.string()
2121
- });
2122
2122
  var PageBlockDefinitionSchema = import_v48.z.union([
2123
2123
  CardBlockDefinitionSchema,
2124
2124
  LegacyFormBlockDefinitionSchema,
2125
- ListBlockDefinitionSchema,
2126
- ModelMapperBlockDefinitionSchema
2125
+ ListBlockDefinitionSchema
2127
2126
  ]);
2128
2127
  var PageContextModeSchema = import_v48.z.enum(["first", "many", "count", "all"]).transform((val) => val === "all" ? "many" : val);
2129
2128
  var PageContextFiltersSchema = import_v48.z.record(
@@ -2262,6 +2261,20 @@ var InstallConfigSchema = import_v48.z.object({
2262
2261
  /** Relationship definitions between SHARED models */
2263
2262
  relationships: import_v48.z.array(RelationshipDefinitionSchema).optional()
2264
2263
  });
2264
+ var SetupStepKindSchema = import_v48.z.enum(["app", "crm", "realtime", "env"]);
2265
+ var SetupStepDefinitionSchema = import_v48.z.object({
2266
+ handle: import_v48.z.string(),
2267
+ label: import_v48.z.string(),
2268
+ description: import_v48.z.string().optional(),
2269
+ kind: SetupStepKindSchema,
2270
+ requires: import_v48.z.array(import_v48.z.string()).optional(),
2271
+ entities: import_v48.z.array(import_v48.z.string()).optional(),
2272
+ workflowHandles: import_v48.z.array(import_v48.z.string()).optional(),
2273
+ envKeys: import_v48.z.array(import_v48.z.string()).optional(),
2274
+ listenToCrm: import_v48.z.boolean().optional(),
2275
+ listenToEnv: import_v48.z.boolean().optional(),
2276
+ capabilities: import_v48.z.array(import_v48.z.string()).optional()
2277
+ });
2265
2278
  var ProvisionConfigSchema = import_v48.z.object({
2266
2279
  env: EnvSchemaSchema.optional(),
2267
2280
  /** INTERNAL model definitions (app-owned, not visible to users) */
@@ -2274,7 +2287,9 @@ var ProvisionConfigSchema = import_v48.z.object({
2274
2287
  workflows: import_v48.z.array(WorkflowDefinitionSchema).optional(),
2275
2288
  /** Base navigation configuration for all pages (can be overridden per page) */
2276
2289
  navigation: NavigationConfigSchema.optional(),
2277
- pages: import_v48.z.array(PageDefinitionSchema).optional()
2290
+ pages: import_v48.z.array(PageDefinitionSchema).optional(),
2291
+ /** Install setup checklist steps (opt-in) */
2292
+ setup: import_v48.z.array(SetupStepDefinitionSchema).optional()
2278
2293
  });
2279
2294
  var SkedyulConfigSchema = import_v48.z.object({
2280
2295
  name: import_v48.z.string(),
@@ -3923,6 +3938,47 @@ var report = {
3923
3938
  return data;
3924
3939
  }
3925
3940
  };
3941
+ var setup = {
3942
+ async list() {
3943
+ const { data } = await callCore("setup.list", {});
3944
+ return data;
3945
+ },
3946
+ async get(handle) {
3947
+ const { data } = await callCore("setup.get", {
3948
+ handle
3949
+ });
3950
+ return data;
3951
+ },
3952
+ async complete(handle, metadata) {
3953
+ const { data } = await callCore("setup.complete", {
3954
+ handle,
3955
+ ...metadata ? { metadata } : {}
3956
+ });
3957
+ return data;
3958
+ },
3959
+ async skip(handle, metadata) {
3960
+ const { data } = await callCore("setup.skip", {
3961
+ handle,
3962
+ ...metadata ? { metadata } : {}
3963
+ });
3964
+ return data;
3965
+ },
3966
+ async invalidate(handle, reason, metadata) {
3967
+ const { data } = await callCore("setup.invalidate", {
3968
+ handle,
3969
+ ...reason ? { reason } : {},
3970
+ ...metadata ? { metadata } : {}
3971
+ });
3972
+ return data;
3973
+ },
3974
+ async capabilities() {
3975
+ const { data } = await callCore(
3976
+ "setup.capabilities",
3977
+ {}
3978
+ );
3979
+ return data.capabilities;
3980
+ }
3981
+ };
3926
3982
 
3927
3983
  // src/ratelimit/context.ts
3928
3984
  var import_async_hooks2 = require("async_hooks");
@@ -4957,6 +5013,72 @@ async function handleProvision(body, hooks) {
4957
5013
  }
4958
5014
  }
4959
5015
 
5016
+ // src/server/handlers/setup-revalidate-handler.ts
5017
+ async function handleSetupRevalidate(body, hooks) {
5018
+ const revalidateHook = hooks?.setup?.revalidate;
5019
+ if (!revalidateHook) {
5020
+ return {
5021
+ status: 404,
5022
+ body: { error: "Setup revalidate handler not configured" }
5023
+ };
5024
+ }
5025
+ if (!body.context?.appInstallationId || !body.context?.workplace || !body.context?.app || !body.reason || !Array.isArray(body.steps)) {
5026
+ return {
5027
+ status: 400,
5028
+ body: {
5029
+ error: {
5030
+ code: -32602,
5031
+ message: "Missing context (appInstallationId, workplace, app, reason, and steps required)"
5032
+ }
5033
+ }
5034
+ };
5035
+ }
5036
+ const ctx = {
5037
+ env: body.env ?? {},
5038
+ workplace: body.context.workplace,
5039
+ appInstallationId: body.context.appInstallationId,
5040
+ app: body.context.app,
5041
+ reason: body.reason,
5042
+ steps: body.steps,
5043
+ crm: body.crm,
5044
+ envChange: body.envChange,
5045
+ invocation: body.invocation,
5046
+ log: createContextLogger()
5047
+ };
5048
+ const requestConfig = {
5049
+ baseUrl: body.env?.SKEDYUL_API_URL ?? process.env.SKEDYUL_API_URL ?? "",
5050
+ apiToken: body.env?.SKEDYUL_API_TOKEN ?? process.env.SKEDYUL_API_TOKEN ?? ""
5051
+ };
5052
+ try {
5053
+ const handler = typeof revalidateHook === "function" ? revalidateHook : revalidateHook.handler;
5054
+ const result = await runWithLogContext(
5055
+ { invocation: body.invocation },
5056
+ async () => {
5057
+ return await runWithConfig(requestConfig, async () => {
5058
+ return await handler(ctx);
5059
+ });
5060
+ }
5061
+ );
5062
+ return {
5063
+ status: 200,
5064
+ body: {
5065
+ completed: result?.completed ?? [],
5066
+ invalidated: result?.invalidated ?? []
5067
+ }
5068
+ };
5069
+ } catch (err) {
5070
+ return {
5071
+ status: 500,
5072
+ body: {
5073
+ error: {
5074
+ code: -32603,
5075
+ message: err instanceof Error ? err.message : String(err ?? "")
5076
+ }
5077
+ }
5078
+ };
5079
+ }
5080
+ }
5081
+
4960
5082
  // src/server/handler-helpers.ts
4961
5083
  function parseHandlerEnvelope(parsedBody) {
4962
5084
  if (typeof parsedBody !== "object" || parsedBody === null || Array.isArray(parsedBody) || !("env" in parsedBody) || !("request" in parsedBody)) {
@@ -5343,6 +5465,14 @@ async function handleProvisionRoute(req, ctx) {
5343
5465
  const result = await handleProvision(parseResult.data, ctx.config.hooks);
5344
5466
  return { status: result.status, body: result.body };
5345
5467
  }
5468
+ async function handleSetupRevalidateRoute(req, ctx) {
5469
+ const parseResult = parseJsonBody(req);
5470
+ if (!parseResult.success) {
5471
+ return parseResult.error;
5472
+ }
5473
+ const result = await handleSetupRevalidate(parseResult.data, ctx.config.hooks);
5474
+ return { status: result.status, body: result.body };
5475
+ }
5346
5476
  async function handleOAuthCallbackRoute(req, ctx) {
5347
5477
  const parseResult = parseJsonBody(req);
5348
5478
  if (!parseResult.success) {
@@ -5704,6 +5834,9 @@ async function routeRequest(req, ctx) {
5704
5834
  if (req.path === "/provision" && req.method === "POST") {
5705
5835
  return handleProvisionRoute(req, ctx);
5706
5836
  }
5837
+ if (req.path === "/setup/revalidate" && req.method === "POST") {
5838
+ return handleSetupRevalidateRoute(req, ctx);
5839
+ }
5707
5840
  if (req.path === "/oauth_callback" && req.method === "POST") {
5708
5841
  return handleOAuthCallbackRoute(req, ctx);
5709
5842
  }
@@ -6179,6 +6312,9 @@ function defineEnv(env) {
6179
6312
  function defineNavigation(navigation) {
6180
6313
  return navigation;
6181
6314
  }
6315
+ function defineSetupStep(step) {
6316
+ return step;
6317
+ }
6182
6318
 
6183
6319
  // src/config/schema-loader.ts
6184
6320
  var fs4 = __toESM(require("fs"));
@@ -8717,7 +8853,6 @@ var index_default = { z: import_v414.z };
8717
8853
  ModelDefinitionSchema,
8718
8854
  ModelDependencySchema,
8719
8855
  ModelFieldDefinitionSchema,
8720
- ModelMapperBlockDefinitionSchema,
8721
8856
  MoneyMinorRangeSchema,
8722
8857
  NavigationBreadcrumbSchema,
8723
8858
  NavigationConfigSchema,
@@ -8768,6 +8903,8 @@ var index_default = { z: import_v414.z };
8768
8903
  SequencerContextError,
8769
8904
  SequencerLockError,
8770
8905
  SequencerNotFoundError,
8906
+ SetupStepDefinitionSchema,
8907
+ SetupStepKindSchema,
8771
8908
  SkedyulConfigSchema,
8772
8909
  SkillExampleSchema,
8773
8910
  SkillMetadataSchema,
@@ -8862,6 +8999,7 @@ var index_default = { z: import_v414.z };
8862
8999
  defineNavigation,
8863
9000
  definePage,
8864
9001
  defineSchema,
9002
+ defineSetupStep,
8865
9003
  defineSkill,
8866
9004
  defineWorkflow,
8867
9005
  defineWorkflowYAML,
@@ -8923,6 +9061,7 @@ var index_default = { z: import_v414.z };
8923
9061
  sequencerAllow,
8924
9062
  sequencerRelease,
8925
9063
  server,
9064
+ setup,
8926
9065
  toGsm7,
8927
9066
  token,
8928
9067
  validateCRMSchema,
package/dist/schemas.d.ts CHANGED
@@ -352,6 +352,7 @@ export declare const EntityFieldDefinitionSchema: z.ZodObject<{
352
352
  date: "date";
353
353
  datetime: "datetime";
354
354
  }>>;
355
+ isUnique: z.ZodOptional<z.ZodBoolean>;
355
356
  matchCandidate: z.ZodOptional<z.ZodBoolean>;
356
357
  required: z.ZodOptional<z.ZodBoolean>;
357
358
  options: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
@@ -383,6 +384,7 @@ export declare const EntityDefinitionSchema: z.ZodObject<{
383
384
  date: "date";
384
385
  datetime: "datetime";
385
386
  }>>;
387
+ isUnique: z.ZodOptional<z.ZodBoolean>;
386
388
  matchCandidate: z.ZodOptional<z.ZodBoolean>;
387
389
  required: z.ZodOptional<z.ZodBoolean>;
388
390
  options: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
@@ -403,6 +405,7 @@ export declare const EntityDefinitionSchema: z.ZodObject<{
403
405
  date: "date";
404
406
  datetime: "datetime";
405
407
  }>>;
408
+ isUnique: z.ZodOptional<z.ZodBoolean>;
406
409
  matchCandidate: z.ZodOptional<z.ZodBoolean>;
407
410
  required: z.ZodOptional<z.ZodBoolean>;
408
411
  options: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
@@ -2166,11 +2169,6 @@ export declare const ListBlockDefinitionSchema: z.ZodObject<{
2166
2169
  icon: z.ZodOptional<z.ZodString>;
2167
2170
  emptyMessage: z.ZodOptional<z.ZodString>;
2168
2171
  }, z.core.$strip>;
2169
- /** Model mapper block definition - for mapping SHARED models to workspace models */
2170
- export declare const ModelMapperBlockDefinitionSchema: z.ZodObject<{
2171
- type: z.ZodLiteral<"model_mapper">;
2172
- model: z.ZodString;
2173
- }, z.core.$strip>;
2174
2172
  /** Union of all block types */
2175
2173
  export declare const PageBlockDefinitionSchema: z.ZodUnion<readonly [z.ZodObject<{
2176
2174
  type: z.ZodLiteral<"card">;
@@ -2569,9 +2567,6 @@ export declare const PageBlockDefinitionSchema: z.ZodUnion<readonly [z.ZodObject
2569
2567
  descriptionField: z.ZodOptional<z.ZodString>;
2570
2568
  icon: z.ZodOptional<z.ZodString>;
2571
2569
  emptyMessage: z.ZodOptional<z.ZodString>;
2572
- }, z.core.$strip>, z.ZodObject<{
2573
- type: z.ZodLiteral<"model_mapper">;
2574
- model: z.ZodString;
2575
2570
  }, z.core.$strip>]>;
2576
2571
  /** Mode for context data fetching */
2577
2572
  export declare const PageContextModeSchema: z.ZodPipe<z.ZodEnum<{
@@ -3119,9 +3114,6 @@ export declare const PageDefinitionSchema: z.ZodObject<{
3119
3114
  descriptionField: z.ZodOptional<z.ZodString>;
3120
3115
  icon: z.ZodOptional<z.ZodString>;
3121
3116
  emptyMessage: z.ZodOptional<z.ZodString>;
3122
- }, z.core.$strip>, z.ZodObject<{
3123
- type: z.ZodLiteral<"model_mapper">;
3124
- model: z.ZodString;
3125
3117
  }, z.core.$strip>]>>;
3126
3118
  actions: z.ZodOptional<z.ZodArray<z.ZodObject<{
3127
3119
  handle: z.ZodString;
@@ -3341,6 +3333,30 @@ export declare const InstallConfigSchema: z.ZodObject<{
3341
3333
  }>>;
3342
3334
  }, z.core.$strip>>>;
3343
3335
  }, z.core.$strip>;
3336
+ export declare const SetupStepKindSchema: z.ZodEnum<{
3337
+ crm: "crm";
3338
+ env: "env";
3339
+ app: "app";
3340
+ realtime: "realtime";
3341
+ }>;
3342
+ export declare const SetupStepDefinitionSchema: z.ZodObject<{
3343
+ handle: z.ZodString;
3344
+ label: z.ZodString;
3345
+ description: z.ZodOptional<z.ZodString>;
3346
+ kind: z.ZodEnum<{
3347
+ crm: "crm";
3348
+ env: "env";
3349
+ app: "app";
3350
+ realtime: "realtime";
3351
+ }>;
3352
+ requires: z.ZodOptional<z.ZodArray<z.ZodString>>;
3353
+ entities: z.ZodOptional<z.ZodArray<z.ZodString>>;
3354
+ workflowHandles: z.ZodOptional<z.ZodArray<z.ZodString>>;
3355
+ envKeys: z.ZodOptional<z.ZodArray<z.ZodString>>;
3356
+ listenToCrm: z.ZodOptional<z.ZodBoolean>;
3357
+ listenToEnv: z.ZodOptional<z.ZodBoolean>;
3358
+ capabilities: z.ZodOptional<z.ZodArray<z.ZodString>>;
3359
+ }, z.core.$strip>;
3344
3360
  export declare const ProvisionConfigSchema: z.ZodObject<{
3345
3361
  env: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
3346
3362
  label: z.ZodString;
@@ -3471,6 +3487,7 @@ export declare const ProvisionConfigSchema: z.ZodObject<{
3471
3487
  date: "date";
3472
3488
  datetime: "datetime";
3473
3489
  }>>;
3490
+ isUnique: z.ZodOptional<z.ZodBoolean>;
3474
3491
  matchCandidate: z.ZodOptional<z.ZodBoolean>;
3475
3492
  required: z.ZodOptional<z.ZodBoolean>;
3476
3493
  options: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
@@ -3491,6 +3508,7 @@ export declare const ProvisionConfigSchema: z.ZodObject<{
3491
3508
  date: "date";
3492
3509
  datetime: "datetime";
3493
3510
  }>>;
3511
+ isUnique: z.ZodOptional<z.ZodBoolean>;
3494
3512
  matchCandidate: z.ZodOptional<z.ZodBoolean>;
3495
3513
  required: z.ZodOptional<z.ZodBoolean>;
3496
3514
  options: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
@@ -4091,9 +4109,6 @@ export declare const ProvisionConfigSchema: z.ZodObject<{
4091
4109
  descriptionField: z.ZodOptional<z.ZodString>;
4092
4110
  icon: z.ZodOptional<z.ZodString>;
4093
4111
  emptyMessage: z.ZodOptional<z.ZodString>;
4094
- }, z.core.$strip>, z.ZodObject<{
4095
- type: z.ZodLiteral<"model_mapper">;
4096
- model: z.ZodString;
4097
4112
  }, z.core.$strip>]>>;
4098
4113
  actions: z.ZodOptional<z.ZodArray<z.ZodObject<{
4099
4114
  handle: z.ZodString;
@@ -4128,6 +4143,24 @@ export declare const ProvisionConfigSchema: z.ZodObject<{
4128
4143
  where: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
4129
4144
  }, z.core.$strip>>;
4130
4145
  }, z.core.$strip>>>;
4146
+ setup: z.ZodOptional<z.ZodArray<z.ZodObject<{
4147
+ handle: z.ZodString;
4148
+ label: z.ZodString;
4149
+ description: z.ZodOptional<z.ZodString>;
4150
+ kind: z.ZodEnum<{
4151
+ crm: "crm";
4152
+ env: "env";
4153
+ app: "app";
4154
+ realtime: "realtime";
4155
+ }>;
4156
+ requires: z.ZodOptional<z.ZodArray<z.ZodString>>;
4157
+ entities: z.ZodOptional<z.ZodArray<z.ZodString>>;
4158
+ workflowHandles: z.ZodOptional<z.ZodArray<z.ZodString>>;
4159
+ envKeys: z.ZodOptional<z.ZodArray<z.ZodString>>;
4160
+ listenToCrm: z.ZodOptional<z.ZodBoolean>;
4161
+ listenToEnv: z.ZodOptional<z.ZodBoolean>;
4162
+ capabilities: z.ZodOptional<z.ZodArray<z.ZodString>>;
4163
+ }, z.core.$strip>>>;
4131
4164
  }, z.core.$strip>;
4132
4165
  export declare const SkedyulConfigSchema: z.ZodObject<{
4133
4166
  name: z.ZodString;
@@ -4269,6 +4302,7 @@ export declare const SkedyulConfigSchema: z.ZodObject<{
4269
4302
  date: "date";
4270
4303
  datetime: "datetime";
4271
4304
  }>>;
4305
+ isUnique: z.ZodOptional<z.ZodBoolean>;
4272
4306
  matchCandidate: z.ZodOptional<z.ZodBoolean>;
4273
4307
  required: z.ZodOptional<z.ZodBoolean>;
4274
4308
  options: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
@@ -4289,6 +4323,7 @@ export declare const SkedyulConfigSchema: z.ZodObject<{
4289
4323
  date: "date";
4290
4324
  datetime: "datetime";
4291
4325
  }>>;
4326
+ isUnique: z.ZodOptional<z.ZodBoolean>;
4292
4327
  matchCandidate: z.ZodOptional<z.ZodBoolean>;
4293
4328
  required: z.ZodOptional<z.ZodBoolean>;
4294
4329
  options: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
@@ -4889,9 +4924,6 @@ export declare const SkedyulConfigSchema: z.ZodObject<{
4889
4924
  descriptionField: z.ZodOptional<z.ZodString>;
4890
4925
  icon: z.ZodOptional<z.ZodString>;
4891
4926
  emptyMessage: z.ZodOptional<z.ZodString>;
4892
- }, z.core.$strip>, z.ZodObject<{
4893
- type: z.ZodLiteral<"model_mapper">;
4894
- model: z.ZodString;
4895
4927
  }, z.core.$strip>]>>;
4896
4928
  actions: z.ZodOptional<z.ZodArray<z.ZodObject<{
4897
4929
  handle: z.ZodString;
@@ -4926,6 +4958,24 @@ export declare const SkedyulConfigSchema: z.ZodObject<{
4926
4958
  where: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
4927
4959
  }, z.core.$strip>>;
4928
4960
  }, z.core.$strip>>>;
4961
+ setup: z.ZodOptional<z.ZodArray<z.ZodObject<{
4962
+ handle: z.ZodString;
4963
+ label: z.ZodString;
4964
+ description: z.ZodOptional<z.ZodString>;
4965
+ kind: z.ZodEnum<{
4966
+ crm: "crm";
4967
+ env: "env";
4968
+ app: "app";
4969
+ realtime: "realtime";
4970
+ }>;
4971
+ requires: z.ZodOptional<z.ZodArray<z.ZodString>>;
4972
+ entities: z.ZodOptional<z.ZodArray<z.ZodString>>;
4973
+ workflowHandles: z.ZodOptional<z.ZodArray<z.ZodString>>;
4974
+ envKeys: z.ZodOptional<z.ZodArray<z.ZodString>>;
4975
+ listenToCrm: z.ZodOptional<z.ZodBoolean>;
4976
+ listenToEnv: z.ZodOptional<z.ZodBoolean>;
4977
+ capabilities: z.ZodOptional<z.ZodArray<z.ZodString>>;
4978
+ }, z.core.$strip>>>;
4929
4979
  }, z.core.$strip>, z.ZodUnknown]>>;
4930
4980
  agents: z.ZodOptional<z.ZodArray<z.ZodObject<{
4931
4981
  handle: z.ZodString;
@@ -4987,6 +5037,8 @@ export type WebhookHandlerDefinition = z.infer<typeof WebhookHandlerDefinitionSc
4987
5037
  export type Webhooks = z.infer<typeof WebhooksSchema>;
4988
5038
  export type InstallConfig = z.infer<typeof InstallConfigSchema>;
4989
5039
  export type ProvisionConfig = z.infer<typeof ProvisionConfigSchema>;
5040
+ export type SetupStepKind = z.infer<typeof SetupStepKindSchema>;
5041
+ export type SetupStepDefinition = z.infer<typeof SetupStepDefinitionSchema>;
4990
5042
  export type FormV2StyleProps = z.infer<typeof FormV2StylePropsSchema>;
4991
5043
  export type FieldSettingButtonProps = z.infer<typeof FieldSettingButtonPropsSchema>;
4992
5044
  export type RelationshipExtension = z.infer<typeof RelationshipExtensionSchema>;
@@ -4999,7 +5051,6 @@ export type CardBlockHeader = z.infer<typeof CardBlockHeaderSchema>;
4999
5051
  export type CardBlockDefinition = z.infer<typeof CardBlockDefinitionSchema>;
5000
5052
  export type LegacyFormBlockDefinition = z.infer<typeof LegacyFormBlockDefinitionSchema>;
5001
5053
  export type ListBlockDefinition = z.infer<typeof ListBlockDefinitionSchema>;
5002
- export type ModelMapperBlockDefinition = z.infer<typeof ModelMapperBlockDefinitionSchema>;
5003
5054
  export declare const MessageSendChannelSchema: z.ZodObject<{
5004
5055
  id: z.ZodString;
5005
5056
  handle: z.ZodString;
@@ -8,5 +8,6 @@ export * from './types';
8
8
  export { handleInstall } from './install-handler';
9
9
  export { handleUninstall } from './uninstall-handler';
10
10
  export { handleProvision } from './provision-handler';
11
+ export { handleSetupRevalidate } from './setup-revalidate-handler';
11
12
  export { handleOAuthCallback } from './oauth-callback-handler';
12
13
  export { parseWebhookRequest, executeWebhookHandler, isMethodAllowed, type ParsedWebhookData, } from './webhook-handler';
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Setup revalidate handler - shared implementation for serverless and dedicated servers.
3
+ */
4
+ import type { ServerHooks } from '../../types';
5
+ import type { HandlerResult, SetupRevalidateRequestBody } from './types';
6
+ /**
7
+ * Handle setup revalidate request (CRM/env change notification).
8
+ */
9
+ export declare function handleSetupRevalidate(body: SetupRevalidateRequestBody, hooks: ServerHooks | undefined): Promise<HandlerResult>;
@@ -99,3 +99,37 @@ export interface ProvisionRequestBody {
99
99
  };
100
100
  };
101
101
  }
102
+ /**
103
+ * Setup revalidate request body format.
104
+ */
105
+ export interface SetupRevalidateRequestBody {
106
+ env?: Record<string, string>;
107
+ invocation?: InvocationContext;
108
+ reason: 'crm_changed' | 'env_changed';
109
+ steps: string[];
110
+ crm?: {
111
+ migrationId?: string;
112
+ deletedModelIds?: string[];
113
+ deletedFieldIds?: string[];
114
+ createdModelIds?: string[];
115
+ updatedModelIds?: string[];
116
+ createdFieldIds?: string[];
117
+ updatedFieldIds?: string[];
118
+ };
119
+ envChange?: {
120
+ keys: string[];
121
+ };
122
+ context?: {
123
+ app: {
124
+ id: string;
125
+ versionId: string;
126
+ handle: string;
127
+ versionHandle: string;
128
+ };
129
+ appInstallationId: string;
130
+ workplace: {
131
+ id: string;
132
+ subdomain: string;
133
+ };
134
+ };
135
+ }
@@ -37,6 +37,10 @@ export declare function handleUninstallRoute(req: UnifiedRequest, ctx: RouteCont
37
37
  * Handle POST /provision
38
38
  */
39
39
  export declare function handleProvisionRoute(req: UnifiedRequest, ctx: RouteContext): Promise<UnifiedResponse>;
40
+ /**
41
+ * Handle POST /setup/revalidate
42
+ */
43
+ export declare function handleSetupRevalidateRoute(req: UnifiedRequest, ctx: RouteContext): Promise<UnifiedResponse>;
40
44
  /**
41
45
  * Handle POST /oauth_callback
42
46
  */
@@ -6,5 +6,5 @@
6
6
  */
7
7
  export type { UnifiedRequest, UnifiedResponse, RouteContext, CallToolFn, ParsedJsonRpcBody, SkedyulToolCallArgs, ParseResult, } from './types';
8
8
  export { fromLambdaEvent, toLambdaResponse, parseJsonBody, parseJsonRpcBody, getHeader, getContentType, parseBodyByContentType, } from './adapters';
9
- export { handleHealthRoute, handleConfigRoute, handleCoreRoute, handleCoreWebhookRoute, handleEstimateRoute, handleInstallRoute, handleUninstallRoute, handleProvisionRoute, handleOAuthCallbackRoute, handleWebhookRoute, handleMcpRoute, createNotFoundResponse, createOptionsResponse, createErrorResponse, } from './handlers';
9
+ export { handleHealthRoute, handleConfigRoute, handleCoreRoute, handleCoreWebhookRoute, handleEstimateRoute, handleInstallRoute, handleUninstallRoute, handleProvisionRoute, handleSetupRevalidateRoute, handleOAuthCallbackRoute, handleWebhookRoute, handleMcpRoute, createNotFoundResponse, createOptionsResponse, createErrorResponse, } from './handlers';
10
10
  export { routeRequest } from './router';
package/dist/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
  }