@novu/framework 2.0.0-canary.0 → 2.0.0-canary.2

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/express.d.ts CHANGED
@@ -4,6 +4,28 @@ import 'zod';
4
4
  import '@novu/shared';
5
5
 
6
6
  declare const frameworkName: SupportedFrameworkName;
7
+ /**
8
+ * Serve and register any declared workflows with Novu, making them available
9
+ * to be triggered by events.
10
+ *
11
+ * The return type is currently `any` to ensure there's no required type matches
12
+ * between the `express` and `vercel` packages. This may change in the future to
13
+ * appropriately infer.
14
+ *
15
+ * @example
16
+ * ```ts
17
+ * import { serve } from "@novu/framework/express";
18
+ * import { myWorkflow } from "./src/novu/workflows"; // Your workflows
19
+ *
20
+ * // Important: ensure you add JSON middleware to process incoming JSON POST payloads.
21
+ * app.use(express.json());
22
+ * app.use(
23
+ * // Expose the middleware on our recommended path at `/api/novu`.
24
+ * "/api/novu",
25
+ * serve({ workflows: [myWorkflow] })
26
+ * );
27
+ * ```
28
+ */
7
29
  declare const serve: (options: ServeHandlerOptions) => any;
8
30
 
9
31
  export { frameworkName, serve };
package/dist/express.js CHANGED
@@ -17,7 +17,7 @@ var N__default = /*#__PURE__*/_interopDefault(N);
17
17
  var me__default = /*#__PURE__*/_interopDefault(me);
18
18
  var Ne__default = /*#__PURE__*/_interopDefault(Ne);
19
19
 
