@contentful/react-apps-toolkit 1.0.0 → 1.0.2
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/LICENSE +21 -0
- package/dist/SDKProvider.d.ts +14 -0
- package/dist/SDKProvider.js +44 -0
- package/dist/SDKProvider.spec.d.ts +1 -0
- package/dist/SDKProvider.spec.js +34 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +20 -0
- package/dist/useCMA.d.ts +6 -0
- package/dist/useCMA.js +25 -0
- package/dist/useCMA.spec.d.ts +1 -0
- package/dist/useCMA.spec.js +36 -0
- package/dist/useFieldValue.d.ts +15 -0
- package/dist/useFieldValue.js +84 -0
- package/dist/useFieldValue.spec.d.ts +1 -0
- package/dist/useFieldValue.spec.js +249 -0
- package/dist/useSDK.d.ts +7 -0
- package/dist/useSDK.js +18 -0
- package/dist/useSDK.spec.d.ts +1 -0
- package/dist/useSDK.spec.js +35 -0
- package/package.json +4 -3
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2020 Contentful
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { KnownSDK } from '@contentful/app-sdk';
|
|
2
|
+
import { FC, ReactElement } from 'react';
|
|
3
|
+
export declare const SDKContext: import("react").Context<{
|
|
4
|
+
sdk: KnownSDK | null;
|
|
5
|
+
}>;
|
|
6
|
+
interface SDKProviderProps {
|
|
7
|
+
loading?: ReactElement;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* The Component providing the AppSdk, the useSDK hook can only be used within this Provider
|
|
11
|
+
* @param props.loading an optional loading element that gets rendered while initializing the app
|
|
12
|
+
*/
|
|
13
|
+
export declare const SDKProvider: FC<SDKProviderProps>;
|
|
14
|
+
export {};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __assign = (this && this.__assign) || function () {
|
|
3
|
+
__assign = Object.assign || function(t) {
|
|
4
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
5
|
+
s = arguments[i];
|
|
6
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
7
|
+
t[p] = s[p];
|
|
8
|
+
}
|
|
9
|
+
return t;
|
|
10
|
+
};
|
|
11
|
+
return __assign.apply(this, arguments);
|
|
12
|
+
};
|
|
13
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
|
+
exports.SDKProvider = exports.SDKContext = void 0;
|
|
15
|
+
var jsx_runtime_1 = require("react/jsx-runtime");
|
|
16
|
+
var app_sdk_1 = require("@contentful/app-sdk");
|
|
17
|
+
var react_1 = require("react");
|
|
18
|
+
exports.SDKContext = (0, react_1.createContext)({ sdk: null });
|
|
19
|
+
var DELAY_TIMEOUT = 4 * 1000;
|
|
20
|
+
/**
|
|
21
|
+
* The Component providing the AppSdk, the useSDK hook can only be used within this Provider
|
|
22
|
+
* @param props.loading an optional loading element that gets rendered while initializing the app
|
|
23
|
+
*/
|
|
24
|
+
var SDKProvider = function (props) {
|
|
25
|
+
var _a = (0, react_1.useState)(), sdk = _a[0], setSDK = _a[1];
|
|
26
|
+
(0, react_1.useEffect)(function () {
|
|
27
|
+
var timeout = window.setTimeout(function () {
|
|
28
|
+
console.warn("Your app is taking longer than expected to initialize. If you think this is an error with Contentful's App SDK, let us know: https://github.com/contentful/ui-extensions-sdk/issues");
|
|
29
|
+
}, DELAY_TIMEOUT);
|
|
30
|
+
(0, app_sdk_1.init)(function (sdk) {
|
|
31
|
+
setSDK(sdk);
|
|
32
|
+
window.clearTimeout(timeout);
|
|
33
|
+
});
|
|
34
|
+
return function () { return window.clearTimeout(timeout); };
|
|
35
|
+
}, []);
|
|
36
|
+
if (!sdk) {
|
|
37
|
+
if (props.loading) {
|
|
38
|
+
return props.loading;
|
|
39
|
+
}
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
return (0, jsx_runtime_1.jsx)(exports.SDKContext.Provider, __assign({ value: { sdk: sdk } }, { children: props.children }));
|
|
43
|
+
};
|
|
44
|
+
exports.SDKProvider = SDKProvider;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
var jsx_runtime_1 = require("react/jsx-runtime");
|
|
4
|
+
var react_1 = require("@testing-library/react");
|
|
5
|
+
var SDKProvider_1 = require("./SDKProvider");
|
|
6
|
+
var app_sdk_1 = require("@contentful/app-sdk");
|
|
7
|
+
jest.useFakeTimers();
|
|
8
|
+
jest.mock('@contentful/app-sdk', function () { return ({
|
|
9
|
+
init: jest.fn(),
|
|
10
|
+
}); });
|
|
11
|
+
describe('SDKProvider', function () {
|
|
12
|
+
var consoleWarnMock;
|
|
13
|
+
beforeEach(function () {
|
|
14
|
+
// @ts-ignore
|
|
15
|
+
app_sdk_1.init.mockImplementation(function (callback) {
|
|
16
|
+
callback({});
|
|
17
|
+
});
|
|
18
|
+
consoleWarnMock = jest.spyOn(console, 'warn').mockImplementation();
|
|
19
|
+
});
|
|
20
|
+
afterEach(function () {
|
|
21
|
+
consoleWarnMock === null || consoleWarnMock === void 0 ? void 0 : consoleWarnMock.mockRestore();
|
|
22
|
+
});
|
|
23
|
+
it('renders its children when sdk the init returns the sdk', function () {
|
|
24
|
+
var getByText = (0, react_1.render)((0, jsx_runtime_1.jsx)(SDKProvider_1.SDKProvider, { children: (0, jsx_runtime_1.jsx)("div", { children: "children" }) })).getByText;
|
|
25
|
+
expect(getByText('children')).toBeTruthy();
|
|
26
|
+
});
|
|
27
|
+
it('calls console warn after timeout if callback is not returning ', function () {
|
|
28
|
+
// @ts-ignore
|
|
29
|
+
app_sdk_1.init.mockImplementation(function () { });
|
|
30
|
+
(0, react_1.render)((0, jsx_runtime_1.jsx)(SDKProvider_1.SDKProvider, { children: (0, jsx_runtime_1.jsx)("div", { children: "children" }) }));
|
|
31
|
+
jest.runAllTimers();
|
|
32
|
+
expect(consoleWarnMock).toHaveBeenCalled();
|
|
33
|
+
});
|
|
34
|
+
});
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./SDKProvider"), exports);
|
|
18
|
+
__exportStar(require("./useCMA"), exports);
|
|
19
|
+
__exportStar(require("./useFieldValue"), exports);
|
|
20
|
+
__exportStar(require("./useSDK"), exports);
|
package/dist/useCMA.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { PlainClientAPI } from 'contentful-management';
|
|
2
|
+
/**
|
|
3
|
+
* React hook returning a CMA plain client instance.
|
|
4
|
+
* Must be used in the `SDKProvider` component. Will throw error, if called outside of `SDKProvider`.
|
|
5
|
+
*/
|
|
6
|
+
export declare function useCMA(): PlainClientAPI;
|
package/dist/useCMA.js
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.useCMA = void 0;
|
|
4
|
+
var contentful_management_1 = require("contentful-management");
|
|
5
|
+
var react_1 = require("react");
|
|
6
|
+
var useSDK_1 = require("./useSDK");
|
|
7
|
+
/**
|
|
8
|
+
* React hook returning a CMA plain client instance.
|
|
9
|
+
* Must be used in the `SDKProvider` component. Will throw error, if called outside of `SDKProvider`.
|
|
10
|
+
*/
|
|
11
|
+
function useCMA() {
|
|
12
|
+
var sdk = (0, useSDK_1.useSDK)();
|
|
13
|
+
var cma = (0, react_1.useMemo)(function () {
|
|
14
|
+
var _a;
|
|
15
|
+
return (0, contentful_management_1.createClient)({ apiAdapter: sdk.cmaAdapter }, {
|
|
16
|
+
type: 'plain',
|
|
17
|
+
defaults: {
|
|
18
|
+
environmentId: (_a = sdk.ids.environmentAlias) !== null && _a !== void 0 ? _a : sdk.ids.environment,
|
|
19
|
+
spaceId: sdk.ids.space,
|
|
20
|
+
},
|
|
21
|
+
});
|
|
22
|
+
}, [sdk]);
|
|
23
|
+
return cma;
|
|
24
|
+
}
|
|
25
|
+
exports.useCMA = useCMA;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __assign = (this && this.__assign) || function () {
|
|
3
|
+
__assign = Object.assign || function(t) {
|
|
4
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
5
|
+
s = arguments[i];
|
|
6
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
7
|
+
t[p] = s[p];
|
|
8
|
+
}
|
|
9
|
+
return t;
|
|
10
|
+
};
|
|
11
|
+
return __assign.apply(this, arguments);
|
|
12
|
+
};
|
|
13
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
|
+
var react_hooks_1 = require("@testing-library/react-hooks");
|
|
15
|
+
var useCMA_1 = require("./useCMA");
|
|
16
|
+
var mockedCma = 'mocked-cma';
|
|
17
|
+
var mockedSdk = {
|
|
18
|
+
cmaAdapter: 'placholder',
|
|
19
|
+
ids: {
|
|
20
|
+
environment: 'placeholder',
|
|
21
|
+
space: 'placeholder',
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
jest.mock('./useSDK', function () { return (__assign(__assign({}, jest.requireActual('./useSDK')), { useSDK: function () { return mockedSdk; } })); });
|
|
25
|
+
jest.mock('./SDKProvider', function () { return ({
|
|
26
|
+
SDKContext: {},
|
|
27
|
+
}); });
|
|
28
|
+
jest.mock('contentful-management', function () {
|
|
29
|
+
return __assign(__assign({}, jest.requireActual('contentful-management')), { createClient: function () { return mockedCma; } });
|
|
30
|
+
});
|
|
31
|
+
describe('useCMA', function () {
|
|
32
|
+
test('should return cma client', function () {
|
|
33
|
+
var result = (0, react_hooks_1.renderHook)(function () { return (0, useCMA_1.useCMA)(); }).result;
|
|
34
|
+
expect(result.current).toBe(mockedCma);
|
|
35
|
+
});
|
|
36
|
+
});
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { SerializedJSONValue } from '@contentful/app-sdk';
|
|
2
|
+
export declare type UseFieldValueReturnValue<Value = unknown> = [
|
|
3
|
+
value: Value | undefined,
|
|
4
|
+
setValue: (newValue: Value | undefined) => Promise<SerializedJSONValue | undefined>
|
|
5
|
+
];
|
|
6
|
+
/**
|
|
7
|
+
* Returns field value and a function to update it.
|
|
8
|
+
* Must be wrapped by SDKProvider.
|
|
9
|
+
* Can only be used when app is rendered in field, sidebar or entry editor location.
|
|
10
|
+
*
|
|
11
|
+
* @param {string=} fieldId Id of the field to read and update. Can be omitted when app is rendered in field location.
|
|
12
|
+
* @param {string=} locale Locale to read and update. When omitted, default locale is used.
|
|
13
|
+
* @returns {UseFieldValueReturnValue} Field value, function to update it
|
|
14
|
+
*/
|
|
15
|
+
export declare function useFieldValue<Value = unknown>(fieldId?: string, locale?: string): UseFieldValueReturnValue<Value>;
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
12
|
+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
13
|
+
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
14
|
+
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
15
|
+
function step(op) {
|
|
16
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
17
|
+
while (_) try {
|
|
18
|
+
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
19
|
+
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
20
|
+
switch (op[0]) {
|
|
21
|
+
case 0: case 1: t = op; break;
|
|
22
|
+
case 4: _.label++; return { value: op[1], done: false };
|
|
23
|
+
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
24
|
+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
25
|
+
default:
|
|
26
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
27
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
28
|
+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
29
|
+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
30
|
+
if (t[2]) _.ops.pop();
|
|
31
|
+
_.trys.pop(); continue;
|
|
32
|
+
}
|
|
33
|
+
op = body.call(thisArg, _);
|
|
34
|
+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
35
|
+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.useFieldValue = void 0;
|
|
40
|
+
var react_1 = require("react");
|
|
41
|
+
var useSDK_1 = require("./useSDK");
|
|
42
|
+
/**
|
|
43
|
+
* Returns field value and a function to update it.
|
|
44
|
+
* Must be wrapped by SDKProvider.
|
|
45
|
+
* Can only be used when app is rendered in field, sidebar or entry editor location.
|
|
46
|
+
*
|
|
47
|
+
* @param {string=} fieldId Id of the field to read and update. Can be omitted when app is rendered in field location.
|
|
48
|
+
* @param {string=} locale Locale to read and update. When omitted, default locale is used.
|
|
49
|
+
* @returns {UseFieldValueReturnValue} Field value, function to update it
|
|
50
|
+
*/
|
|
51
|
+
function useFieldValue(fieldId, locale) {
|
|
52
|
+
var _this = this;
|
|
53
|
+
var sdk = (0, useSDK_1.useSDK)();
|
|
54
|
+
var entryFieldApi = (0, react_1.useMemo)(function () { return getEntryFieldApi(sdk, fieldId); }, [sdk, fieldId]);
|
|
55
|
+
var localeWithDefault = locale !== null && locale !== void 0 ? locale : sdk.locales.default;
|
|
56
|
+
var _a = (0, react_1.useState)(entryFieldApi.getValue(localeWithDefault)), value = _a[0], setValue = _a[1];
|
|
57
|
+
(0, react_1.useEffect)(function () { return entryFieldApi.onValueChanged(localeWithDefault, setValue); }, [entryFieldApi, localeWithDefault]);
|
|
58
|
+
var updateValue = (0, react_1.useCallback)(function (newValue) { return __awaiter(_this, void 0, void 0, function () {
|
|
59
|
+
return __generator(this, function (_a) {
|
|
60
|
+
switch (_a.label) {
|
|
61
|
+
case 0:
|
|
62
|
+
setValue(newValue);
|
|
63
|
+
return [4 /*yield*/, entryFieldApi.setValue(newValue, localeWithDefault)];
|
|
64
|
+
case 1: return [2 /*return*/, _a.sent()];
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
}); }, [entryFieldApi, localeWithDefault]);
|
|
68
|
+
return [value, updateValue];
|
|
69
|
+
}
|
|
70
|
+
exports.useFieldValue = useFieldValue;
|
|
71
|
+
function getEntryFieldApi(sdk, fieldId) {
|
|
72
|
+
if (!('entry' in sdk)) {
|
|
73
|
+
throw new Error('`useFieldValue` can only be used in field, sidebar or entry editor location.');
|
|
74
|
+
}
|
|
75
|
+
var fieldIdWithDefault = fieldId !== null && fieldId !== void 0 ? fieldId : ('field' in sdk ? sdk.field.id : undefined);
|
|
76
|
+
if (!fieldIdWithDefault) {
|
|
77
|
+
throw new Error('Missing `fieldId`. The `fieldId` can only be omitted when your app is renderd in field location.');
|
|
78
|
+
}
|
|
79
|
+
var field = sdk.entry.fields[fieldIdWithDefault];
|
|
80
|
+
if (!field) {
|
|
81
|
+
throw new Error("Invalid `fieldId`. The current entry does not have a field \"".concat(fieldIdWithDefault, "\"."));
|
|
82
|
+
}
|
|
83
|
+
return field;
|
|
84
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __assign = (this && this.__assign) || function () {
|
|
3
|
+
__assign = Object.assign || function(t) {
|
|
4
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
5
|
+
s = arguments[i];
|
|
6
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
7
|
+
t[p] = s[p];
|
|
8
|
+
}
|
|
9
|
+
return t;
|
|
10
|
+
};
|
|
11
|
+
return __assign.apply(this, arguments);
|
|
12
|
+
};
|
|
13
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
14
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
15
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
16
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
17
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
18
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
19
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
20
|
+
});
|
|
21
|
+
};
|
|
22
|
+
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
23
|
+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
24
|
+
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
25
|
+
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
26
|
+
function step(op) {
|
|
27
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
28
|
+
while (_) try {
|
|
29
|
+
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
30
|
+
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
31
|
+
switch (op[0]) {
|
|
32
|
+
case 0: case 1: t = op; break;
|
|
33
|
+
case 4: _.label++; return { value: op[1], done: false };
|
|
34
|
+
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
35
|
+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
36
|
+
default:
|
|
37
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
38
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
39
|
+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
40
|
+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
41
|
+
if (t[2]) _.ops.pop();
|
|
42
|
+
_.trys.pop(); continue;
|
|
43
|
+
}
|
|
44
|
+
op = body.call(thisArg, _);
|
|
45
|
+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
46
|
+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
50
|
+
var react_hooks_1 = require("@testing-library/react-hooks");
|
|
51
|
+
var useFieldValue_1 = require("./useFieldValue");
|
|
52
|
+
var useSDK_1 = require("./useSDK");
|
|
53
|
+
var mockSDK = {
|
|
54
|
+
field: {
|
|
55
|
+
id: 'fieldId',
|
|
56
|
+
},
|
|
57
|
+
locales: {
|
|
58
|
+
default: 'defaultLocale',
|
|
59
|
+
},
|
|
60
|
+
entry: {
|
|
61
|
+
fields: {
|
|
62
|
+
fieldId: {
|
|
63
|
+
getValue: function (locale) { return "fieldId ".concat(locale, " value"); },
|
|
64
|
+
onValueChanged: jest.fn(),
|
|
65
|
+
setValue: jest.fn(),
|
|
66
|
+
},
|
|
67
|
+
otherFieldId: {
|
|
68
|
+
getValue: function (locale) { return "otherFieldId ".concat(locale, " value"); },
|
|
69
|
+
onValueChanged: jest.fn(),
|
|
70
|
+
setValue: jest.fn(),
|
|
71
|
+
},
|
|
72
|
+
},
|
|
73
|
+
},
|
|
74
|
+
};
|
|
75
|
+
jest.mock('./useSDK', function () { return (__assign(__assign({}, jest.requireActual('./useSDK')), { useSDK: jest.fn() })); });
|
|
76
|
+
var useSDKMock = useSDK_1.useSDK;
|
|
77
|
+
beforeEach(function () {
|
|
78
|
+
jest.resetAllMocks();
|
|
79
|
+
mockSDK.entry.fields.fieldId.onValueChanged.mockImplementation(function () { return function () { }; });
|
|
80
|
+
mockSDK.entry.fields.fieldId.setValue.mockImplementation(function () { return Promise.resolve('return value'); });
|
|
81
|
+
mockSDK.entry.fields.otherFieldId.onValueChanged.mockImplementation(function () { return function () { }; });
|
|
82
|
+
mockSDK.entry.fields.otherFieldId.setValue.mockImplementation(function () {
|
|
83
|
+
return Promise.resolve('other return value');
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
describe('useFieldValue', function () {
|
|
87
|
+
describe('throws error', function () {
|
|
88
|
+
it('when rendered in wrong location', function () {
|
|
89
|
+
useSDKMock.mockImplementation(function () { return ({}); });
|
|
90
|
+
var result = (0, react_hooks_1.renderHook)(function () { return (0, useFieldValue_1.useFieldValue)(); }).result;
|
|
91
|
+
expect(function () {
|
|
92
|
+
expect(result.current).not.toBe(undefined);
|
|
93
|
+
}).toThrowErrorMatchingInlineSnapshot("\"`useFieldValue` can only be used in field, sidebar or entry editor location.\"");
|
|
94
|
+
});
|
|
95
|
+
it('when rendered omitting `fieldId` outside of field location', function () {
|
|
96
|
+
// @ts-expect-error
|
|
97
|
+
useSDKMock.mockImplementation(function () { return ({
|
|
98
|
+
entry: mockSDK.entry,
|
|
99
|
+
}); });
|
|
100
|
+
var result = (0, react_hooks_1.renderHook)(function () { return (0, useFieldValue_1.useFieldValue)(); }).result;
|
|
101
|
+
expect(function () {
|
|
102
|
+
expect(result.current).not.toBe(undefined);
|
|
103
|
+
}).toThrowErrorMatchingInlineSnapshot("\"Missing `fieldId`. The `fieldId` can only be omitted when your app is renderd in field location.\"");
|
|
104
|
+
});
|
|
105
|
+
it('when providing unknown `fieldId`', function () {
|
|
106
|
+
// @ts-expect-error
|
|
107
|
+
useSDKMock.mockImplementation(function () { return mockSDK; });
|
|
108
|
+
var result = (0, react_hooks_1.renderHook)(function () { return (0, useFieldValue_1.useFieldValue)('unknownFieldId'); }).result;
|
|
109
|
+
expect(function () {
|
|
110
|
+
expect(result.current).not.toBe(undefined);
|
|
111
|
+
}).toThrowErrorMatchingInlineSnapshot("\"Invalid `fieldId`. The current entry does not have a field \\\"unknownFieldId\\\".\"");
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
describe('with no params', function () {
|
|
115
|
+
var result;
|
|
116
|
+
beforeEach(function () {
|
|
117
|
+
// @ts-expect-error
|
|
118
|
+
useSDKMock.mockImplementation(function () { return mockSDK; });
|
|
119
|
+
result = (0, react_hooks_1.renderHook)(function () { return (0, useFieldValue_1.useFieldValue)(); }).result;
|
|
120
|
+
});
|
|
121
|
+
it('returns initial value', function () {
|
|
122
|
+
expect(result.current[0]).toBe('fieldId defaultLocale value');
|
|
123
|
+
});
|
|
124
|
+
it('updates value', function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
125
|
+
return __generator(this, function (_a) {
|
|
126
|
+
switch (_a.label) {
|
|
127
|
+
case 0: return [4 /*yield*/, (0, react_hooks_1.act)(function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
128
|
+
return __generator(this, function (_a) {
|
|
129
|
+
switch (_a.label) {
|
|
130
|
+
case 0: return [4 /*yield*/, result.current[1]('new value')];
|
|
131
|
+
case 1:
|
|
132
|
+
_a.sent();
|
|
133
|
+
return [2 /*return*/];
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
}); })];
|
|
137
|
+
case 1:
|
|
138
|
+
_a.sent();
|
|
139
|
+
expect(result.current[0]).toBe('new value');
|
|
140
|
+
expect(mockSDK.entry.fields['fieldId'].setValue).toHaveBeenCalledWith('new value', 'defaultLocale');
|
|
141
|
+
return [2 /*return*/];
|
|
142
|
+
}
|
|
143
|
+
});
|
|
144
|
+
}); });
|
|
145
|
+
it('updates value when `onValueChanged` is called', function () {
|
|
146
|
+
var calls = mockSDK.entry.fields.fieldId.onValueChanged.mock.calls;
|
|
147
|
+
expect(calls[0][0]).toBe('defaultLocale');
|
|
148
|
+
(0, react_hooks_1.act)(function () { return calls[0][1]('new value'); });
|
|
149
|
+
expect(result.current[0]).toBe('new value');
|
|
150
|
+
});
|
|
151
|
+
it('returns the updated value', function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
152
|
+
var returnedValue;
|
|
153
|
+
return __generator(this, function (_a) {
|
|
154
|
+
switch (_a.label) {
|
|
155
|
+
case 0: return [4 /*yield*/, (0, react_hooks_1.act)(function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
156
|
+
return __generator(this, function (_a) {
|
|
157
|
+
switch (_a.label) {
|
|
158
|
+
case 0: return [4 /*yield*/, result.current[1]('new value')];
|
|
159
|
+
case 1:
|
|
160
|
+
returnedValue = _a.sent();
|
|
161
|
+
return [2 /*return*/];
|
|
162
|
+
}
|
|
163
|
+
});
|
|
164
|
+
}); })];
|
|
165
|
+
case 1:
|
|
166
|
+
_a.sent();
|
|
167
|
+
expect(returnedValue).toBe('return value');
|
|
168
|
+
return [2 /*return*/];
|
|
169
|
+
}
|
|
170
|
+
});
|
|
171
|
+
}); });
|
|
172
|
+
});
|
|
173
|
+
describe('with `fieldId`', function () {
|
|
174
|
+
var result;
|
|
175
|
+
beforeEach(function () {
|
|
176
|
+
// @ts-expect-error
|
|
177
|
+
useSDKMock.mockImplementation(function () { return mockSDK; });
|
|
178
|
+
result = (0, react_hooks_1.renderHook)(function () { return (0, useFieldValue_1.useFieldValue)('otherFieldId'); }).result;
|
|
179
|
+
});
|
|
180
|
+
it('returns initial value', function () {
|
|
181
|
+
expect(result.current[0]).toBe('otherFieldId defaultLocale value');
|
|
182
|
+
});
|
|
183
|
+
it('updates value', function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
184
|
+
return __generator(this, function (_a) {
|
|
185
|
+
switch (_a.label) {
|
|
186
|
+
case 0: return [4 /*yield*/, (0, react_hooks_1.act)(function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
187
|
+
return __generator(this, function (_a) {
|
|
188
|
+
switch (_a.label) {
|
|
189
|
+
case 0: return [4 /*yield*/, result.current[1]('new value')];
|
|
190
|
+
case 1:
|
|
191
|
+
_a.sent();
|
|
192
|
+
return [2 /*return*/];
|
|
193
|
+
}
|
|
194
|
+
});
|
|
195
|
+
}); })];
|
|
196
|
+
case 1:
|
|
197
|
+
_a.sent();
|
|
198
|
+
expect(result.current[0]).toBe('new value');
|
|
199
|
+
expect(mockSDK.entry.fields['otherFieldId'].setValue).toHaveBeenCalledWith('new value', 'defaultLocale');
|
|
200
|
+
return [2 /*return*/];
|
|
201
|
+
}
|
|
202
|
+
});
|
|
203
|
+
}); });
|
|
204
|
+
it('updates value when `onValueChanged` is called', function () {
|
|
205
|
+
var calls = mockSDK.entry.fields.otherFieldId.onValueChanged.mock.calls;
|
|
206
|
+
expect(calls[0][0]).toBe('defaultLocale');
|
|
207
|
+
(0, react_hooks_1.act)(function () { return calls[0][1]('new value'); });
|
|
208
|
+
expect(result.current[0]).toBe('new value');
|
|
209
|
+
});
|
|
210
|
+
});
|
|
211
|
+
describe('with `locale`', function () {
|
|
212
|
+
var result;
|
|
213
|
+
beforeEach(function () {
|
|
214
|
+
// @ts-expect-error
|
|
215
|
+
useSDKMock.mockImplementation(function () { return mockSDK; });
|
|
216
|
+
result = (0, react_hooks_1.renderHook)(function () { return (0, useFieldValue_1.useFieldValue)('fieldId', 'locale'); }).result;
|
|
217
|
+
});
|
|
218
|
+
it('returns initial value', function () {
|
|
219
|
+
expect(result.current[0]).toBe('fieldId locale value');
|
|
220
|
+
});
|
|
221
|
+
it('updates value', function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
222
|
+
return __generator(this, function (_a) {
|
|
223
|
+
switch (_a.label) {
|
|
224
|
+
case 0: return [4 /*yield*/, (0, react_hooks_1.act)(function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
225
|
+
return __generator(this, function (_a) {
|
|
226
|
+
switch (_a.label) {
|
|
227
|
+
case 0: return [4 /*yield*/, result.current[1]('new value')];
|
|
228
|
+
case 1:
|
|
229
|
+
_a.sent();
|
|
230
|
+
return [2 /*return*/];
|
|
231
|
+
}
|
|
232
|
+
});
|
|
233
|
+
}); })];
|
|
234
|
+
case 1:
|
|
235
|
+
_a.sent();
|
|
236
|
+
expect(result.current[0]).toBe('new value');
|
|
237
|
+
expect(mockSDK.entry.fields['fieldId'].setValue).toHaveBeenCalledWith('new value', 'locale');
|
|
238
|
+
return [2 /*return*/];
|
|
239
|
+
}
|
|
240
|
+
});
|
|
241
|
+
}); });
|
|
242
|
+
it('updates value when `onValueChanged` is called', function () {
|
|
243
|
+
var calls = mockSDK.entry.fields.fieldId.onValueChanged.mock.calls;
|
|
244
|
+
expect(calls[0][0]).toBe('locale');
|
|
245
|
+
(0, react_hooks_1.act)(function () { return calls[0][1]('new value'); });
|
|
246
|
+
expect(result.current[0]).toBe('new value');
|
|
247
|
+
});
|
|
248
|
+
});
|
|
249
|
+
});
|
package/dist/useSDK.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { KnownSDK } from '@contentful/app-sdk';
|
|
2
|
+
/**
|
|
3
|
+
* A react hook returning the App SDK.
|
|
4
|
+
* - The type of SDK varies depending on the location where it is used.
|
|
5
|
+
* - As it is depending on the context providing the SDK, the hook can only be used within the SDKProvider
|
|
6
|
+
*/
|
|
7
|
+
export declare function useSDK<SDK extends KnownSDK = KnownSDK>(): SDK;
|
package/dist/useSDK.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.useSDK = void 0;
|
|
4
|
+
var react_1 = require("react");
|
|
5
|
+
var SDKProvider_1 = require("./SDKProvider");
|
|
6
|
+
/**
|
|
7
|
+
* A react hook returning the App SDK.
|
|
8
|
+
* - The type of SDK varies depending on the location where it is used.
|
|
9
|
+
* - As it is depending on the context providing the SDK, the hook can only be used within the SDKProvider
|
|
10
|
+
*/
|
|
11
|
+
function useSDK() {
|
|
12
|
+
var sdk = (0, react_1.useContext)(SDKProvider_1.SDKContext).sdk;
|
|
13
|
+
if (!sdk) {
|
|
14
|
+
throw new Error('SDKContext not found. Make sure this hook is used inside the SDKProvider');
|
|
15
|
+
}
|
|
16
|
+
return sdk;
|
|
17
|
+
}
|
|
18
|
+
exports.useSDK = useSDK;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __assign = (this && this.__assign) || function () {
|
|
3
|
+
__assign = Object.assign || function(t) {
|
|
4
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
5
|
+
s = arguments[i];
|
|
6
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
7
|
+
t[p] = s[p];
|
|
8
|
+
}
|
|
9
|
+
return t;
|
|
10
|
+
};
|
|
11
|
+
return __assign.apply(this, arguments);
|
|
12
|
+
};
|
|
13
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
|
+
var react_hooks_1 = require("@testing-library/react-hooks");
|
|
15
|
+
var index_1 = require("./index");
|
|
16
|
+
var mockedSdk = 'mocked-sdk';
|
|
17
|
+
jest.mock('react', function () {
|
|
18
|
+
return __assign(__assign({}, jest.requireActual('react')), { useContext: function () { return ({ sdk: mockedSdk }); } });
|
|
19
|
+
});
|
|
20
|
+
jest.mock('./SDKProvider', function () { return ({
|
|
21
|
+
SDKContext: {},
|
|
22
|
+
}); });
|
|
23
|
+
describe('useSDK', function () {
|
|
24
|
+
test('should return the sdk from the context', function () {
|
|
25
|
+
var result = (0, react_hooks_1.renderHook)(function () { return (0, index_1.useSDK)(); }).result;
|
|
26
|
+
expect(result.current).toBe('mocked-sdk');
|
|
27
|
+
});
|
|
28
|
+
test('should throw when the sdk is not in context', function () {
|
|
29
|
+
mockedSdk = undefined;
|
|
30
|
+
var result = (0, react_hooks_1.renderHook)(function () { return (0, index_1.useSDK)(); }).result;
|
|
31
|
+
expect(function () {
|
|
32
|
+
expect(result.current).not.toBe(undefined);
|
|
33
|
+
}).toThrow();
|
|
34
|
+
});
|
|
35
|
+
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@contentful/react-apps-toolkit",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"description": "Toolkit for building a Contentful app in React",
|
|
5
5
|
"keywords": [],
|
|
6
6
|
"author": "Contentful GmbH",
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
37
|
"@testing-library/react": "^12.1.3",
|
|
38
|
-
"@testing-library/react-hooks": "^
|
|
38
|
+
"@testing-library/react-hooks": "^8.0.0",
|
|
39
39
|
"@types/jest": "^27.4.0",
|
|
40
40
|
"@types/react": "^17.0.39",
|
|
41
41
|
"jest": "^27.5.0",
|
|
@@ -50,5 +50,6 @@
|
|
|
50
50
|
"dependencies": {
|
|
51
51
|
"@contentful/app-sdk": "^4.0.0",
|
|
52
52
|
"contentful-management": ">=7.30.0"
|
|
53
|
-
}
|
|
53
|
+
},
|
|
54
|
+
"gitHead": "2d1dc051ed88de975125555694539a430be0126b"
|
|
54
55
|
}
|