alepha 0.12.1 → 0.13.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (198) hide show
  1. package/dist/api-notifications/index.d.ts +111 -111
  2. package/dist/api-users/index.d.ts +1240 -1240
  3. package/dist/api-verifications/index.d.ts +94 -94
  4. package/dist/cli/{dist-Sz2EXvQX.cjs → dist-Dl9Vl7Ur.js} +17 -13
  5. package/dist/cli/{dist-BBPjuQ56.js.map → dist-Dl9Vl7Ur.js.map} +1 -1
  6. package/dist/cli/index.d.ts +3 -11
  7. package/dist/cli/index.js +106 -74
  8. package/dist/cli/index.js.map +1 -1
  9. package/dist/email/index.js +71 -73
  10. package/dist/email/index.js.map +1 -1
  11. package/dist/orm/index.d.ts +1 -1
  12. package/dist/orm/index.js.map +1 -1
  13. package/dist/queue/index.d.ts +4 -4
  14. package/dist/redis/index.d.ts +10 -10
  15. package/dist/retry/index.d.ts +1 -1
  16. package/dist/retry/index.js +2 -2
  17. package/dist/retry/index.js.map +1 -1
  18. package/dist/scheduler/index.d.ts +6 -6
  19. package/dist/server/index.js +1 -1
  20. package/dist/server/index.js.map +1 -1
  21. package/dist/server-auth/index.d.ts +193 -193
  22. package/dist/server-health/index.d.ts +17 -17
  23. package/dist/server-links/index.d.ts +34 -34
  24. package/dist/server-metrics/index.js +170 -174
  25. package/dist/server-metrics/index.js.map +1 -1
  26. package/dist/server-security/index.d.ts +9 -9
  27. package/dist/vite/index.js +4 -5
  28. package/dist/vite/index.js.map +1 -1
  29. package/dist/websocket/index.d.ts +7 -7
  30. package/package.json +52 -103
  31. package/src/cli/apps/AlephaPackageBuilderCli.ts +7 -2
  32. package/src/cli/assets/appRouterTs.ts +9 -0
  33. package/src/cli/assets/indexHtml.ts +2 -1
  34. package/src/cli/assets/mainBrowserTs.ts +10 -0
  35. package/src/cli/commands/CoreCommands.ts +6 -5
  36. package/src/cli/commands/DrizzleCommands.ts +65 -57
  37. package/src/cli/commands/VerifyCommands.ts +1 -1
  38. package/src/cli/services/ProjectUtils.ts +44 -38
  39. package/src/orm/providers/DrizzleKitProvider.ts +1 -1
  40. package/src/retry/descriptors/$retry.ts +5 -3
  41. package/src/server/providers/NodeHttpServerProvider.ts +1 -1
  42. package/src/vite/helpers/boot.ts +3 -3
  43. package/dist/api-files/index.cjs +0 -1293
  44. package/dist/api-files/index.cjs.map +0 -1
  45. package/dist/api-files/index.d.cts +0 -829
  46. package/dist/api-jobs/index.cjs +0 -274
  47. package/dist/api-jobs/index.cjs.map +0 -1
  48. package/dist/api-jobs/index.d.cts +0 -654
  49. package/dist/api-notifications/index.cjs +0 -380
  50. package/dist/api-notifications/index.cjs.map +0 -1
  51. package/dist/api-notifications/index.d.cts +0 -289
  52. package/dist/api-parameters/index.cjs +0 -66
  53. package/dist/api-parameters/index.cjs.map +0 -1
  54. package/dist/api-parameters/index.d.cts +0 -84
  55. package/dist/api-users/index.cjs +0 -6009
  56. package/dist/api-users/index.cjs.map +0 -1
  57. package/dist/api-users/index.d.cts +0 -4740
  58. package/dist/api-verifications/index.cjs +0 -407
  59. package/dist/api-verifications/index.cjs.map +0 -1
  60. package/dist/api-verifications/index.d.cts +0 -207
  61. package/dist/batch/index.cjs +0 -408
  62. package/dist/batch/index.cjs.map +0 -1
  63. package/dist/batch/index.d.cts +0 -330
  64. package/dist/bin/index.cjs +0 -17
  65. package/dist/bin/index.cjs.map +0 -1
  66. package/dist/bin/index.d.cts +0 -1
  67. package/dist/bucket/index.cjs +0 -303
  68. package/dist/bucket/index.cjs.map +0 -1
  69. package/dist/bucket/index.d.cts +0 -355
  70. package/dist/cache/index.cjs +0 -241
  71. package/dist/cache/index.cjs.map +0 -1
  72. package/dist/cache/index.d.cts +0 -202
  73. package/dist/cache-redis/index.cjs +0 -84
  74. package/dist/cache-redis/index.cjs.map +0 -1
  75. package/dist/cache-redis/index.d.cts +0 -40
  76. package/dist/cli/chunk-DSlc6foC.cjs +0 -43
  77. package/dist/cli/dist-BBPjuQ56.js +0 -2778
  78. package/dist/cli/dist-Sz2EXvQX.cjs.map +0 -1
  79. package/dist/cli/index.cjs +0 -1241
  80. package/dist/cli/index.cjs.map +0 -1
  81. package/dist/cli/index.d.cts +0 -422
  82. package/dist/command/index.cjs +0 -693
  83. package/dist/command/index.cjs.map +0 -1
  84. package/dist/command/index.d.cts +0 -340
  85. package/dist/core/index.cjs +0 -2264
  86. package/dist/core/index.cjs.map +0 -1
  87. package/dist/core/index.d.cts +0 -1927
  88. package/dist/datetime/index.cjs +0 -318
  89. package/dist/datetime/index.cjs.map +0 -1
  90. package/dist/datetime/index.d.cts +0 -145
  91. package/dist/email/index.cjs +0 -10874
  92. package/dist/email/index.cjs.map +0 -1
  93. package/dist/email/index.d.cts +0 -186
  94. package/dist/fake/index.cjs +0 -34641
  95. package/dist/fake/index.cjs.map +0 -1
  96. package/dist/fake/index.d.cts +0 -74
  97. package/dist/file/index.cjs +0 -1212
  98. package/dist/file/index.cjs.map +0 -1
  99. package/dist/file/index.d.cts +0 -698
  100. package/dist/lock/index.cjs +0 -226
  101. package/dist/lock/index.cjs.map +0 -1
  102. package/dist/lock/index.d.cts +0 -361
  103. package/dist/lock-redis/index.cjs +0 -113
  104. package/dist/lock-redis/index.cjs.map +0 -1
  105. package/dist/lock-redis/index.d.cts +0 -24
  106. package/dist/logger/index.cjs +0 -521
  107. package/dist/logger/index.cjs.map +0 -1
  108. package/dist/logger/index.d.cts +0 -281
  109. package/dist/orm/index.cjs +0 -2986
  110. package/dist/orm/index.cjs.map +0 -1
  111. package/dist/orm/index.d.cts +0 -2213
  112. package/dist/queue/index.cjs +0 -1044
  113. package/dist/queue/index.cjs.map +0 -1
  114. package/dist/queue/index.d.cts +0 -1265
  115. package/dist/queue-redis/index.cjs +0 -873
  116. package/dist/queue-redis/index.cjs.map +0 -1
  117. package/dist/queue-redis/index.d.cts +0 -82
  118. package/dist/redis/index.cjs +0 -153
  119. package/dist/redis/index.cjs.map +0 -1
  120. package/dist/redis/index.d.cts +0 -82
  121. package/dist/retry/index.cjs +0 -146
  122. package/dist/retry/index.cjs.map +0 -1
  123. package/dist/retry/index.d.cts +0 -172
  124. package/dist/router/index.cjs +0 -111
  125. package/dist/router/index.cjs.map +0 -1
  126. package/dist/router/index.d.cts +0 -46
  127. package/dist/scheduler/index.cjs +0 -576
  128. package/dist/scheduler/index.cjs.map +0 -1
  129. package/dist/scheduler/index.d.cts +0 -145
  130. package/dist/security/index.cjs +0 -2402
  131. package/dist/security/index.cjs.map +0 -1
  132. package/dist/security/index.d.cts +0 -598
  133. package/dist/server/index.cjs +0 -1680
  134. package/dist/server/index.cjs.map +0 -1
  135. package/dist/server/index.d.cts +0 -810
  136. package/dist/server-auth/index.cjs +0 -3146
  137. package/dist/server-auth/index.cjs.map +0 -1
  138. package/dist/server-auth/index.d.cts +0 -1164
  139. package/dist/server-cache/index.cjs +0 -252
  140. package/dist/server-cache/index.cjs.map +0 -1
  141. package/dist/server-cache/index.d.cts +0 -164
  142. package/dist/server-compress/index.cjs +0 -141
  143. package/dist/server-compress/index.cjs.map +0 -1
  144. package/dist/server-compress/index.d.cts +0 -38
  145. package/dist/server-cookies/index.cjs +0 -234
  146. package/dist/server-cookies/index.cjs.map +0 -1
  147. package/dist/server-cookies/index.d.cts +0 -144
  148. package/dist/server-cors/index.cjs +0 -201
  149. package/dist/server-cors/index.cjs.map +0 -1
  150. package/dist/server-cors/index.d.cts +0 -140
  151. package/dist/server-health/index.cjs +0 -62
  152. package/dist/server-health/index.cjs.map +0 -1
  153. package/dist/server-health/index.d.cts +0 -58
  154. package/dist/server-helmet/index.cjs +0 -131
  155. package/dist/server-helmet/index.cjs.map +0 -1
  156. package/dist/server-helmet/index.d.cts +0 -97
  157. package/dist/server-links/index.cjs +0 -992
  158. package/dist/server-links/index.cjs.map +0 -1
  159. package/dist/server-links/index.d.cts +0 -513
  160. package/dist/server-metrics/index.cjs +0 -4535
  161. package/dist/server-metrics/index.cjs.map +0 -1
  162. package/dist/server-metrics/index.d.cts +0 -35
  163. package/dist/server-multipart/index.cjs +0 -237
  164. package/dist/server-multipart/index.cjs.map +0 -1
  165. package/dist/server-multipart/index.d.cts +0 -50
  166. package/dist/server-proxy/index.cjs +0 -186
  167. package/dist/server-proxy/index.cjs.map +0 -1
  168. package/dist/server-proxy/index.d.cts +0 -234
  169. package/dist/server-rate-limit/index.cjs +0 -241
  170. package/dist/server-rate-limit/index.cjs.map +0 -1
  171. package/dist/server-rate-limit/index.d.cts +0 -183
  172. package/dist/server-security/index.cjs +0 -316
  173. package/dist/server-security/index.cjs.map +0 -1
  174. package/dist/server-security/index.d.cts +0 -173
  175. package/dist/server-static/index.cjs +0 -170
  176. package/dist/server-static/index.cjs.map +0 -1
  177. package/dist/server-static/index.d.cts +0 -121
  178. package/dist/server-swagger/index.cjs +0 -1021
  179. package/dist/server-swagger/index.cjs.map +0 -1
  180. package/dist/server-swagger/index.d.cts +0 -382
  181. package/dist/sms/index.cjs +0 -221
  182. package/dist/sms/index.cjs.map +0 -1
  183. package/dist/sms/index.d.cts +0 -130
  184. package/dist/thread/index.cjs +0 -350
  185. package/dist/thread/index.cjs.map +0 -1
  186. package/dist/thread/index.d.cts +0 -260
  187. package/dist/topic/index.cjs +0 -282
  188. package/dist/topic/index.cjs.map +0 -1
  189. package/dist/topic/index.d.cts +0 -523
  190. package/dist/topic-redis/index.cjs +0 -71
  191. package/dist/topic-redis/index.cjs.map +0 -1
  192. package/dist/topic-redis/index.d.cts +0 -42
  193. package/dist/vite/index.cjs +0 -1077
  194. package/dist/vite/index.cjs.map +0 -1
  195. package/dist/vite/index.d.cts +0 -542
  196. package/dist/websocket/index.cjs +0 -1117
  197. package/dist/websocket/index.cjs.map +0 -1
  198. package/dist/websocket/index.d.cts +0 -861
