@prsense/daemon 0.1.0

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 (113) hide show
  1. package/LICENSE +201 -0
  2. package/dist/bootstrap.d.ts +8 -0
  3. package/dist/bootstrap.d.ts.map +1 -0
  4. package/dist/bootstrap.js +22 -0
  5. package/dist/bootstrap.js.map +1 -0
  6. package/dist/http/health.d.ts +5 -0
  7. package/dist/http/health.d.ts.map +1 -0
  8. package/dist/http/health.js +23 -0
  9. package/dist/http/health.js.map +1 -0
  10. package/dist/http/jobs.d.ts +6 -0
  11. package/dist/http/jobs.d.ts.map +1 -0
  12. package/dist/http/jobs.js +65 -0
  13. package/dist/http/jobs.js.map +1 -0
  14. package/dist/http/webhooks/github.d.ts +9 -0
  15. package/dist/http/webhooks/github.d.ts.map +1 -0
  16. package/dist/http/webhooks/github.js +65 -0
  17. package/dist/http/webhooks/github.js.map +1 -0
  18. package/dist/http/webhooks/gitlab.d.ts +9 -0
  19. package/dist/http/webhooks/gitlab.d.ts.map +1 -0
  20. package/dist/http/webhooks/gitlab.js +56 -0
  21. package/dist/http/webhooks/gitlab.js.map +1 -0
  22. package/dist/idempotency/deliveryRegistry.d.ts +5 -0
  23. package/dist/idempotency/deliveryRegistry.d.ts.map +1 -0
  24. package/dist/idempotency/deliveryRegistry.js +24 -0
  25. package/dist/idempotency/deliveryRegistry.js.map +1 -0
  26. package/dist/index.d.ts +2 -0
  27. package/dist/index.d.ts.map +1 -0
  28. package/dist/index.js +50 -0
  29. package/dist/index.js.map +1 -0
  30. package/dist/jobs/index/runIndexJob.d.ts +5 -0
  31. package/dist/jobs/index/runIndexJob.d.ts.map +1 -0
  32. package/dist/jobs/index/runIndexJob.js +20 -0
  33. package/dist/jobs/index/runIndexJob.js.map +1 -0
  34. package/dist/jobs/index/types.d.ts +6 -0
  35. package/dist/jobs/index/types.d.ts.map +1 -0
  36. package/dist/jobs/index/types.js +2 -0
  37. package/dist/jobs/index/types.js.map +1 -0
  38. package/dist/jobs/review/runReviewJob.d.ts +5 -0
  39. package/dist/jobs/review/runReviewJob.d.ts.map +1 -0
  40. package/dist/jobs/review/runReviewJob.js +87 -0
  41. package/dist/jobs/review/runReviewJob.js.map +1 -0
  42. package/dist/jobs/review/types.d.ts +5 -0
  43. package/dist/jobs/review/types.d.ts.map +1 -0
  44. package/dist/jobs/review/types.js +2 -0
  45. package/dist/jobs/review/types.js.map +1 -0
  46. package/dist/jobs/runJob.d.ts +4 -0
  47. package/dist/jobs/runJob.d.ts.map +1 -0
  48. package/dist/jobs/runJob.js +34 -0
  49. package/dist/jobs/runJob.js.map +1 -0
  50. package/dist/jobs/store.d.ts +12 -0
  51. package/dist/jobs/store.d.ts.map +1 -0
  52. package/dist/jobs/store.js +56 -0
  53. package/dist/jobs/store.js.map +1 -0
  54. package/dist/jobs/types.d.ts +14 -0
  55. package/dist/jobs/types.d.ts.map +1 -0
  56. package/dist/jobs/types.js +2 -0
  57. package/dist/jobs/types.js.map +1 -0
  58. package/dist/lifecycle/index.d.ts +5 -0
  59. package/dist/lifecycle/index.d.ts.map +1 -0
  60. package/dist/lifecycle/index.js +5 -0
  61. package/dist/lifecycle/index.js.map +1 -0
  62. package/dist/lifecycle/start.d.ts +4 -0
  63. package/dist/lifecycle/start.d.ts.map +1 -0
  64. package/dist/lifecycle/start.js +24 -0
  65. package/dist/lifecycle/start.js.map +1 -0
  66. package/dist/lifecycle/state.d.ts +3 -0
  67. package/dist/lifecycle/state.d.ts.map +1 -0
  68. package/dist/lifecycle/state.js +11 -0
  69. package/dist/lifecycle/state.js.map +1 -0
  70. package/dist/lifecycle/status.d.ts +2 -0
  71. package/dist/lifecycle/status.d.ts.map +1 -0
  72. package/dist/lifecycle/status.js +15 -0
  73. package/dist/lifecycle/status.js.map +1 -0
  74. package/dist/lifecycle/stop.d.ts +2 -0
  75. package/dist/lifecycle/stop.d.ts.map +1 -0
  76. package/dist/lifecycle/stop.js +11 -0
  77. package/dist/lifecycle/stop.js.map +1 -0
  78. package/dist/logger.d.ts +3 -0
  79. package/dist/logger.d.ts.map +1 -0
  80. package/dist/logger.js +8 -0
  81. package/dist/logger.js.map +1 -0
  82. package/dist/security/verifyGitLabWebhook.d.ts +5 -0
  83. package/dist/security/verifyGitLabWebhook.d.ts.map +1 -0
  84. package/dist/security/verifyGitLabWebhook.js +15 -0
  85. package/dist/security/verifyGitLabWebhook.js.map +1 -0
  86. package/dist/shutdown.d.ts +5 -0
  87. package/dist/shutdown.d.ts.map +1 -0
  88. package/dist/shutdown.js +16 -0
  89. package/dist/shutdown.js.map +1 -0
  90. package/package.json +47 -0
  91. package/src/bootstrap.ts +32 -0
  92. package/src/http/health.ts +32 -0
  93. package/src/http/jobs.ts +108 -0
  94. package/src/http/webhooks/github.ts +106 -0
  95. package/src/http/webhooks/gitlab.ts +91 -0
  96. package/src/idempotency/deliveryRegistry.ts +31 -0
  97. package/src/index.ts +75 -0
  98. package/src/jobs/index/runIndexJob.ts +29 -0
  99. package/src/jobs/index/types.ts +6 -0
  100. package/src/jobs/review/runReviewJob.ts +126 -0
  101. package/src/jobs/review/types.ts +5 -0
  102. package/src/jobs/runJob.ts +47 -0
  103. package/src/jobs/store.ts +70 -0
  104. package/src/jobs/types.ts +19 -0
  105. package/src/lifecycle/index.ts +4 -0
  106. package/src/lifecycle/start.ts +27 -0
  107. package/src/lifecycle/state.ts +14 -0
  108. package/src/lifecycle/status.ts +14 -0
  109. package/src/lifecycle/stop.ts +13 -0
  110. package/src/logger.ts +8 -0
  111. package/src/shutdown.ts +19 -0
  112. package/tsconfig.json +36 -0
  113. package/tsconfig.tsbuildinfo +1 -0
