@knpkv/codecommit-core 0.5.0 → 0.5.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 (138) hide show
  1. package/dist/AwsClient/getDifferences.d.ts +16 -0
  2. package/dist/AwsClient/getDifferences.d.ts.map +1 -0
  3. package/dist/AwsClient/getDifferences.js +22 -0
  4. package/dist/AwsClient/getDifferences.js.map +1 -0
  5. package/dist/AwsClient/getPullRequest.d.ts.map +1 -1
  6. package/dist/AwsClient/getPullRequest.js +26 -5
  7. package/dist/AwsClient/getPullRequest.js.map +1 -1
  8. package/dist/AwsClient/getPullRequests.d.ts.map +1 -1
  9. package/dist/AwsClient/getPullRequests.js +29 -11
  10. package/dist/AwsClient/getPullRequests.js.map +1 -1
  11. package/dist/AwsClient/index.d.ts +21 -13
  12. package/dist/AwsClient/index.d.ts.map +1 -1
  13. package/dist/AwsClient/index.js +3 -1
  14. package/dist/AwsClient/index.js.map +1 -1
  15. package/dist/AwsClient/internal.d.ts +23 -0
  16. package/dist/AwsClient/internal.d.ts.map +1 -1
  17. package/dist/AwsClient/internal.js +4 -1
  18. package/dist/AwsClient/internal.js.map +1 -1
  19. package/dist/CacheService/Database.d.ts.map +1 -1
  20. package/dist/CacheService/Database.js +9 -1
  21. package/dist/CacheService/Database.js.map +1 -1
  22. package/dist/CacheService/index.d.ts +3 -2
  23. package/dist/CacheService/index.d.ts.map +1 -1
  24. package/dist/CacheService/index.js +2 -1
  25. package/dist/CacheService/index.js.map +1 -1
  26. package/dist/CacheService/migrations/0007_stats_columns.d.ts +5 -0
  27. package/dist/CacheService/migrations/0007_stats_columns.d.ts.map +1 -0
  28. package/dist/CacheService/migrations/0007_stats_columns.js +13 -0
  29. package/dist/CacheService/migrations/0007_stats_columns.js.map +1 -0
  30. package/dist/CacheService/migrations/0008_merged_by.d.ts +5 -0
  31. package/dist/CacheService/migrations/0008_merged_by.d.ts.map +1 -0
  32. package/dist/CacheService/migrations/0008_merged_by.js +4 -0
  33. package/dist/CacheService/migrations/0008_merged_by.js.map +1 -0
  34. package/dist/CacheService/migrations/0009_approved_by.d.ts +5 -0
  35. package/dist/CacheService/migrations/0009_approved_by.d.ts.map +1 -0
  36. package/dist/CacheService/migrations/0009_approved_by.js +4 -0
  37. package/dist/CacheService/migrations/0009_approved_by.js.map +1 -0
  38. package/dist/CacheService/migrations/0010_commented_by.d.ts +5 -0
  39. package/dist/CacheService/migrations/0010_commented_by.d.ts.map +1 -0
  40. package/dist/CacheService/migrations/0010_commented_by.js +4 -0
  41. package/dist/CacheService/migrations/0010_commented_by.js.map +1 -0
  42. package/dist/CacheService/repos/PullRequestRepo/index.d.ts +132 -0
  43. package/dist/CacheService/repos/PullRequestRepo/index.d.ts.map +1 -0
  44. package/dist/CacheService/repos/PullRequestRepo/index.js +35 -0
  45. package/dist/CacheService/repos/PullRequestRepo/index.js.map +1 -0
  46. package/dist/CacheService/repos/PullRequestRepo/internal.d.ts +72 -0
  47. package/dist/CacheService/repos/PullRequestRepo/internal.d.ts.map +1 -0
  48. package/dist/CacheService/repos/PullRequestRepo/internal.js +69 -0
  49. package/dist/CacheService/repos/PullRequestRepo/internal.js.map +1 -0
  50. package/dist/CacheService/repos/PullRequestRepo/mutations.d.ts +24 -0
  51. package/dist/CacheService/repos/PullRequestRepo/mutations.d.ts.map +1 -0
  52. package/dist/CacheService/repos/PullRequestRepo/mutations.js +94 -0
  53. package/dist/CacheService/repos/PullRequestRepo/mutations.js.map +1 -0
  54. package/dist/CacheService/repos/PullRequestRepo/queries.d.ts +113 -0
  55. package/dist/CacheService/repos/PullRequestRepo/queries.d.ts.map +1 -0
  56. package/dist/CacheService/repos/PullRequestRepo/queries.js +89 -0
  57. package/dist/CacheService/repos/PullRequestRepo/queries.js.map +1 -0
  58. package/dist/CacheService/repos/StatsRepo/index.d.ts +93 -0
  59. package/dist/CacheService/repos/StatsRepo/index.d.ts.map +1 -0
  60. package/dist/CacheService/repos/StatsRepo/index.js +41 -0
  61. package/dist/CacheService/repos/StatsRepo/index.js.map +1 -0
  62. package/dist/CacheService/repos/StatsRepo/internal.d.ts +120 -0
  63. package/dist/CacheService/repos/StatsRepo/internal.d.ts.map +1 -0
  64. package/dist/CacheService/repos/StatsRepo/internal.js +34 -0
  65. package/dist/CacheService/repos/StatsRepo/internal.js.map +1 -0
  66. package/dist/CacheService/repos/StatsRepo/queries.d.ts +42 -0
  67. package/dist/CacheService/repos/StatsRepo/queries.d.ts.map +1 -0
  68. package/dist/CacheService/repos/StatsRepo/queries.js +182 -0
  69. package/dist/CacheService/repos/StatsRepo/queries.js.map +1 -0
  70. package/dist/CacheService/repos/StatsRepo/reviewerData.d.ts +47 -0
  71. package/dist/CacheService/repos/StatsRepo/reviewerData.d.ts.map +1 -0
  72. package/dist/CacheService/repos/StatsRepo/reviewerData.js +172 -0
  73. package/dist/CacheService/repos/StatsRepo/reviewerData.js.map +1 -0
  74. package/dist/DateUtils.d.ts +28 -0
  75. package/dist/DateUtils.d.ts.map +1 -1
  76. package/dist/DateUtils.js +69 -1
  77. package/dist/DateUtils.js.map +1 -1
  78. package/dist/Domain.d.ts +13 -3
  79. package/dist/Domain.d.ts.map +1 -1
  80. package/dist/Domain.js +6 -5
  81. package/dist/Domain.js.map +1 -1
  82. package/dist/PRService/index.d.ts +3 -3
  83. package/dist/PRService/index.d.ts.map +1 -1
  84. package/dist/PRService/index.js +1 -1
  85. package/dist/PRService/index.js.map +1 -1
  86. package/dist/PRService/internal.d.ts +24 -2
  87. package/dist/PRService/internal.d.ts.map +1 -1
  88. package/dist/PRService/internal.js +23 -8
  89. package/dist/PRService/internal.js.map +1 -1
  90. package/dist/PRService/refresh.d.ts +1 -1
  91. package/dist/PRService/refresh.d.ts.map +1 -1
  92. package/dist/PRService/refresh.js +2 -0
  93. package/dist/PRService/refresh.js.map +1 -1
  94. package/dist/PRService/refreshDiffs.d.ts +16 -0
  95. package/dist/PRService/refreshDiffs.d.ts.map +1 -0
  96. package/dist/PRService/refreshDiffs.js +54 -0
  97. package/dist/PRService/refreshDiffs.js.map +1 -0
  98. package/dist/PRService/refreshEnrich.d.ts +1 -1
  99. package/dist/PRService/refreshEnrich.d.ts.map +1 -1
  100. package/dist/PRService/refreshEnrich.js +3 -1
  101. package/dist/PRService/refreshEnrich.js.map +1 -1
  102. package/dist/PRService/refreshFetch.d.ts +1 -1
  103. package/dist/PRService/refreshFetch.d.ts.map +1 -1
  104. package/dist/PRService/refreshFetch.js +12 -3
  105. package/dist/PRService/refreshFetch.js.map +1 -1
  106. package/dist/PRService/refreshHistory.d.ts +19 -0
  107. package/dist/PRService/refreshHistory.d.ts.map +1 -0
  108. package/dist/PRService/refreshHistory.js +110 -0
  109. package/dist/PRService/refreshHistory.js.map +1 -0
  110. package/dist/PRService/refreshResolve.d.ts +1 -1
  111. package/dist/PRService/refreshResolve.d.ts.map +1 -1
  112. package/dist/PRService/refreshResolve.js +1 -1
  113. package/dist/PRService/refreshResolve.js.map +1 -1
  114. package/dist/PRService/refreshScore.d.ts +1 -1
  115. package/dist/PRService/refreshScore.d.ts.map +1 -1
  116. package/dist/PRService/refreshScore.js +1 -1
  117. package/dist/PRService/refreshScore.js.map +1 -1
  118. package/dist/PRService/refreshSinglePR.d.ts +1 -1
  119. package/dist/PRService/refreshSinglePR.d.ts.map +1 -1
  120. package/dist/PRService/refreshSinglePR.js +4 -3
  121. package/dist/PRService/refreshSinglePR.js.map +1 -1
  122. package/dist/StatsService/WeeklyStats.d.ts +174 -0
  123. package/dist/StatsService/WeeklyStats.d.ts.map +1 -0
  124. package/dist/StatsService/WeeklyStats.js +110 -0
  125. package/dist/StatsService/WeeklyStats.js.map +1 -0
  126. package/dist/StatsService/index.d.ts +45 -0
  127. package/dist/StatsService/index.d.ts.map +1 -0
  128. package/dist/StatsService/index.js +145 -0
  129. package/dist/StatsService/index.js.map +1 -0
  130. package/dist/index.d.ts +1 -0
  131. package/dist/index.d.ts.map +1 -1
  132. package/dist/index.js +1 -0
  133. package/dist/index.js.map +1 -1
  134. package/package.json +1 -1
  135. package/dist/CacheService/repos/PullRequestRepo.d.ts +0 -112
  136. package/dist/CacheService/repos/PullRequestRepo.d.ts.map +0 -1
  137. package/dist/CacheService/repos/PullRequestRepo.js +0 -146
  138. package/dist/CacheService/repos/PullRequestRepo.js.map +0 -1