20
- var D=(r=>(r.TRIGGER="trigger",r.EXECUTE="execute",r.PREVIEW="preview",r))(D||{}),k=(r=>(r.DISCOVER="discover",r.HEALTH_CHECK="health-check",r.CODE="code",r))(k||{});var h=(c=>(c.WORKFLOW_NOT_FOUND_ERROR="WorkflowNotFoundError",c.WORKFLOW_ALREADY_EXISTS_ERROR="WorkflowAlreadyExistsError",c.WORKFLOW_EXECUTION_FAILED_ERROR="WorkflowExecutionFailedError",c.EXECUTION_STATE_OUTPUT_INVALID_ERROR="ExecutionStateOutputInvalidError",c.EXECUTION_STATE_RESULT_INVALID_ERROR="ExecutionStateResultInvalidError",c.EXECUTION_PROVIDER_OUTPUT_INVALID_ERROR="ExecutionProviderOutputInvalidError",c.PROVIDER_NOT_FOUND_ERROR="ProviderNotFoundError",c.PROVIDER_EXECUTION_FAILED_ERROR="ProviderExecutionFailedError",c.STEP_NOT_FOUND_ERROR="StepNotFoundError",c.STEP_ALREADY_EXISTS_ERROR="StepAlreadyExistsError",c.STEP_EXECUTION_FAILED_ERROR="StepExecutionFailedError",c.EXECUTION_STATE_CORRUPT_ERROR="ExecutionStateCorruptError",c.EXECUTION_EVENT_PAYLOAD_INVALID_ERROR="ExecutionEventPayloadInvalidError",c.EXECUTION_EVENT_CONTROL_INVALID_ERROR="ExecutionEventControlInvalidError",c.EXECUTION_STATE_CONTROL_INVALID_ERROR="ExecutionStateControlInvalidError",c.METHOD_NOT_ALLOWED_ERROR="MethodNotAllowedError",c.INVALID_ACTION_ERROR="InvalidActionError",c.MISSING_SECRET_KEY_ERROR="MissingSecretKeyError",c.SIGNATURE_MISMATCH_ERROR="SignatureMismatchError",c.SIGNATURE_NOT_FOUND_ERROR="SignatureNotFoundError",c.SIGNATURE_INVALID_ERROR="SignatureInvalidError",c.SIGNATURE_EXPIRED_ERROR="SignatureExpiredError",c.SIGNING_KEY_NOT_FOUND_ERROR="SigningKeyNotFoundError",c.PLATFORM_ERROR="PlatformError",c.SIGNATURE_VERSION_INVALID_ERROR="SignatureVersionInvalidError",c.WORKFLOW_PAYLOAD_INVALID_ERROR="WorkflowPayloadInvalidError",c))(h||{});var U=(r=>(r.POST="POST",r.GET="GET",r.OPTIONS="OPTIONS",r))(U||{});var O=class extends Error{data},L=class extends O{statusCode=404},R=class extends O{statusCode=400},T=class extends O{statusCode=401},m=class extends O{statusCode=500},b=class extends O{statusCode=409};var V=class extends R{code="ExecutionStateCorruptError";constructor(e,t){super(`Workflow with id: \`${e}\` has a corrupt state. Step with id: \`${t}\` does not exist. Please provide the missing state.`),this.data={workflowId:e,stepId:t};}},x=class extends R{code="ExecutionEventPayloadInvalidError";constructor(e,t){super(`Workflow with id: \`${e}\` has invalid \`payload\`. Please provide the correct event payload.`),this.data=t;}},F=class extends R{code="ExecutionEventControlInvalidError";constructor(e,t){super(`Workflow with id: \`${e}\` has invalid \`controls\`. Please provide the correct event controls.`),this.data=t;}},W=class extends R{code="ExecutionStateControlInvalidError";constructor(e,t,r){super(`Workflow with id: \`${e}\` has an invalid state. Step with id: \`${t}\` has invalid \`controls\`. Please provide the correct step controls.`),this.data=r;}},$=class extends R{code="ExecutionStateOutputInvalidError";constructor(e,t,r){super(`Workflow with id: \`${e}\` has an invalid state. Step with id: \`${t}\` has invalid output. Please provide the correct step output.`),this.data=r;}},M=class extends R{code="ExecutionStateResultInvalidError";constructor(e,t,r){super(`Workflow with id: \`${e}\` has an invalid state. Step with id: \`${t}\` has invalid result. Please provide the correct step result.`),this.data=r;}},G=class extends R{code="ExecutionProviderOutputInvalidError";constructor(e,t,r,o){super(`Workflow with id: \`${e}\` has an invalid state. Step with id: \`${t}\` and provider with id: \`${r}\` has invalid output. Please provide the correct provider output.`),this.data=o;}};var j=class extends Error{statusCode;message;code;constructor(e,t,r){super(r),this.statusCode=e,this.code=t;}};var l={info:s=>N__default.default.blue(s),warning:s=>N__default.default.yellow(s),error:s=>N__default.default.red(s),success:s=>N__default.default.green(s),underline:s=>N__default.default.underline(s),bold:s=>N__default.default.bold(s)},p={SUCCESS:l.success("\u2714"),ERROR:l.error("\u2717"),WARNING:l.warning("\u26A0"),INFO:l.info("\u2139"),ARROW:l.bold("\u2192"),MOCK:l.info("\u25CB"),HYDRATED:l.bold(l.info("\u2192")),STEP:l.info("\u03C3"),ACTION:l.info("\u03B1"),DURATION:l.info("\u0394"),PROVIDER:l.info("\u2699"),OUTPUT:l.info("\u21E2"),INPUT:l.info("\u21E0"),WORKFLOW:l.info("\u03C9"),STATE:l.info("\u03C3"),EXECUTE:l.info("\u03B5"),PREVIEW:l.info("\u03C1")};var de=s=>Object.values(s).map(e=>`\`${e}\``).join(", "),K=s=>s.replaceAll(/(\w)(\w*)/g,(e,t,r)=>t.toUpperCase()+r.toLowerCase()).replaceAll(/[\s-]+/g,"");var ue=(s,e="https://api.novu.co")=>{let t=process.env.NOVU_API_URL||e;return {post:async(r,o)=>{let i=await fetch(t+"/v1"+r,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`ApiKey ${s}`},body:JSON.stringify(o)}),n=await i.json();if(i.ok)return n;throw new j(n.statusCode,n.error,n.message)},delete:async r=>(await fetch(t+"/v1"+r,{method:"DELETE",headers:{"Content-Type":"application/json",Authorization:`ApiKey ${s}`}})).json()}};var Y=class extends O{code="MethodNotAllowedError";statusCode=405;message=`Method not allowed. Please use one of ${de(U)}`},y=class extends R{code="InvalidActionError";constructor(e,t){super(`Invalid query string: \`action\`=\`${e}\`. Please use one of ${de(t)}`);}};var X=class extends m{code="PlatformError";message="Something went wrong. Please try again later."};var g=class extends b{constructor(e,t){super(`${K(e)} with id: \`${t}\` already exists. Please use a different id.`);}},w=class extends L{constructor(e,t){super(`${K(e)} with id: \`${t}\` does not exist. Please provide a valid id.`);}},A=class extends m{constructor(e,t){super(`Failed to execute ${K(e)} with id: \`${t}\`. Please try again later.`);}};var J=class extends w{code="ProviderNotFoundError";constructor(e){super("provider",e);}},B=class extends A{code="ProviderExecutionFailedError";constructor(e){super("workflow",e);}};var q=class extends T{code="SignatureMismatchError";constructor(){super("Signature does not match the expected signature. Please ensure the signature provided in the `novu-signature` header is correct and try again.");}},z=class extends T{code="SignatureNotFoundError";constructor(){super("Signature not found. Please provide a signature in the `novu-signature` header");}},Z=class extends T{code="SignatureInvalidError";constructor(){super("Signature is invalid. Please provide a valid signature in the `novu-signature` header");}},Q=class extends T{code="SignatureExpiredError";constructor(){super(`Signature expired. Please provide a signature with a timestamp no older than ${5} minutes in the \`novu-signature\` header`);}},H=class extends T{code="SigningKeyNotFoundError";constructor(){super("Signature key not found. Please provide a valid key in the Client constructor `config.secretKey`");}};var ee=class extends w{code="StepNotFoundError";constructor(e){super("step",e);}};var S=class extends w{code="WorkflowNotFoundError";constructor(e){super("workflow",e);}},te=class extends g{code="WorkflowAlreadyExistsError";constructor(e){super("workflow",e);}};var re=class{ajv;compiledSchemas;constructor(){this.ajv=new me__default.default({useDefaults:!0,removeAdditional:"all"}),Ne__default.default(this.ajv),this.compiledSchemas=new Map;}isSchema(e){return typeof e=="boolean"?!1:e.type==="object"||!!e.anyOf||!!e.oneOf}async validate(e,t){let r=this.compiledSchemas.get(t);return r||(r=this.ajv.compile(t),this.compiledSchemas.set(t,r)),r(e)?{success:!0,data:e}:{success:!1,errors:r.errors.map(i=>({path:i.instancePath,message:i.message}))}}transformToJsonSchema(e){return e}};var oe=class{isSchema(e){return e.safeParseAsync!==void 0}async validate(e,t){let r=t.safeParse(e);return r.success?{success:!0,data:r.data}:{success:!1,errors:r.error.errors.map(o=>({path:`/${o.path.join("/")}`,message:o.message}))}}transformToJsonSchema(e){try{return zodToJsonSchema.zodToJsonSchema(e)}catch(t){throw t?.message?.includes("Cannot find module")&&console.error("Tried to use a zod schema in @novu/framework without `zod-to-json-schema` installed. Please install it by running `npm install zod-to-json-schema`."),t}}};var Ee=[new oe,new re],he=async(s,e)=>{for(let t of Ee)if(t.isSchema(s))return t.validate(e,s);throw new Error("Invalid schema")},Oe=s=>{for(let e of Ee)if(e.isSchema(s))return e.transformToJsonSchema(s);throw new Error("Invalid schema")};var Te={name:"@novu/framework",version:"2.0.0-canary.0",description:"The Code-First Notifications Workflow SDK.",main:"./dist/index.js",types:"./dist/index.d.ts",publishConfig:{registry:"https://registry.npmjs.org",access:"public"},private:!1,repository:{type:"git",url:"git+https://github.com/novuhq/novu.git"},files:["dist","README.md"],scripts:{preinstall:"npx only-allow pnpm",test:"vitest","test:watch":"vitest --watch",lint:"eslint src --ext .ts","lint:fix":"eslint src --ext .ts --fix",format:"prettier --check --ignore-path .gitignore .","format:fix":"prettier --write --ignore-path .gitignore .",build:"tsup","build:watch":"tsup --watch","$comment:bump:prerelease":"This is a workaround to support `npm version prerelease` with lerna","bump:prerelease":"npm version prerelease --preid=alpha & PID=$!; (sleep 1 && kill -9 $PID) & wait $PID","release:alpha":"pnpm bump:prerelease || pnpm build && npm publish"},keywords:["novu","code-first","workflows","durable","sdk","notifications","email","sms","push","webhooks","next","nuxt","h3","express"],author:"Novu Team <engineering@novu.co>",license:"ISC",exports:{".":{require:"./dist/index.js",import:"./dist/index.js",types:"./dist/index.d.ts"},"./express":{require:"./dist/express.js",import:"./dist/express.js",types:"./dist/express.d.ts"},"./next":{require:"./dist/next.js",import:"./dist/next.js",types:"./dist/next.d.ts"},"./nuxt":{require:"./dist/nuxt.js",import:"./dist/nuxt.js",types:"./dist/nuxt.d.ts"},"./h3":{require:"./dist/h3.js",import:"./dist/h3.js",types:"./dist/h3.d.ts"},"./sveltekit":{require:"./dist/sveltekit.js",import:"./dist/sveltekit.js",types:"./dist/sveltekit.d.ts"},"./remix":{require:"./dist/remix.js",import:"./dist/remix.js",types:"./dist/remix.d.ts"}},peerDependencies:{"@sveltejs/kit":">=1.27.3","@vercel/node":">=2.15.9",express:">=4.19.2",h3:">=1.8.1",next:">=12.0.0",zod:">=3.0.0","zod-to-json-schema":">=3.0.0"},peerDependenciesMeta:{"@sveltejs/kit":{optional:!0},"@vercel/node":{optional:!0},express:{optional:!0},fastify:{optional:!0},h3:{optional:!0},next:{optional:!0},zod:{optional:!0},"zod-to-json-schema":{optional:!0}},devDependencies:{"@sveltejs/kit":"^1.27.3","@types/express":"^4.17.13","@types/json-schema":"^7.0.15","@types/node":"^20.11.20","@vercel/node":"^2.15.9",express:"^4.19.2",h3:"^1.11.1",next:"^13.5.4",prettier:"^3.2.5","ts-node":"^10.9.2",tsup:"^8.0.2",typescript:"^5.3.3",vitest:"^1.2.1",zod:"^3.23.0","zod-to-json-schema":"^3.23.0"},dependencies:{"@novu/shared":"workspace:*",ajv:"^8.12.0","ajv-formats":"^2.1.1","better-ajv-errors":"^1.2.0",chalk:"^4.1.2","cross-fetch":"^4.0.0","json-schema-faker":"^0.5.6","json-schema-to-ts":"^3.0.0",liquidjs:"^10.13.1",ora:"^5.4.1"}};var P=Te.version,se="2024-06-26";jsonSchemaFaker.JSONSchemaFaker.random.shuffle=function(){return ["[placeholder]"]};jsonSchemaFaker.JSONSchemaFaker.option({useDefaultValue:!0,alwaysFakeOptionals:!0});function ye(){return process.env.NODE_ENV==="development"}var ne=class{discoveredWorkflows=[];templateEngine=new liquidjs.Liquid;secretKey;version=P;strictAuthentication;constructor(e){let t=this.buildOptions(e);this.secretKey=t.secretKey,this.strictAuthentication=t.strictAuthentication;}buildOptions(e){let t={secretKey:void 0,strictAuthentication:!ye()};return t.secretKey=e?.secretKey||process.env.NOVU_SECRET_KEY||process.env.NOVU_API_KEY,e?.strictAuthentication!==void 0?t.strictAuthentication=e.strictAuthentication:process.env.NOVU_STRICT_AUTHENTICATION_ENABLED!==void 0&&(t.strictAuthentication=process.env.NOVU_STRICT_AUTHENTICATION_ENABLED==="true"),t}addWorkflows(e){for(let t of e){if(this.discoveredWorkflows.some(r=>r.workflowId===t.definition.workflowId))throw new te(t.definition.workflowId);this.discoveredWorkflows.push(t.definition);}}healthCheck(){let e=this.discoveredWorkflows.length,t=this.discoveredWorkflows.reduce((r,o)=>r+o.steps.length,0);return {status:"ok",sdkVersion:P,frameworkVersion:se,discovered:{workflows:e,steps:t}}}getWorkflow(e){let t=this.discoveredWorkflows.find(r=>r.workflowId===e);if(t)return t;throw new S(e)}getStep(e,t){let o=this.getWorkflow(e).steps.find(i=>i.stepId===t);if(o)return o;throw new ee(t)}getRegisteredWorkflows(){return this.discoveredWorkflows}discover(){return {workflows:this.getRegisteredWorkflows()}}mock(e){return jsonSchemaFaker.JSONSchemaFaker.generate(Oe(e))}async validate(e,t,r,o,i,n,d){let a=await he(t,e);if(a.success)return a.data;switch(r){case"event":this.throwInvalidEvent(o,i,a.errors);case"step":this.throwInvalidStep(n,o,i,a.errors);case"provider":this.throwInvalidProvider(n,d,o,i,a.errors);default:throw new Error(`Invalid component: '${r}'`)}}throwInvalidProvider(e,t,r,o,i){if(!e)throw new Error("stepId is required");if(!t)throw new Error("providerId is required");switch(r){case"output":throw new G(o,e,t,i);default:throw new Error(`Invalid payload type: '${r}'`)}}throwInvalidStep(e,t,r,o){if(!e)throw new Error("stepId is required");switch(t){case"output":throw new $(r,e,o);case"result":throw new M(r,e,o);case"controls":throw new W(r,e,o);default:throw new Error(`Invalid payload type: '${t}'`)}}throwInvalidEvent(e,t,r){switch(e){case"controls":throw new F(t,r);case"payload":throw new x(t,r);default:throw new Error(`Invalid payload type: '${e}'`)}}executeStepFactory(e,t){return async(r,o,i)=>{let n=this.getStep(e.workflowId,r),d=ge(e),a=await this.createStepControls(n,d),E=e.action==="preview";if(!E&&await this.shouldSkip(i?.skip,a))return t({options:{skip:!0}}),{};let u=this.previewStep.bind(this),I=this.executeStep.bind(this),C=await(E?u:I)(e,{...n,providers:n.providers.map(f=>{let v=i?.providers?.[f.type];if(!v)throw new J(f.type);return {...f,resolve:v}}),resolve:o});return r===e.stepId&&t(C),C.outputs}}async shouldSkip(e,t){return e?e(t):!1}async executeWorkflow(e){let o=`${{execute:"Executing",preview:"Previewing"}[e.action]} workflowId:`;console.log(`
20
+ var D=(r=>(r.TRIGGER="trigger",r.EXECUTE="execute",r.PREVIEW="preview",r))(D||{}),k=(r=>(r.DISCOVER="discover",r.HEALTH_CHECK="health-check",r.CODE="code",r))(k||{});var h=(c=>(c.WORKFLOW_NOT_FOUND_ERROR="WorkflowNotFoundError",c.WORKFLOW_ALREADY_EXISTS_ERROR="WorkflowAlreadyExistsError",c.WORKFLOW_EXECUTION_FAILED_ERROR="WorkflowExecutionFailedError",c.EXECUTION_STATE_OUTPUT_INVALID_ERROR="ExecutionStateOutputInvalidError",c.EXECUTION_STATE_RESULT_INVALID_ERROR="ExecutionStateResultInvalidError",c.EXECUTION_PROVIDER_OUTPUT_INVALID_ERROR="ExecutionProviderOutputInvalidError",c.PROVIDER_NOT_FOUND_ERROR="ProviderNotFoundError",c.PROVIDER_EXECUTION_FAILED_ERROR="ProviderExecutionFailedError",c.STEP_NOT_FOUND_ERROR="StepNotFoundError",c.STEP_ALREADY_EXISTS_ERROR="StepAlreadyExistsError",c.STEP_EXECUTION_FAILED_ERROR="StepExecutionFailedError",c.EXECUTION_STATE_CORRUPT_ERROR="ExecutionStateCorruptError",c.EXECUTION_EVENT_PAYLOAD_INVALID_ERROR="ExecutionEventPayloadInvalidError",c.EXECUTION_EVENT_CONTROL_INVALID_ERROR="ExecutionEventControlInvalidError",c.EXECUTION_STATE_CONTROL_INVALID_ERROR="ExecutionStateControlInvalidError",c.METHOD_NOT_ALLOWED_ERROR="MethodNotAllowedError",c.INVALID_ACTION_ERROR="InvalidActionError",c.MISSING_SECRET_KEY_ERROR="MissingSecretKeyError",c.SIGNATURE_MISMATCH_ERROR="SignatureMismatchError",c.SIGNATURE_NOT_FOUND_ERROR="SignatureNotFoundError",c.SIGNATURE_INVALID_ERROR="SignatureInvalidError",c.SIGNATURE_EXPIRED_ERROR="SignatureExpiredError",c.SIGNING_KEY_NOT_FOUND_ERROR="SigningKeyNotFoundError",c.PLATFORM_ERROR="PlatformError",c.SIGNATURE_VERSION_INVALID_ERROR="SignatureVersionInvalidError",c.WORKFLOW_PAYLOAD_INVALID_ERROR="WorkflowPayloadInvalidError",c))(h||{});var U=(r=>(r.POST="POST",r.GET="GET",r.OPTIONS="OPTIONS",r))(U||{});var O=class extends Error{data},L=class extends O{statusCode=404},R=class extends O{statusCode=400},T=class extends O{statusCode=401},m=class extends O{statusCode=500},b=class extends O{statusCode=409};var V=class extends R{code="ExecutionStateCorruptError";constructor(e,t){super(`Workflow with id: \`${e}\` has a corrupt state. Step with id: \`${t}\` does not exist. Please provide the missing state.`),this.data={workflowId:e,stepId:t};}},x=class extends R{code="ExecutionEventPayloadInvalidError";constructor(e,t){super(`Workflow with id: \`${e}\` has invalid \`payload\`. Please provide the correct event payload.`),this.data=t;}},F=class extends R{code="ExecutionEventControlInvalidError";constructor(e,t){super(`Workflow with id: \`${e}\` has invalid \`controls\`. Please provide the correct event controls.`),this.data=t;}},W=class extends R{code="ExecutionStateControlInvalidError";constructor(e,t,r){super(`Workflow with id: \`${e}\` has an invalid state. Step with id: \`${t}\` has invalid \`controls\`. Please provide the correct step controls.`),this.data=r;}},$=class extends R{code="ExecutionStateOutputInvalidError";constructor(e,t,r){super(`Workflow with id: \`${e}\` has an invalid state. Step with id: \`${t}\` has invalid output. Please provide the correct step output.`),this.data=r;}},M=class extends R{code="ExecutionStateResultInvalidError";constructor(e,t,r){super(`Workflow with id: \`${e}\` has an invalid state. Step with id: \`${t}\` has invalid result. Please provide the correct step result.`),this.data=r;}},G=class extends R{code="ExecutionProviderOutputInvalidError";constructor(e,t,r,o){super(`Workflow with id: \`${e}\` has an invalid state. Step with id: \`${t}\` and provider with id: \`${r}\` has invalid output. Please provide the correct provider output.`),this.data=o;}};var j=class extends Error{statusCode;message;code;constructor(e,t,r){super(r),this.statusCode=e,this.code=t;}};var l={info:s=>N__default.default.blue(s),warning:s=>N__default.default.yellow(s),error:s=>N__default.default.red(s),success:s=>N__default.default.green(s),underline:s=>N__default.default.underline(s),bold:s=>N__default.default.bold(s)},p={SUCCESS:l.success("\u2714"),ERROR:l.error("\u2717"),WARNING:l.warning("\u26A0"),INFO:l.info("\u2139"),ARROW:l.bold("\u2192"),MOCK:l.info("\u25CB"),HYDRATED:l.bold(l.info("\u2192")),STEP:l.info("\u03C3"),ACTION:l.info("\u03B1"),DURATION:l.info("\u0394"),PROVIDER:l.info("\u2699"),OUTPUT:l.info("\u21E2"),INPUT:l.info("\u21E0"),WORKFLOW:l.info("\u03C9"),STATE:l.info("\u03C3"),EXECUTE:l.info("\u03B5"),PREVIEW:l.info("\u03C1")};var de=s=>Object.values(s).map(e=>`\`${e}\``).join(", "),K=s=>s.replaceAll(/(\w)(\w*)/g,(e,t,r)=>t.toUpperCase()+r.toLowerCase()).replaceAll(/[\s-]+/g,"");var ue=(s,e="https://api.novu.co")=>{let t=process.env.NOVU_API_URL||e;return {post:async(r,o)=>{let i=await fetch(t+"/v1"+r,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`ApiKey ${s}`},body:JSON.stringify(o)}),n=await i.json();if(i.ok)return n;throw new j(n.statusCode,n.error,n.message)},delete:async r=>(await fetch(t+"/v1"+r,{method:"DELETE",headers:{"Content-Type":"application/json",Authorization:`ApiKey ${s}`}})).json()}};var Y=class extends O{code="MethodNotAllowedError";statusCode=405;message=`Method not allowed. Please use one of ${de(U)}`},y=class extends R{code="InvalidActionError";constructor(e,t){super(`Invalid query string: \`action\`=\`${e}\`. Please use one of ${de(t)}`);}};var X=class extends m{code="PlatformError";message="Something went wrong. Please try again later."};var g=class extends b{constructor(e,t){super(`${K(e)} with id: \`${t}\` already exists. Please use a different id.`);}},w=class extends L{constructor(e,t){super(`${K(e)} with id: \`${t}\` does not exist. Please provide a valid id.`);}},A=class extends m{constructor(e,t){super(`Failed to execute ${K(e)} with id: \`${t}\`. Please try again later.`);}};var J=class extends w{code="ProviderNotFoundError";constructor(e){super("provider",e);}},B=class extends A{code="ProviderExecutionFailedError";constructor(e){super("workflow",e);}};var q=class extends T{code="SignatureMismatchError";constructor(){super("Signature does not match the expected signature. Please ensure the signature provided in the `novu-signature` header is correct and try again.");}},z=class extends T{code="SignatureNotFoundError";constructor(){super("Signature not found. Please provide a signature in the `novu-signature` header");}},Z=class extends T{code="SignatureInvalidError";constructor(){super("Signature is invalid. Please provide a valid signature in the `novu-signature` header");}},Q=class extends T{code="SignatureExpiredError";constructor(){super(`Signature expired. Please provide a signature with a timestamp no older than ${5} minutes in the \`novu-signature\` header`);}},H=class extends T{code="SigningKeyNotFoundError";constructor(){super("Signature key not found. Please provide a valid key in the Client constructor `config.secretKey`");}};var ee=class extends w{code="StepNotFoundError";constructor(e){super("step",e);}};var S=class extends w{code="WorkflowNotFoundError";constructor(e){super("workflow",e);}},te=class extends g{code="WorkflowAlreadyExistsError";constructor(e){super("workflow",e);}};var re=class{ajv;compiledSchemas;constructor(){this.ajv=new me__default.default({useDefaults:!0,removeAdditional:"all"}),Ne__default.default(this.ajv),this.compiledSchemas=new Map;}isSchema(e){return typeof e=="boolean"?!1:e.type==="object"||!!e.anyOf||!!e.oneOf}async validate(e,t){let r=this.compiledSchemas.get(t);return r||(r=this.ajv.compile(t),this.compiledSchemas.set(t,r)),r(e)?{success:!0,data:e}:{success:!1,errors:r.errors.map(i=>({path:i.instancePath,message:i.message}))}}transformToJsonSchema(e){return e}};var oe=class{isSchema(e){return e.safeParseAsync!==void 0}async validate(e,t){let r=t.safeParse(e);return r.success?{success:!0,data:r.data}:{success:!1,errors:r.error.errors.map(o=>({path:`/${o.path.join("/")}`,message:o.message}))}}transformToJsonSchema(e){try{return zodToJsonSchema.zodToJsonSchema(e)}catch(t){throw t?.message?.includes("Cannot find module")&&console.error("Tried to use a zod schema in @novu/framework without `zod-to-json-schema` installed. Please install it by running `npm install zod-to-json-schema`."),t}}};var Ee=[new oe,new re],he=async(s,e)=>{for(let t of Ee)if(t.isSchema(s))return t.validate(e,s);throw new Error("Invalid schema")},Oe=s=>{for(let e of Ee)if(e.isSchema(s))return e.transformToJsonSchema(s);throw new Error("Invalid schema")};var Te={name:"@novu/framework",version:"2.0.0-canary.2",description:"The Code-First Notifications Workflow SDK.",main:"./dist/index.js",types:"./dist/index.d.ts",publishConfig:{registry:"https://registry.npmjs.org",access:"public"},private:!1,repository:{type:"git",url:"git+https://github.com/novuhq/novu.git"},files:["dist","README.md"],scripts:{preinstall:"npx only-allow pnpm",test:"vitest","test:watch":"vitest --watch",lint:"eslint src --ext .ts","lint:fix":"eslint src --ext .ts --fix",format:"prettier --check --ignore-path .gitignore .","format:fix":"prettier --write --ignore-path .gitignore .",build:"tsup","build:watch":"tsup --watch","$comment:bump:prerelease":"This is a workaround to support `npm version prerelease` with lerna","bump:prerelease":"npm version prerelease --preid=alpha & PID=$!; (sleep 1 && kill -9 $PID) & wait $PID","release:alpha":"pnpm bump:prerelease || pnpm build && npm publish"},keywords:["novu","code-first","workflows","durable","sdk","notifications","email","sms","push","webhooks","next","nuxt","h3","express"],author:"Novu Team <engineering@novu.co>",license:"ISC",exports:{".":{require:"./dist/index.js",import:"./dist/index.js",types:"./dist/index.d.ts"},"./express":{require:"./dist/express.js",import:"./dist/express.js",types:"./dist/express.d.ts"},"./next":{require:"./dist/next.js",import:"./dist/next.js",types:"./dist/next.d.ts"},"./nuxt":{require:"./dist/nuxt.js",import:"./dist/nuxt.js",types:"./dist/nuxt.d.ts"},"./h3":{require:"./dist/h3.js",import:"./dist/h3.js",types:"./dist/h3.d.ts"},"./sveltekit":{require:"./dist/sveltekit.js",import:"./dist/sveltekit.js",types:"./dist/sveltekit.d.ts"},"./remix":{require:"./dist/remix.js",import:"./dist/remix.js",types:"./dist/remix.d.ts"}},peerDependencies:{"@sveltejs/kit":">=1.27.3","@vercel/node":">=2.15.9",express:">=4.19.2",h3:">=1.8.1",next:">=12.0.0",zod:">=3.0.0","zod-to-json-schema":">=3.0.0"},peerDependenciesMeta:{"@sveltejs/kit":{optional:!0},"@vercel/node":{optional:!0},express:{optional:!0},fastify:{optional:!0},h3:{optional:!0},next:{optional:!0},zod:{optional:!0},"zod-to-json-schema":{optional:!0}},devDependencies:{"@sveltejs/kit":"^1.27.3","@types/express":"^4.17.13","@types/json-schema":"^7.0.15","@types/node":"^20.11.20","@vercel/node":"^2.15.9",express:"^4.19.2",h3:"^1.11.1",next:"^13.5.4",prettier:"^3.2.5","ts-node":"^10.9.2",tsup:"^8.0.2",typescript:"^5.3.3",vitest:"^1.2.1",zod:"^3.23.0","zod-to-json-schema":"^3.23.0"},dependencies:{"@novu/shared":"^2.0.0-canary.0",ajv:"^8.12.0","ajv-formats":"^2.1.1","better-ajv-errors":"^1.2.0",chalk:"^4.1.2","cross-fetch":"^4.0.0","json-schema-faker":"^0.5.6","json-schema-to-ts":"^3.0.0",liquidjs:"^10.13.1",ora:"^5.4.1"}};var P=Te.version,se="2024-06-26";jsonSchemaFaker.JSONSchemaFaker.random.shuffle=function(){return ["[placeholder]"]};jsonSchemaFaker.JSONSchemaFaker.option({useDefaultValue:!0,alwaysFakeOptionals:!0});function ye(){return process.env.NODE_ENV==="development"}var ne=class{discoveredWorkflows=[];templateEngine=new liquidjs.Liquid;secretKey;version=P;strictAuthentication;constructor(e){let t=this.buildOptions(e);this.secretKey=t.secretKey,this.strictAuthentication=t.strictAuthentication;}buildOptions(e){let t={secretKey:void 0,strictAuthentication:!ye()};return t.secretKey=e?.secretKey||process.env.NOVU_SECRET_KEY||process.env.NOVU_API_KEY,e?.strictAuthentication!==void 0?t.strictAuthentication=e.strictAuthentication:process.env.NOVU_STRICT_AUTHENTICATION_ENABLED!==void 0&&(t.strictAuthentication=process.env.NOVU_STRICT_AUTHENTICATION_ENABLED==="true"),t}addWorkflows(e){for(let t of e){if(this.discoveredWorkflows.some(r=>r.workflowId===t.definition.workflowId))throw new te(t.definition.workflowId);this.discoveredWorkflows.push(t.definition);}}healthCheck(){let e=this.discoveredWorkflows.length,t=this.discoveredWorkflows.reduce((r,o)=>r+o.steps.length,0);return {status:"ok",sdkVersion:P,frameworkVersion:se,discovered:{workflows:e,steps:t}}}getWorkflow(e){let t=this.discoveredWorkflows.find(r=>r.workflowId===e);if(t)return t;throw new S(e)}getStep(e,t){let o=this.getWorkflow(e).steps.find(i=>i.stepId===t);if(o)return o;throw new ee(t)}getRegisteredWorkflows(){return this.discoveredWorkflows}discover(){return {workflows:this.getRegisteredWorkflows()}}mock(e){return jsonSchemaFaker.JSONSchemaFaker.generate(Oe(e))}async validate(e,t,r,o,i,n,d){let a=await he(t,e);if(a.success)return a.data;switch(r){case"event":this.throwInvalidEvent(o,i,a.errors);case"step":this.throwInvalidStep(n,o,i,a.errors);case"provider":this.throwInvalidProvider(n,d,o,i,a.errors);default:throw new Error(`Invalid component: '${r}'`)}}throwInvalidProvider(e,t,r,o,i){if(!e)throw new Error("stepId is required");if(!t)throw new Error("providerId is required");switch(r){case"output":throw new G(o,e,t,i);default:throw new Error(`Invalid payload type: '${r}'`)}}throwInvalidStep(e,t,r,o){if(!e)throw new Error("stepId is required");switch(t){case"output":throw new $(r,e,o);case"result":throw new M(r,e,o);case"controls":throw new W(r,e,o);default:throw new Error(`Invalid payload type: '${t}'`)}}throwInvalidEvent(e,t,r){switch(e){case"controls":throw new F(t,r);case"payload":throw new x(t,r);default:throw new Error(`Invalid payload type: '${e}'`)}}executeStepFactory(e,t){return async(r,o,i)=>{let n=this.getStep(e.workflowId,r),d=ge(e),a=await this.createStepControls(n,d),E=e.action==="preview";if(!E&&await this.shouldSkip(i?.skip,a))return t({options:{skip:!0}}),{};let u=this.previewStep.bind(this),I=this.executeStep.bind(this),C=await(E?u:I)(e,{...n,providers:n.providers.map(f=>{let v=i?.providers?.[f.type];if(!v)throw new J(f.type);return {...f,resolve:v}}),resolve:o});return r===e.stepId&&t(C),C.outputs}}async shouldSkip(e,t){return e?e(t):!1}async executeWorkflow(e){let o=`${{execute:"Executing",preview:"Previewing"}[e.action]} workflowId:`;console.log(`
21
21
  ${l.bold(l.underline(o))} '${e.workflowId}'`);let i=this.getWorkflow(e.workflowId),n=process.hrtime(),d={outputs:{},providers:{},options:{}},a,E=new Promise(_=>{a=_;}),u=_=>{a(),d=_;},I;try{if(e.action==="execute"&&!e.payload&&!e.data)throw new x(e.workflowId,{message:"Event `payload` is required"});let _=await this.createExecutionPayload(e,i);await Promise.race([E,i.execute({payload:_,environment:{},inputs:{},controls:{},subscriber:e.subscriber,step:{email:this.executeStepFactory(e,u),sms:this.executeStepFactory(e,u),inApp:this.executeStepFactory(e,u),digest:this.executeStepFactory(e,u),delay:this.executeStepFactory(e,u),push:this.executeStepFactory(e,u),chat:this.executeStepFactory(e,u),custom:this.executeStepFactory(e,u)}})]);}catch(_){I=_;}let ce=process.hrtime(n),C=ce[0],f=ce[1],v=C*1e3+f/1e6,we=I?p.ERROR:p.SUCCESS,Ie=e.action==="execute"?"Executed":e.action==="preview"?"Previewed":"Invalid action";if(console.log(`${we} ${Ie} workflowId: \`${e.workflowId}\``),this.prettyPrintExecute(e,v,I),I)throw I;return {outputs:d.outputs,providers:d.providers,options:d.options,metadata:{status:"success",error:!1,duration:v}}}async createExecutionPayload(e,t){let r=e.payload||e.data;if(e.action==="preview"){let i=this.mock(t.payload.schema);r=Object.assign(i,r);}return await this.validate(r,t.payload.unknownSchema,"event","payload",e.workflowId)}prettyPrintExecute(e,t,r){let o=r?p.ERROR:p.SUCCESS,i=e.action==="execute"?"Executed":e.action==="preview"?"Previewed":"Invalid action",n=r?"Failed to execute":i,d=r?l.error:l.success,a=`${o} ${n} workflowId: '${e.workflowId}`;console.log(`
22
22
  ${l.bold(d(a))}'`),console.log(` \u251C ${p.STEP} stepId: '${e.stepId}'`),console.log(` \u251C ${p.ACTION} action: '${e.action}'`),console.log(` \u2514 ${p.DURATION} duration: '${t.toFixed(2)}ms'
23
23
  `);}async executeProviders(e,t,r){return t.providers.reduce(async(o,i)=>{let n=await o,d=this.previewProvider.bind(this),a=this.executeProvider.bind(this),u=await(e.action==="preview"?d:a)(e,t,i,r);return {...n,[i.type]:u}},Promise.resolve({}))}previewProvider(e,t,r,o){return console.log(` ${p.MOCK} Mocked provider: \`${r.type}\``),this.mock(r.outputs.schema)}async executeProvider(e,t,r,o){let i=ie__default.default({indent:2}).start(`Executing provider: \`${r.type}\``);try{if(e.stepId===t.stepId){let n=await this.createStepControls(t,e),d=await r.resolve({controls:n,outputs:o}),a=await this.validate(d,r.outputs.unknownSchema,"step","output",e.workflowId,t.stepId,r.type);return i.succeed(`Executed provider: \`${r.type}\``),a}else i.stopAndPersist({symbol:p.HYDRATED,text:`Hydrated provider: \`${r.type}\``});}catch(n){throw i.stopAndPersist({symbol:p.ERROR,text:`Failed to execute provider: \`${r.type}\``}),new B(`Failed to execute provider: '${r.type}'.
package/dist/h3.d.ts CHANGED
@@ -1,11 +1,36 @@
1
- import * as h3 from 'h3';
2
- import { H3Event } from 'h3';
1
+ import { H3Event, EventHandlerRequest } from 'h3';
3
2
  import { q as SupportedFrameworkName, b as ServeHandlerOptions } from './handler-Mor_4K8F.js';
4
3
  import 'json-schema-to-ts';
5
4
  import 'zod';
6
5
  import '@novu/shared';
7
6
 
8
7
  declare const frameworkName: SupportedFrameworkName;
9
- declare const serve: (options: ServeHandlerOptions) => (event: H3Event<h3.EventHandlerRequest>) => Promise<Promise<void>>;
8
+ /**
9
+ * In h3, serve and register any declared workflows with Novu, making
10
+ * them available to be triggered by events.
11
+ *
12
+ * @example
13
+ * ```ts
14
+ * import { createApp, eventHandler, toNodeListener } from "h3";
15
+ * import { serve } from "@novu/framework/h3";
16
+ * import { createServer } from "node:http";
17
+ * import { myWorkflow } from "./src/novu/workflows";
18
+ *
19
+ * const app = createApp();
20
+ * app.use(
21
+ * "/api/novu",
22
+ * eventHandler(
23
+ * serve({
24
+ * workflows: [myWorkflow],
25
+ * })
26
+ * )
27
+ * );
28
+ *
29
+ * createServer(toNodeListener(app)).listen(process.env.PORT || 4000);
30
+ * ```
31
+ *
32
+ * @public
33
+ */
34
+ declare const serve: (options: ServeHandlerOptions) => (event: H3Event<EventHandlerRequest>) => Promise<Promise<void>>;
10
35
 
11
36
  export { frameworkName, serve };
package/dist/h3.js CHANGED
@@ -18,7 +18,7 @@ var N__default = /*#__PURE__*/_interopDefault(N);
18
18
  var Ne__default = /*#__PURE__*/_interopDefault(Ne);
19
19
  var Ae__default = /*#__PURE__*/_interopDefault(Ae);
20
20
 
21
- var D=(r=>(r.TRIGGER="trigger",r.EXECUTE="execute",r.PREVIEW="preview",r))(D||{}),k=(r=>(r.DISCOVER="discover",r.HEALTH_CHECK="health-check",r.CODE="code",r))(k||{});var h=(a=>(a.WORKFLOW_NOT_FOUND_ERROR="WorkflowNotFoundError",a.WORKFLOW_ALREADY_EXISTS_ERROR="WorkflowAlreadyExistsError",a.WORKFLOW_EXECUTION_FAILED_ERROR="WorkflowExecutionFailedError",a.EXECUTION_STATE_OUTPUT_INVALID_ERROR="ExecutionStateOutputInvalidError",a.EXECUTION_STATE_RESULT_INVALID_ERROR="ExecutionStateResultInvalidError",a.EXECUTION_PROVIDER_OUTPUT_INVALID_ERROR="ExecutionProviderOutputInvalidError",a.PROVIDER_NOT_FOUND_ERROR="ProviderNotFoundError",a.PROVIDER_EXECUTION_FAILED_ERROR="ProviderExecutionFailedError",a.STEP_NOT_FOUND_ERROR="StepNotFoundError",a.STEP_ALREADY_EXISTS_ERROR="StepAlreadyExistsError",a.STEP_EXECUTION_FAILED_ERROR="StepExecutionFailedError",a.EXECUTION_STATE_CORRUPT_ERROR="ExecutionStateCorruptError",a.EXECUTION_EVENT_PAYLOAD_INVALID_ERROR="ExecutionEventPayloadInvalidError",a.EXECUTION_EVENT_CONTROL_INVALID_ERROR="ExecutionEventControlInvalidError",a.EXECUTION_STATE_CONTROL_INVALID_ERROR="ExecutionStateControlInvalidError",a.METHOD_NOT_ALLOWED_ERROR="MethodNotAllowedError",a.INVALID_ACTION_ERROR="InvalidActionError",a.MISSING_SECRET_KEY_ERROR="MissingSecretKeyError",a.SIGNATURE_MISMATCH_ERROR="SignatureMismatchError",a.SIGNATURE_NOT_FOUND_ERROR="SignatureNotFoundError",a.SIGNATURE_INVALID_ERROR="SignatureInvalidError",a.SIGNATURE_EXPIRED_ERROR="SignatureExpiredError",a.SIGNING_KEY_NOT_FOUND_ERROR="SigningKeyNotFoundError",a.PLATFORM_ERROR="PlatformError",a.SIGNATURE_VERSION_INVALID_ERROR="SignatureVersionInvalidError",a.WORKFLOW_PAYLOAD_INVALID_ERROR="WorkflowPayloadInvalidError",a))(h||{});var U=(r=>(r.POST="POST",r.GET="GET",r.OPTIONS="OPTIONS",r))(U||{});var O=class extends Error{data},L=class extends O{statusCode=404},R=class extends O{statusCode=400},T=class extends O{statusCode=401},m=class extends O{statusCode=500},b=class extends O{statusCode=409};var V=class extends R{code="ExecutionStateCorruptError";constructor(e,t){super(`Workflow with id: \`${e}\` has a corrupt state. Step with id: \`${t}\` does not exist. Please provide the missing state.`),this.data={workflowId:e,stepId:t};}},x=class extends R{code="ExecutionEventPayloadInvalidError";constructor(e,t){super(`Workflow with id: \`${e}\` has invalid \`payload\`. Please provide the correct event payload.`),this.data=t;}},F=class extends R{code="ExecutionEventControlInvalidError";constructor(e,t){super(`Workflow with id: \`${e}\` has invalid \`controls\`. Please provide the correct event controls.`),this.data=t;}},W=class extends R{code="ExecutionStateControlInvalidError";constructor(e,t,r){super(`Workflow with id: \`${e}\` has an invalid state. Step with id: \`${t}\` has invalid \`controls\`. Please provide the correct step controls.`),this.data=r;}},$=class extends R{code="ExecutionStateOutputInvalidError";constructor(e,t,r){super(`Workflow with id: \`${e}\` has an invalid state. Step with id: \`${t}\` has invalid output. Please provide the correct step output.`),this.data=r;}},M=class extends R{code="ExecutionStateResultInvalidError";constructor(e,t,r){super(`Workflow with id: \`${e}\` has an invalid state. Step with id: \`${t}\` has invalid result. Please provide the correct step result.`),this.data=r;}},G=class extends R{code="ExecutionProviderOutputInvalidError";constructor(e,t,r,o){super(`Workflow with id: \`${e}\` has an invalid state. Step with id: \`${t}\` and provider with id: \`${r}\` has invalid output. Please provide the correct provider output.`),this.data=o;}};var j=class extends Error{statusCode;message;code;constructor(e,t,r){super(r),this.statusCode=e,this.code=t;}};var d={info:s=>N__default.default.blue(s),warning:s=>N__default.default.yellow(s),error:s=>N__default.default.red(s),success:s=>N__default.default.green(s),underline:s=>N__default.default.underline(s),bold:s=>N__default.default.bold(s)},p={SUCCESS:d.success("\u2714"),ERROR:d.error("\u2717"),WARNING:d.warning("\u26A0"),INFO:d.info("\u2139"),ARROW:d.bold("\u2192"),MOCK:d.info("\u25CB"),HYDRATED:d.bold(d.info("\u2192")),STEP:d.info("\u03C3"),ACTION:d.info("\u03B1"),DURATION:d.info("\u0394"),PROVIDER:d.info("\u2699"),OUTPUT:d.info("\u21E2"),INPUT:d.info("\u21E0"),WORKFLOW:d.info("\u03C9"),STATE:d.info("\u03C3"),EXECUTE:d.info("\u03B5"),PREVIEW:d.info("\u03C1")};var de=s=>Object.values(s).map(e=>`\`${e}\``).join(", "),K=s=>s.replaceAll(/(\w)(\w*)/g,(e,t,r)=>t.toUpperCase()+r.toLowerCase()).replaceAll(/[\s-]+/g,"");var ue=(s,e="https://api.novu.co")=>{let t=process.env.NOVU_API_URL||e;return {post:async(r,o)=>{let i=await fetch(t+"/v1"+r,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`ApiKey ${s}`},body:JSON.stringify(o)}),n=await i.json();if(i.ok)return n;throw new j(n.statusCode,n.error,n.message)},delete:async r=>(await fetch(t+"/v1"+r,{method:"DELETE",headers:{"Content-Type":"application/json",Authorization:`ApiKey ${s}`}})).json()}};var Y=class extends O{code="MethodNotAllowedError";statusCode=405;message=`Method not allowed. Please use one of ${de(U)}`},g=class extends R{code="InvalidActionError";constructor(e,t){super(`Invalid query string: \`action\`=\`${e}\`. Please use one of ${de(t)}`);}};var X=class extends m{code="PlatformError";message="Something went wrong. Please try again later."};var y=class extends b{constructor(e,t){super(`${K(e)} with id: \`${t}\` already exists. Please use a different id.`);}},w=class extends L{constructor(e,t){super(`${K(e)} with id: \`${t}\` does not exist. Please provide a valid id.`);}},A=class extends m{constructor(e,t){super(`Failed to execute ${K(e)} with id: \`${t}\`. Please try again later.`);}};var J=class extends w{code="ProviderNotFoundError";constructor(e){super("provider",e);}},B=class extends A{code="ProviderExecutionFailedError";constructor(e){super("workflow",e);}};var q=class extends T{code="SignatureMismatchError";constructor(){super("Signature does not match the expected signature. Please ensure the signature provided in the `novu-signature` header is correct and try again.");}},z=class extends T{code="SignatureNotFoundError";constructor(){super("Signature not found. Please provide a signature in the `novu-signature` header");}},Z=class extends T{code="SignatureInvalidError";constructor(){super("Signature is invalid. Please provide a valid signature in the `novu-signature` header");}},Q=class extends T{code="SignatureExpiredError";constructor(){super(`Signature expired. Please provide a signature with a timestamp no older than ${5} minutes in the \`novu-signature\` header`);}},H=class extends T{code="SigningKeyNotFoundError";constructor(){super("Signature key not found. Please provide a valid key in the Client constructor `config.secretKey`");}};var ee=class extends w{code="StepNotFoundError";constructor(e){super("step",e);}};var S=class extends w{code="WorkflowNotFoundError";constructor(e){super("workflow",e);}},te=class extends y{code="WorkflowAlreadyExistsError";constructor(e){super("workflow",e);}};var re=class{ajv;compiledSchemas;constructor(){this.ajv=new Ne__default.default({useDefaults:!0,removeAdditional:"all"}),Ae__default.default(this.ajv),this.compiledSchemas=new Map;}isSchema(e){return typeof e=="boolean"?!1:e.type==="object"||!!e.anyOf||!!e.oneOf}async validate(e,t){let r=this.compiledSchemas.get(t);return r||(r=this.ajv.compile(t),this.compiledSchemas.set(t,r)),r(e)?{success:!0,data:e}:{success:!1,errors:r.errors.map(i=>({path:i.instancePath,message:i.message}))}}transformToJsonSchema(e){return e}};var oe=class{isSchema(e){return e.safeParseAsync!==void 0}async validate(e,t){let r=t.safeParse(e);return r.success?{success:!0,data:r.data}:{success:!1,errors:r.error.errors.map(o=>({path:`/${o.path.join("/")}`,message:o.message}))}}transformToJsonSchema(e){try{return zodToJsonSchema.zodToJsonSchema(e)}catch(t){throw t?.message?.includes("Cannot find module")&&console.error("Tried to use a zod schema in @novu/framework without `zod-to-json-schema` installed. Please install it by running `npm install zod-to-json-schema`."),t}}};var Ee=[new oe,new re],he=async(s,e)=>{for(let t of Ee)if(t.isSchema(s))return t.validate(e,s);throw new Error("Invalid schema")},Oe=s=>{for(let e of Ee)if(e.isSchema(s))return e.transformToJsonSchema(s);throw new Error("Invalid schema")};var Te={name:"@novu/framework",version:"2.0.0-canary.0",description:"The Code-First Notifications Workflow SDK.",main:"./dist/index.js",types:"./dist/index.d.ts",publishConfig:{registry:"https://registry.npmjs.org",access:"public"},private:!1,repository:{type:"git",url:"git+https://github.com/novuhq/novu.git"},files:["dist","README.md"],scripts:{preinstall:"npx only-allow pnpm",test:"vitest","test:watch":"vitest --watch",lint:"eslint src --ext .ts","lint:fix":"eslint src --ext .ts --fix",format:"prettier --check --ignore-path .gitignore .","format:fix":"prettier --write --ignore-path .gitignore .",build:"tsup","build:watch":"tsup --watch","$comment:bump:prerelease":"This is a workaround to support `npm version prerelease` with lerna","bump:prerelease":"npm version prerelease --preid=alpha & PID=$!; (sleep 1 && kill -9 $PID) & wait $PID","release:alpha":"pnpm bump:prerelease || pnpm build && npm publish"},keywords:["novu","code-first","workflows","durable","sdk","notifications","email","sms","push","webhooks","next","nuxt","h3","express"],author:"Novu Team <engineering@novu.co>",license:"ISC",exports:{".":{require:"./dist/index.js",import:"./dist/index.js",types:"./dist/index.d.ts"},"./express":{require:"./dist/express.js",import:"./dist/express.js",types:"./dist/express.d.ts"},"./next":{require:"./dist/next.js",import:"./dist/next.js",types:"./dist/next.d.ts"},"./nuxt":{require:"./dist/nuxt.js",import:"./dist/nuxt.js",types:"./dist/nuxt.d.ts"},"./h3":{require:"./dist/h3.js",import:"./dist/h3.js",types:"./dist/h3.d.ts"},"./sveltekit":{require:"./dist/sveltekit.js",import:"./dist/sveltekit.js",types:"./dist/sveltekit.d.ts"},"./remix":{require:"./dist/remix.js",import:"./dist/remix.js",types:"./dist/remix.d.ts"}},peerDependencies:{"@sveltejs/kit":">=1.27.3","@vercel/node":">=2.15.9",express:">=4.19.2",h3:">=1.8.1",next:">=12.0.0",zod:">=3.0.0","zod-to-json-schema":">=3.0.0"},peerDependenciesMeta:{"@sveltejs/kit":{optional:!0},"@vercel/node":{optional:!0},express:{optional:!0},fastify:{optional:!0},h3:{optional:!0},next:{optional:!0},zod:{optional:!0},"zod-to-json-schema":{optional:!0}},devDependencies:{"@sveltejs/kit":"^1.27.3","@types/express":"^4.17.13","@types/json-schema":"^7.0.15","@types/node":"^20.11.20","@vercel/node":"^2.15.9",express:"^4.19.2",h3:"^1.11.1",next:"^13.5.4",prettier:"^3.2.5","ts-node":"^10.9.2",tsup:"^8.0.2",typescript:"^5.3.3",vitest:"^1.2.1",zod:"^3.23.0","zod-to-json-schema":"^3.23.0"},dependencies:{"@novu/shared":"workspace:*",ajv:"^8.12.0","ajv-formats":"^2.1.1","better-ajv-errors":"^1.2.0",chalk:"^4.1.2","cross-fetch":"^4.0.0","json-schema-faker":"^0.5.6","json-schema-to-ts":"^3.0.0",liquidjs:"^10.13.1",ora:"^5.4.1"}};var P=Te.version,se="2024-06-26";jsonSchemaFaker.JSONSchemaFaker.random.shuffle=function(){return ["[placeholder]"]};jsonSchemaFaker.JSONSchemaFaker.option({useDefaultValue:!0,alwaysFakeOptionals:!0});function ye(){return process.env.NODE_ENV==="development"}var ne=class{discoveredWorkflows=[];templateEngine=new liquidjs.Liquid;secretKey;version=P;strictAuthentication;constructor(e){let t=this.buildOptions(e);this.secretKey=t.secretKey,this.strictAuthentication=t.strictAuthentication;}buildOptions(e){let t={secretKey:void 0,strictAuthentication:!ye()};return t.secretKey=e?.secretKey||process.env.NOVU_SECRET_KEY||process.env.NOVU_API_KEY,e?.strictAuthentication!==void 0?t.strictAuthentication=e.strictAuthentication:process.env.NOVU_STRICT_AUTHENTICATION_ENABLED!==void 0&&(t.strictAuthentication=process.env.NOVU_STRICT_AUTHENTICATION_ENABLED==="true"),t}addWorkflows(e){for(let t of e){if(this.discoveredWorkflows.some(r=>r.workflowId===t.definition.workflowId))throw new te(t.definition.workflowId);this.discoveredWorkflows.push(t.definition);}}healthCheck(){let e=this.discoveredWorkflows.length,t=this.discoveredWorkflows.reduce((r,o)=>r+o.steps.length,0);return {status:"ok",sdkVersion:P,frameworkVersion:se,discovered:{workflows:e,steps:t}}}getWorkflow(e){let t=this.discoveredWorkflows.find(r=>r.workflowId===e);if(t)return t;throw new S(e)}getStep(e,t){let o=this.getWorkflow(e).steps.find(i=>i.stepId===t);if(o)return o;throw new ee(t)}getRegisteredWorkflows(){return this.discoveredWorkflows}discover(){return {workflows:this.getRegisteredWorkflows()}}mock(e){return jsonSchemaFaker.JSONSchemaFaker.generate(Oe(e))}async validate(e,t,r,o,i,n,l){let c=await he(t,e);if(c.success)return c.data;switch(r){case"event":this.throwInvalidEvent(o,i,c.errors);case"step":this.throwInvalidStep(n,o,i,c.errors);case"provider":this.throwInvalidProvider(n,l,o,i,c.errors);default:throw new Error(`Invalid component: '${r}'`)}}throwInvalidProvider(e,t,r,o,i){if(!e)throw new Error("stepId is required");if(!t)throw new Error("providerId is required");switch(r){case"output":throw new G(o,e,t,i);default:throw new Error(`Invalid payload type: '${r}'`)}}throwInvalidStep(e,t,r,o){if(!e)throw new Error("stepId is required");switch(t){case"output":throw new $(r,e,o);case"result":throw new M(r,e,o);case"controls":throw new W(r,e,o);default:throw new Error(`Invalid payload type: '${t}'`)}}throwInvalidEvent(e,t,r){switch(e){case"controls":throw new F(t,r);case"payload":throw new x(t,r);default:throw new Error(`Invalid payload type: '${e}'`)}}executeStepFactory(e,t){return async(r,o,i)=>{let n=this.getStep(e.workflowId,r),l=Se(e),c=await this.createStepControls(n,l),E=e.action==="preview";if(!E&&await this.shouldSkip(i?.skip,c))return t({options:{skip:!0}}),{};let u=this.previewStep.bind(this),I=this.executeStep.bind(this),C=await(E?u:I)(e,{...n,providers:n.providers.map(f=>{let v=i?.providers?.[f.type];if(!v)throw new J(f.type);return {...f,resolve:v}}),resolve:o});return r===e.stepId&&t(C),C.outputs}}async shouldSkip(e,t){return e?e(t):!1}async executeWorkflow(e){let o=`${{execute:"Executing",preview:"Previewing"}[e.action]} workflowId:`;console.log(`
21
+ var D=(r=>(r.TRIGGER="trigger",r.EXECUTE="execute",r.PREVIEW="preview",r))(D||{}),k=(r=>(r.DISCOVER="discover",r.HEALTH_CHECK="health-check",r.CODE="code",r))(k||{});var h=(a=>(a.WORKFLOW_NOT_FOUND_ERROR="WorkflowNotFoundError",a.WORKFLOW_ALREADY_EXISTS_ERROR="WorkflowAlreadyExistsError",a.WORKFLOW_EXECUTION_FAILED_ERROR="WorkflowExecutionFailedError",a.EXECUTION_STATE_OUTPUT_INVALID_ERROR="ExecutionStateOutputInvalidError",a.EXECUTION_STATE_RESULT_INVALID_ERROR="ExecutionStateResultInvalidError",a.EXECUTION_PROVIDER_OUTPUT_INVALID_ERROR="ExecutionProviderOutputInvalidError",a.PROVIDER_NOT_FOUND_ERROR="ProviderNotFoundError",a.PROVIDER_EXECUTION_FAILED_ERROR="ProviderExecutionFailedError",a.STEP_NOT_FOUND_ERROR="StepNotFoundError",a.STEP_ALREADY_EXISTS_ERROR="StepAlreadyExistsError",a.STEP_EXECUTION_FAILED_ERROR="StepExecutionFailedError",a.EXECUTION_STATE_CORRUPT_ERROR="ExecutionStateCorruptError",a.EXECUTION_EVENT_PAYLOAD_INVALID_ERROR="ExecutionEventPayloadInvalidError",a.EXECUTION_EVENT_CONTROL_INVALID_ERROR="ExecutionEventControlInvalidError",a.EXECUTION_STATE_CONTROL_INVALID_ERROR="ExecutionStateControlInvalidError",a.METHOD_NOT_ALLOWED_ERROR="MethodNotAllowedError",a.INVALID_ACTION_ERROR="InvalidActionError",a.MISSING_SECRET_KEY_ERROR="MissingSecretKeyError",a.SIGNATURE_MISMATCH_ERROR="SignatureMismatchError",a.SIGNATURE_NOT_FOUND_ERROR="SignatureNotFoundError",a.SIGNATURE_INVALID_ERROR="SignatureInvalidError",a.SIGNATURE_EXPIRED_ERROR="SignatureExpiredError",a.SIGNING_KEY_NOT_FOUND_ERROR="SigningKeyNotFoundError",a.PLATFORM_ERROR="PlatformError",a.SIGNATURE_VERSION_INVALID_ERROR="SignatureVersionInvalidError",a.WORKFLOW_PAYLOAD_INVALID_ERROR="WorkflowPayloadInvalidError",a))(h||{});var U=(r=>(r.POST="POST",r.GET="GET",r.OPTIONS="OPTIONS",r))(U||{});var O=class extends Error{data},L=class extends O{statusCode=404},R=class extends O{statusCode=400},T=class extends O{statusCode=401},m=class extends O{statusCode=500},b=class extends O{statusCode=409};var V=class extends R{code="ExecutionStateCorruptError";constructor(e,t){super(`Workflow with id: \`${e}\` has a corrupt state. Step with id: \`${t}\` does not exist. Please provide the missing state.`),this.data={workflowId:e,stepId:t};}},x=class extends R{code="ExecutionEventPayloadInvalidError";constructor(e,t){super(`Workflow with id: \`${e}\` has invalid \`payload\`. Please provide the correct event payload.`),this.data=t;}},F=class extends R{code="ExecutionEventControlInvalidError";constructor(e,t){super(`Workflow with id: \`${e}\` has invalid \`controls\`. Please provide the correct event controls.`),this.data=t;}},W=class extends R{code="ExecutionStateControlInvalidError";constructor(e,t,r){super(`Workflow with id: \`${e}\` has an invalid state. Step with id: \`${t}\` has invalid \`controls\`. Please provide the correct step controls.`),this.data=r;}},$=class extends R{code="ExecutionStateOutputInvalidError";constructor(e,t,r){super(`Workflow with id: \`${e}\` has an invalid state. Step with id: \`${t}\` has invalid output. Please provide the correct step output.`),this.data=r;}},M=class extends R{code="ExecutionStateResultInvalidError";constructor(e,t,r){super(`Workflow with id: \`${e}\` has an invalid state. Step with id: \`${t}\` has invalid result. Please provide the correct step result.`),this.data=r;}},G=class extends R{code="ExecutionProviderOutputInvalidError";constructor(e,t,r,o){super(`Workflow with id: \`${e}\` has an invalid state. Step with id: \`${t}\` and provider with id: \`${r}\` has invalid output. Please provide the correct provider output.`),this.data=o;}};var j=class extends Error{statusCode;message;code;constructor(e,t,r){super(r),this.statusCode=e,this.code=t;}};var d={info:s=>N__default.default.blue(s),warning:s=>N__default.default.yellow(s),error:s=>N__default.default.red(s),success:s=>N__default.default.green(s),underline:s=>N__default.default.underline(s),bold:s=>N__default.default.bold(s)},p={SUCCESS:d.success("\u2714"),ERROR:d.error("\u2717"),WARNING:d.warning("\u26A0"),INFO:d.info("\u2139"),ARROW:d.bold("\u2192"),MOCK:d.info("\u25CB"),HYDRATED:d.bold(d.info("\u2192")),STEP:d.info("\u03C3"),ACTION:d.info("\u03B1"),DURATION:d.info("\u0394"),PROVIDER:d.info("\u2699"),OUTPUT:d.info("\u21E2"),INPUT:d.info("\u21E0"),WORKFLOW:d.info("\u03C9"),STATE:d.info("\u03C3"),EXECUTE:d.info("\u03B5"),PREVIEW:d.info("\u03C1")};var de=s=>Object.values(s).map(e=>`\`${e}\``).join(", "),K=s=>s.replaceAll(/(\w)(\w*)/g,(e,t,r)=>t.toUpperCase()+r.toLowerCase()).replaceAll(/[\s-]+/g,"");var ue=(s,e="https://api.novu.co")=>{let t=process.env.NOVU_API_URL||e;return {post:async(r,o)=>{let i=await fetch(t+"/v1"+r,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`ApiKey ${s}`},body:JSON.stringify(o)}),n=await i.json();if(i.ok)return n;throw new j(n.statusCode,n.error,n.message)},delete:async r=>(await fetch(t+"/v1"+r,{method:"DELETE",headers:{"Content-Type":"application/json",Authorization:`ApiKey ${s}`}})).json()}};var Y=class extends O{code="MethodNotAllowedError";statusCode=405;message=`Method not allowed. Please use one of ${de(U)}`},g=class extends R{code="InvalidActionError";constructor(e,t){super(`Invalid query string: \`action\`=\`${e}\`. Please use one of ${de(t)}`);}};var X=class extends m{code="PlatformError";message="Something went wrong. Please try again later."};var y=class extends b{constructor(e,t){super(`${K(e)} with id: \`${t}\` already exists. Please use a different id.`);}},w=class extends L{constructor(e,t){super(`${K(e)} with id: \`${t}\` does not exist. Please provide a valid id.`);}},A=class extends m{constructor(e,t){super(`Failed to execute ${K(e)} with id: \`${t}\`. Please try again later.`);}};var J=class extends w{code="ProviderNotFoundError";constructor(e){super("provider",e);}},B=class extends A{code="ProviderExecutionFailedError";constructor(e){super("workflow",e);}};var q=class extends T{code="SignatureMismatchError";constructor(){super("Signature does not match the expected signature. Please ensure the signature provided in the `novu-signature` header is correct and try again.");}},z=class extends T{code="SignatureNotFoundError";constructor(){super("Signature not found. Please provide a signature in the `novu-signature` header");}},Z=class extends T{code="SignatureInvalidError";constructor(){super("Signature is invalid. Please provide a valid signature in the `novu-signature` header");}},Q=class extends T{code="SignatureExpiredError";constructor(){super(`Signature expired. Please provide a signature with a timestamp no older than ${5} minutes in the \`novu-signature\` header`);}},H=class extends T{code="SigningKeyNotFoundError";constructor(){super("Signature key not found. Please provide a valid key in the Client constructor `config.secretKey`");}};var ee=class extends w{code="StepNotFoundError";constructor(e){super("step",e);}};var S=class extends w{code="WorkflowNotFoundError";constructor(e){super("workflow",e);}},te=class extends y{code="WorkflowAlreadyExistsError";constructor(e){super("workflow",e);}};var re=class{ajv;compiledSchemas;constructor(){this.ajv=new Ne__default.default({useDefaults:!0,removeAdditional:"all"}),Ae__default.default(this.ajv),this.compiledSchemas=new Map;}isSchema(e){return typeof e=="boolean"?!1:e.type==="object"||!!e.anyOf||!!e.oneOf}async validate(e,t){let r=this.compiledSchemas.get(t);return r||(r=this.ajv.compile(t),this.compiledSchemas.set(t,r)),r(e)?{success:!0,data:e}:{success:!1,errors:r.errors.map(i=>({path:i.instancePath,message:i.message}))}}transformToJsonSchema(e){return e}};var oe=class{isSchema(e){return e.safeParseAsync!==void 0}async validate(e,t){let r=t.safeParse(e);return r.success?{success:!0,data:r.data}:{success:!1,errors:r.error.errors.map(o=>({path:`/${o.path.join("/")}`,message:o.message}))}}transformToJsonSchema(e){try{return zodToJsonSchema.zodToJsonSchema(e)}catch(t){throw t?.message?.includes("Cannot find module")&&console.error("Tried to use a zod schema in @novu/framework without `zod-to-json-schema` installed. Please install it by running `npm install zod-to-json-schema`."),t}}};var Ee=[new oe,new re],he=async(s,e)=>{for(let t of Ee)if(t.isSchema(s))return t.validate(e,s);throw new Error("Invalid schema")},Oe=s=>{for(let e of Ee)if(e.isSchema(s))return e.transformToJsonSchema(s);throw new Error("Invalid schema")};var Te={name:"@novu/framework",version:"2.0.0-canary.2",description:"The Code-First Notifications Workflow SDK.",main:"./dist/index.js",types:"./dist/index.d.ts",publishConfig:{registry:"https://registry.npmjs.org",access:"public"},private:!1,repository:{type:"git",url:"git+https://github.com/novuhq/novu.git"},files:["dist","README.md"],scripts:{preinstall:"npx only-allow pnpm",test:"vitest","test:watch":"vitest --watch",lint:"eslint src --ext .ts","lint:fix":"eslint src --ext .ts --fix",format:"prettier --check --ignore-path .gitignore .","format:fix":"prettier --write --ignore-path .gitignore .",build:"tsup","build:watch":"tsup --watch","$comment:bump:prerelease":"This is a workaround to support `npm version prerelease` with lerna","bump:prerelease":"npm version prerelease --preid=alpha & PID=$!; (sleep 1 && kill -9 $PID) & wait $PID","release:alpha":"pnpm bump:prerelease || pnpm build && npm publish"},keywords:["novu","code-first","workflows","durable","sdk","notifications","email","sms","push","webhooks","next","nuxt","h3","express"],author:"Novu Team <engineering@novu.co>",license:"ISC",exports:{".":{require:"./dist/index.js",import:"./dist/index.js",types:"./dist/index.d.ts"},"./express":{require:"./dist/express.js",import:"./dist/express.js",types:"./dist/express.d.ts"},"./next":{require:"./dist/next.js",import:"./dist/next.js",types:"./dist/next.d.ts"},"./nuxt":{require:"./dist/nuxt.js",import:"./dist/nuxt.js",types:"./dist/nuxt.d.ts"},"./h3":{require:"./dist/h3.js",import:"./dist/h3.js",types:"./dist/h3.d.ts"},"./sveltekit":{require:"./dist/sveltekit.js",import:"./dist/sveltekit.js",types:"./dist/sveltekit.d.ts"},"./remix":{require:"./dist/remix.js",import:"./dist/remix.js",types:"./dist/remix.d.ts"}},peerDependencies:{"@sveltejs/kit":">=1.27.3","@vercel/node":">=2.15.9",express:">=4.19.2",h3:">=1.8.1",next:">=12.0.0",zod:">=3.0.0","zod-to-json-schema":">=3.0.0"},peerDependenciesMeta:{"@sveltejs/kit":{optional:!0},"@vercel/node":{optional:!0},express:{optional:!0},fastify:{optional:!0},h3:{optional:!0},next:{optional:!0},zod:{optional:!0},"zod-to-json-schema":{optional:!0}},devDependencies:{"@sveltejs/kit":"^1.27.3","@types/express":"^4.17.13","@types/json-schema":"^7.0.15","@types/node":"^20.11.20","@vercel/node":"^2.15.9",express:"^4.19.2",h3:"^1.11.1",next:"^13.5.4",prettier:"^3.2.5","ts-node":"^10.9.2",tsup:"^8.0.2",typescript:"^5.3.3",vitest:"^1.2.1",zod:"^3.23.0","zod-to-json-schema":"^3.23.0"},dependencies:{"@novu/shared":"^2.0.0-canary.0",ajv:"^8.12.0","ajv-formats":"^2.1.1","better-ajv-errors":"^1.2.0",chalk:"^4.1.2","cross-fetch":"^4.0.0","json-schema-faker":"^0.5.6","json-schema-to-ts":"^3.0.0",liquidjs:"^10.13.1",ora:"^5.4.1"}};var P=Te.version,se="2024-06-26";jsonSchemaFaker.JSONSchemaFaker.random.shuffle=function(){return ["[placeholder]"]};jsonSchemaFaker.JSONSchemaFaker.option({useDefaultValue:!0,alwaysFakeOptionals:!0});function ye(){return process.env.NODE_ENV==="development"}var ne=class{discoveredWorkflows=[];templateEngine=new liquidjs.Liquid;secretKey;version=P;strictAuthentication;constructor(e){let t=this.buildOptions(e);this.secretKey=t.secretKey,this.strictAuthentication=t.strictAuthentication;}buildOptions(e){let t={secretKey:void 0,strictAuthentication:!ye()};return t.secretKey=e?.secretKey||process.env.NOVU_SECRET_KEY||process.env.NOVU_API_KEY,e?.strictAuthentication!==void 0?t.strictAuthentication=e.strictAuthentication:process.env.NOVU_STRICT_AUTHENTICATION_ENABLED!==void 0&&(t.strictAuthentication=process.env.NOVU_STRICT_AUTHENTICATION_ENABLED==="true"),t}addWorkflows(e){for(let t of e){if(this.discoveredWorkflows.some(r=>r.workflowId===t.definition.workflowId))throw new te(t.definition.workflowId);this.discoveredWorkflows.push(t.definition);}}healthCheck(){let e=this.discoveredWorkflows.length,t=this.discoveredWorkflows.reduce((r,o)=>r+o.steps.length,0);return {status:"ok",sdkVersion:P,frameworkVersion:se,discovered:{workflows:e,steps:t}}}getWorkflow(e){let t=this.discoveredWorkflows.find(r=>r.workflowId===e);if(t)return t;throw new S(e)}getStep(e,t){let o=this.getWorkflow(e).steps.find(i=>i.stepId===t);if(o)return o;throw new ee(t)}getRegisteredWorkflows(){return this.discoveredWorkflows}discover(){return {workflows:this.getRegisteredWorkflows()}}mock(e){return jsonSchemaFaker.JSONSchemaFaker.generate(Oe(e))}async validate(e,t,r,o,i,n,l){let c=await he(t,e);if(c.success)return c.data;switch(r){case"event":this.throwInvalidEvent(o,i,c.errors);case"step":this.throwInvalidStep(n,o,i,c.errors);case"provider":this.throwInvalidProvider(n,l,o,i,c.errors);default:throw new Error(`Invalid component: '${r}'`)}}throwInvalidProvider(e,t,r,o,i){if(!e)throw new Error("stepId is required");if(!t)throw new Error("providerId is required");switch(r){case"output":throw new G(o,e,t,i);default:throw new Error(`Invalid payload type: '${r}'`)}}throwInvalidStep(e,t,r,o){if(!e)throw new Error("stepId is required");switch(t){case"output":throw new $(r,e,o);case"result":throw new M(r,e,o);case"controls":throw new W(r,e,o);default:throw new Error(`Invalid payload type: '${t}'`)}}throwInvalidEvent(e,t,r){switch(e){case"controls":throw new F(t,r);case"payload":throw new x(t,r);default:throw new Error(`Invalid payload type: '${e}'`)}}executeStepFactory(e,t){return async(r,o,i)=>{let n=this.getStep(e.workflowId,r),l=Se(e),c=await this.createStepControls(n,l),E=e.action==="preview";if(!E&&await this.shouldSkip(i?.skip,c))return t({options:{skip:!0}}),{};let u=this.previewStep.bind(this),I=this.executeStep.bind(this),C=await(E?u:I)(e,{...n,providers:n.providers.map(f=>{let v=i?.providers?.[f.type];if(!v)throw new J(f.type);return {...f,resolve:v}}),resolve:o});return r===e.stepId&&t(C),C.outputs}}async shouldSkip(e,t){return e?e(t):!1}async executeWorkflow(e){let o=`${{execute:"Executing",preview:"Previewing"}[e.action]} workflowId:`;console.log(`
22
22
  ${d.bold(d.underline(o))} '${e.workflowId}'`);let i=this.getWorkflow(e.workflowId),n=process.hrtime(),l={outputs:{},providers:{},options:{}},c,E=new Promise(_=>{c=_;}),u=_=>{c(),l=_;},I;try{if(e.action==="execute"&&!e.payload&&!e.data)throw new x(e.workflowId,{message:"Event `payload` is required"});let _=await this.createExecutionPayload(e,i);await Promise.race([E,i.execute({payload:_,environment:{},inputs:{},controls:{},subscriber:e.subscriber,step:{email:this.executeStepFactory(e,u),sms:this.executeStepFactory(e,u),inApp:this.executeStepFactory(e,u),digest:this.executeStepFactory(e,u),delay:this.executeStepFactory(e,u),push:this.executeStepFactory(e,u),chat:this.executeStepFactory(e,u),custom:this.executeStepFactory(e,u)}})]);}catch(_){I=_;}let ce=process.hrtime(n),C=ce[0],f=ce[1],v=C*1e3+f/1e6,Ie=I?p.ERROR:p.SUCCESS,_e=e.action==="execute"?"Executed":e.action==="preview"?"Previewed":"Invalid action";if(console.log(`${Ie} ${_e} workflowId: \`${e.workflowId}\``),this.prettyPrintExecute(e,v,I),I)throw I;return {outputs:l.outputs,providers:l.providers,options:l.options,metadata:{status:"success",error:!1,duration:v}}}async createExecutionPayload(e,t){let r=e.payload||e.data;if(e.action==="preview"){let i=this.mock(t.payload.schema);r=Object.assign(i,r);}return await this.validate(r,t.payload.unknownSchema,"event","payload",e.workflowId)}prettyPrintExecute(e,t,r){let o=r?p.ERROR:p.SUCCESS,i=e.action==="execute"?"Executed":e.action==="preview"?"Previewed":"Invalid action",n=r?"Failed to execute":i,l=r?d.error:d.success,c=`${o} ${n} workflowId: '${e.workflowId}`;console.log(`
23
23
  ${d.bold(l(c))}'`),console.log(` \u251C ${p.STEP} stepId: '${e.stepId}'`),console.log(` \u251C ${p.ACTION} action: '${e.action}'`),console.log(` \u2514 ${p.DURATION} duration: '${t.toFixed(2)}ms'
24
24
  `);}async executeProviders(e,t,r){return t.providers.reduce(async(o,i)=>{let n=await o,l=this.previewProvider.bind(this),c=this.executeProvider.bind(this),u=await(e.action==="preview"?l:c)(e,t,i,r);return {...n,[i.type]:u}},Promise.resolve({}))}previewProvider(e,t,r,o){return console.log(` ${p.MOCK} Mocked provider: \`${r.type}\``),this.mock(r.outputs.schema)}async executeProvider(e,t,r,o){let i=ie__default.default({indent:2}).start(`Executing provider: \`${r.type}\``);try{if(e.stepId===t.stepId){let n=await this.createStepControls(t,e),l=await r.resolve({controls:n,outputs:o}),c=await this.validate(l,r.outputs.unknownSchema,"step","output",e.workflowId,t.stepId,r.type);return i.succeed(`Executed provider: \`${r.type}\``),c}else i.stopAndPersist({symbol:p.HYDRATED,text:`Hydrated provider: \`${r.type}\``});}catch(n){throw i.stopAndPersist({symbol:p.ERROR,text:`Failed to execute provider: \`${r.type}\``}),new B(`Failed to execute provider: '${r.type}'.
package/dist/index.js CHANGED
@@ -17,7 +17,7 @@ var P__default = /*#__PURE__*/_interopDefault(P);
17
17
  var Ze__default = /*#__PURE__*/_interopDefault(Ze);
18
18
  var He__default = /*#__PURE__*/_interopDefault(He);
19
19
 
20
- var V=(i=>(i.TRIGGER="trigger",i.EXECUTE="execute",i.PREVIEW="preview",i))(V||{}),F=(i=>(i.DISCOVER="discover",i.HEALTH_CHECK="health-check",i.CODE="code",i))(F||{});var Je=(t=>(t.SYNC="/v1/bridge/sync",t.DIFF="/v1/bridge/diff",t))(Je||{}),ve=5,Oe=1500;var w=(h=>(h.WORKFLOW_NOT_FOUND_ERROR="WorkflowNotFoundError",h.WORKFLOW_ALREADY_EXISTS_ERROR="WorkflowAlreadyExistsError",h.WORKFLOW_EXECUTION_FAILED_ERROR="WorkflowExecutionFailedError",h.EXECUTION_STATE_OUTPUT_INVALID_ERROR="ExecutionStateOutputInvalidError",h.EXECUTION_STATE_RESULT_INVALID_ERROR="ExecutionStateResultInvalidError",h.EXECUTION_PROVIDER_OUTPUT_INVALID_ERROR="ExecutionProviderOutputInvalidError",h.PROVIDER_NOT_FOUND_ERROR="ProviderNotFoundError",h.PROVIDER_EXECUTION_FAILED_ERROR="ProviderExecutionFailedError",h.STEP_NOT_FOUND_ERROR="StepNotFoundError",h.STEP_ALREADY_EXISTS_ERROR="StepAlreadyExistsError",h.STEP_EXECUTION_FAILED_ERROR="StepExecutionFailedError",h.EXECUTION_STATE_CORRUPT_ERROR="ExecutionStateCorruptError",h.EXECUTION_EVENT_PAYLOAD_INVALID_ERROR="ExecutionEventPayloadInvalidError",h.EXECUTION_EVENT_CONTROL_INVALID_ERROR="ExecutionEventControlInvalidError",h.EXECUTION_STATE_CONTROL_INVALID_ERROR="ExecutionStateControlInvalidError",h.METHOD_NOT_ALLOWED_ERROR="MethodNotAllowedError",h.INVALID_ACTION_ERROR="InvalidActionError",h.MISSING_SECRET_KEY_ERROR="MissingSecretKeyError",h.SIGNATURE_MISMATCH_ERROR="SignatureMismatchError",h.SIGNATURE_NOT_FOUND_ERROR="SignatureNotFoundError",h.SIGNATURE_INVALID_ERROR="SignatureInvalidError",h.SIGNATURE_EXPIRED_ERROR="SignatureExpiredError",h.SIGNING_KEY_NOT_FOUND_ERROR="SigningKeyNotFoundError",h.PLATFORM_ERROR="PlatformError",h.SIGNATURE_VERSION_INVALID_ERROR="SignatureVersionInvalidError",h.WORKFLOW_PAYLOAD_INVALID_ERROR="WorkflowPayloadInvalidError",h))(w||{});var xe=(m=>(m.NOVU_SIGNATURE="novu-signature",m.NOVU_ANONYMOUS="novu-anonymous",m.NOVU_SIGNATURE_DEPRECATED="x-novu-signature",m.NOVU_ANONYMOUS_DEPRECATED="x-novu-anonymous",m.NOVU_FRAMEWORK_SDK="novu-framework-sdk",m.NOVU_FRAMEWORK_API="novu-framework-api",m.NOVU_FRAMEWORK_VERSION="novu-framework-version",m.USER_AGENT="user-agent",m.CONTENT_TYPE="content-type",m.ACCESS_CONTROL_ALLOW_ORIGIN="access-control-allow-origin",m.ACCESS_CONTROL_ALLOW_METHODS="access-control-allow-methods",m.ACCESS_CONTROL_ALLOW_HEADERS="access-control-allow-headers",m.ACCESS_CONTROL_MAX_AGE="access-control-max-age",m))(xe||{});var L=(i=>(i.POST="POST",i.GET="GET",i.OPTIONS="OPTIONS",i))(L||{});var Pe=(s=>(s.WORKFLOW_ID="workflowId",s.STEP_ID="stepId",s.ACTION="action",s.SOURCE="source",s))(Pe||{});var q=(o=>(o[o.CONTINUE=100]="CONTINUE",o[o.SWITCHING_PROTOCOLS=101]="SWITCHING_PROTOCOLS",o[o.PROCESSING=102]="PROCESSING",o[o.EARLYHINTS=103]="EARLYHINTS",o[o.OK=200]="OK",o[o.CREATED=201]="CREATED",o[o.ACCEPTED=202]="ACCEPTED",o[o.NON_AUTHORITATIVE_INFORMATION=203]="NON_AUTHORITATIVE_INFORMATION",o[o.NO_CONTENT=204]="NO_CONTENT",o[o.RESET_CONTENT=205]="RESET_CONTENT",o[o.PARTIAL_CONTENT=206]="PARTIAL_CONTENT",o[o.AMBIGUOUS=300]="AMBIGUOUS",o[o.MOVED_PERMANENTLY=301]="MOVED_PERMANENTLY",o[o.FOUND=302]="FOUND",o[o.SEE_OTHER=303]="SEE_OTHER",o[o.NOT_MODIFIED=304]="NOT_MODIFIED",o[o.TEMPORARY_REDIRECT=307]="TEMPORARY_REDIRECT",o[o.PERMANENT_REDIRECT=308]="PERMANENT_REDIRECT",o[o.BAD_REQUEST=400]="BAD_REQUEST",o[o.UNAUTHORIZED=401]="UNAUTHORIZED",o[o.PAYMENT_REQUIRED=402]="PAYMENT_REQUIRED",o[o.FORBIDDEN=403]="FORBIDDEN",o[o.NOT_FOUND=404]="NOT_FOUND",o[o.METHOD_NOT_ALLOWED=405]="METHOD_NOT_ALLOWED",o[o.NOT_ACCEPTABLE=406]="NOT_ACCEPTABLE",o[o.PROXY_AUTHENTICATION_REQUIRED=407]="PROXY_AUTHENTICATION_REQUIRED",o[o.REQUEST_TIMEOUT=408]="REQUEST_TIMEOUT",o[o.CONFLICT=409]="CONFLICT",o[o.GONE=410]="GONE",o[o.LENGTH_REQUIRED=411]="LENGTH_REQUIRED",o[o.PRECONDITION_FAILED=412]="PRECONDITION_FAILED",o[o.PAYLOAD_TOO_LARGE=413]="PAYLOAD_TOO_LARGE",o[o.URI_TOO_LONG=414]="URI_TOO_LONG",o[o.UNSUPPORTED_MEDIA_TYPE=415]="UNSUPPORTED_MEDIA_TYPE",o[o.REQUESTED_RANGE_NOT_SATISFIABLE=416]="REQUESTED_RANGE_NOT_SATISFIABLE",o[o.EXPECTATION_FAILED=417]="EXPECTATION_FAILED",o[o.I_AM_A_TEAPOT=418]="I_AM_A_TEAPOT",o[o.MISDIRECTED=421]="MISDIRECTED",o[o.UNPROCESSABLE_ENTITY=422]="UNPROCESSABLE_ENTITY",o[o.FAILED_DEPENDENCY=424]="FAILED_DEPENDENCY",o[o.PRECONDITION_REQUIRED=428]="PRECONDITION_REQUIRED",o[o.TOO_MANY_REQUESTS=429]="TOO_MANY_REQUESTS",o[o.INTERNAL_SERVER_ERROR=500]="INTERNAL_SERVER_ERROR",o[o.NOT_IMPLEMENTED=501]="NOT_IMPLEMENTED",o[o.BAD_GATEWAY=502]="BAD_GATEWAY",o[o.SERVICE_UNAVAILABLE=503]="SERVICE_UNAVAILABLE",o[o.GATEWAY_TIMEOUT=504]="GATEWAY_TIMEOUT",o[o.HTTP_VERSION_NOT_SUPPORTED=505]="HTTP_VERSION_NOT_SUPPORTED",o))(q||{}),Vt=[500];var W=(i=>(i.WORKFLOW="workflow",i.PROVIDER="provider",i.STEP="step",i))(W||{});var B=(a=>(a.EMAIL="email",a.SMS="sms",a.PUSH="push",a.CHAT="chat",a.IN_APP="in_app",a))(B||{}),Qe=(i=>(i.DIGEST="digest",i.DELAY="delay",i.CUSTOM="custom",i))(Qe||{});var k=class extends Error{data},G=class extends k{statusCode=404},b=class extends k{statusCode=400},R=class extends k{statusCode=401},O=class extends k{statusCode=500},K=class extends k{statusCode=409};var X=class extends b{code="ExecutionStateCorruptError";constructor(e,t){super(`Workflow with id: \`${e}\` has a corrupt state. Step with id: \`${t}\` does not exist. Please provide the missing state.`),this.data={workflowId:e,stepId:t};}},M=class extends b{code="ExecutionEventPayloadInvalidError";constructor(e,t){super(`Workflow with id: \`${e}\` has invalid \`payload\`. Please provide the correct event payload.`),this.data=t;}},z=class extends b{code="ExecutionEventControlInvalidError";constructor(e,t){super(`Workflow with id: \`${e}\` has invalid \`controls\`. Please provide the correct event controls.`),this.data=t;}},J=class extends b{code="ExecutionStateControlInvalidError";constructor(e,t,i){super(`Workflow with id: \`${e}\` has an invalid state. Step with id: \`${t}\` has invalid \`controls\`. Please provide the correct step controls.`),this.data=i;}},Q=class extends b{code="ExecutionStateOutputInvalidError";constructor(e,t,i){super(`Workflow with id: \`${e}\` has an invalid state. Step with id: \`${t}\` has invalid output. Please provide the correct step output.`),this.data=i;}},Z=class extends b{code="ExecutionStateResultInvalidError";constructor(e,t,i){super(`Workflow with id: \`${e}\` has an invalid state. Step with id: \`${t}\` has invalid result. Please provide the correct step result.`),this.data=i;}},H=class extends b{code="ExecutionProviderOutputInvalidError";constructor(e,t,i,s){super(`Workflow with id: \`${e}\` has an invalid state. Step with id: \`${t}\` and provider with id: \`${i}\` has invalid output. Please provide the correct provider output.`),this.data=s;}},ee=class extends b{code="WorkflowPayloadInvalidError";constructor(e,t){super(`Workflow with id: \`${e}\` has invalid \`payload\`. Please provide the correct payload.`),this.data=t;}},te=class extends Error{statusCode;message;code;constructor(e,t,i){super(i),this.statusCode=e,this.code=t;}};var Ie=async()=>{if(process.env.NOVU_BRIDGE_ORIGIN)return `${process.env.NOVU_BRIDGE_ORIGIN}/api/novu`;if(process.env.NEXT_PUBLIC_VERCEL_ENV==="preview"&&process.env.NEXT_PUBLIC_VERCEL_URL)return `https://${process.env.NEXT_PUBLIC_VERCEL_URL}/api/novu`;try{if(process.env.NODE_ENV==="development"){let e=await(await fetch("http://localhost:2022/.well-known/novu")).json();return `${e.tunnelOrigin}${e.route}`}}catch(n){console.error(n);}return ""};var d={info:n=>P__default.default.blue(n),warning:n=>P__default.default.yellow(n),error:n=>P__default.default.red(n),success:n=>P__default.default.green(n),underline:n=>P__default.default.underline(n),bold:n=>P__default.default.bold(n)},f={SUCCESS:d.success("\u2714"),ERROR:d.error("\u2717"),WARNING:d.warning("\u26A0"),INFO:d.info("\u2139"),ARROW:d.bold("\u2192"),MOCK:d.info("\u25CB"),HYDRATED:d.bold(d.info("\u2192")),STEP:d.info("\u03C3"),ACTION:d.info("\u03B1"),DURATION:d.info("\u0394"),PROVIDER:d.info("\u2699"),OUTPUT:d.info("\u21E2"),INPUT:d.info("\u21E0"),WORKFLOW:d.info("\u03C9"),STATE:d.info("\u03C3"),EXECUTE:d.info("\u03B5"),PREVIEW:d.info("\u03C1")};var ke=n=>Object.values(n).map(e=>`\`${e}\``).join(", "),ie=n=>n.replaceAll(/(\w)(\w*)/g,(e,t,i)=>t.toUpperCase()+i.toLowerCase()).replaceAll(/[\s-]+/g,"");var oe=(n,e="https://api.novu.co")=>{let t=process.env.NOVU_API_URL||e;return {post:async(i,s)=>{let a=await fetch(t+"/v1"+i,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`ApiKey ${n}`},body:JSON.stringify(s)}),l=await a.json();if(a.ok)return l;throw new te(l.statusCode,l.error,l.message)},delete:async i=>(await fetch(t+"/v1"+i,{method:"DELETE",headers:{"Content-Type":"application/json",Authorization:`ApiKey ${n}`}})).json()}};var ne=class extends k{code="MethodNotAllowedError";statusCode=405;message=`Method not allowed. Please use one of ${ke(L)}`},C=class extends b{code="InvalidActionError";constructor(e,t){super(`Invalid query string: \`action\`=\`${e}\`. Please use one of ${ke(t)}`);}},se=class extends b{code="MissingSecretKeyError";constructor(){super("Missing secret key. Set the `NOVU_SECRET_KEY` environment variable or pass `secretKey` to the client options.");}};var re=class extends O{code="PlatformError";message="Something went wrong. Please try again later."};var I=class extends K{constructor(e,t){super(`${ie(e)} with id: \`${t}\` already exists. Please use a different id.`);}},S=class extends G{constructor(e,t){super(`${ie(e)} with id: \`${t}\` does not exist. Please provide a valid id.`);}},D=class extends O{constructor(e,t){super(`Failed to execute ${ie(e)} with id: \`${t}\`. Please try again later.`);}};var ae=class extends S{code="ProviderNotFoundError";constructor(e){super("provider",e);}},le=class extends D{code="ProviderExecutionFailedError";constructor(e){super("workflow",e);}};var ce=class extends R{code="SignatureMismatchError";constructor(){super("Signature does not match the expected signature. Please ensure the signature provided in the `novu-signature` header is correct and try again.");}},pe=class extends R{code="SignatureNotFoundError";constructor(){super("Signature not found. Please provide a signature in the `novu-signature` header");}},de=class extends R{code="SignatureInvalidError";constructor(){super("Signature is invalid. Please provide a valid signature in the `novu-signature` header");}},he=class extends R{code="SignatureExpiredError";constructor(){super(`Signature expired. Please provide a signature with a timestamp no older than ${5} minutes in the \`novu-signature\` header`);}},ue=class extends R{code="SigningKeyNotFoundError";constructor(){super("Signature key not found. Please provide a valid key in the Client constructor `config.secretKey`");}};var me=class extends S{code="StepNotFoundError";constructor(e){super("step",e);}},fe=class extends I{code="StepAlreadyExistsError";constructor(e){super("step",e);}};var j=class extends S{code="WorkflowNotFoundError";constructor(e){super("workflow",e);}},ye=class extends I{code="WorkflowAlreadyExistsError";constructor(e){super("workflow",e);}};var ge=class{ajv;compiledSchemas;constructor(){this.ajv=new Ze__default.default({useDefaults:!0,removeAdditional:"all"}),He__default.default(this.ajv),this.compiledSchemas=new Map;}isSchema(e){return typeof e=="boolean"?!1:e.type==="object"||!!e.anyOf||!!e.oneOf}async validate(e,t){let i=this.compiledSchemas.get(t);return i||(i=this.ajv.compile(t),this.compiledSchemas.set(t,i)),i(e)?{success:!0,data:e}:{success:!1,errors:i.errors.map(a=>({path:a.instancePath,message:a.message}))}}transformToJsonSchema(e){return e}};var _e=class{isSchema(e){return e.safeParseAsync!==void 0}async validate(e,t){let i=t.safeParse(e);return i.success?{success:!0,data:i.data}:{success:!1,errors:i.error.errors.map(s=>({path:`/${s.path.join("/")}`,message:s.message}))}}transformToJsonSchema(e){try{return zodToJsonSchema.zodToJsonSchema(e)}catch(t){throw t?.message?.includes("Cannot find module")&&console.error("Tried to use a zod schema in @novu/framework without `zod-to-json-schema` installed. Please install it by running `npm install zod-to-json-schema`."),t}}};var De=[new _e,new ge],be=async(n,e)=>{for(let t of De)if(t.isSchema(n))return t.validate(e,n);throw new Error("Invalid schema")},y=n=>{for(let e of De)if(e.isSchema(n))return e.transformToJsonSchema(n);throw new Error("Invalid schema")};var Ne={name:"@novu/framework",version:"2.0.0-canary.0",description:"The Code-First Notifications Workflow SDK.",main:"./dist/index.js",types:"./dist/index.d.ts",publishConfig:{registry:"https://registry.npmjs.org",access:"public"},private:!1,repository:{type:"git",url:"git+https://github.com/novuhq/novu.git"},files:["dist","README.md"],scripts:{preinstall:"npx only-allow pnpm",test:"vitest","test:watch":"vitest --watch",lint:"eslint src --ext .ts","lint:fix":"eslint src --ext .ts --fix",format:"prettier --check --ignore-path .gitignore .","format:fix":"prettier --write --ignore-path .gitignore .",build:"tsup","build:watch":"tsup --watch","$comment:bump:prerelease":"This is a workaround to support `npm version prerelease` with lerna","bump:prerelease":"npm version prerelease --preid=alpha & PID=$!; (sleep 1 && kill -9 $PID) & wait $PID","release:alpha":"pnpm bump:prerelease || pnpm build && npm publish"},keywords:["novu","code-first","workflows","durable","sdk","notifications","email","sms","push","webhooks","next","nuxt","h3","express"],author:"Novu Team <engineering@novu.co>",license:"ISC",exports:{".":{require:"./dist/index.js",import:"./dist/index.js",types:"./dist/index.d.ts"},"./express":{require:"./dist/express.js",import:"./dist/express.js",types:"./dist/express.d.ts"},"./next":{require:"./dist/next.js",import:"./dist/next.js",types:"./dist/next.d.ts"},"./nuxt":{require:"./dist/nuxt.js",import:"./dist/nuxt.js",types:"./dist/nuxt.d.ts"},"./h3":{require:"./dist/h3.js",import:"./dist/h3.js",types:"./dist/h3.d.ts"},"./sveltekit":{require:"./dist/sveltekit.js",import:"./dist/sveltekit.js",types:"./dist/sveltekit.d.ts"},"./remix":{require:"./dist/remix.js",import:"./dist/remix.js",types:"./dist/remix.d.ts"}},peerDependencies:{"@sveltejs/kit":">=1.27.3","@vercel/node":">=2.15.9",express:">=4.19.2",h3:">=1.8.1",next:">=12.0.0",zod:">=3.0.0","zod-to-json-schema":">=3.0.0"},peerDependenciesMeta:{"@sveltejs/kit":{optional:!0},"@vercel/node":{optional:!0},express:{optional:!0},fastify:{optional:!0},h3:{optional:!0},next:{optional:!0},zod:{optional:!0},"zod-to-json-schema":{optional:!0}},devDependencies:{"@sveltejs/kit":"^1.27.3","@types/express":"^4.17.13","@types/json-schema":"^7.0.15","@types/node":"^20.11.20","@vercel/node":"^2.15.9",express:"^4.19.2",h3:"^1.11.1",next:"^13.5.4",prettier:"^3.2.5","ts-node":"^10.9.2",tsup:"^8.0.2",typescript:"^5.3.3",vitest:"^1.2.1",zod:"^3.23.0","zod-to-json-schema":"^3.23.0"},dependencies:{"@novu/shared":"workspace:*",ajv:"^8.12.0","ajv-formats":"^2.1.1","better-ajv-errors":"^1.2.0",chalk:"^4.1.2","cross-fetch":"^4.0.0","json-schema-faker":"^0.5.6","json-schema-to-ts":"^3.0.0",liquidjs:"^10.13.1",ora:"^5.4.1"}};var $=Ne.version,we="2024-06-26";jsonSchemaFaker.JSONSchemaFaker.random.shuffle=function(){return ["[placeholder]"]};jsonSchemaFaker.JSONSchemaFaker.option({useDefaultValue:!0,alwaysFakeOptionals:!0});function ot(){return process.env.NODE_ENV==="development"}var U=class{discoveredWorkflows=[];templateEngine=new liquidjs.Liquid;secretKey;version=$;strictAuthentication;constructor(e){let t=this.buildOptions(e);this.secretKey=t.secretKey,this.strictAuthentication=t.strictAuthentication;}buildOptions(e){let t={secretKey:void 0,strictAuthentication:!ot()};return t.secretKey=e?.secretKey||process.env.NOVU_SECRET_KEY||process.env.NOVU_API_KEY,e?.strictAuthentication!==void 0?t.strictAuthentication=e.strictAuthentication:process.env.NOVU_STRICT_AUTHENTICATION_ENABLED!==void 0&&(t.strictAuthentication=process.env.NOVU_STRICT_AUTHENTICATION_ENABLED==="true"),t}addWorkflows(e){for(let t of e){if(this.discoveredWorkflows.some(i=>i.workflowId===t.definition.workflowId))throw new ye(t.definition.workflowId);this.discoveredWorkflows.push(t.definition);}}healthCheck(){let e=this.discoveredWorkflows.length,t=this.discoveredWorkflows.reduce((i,s)=>i+s.steps.length,0);return {status:"ok",sdkVersion:$,frameworkVersion:we,discovered:{workflows:e,steps:t}}}getWorkflow(e){let t=this.discoveredWorkflows.find(i=>i.workflowId===e);if(t)return t;throw new j(e)}getStep(e,t){let s=this.getWorkflow(e).steps.find(a=>a.stepId===t);if(s)return s;throw new me(t)}getRegisteredWorkflows(){return this.discoveredWorkflows}discover(){return {workflows:this.getRegisteredWorkflows()}}mock(e){return jsonSchemaFaker.JSONSchemaFaker.generate(y(e))}async validate(e,t,i,s,a,l,c){let p=await be(t,e);if(p.success)return p.data;switch(i){case"event":this.throwInvalidEvent(s,a,p.errors);case"step":this.throwInvalidStep(l,s,a,p.errors);case"provider":this.throwInvalidProvider(l,c,s,a,p.errors);default:throw new Error(`Invalid component: '${i}'`)}}throwInvalidProvider(e,t,i,s,a){if(!e)throw new Error("stepId is required");if(!t)throw new Error("providerId is required");switch(i){case"output":throw new H(s,e,t,a);default:throw new Error(`Invalid payload type: '${i}'`)}}throwInvalidStep(e,t,i,s){if(!e)throw new Error("stepId is required");switch(t){case"output":throw new Q(i,e,s);case"result":throw new Z(i,e,s);case"controls":throw new J(i,e,s);default:throw new Error(`Invalid payload type: '${t}'`)}}throwInvalidEvent(e,t,i){switch(e){case"controls":throw new z(t,i);case"payload":throw new M(t,i);default:throw new Error(`Invalid payload type: '${e}'`)}}executeStepFactory(e,t){return async(i,s,a)=>{let l=this.getStep(e.workflowId,i),c=nt(e),p=await this.createStepControls(l,c),u=e.action==="preview";if(!u&&await this.shouldSkip(a?.skip,p))return t({options:{skip:!0}}),{};let g=this.previewStep.bind(this),x=this.executeStep.bind(this),m=await(u?g:x)(e,{...l,providers:l.providers.map(v=>{let N=a?.providers?.[v.type];if(!N)throw new ae(v.type);return {...v,resolve:N}}),resolve:s});return i===e.stepId&&t(m),m.outputs}}async shouldSkip(e,t){return e?e(t):!1}async executeWorkflow(e){let s=`${{execute:"Executing",preview:"Previewing"}[e.action]} workflowId:`;console.log(`
20
+ var V=(i=>(i.TRIGGER="trigger",i.EXECUTE="execute",i.PREVIEW="preview",i))(V||{}),F=(i=>(i.DISCOVER="discover",i.HEALTH_CHECK="health-check",i.CODE="code",i))(F||{});var Je=(t=>(t.SYNC="/v1/bridge/sync",t.DIFF="/v1/bridge/diff",t))(Je||{}),ve=5,Oe=1500;var w=(h=>(h.WORKFLOW_NOT_FOUND_ERROR="WorkflowNotFoundError",h.WORKFLOW_ALREADY_EXISTS_ERROR="WorkflowAlreadyExistsError",h.WORKFLOW_EXECUTION_FAILED_ERROR="WorkflowExecutionFailedError",h.EXECUTION_STATE_OUTPUT_INVALID_ERROR="ExecutionStateOutputInvalidError",h.EXECUTION_STATE_RESULT_INVALID_ERROR="ExecutionStateResultInvalidError",h.EXECUTION_PROVIDER_OUTPUT_INVALID_ERROR="ExecutionProviderOutputInvalidError",h.PROVIDER_NOT_FOUND_ERROR="ProviderNotFoundError",h.PROVIDER_EXECUTION_FAILED_ERROR="ProviderExecutionFailedError",h.STEP_NOT_FOUND_ERROR="StepNotFoundError",h.STEP_ALREADY_EXISTS_ERROR="StepAlreadyExistsError",h.STEP_EXECUTION_FAILED_ERROR="StepExecutionFailedError",h.EXECUTION_STATE_CORRUPT_ERROR="ExecutionStateCorruptError",h.EXECUTION_EVENT_PAYLOAD_INVALID_ERROR="ExecutionEventPayloadInvalidError",h.EXECUTION_EVENT_CONTROL_INVALID_ERROR="ExecutionEventControlInvalidError",h.EXECUTION_STATE_CONTROL_INVALID_ERROR="ExecutionStateControlInvalidError",h.METHOD_NOT_ALLOWED_ERROR="MethodNotAllowedError",h.INVALID_ACTION_ERROR="InvalidActionError",h.MISSING_SECRET_KEY_ERROR="MissingSecretKeyError",h.SIGNATURE_MISMATCH_ERROR="SignatureMismatchError",h.SIGNATURE_NOT_FOUND_ERROR="SignatureNotFoundError",h.SIGNATURE_INVALID_ERROR="SignatureInvalidError",h.SIGNATURE_EXPIRED_ERROR="SignatureExpiredError",h.SIGNING_KEY_NOT_FOUND_ERROR="SigningKeyNotFoundError",h.PLATFORM_ERROR="PlatformError",h.SIGNATURE_VERSION_INVALID_ERROR="SignatureVersionInvalidError",h.WORKFLOW_PAYLOAD_INVALID_ERROR="WorkflowPayloadInvalidError",h))(w||{});var xe=(m=>(m.NOVU_SIGNATURE="novu-signature",m.NOVU_ANONYMOUS="novu-anonymous",m.NOVU_SIGNATURE_DEPRECATED="x-novu-signature",m.NOVU_ANONYMOUS_DEPRECATED="x-novu-anonymous",m.NOVU_FRAMEWORK_SDK="novu-framework-sdk",m.NOVU_FRAMEWORK_API="novu-framework-api",m.NOVU_FRAMEWORK_VERSION="novu-framework-version",m.USER_AGENT="user-agent",m.CONTENT_TYPE="content-type",m.ACCESS_CONTROL_ALLOW_ORIGIN="access-control-allow-origin",m.ACCESS_CONTROL_ALLOW_METHODS="access-control-allow-methods",m.ACCESS_CONTROL_ALLOW_HEADERS="access-control-allow-headers",m.ACCESS_CONTROL_MAX_AGE="access-control-max-age",m))(xe||{});var L=(i=>(i.POST="POST",i.GET="GET",i.OPTIONS="OPTIONS",i))(L||{});var Pe=(s=>(s.WORKFLOW_ID="workflowId",s.STEP_ID="stepId",s.ACTION="action",s.SOURCE="source",s))(Pe||{});var q=(o=>(o[o.CONTINUE=100]="CONTINUE",o[o.SWITCHING_PROTOCOLS=101]="SWITCHING_PROTOCOLS",o[o.PROCESSING=102]="PROCESSING",o[o.EARLYHINTS=103]="EARLYHINTS",o[o.OK=200]="OK",o[o.CREATED=201]="CREATED",o[o.ACCEPTED=202]="ACCEPTED",o[o.NON_AUTHORITATIVE_INFORMATION=203]="NON_AUTHORITATIVE_INFORMATION",o[o.NO_CONTENT=204]="NO_CONTENT",o[o.RESET_CONTENT=205]="RESET_CONTENT",o[o.PARTIAL_CONTENT=206]="PARTIAL_CONTENT",o[o.AMBIGUOUS=300]="AMBIGUOUS",o[o.MOVED_PERMANENTLY=301]="MOVED_PERMANENTLY",o[o.FOUND=302]="FOUND",o[o.SEE_OTHER=303]="SEE_OTHER",o[o.NOT_MODIFIED=304]="NOT_MODIFIED",o[o.TEMPORARY_REDIRECT=307]="TEMPORARY_REDIRECT",o[o.PERMANENT_REDIRECT=308]="PERMANENT_REDIRECT",o[o.BAD_REQUEST=400]="BAD_REQUEST",o[o.UNAUTHORIZED=401]="UNAUTHORIZED",o[o.PAYMENT_REQUIRED=402]="PAYMENT_REQUIRED",o[o.FORBIDDEN=403]="FORBIDDEN",o[o.NOT_FOUND=404]="NOT_FOUND",o[o.METHOD_NOT_ALLOWED=405]="METHOD_NOT_ALLOWED",o[o.NOT_ACCEPTABLE=406]="NOT_ACCEPTABLE",o[o.PROXY_AUTHENTICATION_REQUIRED=407]="PROXY_AUTHENTICATION_REQUIRED",o[o.REQUEST_TIMEOUT=408]="REQUEST_TIMEOUT",o[o.CONFLICT=409]="CONFLICT",o[o.GONE=410]="GONE",o[o.LENGTH_REQUIRED=411]="LENGTH_REQUIRED",o[o.PRECONDITION_FAILED=412]="PRECONDITION_FAILED",o[o.PAYLOAD_TOO_LARGE=413]="PAYLOAD_TOO_LARGE",o[o.URI_TOO_LONG=414]="URI_TOO_LONG",o[o.UNSUPPORTED_MEDIA_TYPE=415]="UNSUPPORTED_MEDIA_TYPE",o[o.REQUESTED_RANGE_NOT_SATISFIABLE=416]="REQUESTED_RANGE_NOT_SATISFIABLE",o[o.EXPECTATION_FAILED=417]="EXPECTATION_FAILED",o[o.I_AM_A_TEAPOT=418]="I_AM_A_TEAPOT",o[o.MISDIRECTED=421]="MISDIRECTED",o[o.UNPROCESSABLE_ENTITY=422]="UNPROCESSABLE_ENTITY",o[o.FAILED_DEPENDENCY=424]="FAILED_DEPENDENCY",o[o.PRECONDITION_REQUIRED=428]="PRECONDITION_REQUIRED",o[o.TOO_MANY_REQUESTS=429]="TOO_MANY_REQUESTS",o[o.INTERNAL_SERVER_ERROR=500]="INTERNAL_SERVER_ERROR",o[o.NOT_IMPLEMENTED=501]="NOT_IMPLEMENTED",o[o.BAD_GATEWAY=502]="BAD_GATEWAY",o[o.SERVICE_UNAVAILABLE=503]="SERVICE_UNAVAILABLE",o[o.GATEWAY_TIMEOUT=504]="GATEWAY_TIMEOUT",o[o.HTTP_VERSION_NOT_SUPPORTED=505]="HTTP_VERSION_NOT_SUPPORTED",o))(q||{}),Vt=[500];var W=(i=>(i.WORKFLOW="workflow",i.PROVIDER="provider",i.STEP="step",i))(W||{});var B=(a=>(a.EMAIL="email",a.SMS="sms",a.PUSH="push",a.CHAT="chat",a.IN_APP="in_app",a))(B||{}),Qe=(i=>(i.DIGEST="digest",i.DELAY="delay",i.CUSTOM="custom",i))(Qe||{});var k=class extends Error{data},G=class extends k{statusCode=404},b=class extends k{statusCode=400},R=class extends k{statusCode=401},O=class extends k{statusCode=500},K=class extends k{statusCode=409};var X=class extends b{code="ExecutionStateCorruptError";constructor(e,t){super(`Workflow with id: \`${e}\` has a corrupt state. Step with id: \`${t}\` does not exist. Please provide the missing state.`),this.data={workflowId:e,stepId:t};}},M=class extends b{code="ExecutionEventPayloadInvalidError";constructor(e,t){super(`Workflow with id: \`${e}\` has invalid \`payload\`. Please provide the correct event payload.`),this.data=t;}},z=class extends b{code="ExecutionEventControlInvalidError";constructor(e,t){super(`Workflow with id: \`${e}\` has invalid \`controls\`. Please provide the correct event controls.`),this.data=t;}},J=class extends b{code="ExecutionStateControlInvalidError";constructor(e,t,i){super(`Workflow with id: \`${e}\` has an invalid state. Step with id: \`${t}\` has invalid \`controls\`. Please provide the correct step controls.`),this.data=i;}},Q=class extends b{code="ExecutionStateOutputInvalidError";constructor(e,t,i){super(`Workflow with id: \`${e}\` has an invalid state. Step with id: \`${t}\` has invalid output. Please provide the correct step output.`),this.data=i;}},Z=class extends b{code="ExecutionStateResultInvalidError";constructor(e,t,i){super(`Workflow with id: \`${e}\` has an invalid state. Step with id: \`${t}\` has invalid result. Please provide the correct step result.`),this.data=i;}},H=class extends b{code="ExecutionProviderOutputInvalidError";constructor(e,t,i,s){super(`Workflow with id: \`${e}\` has an invalid state. Step with id: \`${t}\` and provider with id: \`${i}\` has invalid output. Please provide the correct provider output.`),this.data=s;}},ee=class extends b{code="WorkflowPayloadInvalidError";constructor(e,t){super(`Workflow with id: \`${e}\` has invalid \`payload\`. Please provide the correct payload.`),this.data=t;}},te=class extends Error{statusCode;message;code;constructor(e,t,i){super(i),this.statusCode=e,this.code=t;}};var Ie=async()=>{if(process.env.NOVU_BRIDGE_ORIGIN)return `${process.env.NOVU_BRIDGE_ORIGIN}/api/novu`;if(process.env.NEXT_PUBLIC_VERCEL_ENV==="preview"&&process.env.NEXT_PUBLIC_VERCEL_URL)return `https://${process.env.NEXT_PUBLIC_VERCEL_URL}/api/novu`;try{if(process.env.NODE_ENV==="development"){let e=await(await fetch("http://localhost:2022/.well-known/novu")).json();return `${e.tunnelOrigin}${e.route}`}}catch(n){console.error(n);}return ""};var d={info:n=>P__default.default.blue(n),warning:n=>P__default.default.yellow(n),error:n=>P__default.default.red(n),success:n=>P__default.default.green(n),underline:n=>P__default.default.underline(n),bold:n=>P__default.default.bold(n)},f={SUCCESS:d.success("\u2714"),ERROR:d.error("\u2717"),WARNING:d.warning("\u26A0"),INFO:d.info("\u2139"),ARROW:d.bold("\u2192"),MOCK:d.info("\u25CB"),HYDRATED:d.bold(d.info("\u2192")),STEP:d.info("\u03C3"),ACTION:d.info("\u03B1"),DURATION:d.info("\u0394"),PROVIDER:d.info("\u2699"),OUTPUT:d.info("\u21E2"),INPUT:d.info("\u21E0"),WORKFLOW:d.info("\u03C9"),STATE:d.info("\u03C3"),EXECUTE:d.info("\u03B5"),PREVIEW:d.info("\u03C1")};var ke=n=>Object.values(n).map(e=>`\`${e}\``).join(", "),ie=n=>n.replaceAll(/(\w)(\w*)/g,(e,t,i)=>t.toUpperCase()+i.toLowerCase()).replaceAll(/[\s-]+/g,"");var oe=(n,e="https://api.novu.co")=>{let t=process.env.NOVU_API_URL||e;return {post:async(i,s)=>{let a=await fetch(t+"/v1"+i,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`ApiKey ${n}`},body:JSON.stringify(s)}),l=await a.json();if(a.ok)return l;throw new te(l.statusCode,l.error,l.message)},delete:async i=>(await fetch(t+"/v1"+i,{method:"DELETE",headers:{"Content-Type":"application/json",Authorization:`ApiKey ${n}`}})).json()}};var ne=class extends k{code="MethodNotAllowedError";statusCode=405;message=`Method not allowed. Please use one of ${ke(L)}`},C=class extends b{code="InvalidActionError";constructor(e,t){super(`Invalid query string: \`action\`=\`${e}\`. Please use one of ${ke(t)}`);}},se=class extends b{code="MissingSecretKeyError";constructor(){super("Missing secret key. Set the `NOVU_SECRET_KEY` environment variable or pass `secretKey` to the client options.");}};var re=class extends O{code="PlatformError";message="Something went wrong. Please try again later."};var I=class extends K{constructor(e,t){super(`${ie(e)} with id: \`${t}\` already exists. Please use a different id.`);}},S=class extends G{constructor(e,t){super(`${ie(e)} with id: \`${t}\` does not exist. Please provide a valid id.`);}},D=class extends O{constructor(e,t){super(`Failed to execute ${ie(e)} with id: \`${t}\`. Please try again later.`);}};var ae=class extends S{code="ProviderNotFoundError";constructor(e){super("provider",e);}},le=class extends D{code="ProviderExecutionFailedError";constructor(e){super("workflow",e);}};var ce=class extends R{code="SignatureMismatchError";constructor(){super("Signature does not match the expected signature. Please ensure the signature provided in the `novu-signature` header is correct and try again.");}},pe=class extends R{code="SignatureNotFoundError";constructor(){super("Signature not found. Please provide a signature in the `novu-signature` header");}},de=class extends R{code="SignatureInvalidError";constructor(){super("Signature is invalid. Please provide a valid signature in the `novu-signature` header");}},he=class extends R{code="SignatureExpiredError";constructor(){super(`Signature expired. Please provide a signature with a timestamp no older than ${5} minutes in the \`novu-signature\` header`);}},ue=class extends R{code="SigningKeyNotFoundError";constructor(){super("Signature key not found. Please provide a valid key in the Client constructor `config.secretKey`");}};var me=class extends S{code="StepNotFoundError";constructor(e){super("step",e);}},fe=class extends I{code="StepAlreadyExistsError";constructor(e){super("step",e);}};var j=class extends S{code="WorkflowNotFoundError";constructor(e){super("workflow",e);}},ye=class extends I{code="WorkflowAlreadyExistsError";constructor(e){super("workflow",e);}};var ge=class{ajv;compiledSchemas;constructor(){this.ajv=new Ze__default.default({useDefaults:!0,removeAdditional:"all"}),He__default.default(this.ajv),this.compiledSchemas=new Map;}isSchema(e){return typeof e=="boolean"?!1:e.type==="object"||!!e.anyOf||!!e.oneOf}async validate(e,t){let i=this.compiledSchemas.get(t);return i||(i=this.ajv.compile(t),this.compiledSchemas.set(t,i)),i(e)?{success:!0,data:e}:{success:!1,errors:i.errors.map(a=>({path:a.instancePath,message:a.message}))}}transformToJsonSchema(e){return e}};var _e=class{isSchema(e){return e.safeParseAsync!==void 0}async validate(e,t){let i=t.safeParse(e);return i.success?{success:!0,data:i.data}:{success:!1,errors:i.error.errors.map(s=>({path:`/${s.path.join("/")}`,message:s.message}))}}transformToJsonSchema(e){try{return zodToJsonSchema.zodToJsonSchema(e)}catch(t){throw t?.message?.includes("Cannot find module")&&console.error("Tried to use a zod schema in @novu/framework without `zod-to-json-schema` installed. Please install it by running `npm install zod-to-json-schema`."),t}}};var De=[new _e,new ge],be=async(n,e)=>{for(let t of De)if(t.isSchema(n))return t.validate(e,n);throw new Error("Invalid schema")},y=n=>{for(let e of De)if(e.isSchema(n))return e.transformToJsonSchema(n);throw new Error("Invalid schema")};var Ne={name:"@novu/framework",version:"2.0.0-canary.2",description:"The Code-First Notifications Workflow SDK.",main:"./dist/index.js",types:"./dist/index.d.ts",publishConfig:{registry:"https://registry.npmjs.org",access:"public"},private:!1,repository:{type:"git",url:"git+https://github.com/novuhq/novu.git"},files:["dist","README.md"],scripts:{preinstall:"npx only-allow pnpm",test:"vitest","test:watch":"vitest --watch",lint:"eslint src --ext .ts","lint:fix":"eslint src --ext .ts --fix",format:"prettier --check --ignore-path .gitignore .","format:fix":"prettier --write --ignore-path .gitignore .",build:"tsup","build:watch":"tsup --watch","$comment:bump:prerelease":"This is a workaround to support `npm version prerelease` with lerna","bump:prerelease":"npm version prerelease --preid=alpha & PID=$!; (sleep 1 && kill -9 $PID) & wait $PID","release:alpha":"pnpm bump:prerelease || pnpm build && npm publish"},keywords:["novu","code-first","workflows","durable","sdk","notifications","email","sms","push","webhooks","next","nuxt","h3","express"],author:"Novu Team <engineering@novu.co>",license:"ISC",exports:{".":{require:"./dist/index.js",import:"./dist/index.js",types:"./dist/index.d.ts"},"./express":{require:"./dist/express.js",import:"./dist/express.js",types:"./dist/express.d.ts"},"./next":{require:"./dist/next.js",import:"./dist/next.js",types:"./dist/next.d.ts"},"./nuxt":{require:"./dist/nuxt.js",import:"./dist/nuxt.js",types:"./dist/nuxt.d.ts"},"./h3":{require:"./dist/h3.js",import:"./dist/h3.js",types:"./dist/h3.d.ts"},"./sveltekit":{require:"./dist/sveltekit.js",import:"./dist/sveltekit.js",types:"./dist/sveltekit.d.ts"},"./remix":{require:"./dist/remix.js",import:"./dist/remix.js",types:"./dist/remix.d.ts"}},peerDependencies:{"@sveltejs/kit":">=1.27.3","@vercel/node":">=2.15.9",express:">=4.19.2",h3:">=1.8.1",next:">=12.0.0",zod:">=3.0.0","zod-to-json-schema":">=3.0.0"},peerDependenciesMeta:{"@sveltejs/kit":{optional:!0},"@vercel/node":{optional:!0},express:{optional:!0},fastify:{optional:!0},h3:{optional:!0},next:{optional:!0},zod:{optional:!0},"zod-to-json-schema":{optional:!0}},devDependencies:{"@sveltejs/kit":"^1.27.3","@types/express":"^4.17.13","@types/json-schema":"^7.0.15","@types/node":"^20.11.20","@vercel/node":"^2.15.9",express:"^4.19.2",h3:"^1.11.1",next:"^13.5.4",prettier:"^3.2.5","ts-node":"^10.9.2",tsup:"^8.0.2",typescript:"^5.3.3",vitest:"^1.2.1",zod:"^3.23.0","zod-to-json-schema":"^3.23.0"},dependencies:{"@novu/shared":"^2.0.0-canary.0",ajv:"^8.12.0","ajv-formats":"^2.1.1","better-ajv-errors":"^1.2.0",chalk:"^4.1.2","cross-fetch":"^4.0.0","json-schema-faker":"^0.5.6","json-schema-to-ts":"^3.0.0",liquidjs:"^10.13.1",ora:"^5.4.1"}};var $=Ne.version,we="2024-06-26";jsonSchemaFaker.JSONSchemaFaker.random.shuffle=function(){return ["[placeholder]"]};jsonSchemaFaker.JSONSchemaFaker.option({useDefaultValue:!0,alwaysFakeOptionals:!0});function ot(){return process.env.NODE_ENV==="development"}var U=class{discoveredWorkflows=[];templateEngine=new liquidjs.Liquid;secretKey;version=$;strictAuthentication;constructor(e){let t=this.buildOptions(e);this.secretKey=t.secretKey,this.strictAuthentication=t.strictAuthentication;}buildOptions(e){let t={secretKey:void 0,strictAuthentication:!ot()};return t.secretKey=e?.secretKey||process.env.NOVU_SECRET_KEY||process.env.NOVU_API_KEY,e?.strictAuthentication!==void 0?t.strictAuthentication=e.strictAuthentication:process.env.NOVU_STRICT_AUTHENTICATION_ENABLED!==void 0&&(t.strictAuthentication=process.env.NOVU_STRICT_AUTHENTICATION_ENABLED==="true"),t}addWorkflows(e){for(let t of e){if(this.discoveredWorkflows.some(i=>i.workflowId===t.definition.workflowId))throw new ye(t.definition.workflowId);this.discoveredWorkflows.push(t.definition);}}healthCheck(){let e=this.discoveredWorkflows.length,t=this.discoveredWorkflows.reduce((i,s)=>i+s.steps.length,0);return {status:"ok",sdkVersion:$,frameworkVersion:we,discovered:{workflows:e,steps:t}}}getWorkflow(e){let t=this.discoveredWorkflows.find(i=>i.workflowId===e);if(t)return t;throw new j(e)}getStep(e,t){let s=this.getWorkflow(e).steps.find(a=>a.stepId===t);if(s)return s;throw new me(t)}getRegisteredWorkflows(){return this.discoveredWorkflows}discover(){return {workflows:this.getRegisteredWorkflows()}}mock(e){return jsonSchemaFaker.JSONSchemaFaker.generate(y(e))}async validate(e,t,i,s,a,l,c){let p=await be(t,e);if(p.success)return p.data;switch(i){case"event":this.throwInvalidEvent(s,a,p.errors);case"step":this.throwInvalidStep(l,s,a,p.errors);case"provider":this.throwInvalidProvider(l,c,s,a,p.errors);default:throw new Error(`Invalid component: '${i}'`)}}throwInvalidProvider(e,t,i,s,a){if(!e)throw new Error("stepId is required");if(!t)throw new Error("providerId is required");switch(i){case"output":throw new H(s,e,t,a);default:throw new Error(`Invalid payload type: '${i}'`)}}throwInvalidStep(e,t,i,s){if(!e)throw new Error("stepId is required");switch(t){case"output":throw new Q(i,e,s);case"result":throw new Z(i,e,s);case"controls":throw new J(i,e,s);default:throw new Error(`Invalid payload type: '${t}'`)}}throwInvalidEvent(e,t,i){switch(e){case"controls":throw new z(t,i);case"payload":throw new M(t,i);default:throw new Error(`Invalid payload type: '${e}'`)}}executeStepFactory(e,t){return async(i,s,a)=>{let l=this.getStep(e.workflowId,i),c=nt(e),p=await this.createStepControls(l,c),u=e.action==="preview";if(!u&&await this.shouldSkip(a?.skip,p))return t({options:{skip:!0}}),{};let g=this.previewStep.bind(this),x=this.executeStep.bind(this),m=await(u?g:x)(e,{...l,providers:l.providers.map(v=>{let N=a?.providers?.[v.type];if(!N)throw new ae(v.type);return {...v,resolve:N}}),resolve:s});return i===e.stepId&&t(m),m.outputs}}async shouldSkip(e,t){return e?e(t):!1}async executeWorkflow(e){let s=`${{execute:"Executing",preview:"Previewing"}[e.action]} workflowId:`;console.log(`
21
21
  ${d.bold(d.underline(s))} '${e.workflowId}'`);let a=this.getWorkflow(e.workflowId),l=process.hrtime(),c={outputs:{},providers:{},options:{}},p,u=new Promise(A=>{p=A;}),g=A=>{p(),c=A;},x;try{if(e.action==="execute"&&!e.payload&&!e.data)throw new M(e.workflowId,{message:"Event `payload` is required"});let A=await this.createExecutionPayload(e,a);await Promise.race([u,a.execute({payload:A,environment:{},inputs:{},controls:{},subscriber:e.subscriber,step:{email:this.executeStepFactory(e,g),sms:this.executeStepFactory(e,g),inApp:this.executeStepFactory(e,g),digest:this.executeStepFactory(e,g),delay:this.executeStepFactory(e,g),push:this.executeStepFactory(e,g),chat:this.executeStepFactory(e,g),custom:this.executeStepFactory(e,g)}})]);}catch(A){x=A;}let Y=process.hrtime(l),m=Y[0],v=Y[1],N=m*1e3+v/1e6,Xe=x?f.ERROR:f.SUCCESS,ze=e.action==="execute"?"Executed":e.action==="preview"?"Previewed":"Invalid action";if(console.log(`${Xe} ${ze} workflowId: \`${e.workflowId}\``),this.prettyPrintExecute(e,N,x),x)throw x;return {outputs:c.outputs,providers:c.providers,options:c.options,metadata:{status:"success",error:!1,duration:N}}}async createExecutionPayload(e,t){let i=e.payload||e.data;if(e.action==="preview"){let a=this.mock(t.payload.schema);i=Object.assign(a,i);}return await this.validate(i,t.payload.unknownSchema,"event","payload",e.workflowId)}prettyPrintExecute(e,t,i){let s=i?f.ERROR:f.SUCCESS,a=e.action==="execute"?"Executed":e.action==="preview"?"Previewed":"Invalid action",l=i?"Failed to execute":a,c=i?d.error:d.success,p=`${s} ${l} workflowId: '${e.workflowId}`;console.log(`
22
22
  ${d.bold(c(p))}'`),console.log(` \u251C ${f.STEP} stepId: '${e.stepId}'`),console.log(` \u251C ${f.ACTION} action: '${e.action}'`),console.log(` \u2514 ${f.DURATION} duration: '${t.toFixed(2)}ms'
23
23
  `);}async executeProviders(e,t,i){return t.providers.reduce(async(s,a)=>{let l=await s,c=this.previewProvider.bind(this),p=this.executeProvider.bind(this),g=await(e.action==="preview"?c:p)(e,t,a,i);return {...l,[a.type]:g}},Promise.resolve({}))}previewProvider(e,t,i,s){return console.log(` ${f.MOCK} Mocked provider: \`${i.type}\``),this.mock(i.outputs.schema)}async executeProvider(e,t,i,s){let a=Te__default.default({indent:2}).start(`Executing provider: \`${i.type}\``);try{if(e.stepId===t.stepId){let l=await this.createStepControls(t,e),c=await i.resolve({controls:l,outputs:s}),p=await this.validate(c,i.outputs.unknownSchema,"step","output",e.workflowId,t.stepId,i.type);return a.succeed(`Executed provider: \`${i.type}\``),p}else a.stopAndPersist({symbol:f.HYDRATED,text:`Hydrated provider: \`${i.type}\``});}catch(l){throw a.stopAndPersist({symbol:f.ERROR,text:`Failed to execute provider: \`${i.type}\``}),new le(`Failed to execute provider: '${i.type}'.
package/dist/next.d.ts CHANGED
@@ -14,12 +14,18 @@ declare const frameworkName: SupportedFrameworkName;
14
14
  *
15
15
  * @example Next.js <=12 or the pages router can export the handler directly
16
16
  * ```ts
17
- * export default serve({ workflows: [yourWorkflow] });
17
+ * import { serve } from "@novu/framework/next";
18
+ * import { myWorkflow } from "./src/novu/workflows"; // Your workflows
19
+ *
20
+ * export default serve({ workflows: [myWorkflow] });
18
21
  * ```
19
22
  *
20
23
  * @example Next.js >=13 with the `app` dir must export individual methods
21
24
  * ```ts
22
- * export const { GET, POST, OPTIONS } = serve({ workflows: [yourWorkflow] });
25
+ * import { serve } from "@novu/framework/next";
26
+ * import { myWorkflow } from "./src/novu/workflows";
27
+ *
28
+ * export const { GET, POST, OPTIONS } = serve({ workflows: [myWorkflow] });
23
29
  * ```
24
30
  */
25
31
  declare const serve: (options: ServeHandlerOptions) => ((expectedReq: NextRequest, res: NextApiResponse) => Promise<Response>) & {
package/dist/next.js CHANGED
@@ -17,8 +17,8 @@ var v__default = /*#__PURE__*/_interopDefault(v);
17
17
  var Ae__default = /*#__PURE__*/_interopDefault(Ae);
18
18
  var xe__default = /*#__PURE__*/_interopDefault(xe);
19
19
 
20
- var k=(r=>(r.TRIGGER="trigger",r.EXECUTE="execute",r.PREVIEW="preview",r))(k||{}),U=(r=>(r.DISCOVER="discover",r.HEALTH_CHECK="health-check",r.CODE="code",r))(U||{});var w=(l=>(l.WORKFLOW_NOT_FOUND_ERROR="WorkflowNotFoundError",l.WORKFLOW_ALREADY_EXISTS_ERROR="WorkflowAlreadyExistsError",l.WORKFLOW_EXECUTION_FAILED_ERROR="WorkflowExecutionFailedError",l.EXECUTION_STATE_OUTPUT_INVALID_ERROR="ExecutionStateOutputInvalidError",l.EXECUTION_STATE_RESULT_INVALID_ERROR="ExecutionStateResultInvalidError",l.EXECUTION_PROVIDER_OUTPUT_INVALID_ERROR="ExecutionProviderOutputInvalidError",l.PROVIDER_NOT_FOUND_ERROR="ProviderNotFoundError",l.PROVIDER_EXECUTION_FAILED_ERROR="ProviderExecutionFailedError",l.STEP_NOT_FOUND_ERROR="StepNotFoundError",l.STEP_ALREADY_EXISTS_ERROR="StepAlreadyExistsError",l.STEP_EXECUTION_FAILED_ERROR="StepExecutionFailedError",l.EXECUTION_STATE_CORRUPT_ERROR="ExecutionStateCorruptError",l.EXECUTION_EVENT_PAYLOAD_INVALID_ERROR="ExecutionEventPayloadInvalidError",l.EXECUTION_EVENT_CONTROL_INVALID_ERROR="ExecutionEventControlInvalidError",l.EXECUTION_STATE_CONTROL_INVALID_ERROR="ExecutionStateControlInvalidError",l.METHOD_NOT_ALLOWED_ERROR="MethodNotAllowedError",l.INVALID_ACTION_ERROR="InvalidActionError",l.MISSING_SECRET_KEY_ERROR="MissingSecretKeyError",l.SIGNATURE_MISMATCH_ERROR="SignatureMismatchError",l.SIGNATURE_NOT_FOUND_ERROR="SignatureNotFoundError",l.SIGNATURE_INVALID_ERROR="SignatureInvalidError",l.SIGNATURE_EXPIRED_ERROR="SignatureExpiredError",l.SIGNING_KEY_NOT_FOUND_ERROR="SigningKeyNotFoundError",l.PLATFORM_ERROR="PlatformError",l.SIGNATURE_VERSION_INVALID_ERROR="SignatureVersionInvalidError",l.WORKFLOW_PAYLOAD_INVALID_ERROR="WorkflowPayloadInvalidError",l))(w||{});var L=(r=>(r.POST="POST",r.GET="GET",r.OPTIONS="OPTIONS",r))(L||{});var I=class extends Error{data},b=class extends I{statusCode=404},f=class extends I{statusCode=400},_=class extends I{statusCode=401},x=class extends I{statusCode=500},V=class extends I{statusCode=409};var F=class extends f{code="ExecutionStateCorruptError";constructor(e,t){super(`Workflow with id: \`${e}\` has a corrupt state. Step with id: \`${t}\` does not exist. Please provide the missing state.`),this.data={workflowId:e,stepId:t};}},y=class extends f{code="ExecutionEventPayloadInvalidError";constructor(e,t){super(`Workflow with id: \`${e}\` has invalid \`payload\`. Please provide the correct event payload.`),this.data=t;}},W=class extends f{code="ExecutionEventControlInvalidError";constructor(e,t){super(`Workflow with id: \`${e}\` has invalid \`controls\`. Please provide the correct event controls.`),this.data=t;}},$=class extends f{code="ExecutionStateControlInvalidError";constructor(e,t,r){super(`Workflow with id: \`${e}\` has an invalid state. Step with id: \`${t}\` has invalid \`controls\`. Please provide the correct step controls.`),this.data=r;}},M=class extends f{code="ExecutionStateOutputInvalidError";constructor(e,t,r){super(`Workflow with id: \`${e}\` has an invalid state. Step with id: \`${t}\` has invalid output. Please provide the correct step output.`),this.data=r;}},G=class extends f{code="ExecutionStateResultInvalidError";constructor(e,t,r){super(`Workflow with id: \`${e}\` has an invalid state. Step with id: \`${t}\` has invalid result. Please provide the correct step result.`),this.data=r;}},j=class extends f{code="ExecutionProviderOutputInvalidError";constructor(e,t,r,s){super(`Workflow with id: \`${e}\` has an invalid state. Step with id: \`${t}\` and provider with id: \`${r}\` has invalid output. Please provide the correct provider output.`),this.data=s;}};var K=class extends Error{statusCode;message;code;constructor(e,t,r){super(r),this.statusCode=e,this.code=t;}};var ue=()=>typeof Response<"u"?Response:crossFetch.Response;var p={info:o=>v__default.default.blue(o),warning:o=>v__default.default.yellow(o),error:o=>v__default.default.red(o),success:o=>v__default.default.green(o),underline:o=>v__default.default.underline(o),bold:o=>v__default.default.bold(o)},R={SUCCESS:p.success("\u2714"),ERROR:p.error("\u2717"),WARNING:p.warning("\u26A0"),INFO:p.info("\u2139"),ARROW:p.bold("\u2192"),MOCK:p.info("\u25CB"),HYDRATED:p.bold(p.info("\u2192")),STEP:p.info("\u03C3"),ACTION:p.info("\u03B1"),DURATION:p.info("\u0394"),PROVIDER:p.info("\u2699"),OUTPUT:p.info("\u21E2"),INPUT:p.info("\u21E0"),WORKFLOW:p.info("\u03C9"),STATE:p.info("\u03C3"),EXECUTE:p.info("\u03B5"),PREVIEW:p.info("\u03C1")};var de=o=>Object.values(o).map(e=>`\`${e}\``).join(", "),q=o=>o.replaceAll(/(\w)(\w*)/g,(e,t,r)=>t.toUpperCase()+r.toLowerCase()).replaceAll(/[\s-]+/g,"");var Re=(o,e="https://api.novu.co")=>{let t=process.env.NOVU_API_URL||e;return {post:async(r,s)=>{let i=await fetch(t+"/v1"+r,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`ApiKey ${o}`},body:JSON.stringify(s)}),c=await i.json();if(i.ok)return c;throw new K(c.statusCode,c.error,c.message)},delete:async r=>(await fetch(t+"/v1"+r,{method:"DELETE",headers:{"Content-Type":"application/json",Authorization:`ApiKey ${o}`}})).json()}};var Y=class extends I{code="MethodNotAllowedError";statusCode=405;message=`Method not allowed. Please use one of ${de(L)}`},S=class extends f{code="InvalidActionError";constructor(e,t){super(`Invalid query string: \`action\`=\`${e}\`. Please use one of ${de(t)}`);}};var X=class extends x{code="PlatformError";message="Something went wrong. Please try again later."};var P=class extends V{constructor(e,t){super(`${q(e)} with id: \`${t}\` already exists. Please use a different id.`);}},m=class extends b{constructor(e,t){super(`${q(e)} with id: \`${t}\` does not exist. Please provide a valid id.`);}},g=class extends x{constructor(e,t){super(`Failed to execute ${q(e)} with id: \`${t}\`. Please try again later.`);}};var J=class extends m{code="ProviderNotFoundError";constructor(e){super("provider",e);}},B=class extends g{code="ProviderExecutionFailedError";constructor(e){super("workflow",e);}};var z=class extends _{code="SignatureMismatchError";constructor(){super("Signature does not match the expected signature. Please ensure the signature provided in the `novu-signature` header is correct and try again.");}},Z=class extends _{code="SignatureNotFoundError";constructor(){super("Signature not found. Please provide a signature in the `novu-signature` header");}},Q=class extends _{code="SignatureInvalidError";constructor(){super("Signature is invalid. Please provide a valid signature in the `novu-signature` header");}},H=class extends _{code="SignatureExpiredError";constructor(){super(`Signature expired. Please provide a signature with a timestamp no older than ${5} minutes in the \`novu-signature\` header`);}},ee=class extends _{code="SigningKeyNotFoundError";constructor(){super("Signature key not found. Please provide a valid key in the Client constructor `config.secretKey`");}};var te=class extends m{code="StepNotFoundError";constructor(e){super("step",e);}};var C=class extends m{code="WorkflowNotFoundError";constructor(e){super("workflow",e);}},re=class extends P{code="WorkflowAlreadyExistsError";constructor(e){super("workflow",e);}};var oe=class{ajv;compiledSchemas;constructor(){this.ajv=new Ae__default.default({useDefaults:!0,removeAdditional:"all"}),xe__default.default(this.ajv),this.compiledSchemas=new Map;}isSchema(e){return typeof e=="boolean"?!1:e.type==="object"||!!e.anyOf||!!e.oneOf}async validate(e,t){let r=this.compiledSchemas.get(t);return r||(r=this.ajv.compile(t),this.compiledSchemas.set(t,r)),r(e)?{success:!0,data:e}:{success:!1,errors:r.errors.map(i=>({path:i.instancePath,message:i.message}))}}transformToJsonSchema(e){return e}};var se=class{isSchema(e){return e.safeParseAsync!==void 0}async validate(e,t){let r=t.safeParse(e);return r.success?{success:!0,data:r.data}:{success:!1,errors:r.error.errors.map(s=>({path:`/${s.path.join("/")}`,message:s.message}))}}transformToJsonSchema(e){try{return zodToJsonSchema.zodToJsonSchema(e)}catch(t){throw t?.message?.includes("Cannot find module")&&console.error("Tried to use a zod schema in @novu/framework without `zod-to-json-schema` installed. Please install it by running `npm install zod-to-json-schema`."),t}}};var Ee=[new se,new oe],Oe=async(o,e)=>{for(let t of Ee)if(t.isSchema(o))return t.validate(e,o);throw new Error("Invalid schema")},Te=o=>{for(let e of Ee)if(e.isSchema(o))return e.transformToJsonSchema(o);throw new Error("Invalid schema")};var fe={name:"@novu/framework",version:"2.0.0-canary.0",description:"The Code-First Notifications Workflow SDK.",main:"./dist/index.js",types:"./dist/index.d.ts",publishConfig:{registry:"https://registry.npmjs.org",access:"public"},private:!1,repository:{type:"git",url:"git+https://github.com/novuhq/novu.git"},files:["dist","README.md"],scripts:{preinstall:"npx only-allow pnpm",test:"vitest","test:watch":"vitest --watch",lint:"eslint src --ext .ts","lint:fix":"eslint src --ext .ts --fix",format:"prettier --check --ignore-path .gitignore .","format:fix":"prettier --write --ignore-path .gitignore .",build:"tsup","build:watch":"tsup --watch","$comment:bump:prerelease":"This is a workaround to support `npm version prerelease` with lerna","bump:prerelease":"npm version prerelease --preid=alpha & PID=$!; (sleep 1 && kill -9 $PID) & wait $PID","release:alpha":"pnpm bump:prerelease || pnpm build && npm publish"},keywords:["novu","code-first","workflows","durable","sdk","notifications","email","sms","push","webhooks","next","nuxt","h3","express"],author:"Novu Team <engineering@novu.co>",license:"ISC",exports:{".":{require:"./dist/index.js",import:"./dist/index.js",types:"./dist/index.d.ts"},"./express":{require:"./dist/express.js",import:"./dist/express.js",types:"./dist/express.d.ts"},"./next":{require:"./dist/next.js",import:"./dist/next.js",types:"./dist/next.d.ts"},"./nuxt":{require:"./dist/nuxt.js",import:"./dist/nuxt.js",types:"./dist/nuxt.d.ts"},"./h3":{require:"./dist/h3.js",import:"./dist/h3.js",types:"./dist/h3.d.ts"},"./sveltekit":{require:"./dist/sveltekit.js",import:"./dist/sveltekit.js",types:"./dist/sveltekit.d.ts"},"./remix":{require:"./dist/remix.js",import:"./dist/remix.js",types:"./dist/remix.d.ts"}},peerDependencies:{"@sveltejs/kit":">=1.27.3","@vercel/node":">=2.15.9",express:">=4.19.2",h3:">=1.8.1",next:">=12.0.0",zod:">=3.0.0","zod-to-json-schema":">=3.0.0"},peerDependenciesMeta:{"@sveltejs/kit":{optional:!0},"@vercel/node":{optional:!0},express:{optional:!0},fastify:{optional:!0},h3:{optional:!0},next:{optional:!0},zod:{optional:!0},"zod-to-json-schema":{optional:!0}},devDependencies:{"@sveltejs/kit":"^1.27.3","@types/express":"^4.17.13","@types/json-schema":"^7.0.15","@types/node":"^20.11.20","@vercel/node":"^2.15.9",express:"^4.19.2",h3:"^1.11.1",next:"^13.5.4",prettier:"^3.2.5","ts-node":"^10.9.2",tsup:"^8.0.2",typescript:"^5.3.3",vitest:"^1.2.1",zod:"^3.23.0","zod-to-json-schema":"^3.23.0"},dependencies:{"@novu/shared":"workspace:*",ajv:"^8.12.0","ajv-formats":"^2.1.1","better-ajv-errors":"^1.2.0",chalk:"^4.1.2","cross-fetch":"^4.0.0","json-schema-faker":"^0.5.6","json-schema-to-ts":"^3.0.0",liquidjs:"^10.13.1",ora:"^5.4.1"}};var D=fe.version,ie="2024-06-26";jsonSchemaFaker.JSONSchemaFaker.random.shuffle=function(){return ["[placeholder]"]};jsonSchemaFaker.JSONSchemaFaker.option({useDefaultValue:!0,alwaysFakeOptionals:!0});function Se(){return process.env.NODE_ENV==="development"}var ae=class{discoveredWorkflows=[];templateEngine=new liquidjs.Liquid;secretKey;version=D;strictAuthentication;constructor(e){let t=this.buildOptions(e);this.secretKey=t.secretKey,this.strictAuthentication=t.strictAuthentication;}buildOptions(e){let t={secretKey:void 0,strictAuthentication:!Se()};return t.secretKey=e?.secretKey||process.env.NOVU_SECRET_KEY||process.env.NOVU_API_KEY,e?.strictAuthentication!==void 0?t.strictAuthentication=e.strictAuthentication:process.env.NOVU_STRICT_AUTHENTICATION_ENABLED!==void 0&&(t.strictAuthentication=process.env.NOVU_STRICT_AUTHENTICATION_ENABLED==="true"),t}addWorkflows(e){for(let t of e){if(this.discoveredWorkflows.some(r=>r.workflowId===t.definition.workflowId))throw new re(t.definition.workflowId);this.discoveredWorkflows.push(t.definition);}}healthCheck(){let e=this.discoveredWorkflows.length,t=this.discoveredWorkflows.reduce((r,s)=>r+s.steps.length,0);return {status:"ok",sdkVersion:D,frameworkVersion:ie,discovered:{workflows:e,steps:t}}}getWorkflow(e){let t=this.discoveredWorkflows.find(r=>r.workflowId===e);if(t)return t;throw new C(e)}getStep(e,t){let s=this.getWorkflow(e).steps.find(i=>i.stepId===t);if(s)return s;throw new te(t)}getRegisteredWorkflows(){return this.discoveredWorkflows}discover(){return {workflows:this.getRegisteredWorkflows()}}mock(e){return jsonSchemaFaker.JSONSchemaFaker.generate(Te(e))}async validate(e,t,r,s,i,c,d){let n=await Oe(t,e);if(n.success)return n.data;switch(r){case"event":this.throwInvalidEvent(s,i,n.errors);case"step":this.throwInvalidStep(c,s,i,n.errors);case"provider":this.throwInvalidProvider(c,d,s,i,n.errors);default:throw new Error(`Invalid component: '${r}'`)}}throwInvalidProvider(e,t,r,s,i){if(!e)throw new Error("stepId is required");if(!t)throw new Error("providerId is required");switch(r){case"output":throw new j(s,e,t,i);default:throw new Error(`Invalid payload type: '${r}'`)}}throwInvalidStep(e,t,r,s){if(!e)throw new Error("stepId is required");switch(t){case"output":throw new M(r,e,s);case"result":throw new G(r,e,s);case"controls":throw new $(r,e,s);default:throw new Error(`Invalid payload type: '${t}'`)}}throwInvalidEvent(e,t,r){switch(e){case"controls":throw new W(t,r);case"payload":throw new y(t,r);default:throw new Error(`Invalid payload type: '${e}'`)}}executeStepFactory(e,t){return async(r,s,i)=>{let c=this.getStep(e.workflowId,r),d=Pe(e),n=await this.createStepControls(c,d),h=e.action==="preview";if(!h&&await this.shouldSkip(i?.skip,n))return t({options:{skip:!0}}),{};let a=this.previewStep.bind(this),u=this.executeStep.bind(this),N=await(h?a:u)(e,{...c,providers:c.providers.map(E=>{let O=i?.providers?.[E.type];if(!O)throw new J(E.type);return {...E,resolve:O}}),resolve:s});return r===e.stepId&&t(N),N.outputs}}async shouldSkip(e,t){return e?e(t):!1}async executeWorkflow(e){let s=`${{execute:"Executing",preview:"Previewing"}[e.action]} workflowId:`;console.log(`
21
- ${p.bold(p.underline(s))} '${e.workflowId}'`);let i=this.getWorkflow(e.workflowId),c=process.hrtime(),d={outputs:{},providers:{},options:{}},n,h=new Promise(A=>{n=A;}),a=A=>{n(),d=A;},u;try{if(e.action==="execute"&&!e.payload&&!e.data)throw new y(e.workflowId,{message:"Event `payload` is required"});let A=await this.createExecutionPayload(e,i);await Promise.race([h,i.execute({payload:A,environment:{},inputs:{},controls:{},subscriber:e.subscriber,step:{email:this.executeStepFactory(e,a),sms:this.executeStepFactory(e,a),inApp:this.executeStepFactory(e,a),digest:this.executeStepFactory(e,a),delay:this.executeStepFactory(e,a),push:this.executeStepFactory(e,a),chat:this.executeStepFactory(e,a),custom:this.executeStepFactory(e,a)}})]);}catch(A){u=A;}let T=process.hrtime(c),N=T[0],E=T[1],O=N*1e3+E/1e6,we=u?R.ERROR:R.SUCCESS,Ie=e.action==="execute"?"Executed":e.action==="preview"?"Previewed":"Invalid action";if(console.log(`${we} ${Ie} workflowId: \`${e.workflowId}\``),this.prettyPrintExecute(e,O,u),u)throw u;return {outputs:d.outputs,providers:d.providers,options:d.options,metadata:{status:"success",error:!1,duration:O}}}async createExecutionPayload(e,t){let r=e.payload||e.data;if(e.action==="preview"){let i=this.mock(t.payload.schema);r=Object.assign(i,r);}return await this.validate(r,t.payload.unknownSchema,"event","payload",e.workflowId)}prettyPrintExecute(e,t,r){let s=r?R.ERROR:R.SUCCESS,i=e.action==="execute"?"Executed":e.action==="preview"?"Previewed":"Invalid action",c=r?"Failed to execute":i,d=r?p.error:p.success,n=`${s} ${c} workflowId: '${e.workflowId}`;console.log(`
20
+ var k=(r=>(r.TRIGGER="trigger",r.EXECUTE="execute",r.PREVIEW="preview",r))(k||{}),U=(r=>(r.DISCOVER="discover",r.HEALTH_CHECK="health-check",r.CODE="code",r))(U||{});var w=(l=>(l.WORKFLOW_NOT_FOUND_ERROR="WorkflowNotFoundError",l.WORKFLOW_ALREADY_EXISTS_ERROR="WorkflowAlreadyExistsError",l.WORKFLOW_EXECUTION_FAILED_ERROR="WorkflowExecutionFailedError",l.EXECUTION_STATE_OUTPUT_INVALID_ERROR="ExecutionStateOutputInvalidError",l.EXECUTION_STATE_RESULT_INVALID_ERROR="ExecutionStateResultInvalidError",l.EXECUTION_PROVIDER_OUTPUT_INVALID_ERROR="ExecutionProviderOutputInvalidError",l.PROVIDER_NOT_FOUND_ERROR="ProviderNotFoundError",l.PROVIDER_EXECUTION_FAILED_ERROR="ProviderExecutionFailedError",l.STEP_NOT_FOUND_ERROR="StepNotFoundError",l.STEP_ALREADY_EXISTS_ERROR="StepAlreadyExistsError",l.STEP_EXECUTION_FAILED_ERROR="StepExecutionFailedError",l.EXECUTION_STATE_CORRUPT_ERROR="ExecutionStateCorruptError",l.EXECUTION_EVENT_PAYLOAD_INVALID_ERROR="ExecutionEventPayloadInvalidError",l.EXECUTION_EVENT_CONTROL_INVALID_ERROR="ExecutionEventControlInvalidError",l.EXECUTION_STATE_CONTROL_INVALID_ERROR="ExecutionStateControlInvalidError",l.METHOD_NOT_ALLOWED_ERROR="MethodNotAllowedError",l.INVALID_ACTION_ERROR="InvalidActionError",l.MISSING_SECRET_KEY_ERROR="MissingSecretKeyError",l.SIGNATURE_MISMATCH_ERROR="SignatureMismatchError",l.SIGNATURE_NOT_FOUND_ERROR="SignatureNotFoundError",l.SIGNATURE_INVALID_ERROR="SignatureInvalidError",l.SIGNATURE_EXPIRED_ERROR="SignatureExpiredError",l.SIGNING_KEY_NOT_FOUND_ERROR="SigningKeyNotFoundError",l.PLATFORM_ERROR="PlatformError",l.SIGNATURE_VERSION_INVALID_ERROR="SignatureVersionInvalidError",l.WORKFLOW_PAYLOAD_INVALID_ERROR="WorkflowPayloadInvalidError",l))(w||{});var L=(r=>(r.POST="POST",r.GET="GET",r.OPTIONS="OPTIONS",r))(L||{});var I=class extends Error{data},b=class extends I{statusCode=404},f=class extends I{statusCode=400},_=class extends I{statusCode=401},x=class extends I{statusCode=500},V=class extends I{statusCode=409};var F=class extends f{code="ExecutionStateCorruptError";constructor(e,t){super(`Workflow with id: \`${e}\` has a corrupt state. Step with id: \`${t}\` does not exist. Please provide the missing state.`),this.data={workflowId:e,stepId:t};}},g=class extends f{code="ExecutionEventPayloadInvalidError";constructor(e,t){super(`Workflow with id: \`${e}\` has invalid \`payload\`. Please provide the correct event payload.`),this.data=t;}},W=class extends f{code="ExecutionEventControlInvalidError";constructor(e,t){super(`Workflow with id: \`${e}\` has invalid \`controls\`. Please provide the correct event controls.`),this.data=t;}},$=class extends f{code="ExecutionStateControlInvalidError";constructor(e,t,r){super(`Workflow with id: \`${e}\` has an invalid state. Step with id: \`${t}\` has invalid \`controls\`. Please provide the correct step controls.`),this.data=r;}},M=class extends f{code="ExecutionStateOutputInvalidError";constructor(e,t,r){super(`Workflow with id: \`${e}\` has an invalid state. Step with id: \`${t}\` has invalid output. Please provide the correct step output.`),this.data=r;}},G=class extends f{code="ExecutionStateResultInvalidError";constructor(e,t,r){super(`Workflow with id: \`${e}\` has an invalid state. Step with id: \`${t}\` has invalid result. Please provide the correct step result.`),this.data=r;}},j=class extends f{code="ExecutionProviderOutputInvalidError";constructor(e,t,r,s){super(`Workflow with id: \`${e}\` has an invalid state. Step with id: \`${t}\` and provider with id: \`${r}\` has invalid output. Please provide the correct provider output.`),this.data=s;}};var K=class extends Error{statusCode;message;code;constructor(e,t,r){super(r),this.statusCode=e,this.code=t;}};var ue=()=>typeof Response<"u"?Response:crossFetch.Response;var p={info:o=>v__default.default.blue(o),warning:o=>v__default.default.yellow(o),error:o=>v__default.default.red(o),success:o=>v__default.default.green(o),underline:o=>v__default.default.underline(o),bold:o=>v__default.default.bold(o)},R={SUCCESS:p.success("\u2714"),ERROR:p.error("\u2717"),WARNING:p.warning("\u26A0"),INFO:p.info("\u2139"),ARROW:p.bold("\u2192"),MOCK:p.info("\u25CB"),HYDRATED:p.bold(p.info("\u2192")),STEP:p.info("\u03C3"),ACTION:p.info("\u03B1"),DURATION:p.info("\u0394"),PROVIDER:p.info("\u2699"),OUTPUT:p.info("\u21E2"),INPUT:p.info("\u21E0"),WORKFLOW:p.info("\u03C9"),STATE:p.info("\u03C3"),EXECUTE:p.info("\u03B5"),PREVIEW:p.info("\u03C1")};var de=o=>Object.values(o).map(e=>`\`${e}\``).join(", "),q=o=>o.replaceAll(/(\w)(\w*)/g,(e,t,r)=>t.toUpperCase()+r.toLowerCase()).replaceAll(/[\s-]+/g,"");var Re=(o,e="https://api.novu.co")=>{let t=process.env.NOVU_API_URL||e;return {post:async(r,s)=>{let i=await fetch(t+"/v1"+r,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`ApiKey ${o}`},body:JSON.stringify(s)}),c=await i.json();if(i.ok)return c;throw new K(c.statusCode,c.error,c.message)},delete:async r=>(await fetch(t+"/v1"+r,{method:"DELETE",headers:{"Content-Type":"application/json",Authorization:`ApiKey ${o}`}})).json()}};var Y=class extends I{code="MethodNotAllowedError";statusCode=405;message=`Method not allowed. Please use one of ${de(L)}`},S=class extends f{code="InvalidActionError";constructor(e,t){super(`Invalid query string: \`action\`=\`${e}\`. Please use one of ${de(t)}`);}};var X=class extends x{code="PlatformError";message="Something went wrong. Please try again later."};var P=class extends V{constructor(e,t){super(`${q(e)} with id: \`${t}\` already exists. Please use a different id.`);}},m=class extends b{constructor(e,t){super(`${q(e)} with id: \`${t}\` does not exist. Please provide a valid id.`);}},y=class extends x{constructor(e,t){super(`Failed to execute ${q(e)} with id: \`${t}\`. Please try again later.`);}};var J=class extends m{code="ProviderNotFoundError";constructor(e){super("provider",e);}},B=class extends y{code="ProviderExecutionFailedError";constructor(e){super("workflow",e);}};var z=class extends _{code="SignatureMismatchError";constructor(){super("Signature does not match the expected signature. Please ensure the signature provided in the `novu-signature` header is correct and try again.");}},Z=class extends _{code="SignatureNotFoundError";constructor(){super("Signature not found. Please provide a signature in the `novu-signature` header");}},Q=class extends _{code="SignatureInvalidError";constructor(){super("Signature is invalid. Please provide a valid signature in the `novu-signature` header");}},H=class extends _{code="SignatureExpiredError";constructor(){super(`Signature expired. Please provide a signature with a timestamp no older than ${5} minutes in the \`novu-signature\` header`);}},ee=class extends _{code="SigningKeyNotFoundError";constructor(){super("Signature key not found. Please provide a valid key in the Client constructor `config.secretKey`");}};var te=class extends m{code="StepNotFoundError";constructor(e){super("step",e);}};var C=class extends m{code="WorkflowNotFoundError";constructor(e){super("workflow",e);}},re=class extends P{code="WorkflowAlreadyExistsError";constructor(e){super("workflow",e);}};var oe=class{ajv;compiledSchemas;constructor(){this.ajv=new Ae__default.default({useDefaults:!0,removeAdditional:"all"}),xe__default.default(this.ajv),this.compiledSchemas=new Map;}isSchema(e){return typeof e=="boolean"?!1:e.type==="object"||!!e.anyOf||!!e.oneOf}async validate(e,t){let r=this.compiledSchemas.get(t);return r||(r=this.ajv.compile(t),this.compiledSchemas.set(t,r)),r(e)?{success:!0,data:e}:{success:!1,errors:r.errors.map(i=>({path:i.instancePath,message:i.message}))}}transformToJsonSchema(e){return e}};var se=class{isSchema(e){return e.safeParseAsync!==void 0}async validate(e,t){let r=t.safeParse(e);return r.success?{success:!0,data:r.data}:{success:!1,errors:r.error.errors.map(s=>({path:`/${s.path.join("/")}`,message:s.message}))}}transformToJsonSchema(e){try{return zodToJsonSchema.zodToJsonSchema(e)}catch(t){throw t?.message?.includes("Cannot find module")&&console.error("Tried to use a zod schema in @novu/framework without `zod-to-json-schema` installed. Please install it by running `npm install zod-to-json-schema`."),t}}};var Ee=[new se,new oe],Oe=async(o,e)=>{for(let t of Ee)if(t.isSchema(o))return t.validate(e,o);throw new Error("Invalid schema")},Te=o=>{for(let e of Ee)if(e.isSchema(o))return e.transformToJsonSchema(o);throw new Error("Invalid schema")};var fe={name:"@novu/framework",version:"2.0.0-canary.2",description:"The Code-First Notifications Workflow SDK.",main:"./dist/index.js",types:"./dist/index.d.ts",publishConfig:{registry:"https://registry.npmjs.org",access:"public"},private:!1,repository:{type:"git",url:"git+https://github.com/novuhq/novu.git"},files:["dist","README.md"],scripts:{preinstall:"npx only-allow pnpm",test:"vitest","test:watch":"vitest --watch",lint:"eslint src --ext .ts","lint:fix":"eslint src --ext .ts --fix",format:"prettier --check --ignore-path .gitignore .","format:fix":"prettier --write --ignore-path .gitignore .",build:"tsup","build:watch":"tsup --watch","$comment:bump:prerelease":"This is a workaround to support `npm version prerelease` with lerna","bump:prerelease":"npm version prerelease --preid=alpha & PID=$!; (sleep 1 && kill -9 $PID) & wait $PID","release:alpha":"pnpm bump:prerelease || pnpm build && npm publish"},keywords:["novu","code-first","workflows","durable","sdk","notifications","email","sms","push","webhooks","next","nuxt","h3","express"],author:"Novu Team <engineering@novu.co>",license:"ISC",exports:{".":{require:"./dist/index.js",import:"./dist/index.js",types:"./dist/index.d.ts"},"./express":{require:"./dist/express.js",import:"./dist/express.js",types:"./dist/express.d.ts"},"./next":{require:"./dist/next.js",import:"./dist/next.js",types:"./dist/next.d.ts"},"./nuxt":{require:"./dist/nuxt.js",import:"./dist/nuxt.js",types:"./dist/nuxt.d.ts"},"./h3":{require:"./dist/h3.js",import:"./dist/h3.js",types:"./dist/h3.d.ts"},"./sveltekit":{require:"./dist/sveltekit.js",import:"./dist/sveltekit.js",types:"./dist/sveltekit.d.ts"},"./remix":{require:"./dist/remix.js",import:"./dist/remix.js",types:"./dist/remix.d.ts"}},peerDependencies:{"@sveltejs/kit":">=1.27.3","@vercel/node":">=2.15.9",express:">=4.19.2",h3:">=1.8.1",next:">=12.0.0",zod:">=3.0.0","zod-to-json-schema":">=3.0.0"},peerDependenciesMeta:{"@sveltejs/kit":{optional:!0},"@vercel/node":{optional:!0},express:{optional:!0},fastify:{optional:!0},h3:{optional:!0},next:{optional:!0},zod:{optional:!0},"zod-to-json-schema":{optional:!0}},devDependencies:{"@sveltejs/kit":"^1.27.3","@types/express":"^4.17.13","@types/json-schema":"^7.0.15","@types/node":"^20.11.20","@vercel/node":"^2.15.9",express:"^4.19.2",h3:"^1.11.1",next:"^13.5.4",prettier:"^3.2.5","ts-node":"^10.9.2",tsup:"^8.0.2",typescript:"^5.3.3",vitest:"^1.2.1",zod:"^3.23.0","zod-to-json-schema":"^3.23.0"},dependencies:{"@novu/shared":"^2.0.0-canary.0",ajv:"^8.12.0","ajv-formats":"^2.1.1","better-ajv-errors":"^1.2.0",chalk:"^4.1.2","cross-fetch":"^4.0.0","json-schema-faker":"^0.5.6","json-schema-to-ts":"^3.0.0",liquidjs:"^10.13.1",ora:"^5.4.1"}};var D=fe.version,ie="2024-06-26";jsonSchemaFaker.JSONSchemaFaker.random.shuffle=function(){return ["[placeholder]"]};jsonSchemaFaker.JSONSchemaFaker.option({useDefaultValue:!0,alwaysFakeOptionals:!0});function Se(){return process.env.NODE_ENV==="development"}var ae=class{discoveredWorkflows=[];templateEngine=new liquidjs.Liquid;secretKey;version=D;strictAuthentication;constructor(e){let t=this.buildOptions(e);this.secretKey=t.secretKey,this.strictAuthentication=t.strictAuthentication;}buildOptions(e){let t={secretKey:void 0,strictAuthentication:!Se()};return t.secretKey=e?.secretKey||process.env.NOVU_SECRET_KEY||process.env.NOVU_API_KEY,e?.strictAuthentication!==void 0?t.strictAuthentication=e.strictAuthentication:process.env.NOVU_STRICT_AUTHENTICATION_ENABLED!==void 0&&(t.strictAuthentication=process.env.NOVU_STRICT_AUTHENTICATION_ENABLED==="true"),t}addWorkflows(e){for(let t of e){if(this.discoveredWorkflows.some(r=>r.workflowId===t.definition.workflowId))throw new re(t.definition.workflowId);this.discoveredWorkflows.push(t.definition);}}healthCheck(){let e=this.discoveredWorkflows.length,t=this.discoveredWorkflows.reduce((r,s)=>r+s.steps.length,0);return {status:"ok",sdkVersion:D,frameworkVersion:ie,discovered:{workflows:e,steps:t}}}getWorkflow(e){let t=this.discoveredWorkflows.find(r=>r.workflowId===e);if(t)return t;throw new C(e)}getStep(e,t){let s=this.getWorkflow(e).steps.find(i=>i.stepId===t);if(s)return s;throw new te(t)}getRegisteredWorkflows(){return this.discoveredWorkflows}discover(){return {workflows:this.getRegisteredWorkflows()}}mock(e){return jsonSchemaFaker.JSONSchemaFaker.generate(Te(e))}async validate(e,t,r,s,i,c,d){let n=await Oe(t,e);if(n.success)return n.data;switch(r){case"event":this.throwInvalidEvent(s,i,n.errors);case"step":this.throwInvalidStep(c,s,i,n.errors);case"provider":this.throwInvalidProvider(c,d,s,i,n.errors);default:throw new Error(`Invalid component: '${r}'`)}}throwInvalidProvider(e,t,r,s,i){if(!e)throw new Error("stepId is required");if(!t)throw new Error("providerId is required");switch(r){case"output":throw new j(s,e,t,i);default:throw new Error(`Invalid payload type: '${r}'`)}}throwInvalidStep(e,t,r,s){if(!e)throw new Error("stepId is required");switch(t){case"output":throw new M(r,e,s);case"result":throw new G(r,e,s);case"controls":throw new $(r,e,s);default:throw new Error(`Invalid payload type: '${t}'`)}}throwInvalidEvent(e,t,r){switch(e){case"controls":throw new W(t,r);case"payload":throw new g(t,r);default:throw new Error(`Invalid payload type: '${e}'`)}}executeStepFactory(e,t){return async(r,s,i)=>{let c=this.getStep(e.workflowId,r),d=Pe(e),n=await this.createStepControls(c,d),h=e.action==="preview";if(!h&&await this.shouldSkip(i?.skip,n))return t({options:{skip:!0}}),{};let a=this.previewStep.bind(this),u=this.executeStep.bind(this),N=await(h?a:u)(e,{...c,providers:c.providers.map(E=>{let O=i?.providers?.[E.type];if(!O)throw new J(E.type);return {...E,resolve:O}}),resolve:s});return r===e.stepId&&t(N),N.outputs}}async shouldSkip(e,t){return e?e(t):!1}async executeWorkflow(e){let s=`${{execute:"Executing",preview:"Previewing"}[e.action]} workflowId:`;console.log(`
21
+ ${p.bold(p.underline(s))} '${e.workflowId}'`);let i=this.getWorkflow(e.workflowId),c=process.hrtime(),d={outputs:{},providers:{},options:{}},n,h=new Promise(A=>{n=A;}),a=A=>{n(),d=A;},u;try{if(e.action==="execute"&&!e.payload&&!e.data)throw new g(e.workflowId,{message:"Event `payload` is required"});let A=await this.createExecutionPayload(e,i);await Promise.race([h,i.execute({payload:A,environment:{},inputs:{},controls:{},subscriber:e.subscriber,step:{email:this.executeStepFactory(e,a),sms:this.executeStepFactory(e,a),inApp:this.executeStepFactory(e,a),digest:this.executeStepFactory(e,a),delay:this.executeStepFactory(e,a),push:this.executeStepFactory(e,a),chat:this.executeStepFactory(e,a),custom:this.executeStepFactory(e,a)}})]);}catch(A){u=A;}let T=process.hrtime(c),N=T[0],E=T[1],O=N*1e3+E/1e6,we=u?R.ERROR:R.SUCCESS,Ie=e.action==="execute"?"Executed":e.action==="preview"?"Previewed":"Invalid action";if(console.log(`${we} ${Ie} workflowId: \`${e.workflowId}\``),this.prettyPrintExecute(e,O,u),u)throw u;return {outputs:d.outputs,providers:d.providers,options:d.options,metadata:{status:"success",error:!1,duration:O}}}async createExecutionPayload(e,t){let r=e.payload||e.data;if(e.action==="preview"){let i=this.mock(t.payload.schema);r=Object.assign(i,r);}return await this.validate(r,t.payload.unknownSchema,"event","payload",e.workflowId)}prettyPrintExecute(e,t,r){let s=r?R.ERROR:R.SUCCESS,i=e.action==="execute"?"Executed":e.action==="preview"?"Previewed":"Invalid action",c=r?"Failed to execute":i,d=r?p.error:p.success,n=`${s} ${c} workflowId: '${e.workflowId}`;console.log(`
22
22
  ${p.bold(d(n))}'`),console.log(` \u251C ${R.STEP} stepId: '${e.stepId}'`),console.log(` \u251C ${R.ACTION} action: '${e.action}'`),console.log(` \u2514 ${R.DURATION} duration: '${t.toFixed(2)}ms'
23
23
  `);}async executeProviders(e,t,r){return t.providers.reduce(async(s,i)=>{let c=await s,d=this.previewProvider.bind(this),n=this.executeProvider.bind(this),a=await(e.action==="preview"?d:n)(e,t,i,r);return {...c,[i.type]:a}},Promise.resolve({}))}previewProvider(e,t,r,s){return console.log(` ${R.MOCK} Mocked provider: \`${r.type}\``),this.mock(r.outputs.schema)}async executeProvider(e,t,r,s){let i=ne__default.default({indent:2}).start(`Executing provider: \`${r.type}\``);try{if(e.stepId===t.stepId){let c=await this.createStepControls(t,e),d=await r.resolve({controls:c,outputs:s}),n=await this.validate(d,r.outputs.unknownSchema,"step","output",e.workflowId,t.stepId,r.type);return i.succeed(`Executed provider: \`${r.type}\``),n}else i.stopAndPersist({symbol:R.HYDRATED,text:`Hydrated provider: \`${r.type}\``});}catch(c){throw i.stopAndPersist({symbol:R.ERROR,text:`Failed to execute provider: \`${r.type}\``}),new B(`Failed to execute provider: '${r.type}'.
24
24
  ${c.message}`)}}async executeStep(e,t){if(e.stepId===t.stepId){let r=ne__default.default({indent:1}).start(`Executing stepId: \`${t.stepId}\``);try{let s=await this.createStepControls(t,e),i=await this.compileControls(s,e),c=await t.resolve(i),d=await this.validate(c,t.outputs.unknownSchema,"step","output",e.workflowId,t.stepId),n=await this.executeProviders(e,t,d);return r.succeed(`Executed stepId: \`${t.stepId}\``),{outputs:d,providers:n}}catch(s){throw r.stopAndPersist({prefixText:"",symbol:R.ERROR,text:`Failed to execute stepId: \`${t.stepId}\``}),s}}else {let r=ne__default.default({indent:1}).start(`Hydrating stepId: \`${t.stepId}\``);try{let s=e.state.find(i=>i.stepId===t.stepId);if(s){let i=await this.validate(s.outputs,t.results.unknownSchema,"step","result",e.workflowId,t.stepId);return r.stopAndPersist({symbol:R.HYDRATED,text:`Hydrated stepId: \`${t.stepId}\``}),{outputs:i,providers:await this.executeProviders(e,t,i)}}else throw new F(e.workflowId,t.stepId)}catch(s){throw r.stopAndPersist({symbol:R.ERROR,text:`Failed to hydrate stepId: \`${t.stepId}\``}),s}}}async compileControls(e,t){let r=this.templateEngine.parse(JSON.stringify(e)),s=await this.templateEngine.render(r,{...t.payload||t.data,subscriber:t.subscriber});return JSON.parse(s)}async createStepControls(e,t){let r=t.controls||t.inputs;return await this.validate(r,e.controls.unknownSchema,"step","controls",t.workflowId,e.stepId)}async previewStep(e,t){let r=ne__default.default({indent:1}).start(`Previewing stepId: \`${t.stepId}\``);try{if(e.stepId===t.stepId){let s=await this.createStepControls(t,e),i=await this.compileControls(s,e),c=await t.resolve(i),d=await this.validate(c,t.outputs.unknownSchema,"step","output",e.workflowId,t.stepId);return r.stopAndPersist({symbol:R.MOCK,text:`Mocked stepId: \`${t.stepId}\``}),{outputs:d,providers:await this.executeProviders(e,t,d)}}else {let s=this.mock(t.results.schema);return r.stopAndPersist({symbol:R.MOCK,text:`Mocked stepId: \`${t.stepId}\``}),{outputs:s,providers:await this.executeProviders(e,t,s)}}}catch(s){throw r.stopAndPersist({symbol:R.ERROR,text:`Failed to preview stepId: \`${t.stepId}\``}),s}}getStepCode(e,t){return {code:this.getStep(e,t).resolve.toString()}}getWorkflowCode(e){return {code:this.getWorkflow(e).execute.toString()}}getCode(e,t){let r;if(e)t?r=this.getStepCode(e,t):r=this.getWorkflowCode(e);else throw new C(e);return r}};function Pe(o){return JSON.parse(JSON.stringify(o))}var ce=class{frameworkName;handler;client;hmacEnabled;http;constructor(e){this.handler=e.handler,this.client=e.client?e.client:new ae,this.client.addWorkflows(e.workflows),this.http=Re(this.client.secretKey),this.frameworkName=e.frameworkName,this.hmacEnabled=this.client.strictAuthentication;}createHandler(){return async(...e)=>{let t=await this.handler(...e),r=await this.handleAction({actions:t});return t.transformResponse(r)}}getStaticHeaders(){let e=`novu-framework:v${this.client.version}`;return {"content-type":"application/json","access-control-allow-origin":"*","access-control-allow-methods":"GET, POST","access-control-allow-headers":"*","access-control-max-age":"604800","novu-framework-version":ie,"novu-framework-sdk":D,"novu-framework-api":this.frameworkName,"user-agent":e}}createResponse(e,t){return {status:e,body:JSON.stringify(t),headers:{...this.getStaticHeaders()}}}createError(e){return {status:e.statusCode,body:JSON.stringify({message:e.message,data:e.data,code:e.code}),headers:this.getStaticHeaders()}}async handleAction({actions:e}){let t=await e.url(),r=await e.method(),s=t.searchParams.get("action")||"",i=t.searchParams.get("workflowId")||"",c=t.searchParams.get("stepId")||"",d=await e.headers("novu-signature")||await e.headers("x-novu-signature")||"",n={};try{r==="POST"&&(n=await e.body());}catch{}try{s!=="health-check"&&this.validateHmac(n,d);let h=this.getPostActionMap(n,i,c,s),a=this.getGetActionMap(i,c);if(r==="POST")return await this.handlePostAction(s,h);if(r==="GET")return await this.handleGetAction(s,a);if(r==="OPTIONS")return this.createResponse(200,{})}catch(h){return this.handleError(h)}return this.createError(new Y(r))}getPostActionMap(e,t,r,s){return {trigger:this.triggerAction({workflowId:t,...e}),execute:async()=>{let i=await this.client.executeWorkflow({...e,workflowId:t,stepId:r,action:s});return this.createResponse(200,i)},preview:async()=>{let i=await this.client.executeWorkflow({...e,workflowId:t,stepId:r,action:s});return this.createResponse(200,i)}}}triggerAction(e){return async()=>{let t={name:e.workflowId,to:e.to,payload:e?.payload||{},transactionId:e.transactionId,overrides:e.overrides||{},...e.actor&&{actor:e.actor},...e.tenant&&{tenant:e.tenant},...e.bridgeUrl&&{bridgeUrl:e.bridgeUrl},...e.controls&&{controls:e.controls}},r=await this.http.post("/events/trigger",t);return this.createResponse(200,r)}}getGetActionMap(e,t){return {discover:async()=>{let r=await this.client.discover();return this.createResponse(200,r)},"health-check":async()=>{let r=await this.client.healthCheck();return this.createResponse(200,r)},code:async()=>{let r=await this.client.getCode(e,t);return this.createResponse(200,r)}}}async handlePostAction(e,t){if(Object.values(k).includes(e)){let r=t[e];return r()}else throw new S(e,k)}async handleGetAction(e,t){if(Object.values(U).includes(e)){let r=t[e];return r()}else throw new S(e,U)}isClientError(e){let t=Object.values(w).includes(e.code),r=ke(e);return t||r}handleError(e){return this.isClientError(e)?(e.statusCode===500&&console.error(e),this.createError(e)):(console.error(e),this.createError(new X))}validateHmac(e,t){if(!this.hmacEnabled)return;if(!t)throw new Z;if(!this.client.secretKey)throw new ee;let[r,s]=t.split(",");if(!r||!s)throw new Q;let[i,c]=r.split("="),[d,n]=s.split("=");if(Number(i)<Date.now()-1500)throw new H;if(!(this.hashHmac(this.client.secretKey,`${c}.${JSON.stringify(e)}`)===n))throw new z}hashHmac(e,t){return crypto.createHmac("sha256",e).update(t).digest("hex")}};function ke(o){return o?.statusCode>=400&&o?.statusCode<500}var Ue="next",Cr=o=>{let t=new ce({frameworkName:Ue,...o,handler:(i,c,d)=>{let n=c,h=a=>{let u=typeof n.headers.get=="function"?n.headers.get(a):n.headers[a];return Array.isArray(u)?u[0]:u};return {body:()=>typeof n.json=="function"?n.json():n.body,headers:h,method:()=>i||n.method||"",queryString:(a,u)=>{let T=n.query?.[a]||u.searchParams.get(a);return Array.isArray(T)?T[0]:T},url:()=>{let a;try{a=new URL(n.url);}catch{}if(a){let E=h("host");if(E){let O=new URL(E.includes("://")?E:`${a.protocol}//${E}`);a.protocol=O.protocol,a.host=O.host,a.port=O.port,a.username=O.username,a.password=O.password;}return a}let u="https",T=h("host")||"";try{process.env.NODE_ENV==="development"&&(u="http");}catch{}return new URL(n.url,`${u}://${T}`)},transformResponse:({body:a,headers:u,status:T})=>{if(typeof d?.setHeader=="function"&&Object.entries(u).forEach(([E,O])=>{d.setHeader(E,O);}),typeof d?.status=="function"&&typeof d?.send=="function"){d.status(T).send(a);return}let N=ue();return new N(a,{status:T,headers:u})}}}}).createHandler(),r=t.bind(null,void 0);return Object.defineProperties(r,{GET:{value:t.bind(null,"GET")},POST:{value:t.bind(null,"POST")},OPTIONS:{value:t.bind(null,"OPTIONS")}})};