@@ -0,0 +1,5 @@
1
+ import type { ResolvedConfig, CredentialContext } from "@prsense/config";
2
+ import type { Logger } from "@prsense/logging";
3
+ import type { IndexJobInput } from "./types.js";
4
+ export declare function runIndexJob(input: IndexJobInput, config: ResolvedConfig, credentials: CredentialContext, logger: Logger): Promise<import("@prsense/workflows").IndexWorkflowResult>;
5
+ //# sourceMappingURL=runIndexJob.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runIndexJob.d.ts","sourceRoot":"","sources":["../../../src/jobs/index/runIndexJob.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACzE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhD,wBAAsB,WAAW,CAC/B,KAAK,EAAE,aAAa,EACpB,MAAM,EAAE,cAAc,EACtB,WAAW,EAAE,iBAAiB,EAC9B,MAAM,EAAE,MAAM,6DAkBf"}
@@ -0,0 +1,20 @@
1
+ import { runIndexWorkflow } from "@prsense/workflows";
2
+ import { createEventBus, PRSENSE_VERSION } from "@prsense/core";
3
+ export async function runIndexJob(input, config, credentials, logger) {
4
+ const eventBus = createEventBus((event) => {
5
+ logger.info("domain.event", {
6
+ event: event.event,
7
+ fields: event.fields,
8
+ });
9
+ });
10
+ return runIndexWorkflow({
11
+ config,
12
+ credentials,
13
+ target: input.target,
14
+ ...(input.force !== undefined ? { force: input.force } : {}),
15
+ ...(input.dryRun !== undefined ? { dryRun: input.dryRun } : {}),
16
+ eventBus,
17
+ version: PRSENSE_VERSION,
18
+ });
19
+ }
20
+ //# sourceMappingURL=runIndexJob.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runIndexJob.js","sourceRoot":"","sources":["../../../src/jobs/index/runIndexJob.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAKhE,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,KAAoB,EACpB,MAAsB,EACtB,WAA8B,EAC9B,MAAc;IAEd,MAAM,QAAQ,GAAG,cAAc,CAAC,CAAC,KAAK,EAAE,EAAE;QACxC,MAAM,CAAC,IAAI,CAAC,cAAc,EAAE;YAC1B,KAAK,EAAE,KAAK,CAAC,KAAK;YAClB,MAAM,EAAE,KAAK,CAAC,MAAM;SACrB,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,OAAO,gBAAgB,CAAC;QACtB,MAAM;QACN,WAAW;QACX,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,GAAG,CAAC,KAAK,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC5D,GAAG,CAAC,KAAK,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC/D,QAAQ;QACR,OAAO,EAAE,eAAe;KACzB,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,6 @@
1
+ export type IndexJobInput = {
2
+ target: string;
3
+ force?: boolean;
4
+ dryRun?: boolean;
5
+ };
6
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/jobs/index/types.ts"],"names":[],"mappings":"AACA,MAAM,MAAM,aAAa,GAAG;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/jobs/index/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,5 @@
1
+ import type { ResolvedConfig, CredentialContext } from "@prsense/config";
2
+ import type { Logger } from "@prsense/logging";
3
+ import type { ReviewJobInput } from "./types.js";
4
+ export declare function runReviewJob(input: ReviewJobInput, config: ResolvedConfig, credentials: CredentialContext, logger: Logger): Promise<import("@prsense/workflows").ReviewWorkflowResult>;
5
+ //# sourceMappingURL=runReviewJob.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runReviewJob.d.ts","sourceRoot":"","sources":["../../../src/jobs/review/runReviewJob.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACzE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAGjD,wBAAsB,YAAY,CAChC,KAAK,EAAE,cAAc,EACrB,MAAM,EAAE,cAAc,EACtB,WAAW,EAAE,iBAAiB,EAC9B,MAAM,EAAE,MAAM,8DA4Gf"}
@@ -0,0 +1,87 @@
1
+ // apps/daemon/src/jobs/review/runReviewJob.ts
2
+ import { runReviewWorkflow } from "@prsense/workflows";
3
+ import { createEventBus } from "@prsense/core";
4
+ import { LocalGitDiffProvider, GitHubPrDiffProvider, GitLabMrDiffProvider, } from "@prsense/context";
5
+ import { createReporter } from "@prsense/reporters";
6
+ export async function runReviewJob(input, config, credentials, logger) {
7
+ const eventBus = createEventBus((event) => {
8
+ logger.info("domain.event", {
9
+ event: event.event,
10
+ fields: event.fields,
11
+ });
12
+ });
13
+ let diffProvider;
14
+ // -------------------------------------------------
15
+ // Determine Provider
16
+ // -------------------------------------------------
17
+ const githubMatch = input.target.match(/github\.com\/([^\/]+)\/([^\/]+)\/pull\/(\d+)/);
18
+ if (githubMatch) {
19
+ const owner = githubMatch[1];
20
+ const repo = githubMatch[2];
21
+ const pr = githubMatch[3];
22
+ if (!owner || !repo || !pr) {
23
+ throw new Error("Invalid GitHub PR URL");
24
+ }
25
+ diffProvider = new GitHubPrDiffProvider(owner, repo.replace(".git", ""), pr);
26
+ }
27
+ else {
28
+ const gitlabMatch = input.target.match(/gitlab\.com\/([^\/]+)\/([^\/]+)\/-\/merge_requests\/(\d+)/);
29
+ if (gitlabMatch) {
30
+ const group = gitlabMatch[1];
31
+ const project = gitlabMatch[2];
32
+ const mr = gitlabMatch[3];
33
+ if (!group || !project || !mr) {
34
+ throw new Error("Invalid GitLab MR URL");
35
+ }
36
+ diffProvider = new GitLabMrDiffProvider(group, project.replace(".git", ""), mr);
37
+ }
38
+ else {
39
+ // Fallback: local repository
40
+ diffProvider = new LocalGitDiffProvider(input.target, input.baseBranch);
41
+ }
42
+ }
43
+ // -------------------------------------------------
44
+ // Execute Review Workflow
45
+ // -------------------------------------------------
46
+ const result = await runReviewWorkflow({
47
+ config,
48
+ credentials,
49
+ diffProvider,
50
+ eventBus,
51
+ });
52
+ // -------------------------------------------------
53
+ // Delivery (Daemon Mode Only)
54
+ // -------------------------------------------------
55
+ if (result.outcome === "success" &&
56
+ config.mode === "daemon" &&
57
+ "delivery" in config &&
58
+ result.payload.signals.length > 0) {
59
+ const platform = config.delivery.platform;
60
+ const reporter = createReporter(platform, credentials);
61
+ if (!reporter) {
62
+ logger.warn("delivery.reporter_not_available", {
63
+ provider: platform,
64
+ });
65
+ }
66
+ else {
67
+ try {
68
+ await reporter.deliver(result.payload.signals, {
69
+ targetUrl: input.target,
70
+ repositoryProvider: platform,
71
+ });
72
+ logger.info("delivery.completed", {
73
+ provider: platform,
74
+ signalCount: result.payload.signals.length,
75
+ });
76
+ }
77
+ catch (err) {
78
+ logger.error("delivery.failed", {
79
+ provider: platform,
80
+ error: err instanceof Error ? err.message : String(err),
81
+ });
82
+ }
83
+ }
84
+ }
85
+ return result;
86
+ }
87
+ //# sourceMappingURL=runReviewJob.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runReviewJob.js","sourceRoot":"","sources":["../../../src/jobs/review/runReviewJob.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ export type ReviewJobInput = {
2
+ target: string;
3
+ baseBranch?: string;
4
+ };
5
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/jobs/review/types.ts"],"names":[],"mappings":"AACA,MAAM,MAAM,cAAc,GAAG;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/jobs/review/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,4 @@
1
+ import type { JobStore } from "./store.js";
2
+ import type { Logger } from "@prsense/logging";
3
+ export declare function runJob<TResult>(store: JobStore, logger: Logger, jobId: string, fn: () => Promise<TResult>): Promise<unknown>;
4
+ //# sourceMappingURL=runJob.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runJob.d.ts","sourceRoot":"","sources":["../../src/jobs/runJob.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAE/C,wBAAsB,MAAM,CAAC,OAAO,EAClC,KAAK,EAAE,QAAQ,EACf,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,EACb,EAAE,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,oBAuC3B"}
@@ -0,0 +1,34 @@
1
+ export async function runJob(store, logger, jobId, fn) {
2
+ const promise = (async () => {
3
+ logger.info("job.execution.started", { jobId });
4
+ store.update(jobId, {
5
+ state: "running",
6
+ startedAt: Date.now(),
7
+ });
8
+ try {
9
+ const result = await fn();
10
+ store.update(jobId, {
11
+ state: "completed",
12
+ result,
13
+ finishedAt: Date.now(),
14
+ });
15
+ logger.info("job.execution.completed", { jobId });
16
+ return result;
17
+ }
18
+ catch (err) {
19
+ const message = err instanceof Error ? err.message : "Unknown error";
20
+ store.update(jobId, {
21
+ state: "failed",
22
+ error: message,
23
+ finishedAt: Date.now(),
24
+ });
25
+ logger.error("job.execution.failed", {
26
+ jobId,
27
+ error: message,
28
+ });
29
+ throw err;
30
+ }
31
+ })();
32
+ return store.track(jobId, promise);
33
+ }
34
+ //# sourceMappingURL=runJob.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runJob.js","sourceRoot":"","sources":["../../src/jobs/runJob.ts"],"names":[],"mappings":"AAGA,MAAM,CAAC,KAAK,UAAU,MAAM,CAC1B,KAAe,EACf,MAAc,EACd,KAAa,EACb,EAA0B;IAE1B,MAAM,OAAO,GAAG,CAAC,KAAK,IAAI,EAAE;QAC1B,MAAM,CAAC,IAAI,CAAC,uBAAuB,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;QAChD,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE;YAClB,KAAK,EAAE,SAAS;YAChB,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;SACtB,CAAC,CAAC;QAEH,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,EAAE,EAAE,CAAC;YAE1B,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE;gBAClB,KAAK,EAAE,WAAW;gBAClB,MAAM;gBACN,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE;aACvB,CAAC,CAAC;YAEH,MAAM,CAAC,IAAI,CAAC,yBAAyB,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;YAClD,OAAO,MAAM,CAAC;QAChB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC;YAErE,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE;gBAClB,KAAK,EAAE,QAAQ;gBACf,KAAK,EAAE,OAAO;gBACd,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE;aACvB,CAAC,CAAC;YAEH,MAAM,CAAC,KAAK,CAAC,sBAAsB,EAAE;gBACnC,KAAK;gBACL,KAAK,EAAE,OAAO;aACf,CAAC,CAAC;YAEH,MAAM,GAAG,CAAC;QACZ,CAAC;IACH,CAAC,CAAC,EAAE,CAAC;IAEL,OAAO,KAAK,CAAC,KAAK,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;AACrC,CAAC"}
@@ -0,0 +1,12 @@
1
+ import type { Job } from "./types.js";
2
+ import type { Logger } from "@prsense/logging";
3
+ export declare function createJobStore(logger: Logger): {
4
+ get(id: string): Job | undefined;
5
+ list(): Job[];
6
+ create(job: Job): void;
7
+ update(id: string, patch: Partial<Job>): void;
8
+ track(jobId: string, promise: Promise<unknown>): Promise<unknown>;
9
+ drain(): Promise<void>;
10
+ };
11
+ export type JobStore = ReturnType<typeof createJobStore>;
12
+ //# sourceMappingURL=store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/jobs/store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAE/C,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM;YAKjC,MAAM;;gBAQF,GAAG;eASJ,MAAM,SAAS,OAAO,CAAC,GAAG,CAAC;iBA6BnB,MAAM,WAAW,OAAO,CAAC,OAAO,CAAC;;EAavD;AAED,MAAM,MAAM,QAAQ,GAAG,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC"}
@@ -0,0 +1,56 @@
1
+ export function createJobStore(logger) {
2
+ const jobs = new Map();
3
+ const inFlight = new Set();
4
+ return {
5
+ get(id) {
6
+ return jobs.get(id);
7
+ },
8
+ list() {
9
+ return Array.from(jobs.values());
10
+ },
11
+ create(job) {
12
+ jobs.set(job.id, job);
13
+ logger.info("job.queued", {
14
+ jobId: job.id,
15
+ type: job.type,
16
+ });
17
+ },
18
+ update(id, patch) {
19
+ const job = jobs.get(id);
20
+ if (!job)
21
+ return;
22
+ const updated = { ...job, ...patch };
23
+ jobs.set(id, updated);
24
+ if (patch.state === "running") {
25
+ logger.info("job.started", { jobId: id });
26
+ }
27
+ if (patch.state === "completed") {
28
+ logger.info("job.completed", {
29
+ jobId: id,
30
+ duration: updated.finishedAt && updated.startedAt
31
+ ? updated.finishedAt - updated.startedAt
32
+ : undefined,
33
+ });
34
+ }
35
+ if (patch.state === "failed") {
36
+ logger.error("job.failed", {
37
+ jobId: id,
38
+ error: patch.error,
39
+ });
40
+ }
41
+ },
42
+ async track(jobId, promise) {
43
+ inFlight.add(promise);
44
+ try {
45
+ return await promise;
46
+ }
47
+ finally {
48
+ inFlight.delete(promise);
49
+ }
50
+ },
51
+ async drain() {
52
+ await Promise.allSettled(Array.from(inFlight));
53
+ },
54
+ };
55
+ }
56
+ //# sourceMappingURL=store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/jobs/store.ts"],"names":[],"mappings":"AAGA,MAAM,UAAU,cAAc,CAAC,MAAc;IAC3C,MAAM,IAAI,GAAG,IAAI,GAAG,EAAe,CAAC;IACpC,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAoB,CAAC;IAE7C,OAAO;QACL,GAAG,CAAC,EAAU;YACZ,OAAO,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACtB,CAAC;QAED,IAAI;YACF,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;QACnC,CAAC;QAED,MAAM,CAAC,GAAQ;YACb,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;YAEtB,MAAM,CAAC,IAAI,CAAC,YAAY,EAAE;gBACxB,KAAK,EAAE,GAAG,CAAC,EAAE;gBACb,IAAI,EAAE,GAAG,CAAC,IAAI;aACf,CAAC,CAAC;QACL,CAAC;QAED,MAAM,CAAC,EAAU,EAAE,KAAmB;YACpC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YACzB,IAAI,CAAC,GAAG;gBAAE,OAAO;YAEjB,MAAM,OAAO,GAAG,EAAE,GAAG,GAAG,EAAE,GAAG,KAAK,EAAE,CAAC;YACrC,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;YAEtB,IAAI,KAAK,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;gBAC9B,MAAM,CAAC,IAAI,CAAC,aAAa,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,CAAC;YAC5C,CAAC;YAED,IAAI,KAAK,CAAC,KAAK,KAAK,WAAW,EAAE,CAAC;gBAChC,MAAM,CAAC,IAAI,CAAC,eAAe,EAAE;oBAC3B,KAAK,EAAE,EAAE;oBACT,QAAQ,EACN,OAAO,CAAC,UAAU,IAAI,OAAO,CAAC,SAAS;wBACrC,CAAC,CAAC,OAAO,CAAC,UAAU,GAAG,OAAO,CAAC,SAAS;wBACxC,CAAC,CAAC,SAAS;iBAChB,CAAC,CAAC;YACL,CAAC;YAED,IAAI,KAAK,CAAC,KAAK,KAAK,QAAQ,EAAE,CAAC;gBAC7B,MAAM,CAAC,KAAK,CAAC,YAAY,EAAE;oBACzB,KAAK,EAAE,EAAE;oBACT,KAAK,EAAE,KAAK,CAAC,KAAK;iBACnB,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAED,KAAK,CAAC,KAAK,CAAC,KAAa,EAAE,OAAyB;YAClD,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YACtB,IAAI,CAAC;gBACH,OAAO,MAAM,OAAO,CAAC;YACvB,CAAC;oBAAS,CAAC;gBACT,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;YAC3B,CAAC;QACH,CAAC;QAED,KAAK,CAAC,KAAK;YACT,MAAM,OAAO,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;QACjD,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,14 @@
1
+ export type JobState = "queued" | "running" | "completed" | "failed";
2
+ export type JobType = "review" | "index" | "doctor";
3
+ export type Job<TInput = unknown, TResult = unknown> = {
4
+ id: string;
5
+ type: JobType;
6
+ state: JobState;
7
+ input: TInput;
8
+ result?: TResult;
9
+ error?: string;
10
+ createdAt: number;
11
+ startedAt?: number;
12
+ finishedAt?: number;
13
+ };
14
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/jobs/types.ts"],"names":[],"mappings":"AACA,MAAM,MAAM,QAAQ,GAAG,QAAQ,GAAG,SAAS,GAAG,WAAW,GAAG,QAAQ,CAAC;AAErE,MAAM,MAAM,OAAO,GAAG,QAAQ,GAAG,OAAO,GAAG,QAAQ,CAAC;AAEpD,MAAM,MAAM,GAAG,CAAC,MAAM,GAAG,OAAO,EAAE,OAAO,GAAG,OAAO,IAAI;IACrD,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,OAAO,CAAC;IAEd,KAAK,EAAE,QAAQ,CAAC;IAEhB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/jobs/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,5 @@
1
+ export * from "./start.js";
2
+ export * from "./stop.js";
3
+ export * from "./status.js";
4
+ export * from "./state.js";
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/lifecycle/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,WAAW,CAAC;AAC1B,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC"}
@@ -0,0 +1,5 @@
1
+ export * from "./start.js";
2
+ export * from "./stop.js";
3
+ export * from "./status.js";
4
+ export * from "./state.js";
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/lifecycle/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,WAAW,CAAC;AAC1B,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC"}
@@ -0,0 +1,4 @@
1
+ export declare function startDaemon({ foreground }: {
2
+ foreground: boolean;
3
+ }): Promise<void>;
4
+ //# sourceMappingURL=start.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"start.d.ts","sourceRoot":"","sources":["../../src/lifecycle/start.ts"],"names":[],"mappings":"AAKA,wBAAsB,WAAW,CAAC,EAAE,UAAU,EAAE,EAAE;IAAE,UAAU,EAAE,OAAO,CAAA;CAAE,iBAqBxE"}
@@ -0,0 +1,24 @@
1
+ // apps/daemon/src/lifecycle/start.ts
2
+ import fs from "node:fs/promises";
3
+ import { spawn } from "node:child_process";
4
+ import { getDaemonStateDir, getPidFile } from "./state.js";
5
+ export async function startDaemon({ foreground }) {
6
+ await fs.mkdir(getDaemonStateDir(), { recursive: true });
7
+ let child;
8
+ try {
9
+ child = spawn("prsense-daemon", [], {
10
+ detached: !foreground,
11
+ stdio: foreground ? "inherit" : "ignore",
12
+ });
13
+ }
14
+ catch (err) {
15
+ console.error("prsense-daemon not found. Is @prsense/daemon installed and linked?");
16
+ process.exit(1);
17
+ }
18
+ if (!foreground) {
19
+ child.unref();
20
+ await fs.writeFile(getPidFile(), String(child.pid));
21
+ console.log("PRSense daemon started");
22
+ }
23
+ }
24
+ //# sourceMappingURL=start.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"start.js","sourceRoot":"","sources":["../../src/lifecycle/start.ts"],"names":[],"mappings":"AAAA,qCAAqC;AACrC,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EAAE,iBAAiB,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE3D,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,EAAE,UAAU,EAA2B;IACvE,MAAM,EAAE,CAAC,KAAK,CAAC,iBAAiB,EAAE,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAEzD,IAAI,KAAK,CAAC;IACV,IAAI,CAAC;QACH,KAAK,GAAG,KAAK,CAAC,gBAAgB,EAAE,EAAE,EAAE;YAClC,QAAQ,EAAE,CAAC,UAAU;YACrB,KAAK,EAAE,UAAU,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ;SACzC,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CACX,oEAAoE,CACrE,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,KAAK,CAAC,KAAK,EAAE,CAAC;QACd,MAAM,EAAE,CAAC,SAAS,CAAC,UAAU,EAAE,EAAE,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;QACpD,OAAO,CAAC,GAAG,CAAC,wBAAwB,CAAC,CAAC;IACxC,CAAC;AACH,CAAC"}
@@ -0,0 +1,3 @@
1
+ export declare function getDaemonStateDir(): string;
2
+ export declare function getPidFile(): string;
3
+ //# sourceMappingURL=state.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../../src/lifecycle/state.ts"],"names":[],"mappings":"AAIA,wBAAgB,iBAAiB,WAKhC;AAED,wBAAgB,UAAU,WAEzB"}
@@ -0,0 +1,11 @@
1
+ //apps/daemon/src/lifecycle/state.ts
2
+ import path from "node:path";
3
+ import os from "node:os";
4
+ export function getDaemonStateDir() {
5
+ const base = process.env.XDG_STATE_HOME ?? path.join(os.homedir(), ".local", "state");
6
+ return path.join(base, "prsense", "daemon");
7
+ }
8
+ export function getPidFile() {
9
+ return path.join(getDaemonStateDir(), "daemon.pid");
10
+ }
11
+ //# sourceMappingURL=state.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state.js","sourceRoot":"","sources":["../../src/lifecycle/state.ts"],"names":[],"mappings":"AAAA,oCAAoC;AACpC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,MAAM,SAAS,CAAC;AAEzB,MAAM,UAAU,iBAAiB;IAC/B,MAAM,IAAI,GACR,OAAO,CAAC,GAAG,CAAC,cAAc,IAAI,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;IAE3E,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC;AAC9C,CAAC;AAED,MAAM,UAAU,UAAU;IACxB,OAAO,IAAI,CAAC,IAAI,CAAC,iBAAiB,EAAE,EAAE,YAAY,CAAC,CAAC;AACtD,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function daemonStatus(): Promise<void>;
2
+ //# sourceMappingURL=status.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../src/lifecycle/status.ts"],"names":[],"mappings":"AAKA,wBAAsB,YAAY,kBAQjC"}
@@ -0,0 +1,15 @@
1
+ //apps/daemon/src/lifecycle/status.ts
2
+ import fs from "node:fs/promises";
3
+ import process from "node:process";
4
+ import { getPidFile } from "./state.js";
5
+ export async function daemonStatus() {
6
+ try {
7
+ const pid = Number(await fs.readFile(getPidFile(), "utf8"));
8
+ process.kill(pid, 0);
9
+ console.log(`PRsense daemon is running (PID ${pid})`);
10
+ }
11
+ catch {
12
+ console.log("PRsense daemon is not running");
13
+ }
14
+ }
15
+ //# sourceMappingURL=status.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.js","sourceRoot":"","sources":["../../src/lifecycle/status.ts"],"names":[],"mappings":"AAAA,qCAAqC;AACrC,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,OAAO,MAAM,cAAc,CAAC;AACnC,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAExC,MAAM,CAAC,KAAK,UAAU,YAAY;IAChC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,UAAU,EAAE,EAAE,MAAM,CAAC,CAAC,CAAC;QAC5D,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;QACrB,OAAO,CAAC,GAAG,CAAC,kCAAkC,GAAG,GAAG,CAAC,CAAC;IACxD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,CAAC,GAAG,CAAC,+BAA+B,CAAC,CAAC;IAC/C,CAAC;AACH,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function stopDaemon(): Promise<void>;
2
+ //# sourceMappingURL=stop.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stop.d.ts","sourceRoot":"","sources":["../../src/lifecycle/stop.ts"],"names":[],"mappings":"AAKA,wBAAsB,UAAU,kBAO/B"}
@@ -0,0 +1,11 @@
1
+ //apps/daemon/src/lifecycle/stop.ts
2
+ import fs from "node:fs/promises";
3
+ import process from "node:process";
4
+ import { getPidFile } from "./state.js";
5
+ export async function stopDaemon() {
6
+ const pid = Number(await fs.readFile(getPidFile(), "utf8"));
7
+ process.kill(pid, "SIGTERM");
8
+ await fs.unlink(getPidFile());
9
+ console.log("PRsense daemon stopped");
10
+ }
11
+ //# sourceMappingURL=stop.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stop.js","sourceRoot":"","sources":["../../src/lifecycle/stop.ts"],"names":[],"mappings":"AAAA,mCAAmC;AACnC,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,OAAO,MAAM,cAAc,CAAC;AACnC,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAExC,MAAM,CAAC,KAAK,UAAU,UAAU;IAC9B,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,UAAU,EAAE,EAAE,MAAM,CAAC,CAAC,CAAC;IAE5D,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;IAE7B,MAAM,EAAE,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC,CAAC;IAC9B,OAAO,CAAC,GAAG,CAAC,wBAAwB,CAAC,CAAC;AACxC,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { type Logger } from "@prsense/logging";
2
+ export declare function createDaemonLogger(): Logger;
3
+ //# sourceMappingURL=logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoB,KAAK,MAAM,EAAiB,MAAM,kBAAkB,CAAC;AAEhF,wBAAgB,kBAAkB,IAAI,MAAM,CAK3C"}
package/dist/logger.js ADDED
@@ -0,0 +1,8 @@
1
+ import { createPinoLogger } from "@prsense/logging";
2
+ export function createDaemonLogger() {
3
+ return createPinoLogger({
4
+ level: (process.env.PRSENSE_LOG_LEVEL ?? "warn"),
5
+ pretty: false,
6
+ });
7
+ }
8
+ //# sourceMappingURL=logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAA8B,MAAM,kBAAkB,CAAC;AAEhF,MAAM,UAAU,kBAAkB;IAChC,OAAO,gBAAgB,CAAC;QACtB,KAAK,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,iBAAiB,IAAI,MAAM,CAAa;QAC5D,MAAM,EAAE,KAAK;KACd,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,5 @@
1
+ export declare function verifyGitLabWebhook(params: {
2
+ receivedToken: string | undefined;
3
+ expectedToken: string | undefined;
4
+ }): boolean;
5
+ //# sourceMappingURL=verifyGitLabWebhook.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verifyGitLabWebhook.d.ts","sourceRoot":"","sources":["../../src/security/verifyGitLabWebhook.ts"],"names":[],"mappings":"AAEA,wBAAgB,mBAAmB,CAAC,MAAM,EAAE;IAC1C,aAAa,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,aAAa,EAAE,MAAM,GAAG,SAAS,CAAC;CACnC,GAAG,OAAO,CAgBV"}
@@ -0,0 +1,15 @@
1
+ import { timingSafeEqual } from "crypto";
2
+ export function verifyGitLabWebhook(params) {
3
+ const { receivedToken, expectedToken } = params;
4
+ if (!receivedToken || !expectedToken) {
5
+ return false;
6
+ }
7
+ // constant-time comparison to avoid timing attacks
8
+ const a = Buffer.from(receivedToken);
9
+ const b = Buffer.from(expectedToken);
10
+ if (a.length !== b.length) {
11
+ return false;
12
+ }
13
+ return timingSafeEqual(a, b);
14
+ }
15
+ //# sourceMappingURL=verifyGitLabWebhook.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verifyGitLabWebhook.js","sourceRoot":"","sources":["../../src/security/verifyGitLabWebhook.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,QAAQ,CAAC;AAEzC,MAAM,UAAU,mBAAmB,CAAC,MAGnC;IACC,MAAM,EAAE,aAAa,EAAE,aAAa,EAAE,GAAG,MAAM,CAAC;IAEhD,IAAI,CAAC,aAAa,IAAI,CAAC,aAAa,EAAE,CAAC;QACrC,OAAO,KAAK,CAAC;IACf,CAAC;IAED,mDAAmD;IACnD,MAAM,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IACrC,MAAM,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IAErC,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,MAAM,EAAE,CAAC;QAC1B,OAAO,KAAK,CAAC;IACf,CAAC;IAED,OAAO,eAAe,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AAC/B,CAAC"}
@@ -0,0 +1,5 @@
1
+ export declare function setupGracefulShutdown(opts: {
2
+ closeHttp: () => Promise<void>;
3
+ onShutdown?: () => Promise<void>;
4
+ }): void;
5
+ //# sourceMappingURL=shutdown.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shutdown.d.ts","sourceRoot":"","sources":["../src/shutdown.ts"],"names":[],"mappings":"AACA,wBAAgB,qBAAqB,CAAC,IAAI,EAAE;IAC1C,SAAS,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/B,UAAU,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAClC,QAcA"}
@@ -0,0 +1,16 @@
1
+ // apps/daemon/src/shutdown.ts
2
+ export function setupGracefulShutdown(opts) {
3
+ async function shutdown(signal) {
4
+ console.log(`Received ${signal}, shutting down...`);
5
+ try {
6
+ await opts.onShutdown?.();
7
+ await opts.closeHttp();
8
+ }
9
+ finally {
10
+ process.exit(0);
11
+ }
12
+ }
13
+ process.on("SIGTERM", shutdown);
14
+ process.on("SIGINT", shutdown);
15
+ }
16
+ //# sourceMappingURL=shutdown.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shutdown.js","sourceRoot":"","sources":["../src/shutdown.ts"],"names":[],"mappings":"AAAA,8BAA8B;AAC9B,MAAM,UAAU,qBAAqB,CAAC,IAGrC;IACC,KAAK,UAAU,QAAQ,CAAC,MAAc;QACpC,OAAO,CAAC,GAAG,CAAC,YAAY,MAAM,oBAAoB,CAAC,CAAC;QAEpD,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,UAAU,EAAE,EAAE,CAAC;YAC1B,MAAM,IAAI,CAAC,SAAS,EAAE,CAAC;QACzB,CAAC;gBAAS,CAAC;YACT,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC;IAED,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;IAChC,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;AACjC,CAAC"}
package/package.json ADDED
@@ -0,0 +1,47 @@
1
+ {
2
+ "name": "@prsense/daemon",
3
+ "private": false,
4
+ "version": "0.1.0",
5
+ "type": "module",
6
+ "description": "PRsense long-lived daemon (HTTP API + job scheduler)",
7
+ "license": "Apache-2.0",
8
+ "bin": {
9
+ "prsense-daemon": "dist/index.js"
10
+ },
11
+ "dependencies": {
12
+ "fastify": "^5.0.0",
13
+ "fastify-raw-body": "^5.0.0",
14
+ "pg": "^8.17.1",
15
+ "@prsense/config": "0.1.0",
16
+ "@prsense/context": "0.1.0",
17
+ "@prsense/workflows": "0.1.0",
18
+ "@prsense/logging": "0.1.0",
19
+ "@prsense/core": "0.1.0",
20
+ "@prsense/reporters": "0.1.0"
21
+ },
22
+ "devDependencies": {
23
+ "@types/node": "^25.0.3",
24
+ "@types/pg": "^8.16.0",
25
+ "tsx": "^4.21.0",
26
+ "typescript": "^5.9.3"
27
+ },
28
+ "keywords": [
29
+ "cli",
30
+ "pull-request",
31
+ "code-review",
32
+ "automation",
33
+ "ai",
34
+ "developer-tools",
35
+ "llm"
36
+ ],
37
+ "engines": {
38
+ "node": ">=22"
39
+ },
40
+ "scripts": {
41
+ "dev": "tsx watch src/index.ts",
42
+ "build": "tsc -b",
43
+ "start": "node dist/index.js",
44
+ "lint": "eslint .",
45
+ "clean": "rm -rf dist/ *.tsbuildinfo"
46
+ }
47
+ }