@ubiquity-os/plugin-sdk 2.0.6 → 3.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.
package/dist/index.d.mts CHANGED
@@ -1,17 +1,104 @@
1
1
  import * as hono_types from 'hono/types';
2
2
  import { EmitterWebhookEventName, EmitterWebhookEvent } from '@octokit/webhooks';
3
3
  import { Hono } from 'hono';
4
- import { Logs, LogLevel, LogReturn } from '@ubiquity-os/ubiquity-os-logger';
4
+ import * as _ubiquity_os_ubiquity_os_logger from '@ubiquity-os/ubiquity-os-logger';
5
+ import { LogReturn, Metadata, Logs, LogLevel } from '@ubiquity-os/ubiquity-os-logger';
6
+ import { RestEndpointMethodTypes } from '@octokit/plugin-rest-endpoint-methods';
5
7
  import { customOctokit } from './octokit.mjs';
6
8
  import { Manifest } from './manifest.mjs';
7
9
  import { TAnySchema } from '@sinclair/typebox';
8
- import { RestEndpointMethodTypes } from '@octokit/plugin-rest-endpoint-methods';
9
10
  import '@octokit/core/dist-types/types';
10
11
  import '@octokit/plugin-paginate-graphql';
11
12
  import '@octokit/plugin-paginate-rest';
12
13
  import '@octokit/request-error';
13
14
  import '@octokit/core';
14
15
 
