@nascentdigital/funnel-cms 4.4.4
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/api/AssetClient.d.ts +53 -0
- package/dist/api/AssetClient.js +2 -0
- package/dist/api/AssetUploadClient.d.ts +17 -0
- package/dist/api/AssetUploadClient.js +26 -0
- package/dist/api/AuthClient.d.ts +29 -0
- package/dist/api/AuthClient.js +2 -0
- package/dist/api/ChangeSetClient.d.ts +84 -0
- package/dist/api/ChangeSetClient.js +31 -0
- package/dist/api/CollectionClient.d.ts +187 -0
- package/dist/api/CollectionClient.js +2 -0
- package/dist/api/ContentClient.d.ts +43 -0
- package/dist/api/ContentClient.js +34 -0
- package/dist/api/IAssetApiClient.d.ts +9 -0
- package/dist/api/IAssetApiClient.js +2 -0
- package/dist/api/PageClient.d.ts +264 -0
- package/dist/api/PageClient.js +2 -0
- package/dist/api/SiteClient.d.ts +23 -0
- package/dist/api/SiteClient.js +2 -0
- package/dist/api/SiteConfigClient.d.ts +26 -0
- package/dist/api/SiteConfigClient.js +2 -0
- package/dist/api/UpgradeClient.d.ts +16 -0
- package/dist/api/UpgradeClient.js +2 -0
- package/dist/api/UserClient.d.ts +46 -0
- package/dist/api/UserClient.js +2 -0
- package/dist/api/index.d.ts +11 -0
- package/dist/api/index.js +27 -0
- package/dist/errors/CMSError.d.ts +8 -0
- package/dist/errors/CMSError.js +17 -0
- package/dist/errors/CMSErrors.d.ts +5 -0
- package/dist/errors/CMSErrors.js +36 -0
- package/dist/errors/LinkedDependantsError.d.ts +21 -0
- package/dist/errors/LinkedDependantsError.js +31 -0
- package/dist/errors/LockdownError.d.ts +4 -0
- package/dist/errors/LockdownError.js +12 -0
- package/dist/errors/SlugValidationError.d.ts +21 -0
- package/dist/errors/SlugValidationError.js +23 -0
- package/dist/errors/TranslateReferencesError.d.ts +21 -0
- package/dist/errors/TranslateReferencesError.js +22 -0
- package/dist/errors/index.d.ts +4 -0
- package/dist/errors/index.js +25 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +19 -0
- package/dist/models/Entity.d.ts +14 -0
- package/dist/models/Entity.js +2 -0
- package/dist/models/Environment.d.ts +1 -0
- package/dist/models/Environment.js +2 -0
- package/dist/models/Pagination.d.ts +20 -0
- package/dist/models/Pagination.js +21 -0
- package/dist/models/Privilege.d.ts +57 -0
- package/dist/models/Privilege.js +163 -0
- package/dist/models/Role.d.ts +33 -0
- package/dist/models/Role.js +118 -0
- package/dist/models/SiteConfig.d.ts +14 -0
- package/dist/models/SiteConfig.js +2 -0
- package/dist/models/Upgrade.d.ts +40 -0
- package/dist/models/Upgrade.js +19 -0
- package/dist/models/User.d.ts +41 -0
- package/dist/models/User.js +71 -0
- package/dist/models/Versioned.d.ts +22 -0
- package/dist/models/Versioned.js +45 -0
- package/dist/models/index.d.ts +9 -0
- package/dist/models/index.js +25 -0
- package/dist/strapi/IStrapiContentClient.d.ts +39 -0
- package/dist/strapi/IStrapiContentClient.js +2 -0
- package/dist/strapi/Strapi.d.ts +37 -0
- package/dist/strapi/Strapi.js +156 -0
- package/dist/strapi/StrapiAssetClient.d.ts +11 -0
- package/dist/strapi/StrapiAssetClient.js +143 -0
- package/dist/strapi/StrapiAssetUploadClient.d.ts +6 -0
- package/dist/strapi/StrapiAssetUploadClient.js +109 -0
- package/dist/strapi/StrapiAuthClient.d.ts +9 -0
- package/dist/strapi/StrapiAuthClient.js +64 -0
- package/dist/strapi/StrapiChangeSetClient.d.ts +22 -0
- package/dist/strapi/StrapiChangeSetClient.js +218 -0
- package/dist/strapi/StrapiCollectionClient.d.ts +18 -0
- package/dist/strapi/StrapiCollectionClient.js +610 -0
- package/dist/strapi/StrapiContentClient.d.ts +38 -0
- package/dist/strapi/StrapiContentClient.js +105 -0
- package/dist/strapi/StrapiContentClientFactory.d.ts +13 -0
- package/dist/strapi/StrapiContentClientFactory.js +19 -0
- package/dist/strapi/StrapiPageClient.d.ts +23 -0
- package/dist/strapi/StrapiPageClient.js +882 -0
- package/dist/strapi/StrapiSiteConfigClient.d.ts +8 -0
- package/dist/strapi/StrapiSiteConfigClient.js +50 -0
- package/dist/strapi/StrapiUpgradeClient.d.ts +13 -0
- package/dist/strapi/StrapiUpgradeClient.js +118 -0
- package/dist/strapi/StrapiUserClient.d.ts +17 -0
- package/dist/strapi/StrapiUserClient.js +199 -0
- package/dist/strapi/client.d.ts +1 -0
- package/dist/strapi/client.js +17 -0
- package/dist/strapi/index.d.ts +3 -0
- package/dist/strapi/index.js +19 -0
- package/dist/strapi/models/StrapiAsset.d.ts +10 -0
- package/dist/strapi/models/StrapiAsset.js +16 -0
- package/dist/strapi/models/StrapiData.d.ts +13 -0
- package/dist/strapi/models/StrapiData.js +16 -0
- package/dist/strapi/models/StrapiFile.d.ts +18 -0
- package/dist/strapi/models/StrapiFile.js +2 -0
- package/dist/strapi/models/index.d.ts +3 -0
- package/dist/strapi/models/index.js +19 -0
- package/dist/strapi/serialization/ChangeSetData.d.ts +15 -0
- package/dist/strapi/serialization/ChangeSetData.js +76 -0
- package/dist/strapi/serialization/CollectionData.d.ts +57 -0
- package/dist/strapi/serialization/CollectionData.js +258 -0
- package/dist/strapi/serialization/CollectionSnapshotData.d.ts +16 -0
- package/dist/strapi/serialization/CollectionSnapshotData.js +66 -0
- package/dist/strapi/serialization/PageData.d.ts +126 -0
- package/dist/strapi/serialization/PageData.js +335 -0
- package/dist/strapi/serialization/PageSnapshotData.d.ts +20 -0
- package/dist/strapi/serialization/PageSnapshotData.js +69 -0
- package/dist/strapi/serialization/RoleData.d.ts +5 -0
- package/dist/strapi/serialization/RoleData.js +2 -0
- package/dist/strapi/serialization/SiteConfigData.d.ts +11 -0
- package/dist/strapi/serialization/SiteConfigData.js +23 -0
- package/dist/strapi/serialization/StrapiAssetData.d.ts +17 -0
- package/dist/strapi/serialization/StrapiAssetData.js +39 -0
- package/dist/strapi/serialization/UserData.d.ts +18 -0
- package/dist/strapi/serialization/UserData.js +42 -0
- package/dist/strapi/serialization/VersionData.d.ts +26 -0
- package/dist/strapi/serialization/VersionData.js +88 -0
- package/dist/strapi/serialization/index.d.ts +10 -0
- package/dist/strapi/serialization/index.js +26 -0
- package/dist/strapi/test.d.ts +563 -0
- package/dist/strapi/test.js +1131 -0
- package/package.json +42 -0
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { SiteConfigClient } from '../api';
|
|
2
|
+
import type { IStrapiContentClient } from './IStrapiContentClient';
|
|
3
|
+
export declare class StrapiSiteConfigClient implements SiteConfigClient {
|
|
4
|
+
private readonly provider;
|
|
5
|
+
constructor(provider: IStrapiContentClient);
|
|
6
|
+
get({ brand }: SiteConfigClient.Get.Args): Promise<SiteConfigClient.Get.Result>;
|
|
7
|
+
update({ id, ...update }: SiteConfigClient.Update.Args): Promise<SiteConfigClient.Update.Result>;
|
|
8
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
3
|
+
var t = {};
|
|
4
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
5
|
+
t[p] = s[p];
|
|
6
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
7
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
8
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
9
|
+
t[p[i]] = s[p[i]];
|
|
10
|
+
}
|
|
11
|
+
return t;
|
|
12
|
+
};
|
|
13
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
|
+
exports.StrapiSiteConfigClient = void 0;
|
|
15
|
+
const serialization_1 = require("./serialization");
|
|
16
|
+
// client extension
|
|
17
|
+
class StrapiSiteConfigClient {
|
|
18
|
+
constructor(provider) {
|
|
19
|
+
this.provider = provider;
|
|
20
|
+
}
|
|
21
|
+
async get({ brand }) {
|
|
22
|
+
// fetch data
|
|
23
|
+
const client = this.provider.client;
|
|
24
|
+
const collection = client.collection('sites');
|
|
25
|
+
let { data: [data] } = await collection.find({
|
|
26
|
+
filters: { brand: { $eq: brand } },
|
|
27
|
+
pagination: {
|
|
28
|
+
start: 0,
|
|
29
|
+
limit: 1
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
// or create if it doesn't exist
|
|
33
|
+
if (!data) {
|
|
34
|
+
const { data: newData } = await collection.create(serialization_1.SiteConfigData.serialize({ brand, lockdownEditor: false }));
|
|
35
|
+
data = newData;
|
|
36
|
+
}
|
|
37
|
+
// return config
|
|
38
|
+
return serialization_1.SiteConfigData.deserialize(data);
|
|
39
|
+
}
|
|
40
|
+
async update(_a) {
|
|
41
|
+
var { id } = _a, update = __rest(_a, ["id"]);
|
|
42
|
+
// fetch data
|
|
43
|
+
const client = this.provider.client;
|
|
44
|
+
const collection = client.collection('sites');
|
|
45
|
+
const { data } = await collection.update(id, serialization_1.SiteConfigData.serialize(update));
|
|
46
|
+
// return config
|
|
47
|
+
return serialization_1.SiteConfigData.deserialize(data);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
exports.StrapiSiteConfigClient = StrapiSiteConfigClient;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { UpgradeClient } from '../api';
|
|
2
|
+
import { Upgrade } from '../models';
|
|
3
|
+
import type { StrapiContentClient } from './StrapiContentClient';
|
|
4
|
+
export declare class StrapiUpgradeClient implements UpgradeClient {
|
|
5
|
+
private readonly contentClient;
|
|
6
|
+
readonly cmsVersion: Upgrade.Version;
|
|
7
|
+
private readonly upgrades;
|
|
8
|
+
private readonly versions;
|
|
9
|
+
constructor(contentClient: StrapiContentClient);
|
|
10
|
+
status(): Promise<Upgrade.Status>;
|
|
11
|
+
private getCmsVersion;
|
|
12
|
+
upgrade(): Promise<Upgrade.Status>;
|
|
13
|
+
}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.StrapiUpgradeClient = void 0;
|
|
4
|
+
const serialization_1 = require("./serialization");
|
|
5
|
+
// class
|
|
6
|
+
class StrapiUpgradeClient {
|
|
7
|
+
constructor(contentClient) {
|
|
8
|
+
this.contentClient = contentClient;
|
|
9
|
+
this.cmsVersion = 3;
|
|
10
|
+
// initialize upgrades (needs to be ordered from oldest -> latest)
|
|
11
|
+
this.upgrades = [];
|
|
12
|
+
// versions (need to be sorted reversed from upgrades, latest -> oldest)
|
|
13
|
+
this.versions = this.upgrades.map(upgrade => upgrade.version).reverse();
|
|
14
|
+
}
|
|
15
|
+
async status() {
|
|
16
|
+
// query version info
|
|
17
|
+
const [versionsResult, dbReady] = await Promise.all([
|
|
18
|
+
// fetch latest version
|
|
19
|
+
this.contentClient.client.collection('versions').find({
|
|
20
|
+
sort: ['version:desc']
|
|
21
|
+
}),
|
|
22
|
+
// fetch server version
|
|
23
|
+
this.getCmsVersion()
|
|
24
|
+
.then(version => version === this.cmsVersion)
|
|
25
|
+
]);
|
|
26
|
+
// return status from version
|
|
27
|
+
return serialization_1.VersionData.deserialize(versionsResult.data, this.versions, dbReady);
|
|
28
|
+
}
|
|
29
|
+
async getCmsVersion() {
|
|
30
|
+
try {
|
|
31
|
+
// send request to get version
|
|
32
|
+
const { client, token } = this.contentClient;
|
|
33
|
+
const url = new URL('/api/funnel/version', client.baseURL);
|
|
34
|
+
const response = await fetch(url.href, {
|
|
35
|
+
headers: {
|
|
36
|
+
Authorization: `Bearer ${token}`
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
// return undefined if api call failed
|
|
40
|
+
if (!response.ok) {
|
|
41
|
+
console.warn('[StrapiUpgradeClient/getCmsVersion] failed to get version', response.statusText);
|
|
42
|
+
return undefined;
|
|
43
|
+
}
|
|
44
|
+
// deserialize result
|
|
45
|
+
const data = await response.json();
|
|
46
|
+
return Number.parseInt(data);
|
|
47
|
+
}
|
|
48
|
+
catch (e) {
|
|
49
|
+
console.warn('[StrapiUpgradeClient/getCmsVersion] failed to get version', e);
|
|
50
|
+
return undefined;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
async upgrade() {
|
|
54
|
+
var _a;
|
|
55
|
+
// check status (fail if active/complete)
|
|
56
|
+
const status = await this.status();
|
|
57
|
+
switch (status.status) {
|
|
58
|
+
case 'upgrading':
|
|
59
|
+
case 'up-to-date':
|
|
60
|
+
return status;
|
|
61
|
+
}
|
|
62
|
+
// track existing status if we're retrying something that's failed
|
|
63
|
+
const retryVersion = status.status === 'failed'
|
|
64
|
+
? status.failed
|
|
65
|
+
: undefined;
|
|
66
|
+
// try to upgrade all versions
|
|
67
|
+
const statusCollection = this.contentClient.client.collection('versions');
|
|
68
|
+
let lastUpgrade;
|
|
69
|
+
let lastStatusId;
|
|
70
|
+
try {
|
|
71
|
+
// start upgrades
|
|
72
|
+
const currentVersion = status.current;
|
|
73
|
+
for (const upgrade of this.upgrades) {
|
|
74
|
+
// skip if already installed
|
|
75
|
+
if (currentVersion !== undefined && upgrade.version <= currentVersion) {
|
|
76
|
+
console.debug(`[Upgrader] ignoring previously installed v${upgrade.version}`);
|
|
77
|
+
// skip
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
// track upgrade
|
|
81
|
+
lastUpgrade = upgrade;
|
|
82
|
+
// update existing status if it had previously failed
|
|
83
|
+
let statusId;
|
|
84
|
+
if (upgrade.version === retryVersion && status.status === 'failed') {
|
|
85
|
+
statusId = status.id;
|
|
86
|
+
await statusCollection.update(statusId, serialization_1.VersionData.serializeUpdate({ status: 'upgrading' }));
|
|
87
|
+
}
|
|
88
|
+
// or create a new version entry
|
|
89
|
+
else {
|
|
90
|
+
const { data } = await statusCollection.create(serialization_1.VersionData.serializeCreate({
|
|
91
|
+
version: upgrade.version,
|
|
92
|
+
status: 'upgrading'
|
|
93
|
+
}));
|
|
94
|
+
statusId = data.documentId;
|
|
95
|
+
}
|
|
96
|
+
// track upgrade status id (required for error handling below)
|
|
97
|
+
lastStatusId = statusId;
|
|
98
|
+
// run upgrade
|
|
99
|
+
await upgrade.execute();
|
|
100
|
+
// mark as complete if we made it here
|
|
101
|
+
lastStatusId = undefined;
|
|
102
|
+
await statusCollection.update(statusId, serialization_1.VersionData.serializeUpdate({ status: 'up-to-date' }));
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
// handler error
|
|
106
|
+
catch (e) {
|
|
107
|
+
// log issue
|
|
108
|
+
console.error(`[Upgrader] upgrade for v${(_a = lastUpgrade === null || lastUpgrade === void 0 ? void 0 : lastUpgrade.version) !== null && _a !== void 0 ? _a : '?'} failed`, e);
|
|
109
|
+
// persist failure (if possible)
|
|
110
|
+
if (lastStatusId) {
|
|
111
|
+
await statusCollection.update(lastStatusId, serialization_1.VersionData.serializeUpdate({ status: 'failed' }));
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
// return a final status
|
|
115
|
+
return this.status();
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
exports.StrapiUpgradeClient = StrapiUpgradeClient;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { IncomingWebhook } from '@slack/webhook';
|
|
2
|
+
import type { UserClient } from '../api';
|
|
3
|
+
import type { IStrapiContentClient } from './IStrapiContentClient';
|
|
4
|
+
export declare class StrapiUserClient implements UserClient {
|
|
5
|
+
private readonly provider;
|
|
6
|
+
private readonly slack;
|
|
7
|
+
constructor(provider: IStrapiContentClient, slack: IncomingWebhook | undefined);
|
|
8
|
+
me(): Promise<UserClient.Me.Result>;
|
|
9
|
+
getUsers(args?: UserClient.GetUsers.Args): Promise<UserClient.GetUsers.Result>;
|
|
10
|
+
getUser(id: UserClient.GetUser.Args): Promise<UserClient.GetUser.Result>;
|
|
11
|
+
createUser({ password, ...user }: UserClient.CreateUser.Args): Promise<UserClient.CreateUser.Result>;
|
|
12
|
+
updateUser({ id, password, ...user }: UserClient.UpdateUser.Args): Promise<UserClient.UpdateUser.Result>;
|
|
13
|
+
resetUser({ email }: UserClient.ResetUser.Args): Promise<UserClient.ResetUser.Result>;
|
|
14
|
+
deleteUser(id: UserClient.DeleteUser.Args): Promise<UserClient.DeleteUser.Result>;
|
|
15
|
+
private getRoles;
|
|
16
|
+
private getLegacyId;
|
|
17
|
+
}
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
3
|
+
var t = {};
|
|
4
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
5
|
+
t[p] = s[p];
|
|
6
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
7
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
8
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
9
|
+
t[p[i]] = s[p[i]];
|
|
10
|
+
}
|
|
11
|
+
return t;
|
|
12
|
+
};
|
|
13
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
14
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.StrapiUserClient = void 0;
|
|
18
|
+
const funnel_core_1 = require("@nascentdigital/funnel-core");
|
|
19
|
+
const crypto_1 = __importDefault(require("crypto"));
|
|
20
|
+
const serialization_1 = require("./serialization");
|
|
21
|
+
// class
|
|
22
|
+
class StrapiUserClient {
|
|
23
|
+
constructor(provider, slack) {
|
|
24
|
+
this.provider = provider;
|
|
25
|
+
this.slack = slack;
|
|
26
|
+
}
|
|
27
|
+
async me() {
|
|
28
|
+
return this.provider.auth.identify(this.provider.token);
|
|
29
|
+
}
|
|
30
|
+
async getUsers(args = {}) {
|
|
31
|
+
// fetch all users
|
|
32
|
+
const users = this.provider.client.collection('users');
|
|
33
|
+
const result = await users.find({
|
|
34
|
+
populate: '*',
|
|
35
|
+
filters: args && args.brand
|
|
36
|
+
? { brands: { $contains: `"${args.brand}"` } }
|
|
37
|
+
: undefined
|
|
38
|
+
});
|
|
39
|
+
// NOTE: strapi types are different for users for some reason
|
|
40
|
+
const usersData = result;
|
|
41
|
+
// return as users
|
|
42
|
+
return usersData.map(serialization_1.UserData.deserialize);
|
|
43
|
+
}
|
|
44
|
+
async getUser(id) {
|
|
45
|
+
// users collection
|
|
46
|
+
const users = this.provider.client.collection('users');
|
|
47
|
+
// get legacy id of user (users collection uses legacy id still)
|
|
48
|
+
const legacyId = await this.getLegacyId(id);
|
|
49
|
+
// find user by legacy id
|
|
50
|
+
const result = await users.findOne(legacyId, { populate: '*' });
|
|
51
|
+
// NOTE: strapi types are different for users for some reason
|
|
52
|
+
const userData = result;
|
|
53
|
+
// return user transformed
|
|
54
|
+
return userData
|
|
55
|
+
? serialization_1.UserData.deserialize(userData)
|
|
56
|
+
: undefined;
|
|
57
|
+
}
|
|
58
|
+
async createUser(_a) {
|
|
59
|
+
var { password } = _a, user = __rest(_a, ["password"]);
|
|
60
|
+
// get user roles data for serializing (need the role id)
|
|
61
|
+
const rolesData = await this.getRoles();
|
|
62
|
+
// serialize user
|
|
63
|
+
// set a random password (strapi throws error otherwise), and set user to confirmed by default
|
|
64
|
+
const serializedUser = Object.assign(Object.assign({}, serialization_1.UserData.serialize(user, rolesData)), { password: password !== null && password !== void 0 ? password : crypto_1.default.randomBytes(32).toString('hex'), confirmed: true });
|
|
65
|
+
// fetch user list
|
|
66
|
+
const users = await this.getUsers();
|
|
67
|
+
// throw ConflictError if username or email is already used
|
|
68
|
+
for (const existingUser of users) {
|
|
69
|
+
if (existingUser.username === serializedUser.username ||
|
|
70
|
+
existingUser.email === serializedUser.email) {
|
|
71
|
+
throw new funnel_core_1.ConflictError('Username or email is already used');
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
// create user
|
|
75
|
+
// NOTE: strapi client users collections doesn't work for creating
|
|
76
|
+
const { client } = this.provider;
|
|
77
|
+
const response = await client.fetch(`/users`, {
|
|
78
|
+
method: 'POST',
|
|
79
|
+
headers: {
|
|
80
|
+
Authorization: `Bearer ${this.provider.token}`,
|
|
81
|
+
'Content-Type': 'application/json',
|
|
82
|
+
},
|
|
83
|
+
body: JSON.stringify(serializedUser)
|
|
84
|
+
});
|
|
85
|
+
// user data is at the root of response
|
|
86
|
+
const userData = await response.json();
|
|
87
|
+
// return user
|
|
88
|
+
return serialization_1.UserData.deserialize(userData);
|
|
89
|
+
}
|
|
90
|
+
async updateUser(_a) {
|
|
91
|
+
var { id, password } = _a, user = __rest(_a, ["id", "password"]);
|
|
92
|
+
// get legacy id of user (users collection uses legacy id still)
|
|
93
|
+
const legacyId = await this.getLegacyId(id);
|
|
94
|
+
// get user roles data for serializing (need the role id)
|
|
95
|
+
const rolesData = await this.getRoles();
|
|
96
|
+
// serialize user
|
|
97
|
+
const serializedUser = serialization_1.UserData.serialize(user, rolesData);
|
|
98
|
+
if (password) {
|
|
99
|
+
serializedUser.password = password;
|
|
100
|
+
}
|
|
101
|
+
console.debug('[StrapiUserClient/updateUser] updating user with:', serializedUser);
|
|
102
|
+
// update user by legacy id
|
|
103
|
+
// NOTE: strapi client users collections don't work for updating
|
|
104
|
+
const { client } = this.provider;
|
|
105
|
+
const response = await client.fetch(`/users/${legacyId}`, {
|
|
106
|
+
method: 'PUT',
|
|
107
|
+
headers: {
|
|
108
|
+
Authorization: `Bearer ${this.provider.token}`,
|
|
109
|
+
'Content-Type': 'application/json',
|
|
110
|
+
},
|
|
111
|
+
body: JSON.stringify(serializedUser)
|
|
112
|
+
});
|
|
113
|
+
// user data is at the root of response
|
|
114
|
+
const userData = await response.json();
|
|
115
|
+
// return user
|
|
116
|
+
return serialization_1.UserData.deserialize(userData);
|
|
117
|
+
}
|
|
118
|
+
async resetUser({ email }) {
|
|
119
|
+
// try to send request
|
|
120
|
+
try {
|
|
121
|
+
// just log if there's no webhook
|
|
122
|
+
const { slack } = this;
|
|
123
|
+
if (!slack) {
|
|
124
|
+
console.debug('[UserClient] requesting password reset for', email);
|
|
125
|
+
}
|
|
126
|
+
// or send via slack
|
|
127
|
+
else {
|
|
128
|
+
await slack.send({
|
|
129
|
+
text: `A password reset has been requested for ${email}`,
|
|
130
|
+
blocks: [
|
|
131
|
+
{
|
|
132
|
+
type: 'section',
|
|
133
|
+
text: {
|
|
134
|
+
type: 'mrkdwn',
|
|
135
|
+
text: `A password reset has been requested for \`${email}\`.`
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
]
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
// handle error
|
|
143
|
+
catch (e) {
|
|
144
|
+
throw new funnel_core_1.DependencyError('Unable to communicate with Slack server');
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
async deleteUser(id) {
|
|
148
|
+
// get legacy id of user (users collection uses legacy id still)
|
|
149
|
+
const legacyId = await this.getLegacyId(id);
|
|
150
|
+
const { client } = this.provider;
|
|
151
|
+
// dekete user by legacy id
|
|
152
|
+
// NOTE: strapi client users collections don't work for deleting
|
|
153
|
+
const response = await client.fetch(`/users/${legacyId}`, {
|
|
154
|
+
method: 'DELETE',
|
|
155
|
+
headers: {
|
|
156
|
+
Authorization: `Bearer ${this.provider.token}`,
|
|
157
|
+
'Content-Type': 'application/json',
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
// throw if operation failed
|
|
161
|
+
if (!response.ok) {
|
|
162
|
+
throw new funnel_core_1.ServerError('Failed to delete user:' + response.statusText);
|
|
163
|
+
}
|
|
164
|
+
// or return success
|
|
165
|
+
return true;
|
|
166
|
+
}
|
|
167
|
+
async getRoles() {
|
|
168
|
+
// get roles
|
|
169
|
+
const { client } = this.provider;
|
|
170
|
+
const response = await client.fetch('/users-permissions/roles', {
|
|
171
|
+
method: 'GET',
|
|
172
|
+
headers: {
|
|
173
|
+
Authorization: `Bearer ${this.provider.token}`
|
|
174
|
+
}
|
|
175
|
+
});
|
|
176
|
+
// return roles data
|
|
177
|
+
const { roles } = await response.json();
|
|
178
|
+
return roles;
|
|
179
|
+
}
|
|
180
|
+
async getLegacyId(documentId) {
|
|
181
|
+
// search for user by document id
|
|
182
|
+
const users = this.provider.client.collection('users');
|
|
183
|
+
const result = await users.find({
|
|
184
|
+
filters: {
|
|
185
|
+
documentId
|
|
186
|
+
},
|
|
187
|
+
fields: ['id']
|
|
188
|
+
});
|
|
189
|
+
// NOTE: strapi types are different for users for some reason
|
|
190
|
+
const usersData = result;
|
|
191
|
+
// there should only be one result, throw if not
|
|
192
|
+
if (usersData.length !== 1) {
|
|
193
|
+
throw new Error(`Could not get legacy id for user "${documentId}"`);
|
|
194
|
+
}
|
|
195
|
+
// return the legacy id as string
|
|
196
|
+
return usersData[0].id.toString();
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
exports.StrapiUserClient = StrapiUserClient;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './StrapiAssetUploadClient';
|
|
@@ -0,0 +1,17 @@
|
|
|
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("./StrapiAssetUploadClient"), exports);
|
|
@@ -0,0 +1,19 @@
|
|
|
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("./Strapi"), exports);
|
|
18
|
+
__exportStar(require("./StrapiContentClient"), exports);
|
|
19
|
+
__exportStar(require("./StrapiContentClientFactory"), exports);
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Schema } from '@nascentdigital/funnel-core';
|
|
2
|
+
import { Entity } from '../../models';
|
|
3
|
+
export type StrapiAsset = Entity.Extend<Schema.AssetField.LinkedValue, StrapiAsset.Data>;
|
|
4
|
+
export declare namespace StrapiAsset {
|
|
5
|
+
type Data = {
|
|
6
|
+
assetId: number;
|
|
7
|
+
fileId?: number;
|
|
8
|
+
};
|
|
9
|
+
function filter(value: any): value is StrapiAsset;
|
|
10
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.StrapiAsset = void 0;
|
|
4
|
+
const funnel_core_1 = require("@nascentdigital/funnel-core");
|
|
5
|
+
// extension
|
|
6
|
+
var StrapiAsset;
|
|
7
|
+
(function (StrapiAsset) {
|
|
8
|
+
// helpers
|
|
9
|
+
function filter(value) {
|
|
10
|
+
return funnel_core_1.Schema.AssetField.LinkedValue.filter(value)
|
|
11
|
+
&& '__internal' in value && typeof value.__internal === 'object'
|
|
12
|
+
&& !!value.__internal && !Array.isArray(value.__internal)
|
|
13
|
+
&& 'assetId' in value.__internal && typeof value.__internal.assetId === 'number';
|
|
14
|
+
}
|
|
15
|
+
StrapiAsset.filter = filter;
|
|
16
|
+
})(StrapiAsset || (exports.StrapiAsset = StrapiAsset = {}));
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { JsonObject } from 'type-fest';
|
|
2
|
+
import type { Entity } from '../../models';
|
|
3
|
+
export type StrapiData = {
|
|
4
|
+
id: number;
|
|
5
|
+
documentId: string;
|
|
6
|
+
createdAt: string;
|
|
7
|
+
updatedAt: string | null;
|
|
8
|
+
publishedAt: string | null;
|
|
9
|
+
};
|
|
10
|
+
export declare namespace StrapiData {
|
|
11
|
+
type Keys = keyof StrapiData;
|
|
12
|
+
function deserialize<TId, TInternal extends JsonObject = JsonObject>(data: StrapiData, internal?: Omit<TInternal, 'id'>): Entity<TId, TInternal>;
|
|
13
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.StrapiData = void 0;
|
|
4
|
+
// extension
|
|
5
|
+
var StrapiData;
|
|
6
|
+
(function (StrapiData) {
|
|
7
|
+
// helper
|
|
8
|
+
function deserialize(data, internal) {
|
|
9
|
+
var _a;
|
|
10
|
+
return {
|
|
11
|
+
__internal: Object.assign({ id: data.id }, ((_a = internal) !== null && _a !== void 0 ? _a : {})),
|
|
12
|
+
id: data.documentId
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
StrapiData.deserialize = deserialize;
|
|
16
|
+
})(StrapiData || (exports.StrapiData = StrapiData = {}));
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { MimeType } from '@nascentdigital/funnel-core';
|
|
2
|
+
import { StrapiData } from './StrapiData';
|
|
3
|
+
export type StrapiFile = StrapiData & StrapiFile.Base & {
|
|
4
|
+
formats: Record<StrapiFile.Size, StrapiFile.Base> | null;
|
|
5
|
+
};
|
|
6
|
+
export declare namespace StrapiFile {
|
|
7
|
+
type Base = {
|
|
8
|
+
name: string;
|
|
9
|
+
hash: string;
|
|
10
|
+
url: string;
|
|
11
|
+
ext: string;
|
|
12
|
+
mime: MimeType;
|
|
13
|
+
width: number | null;
|
|
14
|
+
height: number | null;
|
|
15
|
+
size: number;
|
|
16
|
+
};
|
|
17
|
+
type Size = 'thumbnail' | 'small' | 'medium' | 'large';
|
|
18
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
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("./StrapiAsset"), exports);
|
|
18
|
+
__exportStar(require("./StrapiData"), exports);
|
|
19
|
+
__exportStar(require("./StrapiFile"), exports);
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Schema } from '@nascentdigital/funnel-core';
|
|
2
|
+
import { StrapiData } from '../models';
|
|
3
|
+
export type ChangeSetData = StrapiData & {
|
|
4
|
+
brand: string;
|
|
5
|
+
groupId: Schema.ChangeSet.GroupId | null;
|
|
6
|
+
name: string;
|
|
7
|
+
changes: Schema.ChangeSet.Change[];
|
|
8
|
+
errors: boolean;
|
|
9
|
+
publishedOn: string | null;
|
|
10
|
+
};
|
|
11
|
+
export declare namespace ChangeSetData {
|
|
12
|
+
function deserialize(data: ChangeSetData): Schema.ChangeSet.Data;
|
|
13
|
+
type Update = Omit<ChangeSetData, StrapiData.Keys>;
|
|
14
|
+
function serialize(changeSet: Schema.ChangeSet.Data.New | Schema.ChangeSet.Data): Update;
|
|
15
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ChangeSetData = void 0;
|
|
4
|
+
const funnel_core_1 = require("@nascentdigital/funnel-core");
|
|
5
|
+
const models_1 = require("../models");
|
|
6
|
+
// extension
|
|
7
|
+
var ChangeSetData;
|
|
8
|
+
(function (ChangeSetData) {
|
|
9
|
+
// deserialize (handles all cases safely)
|
|
10
|
+
function deserialize(data) {
|
|
11
|
+
var _a, _b;
|
|
12
|
+
// create output
|
|
13
|
+
const changeSet = Object.assign({}, models_1.StrapiData.deserialize(data));
|
|
14
|
+
const createdOn = Date.parse(data.createdAt);
|
|
15
|
+
const updatedOn = data.updatedAt ? Date.parse(data.updatedAt) : createdOn;
|
|
16
|
+
// bind required props to changeset
|
|
17
|
+
for (const prop of funnel_core_1.Schema.ChangeSet.Data.props) {
|
|
18
|
+
switch (prop) {
|
|
19
|
+
// handled by base
|
|
20
|
+
case 'id':
|
|
21
|
+
break;
|
|
22
|
+
// direct transforms
|
|
23
|
+
case 'brand':
|
|
24
|
+
case 'groupId':
|
|
25
|
+
case 'name':
|
|
26
|
+
case 'errors':
|
|
27
|
+
changeSet[prop] = (_a = data[prop]) !== null && _a !== void 0 ? _a : undefined;
|
|
28
|
+
break;
|
|
29
|
+
// content
|
|
30
|
+
case 'changes':
|
|
31
|
+
changeSet[prop] = (_b = data[prop]) !== null && _b !== void 0 ? _b : {
|
|
32
|
+
pages: {},
|
|
33
|
+
collections: {},
|
|
34
|
+
assets: {}
|
|
35
|
+
};
|
|
36
|
+
break;
|
|
37
|
+
// timestamps
|
|
38
|
+
case 'createdOn':
|
|
39
|
+
changeSet.createdOn = createdOn;
|
|
40
|
+
break;
|
|
41
|
+
case 'updatedOn':
|
|
42
|
+
changeSet.updatedOn = updatedOn;
|
|
43
|
+
break;
|
|
44
|
+
case 'publishedOn':
|
|
45
|
+
changeSet.publishedOn = data.publishedOn
|
|
46
|
+
? parseInt(data.publishedOn)
|
|
47
|
+
: undefined;
|
|
48
|
+
break;
|
|
49
|
+
// unhandled
|
|
50
|
+
default:
|
|
51
|
+
throw new funnel_core_1.NotImplementedError(`Missing support for transforming ChangeSet "${prop}" prop`);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
// return change set
|
|
55
|
+
return changeSet;
|
|
56
|
+
}
|
|
57
|
+
ChangeSetData.deserialize = deserialize;
|
|
58
|
+
function serialize(changeSet) {
|
|
59
|
+
var _a, _b, _c, _d, _e, _f;
|
|
60
|
+
// serialize base changeset data
|
|
61
|
+
const base = {
|
|
62
|
+
brand: changeSet.brand,
|
|
63
|
+
groupId: (_a = changeSet.groupId) !== null && _a !== void 0 ? _a : null,
|
|
64
|
+
name: (_b = changeSet.name) !== null && _b !== void 0 ? _b : (changeSet.groupId ? funnel_core_1.StringUtils.capitalize(changeSet.groupId) : 'Default')
|
|
65
|
+
};
|
|
66
|
+
// serialize existing changeset
|
|
67
|
+
if ('id' in changeSet) {
|
|
68
|
+
return Object.assign(Object.assign({}, base), { changes: changeSet.changes, errors: changeSet.errors, publishedOn: (_d = (_c = changeSet.publishedOn) === null || _c === void 0 ? void 0 : _c.toString()) !== null && _d !== void 0 ? _d : null });
|
|
69
|
+
}
|
|
70
|
+
// or a new one
|
|
71
|
+
else {
|
|
72
|
+
return Object.assign(Object.assign({}, base), { changes: (_e = changeSet.changes) !== null && _e !== void 0 ? _e : [], errors: (_f = changeSet.errors) !== null && _f !== void 0 ? _f : true, publishedOn: null });
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
ChangeSetData.serialize = serialize;
|
|
76
|
+
})(ChangeSetData || (exports.ChangeSetData = ChangeSetData = {}));
|