Skip to content
This repository has been archived by the owner on Feb 6, 2024. It is now read-only.

Commit

Permalink
feat: support for multiple doc ids in blogs (#40)
Browse files Browse the repository at this point in the history
  • Loading branch information
peterpeterparker authored Nov 4, 2022
1 parent 6c155fa commit 00d94c2
Show file tree
Hide file tree
Showing 8 changed files with 62 additions and 38 deletions.
4 changes: 2 additions & 2 deletions providers/ic/src/providers/publish/publish.providers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export const deckPublish: DeckPublish = async ({

await uploadResources({
meta: deck.data.meta,
hoisted: {
ids: {
...canisterIds,
data_id: deck.id
}
Expand Down Expand Up @@ -53,7 +53,7 @@ export const docPublish: DocPublish = async ({

await uploadResources({
meta: doc.data.meta,
hoisted: {
ids: {
...canisterIds,
data_id: doc.id
}
Expand Down
40 changes: 30 additions & 10 deletions providers/ic/src/publish/common.publish.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ import {log, Meta, PublishData} from '@deckdeckgo/editor';
import {encodeFilename, getStorageActor, upload} from '../api/storage.api';
import {_SERVICE as StorageBucketActor} from '../canisters/storage/storage.did';
import {EnvStore} from '../stores/env.store';
import {PublishCanisterIds} from '../types/publish.types';
import {PublishCanisterIds, PublishIds} from '../types/publish.types';
import {digestMessage, sha256ToBase64String} from '../utils/crypto.utils';
import {BucketActor} from '../utils/manager.utils';
import {updateTemplateSocialImage} from './social.publish';

Expand All @@ -16,16 +17,17 @@ export interface StorageUpload {
folder: 'p' | 'd';
}

export const updateTemplate = ({
export const updateTemplate = async ({
template,
data,
canisterIds
ids
}: {
template: string;
data: Partial<PublishData>;
canisterIds: PublishCanisterIds;
}): string =>
[...Object.entries(data), ...Object.entries(canisterIds)].reduce(
ids: PublishIds | PublishCanisterIds;
}): Promise<string> => {
// 1. Replace all keys
const updatedTemplate: string = [...Object.entries(data), ...Object.entries(ids)].reduce(
(acc: string, [key, value]: [string, string]) =>
acc
.replaceAll(`{{DECKDECKGO_${key.toUpperCase()}}}`, value || '')
Expand All @@ -34,6 +36,24 @@ export const updateTemplate = ({
template
);

// 2. Build a script that injects canisters and data ids
const {data_canister_id, storage_canister_id} = ids;
const {data_id} = ids as PublishIds;

const idsScript: string = `window.data_canister_id = "${data_canister_id}";window.storage_canister_id = "${storage_canister_id}";window.data_id = "${data_id ?? ''}";`;

const templateWithScript: string = updatedTemplate.replaceAll(
'<!-- DECKDECKGO_IDS_SCRIPT -->',
`<script>${idsScript}</script>`
);

// 3. Calculate a sha256 for the above script and parse it in the CSP
const sha256: string = sha256ToBase64String(new Uint8Array(await digestMessage(idsScript)));
const templateWithCSP: string = templateWithScript.replaceAll('{{DECKDECKGO_IDS_SHAS}}', `'sha256-${sha256}'`);

return templateWithCSP;
};

export const initUpload = async ({
indexHTML,
folder,
Expand Down Expand Up @@ -110,21 +130,21 @@ const uploadPaths = ({

export const initIndexHTML = async ({
publishData,
canisterIds,
ids,
updateTemplateContent,
sourceFolder
}: {
publishData: PublishData;
canisterIds: PublishCanisterIds;
ids: PublishIds;
updateTemplateContent: ({attr, template}: {attr: string | undefined; template: string}) => string;
sourceFolder: 'p' | 'd';
}): Promise<{html: string}> => {
const template: string = await htmlTemplate(sourceFolder);

const updatedTemplate: string = updateTemplate({
const updatedTemplate: string = await updateTemplate({
template,
data: publishData,
canisterIds
ids
});

const {attributes} = publishData;
Expand Down
5 changes: 4 additions & 1 deletion providers/ic/src/publish/deck.publish.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,10 @@ const initDeckIndexHTML = async ({

const {html}: {html: string} = await initIndexHTML({
publishData,
canisterIds,
ids: {
...canisterIds,
data_id: deck.id
},
updateTemplateContent,
sourceFolder: 'p'
});
Expand Down
5 changes: 4 additions & 1 deletion providers/ic/src/publish/doc.publish.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,10 @@ const initDocIndexHTML = async ({

const {html}: {html: string} = await initIndexHTML({
publishData,
canisterIds,
ids: {
...canisterIds,
data_id: doc.id
},
updateTemplateContent,
sourceFolder: 'd'
});
Expand Down
2 changes: 1 addition & 1 deletion providers/ic/src/publish/index-html.publish.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export const prepareIndexHtml = async ({

const {photo_url, ...data} = publishData;

let html: string = updateTemplate({template, data, canisterIds});
let html: string = await updateTemplate({template, data, ids: canisterIds});
html = updatePhotoUrl({html, photo_url});

html = updatePostsList({
Expand Down
39 changes: 17 additions & 22 deletions providers/ic/src/publish/resources.publish.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ import {log, Meta} from '@deckdeckgo/editor';
import {getStorageActor, upload} from '../api/storage.api';
import {AssetKey, _SERVICE as StorageBucketActor} from '../canisters/storage/storage.did';
import {EnvStore} from '../stores/env.store';
import {PublishHoistedData} from '../types/publish.types';
import {PublishIds} from '../types/publish.types';
import {HeaderField} from '../types/storage.types';
import {digestMessage} from '../utils/crypto.utils';
import {digestMessage, sha256ToBase64String} from '../utils/crypto.utils';
import {fromNullable, toNullable} from '../utils/did.utils';
import {BucketActor} from '../utils/manager.utils';
import {getAuthor} from './common.publish';
Expand All @@ -13,7 +13,7 @@ type KitMimeType = 'text/javascript' | 'text/plain' | 'application/manifest+json

interface KitUpdateContent {
meta: Meta | undefined;
hoisted: PublishHoistedData;
ids: PublishIds;
content: string;
}

Expand All @@ -28,16 +28,7 @@ interface Kit {

const getKitPath = (): string => EnvStore.getInstance().get().kitPath;

const sha256ToBase64String = (sha256: Iterable<number>): string =>
btoa([...sha256].map((c) => String.fromCharCode(c)).join(''));

export const uploadResources = async ({
meta,
hoisted
}: {
meta: Meta | undefined;
hoisted: PublishHoistedData;
}) => {
export const uploadResources = async ({meta, ids}: {meta: Meta | undefined; ids: PublishIds}) => {
// 1. Get actor
const {actor}: BucketActor<StorageBucketActor> = await getStorageActor();

Expand All @@ -48,7 +39,7 @@ export const uploadResources = async ({
const kit: Kit[] = await getKit();

const promises: Promise<void>[] = kit.map((kit: Kit) =>
addKitIC({kit, actor, meta, hoisted, assetKeys})
addKitIC({kit, actor, meta, ids, assetKeys})
);
await Promise.all(promises);
};
Expand All @@ -75,19 +66,19 @@ const addDynamicKitIC = async ({
kit,
actor,
meta,
hoisted,
ids,
assetKeys
}: {
kit: Kit;
actor: StorageBucketActor;
meta: Meta | undefined;
hoisted: PublishHoistedData;
ids: PublishIds;
assetKeys: AssetKey[];
}) => {
const {src, filename, mimeType, updateContent, headers} = kit;

const content: string = await downloadKit(src);
const updatedContent: string = updateContent({content, meta, hoisted});
const updatedContent: string = updateContent({content, meta, ids: ids});
const sha256: string = sha256ToBase64String(new Uint8Array(await digestMessage(updatedContent)));

if (!updatedResource({src, sha256, assetKeys})) {
Expand All @@ -108,21 +99,21 @@ const addKitIC = async ({
kit,
actor,
meta,
hoisted,
ids,
assetKeys
}: {
kit: Kit;
actor: StorageBucketActor;
meta: Meta | undefined;
hoisted: PublishHoistedData;
ids: PublishIds;
assetKeys: AssetKey[];
}) => {
const {updateContent} = kit;

// If updateContent is defined we have to compare the sha256 value of the content that will be updated first
// e.g. avoiding uploading the manifest at each publish
if (updateContent !== undefined) {
await addDynamicKitIC({kit, actor, meta, hoisted, assetKeys});
await addDynamicKitIC({kit, actor, meta, ids, assetKeys});

return;
}
Expand All @@ -135,7 +126,7 @@ const addKitIC = async ({

const content: string = await downloadKit(src);

const updatedContent: string = updateContent ? updateContent({content, meta, hoisted}) : content;
const updatedContent: string = updateContent ? updateContent({content, meta, ids: ids}) : content;

await uploadKit({
filename,
Expand Down Expand Up @@ -201,9 +192,13 @@ const getKit = async (): Promise<Kit[]> => {
src,
mimeType: 'text/javascript',
sha256,
updateContent: ({content, hoisted: {data_canister_id, data_id}}: KitUpdateContent) =>
updateContent: ({
content,
ids: {data_canister_id, data_id, storage_canister_id}
}: KitUpdateContent) =>
content
.replace('{{DECKDECKGO_DATA_CANISTER_ID}}', data_canister_id)
.replace('{{DECKDECKGO_STORAGE_CANISTER_ID}}', storage_canister_id)
.replace('{{DECKDECKGO_DATA_ID}}', data_id)
};
}
Expand Down
2 changes: 1 addition & 1 deletion providers/ic/src/types/publish.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,6 @@ export interface PublishCanisterIds {
storage_canister_id: string;
}

export interface PublishHoistedData extends PublishCanisterIds {
export interface PublishIds extends PublishCanisterIds {
data_id: string;
}
3 changes: 3 additions & 0 deletions providers/ic/src/utils/crypto.utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,6 @@ export const digestMessage = (message?: string): Promise<ArrayBuffer> => {
const data = encoder.encode(message);
return crypto.subtle.digest('SHA-256', data);
};

export const sha256ToBase64String = (sha256: Iterable<number>): string =>
btoa([...sha256].map((c) => String.fromCharCode(c)).join(''));

0 comments on commit 00d94c2

Please sign in to comment.