@forge/react 10.10.2 → 10.10.3-experimental-147ff14
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 +18 -0
- package/out/hooks/__test__/confluenceEntity.test.js +30 -0
- package/out/hooks/__test__/useConfig.test.js +34 -2
- package/out/hooks/confluenceEntity.d.ts.map +1 -1
- package/out/hooks/confluenceEntity.js +8 -12
- package/out/hooks/useConfig.d.ts.map +1 -1
- package/out/hooks/useConfig.js +25 -3
- package/out/reconciler.js +2 -2
- package/package.json +1 -1
- package/tsconfig.tsbuildinfo +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
# @forge/react
|
|
2
2
|
|
|
3
|
+
## 10.10.3-experimental-147ff14
|
|
4
|
+
|
|
5
|
+
### Major Changes
|
|
6
|
+
|
|
7
|
+
- f9073fe: Improve useConfig hook so it reflects value properly on macro config updates
|
|
8
|
+
|
|
9
|
+
## 10.10.3
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- ea9fa2a: Fix update method in useSpaceProperty to ensure it works as expect when value does not exist
|
|
14
|
+
|
|
15
|
+
## 10.10.3-next.0
|
|
16
|
+
|
|
17
|
+
### Patch Changes
|
|
18
|
+
|
|
19
|
+
- ea9fa2a: Fix update method in useSpaceProperty to ensure it works as expect when value does not exist
|
|
20
|
+
|
|
3
21
|
## 10.10.2
|
|
4
22
|
|
|
5
23
|
### Patch Changes
|
|
@@ -126,6 +126,36 @@ describe('confluenceEntity', () => {
|
|
|
126
126
|
mockRequestConf.mockResolvedValueOnce(mockPropertyHook_1.mockConfGetExistingRes).mockResolvedValueOnce(mockPropertyHook_1.mockFailedRes);
|
|
127
127
|
await expect(() => contentEntity.update(mockPropertyHook_1.UPDATED_PROP_VALUE)).rejects.toThrow(`The request to update the content property (forge-MOCK_LOCAL_ID-MOCK_PROP_KEY) failed with status (400).`);
|
|
128
128
|
});
|
|
129
|
+
describe('if the property does not exist, it should create it', () => {
|
|
130
|
+
beforeEach(() => {
|
|
131
|
+
mockRequestConf.mockReset();
|
|
132
|
+
mockRequestConf
|
|
133
|
+
.mockResolvedValueOnce(mockPropertyHook_1.mockConfGetNonExistentRes)
|
|
134
|
+
.mockResolvedValueOnce(mockPropertyHook_1.mockConfCreateRes)
|
|
135
|
+
.mockResolvedValueOnce(mockPropertyHook_1.mockConfUpdateValueRes);
|
|
136
|
+
});
|
|
137
|
+
it('should make a POST request to the API with the right URL and body', async () => {
|
|
138
|
+
const contentGetUrl = contentEndpoints.fetch('forge-MOCK_LOCAL_ID-MOCK_PROP_KEY');
|
|
139
|
+
const contentGetBody = expect.objectContaining({ method: 'GET' });
|
|
140
|
+
const contentPutUrl = contentEndpoints.update('MOCK_PROP_ID');
|
|
141
|
+
const contentPostUrl = contentEndpoints.create();
|
|
142
|
+
const contentPostBody = expect.objectContaining({
|
|
143
|
+
method: 'POST',
|
|
144
|
+
body: JSON.stringify({ key: 'forge-MOCK_LOCAL_ID-MOCK_PROP_KEY', value: mockPropertyHook_1.DEFAULT_PROP_VALUE })
|
|
145
|
+
});
|
|
146
|
+
// both value & version props need to be present in body string
|
|
147
|
+
const valueUpdateStr = `"value":${mockPropertyHook_1.UPDATED_PROP_VALUE}`;
|
|
148
|
+
const contentPutBody = (updateStr) => expect.objectContaining({
|
|
149
|
+
body: expect.stringContaining(updateStr)
|
|
150
|
+
});
|
|
151
|
+
const valUpdate = await contentEntity.update(mockPropertyHook_1.UPDATED_PROP_VALUE);
|
|
152
|
+
expect(valUpdate).toEqual(mockPropertyHook_1.UPDATED_PROP_VALUE);
|
|
153
|
+
expect(mockRequestConf).toHaveBeenCalledTimes(3);
|
|
154
|
+
expect(mockRequestConf).toHaveBeenNthCalledWith(1, contentGetUrl, contentGetBody);
|
|
155
|
+
expect(mockRequestConf).toHaveBeenNthCalledWith(2, contentPostUrl, contentPostBody);
|
|
156
|
+
expect(mockRequestConf).toHaveBeenNthCalledWith(3, contentPutUrl, contentPutBody(valueUpdateStr));
|
|
157
|
+
});
|
|
158
|
+
});
|
|
129
159
|
});
|
|
130
160
|
describe('when running its delete() output function', () => {
|
|
131
161
|
beforeEach(() => {
|
|
@@ -2,6 +2,23 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const tslib_1 = require("tslib");
|
|
4
4
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
+
const listeners = new Map();
|
|
6
|
+
const simpleBridgeEvents = {
|
|
7
|
+
on: (event, callback) => {
|
|
8
|
+
if (!listeners.has(event)) {
|
|
9
|
+
listeners.set(event, []);
|
|
10
|
+
}
|
|
11
|
+
listeners.get(event)?.push(callback);
|
|
12
|
+
},
|
|
13
|
+
emit: (event, data) => {
|
|
14
|
+
if (listeners.has(event)) {
|
|
15
|
+
listeners.get(event)?.forEach((callback) => callback(data));
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
clearListeners: (event) => {
|
|
19
|
+
listeners.delete(event);
|
|
20
|
+
}
|
|
21
|
+
};
|
|
5
22
|
// defining mock function above import so it is initialised before jest.mock runs
|
|
6
23
|
const mockGetContext = jest.fn(async () => null);
|
|
7
24
|
const react_1 = tslib_1.__importStar(require("react"));
|
|
@@ -11,7 +28,8 @@ const testUtils_1 = require("../../__test__/testUtils");
|
|
|
11
28
|
jest.mock('@forge/bridge', () => ({
|
|
12
29
|
view: {
|
|
13
30
|
getContext: mockGetContext
|
|
14
|
-
}
|
|
31
|
+
},
|
|
32
|
+
events: simpleBridgeEvents
|
|
15
33
|
}));
|
|
16
34
|
const MOCK_CONFIG = {
|
|
17
35
|
value: 1
|
|
@@ -32,10 +50,16 @@ const renderTest = async () => {
|
|
|
32
50
|
(0, react_1.useEffect)(() => configListener(config), [config]);
|
|
33
51
|
return (0, jsx_runtime_1.jsx)(react_1.default.Fragment, {});
|
|
34
52
|
};
|
|
35
|
-
await reconcilerTestRenderer_1.default.create((0, jsx_runtime_1.jsx)(Test, {}));
|
|
53
|
+
const { update } = await reconcilerTestRenderer_1.default.create((0, jsx_runtime_1.jsx)(Test, {}));
|
|
54
|
+
return {
|
|
55
|
+
update: async () => {
|
|
56
|
+
await update((0, jsx_runtime_1.jsx)(Test, {}));
|
|
57
|
+
}
|
|
58
|
+
};
|
|
36
59
|
};
|
|
37
60
|
describe('useConfig', () => {
|
|
38
61
|
beforeAll(() => (0, testUtils_1.setupBridge)());
|
|
62
|
+
beforeEach(() => simpleBridgeEvents.clearListeners('FORGE_CORE_MACRO_CONFIG_CHANGED'));
|
|
39
63
|
afterEach(() => jest.clearAllMocks());
|
|
40
64
|
it('correctly outputs a given config', async () => {
|
|
41
65
|
mockGetContext.mockResolvedValue(MOCK_CONTEXT_WITH_CONFIG);
|
|
@@ -49,4 +73,12 @@ describe('useConfig', () => {
|
|
|
49
73
|
// no change to undef value after productContext call, do not re-render
|
|
50
74
|
expect(configListener).not.toHaveBeenNthCalledWith(2, expect.anything);
|
|
51
75
|
});
|
|
76
|
+
it('when config is updated, outputs new config', async () => {
|
|
77
|
+
mockGetContext.mockResolvedValue(MOCK_CONTEXT_WITH_CONFIG);
|
|
78
|
+
await renderTest();
|
|
79
|
+
expect(mockGetContext).toHaveBeenCalledTimes(1);
|
|
80
|
+
const newConfig = { value: 2 };
|
|
81
|
+
simpleBridgeEvents.emit('FORGE_CORE_MACRO_CONFIG_CHANGED', newConfig);
|
|
82
|
+
expect(mockGetContext).toHaveBeenCalledTimes(2);
|
|
83
|
+
});
|
|
52
84
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"confluenceEntity.d.ts","sourceRoot":"","sources":["../../src/hooks/confluenceEntity.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EACV,uBAAuB,EAEvB,eAAe,EACf,oBAAoB,EACpB,aAAa,EAEd,MAAM,SAAS,CAAC;AAEjB;;;GAGG;AACH,eAAO,MAAM,gBAAgB,4BAA6B,uBAAuB;;yBAqBxD,MAAM;yBACN,MAAM;yBACN,MAAM;CAE9B,CAAC;AAEF,eAAO,MAAM,gBAAgB;gBAIiB,oBAAoB;
|
|
1
|
+
{"version":3,"file":"confluenceEntity.d.ts","sourceRoot":"","sources":["../../src/hooks/confluenceEntity.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EACV,uBAAuB,EAEvB,eAAe,EACf,oBAAoB,EACpB,aAAa,EAEd,MAAM,SAAS,CAAC;AAEjB;;;GAGG;AACH,eAAO,MAAM,gBAAgB,4BAA6B,uBAAuB;;yBAqBxD,MAAM;yBACN,MAAM;yBACN,MAAM;CAE9B,CAAC;AAEF,eAAO,MAAM,gBAAgB;gBAIiB,oBAAoB;8BAkGjE,CAAC"}
|
|
@@ -69,10 +69,10 @@ const confluenceEntity = ({ entityType, origPropertyKey, initValue }) => {
|
|
|
69
69
|
const response = await (0, apiRequestUtils_1.makeRequest)({ url, apiMethod, method: 'DELETE' });
|
|
70
70
|
(0, apiRequestUtils_1.assertSuccessfulResponse)({ entityType, propertyKey, operation: 'delete', response });
|
|
71
71
|
};
|
|
72
|
-
const
|
|
72
|
+
const getProp = async ({ endpointFactory, propertyKey }) => {
|
|
73
73
|
const existingProp = await fetchOriginal({ endpointFactory, propertyKey });
|
|
74
74
|
if (existingProp) {
|
|
75
|
-
return existingProp
|
|
75
|
+
return existingProp;
|
|
76
76
|
}
|
|
77
77
|
// if property doesn't exist, create it
|
|
78
78
|
const resolvedInitVal = await (0, valueUtils_1.resolveValue)(initValue);
|
|
@@ -80,19 +80,15 @@ const confluenceEntity = ({ entityType, origPropertyKey, initValue }) => {
|
|
|
80
80
|
const body = JSON.stringify({ key: propertyKey, value: resolvedInitVal });
|
|
81
81
|
const response = await (0, apiRequestUtils_1.makeRequest)({ url, apiMethod, method: 'POST', body });
|
|
82
82
|
(0, apiRequestUtils_1.assertSuccessfulResponse)({ entityType, propertyKey, operation: 'create', response });
|
|
83
|
-
return
|
|
83
|
+
return await (0, apiRequestUtils_1.getJSONData)(response);
|
|
84
|
+
};
|
|
85
|
+
const get = async ({ endpointFactory, propertyKey }) => {
|
|
86
|
+
const propData = await getProp({ endpointFactory, propertyKey });
|
|
87
|
+
return propData.value;
|
|
84
88
|
};
|
|
85
89
|
const update = async ({ endpointFactory, propertyKey }, valueUpdate) => {
|
|
86
90
|
// fetch original prop first to update based on its value + version + id
|
|
87
|
-
const originalProp = await
|
|
88
|
-
if (!originalProp) {
|
|
89
|
-
throw new types_1.EntityPropertyRequestFailedError({
|
|
90
|
-
entityType,
|
|
91
|
-
propertyKey,
|
|
92
|
-
operation: 'update',
|
|
93
|
-
status: 404
|
|
94
|
-
});
|
|
95
|
-
}
|
|
91
|
+
const originalProp = await getProp({ endpointFactory, propertyKey });
|
|
96
92
|
const newValue = valueUpdate instanceof Function ? valueUpdate(originalProp.value) : valueUpdate;
|
|
97
93
|
const propertyId = originalProp.id;
|
|
98
94
|
const origVersion = originalProp?.version?.number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useConfig.d.ts","sourceRoot":"","sources":["../../src/hooks/useConfig.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"useConfig.d.ts","sourceRoot":"","sources":["../../src/hooks/useConfig.ts"],"names":[],"mappings":"AAeA,eAAO,MAAM,SAAS,WAiBrB,CAAC"}
|
package/out/hooks/useConfig.js
CHANGED
|
@@ -1,9 +1,31 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.useConfig = void 0;
|
|
4
|
-
const
|
|
4
|
+
const react_1 = require("react");
|
|
5
|
+
const bridge_1 = require("@forge/bridge");
|
|
6
|
+
const updateConfig = (setConfig) => {
|
|
7
|
+
bridge_1.view
|
|
8
|
+
.getContext()
|
|
9
|
+
.then((context) => {
|
|
10
|
+
setConfig(context?.extension.config);
|
|
11
|
+
})
|
|
12
|
+
.catch((err) => {
|
|
13
|
+
throw err;
|
|
14
|
+
});
|
|
15
|
+
};
|
|
5
16
|
const useConfig = () => {
|
|
6
|
-
const
|
|
7
|
-
|
|
17
|
+
const [config, setConfig] = (0, react_1.useState)(undefined);
|
|
18
|
+
(0, react_1.useEffect)(() => {
|
|
19
|
+
updateConfig(setConfig);
|
|
20
|
+
}, []);
|
|
21
|
+
(0, react_1.useEffect)(() => {
|
|
22
|
+
const sub = bridge_1.events.on('FORGE_CORE_MACRO_CONFIG_CHANGED', () => {
|
|
23
|
+
updateConfig(setConfig);
|
|
24
|
+
});
|
|
25
|
+
return () => {
|
|
26
|
+
void sub.then((subscription) => subscription.unsubscribe());
|
|
27
|
+
};
|
|
28
|
+
}, []);
|
|
29
|
+
return config;
|
|
8
30
|
};
|
|
9
31
|
exports.useConfig = useConfig;
|
package/out/reconciler.js
CHANGED
|
@@ -218,7 +218,7 @@ exports.hostConfig = {
|
|
|
218
218
|
const reconciler = (0, react_reconciler_1.default)(exports.hostConfig);
|
|
219
219
|
exports.ForgeReconciler = {
|
|
220
220
|
render: (element) => {
|
|
221
|
-
const rootElement = (0, exports.createElement)({ type: 'Root', props: {}, forgeReactMajorVersion:
|
|
221
|
+
const rootElement = (0, exports.createElement)({ type: 'Root', props: {}, forgeReactMajorVersion: 11 });
|
|
222
222
|
const container = reconciler.createContainer(rootElement, 0, null, false, null, 'root', (err) => {
|
|
223
223
|
// eslint-disable-next-line no-console
|
|
224
224
|
console.log(err);
|
|
@@ -233,7 +233,7 @@ exports.ForgeReconciler = {
|
|
|
233
233
|
}
|
|
234
234
|
},
|
|
235
235
|
addConfig: (element) => {
|
|
236
|
-
const macroConfigElement = (0, exports.createElement)({ type: 'MacroConfig', props: {}, forgeReactMajorVersion:
|
|
236
|
+
const macroConfigElement = (0, exports.createElement)({ type: 'MacroConfig', props: {}, forgeReactMajorVersion: 11 });
|
|
237
237
|
const container = reconciler.createContainer(macroConfigElement, 0, null, false, null, 'macroConfig', (err) => {
|
|
238
238
|
// eslint-disable-next-line no-console
|
|
239
239
|
console.log(err);
|