@spfn/core 0.2.0-beta.4 → 0.2.0-beta.6

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.
@@ -61,11 +61,15 @@ interface JobSendOptions {
61
61
  /**
62
62
  * Job handler function type
63
63
  */
64
- type JobHandler<TInput> = TInput extends void ? () => Promise<void> : (input: TInput) => Promise<void>;
64
+ type JobHandler<TInput, TOutput = void> = TInput extends void ? () => Promise<TOutput> : (input: TInput) => Promise<TOutput>;
65
+ /**
66
+ * Compensate handler function type (for rollback)
67
+ */
68
+ type CompensateHandler<TInput, TOutput> = (input: TInput, output: TOutput) => Promise<void>;
65
69
  /**
66
70
  * Job definition interface
67
71
  */
68
- interface JobDef<TInput = void> {
72
+ interface JobDef<TInput = void, TOutput = void> {
69
73
  /**
70
74
  * Unique job name
71
75
  */
@@ -74,6 +78,10 @@ interface JobDef<TInput = void> {
74
78
  * TypeBox input schema (optional)
75
79
  */
76
80
  readonly inputSchema?: TSchema;
81
+ /**
82
+ * TypeBox output schema (optional, for workflow integration)
83
+ */
84
+ readonly outputSchema?: TSchema;
77
85
  /**
78
86
  * Cron expression for scheduled jobs
79
87
  */
@@ -97,7 +105,11 @@ interface JobDef<TInput = void> {
97
105
  /**
98
106
  * Job handler
99
107
  */
100
- readonly handler: JobHandler<TInput>;
108
+ readonly handler: JobHandler<TInput, TOutput>;
109
+ /**
110
+ * Compensate handler for rollback (optional, for workflow integration)
111
+ */
112
+ readonly compensate?: CompensateHandler<TInput, TOutput>;
101
113
  /**
102
114
  * Send job to queue (returns immediately, executes in background)
103
115
  */
@@ -105,16 +117,17 @@ interface JobDef<TInput = void> {
105
117
  /**
106
118
  * Run job synchronously (for testing/debugging)
107
119
  */
108
- run: TInput extends void ? () => Promise<void> : (input: TInput) => Promise<void>;
120
+ run: TInput extends void ? () => Promise<TOutput> : (input: TInput) => Promise<TOutput>;
109
121
  /**
110
122
  * Type inference helpers
111
123
  */
112
124
  _input: TInput;
125
+ _output: TOutput;
113
126
  }
114
127
  /**
115
128
  * Job router entry - can be a job or nested router
116
129
  */
117
- type JobRouterEntry = JobDef<any> | JobRouter<any>;
130
+ type JobRouterEntry = JobDef<any, any> | JobRouter<any>;
118
131
  /**
119
132
  * Job router interface
120
133
  */
@@ -125,7 +138,11 @@ interface JobRouter<TJobs extends Record<string, JobRouterEntry> = Record<string
125
138
  /**
126
139
  * Infer input type from JobDef
127
140
  */
128
- type InferJobInput<TJob> = TJob extends JobDef<infer TInput> ? TInput : never;
141
+ type InferJobInput<TJob> = TJob extends JobDef<infer TInput, any> ? TInput : never;
142
+ /**
143
+ * Infer output type from JobDef
144
+ */
145
+ type InferJobOutput<TJob> = TJob extends JobDef<any, infer TOutput> ? TOutput : never;
129
146
 
130
147
  /**
131
148
  * pg-boss Wrapper
@@ -224,4 +241,4 @@ declare function isBossRunning(): boolean;
224
241
  */
225
242
  declare function shouldClearOnStart(): boolean;
226
243
 
227
- export { type BossOptions as B, type InferJobInput as I, type JobRouter as J, type JobOptions as a, type JobHandler as b, type JobDef as c, type JobRouterEntry as d, type JobSendOptions as e, isBossRunning as f, getBoss as g, shouldClearOnStart as h, initBoss as i, type BossConfig as j, stopBoss as s };
244
+ export { type BossOptions as B, type CompensateHandler as C, type InferJobInput as I, type JobRouter as J, type JobOptions as a, type JobHandler as b, type JobDef as c, type JobRouterEntry as d, type JobSendOptions as e, type InferJobOutput as f, getBoss as g, isBossRunning as h, initBoss as i, shouldClearOnStart as j, type BossConfig as k, stopBoss as s };
@@ -376,6 +376,10 @@ interface DrizzleConfigOptions {
376
376
  packageFilter?: string;
377
377
  /** Expand glob patterns to actual file paths (useful for Drizzle Studio) */
378
378
  expandGlobs?: boolean;
379
+ /** PostgreSQL schema filter for push/introspect commands */
380
+ schemaFilter?: string[];
381
+ /** Auto-detect PostgreSQL schemas from entity files (requires expandGlobs: true) */
382
+ autoDetectSchemas?: boolean;
379
383
  }
380
384
  /**
381
385
  * Detect database dialect from connection URL
@@ -407,6 +411,15 @@ declare function getDrizzleConfig(options?: DrizzleConfigOptions): {
407
411
  dbCredentials: {
408
412
  url: string;
409
413
  };
414
+ schemaFilter?: undefined;
415
+ } | {
416
+ schema: string | string[];
417
+ out: string;
418
+ dialect: "postgresql" | "mysql" | "sqlite";
419
+ dbCredentials: {
420
+ url: string;
421
+ };
422
+ schemaFilter: string[] | undefined;
410
423
  };
411
424
  /**
412
425
  * Generate drizzle.config.ts file content
package/dist/db/index.js CHANGED
@@ -880,6 +880,27 @@ function scanDirectorySingleLevel(dir, filePattern) {
880
880
  }
881
881
  return files;
882
882
  }
883
+ function detectSchemasFromFiles(files) {
884
+ const schemas = /* @__PURE__ */ new Set(["public"]);
885
+ const pgSchemaPattern = /pgSchema\s*\(\s*['"]([^'"]+)['"]\s*\)/g;
886
+ const createSchemaPattern = /createSchema\s*\(\s*['"]([^'"]+)['"]\s*\)/g;
887
+ for (const filePath of files) {
888
+ try {
889
+ const content = readFileSync(filePath, "utf-8");
890
+ let match;
891
+ while ((match = pgSchemaPattern.exec(content)) !== null) {
892
+ schemas.add(match[1]);
893
+ }
894
+ while ((match = createSchemaPattern.exec(content)) !== null) {
895
+ const packageName = match[1];
896
+ const schemaName = packageName.replace(/@/g, "").replace(/\//g, "_").replace(/-/g, "_");
897
+ schemas.add(schemaName);
898
+ }
899
+ } catch {
900
+ }
901
+ }
902
+ return Array.from(schemas);
903
+ }
883
904
  function expandGlobPattern(pattern) {
884
905
  if (!pattern.includes("*")) {
885
906
  return existsSync(pattern) ? [pattern] : [];
@@ -991,21 +1012,32 @@ function getDrizzleConfig(options = {}) {
991
1012
  const userSchemas = Array.isArray(userSchema) ? userSchema : [userSchema];
992
1013
  const packageSchemas = options.disablePackageDiscovery ? [] : discoverPackageSchemas(options.cwd ?? process.cwd());
993
1014
  let allSchemas = [...userSchemas, ...packageSchemas];
1015
+ const cwd = options.cwd ?? process.cwd();
1016
+ let expandedFiles = [];
994
1017
  if (options.expandGlobs) {
995
- const expandedSchemas = [];
996
1018
  for (const schema2 of allSchemas) {
997
- const expanded = expandGlobPattern(schema2);
1019
+ const absoluteSchema = isAbsolutePath(schema2) ? schema2 : join(cwd, schema2);
1020
+ const expanded = expandGlobPattern(absoluteSchema);
998
1021
  const filtered = filterIndexFiles(expanded);
999
- expandedSchemas.push(...filtered);
1022
+ expandedFiles.push(...filtered);
1000
1023
  }
1001
- allSchemas = expandedSchemas;
1024
+ allSchemas = expandedFiles;
1002
1025
  }
1003
1026
  const schema = allSchemas.length === 1 ? allSchemas[0] : allSchemas;
1027
+ let schemaFilter;
1028
+ if (dialect === "postgresql") {
1029
+ if (options.schemaFilter) {
1030
+ schemaFilter = options.schemaFilter;
1031
+ } else if (options.autoDetectSchemas && expandedFiles.length > 0) {
1032
+ schemaFilter = detectSchemasFromFiles(expandedFiles);
1033
+ }
1034
+ }
1004
1035
  return {
1005
1036
  schema,
1006
1037
  out,
1007
1038
  dialect,
1008
- dbCredentials: getDbCredentials(dialect, databaseUrl)
1039
+ dbCredentials: getDbCredentials(dialect, databaseUrl),
1040
+ schemaFilter
1009
1041
  };
1010
1042
  }
1011
1043
  function getDbCredentials(dialect, url) {
@@ -1032,13 +1064,15 @@ function generateDrizzleConfigFile(options = {}) {
1032
1064
  const schemaValue = Array.isArray(config.schema) ? `[
1033
1065
  ${config.schema.map((s) => `'${normalizeSchemaPath(s)}'`).join(",\n ")}
1034
1066
  ]` : `'${normalizeSchemaPath(config.schema)}'`;
1067
+ const schemaFilterLine = config.schemaFilter && config.schemaFilter.length > 0 ? `
1068
+ schemaFilter: ${JSON.stringify(config.schemaFilter)},` : "";
1035
1069
  return `import { defineConfig } from 'drizzle-kit';
1036
1070
 
1037
1071
  export default defineConfig({
1038
1072
  schema: ${schemaValue},
1039
1073
  out: '${config.out}',
1040
1074
  dialect: '${config.dialect}',
1041
- dbCredentials: ${JSON.stringify(config.dbCredentials, null, 4)},
1075
+ dbCredentials: ${JSON.stringify(config.dbCredentials, null, 4)},${schemaFilterLine}
1042
1076
  });
1043
1077
  `;
1044
1078
  }