16
+ interface CommentOptions {
17
+ raw?: boolean;
18
+ updateComment?: boolean;
19
+ }
20
+ type PostedGithubComment = RestEndpointMethodTypes["issues"]["updateComment"]["response"]["data"] | RestEndpointMethodTypes["issues"]["createComment"]["response"]["data"] | RestEndpointMethodTypes["pulls"]["createReplyForReviewComment"]["response"]["data"];
21
+ type WithIssueNumber<T> = T & {
22
+ issueNumber: number;
23
+ };
24
+ interface IssueContext {
25
+ issueNumber: number;
26
+ commentId?: number;
27
+ owner: string;
28
+ repo: string;
29
+ }
30
+ declare class CommentHandler {
31
+ static readonly HEADER_NAME = "UbiquityOS";
32
+ private _lastCommentId;
33
+ _updateIssueComment(context: Context, params: {
34
+ owner: string;
35
+ repo: string;
36
+ body: string;
37
+ issueNumber: number;
38
+ }): Promise<WithIssueNumber<PostedGithubComment>>;
39
+ _updateReviewComment(context: Context, params: {
40
+ owner: string;
41
+ repo: string;
42
+ body: string;
43
+ issueNumber: number;
44
+ }): Promise<WithIssueNumber<PostedGithubComment>>;
45
+ _createNewComment(context: Context, params: {
46
+ owner: string;
47
+ repo: string;
48
+ body: string;
49
+ issueNumber: number;
50
+ commentId?: number;
51
+ }): Promise<WithIssueNumber<PostedGithubComment>>;
52
+ _getIssueNumber(context: Context): number | undefined;
53
+ _getCommentId(context: Context): number | undefined;
54
+ _extractIssueContext(context: Context): IssueContext | null;
55
+ _processMessage(context: Context, message: LogReturn | Error): Promise<{
56
+ metadata: {
57
+ message: string;
58
+ name: string;
59
+ stack: string | undefined;
60
+ };
61
+ logMessage: {
62
+ raw: string;
63
+ diff: string;
64
+ level: _ubiquity_os_ubiquity_os_logger.LogLevel;
65
+ type: _ubiquity_os_ubiquity_os_logger.LogLevelWithOk;
66
+ };
67
+ } | {
68
+ metadata: {
69
+ message: string | undefined;
70
+ stack: string | string[] | undefined;
71
+ caller: {} | undefined;
72
+ error?: Error | {
73
+ stack: string;
74
+ } | undefined;
75
+ name?: string | undefined;
76
+ } | {
77
+ logMessage: {
78
+ raw: string;
79
+ diff: string;
80
+ level: _ubiquity_os_ubiquity_os_logger.LogLevel;
81
+ type: _ubiquity_os_ubiquity_os_logger.LogLevelWithOk;
82
+ };
83
+ metadata?: Metadata;
84
+ };
85
+ logMessage: {
86
+ raw: string;
87
+ diff: string;
88
+ level: _ubiquity_os_ubiquity_os_logger.LogLevel;
89
+ type: _ubiquity_os_ubiquity_os_logger.LogLevelWithOk;
90
+ };
91
+ }>;
92
+ _getInstigatorName(context: Context): string;
93
+ _createMetadataContent(context: Context, metadata: Metadata): Promise<{
94
+ header: string;
95
+ jsonPretty: string;
96
+ }>;
97
+ _formatMetadataContent(logMessage: LogReturn["logMessage"], header: string, jsonPretty: string): string;
98
+ _createCommentBody(context: Context, message: LogReturn | Error, options: CommentOptions): Promise<string>;
99
+ postComment(context: Context, message: LogReturn | Error, options?: CommentOptions): Promise<WithIssueNumber<PostedGithubComment> | null>;
100
+ }
101
+
15
102
  interface Context<TConfig = unknown, TEnv = unknown, TCommand = unknown, TSupportedEvents extends EmitterWebhookEventName = EmitterWebhookEventName> {
16
103
  eventName: TSupportedEvents;
17
104
  payload: {
@@ -22,6 +109,7 @@ interface Context<TConfig = unknown, TEnv = unknown, TCommand = unknown, TSuppor
22
109
  config: TConfig;
23
110
  env: TEnv;
24
111
  logger: Logs;
112
+ commentHandler: CommentHandler;
25
113
  }
26
114
 
27
115
  type Return = Record<string, unknown> | undefined | void;
@@ -44,20 +132,4 @@ declare function createPlugin<TConfig = unknown, TEnv = unknown, TCommand = unkn
44
132
 
45
133
  declare function createActionsPlugin<TConfig = unknown, TEnv = unknown, TCommand = unknown, TSupportedEvents extends EmitterWebhookEventName = EmitterWebhookEventName>(handler: (context: Context<TConfig, TEnv, TCommand, TSupportedEvents>) => HandlerReturn, options?: Options): Promise<void>;
46
134
 
47
- interface CommentOptions {
48
- raw?: boolean;
49
- updateComment?: boolean;
50
- }
51
- type WithIssueNumber<T> = T & {
52
- issueNumber: number;
53
- };
54
- type PostComment = {
55
- (context: Context, message: LogReturn | Error, options?: CommentOptions): Promise<WithIssueNumber<RestEndpointMethodTypes["issues"]["updateComment"]["response"]["data"] | RestEndpointMethodTypes["issues"]["createComment"]["response"]["data"]> | null>;
56
- lastCommentId?: number;
57
- };
58
- /**
59
- * Posts a comment on a GitHub issue if the issue exists in the context payload, embedding structured metadata to it.
60
- */
61
- declare const postComment: PostComment;
62
-
63
- export { type Context, createActionsPlugin, createPlugin, postComment };
135
+ export { CommentHandler, type Context, createActionsPlugin, createPlugin };
package/dist/index.d.ts CHANGED
@@ -1,17 +1,104 @@
1
1
  import * as hono_types from 'hono/types';
2
2
  import { EmitterWebhookEventName, EmitterWebhookEvent } from '@octokit/webhooks';
3
3
  import { Hono } from 'hono';
4
- import { Logs, LogLevel, LogReturn } from '@ubiquity-os/ubiquity-os-logger';
4
+ import * as _ubiquity_os_ubiquity_os_logger from '@ubiquity-os/ubiquity-os-logger';
5
+ import { LogReturn, Metadata, Logs, LogLevel } from '@ubiquity-os/ubiquity-os-logger';
6
+ import { RestEndpointMethodTypes } from '@octokit/plugin-rest-endpoint-methods';
5
7
  import { customOctokit } from './octokit.js';
6
8
  import { Manifest } from './manifest.js';
7
9
  import { TAnySchema } from '@sinclair/typebox';
8
- import { RestEndpointMethodTypes } from '@octokit/plugin-rest-endpoint-methods';
9
10
  import '@octokit/core/dist-types/types';
10
11
  import '@octokit/plugin-paginate-graphql';
11
12
  import '@octokit/plugin-paginate-rest';
12
13
  import '@octokit/request-error';
13
14
  import '@octokit/core';
14
15
 
16
+ interface CommentOptions {
17
+ raw?: boolean;
18
+ updateComment?: boolean;
19
+ }
20
+ type PostedGithubComment = RestEndpointMethodTypes["issues"]["updateComment"]["response"]["data"] | RestEndpointMethodTypes["issues"]["createComment"]["response"]["data"] | RestEndpointMethodTypes["pulls"]["createReplyForReviewComment"]["response"]["data"];
21
+ type WithIssueNumber<T> = T & {
22
+ issueNumber: number;
23
+ };
24
+ interface IssueContext {
25
+ issueNumber: number;
26
+ commentId?: number;
27
+ owner: string;
28
+ repo: string;
29
+ }
30
+ declare class CommentHandler {
31
+ static readonly HEADER_NAME = "UbiquityOS";
32
+ private _lastCommentId;
33
+ _updateIssueComment(context: Context, params: {
34
+ owner: string;
35
+ repo: string;
36
+ body: string;
37
+ issueNumber: number;
38
+ }): Promise<WithIssueNumber<PostedGithubComment>>;
39
+ _updateReviewComment(context: Context, params: {
40
+ owner: string;
41
+ repo: string;
42
+ body: string;
43
+ issueNumber: number;
44
+ }): Promise<WithIssueNumber<PostedGithubComment>>;
45
+ _createNewComment(context: Context, params: {
46
+ owner: string;
47
+ repo: string;
48
+ body: string;
49
+ issueNumber: number;
50
+ commentId?: number;
51
+ }): Promise<WithIssueNumber<PostedGithubComment>>;
52
+ _getIssueNumber(context: Context): number | undefined;
53
+ _getCommentId(context: Context): number | undefined;
54
+ _extractIssueContext(context: Context): IssueContext | null;
55
+ _processMessage(context: Context, message: LogReturn | Error): Promise<{
56
+ metadata: {
57
+ message: string;
58
+ name: string;
59
+ stack: string | undefined;
60
+ };
61
+ logMessage: {
62
+ raw: string;
63
+ diff: string;
64
+ level: _ubiquity_os_ubiquity_os_logger.LogLevel;
65
+ type: _ubiquity_os_ubiquity_os_logger.LogLevelWithOk;
66
+ };
67
+ } | {
68
+ metadata: {
69
+ message: string | undefined;
70
+ stack: string | string[] | undefined;
71
+ caller: {} | undefined;
72
+ error?: Error | {
73
+ stack: string;
74
+ } | undefined;
75
+ name?: string | undefined;
76
+ } | {
77
+ logMessage: {
78
+ raw: string;
79
+ diff: string;
80
+ level: _ubiquity_os_ubiquity_os_logger.LogLevel;
81
+ type: _ubiquity_os_ubiquity_os_logger.LogLevelWithOk;
82
+ };
83
+ metadata?: Metadata;
84
+ };
85
+ logMessage: {
86
+ raw: string;
87
+ diff: string;
88
+ level: _ubiquity_os_ubiquity_os_logger.LogLevel;
89
+ type: _ubiquity_os_ubiquity_os_logger.LogLevelWithOk;
90
+ };
91
+ }>;
92
+ _getInstigatorName(context: Context): string;
93
+ _createMetadataContent(context: Context, metadata: Metadata): Promise<{
94
+ header: string;
95
+ jsonPretty: string;
96
+ }>;
97
+ _formatMetadataContent(logMessage: LogReturn["logMessage"], header: string, jsonPretty: string): string;
98
+ _createCommentBody(context: Context, message: LogReturn | Error, options: CommentOptions): Promise<string>;
99
+ postComment(context: Context, message: LogReturn | Error, options?: CommentOptions): Promise<WithIssueNumber<PostedGithubComment> | null>;
100
+ }
101
+
15
102
  interface Context<TConfig = unknown, TEnv = unknown, TCommand = unknown, TSupportedEvents extends EmitterWebhookEventName = EmitterWebhookEventName> {
16
103
  eventName: TSupportedEvents;
17
104
  payload: {
@@ -22,6 +109,7 @@ interface Context<TConfig = unknown, TEnv = unknown, TCommand = unknown, TSuppor
22
109
  config: TConfig;
23
110
  env: TEnv;
24
111
  logger: Logs;
112
+ commentHandler: CommentHandler;
25
113
  }
26
114
 
27
115
  type Return = Record<string, unknown> | undefined | void;
@@ -44,20 +132,4 @@ declare function createPlugin<TConfig = unknown, TEnv = unknown, TCommand = unkn
44
132
 
45
133
  declare function createActionsPlugin<TConfig = unknown, TEnv = unknown, TCommand = unknown, TSupportedEvents extends EmitterWebhookEventName = EmitterWebhookEventName>(handler: (context: Context<TConfig, TEnv, TCommand, TSupportedEvents>) => HandlerReturn, options?: Options): Promise<void>;
46
134
 
47
- interface CommentOptions {
48
- raw?: boolean;
49
- updateComment?: boolean;
50
- }
51
- type WithIssueNumber<T> = T & {
52
- issueNumber: number;
53
- };
54
- type PostComment = {
55
- (context: Context, message: LogReturn | Error, options?: CommentOptions): Promise<WithIssueNumber<RestEndpointMethodTypes["issues"]["updateComment"]["response"]["data"] | RestEndpointMethodTypes["issues"]["createComment"]["response"]["data"]> | null>;
56
- lastCommentId?: number;
57
- };
58
- /**
59
- * Posts a comment on a GitHub issue if the issue exists in the context payload, embedding structured metadata to it.
60
- */
61
- declare const postComment: PostComment;
62
-
63
- export { type Context, createActionsPlugin, createPlugin, postComment };
135
+ export { CommentHandler, type Context, createActionsPlugin, createPlugin };
package/dist/index.js CHANGED
@@ -30,15 +30,15 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
30
30
  // src/index.ts
31
31
  var src_exports = {};
32
32
  __export(src_exports, {
33
+ CommentHandler: () => CommentHandler,
33
34
  createActionsPlugin: () => createActionsPlugin,
34
- createPlugin: () => createPlugin,
35
- postComment: () => postComment
35
+ createPlugin: () => createPlugin
36
36
  });
37
37
  module.exports = __toCommonJS(src_exports);
38
38
 
39
39
  // src/server.ts
40
40
  var import_value2 = require("@sinclair/typebox/value");
41
- var import_ubiquity_os_logger2 = require("@ubiquity-os/ubiquity-os-logger");
41
+ var import_ubiquity_os_logger3 = require("@ubiquity-os/ubiquity-os-logger");
42
42
  var import_hono = require("hono");
43
43
  var import_adapter2 = require("hono/adapter");
44
44
  var import_http_exception = require("hono/http-exception");
@@ -116,89 +116,168 @@ function getPluginOptions(options) {
116
116
  }
117
117
 
118
118
  // src/comment.ts
119
- var HEADER_NAME = "UbiquityOS";
120
- var postComment = async function(context2, message, options = { updateComment: true, raw: false }) {
121
- let issueNumber;
122
- if ("issue" in context2.payload) {
123
- issueNumber = context2.payload.issue.number;
124
- } else if ("pull_request" in context2.payload) {
125
- issueNumber = context2.payload.pull_request.number;
126
- } else if ("discussion" in context2.payload) {
127
- issueNumber = context2.payload.discussion.number;
128
- } else {
129
- context2.logger.info("Cannot post comment because issue is not found in the payload.");
130
- return null;
119
+ var CommentHandler = class _CommentHandler {
120
+ static HEADER_NAME = "UbiquityOS";
121
+ _lastCommentId = { reviewCommentId: null, issueCommentId: null };
122
+ async _updateIssueComment(context2, params) {
123
+ if (!this._lastCommentId.issueCommentId) {
124
+ throw context2.logger.error("issueCommentId is missing");
125
+ }
126
+ const commentData = await context2.octokit.rest.issues.updateComment({
127
+ owner: params.owner,
128
+ repo: params.repo,
129
+ comment_id: this._lastCommentId.issueCommentId,
130
+ body: params.body
131
+ });
132
+ return { ...commentData.data, issueNumber: params.issueNumber };
131
133
  }
132
- if ("repository" in context2.payload && context2.payload.repository?.owner?.login) {
133
- const body = await createStructuredMetadataWithMessage(context2, message, options);
134
- if (options.updateComment && postComment.lastCommentId) {
135
- const commentData = await context2.octokit.rest.issues.updateComment({
136
- owner: context2.payload.repository.owner.login,
137
- repo: context2.payload.repository.name,
138
- comment_id: postComment.lastCommentId,
139
- body
140
- });
141
- return { ...commentData.data, issueNumber };
142
- } else {
143
- const commentData = await context2.octokit.rest.issues.createComment({
144
- owner: context2.payload.repository.owner.login,
145
- repo: context2.payload.repository.name,
146
- issue_number: issueNumber,
147
- body
134
+ async _updateReviewComment(context2, params) {
135
+ if (!this._lastCommentId.reviewCommentId) {
136
+ throw context2.logger.error("reviewCommentId is missing");
137
+ }
138
+ const commentData = await context2.octokit.rest.pulls.updateReviewComment({
139
+ owner: params.owner,
140
+ repo: params.repo,
141
+ comment_id: this._lastCommentId.reviewCommentId,
142
+ body: params.body
143
+ });
144
+ return { ...commentData.data, issueNumber: params.issueNumber };
145
+ }
146
+ async _createNewComment(context2, params) {
147
+ if (params.commentId) {
148
+ const commentData2 = await context2.octokit.rest.pulls.createReplyForReviewComment({
149
+ owner: params.owner,
150
+ repo: params.repo,
151
+ pull_number: params.issueNumber,
152
+ comment_id: params.commentId,
153
+ body: params.body
148
154
  });
149
- postComment.lastCommentId = commentData.data.id;
150
- return { ...commentData.data, issueNumber };
155
+ this._lastCommentId.reviewCommentId = commentData2.data.id;
156
+ return { ...commentData2.data, issueNumber: params.issueNumber };
151
157
  }
152
- } else {
153
- context2.logger.info("Cannot post comment because repository is not found in the payload.", { payload: context2.payload });
158
+ const commentData = await context2.octokit.rest.issues.createComment({
159
+ owner: params.owner,
160
+ repo: params.repo,
161
+ issue_number: params.issueNumber,
162
+ body: params.body
163
+ });
164
+ this._lastCommentId.issueCommentId = commentData.data.id;
165
+ return { ...commentData.data, issueNumber: params.issueNumber };
154
166
  }
155
- return null;
156
- };
157
- async function createStructuredMetadataWithMessage(context2, message, options) {
158
- let logMessage;
159
- let callingFnName;
160
- let instigatorName;
161
- let metadata;
162
- if (message instanceof Error) {
163
- metadata = {
164
- message: message.message,
165
- name: message.name,
166
- stack: message.stack
167
+ _getIssueNumber(context2) {
168
+ if ("issue" in context2.payload) return context2.payload.issue.number;
169
+ if ("pull_request" in context2.payload) return context2.payload.pull_request.number;
170
+ if ("discussion" in context2.payload) return context2.payload.discussion.number;
171
+ return void 0;
172
+ }
173
+ _getCommentId(context2) {
174
+ return "pull_request" in context2.payload && "comment" in context2.payload ? context2.payload.comment.id : void 0;
175
+ }
176
+ _extractIssueContext(context2) {
177
+ if (!("repository" in context2.payload) || !context2.payload.repository?.owner?.login) {
178
+ return null;
179
+ }
180
+ const issueNumber = this._getIssueNumber(context2);
181
+ if (!issueNumber) return null;
182
+ return {
183
+ issueNumber,
184
+ commentId: this._getCommentId(context2),
185
+ owner: context2.payload.repository.owner.login,
186
+ repo: context2.payload.repository.name
167
187
  };
168
- callingFnName = message.stack?.split("\n")[2]?.match(/at (\S+)/)?.[1] ?? "anonymous";
169
- logMessage = context2.logger.error(message.message).logMessage;
170
- } else if (message.metadata) {
171
- metadata = {
188
+ }
189
+ async _processMessage(context2, message) {
190
+ if (message instanceof Error) {
191
+ const metadata2 = {
192
+ message: message.message,
193
+ name: message.name,
194
+ stack: message.stack
195
+ };
196
+ return { metadata: metadata2, logMessage: context2.logger.error(message.message).logMessage };
197
+ }
198
+ const metadata = message.metadata ? {
199
+ ...message.metadata,
172
200
  message: message.metadata.message,
173
201
  stack: message.metadata.stack || message.metadata.error?.stack,
174
202
  caller: message.metadata.caller || message.metadata.error?.stack?.split("\n")[2]?.match(/at (\S+)/)?.[1]
175
- };
176
- logMessage = message.logMessage;
177
- callingFnName = metadata.caller;
178
- } else {
179
- metadata = { ...message };
203
+ } : { ...message };
204
+ return { metadata, logMessage: message.logMessage };
180
205
  }
181
- const jsonPretty = sanitizeMetadata(metadata);
182
- if ("installation" in context2.payload && context2.payload.installation && "account" in context2.payload.installation) {
183
- instigatorName = context2.payload.installation?.account?.name;
184
- } else {
185
- instigatorName = context2.payload.sender?.login || HEADER_NAME;
206
+ _getInstigatorName(context2) {
207
+ if ("installation" in context2.payload && context2.payload.installation && "account" in context2.payload.installation && context2.payload.installation?.account?.name) {
208
+ return context2.payload.installation?.account?.name;
209
+ }
210
+ return context2.payload.sender?.login || _CommentHandler.HEADER_NAME;
186
211
  }
187
- const runUrl = PluginRuntimeInfo.getInstance().runUrl;
188
- const version = await PluginRuntimeInfo.getInstance().version;
189
- const ubiquityMetadataHeader = `<!-- ${HEADER_NAME} - ${callingFnName} - ${version} - @${instigatorName} - ${runUrl}`;
190
- let metadataSerialized;
191
- const metadataSerializedVisible = ["```json", jsonPretty, "```"].join("\n");
192
- const metadataSerializedHidden = [ubiquityMetadataHeader, jsonPretty, "-->"].join("\n");
193
- if (logMessage?.type === "fatal") {
194
- metadataSerialized = [metadataSerializedVisible, metadataSerializedHidden].join("\n");
195
- } else {
196
- metadataSerialized = metadataSerializedHidden;
212
+ async _createMetadataContent(context2, metadata) {
213
+ const jsonPretty = sanitizeMetadata(metadata);
214
+ const instigatorName = this._getInstigatorName(context2);
215
+ const runUrl = PluginRuntimeInfo.getInstance().runUrl;
216
+ const version = await PluginRuntimeInfo.getInstance().version;
217
+ const callingFnName = metadata.caller || "anonymous";
218
+ return {
219
+ header: `<!-- ${_CommentHandler.HEADER_NAME} - ${callingFnName} - ${version} - @${instigatorName} - ${runUrl}`,
220
+ jsonPretty
221
+ };
222
+ }
223
+ _formatMetadataContent(logMessage, header, jsonPretty) {
224
+ const metadataVisible = ["```json", jsonPretty, "```"].join("\n");
225
+ const metadataHidden = [header, jsonPretty, "-->"].join("\n");
226
+ return logMessage?.type === "fatal" ? [metadataVisible, metadataHidden].join("\n") : metadataHidden;
197
227
  }
198
- return `${options.raw ? logMessage?.raw : logMessage?.diff}
228
+ async _createCommentBody(context2, message, options) {
229
+ const { metadata, logMessage } = await this._processMessage(context2, message);
230
+ const { header, jsonPretty } = await this._createMetadataContent(context2, metadata);
231
+ const metadataContent = this._formatMetadataContent(logMessage, header, jsonPretty);
232
+ return `${options.raw ? logMessage?.raw : logMessage?.diff}
199
233
 
200
- ${metadataSerialized}
234
+ ${metadataContent}
201
235
  `;
236
+ }
237
+ async postComment(context2, message, options = { updateComment: true, raw: false }) {
238
+ const issueContext = this._extractIssueContext(context2);
239
+ if (!issueContext) {
240
+ context2.logger.info("Cannot post comment: missing issue context in payload");
241
+ return null;
242
+ }
243
+ const body = await this._createCommentBody(context2, message, options);
244
+ const { issueNumber, commentId, owner, repo } = issueContext;
245
+ const params = { owner, repo, body, issueNumber };
246
+ if (options.updateComment) {
247
+ if (this._lastCommentId.issueCommentId && !("pull_request" in context2.payload && "comment" in context2.payload)) {
248
+ return this._updateIssueComment(context2, params);
249
+ }
250
+ if (this._lastCommentId.reviewCommentId && "pull_request" in context2.payload && "comment" in context2.payload) {
251
+ return this._updateReviewComment(context2, params);
252
+ }
253
+ }
254
+ return this._createNewComment(context2, { ...params, commentId });
255
+ }
256
+ };
257
+
258
+ // src/error.ts
259
+ var import_ubiquity_os_logger2 = require("@ubiquity-os/ubiquity-os-logger");
260
+ function transformError(context2, error) {
261
+ let loggerError;
262
+ if (error instanceof AggregateError) {
263
+ loggerError = context2.logger.error(
264
+ error.errors.map((err) => {
265
+ if (err instanceof import_ubiquity_os_logger2.LogReturn) {
266
+ return err.logMessage.raw;
267
+ } else if (err instanceof Error) {
268
+ return err.message;
269
+ } else {
270
+ return err;
271
+ }
272
+ }).join("\n\n"),
273
+ { error }
274
+ );
275
+ } else if (error instanceof Error || error instanceof import_ubiquity_os_logger2.LogReturn) {
276
+ loggerError = error;
277
+ } else {
278
+ loggerError = context2.logger.error(String(error));
279
+ }
280
+ return loggerError;
202
281
  }
203
282
 
204
283
  // src/octokit.ts
@@ -297,7 +376,7 @@ function createPlugin(handler, manifest, options) {
297
376
  app.get("/manifest.json", (ctx) => {
298
377
  return ctx.json(manifest);
299
378
  });
300
- app.post("/", async (ctx) => {
379
+ app.post("/", async function appPost(ctx) {
301
380
  if (ctx.req.header("content-type") !== "application/json") {
302
381
  throw new import_http_exception.HTTPException(400, { message: "Content-Type must be application/json" });
303
382
  }
@@ -355,21 +434,17 @@ function createPlugin(handler, manifest, options) {
355
434
  octokit: new customOctokit({ auth: inputs.authToken }),
356
435
  config: config2,
357
436
  env,
358
- logger: new import_ubiquity_os_logger2.Logs(pluginOptions.logLevel)
437
+ logger: new import_ubiquity_os_logger3.Logs(pluginOptions.logLevel),
438
+ commentHandler: new CommentHandler()
359
439
  };
360
440
  try {
361
441
  const result = await handler(context2);
362
442
  return ctx.json({ stateId: inputs.stateId, output: result ?? {} });
363
443
  } catch (error) {
364
444
  console.error(error);
365
- let loggerError;
366
- if (error instanceof Error || error instanceof import_ubiquity_os_logger2.LogReturn) {
367
- loggerError = error;
368
- } else {
369
- loggerError = context2.logger.error(`Error: ${error}`);
370
- }
445
+ const loggerError = transformError(context2, error);
371
446
  if (pluginOptions.postCommentOnError && loggerError) {
372
- await postComment(context2, loggerError);
447
+ await context2.commentHandler.postComment(context2, loggerError);
373
448
  }
374
449
  throw new import_http_exception.HTTPException(500, { message: "Unexpected error" });
375
450
  }
@@ -381,7 +456,7 @@ function createPlugin(handler, manifest, options) {
381
456
  var core = __toESM(require("@actions/core"));
382
457
  var github2 = __toESM(require("@actions/github"));
383
458
  var import_value3 = require("@sinclair/typebox/value");
384
- var import_ubiquity_os_logger3 = require("@ubiquity-os/ubiquity-os-logger");
459
+ var import_ubiquity_os_logger4 = require("@ubiquity-os/ubiquity-os-logger");
385
460
  var import_dotenv = require("dotenv");
386
461
  (0, import_dotenv.config)();
387
462
  async function createActionsPlugin(handler, options) {
@@ -395,7 +470,7 @@ async function createActionsPlugin(handler, options) {
395
470
  const inputSchemaErrors = [...import_value3.Value.Errors(inputSchema, body)];
396
471
  if (inputSchemaErrors.length) {
397
472
  console.dir(inputSchemaErrors, { depth: null });
398
- core.setFailed(`Error: Invalid inputs payload: ${inputSchemaErrors.join(",")}`);
473
+ core.setFailed(`Error: Invalid inputs payload: ${inputSchemaErrors.map((o) => o.message).join(", ")}`);
399
474
  return;
400
475
  }
401
476
  const signature = body.signature;
@@ -410,6 +485,7 @@ async function createActionsPlugin(handler, options) {
410
485
  config2 = import_value3.Value.Decode(pluginOptions.settingsSchema, import_value3.Value.Default(pluginOptions.settingsSchema, inputs.settings));
411
486
  } catch (e) {
412
487
  console.dir(...import_value3.Value.Errors(pluginOptions.settingsSchema, inputs.settings), { depth: null });
488
+ core.setFailed(`Error: Invalid settings provided.`);
413
489
  throw e;
414
490
  }
415
491
  } else {
@@ -421,6 +497,7 @@ async function createActionsPlugin(handler, options) {
421
497
  env = import_value3.Value.Decode(pluginOptions.envSchema, import_value3.Value.Default(pluginOptions.envSchema, process.env));
422
498
  } catch (e) {
423
499
  console.dir(...import_value3.Value.Errors(pluginOptions.envSchema, process.env), { depth: null });
500
+ core.setFailed(`Error: Invalid environment provided.`);
424
501
  throw e;
425
502
  }
426
503
  } else {
@@ -444,7 +521,8 @@ async function createActionsPlugin(handler, options) {
444
521
  octokit: new customOctokit({ auth: inputs.authToken }),
445
522
  config: config2,
446
523
  env,
447
- logger: new import_ubiquity_os_logger3.Logs(pluginOptions.logLevel)
524
+ logger: new import_ubiquity_os_logger4.Logs(pluginOptions.logLevel),
525
+ commentHandler: new CommentHandler()
448
526
  };
449
527
  try {
450
528
  const result = await handler(context2);
@@ -452,19 +530,14 @@ async function createActionsPlugin(handler, options) {
452
530
  await returnDataToKernel(pluginGithubToken, inputs.stateId, result);
453
531
  } catch (error) {
454
532
  console.error(error);
455
- let loggerError;
456
- if (error instanceof Error) {
457
- core.setFailed(error);
458
- loggerError = context2.logger.error(`Error: ${error}`, { error });
459
- } else if (error instanceof import_ubiquity_os_logger3.LogReturn) {
460
- core.setFailed(error.logMessage.raw);
461
- loggerError = error;
462
- } else {
463
- core.setFailed(`Error: ${error}`);
464
- loggerError = context2.logger.error(`Error: ${error}`);
533
+ const loggerError = transformError(context2, error);
534
+ if (loggerError instanceof import_ubiquity_os_logger4.LogReturn) {
535
+ core.setFailed(loggerError.logMessage.diff);
536
+ } else if (loggerError instanceof Error) {
537
+ core.setFailed(loggerError);
465
538
  }
466
539
  if (pluginOptions.postCommentOnError && loggerError) {
467
- await postComment(context2, loggerError);
540
+ await context2.commentHandler.postComment(context2, loggerError);
468
541
  }
469
542
  }
470
543
  }
@@ -482,7 +555,7 @@ async function returnDataToKernel(repoToken, stateId, output) {
482
555
  }
483
556
  // Annotate the CommonJS export names for ESM import in node:
484
557
  0 && (module.exports = {
558
+ CommentHandler,
485
559
  createActionsPlugin,
486
- createPlugin,
487
- postComment
560
+ createPlugin
488
561
  });
package/dist/index.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  // src/server.ts
2
2
  import { Value as Value2 } from "@sinclair/typebox/value";
3
- import { LogReturn as LogReturn2, Logs } from "@ubiquity-os/ubiquity-os-logger";
3
+ import { Logs } from "@ubiquity-os/ubiquity-os-logger";
4
4
  import { Hono } from "hono";
5
5
  import { env as honoEnv } from "hono/adapter";
6
6
  import { HTTPException } from "hono/http-exception";
@@ -78,89 +78,168 @@ function getPluginOptions(options) {
78
78
  }
79
79
 
80
80
  // src/comment.ts
81
- var HEADER_NAME = "UbiquityOS";
82
- var postComment = async function(context2, message, options = { updateComment: true, raw: false }) {
83
- let issueNumber;
84
- if ("issue" in context2.payload) {
85
- issueNumber = context2.payload.issue.number;
86
- } else if ("pull_request" in context2.payload) {
87
- issueNumber = context2.payload.pull_request.number;
88
- } else if ("discussion" in context2.payload) {
89
- issueNumber = context2.payload.discussion.number;
90
- } else {
91
- context2.logger.info("Cannot post comment because issue is not found in the payload.");
92
- return null;
81
+ var CommentHandler = class _CommentHandler {
82
+ static HEADER_NAME = "UbiquityOS";
83
+ _lastCommentId = { reviewCommentId: null, issueCommentId: null };
84
+ async _updateIssueComment(context2, params) {
85
+ if (!this._lastCommentId.issueCommentId) {
86
+ throw context2.logger.error("issueCommentId is missing");
87
+ }
88
+ const commentData = await context2.octokit.rest.issues.updateComment({
89
+ owner: params.owner,
90
+ repo: params.repo,
91
+ comment_id: this._lastCommentId.issueCommentId,
92
+ body: params.body
93
+ });
94
+ return { ...commentData.data, issueNumber: params.issueNumber };
93
95
  }
94
- if ("repository" in context2.payload && context2.payload.repository?.owner?.login) {
95
- const body = await createStructuredMetadataWithMessage(context2, message, options);
96
- if (options.updateComment && postComment.lastCommentId) {
97
- const commentData = await context2.octokit.rest.issues.updateComment({
98
- owner: context2.payload.repository.owner.login,
99
- repo: context2.payload.repository.name,
100
- comment_id: postComment.lastCommentId,
101
- body
102
- });
103
- return { ...commentData.data, issueNumber };
104
- } else {
105
- const commentData = await context2.octokit.rest.issues.createComment({
106
- owner: context2.payload.repository.owner.login,
107
- repo: context2.payload.repository.name,
108
- issue_number: issueNumber,
109
- body
96
+ async _updateReviewComment(context2, params) {
97
+ if (!this._lastCommentId.reviewCommentId) {
98
+ throw context2.logger.error("reviewCommentId is missing");
99
+ }
100
+ const commentData = await context2.octokit.rest.pulls.updateReviewComment({
101
+ owner: params.owner,
102
+ repo: params.repo,
103
+ comment_id: this._lastCommentId.reviewCommentId,
104
+ body: params.body
105
+ });
106
+ return { ...commentData.data, issueNumber: params.issueNumber };
107
+ }
108
+ async _createNewComment(context2, params) {
109
+ if (params.commentId) {
110
+ const commentData2 = await context2.octokit.rest.pulls.createReplyForReviewComment({
111
+ owner: params.owner,
112
+ repo: params.repo,
113
+ pull_number: params.issueNumber,
114
+ comment_id: params.commentId,
115
+ body: params.body
110
116
  });
111
- postComment.lastCommentId = commentData.data.id;
112
- return { ...commentData.data, issueNumber };
117
+ this._lastCommentId.reviewCommentId = commentData2.data.id;
118
+ return { ...commentData2.data, issueNumber: params.issueNumber };
113
119
  }
114
- } else {
115
- context2.logger.info("Cannot post comment because repository is not found in the payload.", { payload: context2.payload });
120
+ const commentData = await context2.octokit.rest.issues.createComment({
121
+ owner: params.owner,
122
+ repo: params.repo,
123
+ issue_number: params.issueNumber,
124
+ body: params.body
125
+ });
126
+ this._lastCommentId.issueCommentId = commentData.data.id;
127
+ return { ...commentData.data, issueNumber: params.issueNumber };
116
128
  }
117
- return null;
118
- };
119
- async function createStructuredMetadataWithMessage(context2, message, options) {
120
- let logMessage;
121
- let callingFnName;
122
- let instigatorName;
123
- let metadata;
124
- if (message instanceof Error) {
125
- metadata = {
126
- message: message.message,
127
- name: message.name,
128
- stack: message.stack
129
+ _getIssueNumber(context2) {
130
+ if ("issue" in context2.payload) return context2.payload.issue.number;
131
+ if ("pull_request" in context2.payload) return context2.payload.pull_request.number;
132
+ if ("discussion" in context2.payload) return context2.payload.discussion.number;
133
+ return void 0;
134
+ }
135
+ _getCommentId(context2) {
136
+ return "pull_request" in context2.payload && "comment" in context2.payload ? context2.payload.comment.id : void 0;
137
+ }
138
+ _extractIssueContext(context2) {
139
+ if (!("repository" in context2.payload) || !context2.payload.repository?.owner?.login) {
140
+ return null;
141
+ }
142
+ const issueNumber = this._getIssueNumber(context2);
143
+ if (!issueNumber) return null;
144
+ return {
145
+ issueNumber,
146
+ commentId: this._getCommentId(context2),
147
+ owner: context2.payload.repository.owner.login,
148
+ repo: context2.payload.repository.name
129
149
  };
130
- callingFnName = message.stack?.split("\n")[2]?.match(/at (\S+)/)?.[1] ?? "anonymous";
131
- logMessage = context2.logger.error(message.message).logMessage;
132
- } else if (message.metadata) {
133
- metadata = {
150
+ }
151
+ async _processMessage(context2, message) {
152
+ if (message instanceof Error) {
153
+ const metadata2 = {
154
+ message: message.message,
155
+ name: message.name,
156
+ stack: message.stack
157
+ };
158
+ return { metadata: metadata2, logMessage: context2.logger.error(message.message).logMessage };
159
+ }
160
+ const metadata = message.metadata ? {
161
+ ...message.metadata,
134
162
  message: message.metadata.message,
135
163
  stack: message.metadata.stack || message.metadata.error?.stack,
136
164
  caller: message.metadata.caller || message.metadata.error?.stack?.split("\n")[2]?.match(/at (\S+)/)?.[1]
137
- };
138
- logMessage = message.logMessage;
139
- callingFnName = metadata.caller;
140
- } else {
141
- metadata = { ...message };
165
+ } : { ...message };
166
+ return { metadata, logMessage: message.logMessage };
142
167
  }
143
- const jsonPretty = sanitizeMetadata(metadata);
144
- if ("installation" in context2.payload && context2.payload.installation && "account" in context2.payload.installation) {
145
- instigatorName = context2.payload.installation?.account?.name;
146
- } else {
147
- instigatorName = context2.payload.sender?.login || HEADER_NAME;
168
+ _getInstigatorName(context2) {
169
+ if ("installation" in context2.payload && context2.payload.installation && "account" in context2.payload.installation && context2.payload.installation?.account?.name) {
170
+ return context2.payload.installation?.account?.name;
171
+ }
172
+ return context2.payload.sender?.login || _CommentHandler.HEADER_NAME;
148
173
  }
149
- const runUrl = PluginRuntimeInfo.getInstance().runUrl;
150
- const version = await PluginRuntimeInfo.getInstance().version;
151
- const ubiquityMetadataHeader = `<!-- ${HEADER_NAME} - ${callingFnName} - ${version} - @${instigatorName} - ${runUrl}`;
152
- let metadataSerialized;
153
- const metadataSerializedVisible = ["```json", jsonPretty, "```"].join("\n");
154
- const metadataSerializedHidden = [ubiquityMetadataHeader, jsonPretty, "-->"].join("\n");
155
- if (logMessage?.type === "fatal") {
156
- metadataSerialized = [metadataSerializedVisible, metadataSerializedHidden].join("\n");
157
- } else {
158
- metadataSerialized = metadataSerializedHidden;
174
+ async _createMetadataContent(context2, metadata) {
175
+ const jsonPretty = sanitizeMetadata(metadata);
176
+ const instigatorName = this._getInstigatorName(context2);
177
+ const runUrl = PluginRuntimeInfo.getInstance().runUrl;
178
+ const version = await PluginRuntimeInfo.getInstance().version;
179
+ const callingFnName = metadata.caller || "anonymous";
180
+ return {
181
+ header: `<!-- ${_CommentHandler.HEADER_NAME} - ${callingFnName} - ${version} - @${instigatorName} - ${runUrl}`,
182
+ jsonPretty
183
+ };
159
184
  }
160
- return `${options.raw ? logMessage?.raw : logMessage?.diff}
185
+ _formatMetadataContent(logMessage, header, jsonPretty) {
186
+ const metadataVisible = ["```json", jsonPretty, "```"].join("\n");
187
+ const metadataHidden = [header, jsonPretty, "-->"].join("\n");
188
+ return logMessage?.type === "fatal" ? [metadataVisible, metadataHidden].join("\n") : metadataHidden;
189
+ }
190
+ async _createCommentBody(context2, message, options) {
191
+ const { metadata, logMessage } = await this._processMessage(context2, message);
192
+ const { header, jsonPretty } = await this._createMetadataContent(context2, metadata);
193
+ const metadataContent = this._formatMetadataContent(logMessage, header, jsonPretty);
194
+ return `${options.raw ? logMessage?.raw : logMessage?.diff}
161
195
 
162
- ${metadataSerialized}
196
+ ${metadataContent}
163
197
  `;
198
+ }
199
+ async postComment(context2, message, options = { updateComment: true, raw: false }) {
200
+ const issueContext = this._extractIssueContext(context2);
201
+ if (!issueContext) {
202
+ context2.logger.info("Cannot post comment: missing issue context in payload");
203
+ return null;
204
+ }
205
+ const body = await this._createCommentBody(context2, message, options);
206
+ const { issueNumber, commentId, owner, repo } = issueContext;
207
+ const params = { owner, repo, body, issueNumber };
208
+ if (options.updateComment) {
209
+ if (this._lastCommentId.issueCommentId && !("pull_request" in context2.payload && "comment" in context2.payload)) {
210
+ return this._updateIssueComment(context2, params);
211
+ }
212
+ if (this._lastCommentId.reviewCommentId && "pull_request" in context2.payload && "comment" in context2.payload) {
213
+ return this._updateReviewComment(context2, params);
214
+ }
215
+ }
216
+ return this._createNewComment(context2, { ...params, commentId });
217
+ }
218
+ };
219
+
220
+ // src/error.ts
221
+ import { LogReturn as LogReturn2 } from "@ubiquity-os/ubiquity-os-logger";
222
+ function transformError(context2, error) {
223
+ let loggerError;
224
+ if (error instanceof AggregateError) {
225
+ loggerError = context2.logger.error(
226
+ error.errors.map((err) => {
227
+ if (err instanceof LogReturn2) {
228
+ return err.logMessage.raw;
229
+ } else if (err instanceof Error) {
230
+ return err.message;
231
+ } else {
232
+ return err;
233
+ }
234
+ }).join("\n\n"),
235
+ { error }
236
+ );
237
+ } else if (error instanceof Error || error instanceof LogReturn2) {
238
+ loggerError = error;
239
+ } else {
240
+ loggerError = context2.logger.error(String(error));
241
+ }
242
+ return loggerError;
164
243
  }
165
244
 
166
245
  // src/octokit.ts
@@ -259,7 +338,7 @@ function createPlugin(handler, manifest, options) {
259
338
  app.get("/manifest.json", (ctx) => {
260
339
  return ctx.json(manifest);
261
340
  });
262
- app.post("/", async (ctx) => {
341
+ app.post("/", async function appPost(ctx) {
263
342
  if (ctx.req.header("content-type") !== "application/json") {
264
343
  throw new HTTPException(400, { message: "Content-Type must be application/json" });
265
344
  }
@@ -317,21 +396,17 @@ function createPlugin(handler, manifest, options) {
317
396
  octokit: new customOctokit({ auth: inputs.authToken }),
318
397
  config: config2,
319
398
  env,
320
- logger: new Logs(pluginOptions.logLevel)
399
+ logger: new Logs(pluginOptions.logLevel),
400
+ commentHandler: new CommentHandler()
321
401
  };
322
402
  try {
323
403
  const result = await handler(context2);
324
404
  return ctx.json({ stateId: inputs.stateId, output: result ?? {} });
325
405
  } catch (error) {
326
406
  console.error(error);
327
- let loggerError;
328
- if (error instanceof Error || error instanceof LogReturn2) {
329
- loggerError = error;
330
- } else {
331
- loggerError = context2.logger.error(`Error: ${error}`);
332
- }
407
+ const loggerError = transformError(context2, error);
333
408
  if (pluginOptions.postCommentOnError && loggerError) {
334
- await postComment(context2, loggerError);
409
+ await context2.commentHandler.postComment(context2, loggerError);
335
410
  }
336
411
  throw new HTTPException(500, { message: "Unexpected error" });
337
412
  }
@@ -357,7 +432,7 @@ async function createActionsPlugin(handler, options) {
357
432
  const inputSchemaErrors = [...Value3.Errors(inputSchema, body)];
358
433
  if (inputSchemaErrors.length) {
359
434
  console.dir(inputSchemaErrors, { depth: null });
360
- core.setFailed(`Error: Invalid inputs payload: ${inputSchemaErrors.join(",")}`);
435
+ core.setFailed(`Error: Invalid inputs payload: ${inputSchemaErrors.map((o) => o.message).join(", ")}`);
361
436
  return;
362
437
  }
363
438
  const signature = body.signature;
@@ -372,6 +447,7 @@ async function createActionsPlugin(handler, options) {
372
447
  config2 = Value3.Decode(pluginOptions.settingsSchema, Value3.Default(pluginOptions.settingsSchema, inputs.settings));
373
448
  } catch (e) {
374
449
  console.dir(...Value3.Errors(pluginOptions.settingsSchema, inputs.settings), { depth: null });
450
+ core.setFailed(`Error: Invalid settings provided.`);
375
451
  throw e;
376
452
  }
377
453
  } else {
@@ -383,6 +459,7 @@ async function createActionsPlugin(handler, options) {
383
459
  env = Value3.Decode(pluginOptions.envSchema, Value3.Default(pluginOptions.envSchema, process.env));
384
460
  } catch (e) {
385
461
  console.dir(...Value3.Errors(pluginOptions.envSchema, process.env), { depth: null });
462
+ core.setFailed(`Error: Invalid environment provided.`);
386
463
  throw e;
387
464
  }
388
465
  } else {
@@ -406,7 +483,8 @@ async function createActionsPlugin(handler, options) {
406
483
  octokit: new customOctokit({ auth: inputs.authToken }),
407
484
  config: config2,
408
485
  env,
409
- logger: new Logs2(pluginOptions.logLevel)
486
+ logger: new Logs2(pluginOptions.logLevel),
487
+ commentHandler: new CommentHandler()
410
488
  };
411
489
  try {
412
490
  const result = await handler(context2);
@@ -414,19 +492,14 @@ async function createActionsPlugin(handler, options) {
414
492
  await returnDataToKernel(pluginGithubToken, inputs.stateId, result);
415
493
  } catch (error) {
416
494
  console.error(error);
417
- let loggerError;
418
- if (error instanceof Error) {
419
- core.setFailed(error);
420
- loggerError = context2.logger.error(`Error: ${error}`, { error });
421
- } else if (error instanceof LogReturn3) {
422
- core.setFailed(error.logMessage.raw);
423
- loggerError = error;
424
- } else {
425
- core.setFailed(`Error: ${error}`);
426
- loggerError = context2.logger.error(`Error: ${error}`);
495
+ const loggerError = transformError(context2, error);
496
+ if (loggerError instanceof LogReturn3) {
497
+ core.setFailed(loggerError.logMessage.diff);
498
+ } else if (loggerError instanceof Error) {
499
+ core.setFailed(loggerError);
427
500
  }
428
501
  if (pluginOptions.postCommentOnError && loggerError) {
429
- await postComment(context2, loggerError);
502
+ await context2.commentHandler.postComment(context2, loggerError);
430
503
  }
431
504
  }
432
505
  }
@@ -443,7 +516,7 @@ async function returnDataToKernel(repoToken, stateId, output) {
443
516
  });
444
517
  }
445
518
  export {
519
+ CommentHandler,
446
520
  createActionsPlugin,
447
- createPlugin,
448
- postComment
521
+ createPlugin
449
522
  };
@@ -1,3 +1,34 @@
1
+ import { EmitterWebhookEventName, EmitterWebhookEvent } from '@octokit/webhooks';
2
+ import * as _sinclair_typebox from '@sinclair/typebox';
3
+ import { StaticDecode } from '@sinclair/typebox';
4
+
5
+ declare const commandCallSchema: _sinclair_typebox.TUnion<[_sinclair_typebox.TNull, _sinclair_typebox.TObject<{
6
+ name: _sinclair_typebox.TString;
7
+ parameters: _sinclair_typebox.TUnknown;
8
+ }>]>;
9
+ type CommandCall = StaticDecode<typeof commandCallSchema>;
10
+
11
+ declare class PluginInput<T extends EmitterWebhookEventName = EmitterWebhookEventName> {
12
+ private _privateKey;
13
+ stateId: string;
14
+ eventName: T;
15
+ eventPayload: EmitterWebhookEvent<T>["payload"];
16
+ settings: unknown;
17
+ authToken: string;
18
+ ref: string;
19
+ command: CommandCall;
20
+ constructor(privateKey: string, stateId: string, eventName: T, eventPayload: EmitterWebhookEvent<T>["payload"], settings: unknown, authToken: string, ref: string, command: CommandCall);
21
+ getInputs(): Promise<{
22
+ signature: string;
23
+ stateId: string;
24
+ eventName: T;
25
+ eventPayload: string;
26
+ settings: string;
27
+ authToken: string;
28
+ ref: string;
29
+ command: string;
30
+ }>;
31
+ }
1
32
  interface Inputs {
2
33
  stateId: unknown;
3
34
  eventName: unknown;
@@ -10,4 +41,4 @@ interface Inputs {
10
41
  declare function verifySignature(publicKeyPem: string, inputs: Inputs, signature: string): Promise<boolean>;
11
42
  declare function signPayload(payload: string, privateKey: string): Promise<string>;
12
43
 
13
- export { signPayload, verifySignature };
44
+ export { PluginInput, signPayload, verifySignature };
@@ -1,3 +1,34 @@
1
+ import { EmitterWebhookEventName, EmitterWebhookEvent } from '@octokit/webhooks';
2
+ import * as _sinclair_typebox from '@sinclair/typebox';
3
+ import { StaticDecode } from '@sinclair/typebox';
4
+
5
+ declare const commandCallSchema: _sinclair_typebox.TUnion<[_sinclair_typebox.TNull, _sinclair_typebox.TObject<{
6
+ name: _sinclair_typebox.TString;
7
+ parameters: _sinclair_typebox.TUnknown;
8
+ }>]>;
9
+ type CommandCall = StaticDecode<typeof commandCallSchema>;
10
+
11
+ declare class PluginInput<T extends EmitterWebhookEventName = EmitterWebhookEventName> {
12
+ private _privateKey;
13
+ stateId: string;
14
+ eventName: T;
15
+ eventPayload: EmitterWebhookEvent<T>["payload"];
16
+ settings: unknown;
17
+ authToken: string;
18
+ ref: string;
19
+ command: CommandCall;
20
+ constructor(privateKey: string, stateId: string, eventName: T, eventPayload: EmitterWebhookEvent<T>["payload"], settings: unknown, authToken: string, ref: string, command: CommandCall);
21
+ getInputs(): Promise<{
22
+ signature: string;
23
+ stateId: string;
24
+ eventName: T;
25
+ eventPayload: string;
26
+ settings: string;
27
+ authToken: string;
28
+ ref: string;
29
+ command: string;
30
+ }>;
31
+ }
1
32
  interface Inputs {
2
33
  stateId: unknown;
3
34
  eventName: unknown;
@@ -10,4 +41,4 @@ interface Inputs {
10
41
  declare function verifySignature(publicKeyPem: string, inputs: Inputs, signature: string): Promise<boolean>;
11
42
  declare function signPayload(payload: string, privateKey: string): Promise<string>;
12
43
 
13
- export { signPayload, verifySignature };
44
+ export { PluginInput, signPayload, verifySignature };
package/dist/signature.js CHANGED
@@ -20,10 +20,47 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/signature.ts
21
21
  var signature_exports = {};
22
22
  __export(signature_exports, {
23
+ PluginInput: () => PluginInput,
23
24
  signPayload: () => signPayload,
24
25
  verifySignature: () => verifySignature
25
26
  });
26
27
  module.exports = __toCommonJS(signature_exports);
28
+ var PluginInput = class {
29
+ _privateKey;
30
+ stateId;
31
+ eventName;
32
+ eventPayload;
33
+ settings;
34
+ authToken;
35
+ ref;
36
+ command;
37
+ constructor(privateKey, stateId, eventName, eventPayload, settings, authToken, ref, command) {
38
+ this._privateKey = privateKey;
39
+ this.stateId = stateId;
40
+ this.eventName = eventName;
41
+ this.eventPayload = eventPayload;
42
+ this.settings = settings;
43
+ this.authToken = authToken;
44
+ this.ref = ref;
45
+ this.command = command;
46
+ }
47
+ async getInputs() {
48
+ const inputs = {
49
+ stateId: this.stateId,
50
+ eventName: this.eventName,
51
+ eventPayload: JSON.stringify(this.eventPayload),
52
+ settings: JSON.stringify(this.settings),
53
+ authToken: this.authToken,
54
+ ref: this.ref,
55
+ command: JSON.stringify(this.command)
56
+ };
57
+ const signature = await signPayload(JSON.stringify(inputs), this._privateKey);
58
+ return {
59
+ ...inputs,
60
+ signature
61
+ };
62
+ }
63
+ };
27
64
  async function verifySignature(publicKeyPem, inputs, signature) {
28
65
  try {
29
66
  const inputsOrdered = {
@@ -77,6 +114,7 @@ async function signPayload(payload, privateKey) {
77
114
  }
78
115
  // Annotate the CommonJS export names for ESM import in node:
79
116
  0 && (module.exports = {
117
+ PluginInput,
80
118
  signPayload,
81
119
  verifySignature
82
120
  });
@@ -1,4 +1,40 @@
1
1
  // src/signature.ts
2
+ var PluginInput = class {
3
+ _privateKey;
4
+ stateId;
5
+ eventName;
6
+ eventPayload;
7
+ settings;
8
+ authToken;
9
+ ref;
10
+ command;
11
+ constructor(privateKey, stateId, eventName, eventPayload, settings, authToken, ref, command) {
12
+ this._privateKey = privateKey;
13
+ this.stateId = stateId;
14
+ this.eventName = eventName;
15
+ this.eventPayload = eventPayload;
16
+ this.settings = settings;
17
+ this.authToken = authToken;
18
+ this.ref = ref;
19
+ this.command = command;
20
+ }
21
+ async getInputs() {
22
+ const inputs = {
23
+ stateId: this.stateId,
24
+ eventName: this.eventName,
25
+ eventPayload: JSON.stringify(this.eventPayload),
26
+ settings: JSON.stringify(this.settings),
27
+ authToken: this.authToken,
28
+ ref: this.ref,
29
+ command: JSON.stringify(this.command)
30
+ };
31
+ const signature = await signPayload(JSON.stringify(inputs), this._privateKey);
32
+ return {
33
+ ...inputs,
34
+ signature
35
+ };
36
+ }
37
+ };
2
38
  async function verifySignature(publicKeyPem, inputs, signature) {
3
39
  try {
4
40
  const inputsOrdered = {
@@ -51,6 +87,7 @@ async function signPayload(payload, privateKey) {
51
87
  return btoa(String.fromCharCode(...new Uint8Array(signature)));
52
88
  }
53
89
  export {
90
+ PluginInput,
54
91
  signPayload,
55
92
  verifySignature
56
93
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ubiquity-os/plugin-sdk",
3
- "version": "2.0.6",
3
+ "version": "3.1.0",
4
4
  "description": "SDK for plugin support.",
5
5
  "author": "Ubiquity DAO",
6
6
  "license": "MIT",