@nascentdigital/funnel-cms 4.6.7 → 5.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/dist/contentful/ContentfulAccess.d.ts +19 -0
- package/dist/contentful/ContentfulAccess.js +67 -0
- package/dist/contentful/ContentfulApiCommand.d.ts +21 -0
- package/dist/contentful/ContentfulApiCommand.js +20 -0
- package/dist/contentful/ContentfulApiResponse.d.ts +10 -0
- package/dist/contentful/ContentfulApiResponse.js +2 -0
- package/dist/contentful/ContentfulAssetClient.d.ts +11 -0
- package/dist/contentful/ContentfulAssetClient.js +26 -0
- package/dist/contentful/ContentfulAuthClient.d.ts +9 -0
- package/dist/contentful/ContentfulAuthClient.js +20 -0
- package/dist/contentful/ContentfulChangeSetClient.d.ts +14 -0
- package/dist/contentful/ContentfulChangeSetClient.js +35 -0
- package/dist/contentful/ContentfulCollectionClient.d.ts +38 -0
- package/dist/contentful/ContentfulCollectionClient.js +173 -0
- package/dist/contentful/ContentfulContentClient.d.ts +59 -0
- package/dist/contentful/ContentfulContentClient.js +208 -0
- package/dist/contentful/ContentfulContentClientFactory.d.ts +12 -0
- package/dist/contentful/ContentfulContentClientFactory.js +19 -0
- package/dist/contentful/ContentfulPageClient.d.ts +43 -0
- package/dist/contentful/ContentfulPageClient.js +251 -0
- package/dist/contentful/ContentfulSiteConfigClient.d.ts +9 -0
- package/dist/contentful/ContentfulSiteConfigClient.js +33 -0
- package/dist/contentful/ContentfulUpgradeClient.d.ts +9 -0
- package/dist/contentful/ContentfulUpgradeClient.js +17 -0
- package/dist/contentful/ContentfulUserClient.d.ts +13 -0
- package/dist/contentful/ContentfulUserClient.js +32 -0
- package/dist/contentful/IContentfulContentClient.d.ts +52 -0
- package/dist/contentful/IContentfulContentClient.js +2 -0
- package/dist/contentful/api/ContentfulApi.d.ts +10 -0
- package/dist/contentful/api/ContentfulApi.js +82 -0
- package/dist/contentful/index.d.ts +12 -0
- package/dist/contentful/index.js +28 -0
- package/dist/contentful/models/ContentfulAssetData.d.ts +8 -0
- package/dist/contentful/models/ContentfulAssetData.js +29 -0
- package/dist/contentful/models/ContentfulCollectionData.d.ts +11 -0
- package/dist/contentful/models/ContentfulCollectionData.js +98 -0
- package/dist/contentful/models/ContentfulData.d.ts +40 -0
- package/dist/contentful/models/ContentfulData.js +118 -0
- package/dist/contentful/models/ContentfulPageData.d.ts +17 -0
- package/dist/contentful/models/ContentfulPageData.js +117 -0
- package/dist/contentful/models/ContentfulSiteConfigData.d.ts +10 -0
- package/dist/contentful/models/ContentfulSiteConfigData.js +9 -0
- package/dist/contentful/models/ContentfulUserData.d.ts +6 -0
- package/dist/contentful/models/ContentfulUserData.js +26 -0
- package/dist/contentful/models/index.d.ts +6 -0
- package/dist/contentful/models/index.js +22 -0
- package/dist/contentful/server.d.ts +1 -0
- package/dist/contentful/server.js +17 -0
- package/package.json +9 -3
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { CMAClient } from '@contentful/app-sdk';
|
|
2
|
+
import { PlainClientAPI, QueryOptions } from 'contentful-management';
|
|
3
|
+
import { Environment, User } from '../models';
|
|
4
|
+
import type { ContentfulAssetClient } from './ContentfulAssetClient';
|
|
5
|
+
import type { ContentfulAuthClient } from './ContentfulAuthClient';
|
|
6
|
+
import type { ContentfulChangeSetClient } from './ContentfulChangeSetClient';
|
|
7
|
+
import type { ContentfulCollectionClient } from './ContentfulCollectionClient';
|
|
8
|
+
import type { ContentfulPageClient } from './ContentfulPageClient';
|
|
9
|
+
import type { ContentfulSiteConfigClient } from './ContentfulSiteConfigClient';
|
|
10
|
+
import type { ContentfulUserClient } from './ContentfulUserClient';
|
|
11
|
+
import { ContentfulData } from './models';
|
|
12
|
+
export interface IContentfulContentClient {
|
|
13
|
+
readonly user: User;
|
|
14
|
+
readonly locale: string;
|
|
15
|
+
readonly cma: CMAClient;
|
|
16
|
+
readonly cda: PlainClientAPI;
|
|
17
|
+
readonly cpa: PlainClientAPI;
|
|
18
|
+
readonly auth: ContentfulAuthClient;
|
|
19
|
+
readonly changeSets: ContentfulChangeSetClient;
|
|
20
|
+
readonly files: ContentfulAssetClient;
|
|
21
|
+
readonly pages: ContentfulPageClient;
|
|
22
|
+
readonly collections: ContentfulCollectionClient;
|
|
23
|
+
readonly users: ContentfulUserClient;
|
|
24
|
+
readonly siteConfig: ContentfulSiteConfigClient;
|
|
25
|
+
createEntry<TEntry extends ContentfulData>(contentType: string, entry: ContentfulData.Draft<TEntry>): Promise<TEntry>;
|
|
26
|
+
getEntry<TEntry extends ContentfulData>(args: IContentfulContentClient.GetEntry.Args<TEntry>): Promise<IContentfulContentClient.GetEntry.Result<TEntry>>;
|
|
27
|
+
getEntries<TEntry extends ContentfulData>(args: IContentfulContentClient.GetEntries.Args<TEntry>): Promise<IContentfulContentClient.GetEntries.Result<TEntry>>;
|
|
28
|
+
}
|
|
29
|
+
export declare namespace IContentfulContentClient {
|
|
30
|
+
type EntryQueryOptions = {
|
|
31
|
+
includeLinks?: boolean | number;
|
|
32
|
+
version?: Environment;
|
|
33
|
+
};
|
|
34
|
+
namespace GetEntry {
|
|
35
|
+
type Args<TEntry extends ContentfulData> = EntryQueryOptions & {
|
|
36
|
+
entryId: ContentfulData.EntryId<TEntry>;
|
|
37
|
+
};
|
|
38
|
+
type Result<TEntry extends ContentfulData> = {
|
|
39
|
+
entry: TEntry;
|
|
40
|
+
references: ContentfulData[];
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
namespace GetEntries {
|
|
44
|
+
type Args<TEntry extends ContentfulData> = Omit<QueryOptions, 'content_type' | 'include'> & EntryQueryOptions & {
|
|
45
|
+
content_type: ContentfulData.ContentType<TEntry>;
|
|
46
|
+
};
|
|
47
|
+
type Result<TEntry extends ContentfulData> = {
|
|
48
|
+
entries: TEntry[];
|
|
49
|
+
references: ContentfulData[];
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import 'server-only';
|
|
2
|
+
import type { NextRequest, NextResponse as NextResponseType } from 'next/server';
|
|
3
|
+
import { ContentfulApiCommand } from '../ContentfulApiCommand';
|
|
4
|
+
export declare namespace ContentfulApi {
|
|
5
|
+
function process(request: NextRequest, NextResponse: typeof NextResponseType): Promise<NextResponseType<{
|
|
6
|
+
data: ContentfulApiCommand.GetAccessTokens.Result;
|
|
7
|
+
}> | NextResponseType<{
|
|
8
|
+
error: import("@nascentdigital/funnel-core").SerializedIsometricError;
|
|
9
|
+
}>>;
|
|
10
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ContentfulApi = void 0;
|
|
4
|
+
require("server-only");
|
|
5
|
+
const funnel_core_1 = require("@nascentdigital/funnel-core");
|
|
6
|
+
const api_1 = require("../../api");
|
|
7
|
+
const ContentfulAccess_1 = require("../ContentfulAccess");
|
|
8
|
+
const ContentfulApiCommand_1 = require("../ContentfulApiCommand");
|
|
9
|
+
// namespace
|
|
10
|
+
var ContentfulApi;
|
|
11
|
+
(function (ContentfulApi) {
|
|
12
|
+
// methods
|
|
13
|
+
async function process(request, NextResponse) {
|
|
14
|
+
// process command
|
|
15
|
+
try {
|
|
16
|
+
const data = await processCommand(request);
|
|
17
|
+
return NextResponse.json({ data });
|
|
18
|
+
}
|
|
19
|
+
// or return error on failure
|
|
20
|
+
catch (e) {
|
|
21
|
+
console.error('[ContentfulApi] caught error processing request', e);
|
|
22
|
+
// handle API error
|
|
23
|
+
if (e instanceof funnel_core_1.ApiError) {
|
|
24
|
+
return NextResponse.json({ error: e.serialize() }, { status: e.status });
|
|
25
|
+
}
|
|
26
|
+
// or handle other isometric errors
|
|
27
|
+
else {
|
|
28
|
+
return NextResponse.json({
|
|
29
|
+
error: e instanceof funnel_core_1.IsometricError
|
|
30
|
+
? e.serialize()
|
|
31
|
+
: new funnel_core_1.ServerError().serialize()
|
|
32
|
+
}, { status: 500 });
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
ContentfulApi.process = process;
|
|
37
|
+
})(ContentfulApi || (exports.ContentfulApi = ContentfulApi = {}));
|
|
38
|
+
// handler
|
|
39
|
+
async function processCommand(request) {
|
|
40
|
+
// parse payload (throw if not valid)
|
|
41
|
+
const command = await parseCommand(request);
|
|
42
|
+
// process command
|
|
43
|
+
switch (command.type) {
|
|
44
|
+
case 'GetAccessTokens': {
|
|
45
|
+
const { deliveryAccessToken, previewAccessToken } = api_1.ContentClient.Factory.get().forServer();
|
|
46
|
+
return { deliveryAccessToken, previewAccessToken };
|
|
47
|
+
}
|
|
48
|
+
default:
|
|
49
|
+
throw new funnel_core_1.NotImplementedError();
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
// helpers
|
|
53
|
+
async function parseCommand(request) {
|
|
54
|
+
// throw if it's not a post
|
|
55
|
+
if (request.method !== 'POST') {
|
|
56
|
+
throw new funnel_core_1.InvalidOperationError();
|
|
57
|
+
}
|
|
58
|
+
// parse payload (throw if not valid)
|
|
59
|
+
const command = await request.json();
|
|
60
|
+
if (!ContentfulApiCommand_1.ContentfulApiCommand.filter(command)) {
|
|
61
|
+
throw new funnel_core_1.ArgumentError('Invalid command');
|
|
62
|
+
}
|
|
63
|
+
// get site config
|
|
64
|
+
const brand = funnel_core_1.AppConfig.brand();
|
|
65
|
+
const client = api_1.ContentClient.Factory.get().forServer();
|
|
66
|
+
const siteConfig = await client.siteConfig.get({ brand });
|
|
67
|
+
// fail if config can't be resolved
|
|
68
|
+
if (!siteConfig) {
|
|
69
|
+
throw new funnel_core_1.ServerError('Unable to resolve site config');
|
|
70
|
+
}
|
|
71
|
+
// fail if not a match
|
|
72
|
+
else if (!(command.userId in siteConfig.access)) {
|
|
73
|
+
throw new funnel_core_1.NotAuthenticatedError();
|
|
74
|
+
}
|
|
75
|
+
// verify access
|
|
76
|
+
const access = new ContentfulAccess_1.ContentfulAccess(siteConfig.access[command.userId]);
|
|
77
|
+
if (access.token !== command.token || access.isExpired) {
|
|
78
|
+
throw new funnel_core_1.NotAuthenticatedError();
|
|
79
|
+
}
|
|
80
|
+
// return command
|
|
81
|
+
return command;
|
|
82
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export * from './models';
|
|
2
|
+
export * from './ContentfulAssetClient';
|
|
3
|
+
export * from './ContentfulAuthClient';
|
|
4
|
+
export * from './ContentfulChangeSetClient';
|
|
5
|
+
export * from './ContentfulCollectionClient';
|
|
6
|
+
export * from './ContentfulContentClient';
|
|
7
|
+
export * from './ContentfulContentClientFactory';
|
|
8
|
+
export * from './ContentfulPageClient';
|
|
9
|
+
export * from './ContentfulSiteConfigClient';
|
|
10
|
+
export * from './ContentfulUpgradeClient';
|
|
11
|
+
export * from './ContentfulUserClient';
|
|
12
|
+
export * from './IContentfulContentClient';
|
|
@@ -0,0 +1,28 @@
|
|
|
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("./models"), exports);
|
|
18
|
+
__exportStar(require("./ContentfulAssetClient"), exports);
|
|
19
|
+
__exportStar(require("./ContentfulAuthClient"), exports);
|
|
20
|
+
__exportStar(require("./ContentfulChangeSetClient"), exports);
|
|
21
|
+
__exportStar(require("./ContentfulCollectionClient"), exports);
|
|
22
|
+
__exportStar(require("./ContentfulContentClient"), exports);
|
|
23
|
+
__exportStar(require("./ContentfulContentClientFactory"), exports);
|
|
24
|
+
__exportStar(require("./ContentfulPageClient"), exports);
|
|
25
|
+
__exportStar(require("./ContentfulSiteConfigClient"), exports);
|
|
26
|
+
__exportStar(require("./ContentfulUpgradeClient"), exports);
|
|
27
|
+
__exportStar(require("./ContentfulUserClient"), exports);
|
|
28
|
+
__exportStar(require("./IContentfulContentClient"), exports);
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { Schema } from '@nascentdigital/funnel-core';
|
|
2
|
+
import { ContentfulData } from './ContentfulData';
|
|
3
|
+
export type ContentfulAssetData = ContentfulData<ContentfulAssetData.ContentType, Schema.Asset.Id> & Omit<Schema.AssetField.LinkedValue, 'id'>;
|
|
4
|
+
export declare namespace ContentfulAssetData {
|
|
5
|
+
const contentType: "asset";
|
|
6
|
+
type ContentType = typeof contentType;
|
|
7
|
+
function deserialize(data: ContentfulAssetData): Schema.Asset.Linked;
|
|
8
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ContentfulAssetData = void 0;
|
|
4
|
+
// extension
|
|
5
|
+
var ContentfulAssetData;
|
|
6
|
+
(function (ContentfulAssetData) {
|
|
7
|
+
// constants
|
|
8
|
+
ContentfulAssetData.contentType = 'asset';
|
|
9
|
+
// deserialize
|
|
10
|
+
function deserialize(data) {
|
|
11
|
+
// return asset
|
|
12
|
+
return {
|
|
13
|
+
__root: 'asset',
|
|
14
|
+
type: 'asset',
|
|
15
|
+
value: {
|
|
16
|
+
id: data.id,
|
|
17
|
+
url: data.url,
|
|
18
|
+
type: data.type,
|
|
19
|
+
size: data.size,
|
|
20
|
+
name: data.name,
|
|
21
|
+
description: data.description,
|
|
22
|
+
scope: data.scope,
|
|
23
|
+
tags: data.tags,
|
|
24
|
+
metadata: data.metadata
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
ContentfulAssetData.deserialize = deserialize;
|
|
29
|
+
})(ContentfulAssetData || (exports.ContentfulAssetData = ContentfulAssetData = {}));
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { RequiredBy, Schema } from '@nascentdigital/funnel-core';
|
|
2
|
+
import { ContentfulData } from './ContentfulData';
|
|
3
|
+
export type ContentfulCollectionData = ContentfulData<ContentfulCollectionData.ContentType, Schema.Collection.Id> & Omit<Schema.Collection.Data, 'id' | 'changeSetId' | 'snapshotId' | 'snapshot'>;
|
|
4
|
+
export declare namespace ContentfulCollectionData {
|
|
5
|
+
const contentType: "collection";
|
|
6
|
+
type ContentType = typeof contentType;
|
|
7
|
+
type ForSchema = Schema.Collection.Data & Pick<ContentfulData, 'references'>;
|
|
8
|
+
type Potential = RequiredBy<Partial<ContentfulCollectionData>, keyof ContentfulData<ContentfulCollectionData.ContentType, Schema.Collection.Id>>;
|
|
9
|
+
function deserialize(data: Potential, props?: ReadonlyArray<Schema.Collection.Data.Props.All>): ForSchema;
|
|
10
|
+
function deserializeRefs(refs: ContentfulData[]): Schema.Collection.References;
|
|
11
|
+
}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ContentfulCollectionData = void 0;
|
|
4
|
+
const funnel_core_1 = require("@nascentdigital/funnel-core");
|
|
5
|
+
const ContentfulAssetData_1 = require("./ContentfulAssetData");
|
|
6
|
+
// extension
|
|
7
|
+
var ContentfulCollectionData;
|
|
8
|
+
(function (ContentfulCollectionData) {
|
|
9
|
+
// constants
|
|
10
|
+
ContentfulCollectionData.contentType = 'collection';
|
|
11
|
+
function deserialize(data, props = funnel_core_1.Schema.Collection.Data.Props.all) {
|
|
12
|
+
var _a;
|
|
13
|
+
// create base collection
|
|
14
|
+
const collection = {
|
|
15
|
+
__root: 'collection',
|
|
16
|
+
id: data.id,
|
|
17
|
+
createdOn: data.createdOn,
|
|
18
|
+
updatedOn: data.updatedOn,
|
|
19
|
+
references: (_a = data.references) !== null && _a !== void 0 ? _a : []
|
|
20
|
+
};
|
|
21
|
+
// helper
|
|
22
|
+
const bindProp = (prop, target, transform) => {
|
|
23
|
+
if (prop in data) {
|
|
24
|
+
collection[target] = transform(data[prop]);
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
// bind required props to page
|
|
28
|
+
for (const prop of props) {
|
|
29
|
+
switch (prop) {
|
|
30
|
+
// handled by base
|
|
31
|
+
case 'id':
|
|
32
|
+
case 'createdOn':
|
|
33
|
+
case 'updatedOn':
|
|
34
|
+
break;
|
|
35
|
+
// direct transforms
|
|
36
|
+
case 'groupId':
|
|
37
|
+
case 'type':
|
|
38
|
+
case 'brand':
|
|
39
|
+
case 'language':
|
|
40
|
+
case 'version':
|
|
41
|
+
case 'name':
|
|
42
|
+
case 'state':
|
|
43
|
+
case 'errors':
|
|
44
|
+
case 'pageIds':
|
|
45
|
+
case 'tags':
|
|
46
|
+
case 'publishedOn':
|
|
47
|
+
bindProp(prop, prop, value => value !== null && value !== void 0 ? value : undefined);
|
|
48
|
+
break;
|
|
49
|
+
// content
|
|
50
|
+
case 'fields':
|
|
51
|
+
bindProp(prop, prop, value => value !== null && value !== void 0 ? value : {});
|
|
52
|
+
break;
|
|
53
|
+
// ignore
|
|
54
|
+
case 'files':
|
|
55
|
+
case 'collections':
|
|
56
|
+
case 'snapshot':
|
|
57
|
+
case 'snapshotId':
|
|
58
|
+
case 'changeSetId':
|
|
59
|
+
break;
|
|
60
|
+
// unhandled
|
|
61
|
+
default:
|
|
62
|
+
throw new funnel_core_1.NotImplementedError(`Missing support for transforming collection "${prop}" prop`);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
// return collection
|
|
66
|
+
return collection;
|
|
67
|
+
}
|
|
68
|
+
ContentfulCollectionData.deserialize = deserialize;
|
|
69
|
+
// deserialize references
|
|
70
|
+
function deserializeRefs(refs) {
|
|
71
|
+
// setup
|
|
72
|
+
const files = {};
|
|
73
|
+
const collections = {};
|
|
74
|
+
// loop over references and serialize
|
|
75
|
+
for (const ref of refs) {
|
|
76
|
+
switch (ref.__type) {
|
|
77
|
+
// asset
|
|
78
|
+
case ContentfulAssetData_1.ContentfulAssetData.contentType: {
|
|
79
|
+
const assetRef = ref;
|
|
80
|
+
files[assetRef.id] = ContentfulAssetData_1.ContentfulAssetData.deserialize(assetRef);
|
|
81
|
+
break;
|
|
82
|
+
}
|
|
83
|
+
// collection
|
|
84
|
+
case ContentfulCollectionData.contentType: {
|
|
85
|
+
const collectionRef = ref;
|
|
86
|
+
collections[collectionRef.id] = ContentfulCollectionData.deserialize(collectionRef, funnel_core_1.Schema.Collection.Data.AsLink.props);
|
|
87
|
+
break;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
// return
|
|
92
|
+
return {
|
|
93
|
+
files,
|
|
94
|
+
collections
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
ContentfulCollectionData.deserializeRefs = deserializeRefs;
|
|
98
|
+
})(ContentfulCollectionData || (exports.ContentfulCollectionData = ContentfulCollectionData = {}));
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { EntryAPI } from '@contentful/app-sdk';
|
|
2
|
+
import type { Entry } from 'contentful';
|
|
3
|
+
import type { EntryProps } from 'contentful-management';
|
|
4
|
+
export type ContentfulData<TType extends string = string, TId extends string = string> = {
|
|
5
|
+
__type: TType;
|
|
6
|
+
__version: number;
|
|
7
|
+
id: TId;
|
|
8
|
+
createdOn: number;
|
|
9
|
+
updatedOn: number;
|
|
10
|
+
references: ContentfulData.References;
|
|
11
|
+
};
|
|
12
|
+
export declare namespace ContentfulData {
|
|
13
|
+
type ContentType<T extends ContentfulData> = T['__type'];
|
|
14
|
+
type EntryId<T extends ContentfulData> = T['id'];
|
|
15
|
+
type References = Array<Link.Entry | Link.Asset>;
|
|
16
|
+
type Draft<T extends ContentfulData> = Omit<T, keyof ContentfulData>;
|
|
17
|
+
type Link<TType extends Link.Type = Link.Type> = {
|
|
18
|
+
sys: {
|
|
19
|
+
type: 'Link';
|
|
20
|
+
linkType: TType;
|
|
21
|
+
id: string;
|
|
22
|
+
};
|
|
23
|
+
};
|
|
24
|
+
namespace Link {
|
|
25
|
+
type Type = 'Asset' | 'Entry' | 'Upload';
|
|
26
|
+
type Asset = Link<'Asset'>;
|
|
27
|
+
type Entry = Link<'Entry'>;
|
|
28
|
+
function create<TType extends Type>(id: string, linkType: TType): Link<TType>;
|
|
29
|
+
}
|
|
30
|
+
type Fields<TData extends Record<string, any>> = {
|
|
31
|
+
[TKey in Exclude<keyof TData, keyof ContentfulData>]: {
|
|
32
|
+
[locale: string]: TData[TKey];
|
|
33
|
+
};
|
|
34
|
+
};
|
|
35
|
+
function toEntryData<T extends Record<string, any>>(entry: T, locale: string): Fields<T>;
|
|
36
|
+
function fromEntryData<T extends ContentfulData>(entry: EntryAPI): T;
|
|
37
|
+
function fromCdaData<T extends ContentfulData>({ sys, fields }: Entry): T;
|
|
38
|
+
function fromCmaData<T extends ContentfulData>({ sys, fields }: EntryProps, locale: string): T;
|
|
39
|
+
function findReferences(source: object): References;
|
|
40
|
+
}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ContentfulData = void 0;
|
|
4
|
+
const funnel_core_1 = require("@nascentdigital/funnel-core");
|
|
5
|
+
var ContentfulData;
|
|
6
|
+
(function (ContentfulData) {
|
|
7
|
+
let Link;
|
|
8
|
+
(function (Link) {
|
|
9
|
+
// helpers
|
|
10
|
+
function create(id, linkType) {
|
|
11
|
+
return {
|
|
12
|
+
sys: {
|
|
13
|
+
type: 'Link',
|
|
14
|
+
linkType,
|
|
15
|
+
id
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
Link.create = create;
|
|
20
|
+
})(Link = ContentfulData.Link || (ContentfulData.Link = {}));
|
|
21
|
+
// helpers
|
|
22
|
+
function toEntryData(entry, locale) {
|
|
23
|
+
return Object.entries(entry).reduce((entryData, [keyRaw, value]) => {
|
|
24
|
+
// map entry (bucket under locale)
|
|
25
|
+
const key = keyRaw;
|
|
26
|
+
entryData[key] = { [locale]: value };
|
|
27
|
+
// keep reducing
|
|
28
|
+
return entryData;
|
|
29
|
+
}, {});
|
|
30
|
+
}
|
|
31
|
+
ContentfulData.toEntryData = toEntryData;
|
|
32
|
+
function fromEntryData(entry) {
|
|
33
|
+
// get sys
|
|
34
|
+
const sys = entry.getSys();
|
|
35
|
+
// simplify fields (remove locale)
|
|
36
|
+
const normalizedFields = {};
|
|
37
|
+
for (const key in entry.fields) {
|
|
38
|
+
normalizedFields[key] = entry.fields[key].getValue();
|
|
39
|
+
}
|
|
40
|
+
// return normalized form
|
|
41
|
+
return Object.assign({ __type: sys.contentType.sys.id, __version: sys.version, id: sys.id, createdOn: new Date(sys.createdAt).getTime(), updatedOn: new Date(sys.updatedAt).getTime() }, normalizedFields);
|
|
42
|
+
}
|
|
43
|
+
ContentfulData.fromEntryData = fromEntryData;
|
|
44
|
+
function fromCdaData({ sys, fields }) {
|
|
45
|
+
// simplify fields (remove locale)
|
|
46
|
+
const normalizedFields = {};
|
|
47
|
+
for (const key in fields) {
|
|
48
|
+
normalizedFields[key] = fields[key];
|
|
49
|
+
}
|
|
50
|
+
// return normalized form
|
|
51
|
+
return Object.assign({ __type: sys.contentType.sys.id, __version: sys.revision, id: sys.id, createdOn: new Date(sys.createdAt).getTime(), updatedOn: new Date(sys.updatedAt).getTime() }, normalizedFields);
|
|
52
|
+
}
|
|
53
|
+
ContentfulData.fromCdaData = fromCdaData;
|
|
54
|
+
function fromCmaData({ sys, fields }, locale) {
|
|
55
|
+
// simplify fields (remove locale)
|
|
56
|
+
const normalizedFields = {};
|
|
57
|
+
for (const key in fields) {
|
|
58
|
+
normalizedFields[key] = fields[key][locale];
|
|
59
|
+
}
|
|
60
|
+
// return normalized form
|
|
61
|
+
return Object.assign({ __type: sys.contentType.sys.id, __version: sys.version, id: sys.id, createdOn: new Date(sys.createdAt).getTime(), updatedOn: new Date(sys.updatedAt).getTime() }, normalizedFields);
|
|
62
|
+
}
|
|
63
|
+
ContentfulData.fromCmaData = fromCmaData;
|
|
64
|
+
function findReferences(source) {
|
|
65
|
+
// prepare sets
|
|
66
|
+
const references = [];
|
|
67
|
+
// extract actual refs
|
|
68
|
+
funnel_core_1.ObjectUtils.walk(source, ({ value }) => {
|
|
69
|
+
// track assets
|
|
70
|
+
if (funnel_core_1.Schema.Asset.filter(value)) {
|
|
71
|
+
// track file (if it's real)
|
|
72
|
+
const assetId = funnel_core_1.Schema.Asset.getId(value);
|
|
73
|
+
if (assetId) {
|
|
74
|
+
references.push(ContentfulData.Link.create(assetId, 'Entry'));
|
|
75
|
+
}
|
|
76
|
+
// don't recurse
|
|
77
|
+
return false;
|
|
78
|
+
}
|
|
79
|
+
// track page links
|
|
80
|
+
else if (funnel_core_1.Schema.Field.Data.InternalLink.filter(value)) {
|
|
81
|
+
// track page (only if the id's real)
|
|
82
|
+
const pageId = funnel_core_1.Schema.Field.Data.InternalLink.getId(value);
|
|
83
|
+
if (pageId && pageId !== funnel_core_1.Schema.Page.Id.draft) {
|
|
84
|
+
references.push(ContentfulData.Link.create(pageId, 'Entry'));
|
|
85
|
+
}
|
|
86
|
+
// don't recurse
|
|
87
|
+
return false;
|
|
88
|
+
}
|
|
89
|
+
// transform collection refs
|
|
90
|
+
else if (funnel_core_1.Schema.Field.Data.Collection.Ref.filter(value)) {
|
|
91
|
+
// track collection (only if the id's real)
|
|
92
|
+
const collectionId = funnel_core_1.Schema.Field.Data.Collection.Ref.getId(value);
|
|
93
|
+
if (collectionId && collectionId !== funnel_core_1.Schema.Collection.Id.draft) {
|
|
94
|
+
references.push(ContentfulData.Link.create(collectionId, 'Entry'));
|
|
95
|
+
}
|
|
96
|
+
// don't recurse
|
|
97
|
+
return false;
|
|
98
|
+
}
|
|
99
|
+
// transform page refs
|
|
100
|
+
else if (funnel_core_1.Schema.Field.Data.Page.filter(value)) {
|
|
101
|
+
// track page (only if the id's real)
|
|
102
|
+
const pageId = funnel_core_1.Schema.Field.Data.Page.getId(value);
|
|
103
|
+
if (pageId && pageId !== funnel_core_1.Schema.Page.Id.draft) {
|
|
104
|
+
references.push(ContentfulData.Link.create(pageId, 'Entry'));
|
|
105
|
+
}
|
|
106
|
+
// don't recurse
|
|
107
|
+
return false;
|
|
108
|
+
}
|
|
109
|
+
// otherwise recurse deeper
|
|
110
|
+
else {
|
|
111
|
+
return true;
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
// return references
|
|
115
|
+
return references;
|
|
116
|
+
}
|
|
117
|
+
ContentfulData.findReferences = findReferences;
|
|
118
|
+
})(ContentfulData || (exports.ContentfulData = ContentfulData = {}));
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { RequiredBy, Schema } from '@nascentdigital/funnel-core';
|
|
2
|
+
import { ContentfulData } from './ContentfulData';
|
|
3
|
+
export type ContentfulPageData = ContentfulData<ContentfulPageData.ContentType, Schema.Page.Id> & Omit<Schema.Page.Data, 'id' | 'changeSetId' | 'snapshotId' | 'snapshot'>;
|
|
4
|
+
export declare namespace ContentfulPageData {
|
|
5
|
+
const contentType: "page";
|
|
6
|
+
type ContentType = typeof contentType;
|
|
7
|
+
const referencesSpec: {
|
|
8
|
+
readonly page: "pages";
|
|
9
|
+
readonly collection: "collections";
|
|
10
|
+
readonly asset: "files";
|
|
11
|
+
};
|
|
12
|
+
type ReferencesSpec = typeof referencesSpec;
|
|
13
|
+
type ForSchema = Schema.Page.Data & Pick<ContentfulData, 'references'>;
|
|
14
|
+
type Potential = RequiredBy<Partial<ContentfulPageData>, keyof ContentfulData<ContentfulPageData.ContentType, Schema.Page.Id>>;
|
|
15
|
+
function deserialize(data: Potential, props?: ReadonlyArray<Schema.Page.Data.Props.All>): ForSchema;
|
|
16
|
+
function deserializeRefs(refs: ContentfulData[]): Schema.Page.References;
|
|
17
|
+
}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ContentfulPageData = void 0;
|
|
4
|
+
const funnel_core_1 = require("@nascentdigital/funnel-core");
|
|
5
|
+
const ContentfulAssetData_1 = require("./ContentfulAssetData");
|
|
6
|
+
const ContentfulCollectionData_1 = require("./ContentfulCollectionData");
|
|
7
|
+
// extension
|
|
8
|
+
var ContentfulPageData;
|
|
9
|
+
(function (ContentfulPageData) {
|
|
10
|
+
// constants
|
|
11
|
+
ContentfulPageData.contentType = 'page';
|
|
12
|
+
ContentfulPageData.referencesSpec = {
|
|
13
|
+
'page': 'pages',
|
|
14
|
+
'collection': 'collections',
|
|
15
|
+
'asset': 'files'
|
|
16
|
+
};
|
|
17
|
+
function deserialize(data, props = funnel_core_1.Schema.Page.Data.Props.all) {
|
|
18
|
+
var _a;
|
|
19
|
+
// create base page
|
|
20
|
+
const page = {
|
|
21
|
+
__root: 'page',
|
|
22
|
+
id: data.id,
|
|
23
|
+
createdOn: data.createdOn,
|
|
24
|
+
updatedOn: data.updatedOn,
|
|
25
|
+
references: (_a = data.references) !== null && _a !== void 0 ? _a : []
|
|
26
|
+
};
|
|
27
|
+
// helper
|
|
28
|
+
const bindProp = (prop, target, transform) => {
|
|
29
|
+
if (prop in data) {
|
|
30
|
+
page[target] = transform(data[prop]);
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
// bind required props to page
|
|
34
|
+
for (const prop of props) {
|
|
35
|
+
switch (prop) {
|
|
36
|
+
// handled by base
|
|
37
|
+
case 'id':
|
|
38
|
+
case 'createdOn':
|
|
39
|
+
case 'updatedOn':
|
|
40
|
+
break;
|
|
41
|
+
// direct transforms
|
|
42
|
+
case 'groupId':
|
|
43
|
+
case 'brand':
|
|
44
|
+
case 'region':
|
|
45
|
+
case 'language':
|
|
46
|
+
case 'type':
|
|
47
|
+
case 'slug':
|
|
48
|
+
case 'url':
|
|
49
|
+
case 'name':
|
|
50
|
+
case 'preview':
|
|
51
|
+
case 'state':
|
|
52
|
+
case 'errors':
|
|
53
|
+
case 'tags':
|
|
54
|
+
case 'publishedOn':
|
|
55
|
+
case 'publication':
|
|
56
|
+
bindProp(prop, prop, value => value !== null && value !== void 0 ? value : undefined);
|
|
57
|
+
break;
|
|
58
|
+
// content
|
|
59
|
+
case 'discover':
|
|
60
|
+
case 'content':
|
|
61
|
+
bindProp(prop, prop, value => value !== null && value !== void 0 ? value : {});
|
|
62
|
+
break;
|
|
63
|
+
// ignore
|
|
64
|
+
case 'files':
|
|
65
|
+
case 'pages':
|
|
66
|
+
case 'collections':
|
|
67
|
+
case 'snapshot':
|
|
68
|
+
case 'snapshotId':
|
|
69
|
+
case 'changeSetId':
|
|
70
|
+
break;
|
|
71
|
+
// unhandled
|
|
72
|
+
default:
|
|
73
|
+
throw new funnel_core_1.NotImplementedError(`Missing support for transforming page "${prop}" prop`);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
// return page
|
|
77
|
+
return page;
|
|
78
|
+
}
|
|
79
|
+
ContentfulPageData.deserialize = deserialize;
|
|
80
|
+
// deserialize references
|
|
81
|
+
function deserializeRefs(refs) {
|
|
82
|
+
// setup
|
|
83
|
+
const files = {};
|
|
84
|
+
const collections = {};
|
|
85
|
+
const pages = {};
|
|
86
|
+
// loop over references and serialize
|
|
87
|
+
for (const ref of refs) {
|
|
88
|
+
switch (ref.__type) {
|
|
89
|
+
// asset
|
|
90
|
+
case ContentfulAssetData_1.ContentfulAssetData.contentType: {
|
|
91
|
+
const assetRef = ref;
|
|
92
|
+
files[assetRef.id] = ContentfulAssetData_1.ContentfulAssetData.deserialize(assetRef);
|
|
93
|
+
break;
|
|
94
|
+
}
|
|
95
|
+
// collection
|
|
96
|
+
case ContentfulCollectionData_1.ContentfulCollectionData.contentType: {
|
|
97
|
+
const collectionRef = ref;
|
|
98
|
+
collections[collectionRef.id] = ContentfulCollectionData_1.ContentfulCollectionData.deserialize(collectionRef, funnel_core_1.Schema.Collection.Data.AsLink.props);
|
|
99
|
+
break;
|
|
100
|
+
}
|
|
101
|
+
// page
|
|
102
|
+
case ContentfulPageData.contentType: {
|
|
103
|
+
const pageRef = ref;
|
|
104
|
+
pages[pageRef.id] = ContentfulPageData.deserialize(pageRef, funnel_core_1.Schema.Page.Data.Props.all);
|
|
105
|
+
break;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
// return
|
|
110
|
+
return {
|
|
111
|
+
files,
|
|
112
|
+
collections,
|
|
113
|
+
pages
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
ContentfulPageData.deserializeRefs = deserializeRefs;
|
|
117
|
+
})(ContentfulPageData || (exports.ContentfulPageData = ContentfulPageData = {}));
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { SiteConfig, User } from '../../models';
|
|
2
|
+
import { ContentfulAccess } from '../ContentfulAccess';
|
|
3
|
+
import { ContentfulData } from './ContentfulData';
|
|
4
|
+
export type ContentfulSiteConfigData = Omit<SiteConfig.Data, 'id'> & ContentfulData<ContentfulSiteConfigData.ContentType, SiteConfig.Id> & {
|
|
5
|
+
access: Record<User.Id, ContentfulAccess.Data>;
|
|
6
|
+
};
|
|
7
|
+
export declare namespace ContentfulSiteConfigData {
|
|
8
|
+
const contentType: "siteConfig";
|
|
9
|
+
type ContentType = typeof contentType;
|
|
10
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ContentfulSiteConfigData = void 0;
|
|
4
|
+
// extension
|
|
5
|
+
var ContentfulSiteConfigData;
|
|
6
|
+
(function (ContentfulSiteConfigData) {
|
|
7
|
+
// constants
|
|
8
|
+
ContentfulSiteConfigData.contentType = 'siteConfig';
|
|
9
|
+
})(ContentfulSiteConfigData || (exports.ContentfulSiteConfigData = ContentfulSiteConfigData = {}));
|