@@ -0,0 +1,113 @@
1
+ /**
2
+ * @module PullRequestRepo/queries
3
+ *
4
+ * Read-only SQL queries. Each function takes `sql` (SqlClient) and returns
5
+ * the query implementation for the PullRequestRepo service.
6
+ *
7
+ * @category CacheService
8
+ */
9
+ import type * as SqlClient from "@effect/sql/SqlClient";
10
+ import { Effect, Option } from "effect";
11
+ import type { CacheError } from "../../CacheError.js";
12
+ import { type SearchResult } from "./internal.js";
13
+ export declare const findAll: (sql: SqlClient.SqlClient) => () => Effect.Effect<readonly {
14
+ readonly link: string;
15
+ readonly awsAccountId: string;
16
+ readonly id: string & import("effect/Brand").Brand<"PullRequestId">;
17
+ readonly title: string;
18
+ readonly author: string;
19
+ readonly repositoryName: string & import("effect/Brand").Brand<"RepositoryName">;
20
+ readonly creationDate: Date;
21
+ readonly lastModifiedDate: Date;
22
+ readonly status: "OPEN" | "CLOSED" | "MERGED";
23
+ readonly sourceBranch: string;
24
+ readonly destinationBranch: string;
25
+ readonly isMergeable: boolean;
26
+ readonly isApproved: boolean;
27
+ readonly description: string | null;
28
+ readonly commentCount: number | null;
29
+ readonly healthScore: number | null;
30
+ readonly fetchedAt: string;
31
+ readonly approvedBy: readonly string[];
32
+ readonly commentedBy: readonly string[];
33
+ readonly mergedBy: string | null;
34
+ readonly accountProfile: string & import("effect/Brand").Brand<"AwsProfileName">;
35
+ readonly accountRegion: string & import("effect/Brand").Brand<"AwsRegion">;
36
+ readonly filesAdded: number | null;
37
+ readonly filesModified: number | null;
38
+ readonly filesDeleted: number | null;
39
+ readonly closedAt: string | null;
40
+ }[], CacheError, never>;
41
+ export declare const findMissingDiffStats: (sql: SqlClient.SqlClient) => () => Effect.Effect<readonly {
42
+ readonly link: string;
43
+ readonly awsAccountId: string;
44
+ readonly id: string & import("effect/Brand").Brand<"PullRequestId">;
45
+ readonly title: string;
46
+ readonly author: string;
47
+ readonly repositoryName: string & import("effect/Brand").Brand<"RepositoryName">;
48
+ readonly creationDate: Date;
49
+ readonly lastModifiedDate: Date;
50
+ readonly status: "OPEN" | "CLOSED" | "MERGED";
51
+ readonly sourceBranch: string;
52
+ readonly destinationBranch: string;
53
+ readonly isMergeable: boolean;
54
+ readonly isApproved: boolean;
55
+ readonly description: string | null;
56
+ readonly commentCount: number | null;
57
+ readonly healthScore: number | null;
58
+ readonly fetchedAt: string;
59
+ readonly approvedBy: readonly string[];
60
+ readonly commentedBy: readonly string[];
61
+ readonly mergedBy: string | null;
62
+ readonly accountProfile: string & import("effect/Brand").Brand<"AwsProfileName">;
63
+ readonly accountRegion: string & import("effect/Brand").Brand<"AwsRegion">;
64
+ readonly filesAdded: number | null;
65
+ readonly filesModified: number | null;
66
+ readonly filesDeleted: number | null;
67
+ readonly closedAt: string | null;
68
+ }[], CacheError, never>;
69
+ export declare const findByAccountAndId: (sql: SqlClient.SqlClient) => (awsAccountId: string, id: string) => Effect.Effect<Option.Option<{
70
+ readonly link: string;
71
+ readonly awsAccountId: string;
72
+ readonly id: string & import("effect/Brand").Brand<"PullRequestId">;
73
+ readonly title: string;
74
+ readonly author: string;
75
+ readonly repositoryName: string & import("effect/Brand").Brand<"RepositoryName">;
76
+ readonly creationDate: Date;
77
+ readonly lastModifiedDate: Date;
78
+ readonly status: "OPEN" | "CLOSED" | "MERGED";
79
+ readonly sourceBranch: string;
80
+ readonly destinationBranch: string;
81
+ readonly isMergeable: boolean;
82
+ readonly isApproved: boolean;
83
+ readonly description: string | null;
84
+ readonly commentCount: number | null;
85
+ readonly healthScore: number | null;
86
+ readonly fetchedAt: string;
87
+ readonly approvedBy: readonly string[];
88
+ readonly commentedBy: readonly string[];
89
+ readonly mergedBy: string | null;
90
+ readonly accountProfile: string & import("effect/Brand").Brand<"AwsProfileName">;
91
+ readonly accountRegion: string & import("effect/Brand").Brand<"AwsRegion">;
92
+ readonly filesAdded: number | null;
93
+ readonly filesModified: number | null;
94
+ readonly filesDeleted: number | null;
95
+ readonly closedAt: string | null;
96
+ }>, CacheError, never>;
97
+ export declare const search: (sql: SqlClient.SqlClient) => (query: string, opts?: {
98
+ readonly limit?: number;
99
+ readonly offset?: number;
100
+ }) => Effect.Effect<SearchResult, CacheError>;
101
+ export declare const findStaleOpen: (sql: SqlClient.SqlClient) => (olderThan: string) => Effect.Effect<readonly {
102
+ readonly awsAccountId: string;
103
+ readonly id: string;
104
+ readonly accountProfile: string & import("effect/Brand").Brand<"AwsProfileName">;
105
+ readonly accountRegion: string & import("effect/Brand").Brand<"AwsRegion">;
106
+ }[], CacheError, never>;
107
+ export declare const findOpenInRange: (sql: SqlClient.SqlClient) => (weekStart: string, weekEnd: string) => Effect.Effect<readonly {
108
+ readonly awsAccountId: string;
109
+ readonly id: string;
110
+ readonly accountProfile: string & import("effect/Brand").Brand<"AwsProfileName">;
111
+ readonly accountRegion: string & import("effect/Brand").Brand<"AwsRegion">;
112
+ }[], CacheError, never>;
113
+ //# sourceMappingURL=queries.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queries.d.ts","sourceRoot":"","sources":["../../../../src/CacheService/repos/PullRequestRepo/queries.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,KAAK,SAAS,MAAM,uBAAuB,CAAA;AAEvD,OAAO,EAAE,MAAM,EAAE,MAAM,EAAU,MAAM,QAAQ,CAAA;AAE/C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAA;AACrD,OAAO,EAIL,KAAK,YAAY,EAClB,MAAM,eAAe,CAAA;AAStB,eAAO,MAAM,OAAO,GAAI,KAAK,SAAS,CAAC,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;uBAO/C,CAAA;AAED,eAAO,MAAM,oBAAoB,GAAI,KAAK,SAAS,CAAC,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;uBAO5D,CAAA;AAED,eAAO,MAAM,kBAAkB,GAAI,KAAK,SAAS,CAAC,SAAS,MAQjD,cAAc,MAAM,EAAE,IAAI,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;sBACzC,CAAA;AAED,eAAO,MAAM,MAAM,GAAI,KAAK,SAAS,CAAC,SAAS,MAsB3C,OAAO,MAAM,EACb,OAAO;IAAE,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,KAC3D,MAAM,CAAC,MAAM,CAAC,YAAY,EAAE,UAAU,CAoB1C,CAAA;AAED,eAAO,MAAM,aAAa,GAAI,KAAK,SAAS,CAAC,SAAS,MAS5C,WAAW,MAAM;;;;;uBAC1B,CAAA;AAED,eAAO,MAAM,eAAe,GAAI,KAAK,SAAS,CAAC,SAAS,MAa9C,WAAW,MAAM,EAAE,SAAS,MAAM;;;;;uBAC3C,CAAA"}
@@ -0,0 +1,89 @@
1
+ import * as SqlSchema from "@effect/sql/SqlSchema";
2
+ import { Effect, Option, Schema } from "effect";
3
+ import { AwsProfileName, AwsRegion } from "../../../Domain.js";
4
+ import { CachedPullRequest as CachedPullRequestSchema, cacheError } from "./internal.js";
5
+ const StaleOpenRow = Schema.Struct({
6
+ id: Schema.String,
7
+ awsAccountId: Schema.String,
8
+ accountProfile: AwsProfileName,
9
+ accountRegion: AwsRegion
10
+ });
11
+ export const findAll = (sql) => {
12
+ const run = SqlSchema.findAll({
13
+ Result: CachedPullRequestSchema,
14
+ Request: Schema.Void,
15
+ execute: () => sql `SELECT * FROM pull_requests ORDER BY creation_date DESC`
16
+ });
17
+ return () => run(undefined).pipe(cacheError("findAll"));
18
+ };
19
+ export const findMissingDiffStats = (sql) => {
20
+ const run = SqlSchema.findAll({
21
+ Result: CachedPullRequestSchema,
22
+ Request: Schema.Void,
23
+ execute: () => sql `SELECT * FROM pull_requests WHERE files_added IS NULL ORDER BY creation_date DESC`
24
+ });
25
+ return () => run(undefined).pipe(cacheError("findMissingDiffStats"));
26
+ };
27
+ export const findByAccountAndId = (sql) => {
28
+ const run = SqlSchema.findOne({
29
+ Result: CachedPullRequestSchema,
30
+ Request: Schema.Struct({ awsAccountId: Schema.String, id: Schema.String }),
31
+ execute: (req) => sql `SELECT * FROM pull_requests
32
+ WHERE aws_account_id = ${req.awsAccountId} AND id = ${req.id}`
33
+ });
34
+ return (awsAccountId, id) => run({ awsAccountId, id }).pipe(cacheError("findByAccountAndId"));
35
+ };
36
+ export const search = (sql) => {
37
+ const search_ = SqlSchema.findAll({
38
+ Result: CachedPullRequestSchema,
39
+ Request: Schema.Struct({ query: Schema.String, limit: Schema.Number, offset: Schema.Number }),
40
+ execute: (req) => sql `SELECT pull_requests.* FROM pull_requests
41
+ JOIN pull_requests_fts fts ON pull_requests.rowid = fts.rowid
42
+ WHERE pull_requests_fts MATCH ${req.query}
43
+ ORDER BY rank
44
+ LIMIT ${req.limit} OFFSET ${req.offset}`
45
+ });
46
+ const searchCount_ = SqlSchema.findOne({
47
+ Result: Schema.Struct({ count: Schema.Number }),
48
+ Request: Schema.Struct({ query: Schema.String }),
49
+ execute: (req) => sql `SELECT count(*) as count FROM pull_requests
50
+ JOIN pull_requests_fts fts ON pull_requests.rowid = fts.rowid
51
+ WHERE pull_requests_fts MATCH ${req.query}`
52
+ });
53
+ return (query, opts) => {
54
+ const limit = opts?.limit ?? 20;
55
+ const offset = opts?.offset ?? 0;
56
+ const stripped = query.replace(/[*^"]/g, "").replace(/\b(NEAR|OR|NOT|AND)\b/gi, "");
57
+ const escaped = stripped.replace(/"/g, `""`);
58
+ const ftsQuery = `"${escaped}"`;
59
+ return Effect.all({
60
+ items: search_({ query: ftsQuery, limit, offset }),
61
+ total: searchCount_({ query: ftsQuery }).pipe(Effect.map((r) => r.pipe(Option.getOrElse(() => ({ count: 0 }))).count))
62
+ }).pipe(Effect.map(({ items, total }) => ({ items, total, hasMore: offset + items.length < total })), Effect.catchTag("SqlError", () => Effect.logWarning("FTS search failed").pipe(Effect.as({ items: [], total: 0, hasMore: false }))), cacheError("search"));
63
+ };
64
+ };
65
+ export const findStaleOpen = (sql) => {
66
+ const run = SqlSchema.findAll({
67
+ Result: StaleOpenRow,
68
+ Request: Schema.Struct({ olderThan: Schema.String }),
69
+ execute: (req) => sql `SELECT id, aws_account_id, account_profile, account_region
70
+ FROM pull_requests
71
+ WHERE status = 'OPEN' AND fetched_at < ${req.olderThan}`
72
+ });
73
+ return (olderThan) => run({ olderThan }).pipe(cacheError("findStaleOpen"));
74
+ };
75
+ export const findOpenInRange = (sql) => {
76
+ const run = SqlSchema.findAll({
77
+ Result: StaleOpenRow,
78
+ Request: Schema.Struct({ weekStart: Schema.String, weekEnd: Schema.String }),
79
+ execute: (req) => sql `SELECT id, aws_account_id, account_profile, account_region
80
+ FROM pull_requests
81
+ WHERE status = 'OPEN'
82
+ AND (
83
+ (creation_date >= ${req.weekStart} AND creation_date < ${req.weekEnd})
84
+ OR (last_modified_date >= ${req.weekStart} AND last_modified_date < ${req.weekEnd})
85
+ )`
86
+ });
87
+ return (weekStart, weekEnd) => run({ weekStart, weekEnd }).pipe(cacheError("findOpenInRange"));
88
+ };
89
+ //# sourceMappingURL=queries.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queries.js","sourceRoot":"","sources":["../../../../src/CacheService/repos/PullRequestRepo/queries.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,93 @@
1
+ /**
2
+ * @module StatsRepo
3
+ *
4
+ * Read-only SQL projection layer for the statistics dashboard.
5
+ * Assembles query methods from `./queries` and `./reviewerData` into
6
+ * a single Effect.Service.
7
+ *
8
+ * @category CacheService
9
+ */
10
+ import * as SqlClient from "@effect/sql/SqlClient";
11
+ import { Effect } from "effect";
12
+ declare const StatsRepo_base: Effect.Service.Class<StatsRepo, "StatsRepo", {
13
+ readonly dependencies: readonly [import("effect/Layer").Layer<SqlClient.SqlClient | import("@effect/sql-libsql/LibsqlClient").LibsqlClient, import("@effect/sql/SqlError").SqlError | import("effect/ConfigError").ConfigError | import("@effect/sql/Migrator").MigrationError, import("@effect/platform/FileSystem").FileSystem>];
14
+ readonly effect: Effect.Effect<{
15
+ readonly weeklyVolume: (weekStart: string, weekEnd: string, filters: import("./internal.ts").Filters) => Effect.Effect<import("./internal.ts").VolumeRow, import("../../CacheError.ts").CacheError, never>;
16
+ readonly topContributors: (weekStart: string, weekEnd: string, filters: import("./internal.ts").Filters, limit?: number) => Effect.Effect<readonly import("./internal.ts").ContributorRow[], import("../../CacheError.ts").CacheError, never>;
17
+ readonly mostActivePRs: (weekStart: string, weekEnd: string, filters: import("./internal.ts").Filters, limit?: number) => Effect.Effect<readonly import("./internal.ts").ActivePRRow[], import("../../CacheError.ts").CacheError, never>;
18
+ readonly prSizeDistribution: (weekStart: string, weekEnd: string, filters: import("./internal.ts").Filters) => Effect.Effect<import("./internal.ts").SizeDistributionRow, import("../../CacheError.ts").CacheError, never>;
19
+ readonly avgDiffSize: (weekStart: string, weekEnd: string, filters: import("./internal.ts").Filters) => Effect.Effect<{
20
+ filesAdded: number;
21
+ filesModified: number;
22
+ filesDeleted: number;
23
+ } | null, import("../../CacheError.ts").CacheError, never>;
24
+ readonly diffSizeByContributor: (weekStart: string, weekEnd: string, filters: import("./internal.ts").Filters, limit?: number) => Effect.Effect<readonly import("./internal.ts").DiffByContributorRow[], import("../../CacheError.ts").CacheError, never>;
25
+ readonly stalePRs: (nowISO: string, filters: import("./internal.ts").Filters, limit?: number) => Effect.Effect<readonly import("./internal.ts").StalePRRow[], import("../../CacheError.ts").CacheError, never>;
26
+ readonly healthIndicators: (weekStart: string, weekEnd: string, filters: import("./internal.ts").Filters) => Effect.Effect<import("./internal.ts").HealthRow, import("../../CacheError.ts").CacheError, never>;
27
+ readonly filterOptions: () => Effect.Effect<{
28
+ repos: string[];
29
+ authors: string[];
30
+ accounts: string[];
31
+ }, import("../../CacheError.ts").CacheError, never>;
32
+ readonly totalComments: (weekStart: string, weekEnd: string, filters: import("./internal.ts").Filters) => Effect.Effect<number, import("../../CacheError.ts").CacheError, never>;
33
+ readonly reviewerData: (weekStart: string, weekEnd: string, filters: import("./internal.ts").Filters) => Effect.Effect<{
34
+ topReviewers: {
35
+ author: string;
36
+ commentCount: number;
37
+ }[];
38
+ topApprovers: {
39
+ author: string;
40
+ approvalCount: number;
41
+ }[];
42
+ avgTimeToFirstReview: number | null;
43
+ avgTimeToMerge: number | null;
44
+ avgTimeToAddressFeedback: number | null;
45
+ firstReviewDetails: {
46
+ prId: string;
47
+ prTitle: string;
48
+ author: string;
49
+ repositoryName: string;
50
+ awsAccountId: string;
51
+ durationMs: number;
52
+ fromLabel: string;
53
+ toLabel: string;
54
+ }[];
55
+ feedbackDetails: {
56
+ prId: string;
57
+ prTitle: string;
58
+ author: string;
59
+ repositoryName: string;
60
+ awsAccountId: string;
61
+ durationMs: number;
62
+ fromLabel: string;
63
+ toLabel: string;
64
+ }[];
65
+ }, import("../../CacheError.ts").CacheError, never>;
66
+ readonly mergeTimeDetails: (weekStart: string, weekEnd: string, filters: import("./internal.ts").Filters) => Effect.Effect<{
67
+ prId: string;
68
+ prTitle: string;
69
+ author: string;
70
+ repositoryName: string;
71
+ awsAccountId: string;
72
+ durationMs: number;
73
+ fromLabel: string;
74
+ toLabel: string;
75
+ }[], import("../../CacheError.ts").CacheError, never>;
76
+ readonly avgTimeToMerge: (weekStart: string, weekEnd: string, filters: import("./internal.ts").Filters) => Effect.Effect<number | null, import("../../CacheError.ts").CacheError, never>;
77
+ readonly dataAvailableSince: () => Effect.Effect<string | null, import("../../CacheError.ts").CacheError, never>;
78
+ }, never, SqlClient.SqlClient>;
79
+ }>;
80
+ export declare class StatsRepo extends StatsRepo_base {
81
+ }
82
+ export declare namespace StatsRepo {
83
+ /**
84
+ * @category models
85
+ */
86
+ interface Filters {
87
+ readonly repo?: string | undefined;
88
+ readonly author?: string | undefined;
89
+ readonly account?: string | undefined;
90
+ }
91
+ }
92
+ export {};
93
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/CacheService/repos/StatsRepo/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,KAAK,SAAS,MAAM,uBAAuB,CAAA;AAClD,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAS/B,qBAAa,SAAU,SAAQ,cAsB7B;CAAG;AAEL,MAAM,CAAC,OAAO,WAAW,SAAS,CAAC;IACjC;;OAEG;IACH,UAAiB,OAAO;QACtB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;QAClC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;QACpC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;KACtC;CACF"}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * @module StatsRepo
3
+ *
4
+ * Read-only SQL projection layer for the statistics dashboard.
5
+ * Assembles query methods from `./queries` and `./reviewerData` into
6
+ * a single Effect.Service.
7
+ *
8
+ * @category CacheService
9
+ */
10
+ import * as SqlClient from "@effect/sql/SqlClient";
11
+ import { Effect } from "effect";
12
+ import { DatabaseLive } from "../../Database.js";
13
+ import * as Q from "./queries.js";
14
+ import { reviewerData } from "./reviewerData.js";
15
+ // ---------------------------------------------------------------------------
16
+ // Service
17
+ // ---------------------------------------------------------------------------
18
+ export class StatsRepo extends Effect.Service()("StatsRepo", {
19
+ dependencies: [DatabaseLive],
20
+ effect: Effect.gen(function* () {
21
+ const sql = yield* SqlClient.SqlClient;
22
+ return {
23
+ weeklyVolume: Q.weeklyVolume(sql),
24
+ topContributors: Q.topContributors(sql),
25
+ mostActivePRs: Q.mostActivePRs(sql),
26
+ prSizeDistribution: Q.prSizeDistribution(sql),
27
+ avgDiffSize: Q.avgDiffSize(sql),
28
+ diffSizeByContributor: Q.diffSizeByContributor(sql),
29
+ stalePRs: Q.stalePRs(sql),
30
+ healthIndicators: Q.healthIndicators(sql),
31
+ filterOptions: Q.filterOptions(sql),
32
+ totalComments: Q.totalComments(sql),
33
+ reviewerData: reviewerData(sql),
34
+ mergeTimeDetails: Q.mergeTimeDetails(sql),
35
+ avgTimeToMerge: Q.avgTimeToMerge(sql),
36
+ dataAvailableSince: Q.dataAvailableSince(sql)
37
+ };
38
+ })
39
+ }) {
40
+ }
41
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/CacheService/repos/StatsRepo/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,KAAK,SAAS,MAAM,uBAAuB,CAAA;AAClD,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAC/B,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAChD,OAAO,KAAK,CAAC,MAAM,cAAc,CAAA;AACjC,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAEhD,8EAA8E;AAC9E,UAAU;AACV,8EAA8E;AAE9E,MAAM,OAAO,SAAU,SAAQ,MAAM,CAAC,OAAO,EAAa,CAAC,WAAW,EAAE;IACtE,YAAY,EAAE,CAAC,YAAY,CAAC;IAC5B,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;QAC1B,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,SAAS,CAAC,SAAS,CAAA;QAEtC,OAAO;YACL,YAAY,EAAE,CAAC,CAAC,YAAY,CAAC,GAAG,CAAC;YACjC,eAAe,EAAE,CAAC,CAAC,eAAe,CAAC,GAAG,CAAC;YACvC,aAAa,EAAE,CAAC,CAAC,aAAa,CAAC,GAAG,CAAC;YACnC,kBAAkB,EAAE,CAAC,CAAC,kBAAkB,CAAC,GAAG,CAAC;YAC7C,WAAW,EAAE,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC;YAC/B,qBAAqB,EAAE,CAAC,CAAC,qBAAqB,CAAC,GAAG,CAAC;YACnD,QAAQ,EAAE,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC;YACzB,gBAAgB,EAAE,CAAC,CAAC,gBAAgB,CAAC,GAAG,CAAC;YACzC,aAAa,EAAE,CAAC,CAAC,aAAa,CAAC,GAAG,CAAC;YACnC,aAAa,EAAE,CAAC,CAAC,aAAa,CAAC,GAAG,CAAC;YACnC,YAAY,EAAE,YAAY,CAAC,GAAG,CAAC;YAC/B,gBAAgB,EAAE,CAAC,CAAC,gBAAgB,CAAC,GAAG,CAAC;YACzC,cAAc,EAAE,CAAC,CAAC,cAAc,CAAC,GAAG,CAAC;YACrC,kBAAkB,EAAE,CAAC,CAAC,kBAAkB,CAAC,GAAG,CAAC;SACrC,CAAA;IACZ,CAAC,CAAC;CACH,CAAC;CAAG"}
@@ -0,0 +1,120 @@
1
+ /**
2
+ * @module StatsRepo/internal
3
+ *
4
+ * Shared types, row interfaces, and helpers used across the StatsRepo query modules.
5
+ * Everything here is pure (no SQL dependency) except `whereFilters` which takes `sql`.
6
+ *
7
+ * @category CacheService
8
+ */
9
+ import type * as SqlClient from "@effect/sql/SqlClient";
10
+ import { Effect, Schema } from "effect";
11
+ import { PRCommentLocationJson } from "../../../Domain.js";
12
+ import { CacheError } from "../../CacheError.js";
13
+ export interface VolumeRow {
14
+ readonly prsCreated: number;
15
+ readonly prsMerged: number;
16
+ readonly prsClosed: number;
17
+ }
18
+ export interface ContributorRow {
19
+ readonly author: string;
20
+ readonly prCount: number;
21
+ }
22
+ export interface ActivePRRow {
23
+ readonly id: string;
24
+ readonly title: string;
25
+ readonly author: string;
26
+ readonly repositoryName: string;
27
+ readonly commentCount: number | null;
28
+ readonly awsAccountId: string;
29
+ }
30
+ export interface SizeDistributionRow {
31
+ readonly small: number;
32
+ readonly medium: number;
33
+ readonly large: number;
34
+ readonly extraLarge: number;
35
+ }
36
+ export interface AvgDiffRow {
37
+ readonly avgAdded: number | null;
38
+ readonly avgModified: number | null;
39
+ readonly avgDeleted: number | null;
40
+ }
41
+ export interface DiffByContributorRow {
42
+ readonly author: string;
43
+ readonly avgFilesChanged: number;
44
+ readonly prCount: number;
45
+ }
46
+ export interface StalePRRow {
47
+ readonly id: string;
48
+ readonly title: string;
49
+ readonly author: string;
50
+ readonly repositoryName: string;
51
+ readonly daysSinceActivity: number;
52
+ readonly awsAccountId: string;
53
+ }
54
+ export interface HealthRow {
55
+ readonly total: number;
56
+ readonly withComments: number;
57
+ readonly approved: number;
58
+ }
59
+ export interface FilterOptionsRow {
60
+ readonly repos: string;
61
+ readonly authors: string;
62
+ readonly accounts: string;
63
+ }
64
+ export interface CommentRow {
65
+ readonly pullRequestId: string;
66
+ readonly awsAccountId: string;
67
+ readonly locationsJson: string;
68
+ }
69
+ export interface PRForReviewRow {
70
+ readonly id: string;
71
+ readonly title: string;
72
+ readonly approvedBy: string | null;
73
+ readonly author: string;
74
+ readonly awsAccountId: string;
75
+ readonly creationDate: string;
76
+ readonly closedAt: string | null;
77
+ readonly lastModifiedDate: string;
78
+ readonly isApproved: number;
79
+ readonly mergedBy: string | null;
80
+ readonly repositoryName: string;
81
+ readonly status: string;
82
+ }
83
+ export interface MergeTimeDetailRow {
84
+ readonly id: string;
85
+ readonly title: string;
86
+ readonly author: string;
87
+ readonly repositoryName: string;
88
+ readonly awsAccountId: string;
89
+ readonly creationDate: string;
90
+ readonly lastModifiedDate: string;
91
+ readonly durationMs: number;
92
+ }
93
+ export interface EarliestRow {
94
+ readonly earliest: string | null;
95
+ }
96
+ export interface CommentInfo {
97
+ readonly author: string;
98
+ readonly creationDate: Date;
99
+ }
100
+ export declare const LocationsFromJson: Schema.transform<Schema.SchemaClass<unknown, string, never>, Schema.Array$<Schema.Struct<{
101
+ filePath: Schema.optional<typeof Schema.String>;
102
+ beforeCommitId: Schema.optional<typeof Schema.String>;
103
+ afterCommitId: Schema.optional<typeof Schema.String>;
104
+ comments: Schema.Array$<Schema.Schema<import("../../../Domain.js").CommentThreadJsonEncoded, import("../../../Domain.js").CommentThreadJsonEncoded, never>>;
105
+ }>>>;
106
+ export declare const cacheError: (op: string) => <A, E, R>(effect: Effect.Effect<A, E, R>) => Effect.Effect<A, CacheError, Exclude<R, import("effect/Tracer").ParentSpan>>;
107
+ export declare const extractComments: (locations: ReadonlyArray<typeof PRCommentLocationJson.Type>) => ReadonlyArray<CommentInfo>;
108
+ export declare const parseFilter: (v?: string) => ReadonlyArray<string> | undefined;
109
+ /** @see StatsRepo.Filters */
110
+ export type Filters = {
111
+ readonly repo?: string | undefined;
112
+ readonly author?: string | undefined;
113
+ readonly account?: string | undefined;
114
+ };
115
+ export declare const whereFilters: (sql: SqlClient.SqlClient, filters: Filters, table?: string) => {
116
+ repo: import("@effect/sql/Statement").Statement<import("@effect/sql/SqlConnection").Row>;
117
+ author: import("@effect/sql/Statement").Statement<import("@effect/sql/SqlConnection").Row>;
118
+ account: import("@effect/sql/Statement").Statement<import("@effect/sql/SqlConnection").Row>;
119
+ };
120
+ //# sourceMappingURL=internal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"internal.d.ts","sourceRoot":"","sources":["../../../../src/CacheService/repos/StatsRepo/internal.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,34 @@
1
+ import { Effect, Schema } from "effect";
2
+ import { PRCommentLocationJson } from "../../../Domain.js";
3
+ import { CacheError } from "../../CacheError.js";
4
+ // ---------------------------------------------------------------------------
5
+ // Helpers
6
+ // ---------------------------------------------------------------------------
7
+ export const LocationsFromJson = Schema.parseJson(Schema.Array(PRCommentLocationJson));
8
+ export const cacheError = (op) => (effect) => effect.pipe(Effect.mapError((cause) => new CacheError({ operation: `StatsRepo.${op}`, cause })), Effect.withSpan(`StatsRepo.${op}`, { captureStackTrace: false }));
9
+ export const extractComments = (locations) => {
10
+ const result = [];
11
+ const walk = (threads) => {
12
+ for (const t of threads) {
13
+ result.push({ author: t.root.author, creationDate: new Date(t.root.creationDate) });
14
+ walk(t.replies);
15
+ }
16
+ };
17
+ for (const loc of locations) {
18
+ walk(loc.comments);
19
+ }
20
+ return result;
21
+ };
22
+ export const parseFilter = (v) => v ? v.split(",").map((s) => s.trim()).filter(Boolean) : undefined;
23
+ export const whereFilters = (sql, filters, table) => {
24
+ const repos = parseFilter(filters.repo);
25
+ const authors = parseFilter(filters.author);
26
+ const accounts = parseFilter(filters.account);
27
+ const t = table ? `${table}.` : "";
28
+ return {
29
+ repo: repos ? sql `AND ${sql.unsafe(`${t}repository_name`)} IN ${sql.in(repos)}` : sql ``,
30
+ author: authors ? sql `AND ${sql.unsafe(`${t}author`)} IN ${sql.in(authors)}` : sql ``,
31
+ account: accounts ? sql `AND ${sql.unsafe(`${t}aws_account_id`)} IN ${sql.in(accounts)}` : sql ``
32
+ };
33
+ };
34
+ //# sourceMappingURL=internal.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"internal.js","sourceRoot":"","sources":["../../../../src/CacheService/repos/StatsRepo/internal.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,42 @@
1
+ /**
2
+ * @module StatsRepo/queries
3
+ *
4
+ * Simple SQL query methods. Each function takes `sql` (SqlClient) and returns
5
+ * the method implementation for the StatsRepo service.
6
+ *
7
+ * @category CacheService
8
+ */
9
+ import type * as SqlClient from "@effect/sql/SqlClient";
10
+ import { Effect } from "effect";
11
+ import { type ActivePRRow, type ContributorRow, type DiffByContributorRow, type Filters, type HealthRow, type SizeDistributionRow, type StalePRRow, type VolumeRow } from "./internal.js";
12
+ export declare const weeklyVolume: (sql: SqlClient.SqlClient) => (weekStart: string, weekEnd: string, filters: Filters) => Effect.Effect<VolumeRow, import("../../CacheError.ts").CacheError, never>;
13
+ export declare const topContributors: (sql: SqlClient.SqlClient) => (weekStart: string, weekEnd: string, filters: Filters, limit?: number) => Effect.Effect<readonly ContributorRow[], import("../../CacheError.ts").CacheError, never>;
14
+ export declare const mostActivePRs: (sql: SqlClient.SqlClient) => (weekStart: string, weekEnd: string, filters: Filters, limit?: number) => Effect.Effect<readonly ActivePRRow[], import("../../CacheError.ts").CacheError, never>;
15
+ export declare const prSizeDistribution: (sql: SqlClient.SqlClient) => (weekStart: string, weekEnd: string, filters: Filters) => Effect.Effect<SizeDistributionRow, import("../../CacheError.ts").CacheError, never>;
16
+ export declare const avgDiffSize: (sql: SqlClient.SqlClient) => (weekStart: string, weekEnd: string, filters: Filters) => Effect.Effect<{
17
+ filesAdded: number;
18
+ filesModified: number;
19
+ filesDeleted: number;
20
+ } | null, import("../../CacheError.ts").CacheError, never>;
21
+ export declare const diffSizeByContributor: (sql: SqlClient.SqlClient) => (weekStart: string, weekEnd: string, filters: Filters, limit?: number) => Effect.Effect<readonly DiffByContributorRow[], import("../../CacheError.ts").CacheError, never>;
22
+ export declare const stalePRs: (sql: SqlClient.SqlClient) => (nowISO: string, filters: Filters, limit?: number) => Effect.Effect<readonly StalePRRow[], import("../../CacheError.ts").CacheError, never>;
23
+ export declare const healthIndicators: (sql: SqlClient.SqlClient) => (weekStart: string, weekEnd: string, filters: Filters) => Effect.Effect<HealthRow, import("../../CacheError.ts").CacheError, never>;
24
+ export declare const filterOptions: (sql: SqlClient.SqlClient) => () => Effect.Effect<{
25
+ repos: string[];
26
+ authors: string[];
27
+ accounts: string[];
28
+ }, import("../../CacheError.ts").CacheError, never>;
29
+ export declare const totalComments: (sql: SqlClient.SqlClient) => (weekStart: string, weekEnd: string, filters: Filters) => Effect.Effect<number, import("../../CacheError.ts").CacheError, never>;
30
+ export declare const mergeTimeDetails: (sql: SqlClient.SqlClient) => (weekStart: string, weekEnd: string, filters: Filters) => Effect.Effect<{
31
+ prId: string;
32
+ prTitle: string;
33
+ author: string;
34
+ repositoryName: string;
35
+ awsAccountId: string;
36
+ durationMs: number;
37
+ fromLabel: string;
38
+ toLabel: string;
39
+ }[], import("../../CacheError.ts").CacheError, never>;
40
+ export declare const avgTimeToMerge: (sql: SqlClient.SqlClient) => (weekStart: string, weekEnd: string, filters: Filters) => Effect.Effect<number | null, import("../../CacheError.ts").CacheError, never>;
41
+ export declare const dataAvailableSince: (sql: SqlClient.SqlClient) => () => Effect.Effect<string | null, import("../../CacheError.ts").CacheError, never>;
42
+ //# sourceMappingURL=queries.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queries.d.ts","sourceRoot":"","sources":["../../../../src/CacheService/repos/StatsRepo/queries.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,KAAK,SAAS,MAAM,uBAAuB,CAAA;AACvD,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAC/B,OAAO,EACL,KAAK,WAAW,EAGhB,KAAK,cAAc,EACnB,KAAK,oBAAoB,EAGzB,KAAK,OAAO,EACZ,KAAK,SAAS,EAEd,KAAK,mBAAmB,EACxB,KAAK,UAAU,EACf,KAAK,SAAS,EAEf,MAAM,eAAe,CAAA;AAItB,eAAO,MAAM,YAAY,GAAI,KAAK,SAAS,CAAC,SAAS,MAAM,WAAW,MAAM,EAAE,SAAS,MAAM,EAAE,SAAS,OAAO,8EAc9G,CAAA;AAED,eAAO,MAAM,eAAe,GACzB,KAAK,SAAS,CAAC,SAAS,MAAM,WAAW,MAAM,EAAE,SAAS,MAAM,EAAE,SAAS,OAAO,EAAE,cAAU,8FAY9F,CAAA;AAEH,eAAO,MAAM,aAAa,GACvB,KAAK,SAAS,CAAC,SAAS,MAAM,WAAW,MAAM,EAAE,SAAS,MAAM,EAAE,SAAS,OAAO,EAAE,cAAU,2FAY9F,CAAA;AAEH,eAAO,MAAM,kBAAkB,GAC5B,KAAK,SAAS,CAAC,SAAS,MAAM,WAAW,MAAM,EAAE,SAAS,MAAM,EAAE,SAAS,OAAO,wFAiBlF,CAAA;AAEH,eAAO,MAAM,WAAW,GAAI,KAAK,SAAS,CAAC,SAAS,MAAM,WAAW,MAAM,EAAE,SAAS,MAAM,EAAE,SAAS,OAAO;;;;0DAoB7G,CAAA;AAED,eAAO,MAAM,qBAAqB,GAC/B,KAAK,SAAS,CAAC,SAAS,MAAM,WAAW,MAAM,EAAE,SAAS,MAAM,EAAE,SAAS,OAAO,EAAE,cAAU,oGAgB9F,CAAA;AAEH,eAAO,MAAM,QAAQ,GAAI,KAAK,SAAS,CAAC,SAAS,MAAM,QAAQ,MAAM,EAAE,SAAS,OAAO,EAAE,cAAU,0FAalG,CAAA;AAED,eAAO,MAAM,gBAAgB,GAC1B,KAAK,SAAS,CAAC,SAAS,MAAM,WAAW,MAAM,EAAE,SAAS,MAAM,EAAE,SAAS,OAAO,8EAelF,CAAA;AAEH,eAAO,MAAM,aAAa,GAAI,KAAK,SAAS,CAAC,SAAS;;;;mDAkBnD,CAAA;AAEH,eAAO,MAAM,aAAa,GAAI,KAAK,SAAS,CAAC,SAAS,MAAM,WAAW,MAAM,EAAE,SAAS,MAAM,EAAE,SAAS,OAAO,2EAY/G,CAAA;AAED,eAAO,MAAM,gBAAgB,GAC1B,KAAK,SAAS,CAAC,SAAS,MAAM,WAAW,MAAM,EAAE,SAAS,MAAM,EAAE,SAAS,OAAO;;;;;;;;;qDA0BlF,CAAA;AAEH,eAAO,MAAM,cAAc,GAAI,KAAK,SAAS,CAAC,SAAS,MAAM,WAAW,MAAM,EAAE,SAAS,MAAM,EAAE,SAAS,OAAO,kFAchH,CAAA;AAED,eAAO,MAAM,kBAAkB,GAAI,KAAK,SAAS,CAAC,SAAS,wFAMxD,CAAA"}