@forge/realtime 0.0.7-next.0 → 0.1.0-experimental-3f68b81
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/CHANGELOG.md +30 -0
- package/out/__test__/publish.test.js +81 -18
- package/out/__test__/signRealtimeToken.test.d.ts +2 -0
- package/out/__test__/signRealtimeToken.test.d.ts.map +1 -0
- package/out/__test__/signRealtimeToken.test.js +80 -0
- package/out/__test__/utils.d.ts.map +1 -1
- package/out/__test__/utils.js +22 -1
- package/out/index.d.ts +1 -0
- package/out/index.d.ts.map +1 -1
- package/out/index.js +3 -1
- package/out/publish.d.ts +22 -4
- package/out/publish.d.ts.map +1 -1
- package/out/publish.js +66 -22
- package/out/signRealtimeToken.d.ts +10 -0
- package/out/signRealtimeToken.d.ts.map +1 -0
- package/out/signRealtimeToken.js +78 -0
- package/out/utils.d.ts +3 -0
- package/out/utils.d.ts.map +1 -0
- package/out/utils.js +13 -0
- package/package.json +2 -2
- package/src/__test__/__snapshots__/publish.test.ts.snap +51 -6
- package/src/__test__/__snapshots__/signRealtimeToken.test.ts.snap +58 -0
- package/src/__test__/publish.test.ts +95 -19
- package/src/__test__/signRealtimeToken.test.ts +96 -0
- package/src/__test__/utils.ts +22 -1
- package/src/index.ts +1 -0
- package/src/publish.ts +74 -18
- package/src/signRealtimeToken.ts +90 -0
- package/src/utils.ts +12 -0
- package/tsconfig.tsbuildinfo +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,35 @@
|
|
|
1
1
|
# @forge/realtime
|
|
2
2
|
|
|
3
|
+
## 0.1.0-experimental-3f68b81
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- fe2852a: Added backend SDK for permission handling
|
|
8
|
+
- 7b7e598: Rename jwt to token in signRealtimeToken output
|
|
9
|
+
|
|
10
|
+
## 0.1.0
|
|
11
|
+
|
|
12
|
+
### Minor Changes
|
|
13
|
+
|
|
14
|
+
- 4242274: Adds new signRealtimeToken method to the forge realtime package
|
|
15
|
+
|
|
16
|
+
### Patch Changes
|
|
17
|
+
|
|
18
|
+
- 32da8c1: Update realtime package publish and publishGlobal to accept new token variable
|
|
19
|
+
- 1bf4466: Updates realtime package publish methods to use the new isGlobal field
|
|
20
|
+
|
|
21
|
+
## 0.1.0-next.2
|
|
22
|
+
|
|
23
|
+
### Patch Changes
|
|
24
|
+
|
|
25
|
+
- 32da8c1: Update realtime package publish and publishGlobal to accept new token variable
|
|
26
|
+
|
|
27
|
+
## 0.1.0-next.1
|
|
28
|
+
|
|
29
|
+
### Minor Changes
|
|
30
|
+
|
|
31
|
+
- 4242274: Adds new signRealtimeToken method to the forge realtime package
|
|
32
|
+
|
|
3
33
|
## 0.0.7-next.0
|
|
4
34
|
|
|
5
35
|
### Patch Changes
|
|
@@ -4,6 +4,33 @@ const tslib_1 = require("tslib");
|
|
|
4
4
|
const runtime = tslib_1.__importStar(require("../runtime"));
|
|
5
5
|
const publish_1 = require("../publish");
|
|
6
6
|
const utils_1 = require("./utils");
|
|
7
|
+
const TEST_EVENT_ID = 'event-id';
|
|
8
|
+
const TEST_EVENT_TIMESTAMP = '1234567890';
|
|
9
|
+
const MOCK_CHANNEL = 'my-channel';
|
|
10
|
+
const MOCK_PUBLISH_OPTIONS = { token: 'my-token' };
|
|
11
|
+
const MOCK_EVENT_PAYLOAD_STRING = 'this is an event payload';
|
|
12
|
+
const MOCK_EVENT_PAYLOAD_OBJECT = { value: 'this is a test payload', funLevel: 100 };
|
|
13
|
+
const MOCK_FETCH_RESPONSE = {
|
|
14
|
+
errors: [],
|
|
15
|
+
data: {
|
|
16
|
+
ecosystem: {
|
|
17
|
+
publishRealtimeChannel: {
|
|
18
|
+
eventId: TEST_EVENT_ID,
|
|
19
|
+
eventTimestamp: TEST_EVENT_TIMESTAMP
|
|
20
|
+
},
|
|
21
|
+
success: true
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
const MOCK_ERRORS = [
|
|
26
|
+
{
|
|
27
|
+
message: 'Error message',
|
|
28
|
+
extensions: {
|
|
29
|
+
errorType: 'Error type',
|
|
30
|
+
statusCode: 500
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
];
|
|
7
34
|
describe('publish', () => {
|
|
8
35
|
beforeEach(() => {
|
|
9
36
|
jest.restoreAllMocks();
|
|
@@ -12,26 +39,25 @@ describe('publish', () => {
|
|
|
12
39
|
it('should publish an event with FCT in header', async () => {
|
|
13
40
|
jest.spyOn(runtime, '__getRuntime').mockReturnValue(utils_1.FORGE_RUNTIME);
|
|
14
41
|
const mockForgeFetch = jest.fn().mockResolvedValue({
|
|
15
|
-
|
|
42
|
+
json: jest.fn().mockResolvedValue(MOCK_FETCH_RESPONSE),
|
|
16
43
|
status: 200,
|
|
17
44
|
headers: { get: jest.fn().mockReturnValue(undefined) }
|
|
18
45
|
});
|
|
19
46
|
global.__forge_fetch__ = mockForgeFetch;
|
|
20
|
-
const response = await (0, publish_1.publish)(
|
|
21
|
-
expect(response
|
|
47
|
+
const response = await (0, publish_1.publish)(MOCK_CHANNEL, MOCK_EVENT_PAYLOAD_STRING, MOCK_PUBLISH_OPTIONS);
|
|
48
|
+
expect(response).toEqual({ eventId: TEST_EVENT_ID, eventTimestamp: TEST_EVENT_TIMESTAMP });
|
|
22
49
|
expect(mockForgeFetch.mock.calls).toMatchSnapshot();
|
|
23
50
|
});
|
|
24
51
|
it('should publish an event when the payload is an object', async () => {
|
|
25
52
|
jest.spyOn(runtime, '__getRuntime').mockReturnValue(utils_1.FORGE_RUNTIME);
|
|
26
53
|
const mockForgeFetch = jest.fn().mockResolvedValue({
|
|
27
|
-
|
|
54
|
+
json: jest.fn().mockResolvedValue(MOCK_FETCH_RESPONSE),
|
|
28
55
|
status: 200,
|
|
29
56
|
headers: { get: jest.fn().mockReturnValue(undefined) }
|
|
30
57
|
});
|
|
31
58
|
global.__forge_fetch__ = mockForgeFetch;
|
|
32
|
-
const
|
|
33
|
-
|
|
34
|
-
expect(response.status).toBe(200);
|
|
59
|
+
const response = await (0, publish_1.publish)(MOCK_CHANNEL, JSON.stringify(MOCK_EVENT_PAYLOAD_OBJECT), MOCK_PUBLISH_OPTIONS);
|
|
60
|
+
expect(response).toEqual({ eventId: TEST_EVENT_ID, eventTimestamp: TEST_EVENT_TIMESTAMP });
|
|
35
61
|
expect(mockForgeFetch.mock.calls).toMatchSnapshot();
|
|
36
62
|
});
|
|
37
63
|
it('should throw an error when Forge Outbound Proxy returns an error', async () => {
|
|
@@ -42,11 +68,30 @@ describe('publish', () => {
|
|
|
42
68
|
headers: { get: jest.fn().mockReturnValue('UPSTREAM_FAILURE') }
|
|
43
69
|
});
|
|
44
70
|
global.__forge_fetch__ = mockForgeFetch;
|
|
45
|
-
const
|
|
46
|
-
const response = (0, publish_1.publish)('my-channel', JSON.stringify(payload));
|
|
71
|
+
const response = (0, publish_1.publish)(MOCK_CHANNEL, JSON.stringify(MOCK_EVENT_PAYLOAD_OBJECT), MOCK_PUBLISH_OPTIONS);
|
|
47
72
|
await expect(response).rejects.toThrow('Forge platform failed to process runtime HTTP request - 502 - UPSTREAM_FAILURE');
|
|
48
73
|
expect(mockForgeFetch.mock.calls).toMatchSnapshot();
|
|
49
74
|
});
|
|
75
|
+
it('should return null eventId and eventTimestamp when the response has errors', async () => {
|
|
76
|
+
jest.spyOn(runtime, '__getRuntime').mockReturnValue(utils_1.FORGE_RUNTIME);
|
|
77
|
+
const mockForgeFetch = jest.fn().mockResolvedValue({
|
|
78
|
+
json: jest.fn().mockResolvedValue({
|
|
79
|
+
errors: MOCK_ERRORS,
|
|
80
|
+
data: {
|
|
81
|
+
ecosystem: {
|
|
82
|
+
publishRealtimeChannel: null,
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}),
|
|
86
|
+
status: 200,
|
|
87
|
+
headers: { get: jest.fn().mockReturnValue(undefined) }
|
|
88
|
+
});
|
|
89
|
+
global.__forge_fetch__ = mockForgeFetch;
|
|
90
|
+
const payload = { value: 'this is a test payload', funLevel: 100 };
|
|
91
|
+
const response = await (0, publish_1.publish)('my-channel', JSON.stringify(payload));
|
|
92
|
+
expect(response).toEqual({ eventId: null, eventTimestamp: null, errors: MOCK_ERRORS });
|
|
93
|
+
expect(mockForgeFetch.mock.calls).toMatchSnapshot();
|
|
94
|
+
});
|
|
50
95
|
});
|
|
51
96
|
describe('publishGlobal', () => {
|
|
52
97
|
beforeEach(() => {
|
|
@@ -56,26 +101,25 @@ describe('publishGlobal', () => {
|
|
|
56
101
|
it('should publish an event', async () => {
|
|
57
102
|
jest.spyOn(runtime, '__getRuntime').mockReturnValue(utils_1.FORGE_RUNTIME);
|
|
58
103
|
const mockForgeFetch = jest.fn().mockResolvedValue({
|
|
59
|
-
|
|
104
|
+
json: jest.fn().mockResolvedValue(MOCK_FETCH_RESPONSE),
|
|
60
105
|
status: 200,
|
|
61
106
|
headers: { get: jest.fn().mockReturnValue(undefined) }
|
|
62
107
|
});
|
|
63
108
|
global.__forge_fetch__ = mockForgeFetch;
|
|
64
|
-
const response = await (0, publish_1.publishGlobal)(
|
|
65
|
-
expect(response
|
|
109
|
+
const response = await (0, publish_1.publishGlobal)(MOCK_CHANNEL, MOCK_EVENT_PAYLOAD_STRING, MOCK_PUBLISH_OPTIONS);
|
|
110
|
+
expect(response).toEqual({ eventId: TEST_EVENT_ID, eventTimestamp: TEST_EVENT_TIMESTAMP });
|
|
66
111
|
expect(mockForgeFetch.mock.calls).toMatchSnapshot();
|
|
67
112
|
});
|
|
68
113
|
it('should publish an event when the payload is an object', async () => {
|
|
69
114
|
jest.spyOn(runtime, '__getRuntime').mockReturnValue(utils_1.FORGE_RUNTIME);
|
|
70
115
|
const mockForgeFetch = jest.fn().mockResolvedValue({
|
|
71
|
-
|
|
116
|
+
json: jest.fn().mockResolvedValue(MOCK_FETCH_RESPONSE),
|
|
72
117
|
status: 200,
|
|
73
118
|
headers: { get: jest.fn().mockReturnValue(undefined) }
|
|
74
119
|
});
|
|
75
120
|
global.__forge_fetch__ = mockForgeFetch;
|
|
76
|
-
const
|
|
77
|
-
|
|
78
|
-
expect(response.status).toBe(200);
|
|
121
|
+
const response = await (0, publish_1.publishGlobal)(MOCK_CHANNEL, JSON.stringify(MOCK_EVENT_PAYLOAD_OBJECT), MOCK_PUBLISH_OPTIONS);
|
|
122
|
+
expect(response).toEqual({ eventId: TEST_EVENT_ID, eventTimestamp: TEST_EVENT_TIMESTAMP });
|
|
79
123
|
expect(mockForgeFetch.mock.calls).toMatchSnapshot();
|
|
80
124
|
});
|
|
81
125
|
it('should throw an error when Forge Outbound Proxy returns an error', async () => {
|
|
@@ -86,9 +130,28 @@ describe('publishGlobal', () => {
|
|
|
86
130
|
headers: { get: jest.fn().mockReturnValue('UPSTREAM_FAILURE') }
|
|
87
131
|
});
|
|
88
132
|
global.__forge_fetch__ = mockForgeFetch;
|
|
89
|
-
const
|
|
90
|
-
const response = (0, publish_1.publishGlobal)('my-channel', JSON.stringify(payload));
|
|
133
|
+
const response = (0, publish_1.publishGlobal)(MOCK_CHANNEL, JSON.stringify(MOCK_EVENT_PAYLOAD_OBJECT), MOCK_PUBLISH_OPTIONS);
|
|
91
134
|
await expect(response).rejects.toThrow('Forge platform failed to process runtime HTTP request - 502 - UPSTREAM_FAILURE');
|
|
92
135
|
expect(mockForgeFetch.mock.calls).toMatchSnapshot();
|
|
93
136
|
});
|
|
137
|
+
it('should return null eventId and eventTimestamp when the response has errors', async () => {
|
|
138
|
+
jest.spyOn(runtime, '__getRuntime').mockReturnValue(utils_1.FORGE_RUNTIME);
|
|
139
|
+
const mockForgeFetch = jest.fn().mockResolvedValue({
|
|
140
|
+
json: jest.fn().mockResolvedValue({
|
|
141
|
+
errors: MOCK_ERRORS,
|
|
142
|
+
data: {
|
|
143
|
+
ecosystem: {
|
|
144
|
+
publishRealtimeChannel: null,
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}),
|
|
148
|
+
status: 200,
|
|
149
|
+
headers: { get: jest.fn().mockReturnValue(undefined) }
|
|
150
|
+
});
|
|
151
|
+
global.__forge_fetch__ = mockForgeFetch;
|
|
152
|
+
const payload = { value: 'this is a test payload', funLevel: 100 };
|
|
153
|
+
const response = await (0, publish_1.publishGlobal)('my-channel', JSON.stringify(payload));
|
|
154
|
+
expect(response).toEqual({ eventId: null, eventTimestamp: null, errors: MOCK_ERRORS });
|
|
155
|
+
expect(mockForgeFetch.mock.calls).toMatchSnapshot();
|
|
156
|
+
});
|
|
94
157
|
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"signRealtimeToken.test.d.ts","sourceRoot":"","sources":["../../src/__test__/signRealtimeToken.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const tslib_1 = require("tslib");
|
|
4
|
+
const runtime = tslib_1.__importStar(require("../runtime"));
|
|
5
|
+
const signRealtimeToken_1 = require("../signRealtimeToken");
|
|
6
|
+
const utils_1 = require("./utils");
|
|
7
|
+
const TEST_TOKEN = 'jwt-token';
|
|
8
|
+
const TEST_EXPIRES_AT = '1234567890';
|
|
9
|
+
const MOCK_ERRORS = [
|
|
10
|
+
{
|
|
11
|
+
message: 'Error message',
|
|
12
|
+
extensions: {
|
|
13
|
+
errorType: 'Error type',
|
|
14
|
+
statusCode: 500
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
];
|
|
18
|
+
describe('signRealtimeToken', () => {
|
|
19
|
+
beforeEach(() => {
|
|
20
|
+
jest.restoreAllMocks();
|
|
21
|
+
jest.resetAllMocks();
|
|
22
|
+
});
|
|
23
|
+
it('should send a signRealtimeToken request and recieve a jwt and expiresAt', async () => {
|
|
24
|
+
jest.spyOn(runtime, '__getRuntime').mockReturnValue(utils_1.FORGE_RUNTIME);
|
|
25
|
+
const mockForgeFetch = jest.fn().mockResolvedValue({
|
|
26
|
+
json: jest.fn().mockResolvedValue({
|
|
27
|
+
errors: [],
|
|
28
|
+
data: {
|
|
29
|
+
ecosystem: {
|
|
30
|
+
signRealtimeToken: {
|
|
31
|
+
errors: [],
|
|
32
|
+
forgeRealtimeToken: {
|
|
33
|
+
jwt: TEST_TOKEN,
|
|
34
|
+
expiresAt: TEST_EXPIRES_AT
|
|
35
|
+
},
|
|
36
|
+
success: true
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}),
|
|
41
|
+
status: 200,
|
|
42
|
+
headers: { get: jest.fn().mockReturnValue(undefined) }
|
|
43
|
+
});
|
|
44
|
+
global.__forge_fetch__ = mockForgeFetch;
|
|
45
|
+
const response = await (0, signRealtimeToken_1.signRealtimeToken)('my-channel', { 'test-key': 'test-value' });
|
|
46
|
+
expect(response).toEqual({ token: TEST_TOKEN, expiresAt: TEST_EXPIRES_AT });
|
|
47
|
+
expect(mockForgeFetch.mock.calls).toMatchSnapshot();
|
|
48
|
+
});
|
|
49
|
+
it('should throw an error when Forge Outbound Proxy returns an error', async () => {
|
|
50
|
+
jest.spyOn(runtime, '__getRuntime').mockReturnValue(utils_1.FORGE_RUNTIME);
|
|
51
|
+
const mockForgeFetch = jest.fn().mockResolvedValue({
|
|
52
|
+
text: jest.fn().mockResolvedValue('Error occurred'),
|
|
53
|
+
status: 502,
|
|
54
|
+
headers: { get: jest.fn().mockReturnValue('UPSTREAM_FAILURE') }
|
|
55
|
+
});
|
|
56
|
+
global.__forge_fetch__ = mockForgeFetch;
|
|
57
|
+
const response = (0, signRealtimeToken_1.signRealtimeToken)('my-channel', { 'test-key': 'test-value' });
|
|
58
|
+
await expect(response).rejects.toThrow('Forge platform failed to process runtime HTTP request - 502 - UPSTREAM_FAILURE');
|
|
59
|
+
expect(mockForgeFetch.mock.calls).toMatchSnapshot();
|
|
60
|
+
});
|
|
61
|
+
it('should send generic error when errors are returned', async () => {
|
|
62
|
+
jest.spyOn(runtime, '__getRuntime').mockReturnValue(utils_1.FORGE_RUNTIME);
|
|
63
|
+
const mockForgeFetch = jest.fn().mockResolvedValue({
|
|
64
|
+
json: jest.fn().mockResolvedValue({
|
|
65
|
+
errors: MOCK_ERRORS,
|
|
66
|
+
data: {
|
|
67
|
+
ecosystem: {
|
|
68
|
+
signRealtimeToken: null,
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}),
|
|
72
|
+
status: 200,
|
|
73
|
+
headers: { get: jest.fn().mockReturnValue(undefined) }
|
|
74
|
+
});
|
|
75
|
+
global.__forge_fetch__ = mockForgeFetch;
|
|
76
|
+
const response = await (0, signRealtimeToken_1.signRealtimeToken)('my-channel', { 'test-key': 'test-value' });
|
|
77
|
+
expect(response).toEqual({ token: null, expiresAt: null, errors: MOCK_ERRORS });
|
|
78
|
+
expect(mockForgeFetch.mock.calls).toMatchSnapshot();
|
|
79
|
+
});
|
|
80
|
+
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/__test__/utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAG/C,eAAO,MAAM,aAAa,EAAE,
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/__test__/utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAG/C,eAAO,MAAM,aAAa,EAAE,YAkD3B,CAAC"}
|
package/out/__test__/utils.js
CHANGED
|
@@ -16,7 +16,28 @@ exports.FORGE_RUNTIME = {
|
|
|
16
16
|
functionKey: 'functionKey',
|
|
17
17
|
moduleType: 'moduleType',
|
|
18
18
|
moduleKey: 'moduleKey',
|
|
19
|
-
license: { isActive: true }
|
|
19
|
+
license: { isActive: true },
|
|
20
|
+
permissions: {
|
|
21
|
+
scopes: ['read:confluence-content.summary', 'write:confluence-content'],
|
|
22
|
+
content: {
|
|
23
|
+
scripts: [],
|
|
24
|
+
styles: []
|
|
25
|
+
},
|
|
26
|
+
external: {
|
|
27
|
+
fetch: {
|
|
28
|
+
backend: [],
|
|
29
|
+
client: []
|
|
30
|
+
},
|
|
31
|
+
fonts: [],
|
|
32
|
+
frames: [],
|
|
33
|
+
navigation: [],
|
|
34
|
+
images: [],
|
|
35
|
+
media: [],
|
|
36
|
+
scripts: [],
|
|
37
|
+
styles: []
|
|
38
|
+
},
|
|
39
|
+
format: () => ''
|
|
40
|
+
}
|
|
20
41
|
},
|
|
21
42
|
tracing: {
|
|
22
43
|
traceId: 'traceId',
|
package/out/index.d.ts
CHANGED
package/out/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC"}
|
package/out/index.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.publishGlobal = exports.publish = void 0;
|
|
3
|
+
exports.signRealtimeToken = exports.publishGlobal = exports.publish = void 0;
|
|
4
4
|
var publish_1 = require("./publish");
|
|
5
5
|
Object.defineProperty(exports, "publish", { enumerable: true, get: function () { return publish_1.publish; } });
|
|
6
6
|
Object.defineProperty(exports, "publishGlobal", { enumerable: true, get: function () { return publish_1.publishGlobal; } });
|
|
7
|
+
var signRealtimeToken_1 = require("./signRealtimeToken");
|
|
8
|
+
Object.defineProperty(exports, "signRealtimeToken", { enumerable: true, get: function () { return signRealtimeToken_1.signRealtimeToken; } });
|
package/out/publish.d.ts
CHANGED
|
@@ -1,5 +1,23 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
export declare const
|
|
1
|
+
interface PublishOptions {
|
|
2
|
+
token?: string;
|
|
3
|
+
}
|
|
4
|
+
export declare const publish: (channelName: string, eventPayload: string, options?: PublishOptions) => Promise<{
|
|
5
|
+
eventId: null;
|
|
6
|
+
eventTimestamp: null;
|
|
7
|
+
errors: any;
|
|
8
|
+
} | {
|
|
9
|
+
eventId: any;
|
|
10
|
+
eventTimestamp: any;
|
|
11
|
+
errors?: undefined;
|
|
12
|
+
}>;
|
|
13
|
+
export declare const publishGlobal: (channelName: string, eventPayload: string, options?: PublishOptions) => Promise<{
|
|
14
|
+
eventId: null;
|
|
15
|
+
eventTimestamp: null;
|
|
16
|
+
errors: any;
|
|
17
|
+
} | {
|
|
18
|
+
eventId: any;
|
|
19
|
+
eventTimestamp: any;
|
|
20
|
+
errors?: undefined;
|
|
21
|
+
}>;
|
|
22
|
+
export {};
|
|
5
23
|
//# sourceMappingURL=publish.d.ts.map
|
package/out/publish.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"publish.d.ts","sourceRoot":"","sources":["../src/publish.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"publish.d.ts","sourceRoot":"","sources":["../src/publish.ts"],"names":[],"mappings":"AAwBA,UAAU,cAAc;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,eAAO,MAAM,OAAO,gBAAuB,MAAM,gBAAgB,MAAM,YAAY,cAAc;;;;;;;;EAiEhG,CAAC;AAEF,eAAO,MAAM,aAAa,gBAAuB,MAAM,gBAAgB,MAAM,YAAY,cAAc;;;;;;;;EAgEtG,CAAC"}
|
package/out/publish.js
CHANGED
|
@@ -1,22 +1,14 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.publishGlobal = exports.publish =
|
|
4
|
-
const api_1 = require("@forge/api");
|
|
3
|
+
exports.publishGlobal = exports.publish = void 0;
|
|
5
4
|
const runtime_1 = require("./runtime");
|
|
6
|
-
const
|
|
7
|
-
exports.getForgeProxyError = getForgeProxyError;
|
|
8
|
-
const handleProxyResponseErrors = (response) => {
|
|
9
|
-
const errorReason = (0, exports.getForgeProxyError)(response);
|
|
10
|
-
if (errorReason) {
|
|
11
|
-
throw new api_1.ProxyRequestError(response.status, errorReason);
|
|
12
|
-
}
|
|
13
|
-
};
|
|
14
|
-
exports.handleProxyResponseErrors = handleProxyResponseErrors;
|
|
5
|
+
const utils_1 = require("./utils");
|
|
15
6
|
const graphqlBody = `mutation publishRealtimeChannel(
|
|
16
7
|
$installationId: ID!
|
|
17
8
|
$name: String!
|
|
18
9
|
$payload: String!
|
|
19
10
|
$isGlobal: Boolean
|
|
11
|
+
$token: String
|
|
20
12
|
){
|
|
21
13
|
ecosystem {
|
|
22
14
|
publishRealtimeChannel(
|
|
@@ -24,17 +16,17 @@ const graphqlBody = `mutation publishRealtimeChannel(
|
|
|
24
16
|
name: $name
|
|
25
17
|
payload: $payload
|
|
26
18
|
isGlobal: $isGlobal
|
|
19
|
+
token: $token
|
|
27
20
|
) {
|
|
28
21
|
eventId,
|
|
29
22
|
eventTimestamp
|
|
30
23
|
}
|
|
31
24
|
}
|
|
32
25
|
}`;
|
|
33
|
-
const
|
|
34
|
-
const publish = async (channelName, eventPayload) => {
|
|
26
|
+
const publish = async (channelName, eventPayload, options) => {
|
|
35
27
|
const { appContext, realtime } = (0, runtime_1.__getRuntime)();
|
|
36
28
|
if (appContext?.environmentType === 'PRODUCTION') {
|
|
37
|
-
throw new Error(prodEnvErrorMessage);
|
|
29
|
+
throw new Error(utils_1.prodEnvErrorMessage);
|
|
38
30
|
}
|
|
39
31
|
const response = await global.__forge_fetch__({
|
|
40
32
|
type: 'realtime'
|
|
@@ -46,22 +38,48 @@ const publish = async (channelName, eventPayload) => {
|
|
|
46
38
|
installationId: appContext.installationId,
|
|
47
39
|
name: channelName,
|
|
48
40
|
payload: eventPayload,
|
|
49
|
-
isGlobal: false
|
|
41
|
+
isGlobal: false,
|
|
42
|
+
token: options?.token
|
|
50
43
|
}
|
|
51
44
|
}),
|
|
45
|
+
errors: [],
|
|
52
46
|
headers: {
|
|
53
47
|
'Content-Type': 'application/json',
|
|
54
48
|
'x-forge-context-token': realtime?.contextToken
|
|
55
49
|
}
|
|
56
50
|
});
|
|
57
|
-
(0,
|
|
58
|
-
|
|
51
|
+
(0, utils_1.handleProxyResponseErrors)(response);
|
|
52
|
+
const awaitedResponse = await response.json();
|
|
53
|
+
const { data, errors } = awaitedResponse;
|
|
54
|
+
if (errors && errors.length > 0) {
|
|
55
|
+
return {
|
|
56
|
+
eventId: null,
|
|
57
|
+
eventTimestamp: null,
|
|
58
|
+
errors
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
if (!data) {
|
|
62
|
+
return {
|
|
63
|
+
eventId: null,
|
|
64
|
+
eventTimestamp: null,
|
|
65
|
+
errors: [
|
|
66
|
+
{
|
|
67
|
+
message: 'Error publishing event to channel.'
|
|
68
|
+
}
|
|
69
|
+
]
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
const { eventId, eventTimestamp } = awaitedResponse.data.ecosystem.publishRealtimeChannel;
|
|
73
|
+
return {
|
|
74
|
+
eventId,
|
|
75
|
+
eventTimestamp
|
|
76
|
+
};
|
|
59
77
|
};
|
|
60
78
|
exports.publish = publish;
|
|
61
|
-
const publishGlobal = async (channelName, eventPayload) => {
|
|
79
|
+
const publishGlobal = async (channelName, eventPayload, options) => {
|
|
62
80
|
const { appContext } = (0, runtime_1.__getRuntime)();
|
|
63
81
|
if (appContext?.environmentType === 'PRODUCTION') {
|
|
64
|
-
throw new Error(prodEnvErrorMessage);
|
|
82
|
+
throw new Error(utils_1.prodEnvErrorMessage);
|
|
65
83
|
}
|
|
66
84
|
const response = await global.__forge_fetch__({
|
|
67
85
|
type: 'realtime'
|
|
@@ -73,14 +91,40 @@ const publishGlobal = async (channelName, eventPayload) => {
|
|
|
73
91
|
installationId: appContext.installationId,
|
|
74
92
|
name: channelName,
|
|
75
93
|
payload: eventPayload,
|
|
76
|
-
isGlobal: true
|
|
94
|
+
isGlobal: true,
|
|
95
|
+
token: options?.token
|
|
77
96
|
}
|
|
78
97
|
}),
|
|
98
|
+
errors: [],
|
|
79
99
|
headers: {
|
|
80
100
|
'Content-Type': 'application/json'
|
|
81
101
|
}
|
|
82
102
|
});
|
|
83
|
-
(0,
|
|
84
|
-
|
|
103
|
+
(0, utils_1.handleProxyResponseErrors)(response);
|
|
104
|
+
const awaitedResponse = await response.json();
|
|
105
|
+
const { data, errors } = awaitedResponse;
|
|
106
|
+
if (errors && errors.length > 0) {
|
|
107
|
+
return {
|
|
108
|
+
eventId: null,
|
|
109
|
+
eventTimestamp: null,
|
|
110
|
+
errors
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
if (!data) {
|
|
114
|
+
return {
|
|
115
|
+
eventId: null,
|
|
116
|
+
eventTimestamp: null,
|
|
117
|
+
errors: [
|
|
118
|
+
{
|
|
119
|
+
message: 'Error publishing global event to channel.'
|
|
120
|
+
}
|
|
121
|
+
]
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
const { eventId, eventTimestamp } = data.ecosystem.publishRealtimeChannel;
|
|
125
|
+
return {
|
|
126
|
+
eventId,
|
|
127
|
+
eventTimestamp
|
|
128
|
+
};
|
|
85
129
|
};
|
|
86
130
|
exports.publishGlobal = publishGlobal;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"signRealtimeToken.d.ts","sourceRoot":"","sources":["../src/signRealtimeToken.ts"],"names":[],"mappings":"AA4BA,eAAO,MAAM,iBAAiB,gBAAuB,MAAM,UAAU,GAAG;;;;;;;;EA6DvE,CAAC"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.signRealtimeToken = void 0;
|
|
4
|
+
const runtime_1 = require("./runtime");
|
|
5
|
+
const utils_1 = require("./utils");
|
|
6
|
+
const graphqlBody = `mutation signRealtimeToken(
|
|
7
|
+
$channelName: String!
|
|
8
|
+
$claims: JSON!
|
|
9
|
+
){
|
|
10
|
+
ecosystem {
|
|
11
|
+
signRealtimeToken(
|
|
12
|
+
channelName: $channelName
|
|
13
|
+
claims: $claims
|
|
14
|
+
) {
|
|
15
|
+
errors {
|
|
16
|
+
message
|
|
17
|
+
extensions {
|
|
18
|
+
errorType
|
|
19
|
+
statusCode
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
forgeRealtimeToken {
|
|
23
|
+
jwt
|
|
24
|
+
expiresAt
|
|
25
|
+
}
|
|
26
|
+
success
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}`;
|
|
30
|
+
const signRealtimeToken = async (channelName, claims) => {
|
|
31
|
+
const { appContext } = (0, runtime_1.__getRuntime)();
|
|
32
|
+
if (appContext?.environmentType === 'PRODUCTION') {
|
|
33
|
+
throw new Error(utils_1.prodEnvErrorMessage);
|
|
34
|
+
}
|
|
35
|
+
const response = await global.__forge_fetch__({
|
|
36
|
+
type: 'realtime'
|
|
37
|
+
}, '/', {
|
|
38
|
+
method: 'POST',
|
|
39
|
+
body: JSON.stringify({
|
|
40
|
+
query: graphqlBody,
|
|
41
|
+
variables: {
|
|
42
|
+
channelName,
|
|
43
|
+
claims
|
|
44
|
+
}
|
|
45
|
+
}),
|
|
46
|
+
errors: [],
|
|
47
|
+
headers: {
|
|
48
|
+
'Content-Type': 'application/json'
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
(0, utils_1.handleProxyResponseErrors)(response);
|
|
52
|
+
const awaitedResponse = await response.json();
|
|
53
|
+
const { data, errors } = awaitedResponse;
|
|
54
|
+
if (errors && errors.length > 0) {
|
|
55
|
+
return {
|
|
56
|
+
token: null,
|
|
57
|
+
expiresAt: null,
|
|
58
|
+
errors
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
if (!data) {
|
|
62
|
+
return {
|
|
63
|
+
token: null,
|
|
64
|
+
expiresAt: null,
|
|
65
|
+
errors: [
|
|
66
|
+
{
|
|
67
|
+
message: 'Error signing realtime token.'
|
|
68
|
+
}
|
|
69
|
+
]
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
const { jwt, expiresAt } = data.ecosystem.signRealtimeToken.forgeRealtimeToken;
|
|
73
|
+
return {
|
|
74
|
+
token: jwt,
|
|
75
|
+
expiresAt
|
|
76
|
+
};
|
|
77
|
+
};
|
|
78
|
+
exports.signRealtimeToken = signRealtimeToken;
|
package/out/utils.d.ts
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export declare const handleProxyResponseErrors: (response: Response) => void;
|
|
2
|
+
export declare const prodEnvErrorMessage = "Forge realtime usage is restricted to Forge apps in a non-production environment. Please see https://developer.atlassian.com/platform/forge/cli-reference/environments/ for reference on Forge app environments.";
|
|
3
|
+
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,yBAAyB,aAAc,QAAQ,KAAG,IAK9D,CAAC;AAEF,eAAO,MAAM,mBAAmB,qNACoL,CAAC"}
|
package/out/utils.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.prodEnvErrorMessage = exports.handleProxyResponseErrors = void 0;
|
|
4
|
+
const api_1 = require("@forge/api");
|
|
5
|
+
const getForgeProxyError = (response) => response.headers.get('forge-proxy-error');
|
|
6
|
+
const handleProxyResponseErrors = (response) => {
|
|
7
|
+
const errorReason = getForgeProxyError(response);
|
|
8
|
+
if (errorReason) {
|
|
9
|
+
throw new api_1.ProxyRequestError(response.status, errorReason);
|
|
10
|
+
}
|
|
11
|
+
};
|
|
12
|
+
exports.handleProxyResponseErrors = handleProxyResponseErrors;
|
|
13
|
+
exports.prodEnvErrorMessage = 'Forge realtime usage is restricted to Forge apps in a non-production environment. Please see https://developer.atlassian.com/platform/forge/cli-reference/environments/ for reference on Forge app environments.';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@forge/realtime",
|
|
3
|
-
"version": "0.0
|
|
3
|
+
"version": "0.1.0-experimental-3f68b81",
|
|
4
4
|
"description": "Forge realtime",
|
|
5
5
|
"main": "out/index.js",
|
|
6
6
|
"types": "out/index.d.ts",
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
},
|
|
15
15
|
"devDependencies": {
|
|
16
16
|
"@atlassian/metrics-interface": "4.0.0",
|
|
17
|
-
"@forge/api": "6.1.
|
|
17
|
+
"@forge/api": "6.1.1-experimental-3f68b81",
|
|
18
18
|
"@types/node": "20.19.1"
|
|
19
19
|
},
|
|
20
20
|
"publishConfig": {
|