blokctl 0.6.10 → 0.6.11

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.
@@ -17,7 +17,7 @@ const exec = util.promisify(child_process.exec);
17
17
  const HOME_DIR = `${os.homedir()}/.blok`;
18
18
  const GITHUB_REPO_LOCAL = `${HOME_DIR}/blok`;
19
19
  const GITHUB_REPO_REMOTE = "https://github.com/well-prado/blok.git";
20
- const GITHUB_REPO_RELEASE_TAG = "v0.6.10";
20
+ const GITHUB_REPO_RELEASE_TAG = "v0.6.11";
21
21
  fsExtra.ensureDirSync(HOME_DIR);
22
22
  const options = {
23
23
  baseDir: HOME_DIR,
@@ -264,15 +264,15 @@ export async function createProject(opts, version, currentPath = false, localRep
264
264
  const triggerConfigs = selectedTriggers.map((kind) => createTriggerConfig(kind));
265
265
  const mountedOnHttp = new Set();
266
266
  if (selectedTriggers.includes("http")) {
267
- for (const kind of ["sse", "websocket"]) {
267
+ for (const kind of ["sse", "websocket", "webhook"]) {
268
268
  if (selectedTriggers.includes(kind))
269
269
  mountedOnHttp.add(kind);
270
270
  }
271
271
  }
272
272
  const spawnedTriggerConfigs = triggerConfigs.filter((tc) => !mountedOnHttp.has(tc.kind));
273
273
  const primaryTrigger = selectedTriggers[0];
274
- const primaryTriggerDir = primaryTrigger === "pubsub" || primaryTrigger === "queue"
275
- ? `${repoSource}/triggers/${primaryTrigger === "queue" ? "worker" : primaryTrigger}/template`
274
+ const primaryTriggerDir = primaryTrigger === "pubsub" || primaryTrigger === "queue" || primaryTrigger === "worker"
275
+ ? `${repoSource}/triggers/${primaryTrigger === "queue" || primaryTrigger === "worker" ? "worker" : primaryTrigger}/template`
276
276
  : `${repoSource}/triggers/${primaryTrigger}`;
277
277
  const baseFiles = ["package.json", "tsconfig.json", ".env.example", ".gitignore", "vitest.config.ts"];
278
278
  for (const file of baseFiles) {
@@ -318,8 +318,8 @@ export async function createProject(opts, version, currentPath = false, localRep
318
318
  for (const triggerKind of selectedTriggers) {
319
319
  const triggerDestDir = `${dirPath}/src/triggers/${triggerKind}`;
320
320
  fsExtra.ensureDirSync(triggerDestDir);
321
- if (triggerKind === "pubsub" || triggerKind === "queue") {
322
- const templatePkgDir = triggerKind === "queue" ? "worker" : triggerKind;
321
+ if (triggerKind === "pubsub" || triggerKind === "queue" || triggerKind === "worker") {
322
+ const templatePkgDir = triggerKind === "queue" || triggerKind === "worker" ? "worker" : triggerKind;
323
323
  const templateDir = `${repoSource}/triggers/${templatePkgDir}/template/src`;
324
324
  if (fsExtra.existsSync(templateDir)) {
325
325
  fsExtra.copySync(templateDir, triggerDestDir);
@@ -332,7 +332,7 @@ export async function createProject(opts, version, currentPath = false, localRep
332
332
  if (triggerKind === "pubsub") {
333
333
  updatePubSubProvider(triggerDestDir, pubsubProvider);
334
334
  }
335
- else if (triggerKind === "queue") {
335
+ else if (triggerKind === "queue" || triggerKind === "worker") {
336
336
  updateQueueProvider(triggerDestDir, queueProvider);
337
337
  }
338
338
  }
@@ -383,7 +383,14 @@ export async function createProject(opts, version, currentPath = false, localRep
383
383
  fsExtra.writeFileSync(`${dirPath}/src/Nodes.ts`, sharedNodesContent);
384
384
  const sharedWorkflowsContent = generateSharedWorkflowsFile(selectedTriggers);
385
385
  fsExtra.writeFileSync(`${dirPath}/src/Workflows.ts`, sharedWorkflowsContent);
386
+ const triggersWithRealTemplate = new Set(["worker", "queue", "pubsub"]);
386
387
  for (const triggerKind of selectedTriggers) {
388
+ if (triggersWithRealTemplate.has(triggerKind)) {
389
+ continue;
390
+ }
391
+ if (mountedOnHttp.has(triggerKind)) {
392
+ continue;
393
+ }
387
394
  const entryContent = generateTriggerEntryFile(triggerKind, selectedTriggers);
388
395
  fsExtra.writeFileSync(`${dirPath}/src/triggers/${triggerKind}/index.ts`, entryContent);
389
396
  }
@@ -426,7 +433,7 @@ export async function createProject(opts, version, currentPath = false, localRep
426
433
  fsExtra.ensureDirSync(`${dirPath}/infra/metrics`);
427
434
  fsExtra.copySync(`${repoSource}/infra/metrics`, `${dirPath}/infra/metrics`);
428
435
  fsExtra.removeSync(`${dirPath}/public/metric`);
429
- if (selectedTriggers.includes("queue")) {
436
+ if (selectedTriggers.includes("queue") || selectedTriggers.includes("worker")) {
430
437
  fsExtra.ensureDirSync(`${dirPath}/infra/development`);
431
438
  fsExtra.copySync(`${repoSource}/infra/development`, `${dirPath}/infra/development`);
432
439
  }
@@ -478,7 +485,7 @@ export async function createProject(opts, version, currentPath = false, localRep
478
485
  "@blokjs/trigger-websocket": "triggers/websocket",
479
486
  "@blokjs/trigger-worker": "triggers/worker",
480
487
  };
481
- const BLOKJS_DEP_RANGE = "^0.6.10";
488
+ const BLOKJS_DEP_RANGE = "^0.6.11";
482
489
  for (const depGroup of ["dependencies", "devDependencies", "peerDependencies"]) {
483
490
  const deps = packageJsonContent[depGroup];
484
491
  if (!deps)
@@ -547,7 +554,8 @@ export async function createProject(opts, version, currentPath = false, localRep
547
554
  ? `file:${path.resolve(repoSource, "triggers/pubsub")}`
548
555
  : BLOKJS_DEP_RANGE;
549
556
  }
550
- if (selectedTriggers.includes("queue")) {
557
+ const needsTriggerWorker = selectedTriggers.includes("queue") || selectedTriggers.includes("worker") || examples;
558
+ if (needsTriggerWorker) {
551
559
  triggerPackageDeps["@blokjs/trigger-worker"] = localRepoPath
552
560
  ? `file:${path.resolve(repoSource, "triggers/worker")}`
553
561
  : BLOKJS_DEP_RANGE;
@@ -721,7 +729,7 @@ export async function createProject(opts, version, currentPath = false, localRep
721
729
  console.log(` ${rc.label}: http://localhost:${rc.port}/health`);
722
730
  }
723
731
  }
724
- if (selectedTriggers.includes("queue") && queueProvider === "redis") {
732
+ if ((selectedTriggers.includes("queue") || selectedTriggers.includes("worker")) && queueProvider === "redis") {
725
733
  console.log(color.cyan("\nšŸ“¦ Redis Setup (for Queue trigger):"));
726
734
  console.log(" Start Redis with Docker:");
727
735
  console.log(color.dim(" cd infra/development"));
@@ -729,7 +737,7 @@ export async function createProject(opts, version, currentPath = false, localRep
729
737
  console.log(color.dim(" docker compose up -d redis redis-commander"));
730
738
  console.log(" Redis Commander UI: http://localhost:8081");
731
739
  }
732
- if (selectedTriggers.includes("queue") && queueProvider === "nats") {
740
+ if ((selectedTriggers.includes("queue") || selectedTriggers.includes("worker")) && queueProvider === "nats") {
733
741
  console.log(color.cyan("\nšŸ“¦ NATS JetStream Setup (for Queue trigger):"));
734
742
  console.log(" Start NATS with Docker:");
735
743
  console.log(color.dim(" cd infra/development"));
@@ -799,8 +807,8 @@ function generateSharedWorkflowsFile(triggers) {
799
807
  imports.push('import OnPubSubMessage from "./workflows/pubsub/messages/on-message";');
800
808
  workflowEntries.push('\t"on-pubsub-message": OnPubSubMessage,');
801
809
  }
802
- else if (trigger === "queue") {
803
- imports.push('import ProcessJob from "./workflows/queue/jobs/process-job";');
810
+ else if (trigger === "queue" || trigger === "worker") {
811
+ imports.push(`import ProcessJob from "./workflows/${trigger}/jobs/process-job";`);
804
812
  workflowEntries.push('\t"process-job": ProcessJob,');
805
813
  }
806
814
  }
@@ -820,12 +828,14 @@ function generateTriggerEntryFile(triggerKind, selectedTriggers = [triggerKind])
820
828
  if (triggerKind === "http") {
821
829
  const sseAlsoSelected = selectedTriggers.includes("sse");
822
830
  const wsAlsoSelected = selectedTriggers.includes("websocket");
823
- const needsShared = sseAlsoSelected || wsAlsoSelected;
831
+ const webhookAlsoSelected = selectedTriggers.includes("webhook");
832
+ const needsShared = sseAlsoSelected || wsAlsoSelected || webhookAlsoSelected;
824
833
  const sharedHelperImports = needsShared
825
834
  ? `\nimport { NodeMap, WorkflowRegistry } from "@blokjs/runner";\nimport sharedNodes from "../../Nodes";\nimport sharedWorkflows from "../../Workflows";`
826
835
  : "";
827
836
  const sseImports = sseAlsoSelected ? `\nimport SSETrigger from "@blokjs/trigger-sse";` : "";
828
837
  const wsImports = wsAlsoSelected ? `\nimport WebSocketTrigger from "@blokjs/trigger-websocket";` : "";
838
+ const webhookImports = webhookAlsoSelected ? `\nimport WebhookTrigger from "@blokjs/trigger-webhook";` : "";
829
839
  const sharedBootstrapPrelude = needsShared
830
840
  ? `\n\n // Build a NodeMap from the shared Nodes record; both SSE and
831
841
  // WebSocket triggers consume this via setNodeMap so they can
@@ -848,15 +858,15 @@ function generateTriggerEntryFile(triggerKind, selectedTriggers = [triggerKind])
848
858
  for (const [name, wf] of Object.entries(sharedWorkflows)) {
849
859
  const w = wf as {
850
860
  name?: string;
851
- trigger?: { sse?: unknown; websocket?: unknown };
852
- _config?: { name?: string; trigger?: { sse?: unknown; websocket?: unknown } };
861
+ trigger?: { sse?: unknown; websocket?: unknown; webhook?: unknown };
862
+ _config?: { name?: string; trigger?: { sse?: unknown; websocket?: unknown; webhook?: unknown } };
853
863
  };
854
864
  const triggerCfg = w._config?.trigger ?? w.trigger;
855
865
  if (!triggerCfg) continue;
856
- if (!triggerCfg.sse && !triggerCfg.websocket) continue;
866
+ if (!triggerCfg.sse && !triggerCfg.websocket && !triggerCfg.webhook) continue;
857
867
  const resolvedName = w._config?.name ?? w.name ?? name;
858
868
  if (registry.get(resolvedName)) continue;
859
- const kind = triggerCfg.sse ? "sse" : "websocket";
869
+ const kind = triggerCfg.sse ? "sse" : triggerCfg.websocket ? "websocket" : "webhook";
860
870
  registry.register({
861
871
  name: resolvedName,
862
872
  source: \`\${kind}:\${name}\`,
@@ -893,10 +903,26 @@ function generateTriggerEntryFile(triggerKind, selectedTriggers = [triggerKind])
893
903
  });
894
904
  await wsTrigger.listen();`
895
905
  : "";
896
- const fullBootstrap = `${sharedBootstrapPrelude}${sseBootstrap}${wsBootstrap}`;
906
+ const webhookBootstrap = webhookAlsoSelected
907
+ ? `\n // Mount Webhook trigger on the HTTP process's shared Hono app.
908
+ // WebhookTrigger.constructor(app, httpTrigger?) mirrors SSE / WS —
909
+ // when an HttpTrigger is supplied, the webhook trigger registers
910
+ // its /webhooks/<provider> routes inside addPreCatchAllHook so they
911
+ // win Hono's first-match dispatch over the legacy workflow catch-
912
+ // all. The shared @blokjs/trigger-webhook singleton this creates
913
+ // is also what @blokjs/hmac-verify (and other webhook-aware helpers)
914
+ // look up at run time.
915
+ const webhookTrigger = new WebhookTrigger(this.httpTrigger.getApp(), this.httpTrigger);
916
+ webhookTrigger.setNodeMap({
917
+ nodes: subTriggerNodeMap,
918
+ workflows: sharedWorkflows as unknown as Parameters<typeof webhookTrigger.setNodeMap>[0]["workflows"],
919
+ });
920
+ await webhookTrigger.listen();`
921
+ : "";
922
+ const fullBootstrap = `${sharedBootstrapPrelude}${sseBootstrap}${wsBootstrap}${webhookBootstrap}`;
897
923
  return `import { DefaultLogger } from "@blokjs/runner";
898
924
  import { type Span, metrics, trace } from "@opentelemetry/api";
899
- import HttpTrigger from "./runner/HttpTrigger";${sharedHelperImports}${sseImports}${wsImports}
925
+ import HttpTrigger from "./runner/HttpTrigger";${sharedHelperImports}${sseImports}${wsImports}${webhookImports}
900
926
 
901
927
  export default class App {
902
928
  private httpTrigger: HttpTrigger = <HttpTrigger>{};
@@ -1370,7 +1396,7 @@ function fixRunnerImportPaths(triggerDestDir, triggerKind) {
1370
1396
  else if (triggerKind === "pubsub") {
1371
1397
  fileFixes.push({ file: `${triggerDestDir}/runner/PubSubServer.ts`, up: "../../../" });
1372
1398
  }
1373
- else if (triggerKind === "queue") {
1399
+ else if (triggerKind === "queue" || triggerKind === "worker") {
1374
1400
  fileFixes.push({ file: `${triggerDestDir}/runner/WorkerServer.ts`, up: "../../../" });
1375
1401
  }
1376
1402
  for (const { file, up } of fileFixes) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "blokctl",
3
- "version": "0.6.10",
3
+ "version": "0.6.11",
4
4
  "author": "Deskree Technologies Inc.",
5
5
  "license": "Apache-2.0",
6
6
  "description": "cli for blok",
@@ -30,7 +30,7 @@
30
30
  "keywords": ["blokctl", "cli", "blok", "blok"],
31
31
  "dependencies": {
32
32
  "@ai-sdk/openai": "^1.3.22",
33
- "@blokjs/runner": "^0.6.10",
33
+ "@blokjs/runner": "^0.6.11",
34
34
  "@clack/prompts": "^1.0.0",
35
35
  "ai": "^4.3.16",
36
36
  "better-sqlite3": "^12.6.2",