@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,610 @@
|
|
|
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.StrapiCollectionClient = void 0;
|
|
15
|
+
const funnel_core_1 = require("@nascentdigital/funnel-core");
|
|
16
|
+
const errors_1 = require("../errors");
|
|
17
|
+
const serialization_1 = require("./serialization");
|
|
18
|
+
const Strapi_1 = require("./Strapi");
|
|
19
|
+
// class
|
|
20
|
+
class StrapiCollectionClient {
|
|
21
|
+
constructor(provider) {
|
|
22
|
+
this.provider = provider;
|
|
23
|
+
}
|
|
24
|
+
getOverview({ brand, version }) {
|
|
25
|
+
return this.provider.customRequest({
|
|
26
|
+
command: 'query/collections',
|
|
27
|
+
params: { brand, preview: version === 'draft' ? 'true' : 'false' }
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
async getItems({ brand, type, language, tags, version }) {
|
|
31
|
+
// create params (add tags if any)
|
|
32
|
+
const params = {
|
|
33
|
+
brand,
|
|
34
|
+
type,
|
|
35
|
+
language,
|
|
36
|
+
preview: version === 'draft' ? 'true' : 'false'
|
|
37
|
+
};
|
|
38
|
+
if (tags && tags.length > 0) {
|
|
39
|
+
params.tags = tags.join(',');
|
|
40
|
+
}
|
|
41
|
+
const itemsData = await this.provider.customRequest({
|
|
42
|
+
command: 'query/collection',
|
|
43
|
+
params
|
|
44
|
+
});
|
|
45
|
+
// convert refs and return
|
|
46
|
+
return itemsData.map((_a) => {
|
|
47
|
+
var { refs } = _a, itemData = __rest(_a, ["refs"]);
|
|
48
|
+
return (Object.assign(Object.assign({}, itemData), { refs: Object.values(refs).reduce((refs, ref) => {
|
|
49
|
+
// map ref
|
|
50
|
+
refs[ref.lang] = serialization_1.CollectionData.deserializeRef(ref);
|
|
51
|
+
// keep reducing
|
|
52
|
+
return refs;
|
|
53
|
+
}, {}) }));
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
async find(_a) {
|
|
57
|
+
var { pagination } = _a, args = __rest(_a, ["pagination"]);
|
|
58
|
+
// fetch all pages that match (as link data)
|
|
59
|
+
const client = this.provider.client;
|
|
60
|
+
const strapiUrl = client.baseURL;
|
|
61
|
+
const collection = client.collection('collections');
|
|
62
|
+
const resultProps = funnel_core_1.Schema.Collection.Data.Props.all;
|
|
63
|
+
const _b = await Strapi_1.Strapi.paginate(Object.assign({ collection,
|
|
64
|
+
pagination, fields: serialization_1.CollectionData.getStrapiFilter(resultProps), sort: args.version === 'published'
|
|
65
|
+
? ['publishedOn:desc', 'updatedAt:desc']
|
|
66
|
+
: ['updatedAt:desc'], populate: serialization_1.CollectionData.populate }, getCollectionQueryParams(args))), { items } = _b, paginated = __rest(_b, ["items"]);
|
|
67
|
+
// transform to DTOs
|
|
68
|
+
return Object.assign({ items: items.map(item => serialization_1.CollectionData.deserialize(item, strapiUrl, resultProps)) }, paginated);
|
|
69
|
+
}
|
|
70
|
+
async getGroup({ version, type, brand, groupId, language }) {
|
|
71
|
+
var _a, _b;
|
|
72
|
+
// fetch all collection items in group
|
|
73
|
+
const client = this.provider.client;
|
|
74
|
+
const collection = client.collection('collections');
|
|
75
|
+
const { items = [] } = await Strapi_1.Strapi.paginate(Object.assign({ collection, pagination: 'all', fields: serialization_1.CollectionData.getStrapiFilter(funnel_core_1.Schema.Collection.Data.Props.id) }, getCollectionQueryParams({ version, brand, groupId })));
|
|
76
|
+
// return nothing if there are no instances
|
|
77
|
+
if (items.length === 0) {
|
|
78
|
+
return undefined;
|
|
79
|
+
}
|
|
80
|
+
// create group
|
|
81
|
+
const schema = funnel_core_1.Schema.Site.getCollection(type);
|
|
82
|
+
const instances = items.map(serialization_1.CollectionData.deserializeRef);
|
|
83
|
+
const result = {
|
|
84
|
+
group: {
|
|
85
|
+
type,
|
|
86
|
+
brand,
|
|
87
|
+
groupId,
|
|
88
|
+
name: (_b = (_a = funnel_core_1.ArrayUtils.first(items)) === null || _a === void 0 ? void 0 : _a.name) !== null && _b !== void 0 ? _b : schema.name,
|
|
89
|
+
instances
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
// add language if it exists as an instance
|
|
93
|
+
const target = instances.find(item => item.language === language);
|
|
94
|
+
if (target) {
|
|
95
|
+
// get collection
|
|
96
|
+
result.collection = await this.get({ version, id: target.id });
|
|
97
|
+
// sync name if collection was found
|
|
98
|
+
if (result.collection) {
|
|
99
|
+
result.group.name = result.collection.name;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
// return result
|
|
103
|
+
return result;
|
|
104
|
+
}
|
|
105
|
+
async get({ version, id }) {
|
|
106
|
+
// get data
|
|
107
|
+
const client = this.provider.client;
|
|
108
|
+
const resultProps = funnel_core_1.Schema.Collection.Data.Props.all;
|
|
109
|
+
const { data } = await client.collection('collections').findOne(id, {
|
|
110
|
+
fields: serialization_1.CollectionData.getStrapiFilter(resultProps),
|
|
111
|
+
status: version,
|
|
112
|
+
populate: serialization_1.CollectionData.populate
|
|
113
|
+
});
|
|
114
|
+
// deserialize and return
|
|
115
|
+
return data
|
|
116
|
+
? serialization_1.CollectionData.deserialize(data, client.baseURL, resultProps)
|
|
117
|
+
: undefined;
|
|
118
|
+
}
|
|
119
|
+
async create(args) {
|
|
120
|
+
// resolve current user (or throw)
|
|
121
|
+
const { client, users } = this.provider;
|
|
122
|
+
const strapiUrl = client.baseURL;
|
|
123
|
+
const user = await users.me();
|
|
124
|
+
if (!user) {
|
|
125
|
+
throw new funnel_core_1.NotAuthenticatedError();
|
|
126
|
+
}
|
|
127
|
+
// create a new language of an existing collection
|
|
128
|
+
if (funnel_core_1.Schema.Collection.Data.AsNewLanguage.filter(args)) {
|
|
129
|
+
// fetch all collections in group
|
|
130
|
+
const groupResult = await this.getGroup({
|
|
131
|
+
version: 'draft',
|
|
132
|
+
type: args.type,
|
|
133
|
+
groupId: args.groupId,
|
|
134
|
+
language: args.language
|
|
135
|
+
});
|
|
136
|
+
// throw if the group doesn't exist
|
|
137
|
+
if (groupResult === undefined) {
|
|
138
|
+
throw new funnel_core_1.ArgumentError(`Collection group "${args.groupId}" no longer exists in "${args.brand}"`);
|
|
139
|
+
}
|
|
140
|
+
// extract group and existing collection from result
|
|
141
|
+
const { group, collection: existingCollection } = groupResult;
|
|
142
|
+
// return existing collection if it's there
|
|
143
|
+
if (existingCollection) {
|
|
144
|
+
return {
|
|
145
|
+
group,
|
|
146
|
+
collection: existingCollection
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
// bind data + update url
|
|
150
|
+
const draft = funnel_core_1.Schema.CollectionModel.fromDraft(Object.assign(Object.assign({}, args), { type: group.type, name: group.name, tags: [] }));
|
|
151
|
+
draft.sync();
|
|
152
|
+
// resolve change set (rebind)
|
|
153
|
+
const { provider } = this;
|
|
154
|
+
const changeSet = await provider.changeSets.resolve();
|
|
155
|
+
// create collection
|
|
156
|
+
try {
|
|
157
|
+
// connect collection to changeset
|
|
158
|
+
draft.data.changeSetId = changeSet.id;
|
|
159
|
+
// create data model based on existing page
|
|
160
|
+
const { data } = await client.collection('collections')
|
|
161
|
+
.create(serialization_1.CollectionData.serialize(draft.data), {
|
|
162
|
+
status: 'draft',
|
|
163
|
+
populate: serialization_1.CollectionData.populate
|
|
164
|
+
});
|
|
165
|
+
// transform the deserialized entry
|
|
166
|
+
const collection = serialization_1.CollectionData.deserialize(data, strapiUrl, funnel_core_1.Schema.Collection.Data.Props.all);
|
|
167
|
+
// add collection to changeset
|
|
168
|
+
await provider.changeSets.update({
|
|
169
|
+
id: changeSet.id,
|
|
170
|
+
changes: [
|
|
171
|
+
...changeSet.changes,
|
|
172
|
+
{
|
|
173
|
+
__type: 'collection',
|
|
174
|
+
type: 'create',
|
|
175
|
+
schema: collection.type,
|
|
176
|
+
id: collection.id,
|
|
177
|
+
groupId: collection.groupId,
|
|
178
|
+
name: collection.name,
|
|
179
|
+
language: collection.language,
|
|
180
|
+
errors: collection.errors,
|
|
181
|
+
attribution: [
|
|
182
|
+
{ userId: user.id, updatedOn: Date.now() }
|
|
183
|
+
]
|
|
184
|
+
}
|
|
185
|
+
]
|
|
186
|
+
});
|
|
187
|
+
// add collection to group
|
|
188
|
+
group.instances.push({
|
|
189
|
+
id: collection.id,
|
|
190
|
+
language: collection.language,
|
|
191
|
+
version: collection.version,
|
|
192
|
+
tags: collection.tags
|
|
193
|
+
});
|
|
194
|
+
// return updated group
|
|
195
|
+
return {
|
|
196
|
+
group,
|
|
197
|
+
collection
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
// or remove on failure remove
|
|
201
|
+
catch (e) {
|
|
202
|
+
// discard if it had no changes
|
|
203
|
+
if (changeSet.changes.length === 0) {
|
|
204
|
+
await provider.changeSets.delete(changeSet.id);
|
|
205
|
+
}
|
|
206
|
+
// throw error
|
|
207
|
+
throw funnel_core_1.IsometricErrorUtils.coerceError(e);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
// or create a net new collection
|
|
211
|
+
else {
|
|
212
|
+
// bind data + update url
|
|
213
|
+
const draft = funnel_core_1.Schema.CollectionModel.fromDraft(Object.assign(Object.assign({}, args), { groupId: funnel_core_1.Value.uuid() }));
|
|
214
|
+
draft.sync();
|
|
215
|
+
console.debug('[StrapiCollectionClient/create/new] creating new draft', serialization_1.CollectionData.serialize(draft.data));
|
|
216
|
+
// resolve change set (rebind)
|
|
217
|
+
const { provider } = this;
|
|
218
|
+
const changeSet = await provider.changeSets.resolve();
|
|
219
|
+
// or create it
|
|
220
|
+
try {
|
|
221
|
+
// connect collection to changeset
|
|
222
|
+
draft.data.changeSetId = changeSet.id;
|
|
223
|
+
// create collection
|
|
224
|
+
const { data } = await client.collection('collections')
|
|
225
|
+
.create(serialization_1.CollectionData.serialize(draft.data), {
|
|
226
|
+
status: 'draft',
|
|
227
|
+
populate: serialization_1.CollectionData.populate
|
|
228
|
+
});
|
|
229
|
+
// transform the deserialized entry
|
|
230
|
+
const collection = serialization_1.CollectionData.deserialize(data, strapiUrl, funnel_core_1.Schema.Collection.Data.Props.all);
|
|
231
|
+
// add collection to changeset
|
|
232
|
+
await provider.changeSets.update({
|
|
233
|
+
id: changeSet.id,
|
|
234
|
+
changes: [
|
|
235
|
+
...changeSet.changes,
|
|
236
|
+
{
|
|
237
|
+
__type: 'collection',
|
|
238
|
+
type: 'create',
|
|
239
|
+
schema: collection.type,
|
|
240
|
+
id: collection.id,
|
|
241
|
+
groupId: collection.groupId,
|
|
242
|
+
name: collection.name,
|
|
243
|
+
language: collection.language,
|
|
244
|
+
errors: collection.errors,
|
|
245
|
+
attribution: [
|
|
246
|
+
{ userId: user.id, updatedOn: Date.now() }
|
|
247
|
+
]
|
|
248
|
+
}
|
|
249
|
+
]
|
|
250
|
+
});
|
|
251
|
+
// return collection
|
|
252
|
+
return {
|
|
253
|
+
group: {
|
|
254
|
+
groupId: collection.groupId,
|
|
255
|
+
brand: collection.brand,
|
|
256
|
+
type: collection.type,
|
|
257
|
+
name: collection.name,
|
|
258
|
+
instances: [{
|
|
259
|
+
id: collection.id,
|
|
260
|
+
language: collection.language,
|
|
261
|
+
version: collection.version,
|
|
262
|
+
tags: collection.tags
|
|
263
|
+
}]
|
|
264
|
+
},
|
|
265
|
+
collection
|
|
266
|
+
};
|
|
267
|
+
}
|
|
268
|
+
// or remove on failure remove
|
|
269
|
+
catch (e) {
|
|
270
|
+
// discard if it had no changes
|
|
271
|
+
if (changeSet.changes.length === 0) {
|
|
272
|
+
await provider.changeSets.delete(changeSet.id);
|
|
273
|
+
}
|
|
274
|
+
// throw error
|
|
275
|
+
throw funnel_core_1.IsometricErrorUtils.coerceError(e);
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
async duplicate({ source: collectionId, targetCollection, targetLanguage }) {
|
|
280
|
+
// resolve current user (or throw)
|
|
281
|
+
const { client, users } = this.provider;
|
|
282
|
+
const strapiUrl = client.baseURL;
|
|
283
|
+
const user = await users.me();
|
|
284
|
+
if (!user) {
|
|
285
|
+
throw new funnel_core_1.NotAuthenticatedError();
|
|
286
|
+
}
|
|
287
|
+
// get collection by id
|
|
288
|
+
const collectionCollection = client.collection('collections');
|
|
289
|
+
const { data: sourceData } = await collectionCollection.findOne(collectionId, {
|
|
290
|
+
fields: serialization_1.CollectionData.getStrapiFilter(funnel_core_1.Schema.Collection.Data.Props.all),
|
|
291
|
+
status: 'draft',
|
|
292
|
+
populate: serialization_1.CollectionData.populate
|
|
293
|
+
});
|
|
294
|
+
const sourceCollection = sourceData;
|
|
295
|
+
// throw if there's no collection
|
|
296
|
+
if (!sourceCollection) {
|
|
297
|
+
throw new funnel_core_1.NotFoundError(`Unable to resolve collection with id "${collectionId}"`);
|
|
298
|
+
}
|
|
299
|
+
// make sure target language doesn't already exist if we are targeting the current group
|
|
300
|
+
if (targetCollection === 'current') {
|
|
301
|
+
const { data: collectionsWithTargetLanguage } = await collectionCollection.find(Object.assign({ fields: ['documentId'] }, getCollectionQueryParams({ version: 'draft', groupId: sourceCollection.groupId, language: targetLanguage })));
|
|
302
|
+
if (collectionsWithTargetLanguage.length > 0) {
|
|
303
|
+
throw new funnel_core_1.InvalidOperationError(`There is already a collection in group "${sourceCollection.groupId}" with ${targetLanguage} language`);
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
// get refs from source collection
|
|
307
|
+
const { assetRefs, collectionRefs } = sourceCollection;
|
|
308
|
+
// target refs and body
|
|
309
|
+
let targetCollectionRefIds;
|
|
310
|
+
let targetBody;
|
|
311
|
+
// if we are targeting a different language then we need to "translate" the references
|
|
312
|
+
if (targetLanguage !== sourceCollection.lang) {
|
|
313
|
+
// fetch target language refs
|
|
314
|
+
const { collectionIdMappings } = await Strapi_1.Strapi.translateReferences({
|
|
315
|
+
client,
|
|
316
|
+
targetLanguage,
|
|
317
|
+
collectionRefs
|
|
318
|
+
});
|
|
319
|
+
// set target values
|
|
320
|
+
targetCollectionRefIds = collectionIdMappings.map(mapping => mapping.targetId);
|
|
321
|
+
targetBody = {
|
|
322
|
+
fields: Strapi_1.Strapi.updateRefs({ value: sourceCollection.fields, collectionIdMappings })
|
|
323
|
+
};
|
|
324
|
+
}
|
|
325
|
+
// otherwise we can keep everything the same as the source page
|
|
326
|
+
else {
|
|
327
|
+
// set target values
|
|
328
|
+
targetCollectionRefIds = collectionRefs.map(ref => ref.documentId);
|
|
329
|
+
targetBody = {
|
|
330
|
+
fields: sourceCollection.fields
|
|
331
|
+
};
|
|
332
|
+
}
|
|
333
|
+
// resolve change set (rebind)
|
|
334
|
+
const { provider } = this;
|
|
335
|
+
const changeSet = await provider.changeSets.resolve();
|
|
336
|
+
// create duplicate collection
|
|
337
|
+
try {
|
|
338
|
+
// create target collection using content of source
|
|
339
|
+
const { data: dupData } = await collectionCollection.create(Object.assign({ groupId: targetCollection === 'current'
|
|
340
|
+
? sourceCollection.groupId
|
|
341
|
+
: funnel_core_1.Value.uuid(), version: 1, type: sourceCollection.type, brand: sourceCollection.brand, lang: targetLanguage, name: sourceCollection.name, tags: sourceCollection.tags, state: 'draft', errors: sourceCollection.errors, assetRefs: { set: assetRefs.map(ref => ref.documentId) }, collectionRefs: { set: targetCollectionRefIds } }, targetBody), { status: 'draft', populate: serialization_1.CollectionData.populate });
|
|
342
|
+
const dupCollectionData = dupData;
|
|
343
|
+
console.debug('[StrapiCollectionClient] duplicate: created duplicate collection', { dupCollectionData });
|
|
344
|
+
// touch new duplicated collection
|
|
345
|
+
let dupCollection = serialization_1.CollectionData.deserialize(dupCollectionData, strapiUrl, funnel_core_1.Schema.Collection.Data.Props.all);
|
|
346
|
+
const dupCollectionModel = funnel_core_1.Schema.CollectionModel.from(dupCollection);
|
|
347
|
+
dupCollectionModel.sync();
|
|
348
|
+
// connect collection to changeset
|
|
349
|
+
dupCollection.changeSetId = changeSet.id;
|
|
350
|
+
// update duplicate collection with updated data from sync
|
|
351
|
+
const update = serialization_1.CollectionData.serialize(dupCollection);
|
|
352
|
+
const { data: updatedData } = await collectionCollection.update(dupCollection.id, update, { status: 'draft' });
|
|
353
|
+
dupCollection = serialization_1.CollectionData.deserialize(updatedData, strapiUrl, funnel_core_1.Schema.Collection.Data.Props.all);
|
|
354
|
+
console.debug('[StrapiCollectionClient] duplicate: touched duplicated collection');
|
|
355
|
+
// add collection to changeset
|
|
356
|
+
await provider.changeSets.update({
|
|
357
|
+
id: changeSet.id,
|
|
358
|
+
changes: [
|
|
359
|
+
...changeSet.changes,
|
|
360
|
+
{
|
|
361
|
+
__type: 'collection',
|
|
362
|
+
type: 'create',
|
|
363
|
+
schema: dupCollection.type,
|
|
364
|
+
id: dupCollection.id,
|
|
365
|
+
groupId: dupCollection.groupId,
|
|
366
|
+
name: dupCollection.name,
|
|
367
|
+
language: dupCollection.language,
|
|
368
|
+
errors: dupCollection.errors,
|
|
369
|
+
attribution: [
|
|
370
|
+
{ userId: user.id, updatedOn: Date.now() }
|
|
371
|
+
]
|
|
372
|
+
}
|
|
373
|
+
]
|
|
374
|
+
});
|
|
375
|
+
// return group for duplicated collection
|
|
376
|
+
const group = await this.getGroup({
|
|
377
|
+
brand: dupCollection.brand,
|
|
378
|
+
groupId: dupCollection.groupId,
|
|
379
|
+
type: dupCollection.type,
|
|
380
|
+
language: dupCollection.language,
|
|
381
|
+
version: 'draft'
|
|
382
|
+
});
|
|
383
|
+
// should not happen
|
|
384
|
+
if (!group) {
|
|
385
|
+
throw new funnel_core_1.IllegalStateError(`cannot find group that was just created`);
|
|
386
|
+
}
|
|
387
|
+
// return
|
|
388
|
+
return group;
|
|
389
|
+
}
|
|
390
|
+
// handle errors
|
|
391
|
+
catch (e) {
|
|
392
|
+
// discard changeset if it had no changes
|
|
393
|
+
if (changeSet.changes.length === 0) {
|
|
394
|
+
await provider.changeSets.delete(changeSet.id);
|
|
395
|
+
}
|
|
396
|
+
// throw error
|
|
397
|
+
throw funnel_core_1.IsometricErrorUtils.coerceError(e);
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
async update({ id: collectionId, errors, updates }) {
|
|
401
|
+
// resolve current user (or throw)
|
|
402
|
+
const { client, users } = this.provider;
|
|
403
|
+
const strapiUrl = client.baseURL;
|
|
404
|
+
const user = await users.me();
|
|
405
|
+
if (!user) {
|
|
406
|
+
throw new funnel_core_1.NotAuthenticatedError();
|
|
407
|
+
}
|
|
408
|
+
// get latest version of collection
|
|
409
|
+
const entries = client.collection('collections');
|
|
410
|
+
const resultProps = funnel_core_1.Schema.Collection.Data.Props.all;
|
|
411
|
+
const { data: currentData } = await entries.findOne(collectionId, {
|
|
412
|
+
status: 'draft',
|
|
413
|
+
populate: serialization_1.CollectionData.populate
|
|
414
|
+
});
|
|
415
|
+
// TODO: validate collection is able to be updated (e.g. not archived, etc.)
|
|
416
|
+
// TODO: switch to isometric error so we can catch it on client-side
|
|
417
|
+
// throw if collection doesn't exist
|
|
418
|
+
if (!currentData) {
|
|
419
|
+
throw new funnel_core_1.NotFoundError();
|
|
420
|
+
}
|
|
421
|
+
// deserialize collection (we'll be updating this version)
|
|
422
|
+
const collection = serialization_1.CollectionData.deserialize(currentData, strapiUrl, resultProps);
|
|
423
|
+
// set errors
|
|
424
|
+
collection.errors = errors;
|
|
425
|
+
console.debug(`[StrapiPageClient/update] applying ${updates.length} collection updates`);
|
|
426
|
+
// merge changes (the original collection will have changed)
|
|
427
|
+
const model = funnel_core_1.Schema.CollectionModel.from(collection);
|
|
428
|
+
model.update(updates);
|
|
429
|
+
console.debug(`[StrapiPageClient/update] saving updated collection`);
|
|
430
|
+
// resolve change set (rebind)
|
|
431
|
+
const { provider } = this;
|
|
432
|
+
const changeSet = await provider.changeSets.resolve({ id: collection.changeSetId, fallbackToGlobal: true });
|
|
433
|
+
collection.changeSetId = changeSet.id;
|
|
434
|
+
// save collection
|
|
435
|
+
const update = serialization_1.CollectionData.serialize(collection);
|
|
436
|
+
const { data: updatedData } = await entries.update(collection.id, Object.assign(Object.assign({}, update), { state: 'draft' }), {
|
|
437
|
+
status: 'draft',
|
|
438
|
+
populate: serialization_1.CollectionData.populate
|
|
439
|
+
});
|
|
440
|
+
// update changeset
|
|
441
|
+
changeSet.addCollectionChange(user.id, {
|
|
442
|
+
__type: 'collection',
|
|
443
|
+
id: collection.id,
|
|
444
|
+
groupId: collection.groupId,
|
|
445
|
+
name: collection.name,
|
|
446
|
+
schema: collection.type,
|
|
447
|
+
language: collection.language,
|
|
448
|
+
type: collection.publishedOn ? 'update' : 'create',
|
|
449
|
+
errors: collection.errors
|
|
450
|
+
});
|
|
451
|
+
provider.changeSets.update(changeSet.toData())
|
|
452
|
+
.catch(console.error);
|
|
453
|
+
// return collection
|
|
454
|
+
return serialization_1.CollectionData.deserialize(updatedData, strapiUrl, resultProps);
|
|
455
|
+
}
|
|
456
|
+
async replace({ updatedCollection, version, skipSync }) {
|
|
457
|
+
console.debug(`[StrapiCollectionClient/replace] replacing collection`);
|
|
458
|
+
// get latest version of collection
|
|
459
|
+
const client = this.provider.client;
|
|
460
|
+
const strapiUrl = client.baseURL;
|
|
461
|
+
const collection = client.collection('collection');
|
|
462
|
+
// sync changes (the original collection will have changed)
|
|
463
|
+
const model = funnel_core_1.Schema.CollectionModel.from(updatedCollection);
|
|
464
|
+
if (!skipSync) {
|
|
465
|
+
model.sync();
|
|
466
|
+
}
|
|
467
|
+
// save collection
|
|
468
|
+
const update = serialization_1.CollectionData.serialize(updatedCollection);
|
|
469
|
+
const { data: updatedData } = await collection.update(updatedCollection.id, update, {
|
|
470
|
+
status: version,
|
|
471
|
+
populate: serialization_1.CollectionData.populate
|
|
472
|
+
});
|
|
473
|
+
console.debug(`[StrapiCollectionClient/replace] returning final collection`);
|
|
474
|
+
// return collection
|
|
475
|
+
return serialization_1.CollectionData.deserialize(updatedData, strapiUrl);
|
|
476
|
+
}
|
|
477
|
+
async unpublish(collectionId) {
|
|
478
|
+
// get collection
|
|
479
|
+
const collection = await this.get({ id: collectionId, version: 'draft' });
|
|
480
|
+
// throw if there's no collection
|
|
481
|
+
if (!collection) {
|
|
482
|
+
throw new funnel_core_1.NotFoundError('Unable to resolve collection');
|
|
483
|
+
}
|
|
484
|
+
// or throw if it's already draft
|
|
485
|
+
else if (!collection.publishedOn) {
|
|
486
|
+
throw new funnel_core_1.InvalidOperationError('Collection is not published');
|
|
487
|
+
}
|
|
488
|
+
// unpublish the document
|
|
489
|
+
await this.provider.customRequest({
|
|
490
|
+
method: 'POST',
|
|
491
|
+
command: 'unpublish',
|
|
492
|
+
data: JSON.stringify({
|
|
493
|
+
collection: 'collection',
|
|
494
|
+
documentId: collection.id
|
|
495
|
+
}),
|
|
496
|
+
onError: ({ pageRefs, collectionRefs }) => {
|
|
497
|
+
// throw dependants error if we got any refs
|
|
498
|
+
if (pageRefs || collectionRefs) {
|
|
499
|
+
const client = this.provider.client;
|
|
500
|
+
const strapiUrl = client.baseURL;
|
|
501
|
+
throw new errors_1.LinkedDependantsError({
|
|
502
|
+
message: 'This collection cannot be unpublished because it would break dependencies',
|
|
503
|
+
pages: pageRefs.map(data => serialization_1.PageData.deserialize(data, strapiUrl, funnel_core_1.Schema.Page.Data.AsLink.props)),
|
|
504
|
+
collections: collectionRefs.map(data => serialization_1.CollectionData.deserialize(data, strapiUrl, funnel_core_1.Schema.Collection.Data.AsLink.props))
|
|
505
|
+
});
|
|
506
|
+
}
|
|
507
|
+
// or assume the page isn't published
|
|
508
|
+
else {
|
|
509
|
+
throw new funnel_core_1.NotFoundError();
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
});
|
|
513
|
+
// indicate success
|
|
514
|
+
return true;
|
|
515
|
+
}
|
|
516
|
+
async getDependants({ id: collectionId, version }) {
|
|
517
|
+
// setup strapi collections and query
|
|
518
|
+
const client = this.provider.client;
|
|
519
|
+
const strapiUrl = client.baseURL;
|
|
520
|
+
const pagesCollection = client.collection('pages');
|
|
521
|
+
const collectionsCollection = client.collection('collections');
|
|
522
|
+
const dependantsQuery = {
|
|
523
|
+
pagination: 'all',
|
|
524
|
+
filters: {
|
|
525
|
+
collectionRefs: {
|
|
526
|
+
documentId: collectionId
|
|
527
|
+
}
|
|
528
|
+
},
|
|
529
|
+
status: version
|
|
530
|
+
};
|
|
531
|
+
// fetch dependants
|
|
532
|
+
const [{ items: pages = [] }, { items: collections = [] }] = await Promise.all([
|
|
533
|
+
Strapi_1.Strapi.paginate(Object.assign({ collection: pagesCollection }, dependantsQuery)),
|
|
534
|
+
Strapi_1.Strapi.paginate(Object.assign({ collection: collectionsCollection }, dependantsQuery))
|
|
535
|
+
]);
|
|
536
|
+
// return
|
|
537
|
+
return {
|
|
538
|
+
pages: pages.map(page => serialization_1.PageData.deserialize(page, strapiUrl, funnel_core_1.Schema.Page.Data.AsRef.props)),
|
|
539
|
+
collections: collections.map(collection => serialization_1.CollectionData.deserialize(collection, strapiUrl, funnel_core_1.Schema.Collection.Data.AsRef.props))
|
|
540
|
+
};
|
|
541
|
+
}
|
|
542
|
+
async getDependencies({ id: collectionId, version }) {
|
|
543
|
+
// get collection by id
|
|
544
|
+
const client = this.provider.client;
|
|
545
|
+
const strapiUrl = client.baseURL;
|
|
546
|
+
const collection = client.collection('collections');
|
|
547
|
+
const { data } = await collection.findOne(collectionId, {
|
|
548
|
+
status: version,
|
|
549
|
+
populate: ['collectionRefs']
|
|
550
|
+
});
|
|
551
|
+
const collectionData = data;
|
|
552
|
+
// throw if not found
|
|
553
|
+
if (!collectionData) {
|
|
554
|
+
throw new funnel_core_1.NotFoundError(`cannot find collection with id "${collectionId}"`);
|
|
555
|
+
}
|
|
556
|
+
// return
|
|
557
|
+
return {
|
|
558
|
+
collections: collectionData.collectionRefs.map(collectionRef => serialization_1.CollectionData.deserialize(collectionRef, strapiUrl, funnel_core_1.Schema.Collection.Data.AsRef.props))
|
|
559
|
+
};
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
exports.StrapiCollectionClient = StrapiCollectionClient;
|
|
563
|
+
// helper
|
|
564
|
+
function getCollectionQueryParams(query) {
|
|
565
|
+
// build filters
|
|
566
|
+
const { groupId, brand, type, language, name, tags = [], tagsMatch = 'any', version } = query;
|
|
567
|
+
const filters = [];
|
|
568
|
+
// filter group
|
|
569
|
+
if (groupId) {
|
|
570
|
+
filters.push({ groupId: { $eq: groupId } });
|
|
571
|
+
}
|
|
572
|
+
// filter brand
|
|
573
|
+
if (brand) {
|
|
574
|
+
filters.push({ brand: { $eq: brand } });
|
|
575
|
+
}
|
|
576
|
+
// filter type
|
|
577
|
+
const normalizedType = type
|
|
578
|
+
? Array.isArray(type)
|
|
579
|
+
? type
|
|
580
|
+
: [type]
|
|
581
|
+
: [];
|
|
582
|
+
if (normalizedType.length > 0) {
|
|
583
|
+
filters.push({ type: { $in: type } });
|
|
584
|
+
}
|
|
585
|
+
// filter language
|
|
586
|
+
if (language) {
|
|
587
|
+
filters.push({ lang: { $eq: language } });
|
|
588
|
+
}
|
|
589
|
+
// filter name
|
|
590
|
+
if (name) {
|
|
591
|
+
filters.push({ name: { $contains: name } });
|
|
592
|
+
}
|
|
593
|
+
// filter tags
|
|
594
|
+
if (tags.length === 1) {
|
|
595
|
+
filters.push({ tags: { $contains: `"${tags[0]}"` } });
|
|
596
|
+
}
|
|
597
|
+
else if (tags.length > 1) {
|
|
598
|
+
const operator = tagsMatch === 'any' ? '$or' : '$and';
|
|
599
|
+
filters.push({
|
|
600
|
+
[operator]: tags
|
|
601
|
+
.filter((tag) => !!tag)
|
|
602
|
+
.map((tag) => ({ tags: { $contains: `"${tag}"` } }))
|
|
603
|
+
});
|
|
604
|
+
}
|
|
605
|
+
// return query
|
|
606
|
+
return {
|
|
607
|
+
filters: filters.length > 0 ? { $and: filters } : undefined,
|
|
608
|
+
status: version
|
|
609
|
+
};
|
|
610
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { StrapiClient } from '@strapi/client';
|
|
2
|
+
import { JsonValue } from 'type-fest';
|
|
3
|
+
import { AuthClient, ContentClient } from '../api';
|
|
4
|
+
import { IStrapiContentClient } from './IStrapiContentClient';
|
|
5
|
+
import { StrapiAssetClient } from './StrapiAssetClient';
|
|
6
|
+
import { StrapiAuthClient } from './StrapiAuthClient';
|
|
7
|
+
import { StrapiChangeSetClient } from './StrapiChangeSetClient';
|
|
8
|
+
import { StrapiCollectionClient } from './StrapiCollectionClient';
|
|
9
|
+
import { StrapiPageClient } from './StrapiPageClient';
|
|
10
|
+
import { StrapiSiteConfigClient } from './StrapiSiteConfigClient';
|
|
11
|
+
import { StrapiUpgradeClient } from './StrapiUpgradeClient';
|
|
12
|
+
import { StrapiUserClient } from './StrapiUserClient';
|
|
13
|
+
export declare class StrapiContentClient implements ContentClient, IStrapiContentClient {
|
|
14
|
+
readonly auth: StrapiAuthClient;
|
|
15
|
+
readonly changeSets: StrapiChangeSetClient;
|
|
16
|
+
readonly files: StrapiAssetClient;
|
|
17
|
+
readonly pages: StrapiPageClient;
|
|
18
|
+
readonly collections: StrapiCollectionClient;
|
|
19
|
+
readonly upgrade: StrapiUpgradeClient;
|
|
20
|
+
readonly users: StrapiUserClient;
|
|
21
|
+
readonly siteConfig: StrapiSiteConfigClient;
|
|
22
|
+
private readonly _baseUrl;
|
|
23
|
+
private _token?;
|
|
24
|
+
private _client;
|
|
25
|
+
constructor({ baseUrl, token, slackUrl }: StrapiContentClient.ConstructorArgs);
|
|
26
|
+
get client(): StrapiClient;
|
|
27
|
+
get token(): AuthClient.AccessToken;
|
|
28
|
+
set token(token: AuthClient.AccessToken);
|
|
29
|
+
clearToken(): void;
|
|
30
|
+
customRequest<TResult extends JsonValue = JsonValue, TError extends JsonValue = JsonValue>({ command, method, params, data, onError }: IStrapiContentClient.CustomRequestArgs<TError>): Promise<TResult>;
|
|
31
|
+
}
|
|
32
|
+
export declare namespace StrapiContentClient {
|
|
33
|
+
type ConstructorArgs = {
|
|
34
|
+
baseUrl: string;
|
|
35
|
+
token?: string;
|
|
36
|
+
slackUrl?: string;
|
|
37
|
+
};
|
|
38
|
+
}
|