package/dist/nuxt.js CHANGED
@@ -18,7 +18,7 @@ var N__default = /*#__PURE__*/_interopDefault(N);
18
18
  var Ne__default = /*#__PURE__*/_interopDefault(Ne);
19
19
  var Ae__default = /*#__PURE__*/_interopDefault(Ae);
20
20
 
21
- var D=(r=>(r.TRIGGER="trigger",r.EXECUTE="execute",r.PREVIEW="preview",r))(D||{}),k=(r=>(r.DISCOVER="discover",r.HEALTH_CHECK="health-check",r.CODE="code",r))(k||{});var O=(a=>(a.WORKFLOW_NOT_FOUND_ERROR="WorkflowNotFoundError",a.WORKFLOW_ALREADY_EXISTS_ERROR="WorkflowAlreadyExistsError",a.WORKFLOW_EXECUTION_FAILED_ERROR="WorkflowExecutionFailedError",a.EXECUTION_STATE_OUTPUT_INVALID_ERROR="ExecutionStateOutputInvalidError",a.EXECUTION_STATE_RESULT_INVALID_ERROR="ExecutionStateResultInvalidError",a.EXECUTION_PROVIDER_OUTPUT_INVALID_ERROR="ExecutionProviderOutputInvalidError",a.PROVIDER_NOT_FOUND_ERROR="ProviderNotFoundError",a.PROVIDER_EXECUTION_FAILED_ERROR="ProviderExecutionFailedError",a.STEP_NOT_FOUND_ERROR="StepNotFoundError",a.STEP_ALREADY_EXISTS_ERROR="StepAlreadyExistsError",a.STEP_EXECUTION_FAILED_ERROR="StepExecutionFailedError",a.EXECUTION_STATE_CORRUPT_ERROR="ExecutionStateCorruptError",a.EXECUTION_EVENT_PAYLOAD_INVALID_ERROR="ExecutionEventPayloadInvalidError",a.EXECUTION_EVENT_CONTROL_INVALID_ERROR="ExecutionEventControlInvalidError",a.EXECUTION_STATE_CONTROL_INVALID_ERROR="ExecutionStateControlInvalidError",a.METHOD_NOT_ALLOWED_ERROR="MethodNotAllowedError",a.INVALID_ACTION_ERROR="InvalidActionError",a.MISSING_SECRET_KEY_ERROR="MissingSecretKeyError",a.SIGNATURE_MISMATCH_ERROR="SignatureMismatchError",a.SIGNATURE_NOT_FOUND_ERROR="SignatureNotFoundError",a.SIGNATURE_INVALID_ERROR="SignatureInvalidError",a.SIGNATURE_EXPIRED_ERROR="SignatureExpiredError",a.SIGNING_KEY_NOT_FOUND_ERROR="SigningKeyNotFoundError",a.PLATFORM_ERROR="PlatformError",a.SIGNATURE_VERSION_INVALID_ERROR="SignatureVersionInvalidError",a.WORKFLOW_PAYLOAD_INVALID_ERROR="WorkflowPayloadInvalidError",a))(O||{});var U=(r=>(r.POST="POST",r.GET="GET",r.OPTIONS="OPTIONS",r))(U||{});var h=class extends Error{data},L=class extends h{statusCode=404},R=class extends h{statusCode=400},T=class extends h{statusCode=401},m=class extends h{statusCode=500},b=class extends h{statusCode=409};var V=class extends R{code="ExecutionStateCorruptError";constructor(e,t){super(`Workflow with id: \`${e}\` has a corrupt state. Step with id: \`${t}\` does not exist. Please provide the missing state.`),this.data={workflowId:e,stepId:t};}},x=class extends R{code="ExecutionEventPayloadInvalidError";constructor(e,t){super(`Workflow with id: \`${e}\` has invalid \`payload\`. Please provide the correct event payload.`),this.data=t;}},F=class extends R{code="ExecutionEventControlInvalidError";constructor(e,t){super(`Workflow with id: \`${e}\` has invalid \`controls\`. Please provide the correct event controls.`),this.data=t;}},W=class extends R{code="ExecutionStateControlInvalidError";constructor(e,t,r){super(`Workflow with id: \`${e}\` has an invalid state. Step with id: \`${t}\` has invalid \`controls\`. Please provide the correct step controls.`),this.data=r;}},$=class extends R{code="ExecutionStateOutputInvalidError";constructor(e,t,r){super(`Workflow with id: \`${e}\` has an invalid state. Step with id: \`${t}\` has invalid output. Please provide the correct step output.`),this.data=r;}},M=class extends R{code="ExecutionStateResultInvalidError";constructor(e,t,r){super(`Workflow with id: \`${e}\` has an invalid state. Step with id: \`${t}\` has invalid result. Please provide the correct step result.`),this.data=r;}},G=class extends R{code="ExecutionProviderOutputInvalidError";constructor(e,t,r,o){super(`Workflow with id: \`${e}\` has an invalid state. Step with id: \`${t}\` and provider with id: \`${r}\` has invalid output. Please provide the correct provider output.`),this.data=o;}};var j=class extends Error{statusCode;message;code;constructor(e,t,r){super(r),this.statusCode=e,this.code=t;}};var d={info:s=>N__default.default.blue(s),warning:s=>N__default.default.yellow(s),error:s=>N__default.default.red(s),success:s=>N__default.default.green(s),underline:s=>N__default.default.underline(s),bold:s=>N__default.default.bold(s)},p={SUCCESS:d.success("\u2714"),ERROR:d.error("\u2717"),WARNING:d.warning("\u26A0"),INFO:d.info("\u2139"),ARROW:d.bold("\u2192"),MOCK:d.info("\u25CB"),HYDRATED:d.bold(d.info("\u2192")),STEP:d.info("\u03C3"),ACTION:d.info("\u03B1"),DURATION:d.info("\u0394"),PROVIDER:d.info("\u2699"),OUTPUT:d.info("\u21E2"),INPUT:d.info("\u21E0"),WORKFLOW:d.info("\u03C9"),STATE:d.info("\u03C3"),EXECUTE:d.info("\u03B5"),PREVIEW:d.info("\u03C1")};var de=s=>Object.values(s).map(e=>`\`${e}\``).join(", "),K=s=>s.replaceAll(/(\w)(\w*)/g,(e,t,r)=>t.toUpperCase()+r.toLowerCase()).replaceAll(/[\s-]+/g,"");var ue=(s,e="https://api.novu.co")=>{let t=process.env.NOVU_API_URL||e;return {post:async(r,o)=>{let i=await fetch(t+"/v1"+r,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`ApiKey ${s}`},body:JSON.stringify(o)}),n=await i.json();if(i.ok)return n;throw new j(n.statusCode,n.error,n.message)},delete:async r=>(await fetch(t+"/v1"+r,{method:"DELETE",headers:{"Content-Type":"application/json",Authorization:`ApiKey ${s}`}})).json()}};var Y=class extends h{code="MethodNotAllowedError";statusCode=405;message=`Method not allowed. Please use one of ${de(U)}`},g=class extends R{code="InvalidActionError";constructor(e,t){super(`Invalid query string: \`action\`=\`${e}\`. Please use one of ${de(t)}`);}};var X=class extends m{code="PlatformError";message="Something went wrong. Please try again later."};var y=class extends b{constructor(e,t){super(`${K(e)} with id: \`${t}\` already exists. Please use a different id.`);}},w=class extends L{constructor(e,t){super(`${K(e)} with id: \`${t}\` does not exist. Please provide a valid id.`);}},A=class extends m{constructor(e,t){super(`Failed to execute ${K(e)} with id: \`${t}\`. Please try again later.`);}};var J=class extends w{code="ProviderNotFoundError";constructor(e){super("provider",e);}},B=class extends A{code="ProviderExecutionFailedError";constructor(e){super("workflow",e);}};var q=class extends T{code="SignatureMismatchError";constructor(){super("Signature does not match the expected signature. Please ensure the signature provided in the `novu-signature` header is correct and try again.");}},z=class extends T{code="SignatureNotFoundError";constructor(){super("Signature not found. Please provide a signature in the `novu-signature` header");}},Z=class extends T{code="SignatureInvalidError";constructor(){super("Signature is invalid. Please provide a valid signature in the `novu-signature` header");}},Q=class extends T{code="SignatureExpiredError";constructor(){super(`Signature expired. Please provide a signature with a timestamp no older than ${5} minutes in the \`novu-signature\` header`);}},H=class extends T{code="SigningKeyNotFoundError";constructor(){super("Signature key not found. Please provide a valid key in the Client constructor `config.secretKey`");}};var ee=class extends w{code="StepNotFoundError";constructor(e){super("step",e);}};var S=class extends w{code="WorkflowNotFoundError";constructor(e){super("workflow",e);}},te=class extends y{code="WorkflowAlreadyExistsError";constructor(e){super("workflow",e);}};var re=class{ajv;compiledSchemas;constructor(){this.ajv=new Ne__default.default({useDefaults:!0,removeAdditional:"all"}),Ae__default.default(this.ajv),this.compiledSchemas=new Map;}isSchema(e){return typeof e=="boolean"?!1:e.type==="object"||!!e.anyOf||!!e.oneOf}async validate(e,t){let r=this.compiledSchemas.get(t);return r||(r=this.ajv.compile(t),this.compiledSchemas.set(t,r)),r(e)?{success:!0,data:e}:{success:!1,errors:r.errors.map(i=>({path:i.instancePath,message:i.message}))}}transformToJsonSchema(e){return e}};var oe=class{isSchema(e){return e.safeParseAsync!==void 0}async validate(e,t){let r=t.safeParse(e);return r.success?{success:!0,data:r.data}:{success:!1,errors:r.error.errors.map(o=>({path:`/${o.path.join("/")}`,message:o.message}))}}transformToJsonSchema(e){try{return zodToJsonSchema.zodToJsonSchema(e)}catch(t){throw t?.message?.includes("Cannot find module")&&console.error("Tried to use a zod schema in @novu/framework without `zod-to-json-schema` installed. Please install it by running `npm install zod-to-json-schema`."),t}}};var Ee=[new oe,new re],Oe=async(s,e)=>{for(let t of Ee)if(t.isSchema(s))return t.validate(e,s);throw new Error("Invalid schema")},he=s=>{for(let e of Ee)if(e.isSchema(s))return e.transformToJsonSchema(s);throw new Error("Invalid schema")};var Te={name:"@novu/framework",version:"2.0.0-canary.0",description:"The Code-First Notifications Workflow SDK.",main:"./dist/index.js",types:"./dist/index.d.ts",publishConfig:{registry:"https://registry.npmjs.org",access:"public"},private:!1,repository:{type:"git",url:"git+https://github.com/novuhq/novu.git"},files:["dist","README.md"],scripts:{preinstall:"npx only-allow pnpm",test:"vitest","test:watch":"vitest --watch",lint:"eslint src --ext .ts","lint:fix":"eslint src --ext .ts --fix",format:"prettier --check --ignore-path .gitignore .","format:fix":"prettier --write --ignore-path .gitignore .",build:"tsup","build:watch":"tsup --watch","$comment:bump:prerelease":"This is a workaround to support `npm version prerelease` with lerna","bump:prerelease":"npm version prerelease --preid=alpha & PID=$!; (sleep 1 && kill -9 $PID) & wait $PID","release:alpha":"pnpm bump:prerelease || pnpm build && npm publish"},keywords:["novu","code-first","workflows","durable","sdk","notifications","email","sms","push","webhooks","next","nuxt","h3","express"],author:"Novu Team <engineering@novu.co>",license:"ISC",exports:{".":{require:"./dist/index.js",import:"./dist/index.js",types:"./dist/index.d.ts"},"./express":{require:"./dist/express.js",import:"./dist/express.js",types:"./dist/express.d.ts"},"./next":{require:"./dist/next.js",import:"./dist/next.js",types:"./dist/next.d.ts"},"./nuxt":{require:"./dist/nuxt.js",import:"./dist/nuxt.js",types:"./dist/nuxt.d.ts"},"./h3":{require:"./dist/h3.js",import:"./dist/h3.js",types:"./dist/h3.d.ts"},"./sveltekit":{require:"./dist/sveltekit.js",import:"./dist/sveltekit.js",types:"./dist/sveltekit.d.ts"},"./remix":{require:"./dist/remix.js",import:"./dist/remix.js",types:"./dist/remix.d.ts"}},peerDependencies:{"@sveltejs/kit":">=1.27.3","@vercel/node":">=2.15.9",express:">=4.19.2",h3:">=1.8.1",next:">=12.0.0",zod:">=3.0.0","zod-to-json-schema":">=3.0.0"},peerDependenciesMeta:{"@sveltejs/kit":{optional:!0},"@vercel/node":{optional:!0},express:{optional:!0},fastify:{optional:!0},h3:{optional:!0},next:{optional:!0},zod:{optional:!0},"zod-to-json-schema":{optional:!0}},devDependencies:{"@sveltejs/kit":"^1.27.3","@types/express":"^4.17.13","@types/json-schema":"^7.0.15","@types/node":"^20.11.20","@vercel/node":"^2.15.9",express:"^4.19.2",h3:"^1.11.1",next:"^13.5.4",prettier:"^3.2.5","ts-node":"^10.9.2",tsup:"^8.0.2",typescript:"^5.3.3",vitest:"^1.2.1",zod:"^3.23.0","zod-to-json-schema":"^3.23.0"},dependencies:{"@novu/shared":"workspace:*",ajv:"^8.12.0","ajv-formats":"^2.1.1","better-ajv-errors":"^1.2.0",chalk:"^4.1.2","cross-fetch":"^4.0.0","json-schema-faker":"^0.5.6","json-schema-to-ts":"^3.0.0",liquidjs:"^10.13.1",ora:"^5.4.1"}};var P=Te.version,se="2024-06-26";jsonSchemaFaker.JSONSchemaFaker.random.shuffle=function(){return ["[placeholder]"]};jsonSchemaFaker.JSONSchemaFaker.option({useDefaultValue:!0,alwaysFakeOptionals:!0});function ye(){return process.env.NODE_ENV==="development"}var ne=class{discoveredWorkflows=[];templateEngine=new liquidjs.Liquid;secretKey;version=P;strictAuthentication;constructor(e){let t=this.buildOptions(e);this.secretKey=t.secretKey,this.strictAuthentication=t.strictAuthentication;}buildOptions(e){let t={secretKey:void 0,strictAuthentication:!ye()};return t.secretKey=e?.secretKey||process.env.NOVU_SECRET_KEY||process.env.NOVU_API_KEY,e?.strictAuthentication!==void 0?t.strictAuthentication=e.strictAuthentication:process.env.NOVU_STRICT_AUTHENTICATION_ENABLED!==void 0&&(t.strictAuthentication=process.env.NOVU_STRICT_AUTHENTICATION_ENABLED==="true"),t}addWorkflows(e){for(let t of e){if(this.discoveredWorkflows.some(r=>r.workflowId===t.definition.workflowId))throw new te(t.definition.workflowId);this.discoveredWorkflows.push(t.definition);}}healthCheck(){let e=this.discoveredWorkflows.length,t=this.discoveredWorkflows.reduce((r,o)=>r+o.steps.length,0);return {status:"ok",sdkVersion:P,frameworkVersion:se,discovered:{workflows:e,steps:t}}}getWorkflow(e){let t=this.discoveredWorkflows.find(r=>r.workflowId===e);if(t)return t;throw new S(e)}getStep(e,t){let o=this.getWorkflow(e).steps.find(i=>i.stepId===t);if(o)return o;throw new ee(t)}getRegisteredWorkflows(){return this.discoveredWorkflows}discover(){return {workflows:this.getRegisteredWorkflows()}}mock(e){return jsonSchemaFaker.JSONSchemaFaker.generate(he(e))}async validate(e,t,r,o,i,n,l){let c=await Oe(t,e);if(c.success)return c.data;switch(r){case"event":this.throwInvalidEvent(o,i,c.errors);case"step":this.throwInvalidStep(n,o,i,c.errors);case"provider":this.throwInvalidProvider(n,l,o,i,c.errors);default:throw new Error(`Invalid component: '${r}'`)}}throwInvalidProvider(e,t,r,o,i){if(!e)throw new Error("stepId is required");if(!t)throw new Error("providerId is required");switch(r){case"output":throw new G(o,e,t,i);default:throw new Error(`Invalid payload type: '${r}'`)}}throwInvalidStep(e,t,r,o){if(!e)throw new Error("stepId is required");switch(t){case"output":throw new $(r,e,o);case"result":throw new M(r,e,o);case"controls":throw new W(r,e,o);default:throw new Error(`Invalid payload type: '${t}'`)}}throwInvalidEvent(e,t,r){switch(e){case"controls":throw new F(t,r);case"payload":throw new x(t,r);default:throw new Error(`Invalid payload type: '${e}'`)}}executeStepFactory(e,t){return async(r,o,i)=>{let n=this.getStep(e.workflowId,r),l=Se(e),c=await this.createStepControls(n,l),E=e.action==="preview";if(!E&&await this.shouldSkip(i?.skip,c))return t({options:{skip:!0}}),{};let u=this.previewStep.bind(this),I=this.executeStep.bind(this),C=await(E?u:I)(e,{...n,providers:n.providers.map(f=>{let v=i?.providers?.[f.type];if(!v)throw new J(f.type);return {...f,resolve:v}}),resolve:o});return r===e.stepId&&t(C),C.outputs}}async shouldSkip(e,t){return e?e(t):!1}async executeWorkflow(e){let o=`${{execute:"Executing",preview:"Previewing"}[e.action]} workflowId:`;console.log(`
21
+ var D=(r=>(r.TRIGGER="trigger",r.EXECUTE="execute",r.PREVIEW="preview",r))(D||{}),k=(r=>(r.DISCOVER="discover",r.HEALTH_CHECK="health-check",r.CODE="code",r))(k||{});var O=(a=>(a.WORKFLOW_NOT_FOUND_ERROR="WorkflowNotFoundError",a.WORKFLOW_ALREADY_EXISTS_ERROR="WorkflowAlreadyExistsError",a.WORKFLOW_EXECUTION_FAILED_ERROR="WorkflowExecutionFailedError",a.EXECUTION_STATE_OUTPUT_INVALID_ERROR="ExecutionStateOutputInvalidError",a.EXECUTION_STATE_RESULT_INVALID_ERROR="ExecutionStateResultInvalidError",a.EXECUTION_PROVIDER_OUTPUT_INVALID_ERROR="ExecutionProviderOutputInvalidError",a.PROVIDER_NOT_FOUND_ERROR="ProviderNotFoundError",a.PROVIDER_EXECUTION_FAILED_ERROR="ProviderExecutionFailedError",a.STEP_NOT_FOUND_ERROR="StepNotFoundError",a.STEP_ALREADY_EXISTS_ERROR="StepAlreadyExistsError",a.STEP_EXECUTION_FAILED_ERROR="StepExecutionFailedError",a.EXECUTION_STATE_CORRUPT_ERROR="ExecutionStateCorruptError",a.EXECUTION_EVENT_PAYLOAD_INVALID_ERROR="ExecutionEventPayloadInvalidError",a.EXECUTION_EVENT_CONTROL_INVALID_ERROR="ExecutionEventControlInvalidError",a.EXECUTION_STATE_CONTROL_INVALID_ERROR="ExecutionStateControlInvalidError",a.METHOD_NOT_ALLOWED_ERROR="MethodNotAllowedError",a.INVALID_ACTION_ERROR="InvalidActionError",a.MISSING_SECRET_KEY_ERROR="MissingSecretKeyError",a.SIGNATURE_MISMATCH_ERROR="SignatureMismatchError",a.SIGNATURE_NOT_FOUND_ERROR="SignatureNotFoundError",a.SIGNATURE_INVALID_ERROR="SignatureInvalidError",a.SIGNATURE_EXPIRED_ERROR="SignatureExpiredError",a.SIGNING_KEY_NOT_FOUND_ERROR="SigningKeyNotFoundError",a.PLATFORM_ERROR="PlatformError",a.SIGNATURE_VERSION_INVALID_ERROR="SignatureVersionInvalidError",a.WORKFLOW_PAYLOAD_INVALID_ERROR="WorkflowPayloadInvalidError",a))(O||{});var U=(r=>(r.POST="POST",r.GET="GET",r.OPTIONS="OPTIONS",r))(U||{});var h=class extends Error{data},L=class extends h{statusCode=404},R=class extends h{statusCode=400},T=class extends h{statusCode=401},m=class extends h{statusCode=500},b=class extends h{statusCode=409};var V=class extends R{code="ExecutionStateCorruptError";constructor(e,t){super(`Workflow with id: \`${e}\` has a corrupt state. Step with id: \`${t}\` does not exist. Please provide the missing state.`),this.data={workflowId:e,stepId:t};}},x=class extends R{code="ExecutionEventPayloadInvalidError";constructor(e,t){super(`Workflow with id: \`${e}\` has invalid \`payload\`. Please provide the correct event payload.`),this.data=t;}},F=class extends R{code="ExecutionEventControlInvalidError";constructor(e,t){super(`Workflow with id: \`${e}\` has invalid \`controls\`. Please provide the correct event controls.`),this.data=t;}},W=class extends R{code="ExecutionStateControlInvalidError";constructor(e,t,r){super(`Workflow with id: \`${e}\` has an invalid state. Step with id: \`${t}\` has invalid \`controls\`. Please provide the correct step controls.`),this.data=r;}},$=class extends R{code="ExecutionStateOutputInvalidError";constructor(e,t,r){super(`Workflow with id: \`${e}\` has an invalid state. Step with id: \`${t}\` has invalid output. Please provide the correct step output.`),this.data=r;}},M=class extends R{code="ExecutionStateResultInvalidError";constructor(e,t,r){super(`Workflow with id: \`${e}\` has an invalid state. Step with id: \`${t}\` has invalid result. Please provide the correct step result.`),this.data=r;}},G=class extends R{code="ExecutionProviderOutputInvalidError";constructor(e,t,r,o){super(`Workflow with id: \`${e}\` has an invalid state. Step with id: \`${t}\` and provider with id: \`${r}\` has invalid output. Please provide the correct provider output.`),this.data=o;}};var j=class extends Error{statusCode;message;code;constructor(e,t,r){super(r),this.statusCode=e,this.code=t;}};var d={info:s=>N__default.default.blue(s),warning:s=>N__default.default.yellow(s),error:s=>N__default.default.red(s),success:s=>N__default.default.green(s),underline:s=>N__default.default.underline(s),bold:s=>N__default.default.bold(s)},p={SUCCESS:d.success("\u2714"),ERROR:d.error("\u2717"),WARNING:d.warning("\u26A0"),INFO:d.info("\u2139"),ARROW:d.bold("\u2192"),MOCK:d.info("\u25CB"),HYDRATED:d.bold(d.info("\u2192")),STEP:d.info("\u03C3"),ACTION:d.info("\u03B1"),DURATION:d.info("\u0394"),PROVIDER:d.info("\u2699"),OUTPUT:d.info("\u21E2"),INPUT:d.info("\u21E0"),WORKFLOW:d.info("\u03C9"),STATE:d.info("\u03C3"),EXECUTE:d.info("\u03B5"),PREVIEW:d.info("\u03C1")};var de=s=>Object.values(s).map(e=>`\`${e}\``).join(", "),K=s=>s.replaceAll(/(\w)(\w*)/g,(e,t,r)=>t.toUpperCase()+r.toLowerCase()).replaceAll(/[\s-]+/g,"");var ue=(s,e="https://api.novu.co")=>{let t=process.env.NOVU_API_URL||e;return {post:async(r,o)=>{let i=await fetch(t+"/v1"+r,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`ApiKey ${s}`},body:JSON.stringify(o)}),n=await i.json();if(i.ok)return n;throw new j(n.statusCode,n.error,n.message)},delete:async r=>(await fetch(t+"/v1"+r,{method:"DELETE",headers:{"Content-Type":"application/json",Authorization:`ApiKey ${s}`}})).json()}};var Y=class extends h{code="MethodNotAllowedError";statusCode=405;message=`Method not allowed. Please use one of ${de(U)}`},g=class extends R{code="InvalidActionError";constructor(e,t){super(`Invalid query string: \`action\`=\`${e}\`. Please use one of ${de(t)}`);}};var X=class extends m{code="PlatformError";message="Something went wrong. Please try again later."};var y=class extends b{constructor(e,t){super(`${K(e)} with id: \`${t}\` already exists. Please use a different id.`);}},w=class extends L{constructor(e,t){super(`${K(e)} with id: \`${t}\` does not exist. Please provide a valid id.`);}},A=class extends m{constructor(e,t){super(`Failed to execute ${K(e)} with id: \`${t}\`. Please try again later.`);}};var J=class extends w{code="ProviderNotFoundError";constructor(e){super("provider",e);}},B=class extends A{code="ProviderExecutionFailedError";constructor(e){super("workflow",e);}};var q=class extends T{code="SignatureMismatchError";constructor(){super("Signature does not match the expected signature. Please ensure the signature provided in the `novu-signature` header is correct and try again.");}},z=class extends T{code="SignatureNotFoundError";constructor(){super("Signature not found. Please provide a signature in the `novu-signature` header");}},Z=class extends T{code="SignatureInvalidError";constructor(){super("Signature is invalid. Please provide a valid signature in the `novu-signature` header");}},Q=class extends T{code="SignatureExpiredError";constructor(){super(`Signature expired. Please provide a signature with a timestamp no older than ${5} minutes in the \`novu-signature\` header`);}},H=class extends T{code="SigningKeyNotFoundError";constructor(){super("Signature key not found. Please provide a valid key in the Client constructor `config.secretKey`");}};var ee=class extends w{code="StepNotFoundError";constructor(e){super("step",e);}};var S=class extends w{code="WorkflowNotFoundError";constructor(e){super("workflow",e);}},te=class extends y{code="WorkflowAlreadyExistsError";constructor(e){super("workflow",e);}};var re=class{ajv;compiledSchemas;constructor(){this.ajv=new Ne__default.default({useDefaults:!0,removeAdditional:"all"}),Ae__default.default(this.ajv),this.compiledSchemas=new Map;}isSchema(e){return typeof e=="boolean"?!1:e.type==="object"||!!e.anyOf||!!e.oneOf}async validate(e,t){let r=this.compiledSchemas.get(t);return r||(r=this.ajv.compile(t),this.compiledSchemas.set(t,r)),r(e)?{success:!0,data:e}:{success:!1,errors:r.errors.map(i=>({path:i.instancePath,message:i.message}))}}transformToJsonSchema(e){return e}};var oe=class{isSchema(e){return e.safeParseAsync!==void 0}async validate(e,t){let r=t.safeParse(e);return r.success?{success:!0,data:r.data}:{success:!1,errors:r.error.errors.map(o=>({path:`/${o.path.join("/")}`,message:o.message}))}}transformToJsonSchema(e){try{return zodToJsonSchema.zodToJsonSchema(e)}catch(t){throw t?.message?.includes("Cannot find module")&&console.error("Tried to use a zod schema in @novu/framework without `zod-to-json-schema` installed. Please install it by running `npm install zod-to-json-schema`."),t}}};var Ee=[new oe,new re],Oe=async(s,e)=>{for(let t of Ee)if(t.isSchema(s))return t.validate(e,s);throw new Error("Invalid schema")},he=s=>{for(let e of Ee)if(e.isSchema(s))return e.transformToJsonSchema(s);throw new Error("Invalid schema")};var Te={name:"@novu/framework",version:"2.0.0-canary.2",description:"The Code-First Notifications Workflow SDK.",main:"./dist/index.js",types:"./dist/index.d.ts",publishConfig:{registry:"https://registry.npmjs.org",access:"public"},private:!1,repository:{type:"git",url:"git+https://github.com/novuhq/novu.git"},files:["dist","README.md"],scripts:{preinstall:"npx only-allow pnpm",test:"vitest","test:watch":"vitest --watch",lint:"eslint src --ext .ts","lint:fix":"eslint src --ext .ts --fix",format:"prettier --check --ignore-path .gitignore .","format:fix":"prettier --write --ignore-path .gitignore .",build:"tsup","build:watch":"tsup --watch","$comment:bump:prerelease":"This is a workaround to support `npm version prerelease` with lerna","bump:prerelease":"npm version prerelease --preid=alpha & PID=$!; (sleep 1 && kill -9 $PID) & wait $PID","release:alpha":"pnpm bump:prerelease || pnpm build && npm publish"},keywords:["novu","code-first","workflows","durable","sdk","notifications","email","sms","push","webhooks","next","nuxt","h3","express"],author:"Novu Team <engineering@novu.co>",license:"ISC",exports:{".":{require:"./dist/index.js",import:"./dist/index.js",types:"./dist/index.d.ts"},"./express":{require:"./dist/express.js",import:"./dist/express.js",types:"./dist/express.d.ts"},"./next":{require:"./dist/next.js",import:"./dist/next.js",types:"./dist/next.d.ts"},"./nuxt":{require:"./dist/nuxt.js",import:"./dist/nuxt.js",types:"./dist/nuxt.d.ts"},"./h3":{require:"./dist/h3.js",import:"./dist/h3.js",types:"./dist/h3.d.ts"},"./sveltekit":{require:"./dist/sveltekit.js",import:"./dist/sveltekit.js",types:"./dist/sveltekit.d.ts"},"./remix":{require:"./dist/remix.js",import:"./dist/remix.js",types:"./dist/remix.d.ts"}},peerDependencies:{"@sveltejs/kit":">=1.27.3","@vercel/node":">=2.15.9",express:">=4.19.2",h3:">=1.8.1",next:">=12.0.0",zod:">=3.0.0","zod-to-json-schema":">=3.0.0"},peerDependenciesMeta:{"@sveltejs/kit":{optional:!0},"@vercel/node":{optional:!0},express:{optional:!0},fastify:{optional:!0},h3:{optional:!0},next:{optional:!0},zod:{optional:!0},"zod-to-json-schema":{optional:!0}},devDependencies:{"@sveltejs/kit":"^1.27.3","@types/express":"^4.17.13","@types/json-schema":"^7.0.15","@types/node":"^20.11.20","@vercel/node":"^2.15.9",express:"^4.19.2",h3:"^1.11.1",next:"^13.5.4",prettier:"^3.2.5","ts-node":"^10.9.2",tsup:"^8.0.2",typescript:"^5.3.3",vitest:"^1.2.1",zod:"^3.23.0","zod-to-json-schema":"^3.23.0"},dependencies:{"@novu/shared":"^2.0.0-canary.0",ajv:"^8.12.0","ajv-formats":"^2.1.1","better-ajv-errors":"^1.2.0",chalk:"^4.1.2","cross-fetch":"^4.0.0","json-schema-faker":"^0.5.6","json-schema-to-ts":"^3.0.0",liquidjs:"^10.13.1",ora:"^5.4.1"}};var P=Te.version,se="2024-06-26";jsonSchemaFaker.JSONSchemaFaker.random.shuffle=function(){return ["[placeholder]"]};jsonSchemaFaker.JSONSchemaFaker.option({useDefaultValue:!0,alwaysFakeOptionals:!0});function ye(){return process.env.NODE_ENV==="development"}var ne=class{discoveredWorkflows=[];templateEngine=new liquidjs.Liquid;secretKey;version=P;strictAuthentication;constructor(e){let t=this.buildOptions(e);this.secretKey=t.secretKey,this.strictAuthentication=t.strictAuthentication;}buildOptions(e){let t={secretKey:void 0,strictAuthentication:!ye()};return t.secretKey=e?.secretKey||process.env.NOVU_SECRET_KEY||process.env.NOVU_API_KEY,e?.strictAuthentication!==void 0?t.strictAuthentication=e.strictAuthentication:process.env.NOVU_STRICT_AUTHENTICATION_ENABLED!==void 0&&(t.strictAuthentication=process.env.NOVU_STRICT_AUTHENTICATION_ENABLED==="true"),t}addWorkflows(e){for(let t of e){if(this.discoveredWorkflows.some(r=>r.workflowId===t.definition.workflowId))throw new te(t.definition.workflowId);this.discoveredWorkflows.push(t.definition);}}healthCheck(){let e=this.discoveredWorkflows.length,t=this.discoveredWorkflows.reduce((r,o)=>r+o.steps.length,0);return {status:"ok",sdkVersion:P,frameworkVersion:se,discovered:{workflows:e,steps:t}}}getWorkflow(e){let t=this.discoveredWorkflows.find(r=>r.workflowId===e);if(t)return t;throw new S(e)}getStep(e,t){let o=this.getWorkflow(e).steps.find(i=>i.stepId===t);if(o)return o;throw new ee(t)}getRegisteredWorkflows(){return this.discoveredWorkflows}discover(){return {workflows:this.getRegisteredWorkflows()}}mock(e){return jsonSchemaFaker.JSONSchemaFaker.generate(he(e))}async validate(e,t,r,o,i,n,l){let c=await Oe(t,e);if(c.success)return c.data;switch(r){case"event":this.throwInvalidEvent(o,i,c.errors);case"step":this.throwInvalidStep(n,o,i,c.errors);case"provider":this.throwInvalidProvider(n,l,o,i,c.errors);default:throw new Error(`Invalid component: '${r}'`)}}throwInvalidProvider(e,t,r,o,i){if(!e)throw new Error("stepId is required");if(!t)throw new Error("providerId is required");switch(r){case"output":throw new G(o,e,t,i);default:throw new Error(`Invalid payload type: '${r}'`)}}throwInvalidStep(e,t,r,o){if(!e)throw new Error("stepId is required");switch(t){case"output":throw new $(r,e,o);case"result":throw new M(r,e,o);case"controls":throw new W(r,e,o);default:throw new Error(`Invalid payload type: '${t}'`)}}throwInvalidEvent(e,t,r){switch(e){case"controls":throw new F(t,r);case"payload":throw new x(t,r);default:throw new Error(`Invalid payload type: '${e}'`)}}executeStepFactory(e,t){return async(r,o,i)=>{let n=this.getStep(e.workflowId,r),l=Se(e),c=await this.createStepControls(n,l),E=e.action==="preview";if(!E&&await this.shouldSkip(i?.skip,c))return t({options:{skip:!0}}),{};let u=this.previewStep.bind(this),I=this.executeStep.bind(this),C=await(E?u:I)(e,{...n,providers:n.providers.map(f=>{let v=i?.providers?.[f.type];if(!v)throw new J(f.type);return {...f,resolve:v}}),resolve:o});return r===e.stepId&&t(C),C.outputs}}async shouldSkip(e,t){return e?e(t):!1}async executeWorkflow(e){let o=`${{execute:"Executing",preview:"Previewing"}[e.action]} workflowId:`;console.log(`
22
22
  ${d.bold(d.underline(o))} '${e.workflowId}'`);let i=this.getWorkflow(e.workflowId),n=process.hrtime(),l={outputs:{},providers:{},options:{}},c,E=new Promise(_=>{c=_;}),u=_=>{c(),l=_;},I;try{if(e.action==="execute"&&!e.payload&&!e.data)throw new x(e.workflowId,{message:"Event `payload` is required"});let _=await this.createExecutionPayload(e,i);await Promise.race([E,i.execute({payload:_,environment:{},inputs:{},controls:{},subscriber:e.subscriber,step:{email:this.executeStepFactory(e,u),sms:this.executeStepFactory(e,u),inApp:this.executeStepFactory(e,u),digest:this.executeStepFactory(e,u),delay:this.executeStepFactory(e,u),push:this.executeStepFactory(e,u),chat:this.executeStepFactory(e,u),custom:this.executeStepFactory(e,u)}})]);}catch(_){I=_;}let ce=process.hrtime(n),C=ce[0],f=ce[1],v=C*1e3+f/1e6,Ie=I?p.ERROR:p.SUCCESS,_e=e.action==="execute"?"Executed":e.action==="preview"?"Previewed":"Invalid action";if(console.log(`${Ie} ${_e} workflowId: \`${e.workflowId}\``),this.prettyPrintExecute(e,v,I),I)throw I;return {outputs:l.outputs,providers:l.providers,options:l.options,metadata:{status:"success",error:!1,duration:v}}}async createExecutionPayload(e,t){let r=e.payload||e.data;if(e.action==="preview"){let i=this.mock(t.payload.schema);r=Object.assign(i,r);}return await this.validate(r,t.payload.unknownSchema,"event","payload",e.workflowId)}prettyPrintExecute(e,t,r){let o=r?p.ERROR:p.SUCCESS,i=e.action==="execute"?"Executed":e.action==="preview"?"Previewed":"Invalid action",n=r?"Failed to execute":i,l=r?d.error:d.success,c=`${o} ${n} workflowId: '${e.workflowId}`;console.log(`
23
23
  ${d.bold(l(c))}'`),console.log(` \u251C ${p.STEP} stepId: '${e.stepId}'`),console.log(` \u251C ${p.ACTION} action: '${e.action}'`),console.log(` \u2514 ${p.DURATION} duration: '${t.toFixed(2)}ms'
24
24
  `);}async executeProviders(e,t,r){return t.providers.reduce(async(o,i)=>{let n=await o,l=this.previewProvider.bind(this),c=this.executeProvider.bind(this),u=await(e.action==="preview"?l:c)(e,t,i,r);return {...n,[i.type]:u}},Promise.resolve({}))}previewProvider(e,t,r,o){return console.log(` ${p.MOCK} Mocked provider: \`${r.type}\``),this.mock(r.outputs.schema)}async executeProvider(e,t,r,o){let i=ie__default.default({indent:2}).start(`Executing provider: \`${r.type}\``);try{if(e.stepId===t.stepId){let n=await this.createStepControls(t,e),l=await r.resolve({controls:n,outputs:o}),c=await this.validate(l,r.outputs.unknownSchema,"step","output",e.workflowId,t.stepId,r.type);return i.succeed(`Executed provider: \`${r.type}\``),c}else i.stopAndPersist({symbol:p.HYDRATED,text:`Hydrated provider: \`${r.type}\``});}catch(n){throw i.stopAndPersist({symbol:p.ERROR,text:`Failed to execute provider: \`${r.type}\``}),new B(`Failed to execute provider: '${r.type}'.
package/dist/remix.d.ts CHANGED
@@ -4,6 +4,26 @@ import 'zod';
4
4
  import '@novu/shared';
5
5
 
6
6
  declare const frameworkName: SupportedFrameworkName;
7
+ /**
8
+ * In Remix, serve and register any declared workflows with Novu, making them
9
+ * available to be triggered by events.
10
+ *
11
+ * Remix requires that you export both a "loader" for serving `GET` requests,
12
+ * and an "action" for serving other requests, therefore exporting both is
13
+ * required.
14
+ *
15
+ * See {@link https://remix.run/docs/en/v1/guides/resource-routes}
16
+ *
17
+ * @example
18
+ * ```ts
19
+ * import { serve } from "@novu/framework/remix";
20
+ * import { myWorkflow } from "./src/novu/workflows";
21
+ *
22
+ * const handler = serve({ workflows: [myWorkflow] });
23
+ *
24
+ * export { handler as loader, handler as action };
25
+ * ```
26
+ */
7
27
  declare const serve: (options: ServeHandlerOptions) => ((ctx: {
8
28
  request: Request;
9
29
  context?: unknown;
package/dist/remix.js CHANGED
@@ -17,7 +17,7 @@ var N__default = /*#__PURE__*/_interopDefault(N);
17
17
  var Ae__default = /*#__PURE__*/_interopDefault(Ae);
18
18
  var ve__default = /*#__PURE__*/_interopDefault(ve);
19
19
 
20
- var D=(r=>(r.TRIGGER="trigger",r.EXECUTE="execute",r.PREVIEW="preview",r))(D||{}),k=(r=>(r.DISCOVER="discover",r.HEALTH_CHECK="health-check",r.CODE="code",r))(k||{});var O=(a=>(a.WORKFLOW_NOT_FOUND_ERROR="WorkflowNotFoundError",a.WORKFLOW_ALREADY_EXISTS_ERROR="WorkflowAlreadyExistsError",a.WORKFLOW_EXECUTION_FAILED_ERROR="WorkflowExecutionFailedError",a.EXECUTION_STATE_OUTPUT_INVALID_ERROR="ExecutionStateOutputInvalidError",a.EXECUTION_STATE_RESULT_INVALID_ERROR="ExecutionStateResultInvalidError",a.EXECUTION_PROVIDER_OUTPUT_INVALID_ERROR="ExecutionProviderOutputInvalidError",a.PROVIDER_NOT_FOUND_ERROR="ProviderNotFoundError",a.PROVIDER_EXECUTION_FAILED_ERROR="ProviderExecutionFailedError",a.STEP_NOT_FOUND_ERROR="StepNotFoundError",a.STEP_ALREADY_EXISTS_ERROR="StepAlreadyExistsError",a.STEP_EXECUTION_FAILED_ERROR="StepExecutionFailedError",a.EXECUTION_STATE_CORRUPT_ERROR="ExecutionStateCorruptError",a.EXECUTION_EVENT_PAYLOAD_INVALID_ERROR="ExecutionEventPayloadInvalidError",a.EXECUTION_EVENT_CONTROL_INVALID_ERROR="ExecutionEventControlInvalidError",a.EXECUTION_STATE_CONTROL_INVALID_ERROR="ExecutionStateControlInvalidError",a.METHOD_NOT_ALLOWED_ERROR="MethodNotAllowedError",a.INVALID_ACTION_ERROR="InvalidActionError",a.MISSING_SECRET_KEY_ERROR="MissingSecretKeyError",a.SIGNATURE_MISMATCH_ERROR="SignatureMismatchError",a.SIGNATURE_NOT_FOUND_ERROR="SignatureNotFoundError",a.SIGNATURE_INVALID_ERROR="SignatureInvalidError",a.SIGNATURE_EXPIRED_ERROR="SignatureExpiredError",a.SIGNING_KEY_NOT_FOUND_ERROR="SigningKeyNotFoundError",a.PLATFORM_ERROR="PlatformError",a.SIGNATURE_VERSION_INVALID_ERROR="SignatureVersionInvalidError",a.WORKFLOW_PAYLOAD_INVALID_ERROR="WorkflowPayloadInvalidError",a))(O||{});var U=(r=>(r.POST="POST",r.GET="GET",r.OPTIONS="OPTIONS",r))(U||{});var h=class extends Error{data},L=class extends h{statusCode=404},R=class extends h{statusCode=400},T=class extends h{statusCode=401},m=class extends h{statusCode=500},b=class extends h{statusCode=409};var V=class extends R{code="ExecutionStateCorruptError";constructor(e,t){super(`Workflow with id: \`${e}\` has a corrupt state. Step with id: \`${t}\` does not exist. Please provide the missing state.`),this.data={workflowId:e,stepId:t};}},x=class extends R{code="ExecutionEventPayloadInvalidError";constructor(e,t){super(`Workflow with id: \`${e}\` has invalid \`payload\`. Please provide the correct event payload.`),this.data=t;}},F=class extends R{code="ExecutionEventControlInvalidError";constructor(e,t){super(`Workflow with id: \`${e}\` has invalid \`controls\`. Please provide the correct event controls.`),this.data=t;}},W=class extends R{code="ExecutionStateControlInvalidError";constructor(e,t,r){super(`Workflow with id: \`${e}\` has an invalid state. Step with id: \`${t}\` has invalid \`controls\`. Please provide the correct step controls.`),this.data=r;}},$=class extends R{code="ExecutionStateOutputInvalidError";constructor(e,t,r){super(`Workflow with id: \`${e}\` has an invalid state. Step with id: \`${t}\` has invalid output. Please provide the correct step output.`),this.data=r;}},M=class extends R{code="ExecutionStateResultInvalidError";constructor(e,t,r){super(`Workflow with id: \`${e}\` has an invalid state. Step with id: \`${t}\` has invalid result. Please provide the correct step result.`),this.data=r;}},G=class extends R{code="ExecutionProviderOutputInvalidError";constructor(e,t,r,o){super(`Workflow with id: \`${e}\` has an invalid state. Step with id: \`${t}\` and provider with id: \`${r}\` has invalid output. Please provide the correct provider output.`),this.data=o;}};var j=class extends Error{statusCode;message;code;constructor(e,t,r){super(r),this.statusCode=e,this.code=t;}};var ue=()=>typeof Response<"u"?Response:crossFetch.Response;var d={info:s=>N__default.default.blue(s),warning:s=>N__default.default.yellow(s),error:s=>N__default.default.red(s),success:s=>N__default.default.green(s),underline:s=>N__default.default.underline(s),bold:s=>N__default.default.bold(s)},p={SUCCESS:d.success("\u2714"),ERROR:d.error("\u2717"),WARNING:d.warning("\u26A0"),INFO:d.info("\u2139"),ARROW:d.bold("\u2192"),MOCK:d.info("\u25CB"),HYDRATED:d.bold(d.info("\u2192")),STEP:d.info("\u03C3"),ACTION:d.info("\u03B1"),DURATION:d.info("\u0394"),PROVIDER:d.info("\u2699"),OUTPUT:d.info("\u21E2"),INPUT:d.info("\u21E0"),WORKFLOW:d.info("\u03C9"),STATE:d.info("\u03C3"),EXECUTE:d.info("\u03B5"),PREVIEW:d.info("\u03C1")};var de=s=>Object.values(s).map(e=>`\`${e}\``).join(", "),K=s=>s.replaceAll(/(\w)(\w*)/g,(e,t,r)=>t.toUpperCase()+r.toLowerCase()).replaceAll(/[\s-]+/g,"");var Re=(s,e="https://api.novu.co")=>{let t=process.env.NOVU_API_URL||e;return {post:async(r,o)=>{let i=await fetch(t+"/v1"+r,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`ApiKey ${s}`},body:JSON.stringify(o)}),n=await i.json();if(i.ok)return n;throw new j(n.statusCode,n.error,n.message)},delete:async r=>(await fetch(t+"/v1"+r,{method:"DELETE",headers:{"Content-Type":"application/json",Authorization:`ApiKey ${s}`}})).json()}};var Y=class extends h{code="MethodNotAllowedError";statusCode=405;message=`Method not allowed. Please use one of ${de(U)}`},g=class extends R{code="InvalidActionError";constructor(e,t){super(`Invalid query string: \`action\`=\`${e}\`. Please use one of ${de(t)}`);}};var X=class extends m{code="PlatformError";message="Something went wrong. Please try again later."};var y=class extends b{constructor(e,t){super(`${K(e)} with id: \`${t}\` already exists. Please use a different id.`);}},w=class extends L{constructor(e,t){super(`${K(e)} with id: \`${t}\` does not exist. Please provide a valid id.`);}},A=class extends m{constructor(e,t){super(`Failed to execute ${K(e)} with id: \`${t}\`. Please try again later.`);}};var J=class extends w{code="ProviderNotFoundError";constructor(e){super("provider",e);}},B=class extends A{code="ProviderExecutionFailedError";constructor(e){super("workflow",e);}};var q=class extends T{code="SignatureMismatchError";constructor(){super("Signature does not match the expected signature. Please ensure the signature provided in the `novu-signature` header is correct and try again.");}},z=class extends T{code="SignatureNotFoundError";constructor(){super("Signature not found. Please provide a signature in the `novu-signature` header");}},Z=class extends T{code="SignatureInvalidError";constructor(){super("Signature is invalid. Please provide a valid signature in the `novu-signature` header");}},Q=class extends T{code="SignatureExpiredError";constructor(){super(`Signature expired. Please provide a signature with a timestamp no older than ${5} minutes in the \`novu-signature\` header`);}},H=class extends T{code="SigningKeyNotFoundError";constructor(){super("Signature key not found. Please provide a valid key in the Client constructor `config.secretKey`");}};var ee=class extends w{code="StepNotFoundError";constructor(e){super("step",e);}};var S=class extends w{code="WorkflowNotFoundError";constructor(e){super("workflow",e);}},te=class extends y{code="WorkflowAlreadyExistsError";constructor(e){super("workflow",e);}};var re=class{ajv;compiledSchemas;constructor(){this.ajv=new Ae__default.default({useDefaults:!0,removeAdditional:"all"}),ve__default.default(this.ajv),this.compiledSchemas=new Map;}isSchema(e){return typeof e=="boolean"?!1:e.type==="object"||!!e.anyOf||!!e.oneOf}async validate(e,t){let r=this.compiledSchemas.get(t);return r||(r=this.ajv.compile(t),this.compiledSchemas.set(t,r)),r(e)?{success:!0,data:e}:{success:!1,errors:r.errors.map(i=>({path:i.instancePath,message:i.message}))}}transformToJsonSchema(e){return e}};var oe=class{isSchema(e){return e.safeParseAsync!==void 0}async validate(e,t){let r=t.safeParse(e);return r.success?{success:!0,data:r.data}:{success:!1,errors:r.error.errors.map(o=>({path:`/${o.path.join("/")}`,message:o.message}))}}transformToJsonSchema(e){try{return zodToJsonSchema.zodToJsonSchema(e)}catch(t){throw t?.message?.includes("Cannot find module")&&console.error("Tried to use a zod schema in @novu/framework without `zod-to-json-schema` installed. Please install it by running `npm install zod-to-json-schema`."),t}}};var Oe=[new oe,new re],he=async(s,e)=>{for(let t of Oe)if(t.isSchema(s))return t.validate(e,s);throw new Error("Invalid schema")},Te=s=>{for(let e of Oe)if(e.isSchema(s))return e.transformToJsonSchema(s);throw new Error("Invalid schema")};var we={name:"@novu/framework",version:"2.0.0-canary.0",description:"The Code-First Notifications Workflow SDK.",main:"./dist/index.js",types:"./dist/index.d.ts",publishConfig:{registry:"https://registry.npmjs.org",access:"public"},private:!1,repository:{type:"git",url:"git+https://github.com/novuhq/novu.git"},files:["dist","README.md"],scripts:{preinstall:"npx only-allow pnpm",test:"vitest","test:watch":"vitest --watch",lint:"eslint src --ext .ts","lint:fix":"eslint src --ext .ts --fix",format:"prettier --check --ignore-path .gitignore .","format:fix":"prettier --write --ignore-path .gitignore .",build:"tsup","build:watch":"tsup --watch","$comment:bump:prerelease":"This is a workaround to support `npm version prerelease` with lerna","bump:prerelease":"npm version prerelease --preid=alpha & PID=$!; (sleep 1 && kill -9 $PID) & wait $PID","release:alpha":"pnpm bump:prerelease || pnpm build && npm publish"},keywords:["novu","code-first","workflows","durable","sdk","notifications","email","sms","push","webhooks","next","nuxt","h3","express"],author:"Novu Team <engineering@novu.co>",license:"ISC",exports:{".":{require:"./dist/index.js",import:"./dist/index.js",types:"./dist/index.d.ts"},"./express":{require:"./dist/express.js",import:"./dist/express.js",types:"./dist/express.d.ts"},"./next":{require:"./dist/next.js",import:"./dist/next.js",types:"./dist/next.d.ts"},"./nuxt":{require:"./dist/nuxt.js",import:"./dist/nuxt.js",types:"./dist/nuxt.d.ts"},"./h3":{require:"./dist/h3.js",import:"./dist/h3.js",types:"./dist/h3.d.ts"},"./sveltekit":{require:"./dist/sveltekit.js",import:"./dist/sveltekit.js",types:"./dist/sveltekit.d.ts"},"./remix":{require:"./dist/remix.js",import:"./dist/remix.js",types:"./dist/remix.d.ts"}},peerDependencies:{"@sveltejs/kit":">=1.27.3","@vercel/node":">=2.15.9",express:">=4.19.2",h3:">=1.8.1",next:">=12.0.0",zod:">=3.0.0","zod-to-json-schema":">=3.0.0"},peerDependenciesMeta:{"@sveltejs/kit":{optional:!0},"@vercel/node":{optional:!0},express:{optional:!0},fastify:{optional:!0},h3:{optional:!0},next:{optional:!0},zod:{optional:!0},"zod-to-json-schema":{optional:!0}},devDependencies:{"@sveltejs/kit":"^1.27.3","@types/express":"^4.17.13","@types/json-schema":"^7.0.15","@types/node":"^20.11.20","@vercel/node":"^2.15.9",express:"^4.19.2",h3:"^1.11.1",next:"^13.5.4",prettier:"^3.2.5","ts-node":"^10.9.2",tsup:"^8.0.2",typescript:"^5.3.3",vitest:"^1.2.1",zod:"^3.23.0","zod-to-json-schema":"^3.23.0"},dependencies:{"@novu/shared":"workspace:*",ajv:"^8.12.0","ajv-formats":"^2.1.1","better-ajv-errors":"^1.2.0",chalk:"^4.1.2","cross-fetch":"^4.0.0","json-schema-faker":"^0.5.6","json-schema-to-ts":"^3.0.0",liquidjs:"^10.13.1",ora:"^5.4.1"}};var P=we.version,se="2024-06-26";jsonSchemaFaker.JSONSchemaFaker.random.shuffle=function(){return ["[placeholder]"]};jsonSchemaFaker.JSONSchemaFaker.option({useDefaultValue:!0,alwaysFakeOptionals:!0});function Se(){return process.env.NODE_ENV==="development"}var ne=class{discoveredWorkflows=[];templateEngine=new liquidjs.Liquid;secretKey;version=P;strictAuthentication;constructor(e){let t=this.buildOptions(e);this.secretKey=t.secretKey,this.strictAuthentication=t.strictAuthentication;}buildOptions(e){let t={secretKey:void 0,strictAuthentication:!Se()};return t.secretKey=e?.secretKey||process.env.NOVU_SECRET_KEY||process.env.NOVU_API_KEY,e?.strictAuthentication!==void 0?t.strictAuthentication=e.strictAuthentication:process.env.NOVU_STRICT_AUTHENTICATION_ENABLED!==void 0&&(t.strictAuthentication=process.env.NOVU_STRICT_AUTHENTICATION_ENABLED==="true"),t}addWorkflows(e){for(let t of e){if(this.discoveredWorkflows.some(r=>r.workflowId===t.definition.workflowId))throw new te(t.definition.workflowId);this.discoveredWorkflows.push(t.definition);}}healthCheck(){let e=this.discoveredWorkflows.length,t=this.discoveredWorkflows.reduce((r,o)=>r+o.steps.length,0);return {status:"ok",sdkVersion:P,frameworkVersion:se,discovered:{workflows:e,steps:t}}}getWorkflow(e){let t=this.discoveredWorkflows.find(r=>r.workflowId===e);if(t)return t;throw new S(e)}getStep(e,t){let o=this.getWorkflow(e).steps.find(i=>i.stepId===t);if(o)return o;throw new ee(t)}getRegisteredWorkflows(){return this.discoveredWorkflows}discover(){return {workflows:this.getRegisteredWorkflows()}}mock(e){return jsonSchemaFaker.JSONSchemaFaker.generate(Te(e))}async validate(e,t,r,o,i,n,l){let c=await he(t,e);if(c.success)return c.data;switch(r){case"event":this.throwInvalidEvent(o,i,c.errors);case"step":this.throwInvalidStep(n,o,i,c.errors);case"provider":this.throwInvalidProvider(n,l,o,i,c.errors);default:throw new Error(`Invalid component: '${r}'`)}}throwInvalidProvider(e,t,r,o,i){if(!e)throw new Error("stepId is required");if(!t)throw new Error("providerId is required");switch(r){case"output":throw new G(o,e,t,i);default:throw new Error(`Invalid payload type: '${r}'`)}}throwInvalidStep(e,t,r,o){if(!e)throw new Error("stepId is required");switch(t){case"output":throw new $(r,e,o);case"result":throw new M(r,e,o);case"controls":throw new W(r,e,o);default:throw new Error(`Invalid payload type: '${t}'`)}}throwInvalidEvent(e,t,r){switch(e){case"controls":throw new F(t,r);case"payload":throw new x(t,r);default:throw new Error(`Invalid payload type: '${e}'`)}}executeStepFactory(e,t){return async(r,o,i)=>{let n=this.getStep(e.workflowId,r),l=Pe(e),c=await this.createStepControls(n,l),E=e.action==="preview";if(!E&&await this.shouldSkip(i?.skip,c))return t({options:{skip:!0}}),{};let u=this.previewStep.bind(this),I=this.executeStep.bind(this),C=await(E?u:I)(e,{...n,providers:n.providers.map(f=>{let v=i?.providers?.[f.type];if(!v)throw new J(f.type);return {...f,resolve:v}}),resolve:o});return r===e.stepId&&t(C),C.outputs}}async shouldSkip(e,t){return e?e(t):!1}async executeWorkflow(e){let o=`${{execute:"Executing",preview:"Previewing"}[e.action]} workflowId:`;console.log(`
20
+ var D=(r=>(r.TRIGGER="trigger",r.EXECUTE="execute",r.PREVIEW="preview",r))(D||{}),k=(r=>(r.DISCOVER="discover",r.HEALTH_CHECK="health-check",r.CODE="code",r))(k||{});var O=(a=>(a.WORKFLOW_NOT_FOUND_ERROR="WorkflowNotFoundError",a.WORKFLOW_ALREADY_EXISTS_ERROR="WorkflowAlreadyExistsError",a.WORKFLOW_EXECUTION_FAILED_ERROR="WorkflowExecutionFailedError",a.EXECUTION_STATE_OUTPUT_INVALID_ERROR="ExecutionStateOutputInvalidError",a.EXECUTION_STATE_RESULT_INVALID_ERROR="ExecutionStateResultInvalidError",a.EXECUTION_PROVIDER_OUTPUT_INVALID_ERROR="ExecutionProviderOutputInvalidError",a.PROVIDER_NOT_FOUND_ERROR="ProviderNotFoundError",a.PROVIDER_EXECUTION_FAILED_ERROR="ProviderExecutionFailedError",a.STEP_NOT_FOUND_ERROR="StepNotFoundError",a.STEP_ALREADY_EXISTS_ERROR="StepAlreadyExistsError",a.STEP_EXECUTION_FAILED_ERROR="StepExecutionFailedError",a.EXECUTION_STATE_CORRUPT_ERROR="ExecutionStateCorruptError",a.EXECUTION_EVENT_PAYLOAD_INVALID_ERROR="ExecutionEventPayloadInvalidError",a.EXECUTION_EVENT_CONTROL_INVALID_ERROR="ExecutionEventControlInvalidError",a.EXECUTION_STATE_CONTROL_INVALID_ERROR="ExecutionStateControlInvalidError",a.METHOD_NOT_ALLOWED_ERROR="MethodNotAllowedError",a.INVALID_ACTION_ERROR="InvalidActionError",a.MISSING_SECRET_KEY_ERROR="MissingSecretKeyError",a.SIGNATURE_MISMATCH_ERROR="SignatureMismatchError",a.SIGNATURE_NOT_FOUND_ERROR="SignatureNotFoundError",a.SIGNATURE_INVALID_ERROR="SignatureInvalidError",a.SIGNATURE_EXPIRED_ERROR="SignatureExpiredError",a.SIGNING_KEY_NOT_FOUND_ERROR="SigningKeyNotFoundError",a.PLATFORM_ERROR="PlatformError",a.SIGNATURE_VERSION_INVALID_ERROR="SignatureVersionInvalidError",a.WORKFLOW_PAYLOAD_INVALID_ERROR="WorkflowPayloadInvalidError",a))(O||{});var U=(r=>(r.POST="POST",r.GET="GET",r.OPTIONS="OPTIONS",r))(U||{});var h=class extends Error{data},L=class extends h{statusCode=404},R=class extends h{statusCode=400},T=class extends h{statusCode=401},m=class extends h{statusCode=500},b=class extends h{statusCode=409};var V=class extends R{code="ExecutionStateCorruptError";constructor(e,t){super(`Workflow with id: \`${e}\` has a corrupt state. Step with id: \`${t}\` does not exist. Please provide the missing state.`),this.data={workflowId:e,stepId:t};}},x=class extends R{code="ExecutionEventPayloadInvalidError";constructor(e,t){super(`Workflow with id: \`${e}\` has invalid \`payload\`. Please provide the correct event payload.`),this.data=t;}},F=class extends R{code="ExecutionEventControlInvalidError";constructor(e,t){super(`Workflow with id: \`${e}\` has invalid \`controls\`. Please provide the correct event controls.`),this.data=t;}},W=class extends R{code="ExecutionStateControlInvalidError";constructor(e,t,r){super(`Workflow with id: \`${e}\` has an invalid state. Step with id: \`${t}\` has invalid \`controls\`. Please provide the correct step controls.`),this.data=r;}},$=class extends R{code="ExecutionStateOutputInvalidError";constructor(e,t,r){super(`Workflow with id: \`${e}\` has an invalid state. Step with id: \`${t}\` has invalid output. Please provide the correct step output.`),this.data=r;}},M=class extends R{code="ExecutionStateResultInvalidError";constructor(e,t,r){super(`Workflow with id: \`${e}\` has an invalid state. Step with id: \`${t}\` has invalid result. Please provide the correct step result.`),this.data=r;}},G=class extends R{code="ExecutionProviderOutputInvalidError";constructor(e,t,r,o){super(`Workflow with id: \`${e}\` has an invalid state. Step with id: \`${t}\` and provider with id: \`${r}\` has invalid output. Please provide the correct provider output.`),this.data=o;}};var j=class extends Error{statusCode;message;code;constructor(e,t,r){super(r),this.statusCode=e,this.code=t;}};var ue=()=>typeof Response<"u"?Response:crossFetch.Response;var d={info:s=>N__default.default.blue(s),warning:s=>N__default.default.yellow(s),error:s=>N__default.default.red(s),success:s=>N__default.default.green(s),underline:s=>N__default.default.underline(s),bold:s=>N__default.default.bold(s)},p={SUCCESS:d.success("\u2714"),ERROR:d.error("\u2717"),WARNING:d.warning("\u26A0"),INFO:d.info("\u2139"),ARROW:d.bold("\u2192"),MOCK:d.info("\u25CB"),HYDRATED:d.bold(d.info("\u2192")),STEP:d.info("\u03C3"),ACTION:d.info("\u03B1"),DURATION:d.info("\u0394"),PROVIDER:d.info("\u2699"),OUTPUT:d.info("\u21E2"),INPUT:d.info("\u21E0"),WORKFLOW:d.info("\u03C9"),STATE:d.info("\u03C3"),EXECUTE:d.info("\u03B5"),PREVIEW:d.info("\u03C1")};var de=s=>Object.values(s).map(e=>`\`${e}\``).join(", "),K=s=>s.replaceAll(/(\w)(\w*)/g,(e,t,r)=>t.toUpperCase()+r.toLowerCase()).replaceAll(/[\s-]+/g,"");var Re=(s,e="https://api.novu.co")=>{let t=process.env.NOVU_API_URL||e;return {post:async(r,o)=>{let i=await fetch(t+"/v1"+r,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`ApiKey ${s}`},body:JSON.stringify(o)}),n=await i.json();if(i.ok)return n;throw new j(n.statusCode,n.error,n.message)},delete:async r=>(await fetch(t+"/v1"+r,{method:"DELETE",headers:{"Content-Type":"application/json",Authorization:`ApiKey ${s}`}})).json()}};var Y=class extends h{code="MethodNotAllowedError";statusCode=405;message=`Method not allowed. Please use one of ${de(U)}`},g=class extends R{code="InvalidActionError";constructor(e,t){super(`Invalid query string: \`action\`=\`${e}\`. Please use one of ${de(t)}`);}};var X=class extends m{code="PlatformError";message="Something went wrong. Please try again later."};var y=class extends b{constructor(e,t){super(`${K(e)} with id: \`${t}\` already exists. Please use a different id.`);}},w=class extends L{constructor(e,t){super(`${K(e)} with id: \`${t}\` does not exist. Please provide a valid id.`);}},A=class extends m{constructor(e,t){super(`Failed to execute ${K(e)} with id: \`${t}\`. Please try again later.`);}};var J=class extends w{code="ProviderNotFoundError";constructor(e){super("provider",e);}},B=class extends A{code="ProviderExecutionFailedError";constructor(e){super("workflow",e);}};var q=class extends T{code="SignatureMismatchError";constructor(){super("Signature does not match the expected signature. Please ensure the signature provided in the `novu-signature` header is correct and try again.");}},z=class extends T{code="SignatureNotFoundError";constructor(){super("Signature not found. Please provide a signature in the `novu-signature` header");}},Z=class extends T{code="SignatureInvalidError";constructor(){super("Signature is invalid. Please provide a valid signature in the `novu-signature` header");}},Q=class extends T{code="SignatureExpiredError";constructor(){super(`Signature expired. Please provide a signature with a timestamp no older than ${5} minutes in the \`novu-signature\` header`);}},H=class extends T{code="SigningKeyNotFoundError";constructor(){super("Signature key not found. Please provide a valid key in the Client constructor `config.secretKey`");}};var ee=class extends w{code="StepNotFoundError";constructor(e){super("step",e);}};var S=class extends w{code="WorkflowNotFoundError";constructor(e){super("workflow",e);}},te=class extends y{code="WorkflowAlreadyExistsError";constructor(e){super("workflow",e);}};var re=class{ajv;compiledSchemas;constructor(){this.ajv=new Ae__default.default({useDefaults:!0,removeAdditional:"all"}),ve__default.default(this.ajv),this.compiledSchemas=new Map;}isSchema(e){return typeof e=="boolean"?!1:e.type==="object"||!!e.anyOf||!!e.oneOf}async validate(e,t){let r=this.compiledSchemas.get(t);return r||(r=this.ajv.compile(t),this.compiledSchemas.set(t,r)),r(e)?{success:!0,data:e}:{success:!1,errors:r.errors.map(i=>({path:i.instancePath,message:i.message}))}}transformToJsonSchema(e){return e}};var oe=class{isSchema(e){return e.safeParseAsync!==void 0}async validate(e,t){let r=t.safeParse(e);return r.success?{success:!0,data:r.data}:{success:!1,errors:r.error.errors.map(o=>({path:`/${o.path.join("/")}`,message:o.message}))}}transformToJsonSchema(e){try{return zodToJsonSchema.zodToJsonSchema(e)}catch(t){throw t?.message?.includes("Cannot find module")&&console.error("Tried to use a zod schema in @novu/framework without `zod-to-json-schema` installed. Please install it by running `npm install zod-to-json-schema`."),t}}};var Oe=[new oe,new re],he=async(s,e)=>{for(let t of Oe)if(t.isSchema(s))return t.validate(e,s);throw new Error("Invalid schema")},Te=s=>{for(let e of Oe)if(e.isSchema(s))return e.transformToJsonSchema(s);throw new Error("Invalid schema")};var we={name:"@novu/framework",version:"2.0.0-canary.2",description:"The Code-First Notifications Workflow SDK.",main:"./dist/index.js",types:"./dist/index.d.ts",publishConfig:{registry:"https://registry.npmjs.org",access:"public"},private:!1,repository:{type:"git",url:"git+https://github.com/novuhq/novu.git"},files:["dist","README.md"],scripts:{preinstall:"npx only-allow pnpm",test:"vitest","test:watch":"vitest --watch",lint:"eslint src --ext .ts","lint:fix":"eslint src --ext .ts --fix",format:"prettier --check --ignore-path .gitignore .","format:fix":"prettier --write --ignore-path .gitignore .",build:"tsup","build:watch":"tsup --watch","$comment:bump:prerelease":"This is a workaround to support `npm version prerelease` with lerna","bump:prerelease":"npm version prerelease --preid=alpha & PID=$!; (sleep 1 && kill -9 $PID) & wait $PID","release:alpha":"pnpm bump:prerelease || pnpm build && npm publish"},keywords:["novu","code-first","workflows","durable","sdk","notifications","email","sms","push","webhooks","next","nuxt","h3","express"],author:"Novu Team <engineering@novu.co>",license:"ISC",exports:{".":{require:"./dist/index.js",import:"./dist/index.js",types:"./dist/index.d.ts"},"./express":{require:"./dist/express.js",import:"./dist/express.js",types:"./dist/express.d.ts"},"./next":{require:"./dist/next.js",import:"./dist/next.js",types:"./dist/next.d.ts"},"./nuxt":{require:"./dist/nuxt.js",import:"./dist/nuxt.js",types:"./dist/nuxt.d.ts"},"./h3":{require:"./dist/h3.js",import:"./dist/h3.js",types:"./dist/h3.d.ts"},"./sveltekit":{require:"./dist/sveltekit.js",import:"./dist/sveltekit.js",types:"./dist/sveltekit.d.ts"},"./remix":{require:"./dist/remix.js",import:"./dist/remix.js",types:"./dist/remix.d.ts"}},peerDependencies:{"@sveltejs/kit":">=1.27.3","@vercel/node":">=2.15.9",express:">=4.19.2",h3:">=1.8.1",next:">=12.0.0",zod:">=3.0.0","zod-to-json-schema":">=3.0.0"},peerDependenciesMeta:{"@sveltejs/kit":{optional:!0},"@vercel/node":{optional:!0},express:{optional:!0},fastify:{optional:!0},h3:{optional:!0},next:{optional:!0},zod:{optional:!0},"zod-to-json-schema":{optional:!0}},devDependencies:{"@sveltejs/kit":"^1.27.3","@types/express":"^4.17.13","@types/json-schema":"^7.0.15","@types/node":"^20.11.20","@vercel/node":"^2.15.9",express:"^4.19.2",h3:"^1.11.1",next:"^13.5.4",prettier:"^3.2.5","ts-node":"^10.9.2",tsup:"^8.0.2",typescript:"^5.3.3",vitest:"^1.2.1",zod:"^3.23.0","zod-to-json-schema":"^3.23.0"},dependencies:{"@novu/shared":"^2.0.0-canary.0",ajv:"^8.12.0","ajv-formats":"^2.1.1","better-ajv-errors":"^1.2.0",chalk:"^4.1.2","cross-fetch":"^4.0.0","json-schema-faker":"^0.5.6","json-schema-to-ts":"^3.0.0",liquidjs:"^10.13.1",ora:"^5.4.1"}};var P=we.version,se="2024-06-26";jsonSchemaFaker.JSONSchemaFaker.random.shuffle=function(){return ["[placeholder]"]};jsonSchemaFaker.JSONSchemaFaker.option({useDefaultValue:!0,alwaysFakeOptionals:!0});function Se(){return process.env.NODE_ENV==="development"}var ne=class{discoveredWorkflows=[];templateEngine=new liquidjs.Liquid;secretKey;version=P;strictAuthentication;constructor(e){let t=this.buildOptions(e);this.secretKey=t.secretKey,this.strictAuthentication=t.strictAuthentication;}buildOptions(e){let t={secretKey:void 0,strictAuthentication:!Se()};return t.secretKey=e?.secretKey||process.env.NOVU_SECRET_KEY||process.env.NOVU_API_KEY,e?.strictAuthentication!==void 0?t.strictAuthentication=e.strictAuthentication:process.env.NOVU_STRICT_AUTHENTICATION_ENABLED!==void 0&&(t.strictAuthentication=process.env.NOVU_STRICT_AUTHENTICATION_ENABLED==="true"),t}addWorkflows(e){for(let t of e){if(this.discoveredWorkflows.some(r=>r.workflowId===t.definition.workflowId))throw new te(t.definition.workflowId);this.discoveredWorkflows.push(t.definition);}}healthCheck(){let e=this.discoveredWorkflows.length,t=this.discoveredWorkflows.reduce((r,o)=>r+o.steps.length,0);return {status:"ok",sdkVersion:P,frameworkVersion:se,discovered:{workflows:e,steps:t}}}getWorkflow(e){let t=this.discoveredWorkflows.find(r=>r.workflowId===e);if(t)return t;throw new S(e)}getStep(e,t){let o=this.getWorkflow(e).steps.find(i=>i.stepId===t);if(o)return o;throw new ee(t)}getRegisteredWorkflows(){return this.discoveredWorkflows}discover(){return {workflows:this.getRegisteredWorkflows()}}mock(e){return jsonSchemaFaker.JSONSchemaFaker.generate(Te(e))}async validate(e,t,r,o,i,n,l){let c=await he(t,e);if(c.success)return c.data;switch(r){case"event":this.throwInvalidEvent(o,i,c.errors);case"step":this.throwInvalidStep(n,o,i,c.errors);case"provider":this.throwInvalidProvider(n,l,o,i,c.errors);default:throw new Error(`Invalid component: '${r}'`)}}throwInvalidProvider(e,t,r,o,i){if(!e)throw new Error("stepId is required");if(!t)throw new Error("providerId is required");switch(r){case"output":throw new G(o,e,t,i);default:throw new Error(`Invalid payload type: '${r}'`)}}throwInvalidStep(e,t,r,o){if(!e)throw new Error("stepId is required");switch(t){case"output":throw new $(r,e,o);case"result":throw new M(r,e,o);case"controls":throw new W(r,e,o);default:throw new Error(`Invalid payload type: '${t}'`)}}throwInvalidEvent(e,t,r){switch(e){case"controls":throw new F(t,r);case"payload":throw new x(t,r);default:throw new Error(`Invalid payload type: '${e}'`)}}executeStepFactory(e,t){return async(r,o,i)=>{let n=this.getStep(e.workflowId,r),l=Pe(e),c=await this.createStepControls(n,l),E=e.action==="preview";if(!E&&await this.shouldSkip(i?.skip,c))return t({options:{skip:!0}}),{};let u=this.previewStep.bind(this),I=this.executeStep.bind(this),C=await(E?u:I)(e,{...n,providers:n.providers.map(f=>{let v=i?.providers?.[f.type];if(!v)throw new J(f.type);return {...f,resolve:v}}),resolve:o});return r===e.stepId&&t(C),C.outputs}}async shouldSkip(e,t){return e?e(t):!1}async executeWorkflow(e){let o=`${{execute:"Executing",preview:"Previewing"}[e.action]} workflowId:`;console.log(`
21
21
  ${d.bold(d.underline(o))} '${e.workflowId}'`);let i=this.getWorkflow(e.workflowId),n=process.hrtime(),l={outputs:{},providers:{},options:{}},c,E=new Promise(_=>{c=_;}),u=_=>{c(),l=_;},I;try{if(e.action==="execute"&&!e.payload&&!e.data)throw new x(e.workflowId,{message:"Event `payload` is required"});let _=await this.createExecutionPayload(e,i);await Promise.race([E,i.execute({payload:_,environment:{},inputs:{},controls:{},subscriber:e.subscriber,step:{email:this.executeStepFactory(e,u),sms:this.executeStepFactory(e,u),inApp:this.executeStepFactory(e,u),digest:this.executeStepFactory(e,u),delay:this.executeStepFactory(e,u),push:this.executeStepFactory(e,u),chat:this.executeStepFactory(e,u),custom:this.executeStepFactory(e,u)}})]);}catch(_){I=_;}let ce=process.hrtime(n),C=ce[0],f=ce[1],v=C*1e3+f/1e6,Ie=I?p.ERROR:p.SUCCESS,_e=e.action==="execute"?"Executed":e.action==="preview"?"Previewed":"Invalid action";if(console.log(`${Ie} ${_e} workflowId: \`${e.workflowId}\``),this.prettyPrintExecute(e,v,I),I)throw I;return {outputs:l.outputs,providers:l.providers,options:l.options,metadata:{status:"success",error:!1,duration:v}}}async createExecutionPayload(e,t){let r=e.payload||e.data;if(e.action==="preview"){let i=this.mock(t.payload.schema);r=Object.assign(i,r);}return await this.validate(r,t.payload.unknownSchema,"event","payload",e.workflowId)}prettyPrintExecute(e,t,r){let o=r?p.ERROR:p.SUCCESS,i=e.action==="execute"?"Executed":e.action==="preview"?"Previewed":"Invalid action",n=r?"Failed to execute":i,l=r?d.error:d.success,c=`${o} ${n} workflowId: '${e.workflowId}`;console.log(`
22
22
  ${d.bold(l(c))}'`),console.log(` \u251C ${p.STEP} stepId: '${e.stepId}'`),console.log(` \u251C ${p.ACTION} action: '${e.action}'`),console.log(` \u2514 ${p.DURATION} duration: '${t.toFixed(2)}ms'
23
23
  `);}async executeProviders(e,t,r){return t.providers.reduce(async(o,i)=>{let n=await o,l=this.previewProvider.bind(this),c=this.executeProvider.bind(this),u=await(e.action==="preview"?l:c)(e,t,i,r);return {...n,[i.type]:u}},Promise.resolve({}))}previewProvider(e,t,r,o){return console.log(` ${p.MOCK} Mocked provider: \`${r.type}\``),this.mock(r.outputs.schema)}async executeProvider(e,t,r,o){let i=ie__default.default({indent:2}).start(`Executing provider: \`${r.type}\``);try{if(e.stepId===t.stepId){let n=await this.createStepControls(t,e),l=await r.resolve({controls:n,outputs:o}),c=await this.validate(l,r.outputs.unknownSchema,"step","output",e.workflowId,t.stepId,r.type);return i.succeed(`Executed provider: \`${r.type}\``),c}else i.stopAndPersist({symbol:p.HYDRATED,text:`Hydrated provider: \`${r.type}\``});}catch(n){throw i.stopAndPersist({symbol:p.ERROR,text:`Failed to execute provider: \`${r.type}\``}),new B(`Failed to execute provider: '${r.type}'.
@@ -5,10 +5,25 @@ import 'zod';
5
5
  import '@novu/shared';
6
6
 
7
7
  declare const frameworkName: SupportedFrameworkName;
8
+ /**
9
+ * Using SvelteKit, serve and register any declared workflows with Novu,
10
+ * making them available to be triggered by events.
11
+ *
12
+ * @example
13
+ * ```ts
14
+ * // app/routes/api/novu/+server.ts
15
+ * import { serve } from "@novu/framework/sveltekit";
16
+ * import { myWorkflow } from "./src/novu/workflows"; // Your workflows
17
+ *
18
+ * const handler = serve({ workflows: [myWorkflow] });
19
+ *
20
+ * export { handler as action, handler as loader };
21
+ * ```
22
+ */
8
23
  declare const serve: (options: ServeHandlerOptions) => ((event: RequestEvent) => Promise<Response>) & {
9
24
  GET: (event: RequestEvent) => Promise<Response>;
10
25
  POST: (event: RequestEvent) => Promise<Response>;
11
- PUT: (event: RequestEvent) => Promise<Response>;
26
+ OPTIONS: (event: RequestEvent) => Promise<Response>;
12
27
  };
13
28
 
14
29
  export { frameworkName, serve };
package/dist/sveltekit.js CHANGED
@@ -5,23 +5,23 @@ var jsonSchemaFaker = require('json-schema-faker');
5
5
  var liquidjs = require('liquidjs');
6
6
  var ie = require('ora');
7
7
  var crossFetch = require('cross-fetch');
8
- var v = require('chalk');
9
- var Ne = require('ajv');
8
+ var N = require('chalk');
9
+ var ve = require('ajv');
10
10
  var Ae = require('ajv-formats');
11
11
  var zodToJsonSchema = require('zod-to-json-schema');
12
12
 
13
13
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
14
14
 
15
15
  var ie__default = /*#__PURE__*/_interopDefault(ie);
16
- var v__default = /*#__PURE__*/_interopDefault(v);
17
- var Ne__default = /*#__PURE__*/_interopDefault(Ne);
16
+ var N__default = /*#__PURE__*/_interopDefault(N);
17
+ var ve__default = /*#__PURE__*/_interopDefault(ve);
18
18
  var Ae__default = /*#__PURE__*/_interopDefault(Ae);
19
19
 
20
- var D=(r=>(r.TRIGGER="trigger",r.EXECUTE="execute",r.PREVIEW="preview",r))(D||{}),k=(r=>(r.DISCOVER="discover",r.HEALTH_CHECK="health-check",r.CODE="code",r))(k||{});var O=(d=>(d.WORKFLOW_NOT_FOUND_ERROR="WorkflowNotFoundError",d.WORKFLOW_ALREADY_EXISTS_ERROR="WorkflowAlreadyExistsError",d.WORKFLOW_EXECUTION_FAILED_ERROR="WorkflowExecutionFailedError",d.EXECUTION_STATE_OUTPUT_INVALID_ERROR="ExecutionStateOutputInvalidError",d.EXECUTION_STATE_RESULT_INVALID_ERROR="ExecutionStateResultInvalidError",d.EXECUTION_PROVIDER_OUTPUT_INVALID_ERROR="ExecutionProviderOutputInvalidError",d.PROVIDER_NOT_FOUND_ERROR="ProviderNotFoundError",d.PROVIDER_EXECUTION_FAILED_ERROR="ProviderExecutionFailedError",d.STEP_NOT_FOUND_ERROR="StepNotFoundError",d.STEP_ALREADY_EXISTS_ERROR="StepAlreadyExistsError",d.STEP_EXECUTION_FAILED_ERROR="StepExecutionFailedError",d.EXECUTION_STATE_CORRUPT_ERROR="ExecutionStateCorruptError",d.EXECUTION_EVENT_PAYLOAD_INVALID_ERROR="ExecutionEventPayloadInvalidError",d.EXECUTION_EVENT_CONTROL_INVALID_ERROR="ExecutionEventControlInvalidError",d.EXECUTION_STATE_CONTROL_INVALID_ERROR="ExecutionStateControlInvalidError",d.METHOD_NOT_ALLOWED_ERROR="MethodNotAllowedError",d.INVALID_ACTION_ERROR="InvalidActionError",d.MISSING_SECRET_KEY_ERROR="MissingSecretKeyError",d.SIGNATURE_MISMATCH_ERROR="SignatureMismatchError",d.SIGNATURE_NOT_FOUND_ERROR="SignatureNotFoundError",d.SIGNATURE_INVALID_ERROR="SignatureInvalidError",d.SIGNATURE_EXPIRED_ERROR="SignatureExpiredError",d.SIGNING_KEY_NOT_FOUND_ERROR="SigningKeyNotFoundError",d.PLATFORM_ERROR="PlatformError",d.SIGNATURE_VERSION_INVALID_ERROR="SignatureVersionInvalidError",d.WORKFLOW_PAYLOAD_INVALID_ERROR="WorkflowPayloadInvalidError",d))(O||{});var U=(r=>(r.POST="POST",r.GET="GET",r.OPTIONS="OPTIONS",r))(U||{});var h=class extends Error{data},L=class extends h{statusCode=404},E=class extends h{statusCode=400},T=class extends h{statusCode=401},m=class extends h{statusCode=500},b=class extends h{statusCode=409};var V=class extends E{code="ExecutionStateCorruptError";constructor(e,t){super(`Workflow with id: \`${e}\` has a corrupt state. Step with id: \`${t}\` does not exist. Please provide the missing state.`),this.data={workflowId:e,stepId:t};}},x=class extends E{code="ExecutionEventPayloadInvalidError";constructor(e,t){super(`Workflow with id: \`${e}\` has invalid \`payload\`. Please provide the correct event payload.`),this.data=t;}},F=class extends E{code="ExecutionEventControlInvalidError";constructor(e,t){super(`Workflow with id: \`${e}\` has invalid \`controls\`. Please provide the correct event controls.`),this.data=t;}},W=class extends E{code="ExecutionStateControlInvalidError";constructor(e,t,r){super(`Workflow with id: \`${e}\` has an invalid state. Step with id: \`${t}\` has invalid \`controls\`. Please provide the correct step controls.`),this.data=r;}},$=class extends E{code="ExecutionStateOutputInvalidError";constructor(e,t,r){super(`Workflow with id: \`${e}\` has an invalid state. Step with id: \`${t}\` has invalid output. Please provide the correct step output.`),this.data=r;}},M=class extends E{code="ExecutionStateResultInvalidError";constructor(e,t,r){super(`Workflow with id: \`${e}\` has an invalid state. Step with id: \`${t}\` has invalid result. Please provide the correct step result.`),this.data=r;}},G=class extends E{code="ExecutionProviderOutputInvalidError";constructor(e,t,r,s){super(`Workflow with id: \`${e}\` has an invalid state. Step with id: \`${t}\` and provider with id: \`${r}\` has invalid output. Please provide the correct provider output.`),this.data=s;}};var j=class extends Error{statusCode;message;code;constructor(e,t,r){super(r),this.statusCode=e,this.code=t;}};var ue=()=>typeof Response<"u"?Response:crossFetch.Response;var l={info:o=>v__default.default.blue(o),warning:o=>v__default.default.yellow(o),error:o=>v__default.default.red(o),success:o=>v__default.default.green(o),underline:o=>v__default.default.underline(o),bold:o=>v__default.default.bold(o)},u={SUCCESS:l.success("\u2714"),ERROR:l.error("\u2717"),WARNING:l.warning("\u26A0"),INFO:l.info("\u2139"),ARROW:l.bold("\u2192"),MOCK:l.info("\u25CB"),HYDRATED:l.bold(l.info("\u2192")),STEP:l.info("\u03C3"),ACTION:l.info("\u03B1"),DURATION:l.info("\u0394"),PROVIDER:l.info("\u2699"),OUTPUT:l.info("\u21E2"),INPUT:l.info("\u21E0"),WORKFLOW:l.info("\u03C9"),STATE:l.info("\u03C3"),EXECUTE:l.info("\u03B5"),PREVIEW:l.info("\u03C1")};var de=o=>Object.values(o).map(e=>`\`${e}\``).join(", "),K=o=>o.replaceAll(/(\w)(\w*)/g,(e,t,r)=>t.toUpperCase()+r.toLowerCase()).replaceAll(/[\s-]+/g,"");var Re=(o,e="https://api.novu.co")=>{let t=process.env.NOVU_API_URL||e;return {post:async(r,s)=>{let i=await fetch(t+"/v1"+r,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`ApiKey ${o}`},body:JSON.stringify(s)}),n=await i.json();if(i.ok)return n;throw new j(n.statusCode,n.error,n.message)},delete:async r=>(await fetch(t+"/v1"+r,{method:"DELETE",headers:{"Content-Type":"application/json",Authorization:`ApiKey ${o}`}})).json()}};var Y=class extends h{code="MethodNotAllowedError";statusCode=405;message=`Method not allowed. Please use one of ${de(U)}`},g=class extends E{code="InvalidActionError";constructor(e,t){super(`Invalid query string: \`action\`=\`${e}\`. Please use one of ${de(t)}`);}};var X=class extends m{code="PlatformError";message="Something went wrong. Please try again later."};var y=class extends b{constructor(e,t){super(`${K(e)} with id: \`${t}\` already exists. Please use a different id.`);}},w=class extends L{constructor(e,t){super(`${K(e)} with id: \`${t}\` does not exist. Please provide a valid id.`);}},N=class extends m{constructor(e,t){super(`Failed to execute ${K(e)} with id: \`${t}\`. Please try again later.`);}};var q=class extends w{code="ProviderNotFoundError";constructor(e){super("provider",e);}},J=class extends N{code="ProviderExecutionFailedError";constructor(e){super("workflow",e);}};var B=class extends T{code="SignatureMismatchError";constructor(){super("Signature does not match the expected signature. Please ensure the signature provided in the `novu-signature` header is correct and try again.");}},z=class extends T{code="SignatureNotFoundError";constructor(){super("Signature not found. Please provide a signature in the `novu-signature` header");}},Z=class extends T{code="SignatureInvalidError";constructor(){super("Signature is invalid. Please provide a valid signature in the `novu-signature` header");}},Q=class extends T{code="SignatureExpiredError";constructor(){super(`Signature expired. Please provide a signature with a timestamp no older than ${5} minutes in the \`novu-signature\` header`);}},H=class extends T{code="SigningKeyNotFoundError";constructor(){super("Signature key not found. Please provide a valid key in the Client constructor `config.secretKey`");}};var ee=class extends w{code="StepNotFoundError";constructor(e){super("step",e);}};var P=class extends w{code="WorkflowNotFoundError";constructor(e){super("workflow",e);}},te=class extends y{code="WorkflowAlreadyExistsError";constructor(e){super("workflow",e);}};var re=class{ajv;compiledSchemas;constructor(){this.ajv=new Ne__default.default({useDefaults:!0,removeAdditional:"all"}),Ae__default.default(this.ajv),this.compiledSchemas=new Map;}isSchema(e){return typeof e=="boolean"?!1:e.type==="object"||!!e.anyOf||!!e.oneOf}async validate(e,t){let r=this.compiledSchemas.get(t);return r||(r=this.ajv.compile(t),this.compiledSchemas.set(t,r)),r(e)?{success:!0,data:e}:{success:!1,errors:r.errors.map(i=>({path:i.instancePath,message:i.message}))}}transformToJsonSchema(e){return e}};var oe=class{isSchema(e){return e.safeParseAsync!==void 0}async validate(e,t){let r=t.safeParse(e);return r.success?{success:!0,data:r.data}:{success:!1,errors:r.error.errors.map(s=>({path:`/${s.path.join("/")}`,message:s.message}))}}transformToJsonSchema(e){try{return zodToJsonSchema.zodToJsonSchema(e)}catch(t){throw t?.message?.includes("Cannot find module")&&console.error("Tried to use a zod schema in @novu/framework without `zod-to-json-schema` installed. Please install it by running `npm install zod-to-json-schema`."),t}}};var Oe=[new oe,new re],he=async(o,e)=>{for(let t of Oe)if(t.isSchema(o))return t.validate(e,o);throw new Error("Invalid schema")},Te=o=>{for(let e of Oe)if(e.isSchema(o))return e.transformToJsonSchema(o);throw new Error("Invalid schema")};var we={name:"@novu/framework",version:"2.0.0-canary.0",description:"The Code-First Notifications Workflow SDK.",main:"./dist/index.js",types:"./dist/index.d.ts",publishConfig:{registry:"https://registry.npmjs.org",access:"public"},private:!1,repository:{type:"git",url:"git+https://github.com/novuhq/novu.git"},files:["dist","README.md"],scripts:{preinstall:"npx only-allow pnpm",test:"vitest","test:watch":"vitest --watch",lint:"eslint src --ext .ts","lint:fix":"eslint src --ext .ts --fix",format:"prettier --check --ignore-path .gitignore .","format:fix":"prettier --write --ignore-path .gitignore .",build:"tsup","build:watch":"tsup --watch","$comment:bump:prerelease":"This is a workaround to support `npm version prerelease` with lerna","bump:prerelease":"npm version prerelease --preid=alpha & PID=$!; (sleep 1 && kill -9 $PID) & wait $PID","release:alpha":"pnpm bump:prerelease || pnpm build && npm publish"},keywords:["novu","code-first","workflows","durable","sdk","notifications","email","sms","push","webhooks","next","nuxt","h3","express"],author:"Novu Team <engineering@novu.co>",license:"ISC",exports:{".":{require:"./dist/index.js",import:"./dist/index.js",types:"./dist/index.d.ts"},"./express":{require:"./dist/express.js",import:"./dist/express.js",types:"./dist/express.d.ts"},"./next":{require:"./dist/next.js",import:"./dist/next.js",types:"./dist/next.d.ts"},"./nuxt":{require:"./dist/nuxt.js",import:"./dist/nuxt.js",types:"./dist/nuxt.d.ts"},"./h3":{require:"./dist/h3.js",import:"./dist/h3.js",types:"./dist/h3.d.ts"},"./sveltekit":{require:"./dist/sveltekit.js",import:"./dist/sveltekit.js",types:"./dist/sveltekit.d.ts"},"./remix":{require:"./dist/remix.js",import:"./dist/remix.js",types:"./dist/remix.d.ts"}},peerDependencies:{"@sveltejs/kit":">=1.27.3","@vercel/node":">=2.15.9",express:">=4.19.2",h3:">=1.8.1",next:">=12.0.0",zod:">=3.0.0","zod-to-json-schema":">=3.0.0"},peerDependenciesMeta:{"@sveltejs/kit":{optional:!0},"@vercel/node":{optional:!0},express:{optional:!0},fastify:{optional:!0},h3:{optional:!0},next:{optional:!0},zod:{optional:!0},"zod-to-json-schema":{optional:!0}},devDependencies:{"@sveltejs/kit":"^1.27.3","@types/express":"^4.17.13","@types/json-schema":"^7.0.15","@types/node":"^20.11.20","@vercel/node":"^2.15.9",express:"^4.19.2",h3:"^1.11.1",next:"^13.5.4",prettier:"^3.2.5","ts-node":"^10.9.2",tsup:"^8.0.2",typescript:"^5.3.3",vitest:"^1.2.1",zod:"^3.23.0","zod-to-json-schema":"^3.23.0"},dependencies:{"@novu/shared":"workspace:*",ajv:"^8.12.0","ajv-formats":"^2.1.1","better-ajv-errors":"^1.2.0",chalk:"^4.1.2","cross-fetch":"^4.0.0","json-schema-faker":"^0.5.6","json-schema-to-ts":"^3.0.0",liquidjs:"^10.13.1",ora:"^5.4.1"}};var S=we.version,se="2024-06-26";jsonSchemaFaker.JSONSchemaFaker.random.shuffle=function(){return ["[placeholder]"]};jsonSchemaFaker.JSONSchemaFaker.option({useDefaultValue:!0,alwaysFakeOptionals:!0});function Pe(){return process.env.NODE_ENV==="development"}var ne=class{discoveredWorkflows=[];templateEngine=new liquidjs.Liquid;secretKey;version=S;strictAuthentication;constructor(e){let t=this.buildOptions(e);this.secretKey=t.secretKey,this.strictAuthentication=t.strictAuthentication;}buildOptions(e){let t={secretKey:void 0,strictAuthentication:!Pe()};return t.secretKey=e?.secretKey||process.env.NOVU_SECRET_KEY||process.env.NOVU_API_KEY,e?.strictAuthentication!==void 0?t.strictAuthentication=e.strictAuthentication:process.env.NOVU_STRICT_AUTHENTICATION_ENABLED!==void 0&&(t.strictAuthentication=process.env.NOVU_STRICT_AUTHENTICATION_ENABLED==="true"),t}addWorkflows(e){for(let t of e){if(this.discoveredWorkflows.some(r=>r.workflowId===t.definition.workflowId))throw new te(t.definition.workflowId);this.discoveredWorkflows.push(t.definition);}}healthCheck(){let e=this.discoveredWorkflows.length,t=this.discoveredWorkflows.reduce((r,s)=>r+s.steps.length,0);return {status:"ok",sdkVersion:S,frameworkVersion:se,discovered:{workflows:e,steps:t}}}getWorkflow(e){let t=this.discoveredWorkflows.find(r=>r.workflowId===e);if(t)return t;throw new P(e)}getStep(e,t){let s=this.getWorkflow(e).steps.find(i=>i.stepId===t);if(s)return s;throw new ee(t)}getRegisteredWorkflows(){return this.discoveredWorkflows}discover(){return {workflows:this.getRegisteredWorkflows()}}mock(e){return jsonSchemaFaker.JSONSchemaFaker.generate(Te(e))}async validate(e,t,r,s,i,n,a){let c=await he(t,e);if(c.success)return c.data;switch(r){case"event":this.throwInvalidEvent(s,i,c.errors);case"step":this.throwInvalidStep(n,s,i,c.errors);case"provider":this.throwInvalidProvider(n,a,s,i,c.errors);default:throw new Error(`Invalid component: '${r}'`)}}throwInvalidProvider(e,t,r,s,i){if(!e)throw new Error("stepId is required");if(!t)throw new Error("providerId is required");switch(r){case"output":throw new G(s,e,t,i);default:throw new Error(`Invalid payload type: '${r}'`)}}throwInvalidStep(e,t,r,s){if(!e)throw new Error("stepId is required");switch(t){case"output":throw new $(r,e,s);case"result":throw new M(r,e,s);case"controls":throw new W(r,e,s);default:throw new Error(`Invalid payload type: '${t}'`)}}throwInvalidEvent(e,t,r){switch(e){case"controls":throw new F(t,r);case"payload":throw new x(t,r);default:throw new Error(`Invalid payload type: '${e}'`)}}executeStepFactory(e,t){return async(r,s,i)=>{let n=this.getStep(e.workflowId,r),a=Se(e),c=await this.createStepControls(n,a),R=e.action==="preview";if(!R&&await this.shouldSkip(i?.skip,c))return t({options:{skip:!0}}),{};let p=this.previewStep.bind(this),I=this.executeStep.bind(this),C=await(R?p:I)(e,{...n,providers:n.providers.map(f=>{let A=i?.providers?.[f.type];if(!A)throw new q(f.type);return {...f,resolve:A}}),resolve:s});return r===e.stepId&&t(C),C.outputs}}async shouldSkip(e,t){return e?e(t):!1}async executeWorkflow(e){let s=`${{execute:"Executing",preview:"Previewing"}[e.action]} workflowId:`;console.log(`
20
+ var D=(r=>(r.TRIGGER="trigger",r.EXECUTE="execute",r.PREVIEW="preview",r))(D||{}),k=(r=>(r.DISCOVER="discover",r.HEALTH_CHECK="health-check",r.CODE="code",r))(k||{});var O=(d=>(d.WORKFLOW_NOT_FOUND_ERROR="WorkflowNotFoundError",d.WORKFLOW_ALREADY_EXISTS_ERROR="WorkflowAlreadyExistsError",d.WORKFLOW_EXECUTION_FAILED_ERROR="WorkflowExecutionFailedError",d.EXECUTION_STATE_OUTPUT_INVALID_ERROR="ExecutionStateOutputInvalidError",d.EXECUTION_STATE_RESULT_INVALID_ERROR="ExecutionStateResultInvalidError",d.EXECUTION_PROVIDER_OUTPUT_INVALID_ERROR="ExecutionProviderOutputInvalidError",d.PROVIDER_NOT_FOUND_ERROR="ProviderNotFoundError",d.PROVIDER_EXECUTION_FAILED_ERROR="ProviderExecutionFailedError",d.STEP_NOT_FOUND_ERROR="StepNotFoundError",d.STEP_ALREADY_EXISTS_ERROR="StepAlreadyExistsError",d.STEP_EXECUTION_FAILED_ERROR="StepExecutionFailedError",d.EXECUTION_STATE_CORRUPT_ERROR="ExecutionStateCorruptError",d.EXECUTION_EVENT_PAYLOAD_INVALID_ERROR="ExecutionEventPayloadInvalidError",d.EXECUTION_EVENT_CONTROL_INVALID_ERROR="ExecutionEventControlInvalidError",d.EXECUTION_STATE_CONTROL_INVALID_ERROR="ExecutionStateControlInvalidError",d.METHOD_NOT_ALLOWED_ERROR="MethodNotAllowedError",d.INVALID_ACTION_ERROR="InvalidActionError",d.MISSING_SECRET_KEY_ERROR="MissingSecretKeyError",d.SIGNATURE_MISMATCH_ERROR="SignatureMismatchError",d.SIGNATURE_NOT_FOUND_ERROR="SignatureNotFoundError",d.SIGNATURE_INVALID_ERROR="SignatureInvalidError",d.SIGNATURE_EXPIRED_ERROR="SignatureExpiredError",d.SIGNING_KEY_NOT_FOUND_ERROR="SigningKeyNotFoundError",d.PLATFORM_ERROR="PlatformError",d.SIGNATURE_VERSION_INVALID_ERROR="SignatureVersionInvalidError",d.WORKFLOW_PAYLOAD_INVALID_ERROR="WorkflowPayloadInvalidError",d))(O||{});var U=(r=>(r.POST="POST",r.GET="GET",r.OPTIONS="OPTIONS",r))(U||{});var h=class extends Error{data},L=class extends h{statusCode=404},E=class extends h{statusCode=400},T=class extends h{statusCode=401},m=class extends h{statusCode=500},b=class extends h{statusCode=409};var V=class extends E{code="ExecutionStateCorruptError";constructor(e,t){super(`Workflow with id: \`${e}\` has a corrupt state. Step with id: \`${t}\` does not exist. Please provide the missing state.`),this.data={workflowId:e,stepId:t};}},x=class extends E{code="ExecutionEventPayloadInvalidError";constructor(e,t){super(`Workflow with id: \`${e}\` has invalid \`payload\`. Please provide the correct event payload.`),this.data=t;}},F=class extends E{code="ExecutionEventControlInvalidError";constructor(e,t){super(`Workflow with id: \`${e}\` has invalid \`controls\`. Please provide the correct event controls.`),this.data=t;}},W=class extends E{code="ExecutionStateControlInvalidError";constructor(e,t,r){super(`Workflow with id: \`${e}\` has an invalid state. Step with id: \`${t}\` has invalid \`controls\`. Please provide the correct step controls.`),this.data=r;}},$=class extends E{code="ExecutionStateOutputInvalidError";constructor(e,t,r){super(`Workflow with id: \`${e}\` has an invalid state. Step with id: \`${t}\` has invalid output. Please provide the correct step output.`),this.data=r;}},M=class extends E{code="ExecutionStateResultInvalidError";constructor(e,t,r){super(`Workflow with id: \`${e}\` has an invalid state. Step with id: \`${t}\` has invalid result. Please provide the correct step result.`),this.data=r;}},G=class extends E{code="ExecutionProviderOutputInvalidError";constructor(e,t,r,s){super(`Workflow with id: \`${e}\` has an invalid state. Step with id: \`${t}\` and provider with id: \`${r}\` has invalid output. Please provide the correct provider output.`),this.data=s;}};var j=class extends Error{statusCode;message;code;constructor(e,t,r){super(r),this.statusCode=e,this.code=t;}};var ue=()=>typeof Response<"u"?Response:crossFetch.Response;var l={info:o=>N__default.default.blue(o),warning:o=>N__default.default.yellow(o),error:o=>N__default.default.red(o),success:o=>N__default.default.green(o),underline:o=>N__default.default.underline(o),bold:o=>N__default.default.bold(o)},u={SUCCESS:l.success("\u2714"),ERROR:l.error("\u2717"),WARNING:l.warning("\u26A0"),INFO:l.info("\u2139"),ARROW:l.bold("\u2192"),MOCK:l.info("\u25CB"),HYDRATED:l.bold(l.info("\u2192")),STEP:l.info("\u03C3"),ACTION:l.info("\u03B1"),DURATION:l.info("\u0394"),PROVIDER:l.info("\u2699"),OUTPUT:l.info("\u21E2"),INPUT:l.info("\u21E0"),WORKFLOW:l.info("\u03C9"),STATE:l.info("\u03C3"),EXECUTE:l.info("\u03B5"),PREVIEW:l.info("\u03C1")};var de=o=>Object.values(o).map(e=>`\`${e}\``).join(", "),K=o=>o.replaceAll(/(\w)(\w*)/g,(e,t,r)=>t.toUpperCase()+r.toLowerCase()).replaceAll(/[\s-]+/g,"");var Re=(o,e="https://api.novu.co")=>{let t=process.env.NOVU_API_URL||e;return {post:async(r,s)=>{let i=await fetch(t+"/v1"+r,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`ApiKey ${o}`},body:JSON.stringify(s)}),n=await i.json();if(i.ok)return n;throw new j(n.statusCode,n.error,n.message)},delete:async r=>(await fetch(t+"/v1"+r,{method:"DELETE",headers:{"Content-Type":"application/json",Authorization:`ApiKey ${o}`}})).json()}};var Y=class extends h{code="MethodNotAllowedError";statusCode=405;message=`Method not allowed. Please use one of ${de(U)}`},g=class extends E{code="InvalidActionError";constructor(e,t){super(`Invalid query string: \`action\`=\`${e}\`. Please use one of ${de(t)}`);}};var X=class extends m{code="PlatformError";message="Something went wrong. Please try again later."};var y=class extends b{constructor(e,t){super(`${K(e)} with id: \`${t}\` already exists. Please use a different id.`);}},w=class extends L{constructor(e,t){super(`${K(e)} with id: \`${t}\` does not exist. Please provide a valid id.`);}},v=class extends m{constructor(e,t){super(`Failed to execute ${K(e)} with id: \`${t}\`. Please try again later.`);}};var q=class extends w{code="ProviderNotFoundError";constructor(e){super("provider",e);}},J=class extends v{code="ProviderExecutionFailedError";constructor(e){super("workflow",e);}};var B=class extends T{code="SignatureMismatchError";constructor(){super("Signature does not match the expected signature. Please ensure the signature provided in the `novu-signature` header is correct and try again.");}},z=class extends T{code="SignatureNotFoundError";constructor(){super("Signature not found. Please provide a signature in the `novu-signature` header");}},Z=class extends T{code="SignatureInvalidError";constructor(){super("Signature is invalid. Please provide a valid signature in the `novu-signature` header");}},Q=class extends T{code="SignatureExpiredError";constructor(){super(`Signature expired. Please provide a signature with a timestamp no older than ${5} minutes in the \`novu-signature\` header`);}},H=class extends T{code="SigningKeyNotFoundError";constructor(){super("Signature key not found. Please provide a valid key in the Client constructor `config.secretKey`");}};var ee=class extends w{code="StepNotFoundError";constructor(e){super("step",e);}};var S=class extends w{code="WorkflowNotFoundError";constructor(e){super("workflow",e);}},te=class extends y{code="WorkflowAlreadyExistsError";constructor(e){super("workflow",e);}};var re=class{ajv;compiledSchemas;constructor(){this.ajv=new ve__default.default({useDefaults:!0,removeAdditional:"all"}),Ae__default.default(this.ajv),this.compiledSchemas=new Map;}isSchema(e){return typeof e=="boolean"?!1:e.type==="object"||!!e.anyOf||!!e.oneOf}async validate(e,t){let r=this.compiledSchemas.get(t);return r||(r=this.ajv.compile(t),this.compiledSchemas.set(t,r)),r(e)?{success:!0,data:e}:{success:!1,errors:r.errors.map(i=>({path:i.instancePath,message:i.message}))}}transformToJsonSchema(e){return e}};var oe=class{isSchema(e){return e.safeParseAsync!==void 0}async validate(e,t){let r=t.safeParse(e);return r.success?{success:!0,data:r.data}:{success:!1,errors:r.error.errors.map(s=>({path:`/${s.path.join("/")}`,message:s.message}))}}transformToJsonSchema(e){try{return zodToJsonSchema.zodToJsonSchema(e)}catch(t){throw t?.message?.includes("Cannot find module")&&console.error("Tried to use a zod schema in @novu/framework without `zod-to-json-schema` installed. Please install it by running `npm install zod-to-json-schema`."),t}}};var Oe=[new oe,new re],he=async(o,e)=>{for(let t of Oe)if(t.isSchema(o))return t.validate(e,o);throw new Error("Invalid schema")},Te=o=>{for(let e of Oe)if(e.isSchema(o))return e.transformToJsonSchema(o);throw new Error("Invalid schema")};var we={name:"@novu/framework",version:"2.0.0-canary.2",description:"The Code-First Notifications Workflow SDK.",main:"./dist/index.js",types:"./dist/index.d.ts",publishConfig:{registry:"https://registry.npmjs.org",access:"public"},private:!1,repository:{type:"git",url:"git+https://github.com/novuhq/novu.git"},files:["dist","README.md"],scripts:{preinstall:"npx only-allow pnpm",test:"vitest","test:watch":"vitest --watch",lint:"eslint src --ext .ts","lint:fix":"eslint src --ext .ts --fix",format:"prettier --check --ignore-path .gitignore .","format:fix":"prettier --write --ignore-path .gitignore .",build:"tsup","build:watch":"tsup --watch","$comment:bump:prerelease":"This is a workaround to support `npm version prerelease` with lerna","bump:prerelease":"npm version prerelease --preid=alpha & PID=$!; (sleep 1 && kill -9 $PID) & wait $PID","release:alpha":"pnpm bump:prerelease || pnpm build && npm publish"},keywords:["novu","code-first","workflows","durable","sdk","notifications","email","sms","push","webhooks","next","nuxt","h3","express"],author:"Novu Team <engineering@novu.co>",license:"ISC",exports:{".":{require:"./dist/index.js",import:"./dist/index.js",types:"./dist/index.d.ts"},"./express":{require:"./dist/express.js",import:"./dist/express.js",types:"./dist/express.d.ts"},"./next":{require:"./dist/next.js",import:"./dist/next.js",types:"./dist/next.d.ts"},"./nuxt":{require:"./dist/nuxt.js",import:"./dist/nuxt.js",types:"./dist/nuxt.d.ts"},"./h3":{require:"./dist/h3.js",import:"./dist/h3.js",types:"./dist/h3.d.ts"},"./sveltekit":{require:"./dist/sveltekit.js",import:"./dist/sveltekit.js",types:"./dist/sveltekit.d.ts"},"./remix":{require:"./dist/remix.js",import:"./dist/remix.js",types:"./dist/remix.d.ts"}},peerDependencies:{"@sveltejs/kit":">=1.27.3","@vercel/node":">=2.15.9",express:">=4.19.2",h3:">=1.8.1",next:">=12.0.0",zod:">=3.0.0","zod-to-json-schema":">=3.0.0"},peerDependenciesMeta:{"@sveltejs/kit":{optional:!0},"@vercel/node":{optional:!0},express:{optional:!0},fastify:{optional:!0},h3:{optional:!0},next:{optional:!0},zod:{optional:!0},"zod-to-json-schema":{optional:!0}},devDependencies:{"@sveltejs/kit":"^1.27.3","@types/express":"^4.17.13","@types/json-schema":"^7.0.15","@types/node":"^20.11.20","@vercel/node":"^2.15.9",express:"^4.19.2",h3:"^1.11.1",next:"^13.5.4",prettier:"^3.2.5","ts-node":"^10.9.2",tsup:"^8.0.2",typescript:"^5.3.3",vitest:"^1.2.1",zod:"^3.23.0","zod-to-json-schema":"^3.23.0"},dependencies:{"@novu/shared":"^2.0.0-canary.0",ajv:"^8.12.0","ajv-formats":"^2.1.1","better-ajv-errors":"^1.2.0",chalk:"^4.1.2","cross-fetch":"^4.0.0","json-schema-faker":"^0.5.6","json-schema-to-ts":"^3.0.0",liquidjs:"^10.13.1",ora:"^5.4.1"}};var P=we.version,se="2024-06-26";jsonSchemaFaker.JSONSchemaFaker.random.shuffle=function(){return ["[placeholder]"]};jsonSchemaFaker.JSONSchemaFaker.option({useDefaultValue:!0,alwaysFakeOptionals:!0});function Se(){return process.env.NODE_ENV==="development"}var ne=class{discoveredWorkflows=[];templateEngine=new liquidjs.Liquid;secretKey;version=P;strictAuthentication;constructor(e){let t=this.buildOptions(e);this.secretKey=t.secretKey,this.strictAuthentication=t.strictAuthentication;}buildOptions(e){let t={secretKey:void 0,strictAuthentication:!Se()};return t.secretKey=e?.secretKey||process.env.NOVU_SECRET_KEY||process.env.NOVU_API_KEY,e?.strictAuthentication!==void 0?t.strictAuthentication=e.strictAuthentication:process.env.NOVU_STRICT_AUTHENTICATION_ENABLED!==void 0&&(t.strictAuthentication=process.env.NOVU_STRICT_AUTHENTICATION_ENABLED==="true"),t}addWorkflows(e){for(let t of e){if(this.discoveredWorkflows.some(r=>r.workflowId===t.definition.workflowId))throw new te(t.definition.workflowId);this.discoveredWorkflows.push(t.definition);}}healthCheck(){let e=this.discoveredWorkflows.length,t=this.discoveredWorkflows.reduce((r,s)=>r+s.steps.length,0);return {status:"ok",sdkVersion:P,frameworkVersion:se,discovered:{workflows:e,steps:t}}}getWorkflow(e){let t=this.discoveredWorkflows.find(r=>r.workflowId===e);if(t)return t;throw new S(e)}getStep(e,t){let s=this.getWorkflow(e).steps.find(i=>i.stepId===t);if(s)return s;throw new ee(t)}getRegisteredWorkflows(){return this.discoveredWorkflows}discover(){return {workflows:this.getRegisteredWorkflows()}}mock(e){return jsonSchemaFaker.JSONSchemaFaker.generate(Te(e))}async validate(e,t,r,s,i,n,a){let c=await he(t,e);if(c.success)return c.data;switch(r){case"event":this.throwInvalidEvent(s,i,c.errors);case"step":this.throwInvalidStep(n,s,i,c.errors);case"provider":this.throwInvalidProvider(n,a,s,i,c.errors);default:throw new Error(`Invalid component: '${r}'`)}}throwInvalidProvider(e,t,r,s,i){if(!e)throw new Error("stepId is required");if(!t)throw new Error("providerId is required");switch(r){case"output":throw new G(s,e,t,i);default:throw new Error(`Invalid payload type: '${r}'`)}}throwInvalidStep(e,t,r,s){if(!e)throw new Error("stepId is required");switch(t){case"output":throw new $(r,e,s);case"result":throw new M(r,e,s);case"controls":throw new W(r,e,s);default:throw new Error(`Invalid payload type: '${t}'`)}}throwInvalidEvent(e,t,r){switch(e){case"controls":throw new F(t,r);case"payload":throw new x(t,r);default:throw new Error(`Invalid payload type: '${e}'`)}}executeStepFactory(e,t){return async(r,s,i)=>{let n=this.getStep(e.workflowId,r),a=Pe(e),c=await this.createStepControls(n,a),R=e.action==="preview";if(!R&&await this.shouldSkip(i?.skip,c))return t({options:{skip:!0}}),{};let p=this.previewStep.bind(this),I=this.executeStep.bind(this),C=await(R?p:I)(e,{...n,providers:n.providers.map(f=>{let A=i?.providers?.[f.type];if(!A)throw new q(f.type);return {...f,resolve:A}}),resolve:s});return r===e.stepId&&t(C),C.outputs}}async shouldSkip(e,t){return e?e(t):!1}async executeWorkflow(e){let s=`${{execute:"Executing",preview:"Previewing"}[e.action]} workflowId:`;console.log(`
21
21
  ${l.bold(l.underline(s))} '${e.workflowId}'`);let i=this.getWorkflow(e.workflowId),n=process.hrtime(),a={outputs:{},providers:{},options:{}},c,R=new Promise(_=>{c=_;}),p=_=>{c(),a=_;},I;try{if(e.action==="execute"&&!e.payload&&!e.data)throw new x(e.workflowId,{message:"Event `payload` is required"});let _=await this.createExecutionPayload(e,i);await Promise.race([R,i.execute({payload:_,environment:{},inputs:{},controls:{},subscriber:e.subscriber,step:{email:this.executeStepFactory(e,p),sms:this.executeStepFactory(e,p),inApp:this.executeStepFactory(e,p),digest:this.executeStepFactory(e,p),delay:this.executeStepFactory(e,p),push:this.executeStepFactory(e,p),chat:this.executeStepFactory(e,p),custom:this.executeStepFactory(e,p)}})]);}catch(_){I=_;}let ce=process.hrtime(n),C=ce[0],f=ce[1],A=C*1e3+f/1e6,Ie=I?u.ERROR:u.SUCCESS,_e=e.action==="execute"?"Executed":e.action==="preview"?"Previewed":"Invalid action";if(console.log(`${Ie} ${_e} workflowId: \`${e.workflowId}\``),this.prettyPrintExecute(e,A,I),I)throw I;return {outputs:a.outputs,providers:a.providers,options:a.options,metadata:{status:"success",error:!1,duration:A}}}async createExecutionPayload(e,t){let r=e.payload||e.data;if(e.action==="preview"){let i=this.mock(t.payload.schema);r=Object.assign(i,r);}return await this.validate(r,t.payload.unknownSchema,"event","payload",e.workflowId)}prettyPrintExecute(e,t,r){let s=r?u.ERROR:u.SUCCESS,i=e.action==="execute"?"Executed":e.action==="preview"?"Previewed":"Invalid action",n=r?"Failed to execute":i,a=r?l.error:l.success,c=`${s} ${n} workflowId: '${e.workflowId}`;console.log(`
22
22
  ${l.bold(a(c))}'`),console.log(` \u251C ${u.STEP} stepId: '${e.stepId}'`),console.log(` \u251C ${u.ACTION} action: '${e.action}'`),console.log(` \u2514 ${u.DURATION} duration: '${t.toFixed(2)}ms'
23
23
  `);}async executeProviders(e,t,r){return t.providers.reduce(async(s,i)=>{let n=await s,a=this.previewProvider.bind(this),c=this.executeProvider.bind(this),p=await(e.action==="preview"?a:c)(e,t,i,r);return {...n,[i.type]:p}},Promise.resolve({}))}previewProvider(e,t,r,s){return console.log(` ${u.MOCK} Mocked provider: \`${r.type}\``),this.mock(r.outputs.schema)}async executeProvider(e,t,r,s){let i=ie__default.default({indent:2}).start(`Executing provider: \`${r.type}\``);try{if(e.stepId===t.stepId){let n=await this.createStepControls(t,e),a=await r.resolve({controls:n,outputs:s}),c=await this.validate(a,r.outputs.unknownSchema,"step","output",e.workflowId,t.stepId,r.type);return i.succeed(`Executed provider: \`${r.type}\``),c}else i.stopAndPersist({symbol:u.HYDRATED,text:`Hydrated provider: \`${r.type}\``});}catch(n){throw i.stopAndPersist({symbol:u.ERROR,text:`Failed to execute provider: \`${r.type}\``}),new J(`Failed to execute provider: '${r.type}'.
24
- ${n.message}`)}}async executeStep(e,t){if(e.stepId===t.stepId){let r=ie__default.default({indent:1}).start(`Executing stepId: \`${t.stepId}\``);try{let s=await this.createStepControls(t,e),i=await this.compileControls(s,e),n=await t.resolve(i),a=await this.validate(n,t.outputs.unknownSchema,"step","output",e.workflowId,t.stepId),c=await this.executeProviders(e,t,a);return r.succeed(`Executed stepId: \`${t.stepId}\``),{outputs:a,providers:c}}catch(s){throw r.stopAndPersist({prefixText:"",symbol:u.ERROR,text:`Failed to execute stepId: \`${t.stepId}\``}),s}}else {let r=ie__default.default({indent:1}).start(`Hydrating stepId: \`${t.stepId}\``);try{let s=e.state.find(i=>i.stepId===t.stepId);if(s){let i=await this.validate(s.outputs,t.results.unknownSchema,"step","result",e.workflowId,t.stepId);return r.stopAndPersist({symbol:u.HYDRATED,text:`Hydrated stepId: \`${t.stepId}\``}),{outputs:i,providers:await this.executeProviders(e,t,i)}}else throw new V(e.workflowId,t.stepId)}catch(s){throw r.stopAndPersist({symbol:u.ERROR,text:`Failed to hydrate stepId: \`${t.stepId}\``}),s}}}async compileControls(e,t){let r=this.templateEngine.parse(JSON.stringify(e)),s=await this.templateEngine.render(r,{...t.payload||t.data,subscriber:t.subscriber});return JSON.parse(s)}async createStepControls(e,t){let r=t.controls||t.inputs;return await this.validate(r,e.controls.unknownSchema,"step","controls",t.workflowId,e.stepId)}async previewStep(e,t){let r=ie__default.default({indent:1}).start(`Previewing stepId: \`${t.stepId}\``);try{if(e.stepId===t.stepId){let s=await this.createStepControls(t,e),i=await this.compileControls(s,e),n=await t.resolve(i),a=await this.validate(n,t.outputs.unknownSchema,"step","output",e.workflowId,t.stepId);return r.stopAndPersist({symbol:u.MOCK,text:`Mocked stepId: \`${t.stepId}\``}),{outputs:a,providers:await this.executeProviders(e,t,a)}}else {let s=this.mock(t.results.schema);return r.stopAndPersist({symbol:u.MOCK,text:`Mocked stepId: \`${t.stepId}\``}),{outputs:s,providers:await this.executeProviders(e,t,s)}}}catch(s){throw r.stopAndPersist({symbol:u.ERROR,text:`Failed to preview stepId: \`${t.stepId}\``}),s}}getStepCode(e,t){return {code:this.getStep(e,t).resolve.toString()}}getWorkflowCode(e){return {code:this.getWorkflow(e).execute.toString()}}getCode(e,t){let r;if(e)t?r=this.getStepCode(e,t):r=this.getWorkflowCode(e);else throw new P(e);return r}};function Se(o){return JSON.parse(JSON.stringify(o))}var ae=class{frameworkName;handler;client;hmacEnabled;http;constructor(e){this.handler=e.handler,this.client=e.client?e.client:new ne,this.client.addWorkflows(e.workflows),this.http=Re(this.client.secretKey),this.frameworkName=e.frameworkName,this.hmacEnabled=this.client.strictAuthentication;}createHandler(){return async(...e)=>{let t=await this.handler(...e),r=await this.handleAction({actions:t});return t.transformResponse(r)}}getStaticHeaders(){let e=`novu-framework:v${this.client.version}`;return {"content-type":"application/json","access-control-allow-origin":"*","access-control-allow-methods":"GET, POST","access-control-allow-headers":"*","access-control-max-age":"604800","novu-framework-version":se,"novu-framework-sdk":S,"novu-framework-api":this.frameworkName,"user-agent":e}}createResponse(e,t){return {status:e,body:JSON.stringify(t),headers:{...this.getStaticHeaders()}}}createError(e){return {status:e.statusCode,body:JSON.stringify({message:e.message,data:e.data,code:e.code}),headers:this.getStaticHeaders()}}async handleAction({actions:e}){let t=await e.url(),r=await e.method(),s=t.searchParams.get("action")||"",i=t.searchParams.get("workflowId")||"",n=t.searchParams.get("stepId")||"",a=await e.headers("novu-signature")||await e.headers("x-novu-signature")||"",c={};try{r==="POST"&&(c=await e.body());}catch{}try{s!=="health-check"&&this.validateHmac(c,a);let R=this.getPostActionMap(c,i,n,s),p=this.getGetActionMap(i,n);if(r==="POST")return await this.handlePostAction(s,R);if(r==="GET")return await this.handleGetAction(s,p);if(r==="OPTIONS")return this.createResponse(200,{})}catch(R){return this.handleError(R)}return this.createError(new Y(r))}getPostActionMap(e,t,r,s){return {trigger:this.triggerAction({workflowId:t,...e}),execute:async()=>{let i=await this.client.executeWorkflow({...e,workflowId:t,stepId:r,action:s});return this.createResponse(200,i)},preview:async()=>{let i=await this.client.executeWorkflow({...e,workflowId:t,stepId:r,action:s});return this.createResponse(200,i)}}}triggerAction(e){return async()=>{let t={name:e.workflowId,to:e.to,payload:e?.payload||{},transactionId:e.transactionId,overrides:e.overrides||{},...e.actor&&{actor:e.actor},...e.tenant&&{tenant:e.tenant},...e.bridgeUrl&&{bridgeUrl:e.bridgeUrl},...e.controls&&{controls:e.controls}},r=await this.http.post("/events/trigger",t);return this.createResponse(200,r)}}getGetActionMap(e,t){return {discover:async()=>{let r=await this.client.discover();return this.createResponse(200,r)},"health-check":async()=>{let r=await this.client.healthCheck();return this.createResponse(200,r)},code:async()=>{let r=await this.client.getCode(e,t);return this.createResponse(200,r)}}}async handlePostAction(e,t){if(Object.values(D).includes(e)){let r=t[e];return r()}else throw new g(e,D)}async handleGetAction(e,t){if(Object.values(k).includes(e)){let r=t[e];return r()}else throw new g(e,k)}isClientError(e){let t=Object.values(O).includes(e.code),r=ke(e);return t||r}handleError(e){return this.isClientError(e)?(e.statusCode===500&&console.error(e),this.createError(e)):(console.error(e),this.createError(new X))}validateHmac(e,t){if(!this.hmacEnabled)return;if(!t)throw new z;if(!this.client.secretKey)throw new H;let[r,s]=t.split(",");if(!r||!s)throw new Z;let[i,n]=r.split("="),[a,c]=s.split("=");if(Number(i)<Date.now()-1500)throw new Q;if(!(this.hashHmac(this.client.secretKey,`${n}.${JSON.stringify(e)}`)===c))throw new B}hashHmac(e,t){return crypto.createHmac("sha256",e).update(t).digest("hex")}};function ke(o){return o?.statusCode>=400&&o?.statusCode<500}var Ue="sveltekit",Cr=o=>{let t=new ae({frameworkName:Ue,...o,handler:(i,n)=>({method:()=>i||n.request.method||"",body:()=>n.request.json(),headers:a=>n.request.headers.get(a),url:()=>{let a=process.env.NODE_ENV==="development"?"http":"https";return new URL(n.request.url,`${a}://${n.request.headers.get("host")||""}`)},transformResponse:({body:a,headers:c,status:R})=>{let p=ue();return new p(a,{status:R,headers:c})}})}).createHandler(),r=t.bind(null,void 0);return Object.defineProperties(r,{GET:{value:t.bind(null,"GET")},POST:{value:t.bind(null,"POST")},PUT:{value:t.bind(null,"PUT")}})};
24
+ ${n.message}`)}}async executeStep(e,t){if(e.stepId===t.stepId){let r=ie__default.default({indent:1}).start(`Executing stepId: \`${t.stepId}\``);try{let s=await this.createStepControls(t,e),i=await this.compileControls(s,e),n=await t.resolve(i),a=await this.validate(n,t.outputs.unknownSchema,"step","output",e.workflowId,t.stepId),c=await this.executeProviders(e,t,a);return r.succeed(`Executed stepId: \`${t.stepId}\``),{outputs:a,providers:c}}catch(s){throw r.stopAndPersist({prefixText:"",symbol:u.ERROR,text:`Failed to execute stepId: \`${t.stepId}\``}),s}}else {let r=ie__default.default({indent:1}).start(`Hydrating stepId: \`${t.stepId}\``);try{let s=e.state.find(i=>i.stepId===t.stepId);if(s){let i=await this.validate(s.outputs,t.results.unknownSchema,"step","result",e.workflowId,t.stepId);return r.stopAndPersist({symbol:u.HYDRATED,text:`Hydrated stepId: \`${t.stepId}\``}),{outputs:i,providers:await this.executeProviders(e,t,i)}}else throw new V(e.workflowId,t.stepId)}catch(s){throw r.stopAndPersist({symbol:u.ERROR,text:`Failed to hydrate stepId: \`${t.stepId}\``}),s}}}async compileControls(e,t){let r=this.templateEngine.parse(JSON.stringify(e)),s=await this.templateEngine.render(r,{...t.payload||t.data,subscriber:t.subscriber});return JSON.parse(s)}async createStepControls(e,t){let r=t.controls||t.inputs;return await this.validate(r,e.controls.unknownSchema,"step","controls",t.workflowId,e.stepId)}async previewStep(e,t){let r=ie__default.default({indent:1}).start(`Previewing stepId: \`${t.stepId}\``);try{if(e.stepId===t.stepId){let s=await this.createStepControls(t,e),i=await this.compileControls(s,e),n=await t.resolve(i),a=await this.validate(n,t.outputs.unknownSchema,"step","output",e.workflowId,t.stepId);return r.stopAndPersist({symbol:u.MOCK,text:`Mocked stepId: \`${t.stepId}\``}),{outputs:a,providers:await this.executeProviders(e,t,a)}}else {let s=this.mock(t.results.schema);return r.stopAndPersist({symbol:u.MOCK,text:`Mocked stepId: \`${t.stepId}\``}),{outputs:s,providers:await this.executeProviders(e,t,s)}}}catch(s){throw r.stopAndPersist({symbol:u.ERROR,text:`Failed to preview stepId: \`${t.stepId}\``}),s}}getStepCode(e,t){return {code:this.getStep(e,t).resolve.toString()}}getWorkflowCode(e){return {code:this.getWorkflow(e).execute.toString()}}getCode(e,t){let r;if(e)t?r=this.getStepCode(e,t):r=this.getWorkflowCode(e);else throw new S(e);return r}};function Pe(o){return JSON.parse(JSON.stringify(o))}var ae=class{frameworkName;handler;client;hmacEnabled;http;constructor(e){this.handler=e.handler,this.client=e.client?e.client:new ne,this.client.addWorkflows(e.workflows),this.http=Re(this.client.secretKey),this.frameworkName=e.frameworkName,this.hmacEnabled=this.client.strictAuthentication;}createHandler(){return async(...e)=>{let t=await this.handler(...e),r=await this.handleAction({actions:t});return t.transformResponse(r)}}getStaticHeaders(){let e=`novu-framework:v${this.client.version}`;return {"content-type":"application/json","access-control-allow-origin":"*","access-control-allow-methods":"GET, POST","access-control-allow-headers":"*","access-control-max-age":"604800","novu-framework-version":se,"novu-framework-sdk":P,"novu-framework-api":this.frameworkName,"user-agent":e}}createResponse(e,t){return {status:e,body:JSON.stringify(t),headers:{...this.getStaticHeaders()}}}createError(e){return {status:e.statusCode,body:JSON.stringify({message:e.message,data:e.data,code:e.code}),headers:this.getStaticHeaders()}}async handleAction({actions:e}){let t=await e.url(),r=await e.method(),s=t.searchParams.get("action")||"",i=t.searchParams.get("workflowId")||"",n=t.searchParams.get("stepId")||"",a=await e.headers("novu-signature")||await e.headers("x-novu-signature")||"",c={};try{r==="POST"&&(c=await e.body());}catch{}try{s!=="health-check"&&this.validateHmac(c,a);let R=this.getPostActionMap(c,i,n,s),p=this.getGetActionMap(i,n);if(r==="POST")return await this.handlePostAction(s,R);if(r==="GET")return await this.handleGetAction(s,p);if(r==="OPTIONS")return this.createResponse(200,{})}catch(R){return this.handleError(R)}return this.createError(new Y(r))}getPostActionMap(e,t,r,s){return {trigger:this.triggerAction({workflowId:t,...e}),execute:async()=>{let i=await this.client.executeWorkflow({...e,workflowId:t,stepId:r,action:s});return this.createResponse(200,i)},preview:async()=>{let i=await this.client.executeWorkflow({...e,workflowId:t,stepId:r,action:s});return this.createResponse(200,i)}}}triggerAction(e){return async()=>{let t={name:e.workflowId,to:e.to,payload:e?.payload||{},transactionId:e.transactionId,overrides:e.overrides||{},...e.actor&&{actor:e.actor},...e.tenant&&{tenant:e.tenant},...e.bridgeUrl&&{bridgeUrl:e.bridgeUrl},...e.controls&&{controls:e.controls}},r=await this.http.post("/events/trigger",t);return this.createResponse(200,r)}}getGetActionMap(e,t){return {discover:async()=>{let r=await this.client.discover();return this.createResponse(200,r)},"health-check":async()=>{let r=await this.client.healthCheck();return this.createResponse(200,r)},code:async()=>{let r=await this.client.getCode(e,t);return this.createResponse(200,r)}}}async handlePostAction(e,t){if(Object.values(D).includes(e)){let r=t[e];return r()}else throw new g(e,D)}async handleGetAction(e,t){if(Object.values(k).includes(e)){let r=t[e];return r()}else throw new g(e,k)}isClientError(e){let t=Object.values(O).includes(e.code),r=ke(e);return t||r}handleError(e){return this.isClientError(e)?(e.statusCode===500&&console.error(e),this.createError(e)):(console.error(e),this.createError(new X))}validateHmac(e,t){if(!this.hmacEnabled)return;if(!t)throw new z;if(!this.client.secretKey)throw new H;let[r,s]=t.split(",");if(!r||!s)throw new Z;let[i,n]=r.split("="),[a,c]=s.split("=");if(Number(i)<Date.now()-1500)throw new Q;if(!(this.hashHmac(this.client.secretKey,`${n}.${JSON.stringify(e)}`)===c))throw new B}hashHmac(e,t){return crypto.createHmac("sha256",e).update(t).digest("hex")}};function ke(o){return o?.statusCode>=400&&o?.statusCode<500}var Ue="sveltekit",Cr=o=>{let t=new ae({frameworkName:Ue,...o,handler:(i,n)=>({method:()=>i||n.request.method||"",body:()=>n.request.json(),headers:a=>n.request.headers.get(a),url:()=>{let a=process.env.NODE_ENV==="development"?"http":"https";return new URL(n.request.url,`${a}://${n.request.headers.get("host")||""}`)},transformResponse:({body:a,headers:c,status:R})=>{let p=ue();return new p(a,{status:R,headers:c})}})}).createHandler(),r=t.bind(null,void 0);return Object.defineProperties(r,{GET:{value:t.bind(null,"GET")},POST:{value:t.bind(null,"POST")},OPTIONS:{value:t.bind(null,"OPTIONS")}})};
25
25
 
26
26
  exports.frameworkName = Ue;
27
27
  exports.serve = Cr;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@novu/framework",
3
- "version": "2.0.0-canary.0",
3
+ "version": "2.0.0-canary.2",
4
4
  "description": "The Code-First Notifications Workflow SDK.",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -139,7 +139,7 @@
139
139
  "zod-to-json-schema": "^3.23.0"
140
140
  },
141
141
  "dependencies": {
142
- "@novu/shared": "2.0.0-canary.0",
142
+ "@novu/shared": "^2.0.0-canary.0",
143
143
  "ajv": "^8.12.0",
144
144
  "ajv-formats": "^2.1.1",
145
145
  "better-ajv-errors": "^1.2.0",