@@ -1,274 +0,0 @@
1
- let alepha = require("alepha");
2
- let alepha_server = require("alepha/server");
3
- let alepha_orm = require("alepha/orm");
4
- let alepha_logger = require("alepha/logger");
5
- let alepha_datetime = require("alepha/datetime");
6
- let alepha_lock = require("alepha/lock");
7
- let alepha_scheduler = require("alepha/scheduler");
8
-
9
- //#region src/api-jobs/schemas/jobExecutionQuerySchema.ts
10
- const jobExecutionQuerySchema = alepha.t.extend(alepha_orm.pageQuerySchema, {
11
- status: alepha.t.optional(alepha.t.enum([
12
- "STARTED",
13
- "FAILED",
14
- "COMPLETED"
15
- ])),
16
- job: alepha.t.optional(alepha.t.text({ description: "Filter by job name" }))
17
- });
18
-
19
- //#endregion
20
- //#region src/api-jobs/entities/jobExecutions.ts
21
- const jobExecutions = (0, alepha_orm.$entity)({
22
- name: "job_executions",
23
- schema: alepha.t.object({
24
- id: alepha_orm.pg.primaryKey(alepha.t.uuid()),
25
- version: alepha_orm.pg.version(),
26
- createdAt: alepha_orm.pg.createdAt(),
27
- updatedAt: alepha_orm.pg.updatedAt(),
28
- finishedAt: alepha.t.optional(alepha.t.datetime()),
29
- job: alepha.t.string(),
30
- status: alepha.t.enum([
31
- "STARTED",
32
- "FAILED",
33
- "COMPLETED"
34
- ]),
35
- error: alepha.t.optional(alepha.t.string()),
36
- logs: alepha.t.optional(alepha.t.array(alepha_logger.logEntrySchema))
37
- })
38
- });
39
-
40
- //#endregion
41
- //#region src/api-jobs/schemas/jobExecutionResourceSchema.ts
42
- const jobExecutionResourceSchema = alepha.t.extend(jobExecutions.schema, {}, {
43
- title: "JobExecutionResource",
44
- description: "A job execution resource representing the execution details of a job."
45
- });
46
-
47
- //#endregion
48
- //#region src/api-jobs/schemas/triggerJobSchema.ts
49
- const triggerJobSchema = alepha.t.object({ name: alepha.t.string() });
50
-
51
- //#endregion
52
- //#region src/api-jobs/providers/JobProvider.ts
53
- const envSchema = alepha.t.object({ JOB_PREFIX: alepha.t.optional(alepha.t.text({ description: "Prefix for job lock keys" })) });
54
- /**
55
- * Provider for job management and execution.
56
- * Handles job lifecycle, execution tracking, log capturing, and event emission.
57
- */
58
- var JobProvider = class {
59
- alepha = (0, alepha.$inject)(alepha.Alepha);
60
- dateTimeProvider = (0, alepha.$inject)(alepha_datetime.DateTimeProvider);
61
- cronProvider = (0, alepha.$inject)(alepha_scheduler.CronProvider);
62
- executionRepository = (0, alepha_orm.$repository)(jobExecutions);
63
- env = (0, alepha.$env)(envSchema);
64
- logs = /* @__PURE__ */ new Map();
65
- jobs = /* @__PURE__ */ new Map();
66
- /**
67
- * Register and set up a job for execution (called during descriptor initialization).
68
- */
69
- registerJob(options) {
70
- const jobName = options.name;
71
- if (this.jobs.size === 0) this.alepha.events.on("log", ({ entry }) => {
72
- const context = entry.context;
73
- if (!context) return;
74
- const entries = this.logs.get(context);
75
- if (!entries) return;
76
- entries.push(entry);
77
- this.logs.set(context, entries);
78
- });
79
- const registration = {
80
- name: jobName,
81
- options,
82
- lockDescriptor: options.lock !== false ? (0, alepha_lock.$lock)({
83
- name: () => {
84
- return `${this.env.JOB_PREFIX ? `${this.env.JOB_PREFIX}:` : ""}job:${jobName}`;
85
- },
86
- handler: async () => {
87
- await this.executeJob(jobName, options.handler);
88
- }
89
- }) : null
90
- };
91
- this.jobs.set(jobName, registration);
92
- if (options.cron) this.cronProvider.createCronJob(jobName, options.cron, () => this.triggerJob(jobName));
93
- return registration;
94
- }
95
- /**
96
- * Trigger a job by name.
97
- */
98
- async triggerJob(jobName) {
99
- const registration = this.jobs.get(jobName);
100
- if (!registration) throw new Error(`Job not registered: ${jobName}`);
101
- if (registration.options.lock !== false && registration.lockDescriptor) await registration.lockDescriptor.run();
102
- else await this.executeJob(jobName, registration.options.handler);
103
- }
104
- /**
105
- * Execute a job handler (called by the job descriptor).
106
- */
107
- async executeJob(jobName, handler) {
108
- if (!this.alepha.isStarted()) return;
109
- const context = this.alepha.context.createContextId();
110
- await this.alepha.context.run(async () => {
111
- try {
112
- const now = this.dateTimeProvider.now();
113
- this.logs.set(context, []);
114
- await this.executionRepository.create({
115
- job: jobName,
116
- status: "STARTED"
117
- });
118
- await this.alepha.events.emit("scheduler:begin", {
119
- name: jobName,
120
- now,
121
- context
122
- });
123
- await handler({ now });
124
- const logs = this.logs.get(context) || [];
125
- const exec = await this.executionRepository.findOne({ where: {
126
- job: jobName,
127
- status: "STARTED"
128
- } });
129
- exec.status = "COMPLETED";
130
- exec.logs = logs;
131
- exec.finishedAt = this.dateTimeProvider.nowISOString();
132
- await this.executionRepository.save(exec);
133
- await this.alepha.events.emit("scheduler:success", {
134
- name: jobName,
135
- context
136
- }, { catch: true });
137
- } catch (error) {
138
- const logs = this.logs.get(context) || [];
139
- const exec = await this.executionRepository.findOne({ where: {
140
- job: jobName,
141
- status: "STARTED"
142
- } });
143
- exec.status = "FAILED";
144
- exec.error = error.message;
145
- exec.logs = logs;
146
- exec.finishedAt = this.dateTimeProvider.nowISOString();
147
- await this.executionRepository.save(exec);
148
- await this.alepha.events.emit("scheduler:error", {
149
- name: jobName,
150
- error,
151
- context
152
- }, { catch: true });
153
- }
154
- this.logs.delete(context);
155
- await this.alepha.events.emit("scheduler:end", {
156
- name: jobName,
157
- context
158
- }, { catch: true });
159
- }, { context });
160
- }
161
- };
162
-
163
- //#endregion
164
- //#region src/api-jobs/descriptors/$job.ts
165
- /**
166
- * Job descriptor - a drop-in replacement for $scheduler with built-in execution tracking.
167
- */
168
- const $job = (options) => {
169
- return (0, alepha.createDescriptor)(JobDescriptor, options);
170
- };
171
- var JobDescriptor = class extends alepha.Descriptor {
172
- jobProvider = (0, alepha.$inject)(JobProvider);
173
- get name() {
174
- return this.options.name ?? `${this.config.service.name}.${this.config.propertyKey}`;
175
- }
176
- onInit() {
177
- this.jobProvider.registerJob({
178
- ...this.options,
179
- name: this.name
180
- });
181
- }
182
- async trigger() {
183
- await this.jobProvider.triggerJob(this.name);
184
- }
185
- };
186
- $job[alepha.KIND] = JobDescriptor;
187
-
188
- //#endregion
189
- //#region src/api-jobs/services/JobService.ts
190
- var JobService = class {
191
- alepha = (0, alepha.$inject)(alepha.Alepha);
192
- executionRepository = (0, alepha_orm.$repository)(jobExecutions);
193
- async getJobs() {
194
- return this.alepha.descriptors($job).map((job) => job.name);
195
- }
196
- async getJobExecutions(query = {}) {
197
- query.sort ??= "-createdAt";
198
- const where = this.executionRepository.createQueryWhere();
199
- if (query.job) where.job = { eq: query.job };
200
- if (query.status) where.status = { eq: query.status };
201
- return await this.executionRepository.paginate(query, { where }, { count: true });
202
- }
203
- async triggerJob(name) {
204
- const job = this.alepha.descriptors($job).find((j) => j.name === name);
205
- if (!job) throw new Error(`Job not found: ${name}`);
206
- await job.trigger();
207
- return { ok: true };
208
- }
209
- };
210
-
211
- //#endregion
212
- //#region src/api-jobs/controllers/JobController.ts
213
- var JobController = class {
214
- url = "/jobs";
215
- group = "jobs";
216
- jobService = (0, alepha.$inject)(JobService);
217
- getJobs = (0, alepha_server.$action)({
218
- path: this.url,
219
- group: this.group,
220
- schema: { response: alepha.t.array(alepha.t.string()) },
221
- handler: () => this.jobService.getJobs()
222
- });
223
- getJobExecutions = (0, alepha_server.$action)({
224
- path: `${this.url}/executions`,
225
- group: this.group,
226
- schema: {
227
- query: jobExecutionQuerySchema,
228
- response: alepha.t.page(jobExecutionResourceSchema)
229
- },
230
- handler: ({ query }) => this.jobService.getJobExecutions(query)
231
- });
232
- triggerJob = (0, alepha_server.$action)({
233
- method: "POST",
234
- path: `${this.url}/trigger`,
235
- group: this.group,
236
- schema: {
237
- body: triggerJobSchema,
238
- response: alepha_server.okSchema
239
- },
240
- handler: ({ body }) => this.jobService.triggerJob(body.name)
241
- });
242
- };
243
-
244
- //#endregion
245
- //#region src/api-jobs/index.ts
246
- /**
247
- * Provides job management API endpoints for Alepha applications.
248
- *
249
- * This module includes job queue operations, job status monitoring,
250
- * and background task management capabilities.
251
- *
252
- * @module alepha.api.jobs
253
- */
254
- const AlephaApiJobs = (0, alepha.$module)({
255
- name: "alepha.api.jobs",
256
- services: [
257
- JobController,
258
- JobProvider,
259
- JobService
260
- ]
261
- });
262
-
263
- //#endregion
264
- exports.$job = $job;
265
- exports.AlephaApiJobs = AlephaApiJobs;
266
- exports.JobController = JobController;
267
- exports.JobDescriptor = JobDescriptor;
268
- exports.JobProvider = JobProvider;
269
- exports.JobService = JobService;
270
- exports.jobExecutionQuerySchema = jobExecutionQuerySchema;
271
- exports.jobExecutionResourceSchema = jobExecutionResourceSchema;
272
- exports.jobExecutions = jobExecutions;
273
- exports.triggerJobSchema = triggerJobSchema;
274
- //# sourceMappingURL=index.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.cjs","names":["t","pageQuerySchema","t","pg","logEntrySchema","t","t","t","Alepha","DateTimeProvider","CronProvider","registration: JobRegistration","Descriptor","KIND","Alepha","t","okSchema"],"sources":["../../src/api-jobs/schemas/jobExecutionQuerySchema.ts","../../src/api-jobs/entities/jobExecutions.ts","../../src/api-jobs/schemas/jobExecutionResourceSchema.ts","../../src/api-jobs/schemas/triggerJobSchema.ts","../../src/api-jobs/providers/JobProvider.ts","../../src/api-jobs/descriptors/$job.ts","../../src/api-jobs/services/JobService.ts","../../src/api-jobs/controllers/JobController.ts","../../src/api-jobs/index.ts"],"sourcesContent":["import type { Static } from \"alepha\";\nimport { t } from \"alepha\";\nimport { pageQuerySchema } from \"alepha/orm\";\n\nexport const jobExecutionQuerySchema = t.extend(pageQuerySchema, {\n status: t.optional(t.enum([\"STARTED\", \"FAILED\", \"COMPLETED\"])),\n job: t.optional(\n t.text({\n description: \"Filter by job name\",\n }),\n ),\n});\n\nexport type JobExecutionQuery = Static<typeof jobExecutionQuerySchema>;\n","import { type Static, t } from \"alepha\";\nimport { logEntrySchema } from \"alepha/logger\";\nimport { $entity, pg } from \"alepha/orm\";\n\nexport const jobExecutions = $entity({\n name: \"job_executions\",\n schema: t.object({\n id: pg.primaryKey(t.uuid()),\n version: pg.version(),\n createdAt: pg.createdAt(),\n updatedAt: pg.updatedAt(),\n finishedAt: t.optional(t.datetime()),\n job: t.string(),\n status: t.enum([\"STARTED\", \"FAILED\", \"COMPLETED\"]),\n error: t.optional(t.string()),\n logs: t.optional(t.array(logEntrySchema)),\n }),\n});\n\nexport type JobExecutionEntity = Static<typeof jobExecutions.schema>;\n","import { type Static, t } from \"alepha\";\nimport { jobExecutions } from \"../entities/jobExecutions.ts\";\n\nexport const jobExecutionResourceSchema = t.extend(\n jobExecutions.schema,\n {},\n {\n title: \"JobExecutionResource\",\n description:\n \"A job execution resource representing the execution details of a job.\",\n },\n);\n\nexport type JobExecutionResource = Static<typeof jobExecutionResourceSchema>;\n","import type { Static } from \"alepha\";\nimport { t } from \"alepha\";\n\nexport const triggerJobSchema = t.object({\n name: t.string(),\n});\n\nexport type TriggerJob = Static<typeof triggerJobSchema>;\n","import { $env, $inject, Alepha, type Async, type Static, t } from \"alepha\";\nimport { type DateTime, DateTimeProvider } from \"alepha/datetime\";\nimport { $lock, type LockDescriptor } from \"alepha/lock\";\nimport type { LogEntry } from \"alepha/logger\";\nimport { $repository } from \"alepha/orm\";\nimport { CronProvider } from \"alepha/scheduler\";\nimport { jobExecutions } from \"../entities/jobExecutions.ts\";\n\nconst envSchema = t.object({\n JOB_PREFIX: t.optional(\n t.text({\n description: \"Prefix for job lock keys\",\n }),\n ),\n});\n\ndeclare module \"alepha\" {\n interface Env extends Partial<Static<typeof envSchema>> {}\n}\n\n/**\n * Provider for job management and execution.\n * Handles job lifecycle, execution tracking, log capturing, and event emission.\n */\nexport class JobProvider {\n protected readonly alepha = $inject(Alepha);\n protected readonly dateTimeProvider = $inject(DateTimeProvider);\n protected readonly cronProvider = $inject(CronProvider);\n protected readonly executionRepository = $repository(jobExecutions);\n protected readonly env = $env(envSchema);\n protected readonly logs = new Map<string, LogEntry[]>();\n protected readonly jobs = new Map<string, JobRegistration>();\n\n /**\n * Register and set up a job for execution (called during descriptor initialization).\n */\n public registerJob(options: Job): JobRegistration {\n const jobName = options.name;\n\n // Set up log capturing for this job (only once)\n if (this.jobs.size === 0) {\n this.alepha.events.on(\"log\", ({ entry }) => {\n const context = entry.context;\n if (!context) {\n return;\n }\n\n const entries = this.logs.get(context);\n if (!entries) {\n return;\n }\n\n entries.push(entry);\n this.logs.set(context, entries);\n });\n }\n\n // Create lock descriptor if locking is enabled\n const lockDescriptor =\n options.lock !== false\n ? $lock({\n name: () => {\n const prefix = this.env.JOB_PREFIX\n ? `${this.env.JOB_PREFIX}:`\n : \"\";\n return `${prefix}job:${jobName}`;\n },\n handler: async () => {\n await this.executeJob(jobName, options.handler);\n },\n })\n : null;\n\n const registration: JobRegistration = {\n name: jobName,\n options,\n lockDescriptor,\n };\n\n this.jobs.set(jobName, registration);\n\n // Set up cron scheduling if provided\n if (options.cron) {\n this.cronProvider.createCronJob(jobName, options.cron, () =>\n this.triggerJob(jobName),\n );\n }\n\n return registration;\n }\n\n /**\n * Trigger a job by name.\n */\n public async triggerJob(jobName: string): Promise<void> {\n const registration = this.jobs.get(jobName);\n if (!registration) {\n throw new Error(`Job not registered: ${jobName}`);\n }\n\n // Execute handler with or without lock\n if (registration.options.lock !== false && registration.lockDescriptor) {\n await registration.lockDescriptor.run();\n } else {\n await this.executeJob(jobName, registration.options.handler);\n }\n }\n\n /**\n * Execute a job handler (called by the job descriptor).\n */\n public async executeJob(\n jobName: string,\n handler: (args: { now: DateTime }) => Async<void>,\n ): Promise<void> {\n if (!this.alepha.isStarted()) {\n return;\n }\n\n const context = this.alepha.context.createContextId();\n\n await this.alepha.context.run(\n async () => {\n try {\n const now = this.dateTimeProvider.now();\n\n // Initialize log collection for this context\n this.logs.set(context, []);\n\n // Create execution record\n await this.executionRepository.create({\n job: jobName,\n status: \"STARTED\",\n });\n\n await this.alepha.events.emit(\"scheduler:begin\", {\n name: jobName,\n now,\n context,\n });\n\n // Execute the handler\n await handler({ now });\n\n // Update execution as completed\n const logs = this.logs.get(context) || [];\n const exec = await this.executionRepository.findOne({\n where: {\n job: jobName,\n status: \"STARTED\",\n },\n });\n\n exec.status = \"COMPLETED\";\n exec.logs = logs;\n exec.finishedAt = this.dateTimeProvider.nowISOString();\n\n await this.executionRepository.save(exec);\n\n await this.alepha.events.emit(\n \"scheduler:success\",\n {\n name: jobName,\n context,\n },\n {\n catch: true,\n },\n );\n } catch (error) {\n // Update execution as failed\n const logs = this.logs.get(context) || [];\n const exec = await this.executionRepository.findOne({\n where: {\n job: jobName,\n status: \"STARTED\",\n },\n });\n\n exec.status = \"FAILED\";\n exec.error = (error as Error).message;\n exec.logs = logs;\n exec.finishedAt = this.dateTimeProvider.nowISOString();\n\n await this.executionRepository.save(exec);\n\n await this.alepha.events.emit(\n \"scheduler:error\",\n {\n name: jobName,\n error: error as Error,\n context,\n },\n {\n catch: true,\n },\n );\n\n // Don't re-throw, jobs should handle errors gracefully\n }\n\n // Clean up logs\n this.logs.delete(context);\n\n await this.alepha.events.emit(\n \"scheduler:end\",\n {\n name: jobName,\n context,\n },\n {\n catch: true,\n },\n );\n },\n {\n context,\n },\n );\n }\n}\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport interface Job {\n /**\n * Name of the job.\n */\n name: string;\n\n /**\n * Optional description of the job.\n */\n description?: string;\n\n /**\n * Function to run on schedule.\n */\n handler: (args: { now: DateTime }) => Async<void>;\n\n /**\n * Cron expression to run the job.\n */\n cron?: string;\n\n /**\n * If true, the job will be locked and only one instance will run at a time.\n * You probably need to import {@link AlephaLockRedis} for distributed locking.\n *\n * @default true\n */\n lock?: boolean;\n\n /**\n * Optional prefix for job lock keys.\n */\n lockPrefix?: string;\n}\n\nexport interface JobRegistration {\n name: string;\n options: Job;\n lockDescriptor: LockDescriptor<() => Promise<void>> | null;\n}\n","import { $inject, createDescriptor, Descriptor, KIND } from \"alepha\";\nimport type { DateTime } from \"alepha/datetime\";\nimport { type Job, JobProvider } from \"../providers/JobProvider.ts\";\n\n/**\n * Job descriptor - a drop-in replacement for $scheduler with built-in execution tracking.\n */\nexport const $job = (options: JobDescriptorOptions): JobDescriptor => {\n return createDescriptor(JobDescriptor, options);\n};\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport type JobDescriptorOptions = Omit<Job, \"name\"> & {\n /**\n * Name of the job. Defaults to the descriptor property name.\n */\n name?: string;\n};\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport class JobDescriptor extends Descriptor<JobDescriptorOptions> {\n protected readonly jobProvider = $inject(JobProvider);\n\n public get name(): string {\n return (\n this.options.name ??\n `${this.config.service.name}.${this.config.propertyKey}`\n );\n }\n\n protected onInit() {\n // Register job with JobProvider\n this.jobProvider.registerJob({\n ...this.options,\n name: this.name,\n });\n }\n\n public async trigger(): Promise<void> {\n await this.jobProvider.triggerJob(this.name);\n }\n}\n\n$job[KIND] = JobDescriptor;\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport interface JobHandlerArguments {\n now: DateTime;\n}\n","import { $inject, Alepha } from \"alepha\";\nimport { $repository } from \"alepha/orm\";\nimport { $job } from \"../descriptors/$job.ts\";\nimport { jobExecutions } from \"../entities/jobExecutions.ts\";\nimport type { JobExecutionQuery } from \"../schemas/jobExecutionQuerySchema.ts\";\n\nexport class JobService {\n protected readonly alepha = $inject(Alepha);\n protected readonly executionRepository = $repository(jobExecutions);\n\n public async getJobs(): Promise<string[]> {\n const jobDescriptors = this.alepha.descriptors($job);\n return jobDescriptors.map((job) => job.name);\n }\n\n public async getJobExecutions(query: JobExecutionQuery = {}) {\n query.sort ??= \"-createdAt\";\n\n const where = this.executionRepository.createQueryWhere();\n\n if (query.job) {\n where.job = { eq: query.job };\n }\n\n if (query.status) {\n where.status = { eq: query.status };\n }\n\n return await this.executionRepository.paginate(\n query,\n { where },\n { count: true },\n );\n }\n\n public async triggerJob(name: string): Promise<{ ok: boolean }> {\n const jobDescriptors = this.alepha.descriptors($job);\n const job = jobDescriptors.find((j) => j.name === name);\n\n if (!job) {\n throw new Error(`Job not found: ${name}`);\n }\n\n await job.trigger();\n return { ok: true };\n }\n}\n","import { $inject, t } from \"alepha\";\nimport { $action, okSchema } from \"alepha/server\";\nimport { jobExecutionQuerySchema } from \"../schemas/jobExecutionQuerySchema.ts\";\nimport { jobExecutionResourceSchema } from \"../schemas/jobExecutionResourceSchema.ts\";\nimport { triggerJobSchema } from \"../schemas/triggerJobSchema.ts\";\nimport { JobService } from \"../services/JobService.ts\";\n\nexport class JobController {\n protected readonly url: string = \"/jobs\";\n protected readonly group: string = \"jobs\";\n protected readonly jobService = $inject(JobService);\n\n public readonly getJobs = $action({\n path: this.url,\n group: this.group,\n schema: {\n response: t.array(t.string()),\n },\n handler: () => this.jobService.getJobs(),\n });\n\n public readonly getJobExecutions = $action({\n path: `${this.url}/executions`,\n group: this.group,\n schema: {\n query: jobExecutionQuerySchema,\n response: t.page(jobExecutionResourceSchema),\n },\n handler: ({ query }) => this.jobService.getJobExecutions(query),\n });\n\n public readonly triggerJob = $action({\n method: \"POST\",\n path: `${this.url}/trigger`,\n group: this.group,\n schema: {\n body: triggerJobSchema,\n response: okSchema,\n },\n handler: ({ body }) => this.jobService.triggerJob(body.name),\n });\n}\n","import { $module } from \"alepha\";\nimport { JobController } from \"./controllers/JobController.ts\";\nimport { JobProvider } from \"./providers/JobProvider.ts\";\nimport { JobService } from \"./services/JobService.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport * from \"./controllers/JobController.ts\";\nexport * from \"./descriptors/$job.ts\";\nexport * from \"./entities/jobExecutions.ts\";\nexport * from \"./providers/JobProvider.ts\";\nexport * from \"./schemas/jobExecutionQuerySchema.ts\";\nexport * from \"./schemas/jobExecutionResourceSchema.ts\";\nexport * from \"./schemas/triggerJobSchema.ts\";\nexport * from \"./services/JobService.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\n/**\n * Provides job management API endpoints for Alepha applications.\n *\n * This module includes job queue operations, job status monitoring,\n * and background task management capabilities.\n *\n * @module alepha.api.jobs\n */\nexport const AlephaApiJobs = $module({\n name: \"alepha.api.jobs\",\n services: [JobController, JobProvider, JobService],\n});\n"],"mappings":"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"}