Skip to content

WIP: create from template with body inclusion #1

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion examples/pages/create-from-template/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ const { createFromTemplate } = require('../../shared/create-from-template');
const titledDate = require('../../shared/titled-date');
const { log } = require('../../shared/utils');

const templateId = 'da29caf7fb84440f80f2a0ed9804b6e7';
const templateId = '2aff60e00a314bffb1a53971c9a756ff';
const argv = yargs.default({ templateId }).argv;

(async () => {
Expand Down
30 changes: 29 additions & 1 deletion examples/pages/create/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ const props = require('../../shared/props');
const titledDate = require('../../shared/titled-date');
const { log } = require('../../shared/utils');

const databaseId = '7b71eb300cbf4f4998f8c2208d733ee2';
const databaseId = '9e0d31a2f1bb41a1992b4e6f7f122a5f';
const argv = yargs.default({ databaseId }).argv;

const params = {
Expand All @@ -12,6 +12,34 @@ const params = {
},
icon: props.icon('👨‍🚒'),
properties: titledDate('Duty Crew'),
children: [
{
type: 'paragraph',
paragraph: {
text: [
{
type: 'text',
text: {
content: 'Level 1',
},
},
],
children: [
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

raises error, no children of children

{
type: 'paragraph',
text: [
{
type: 'text',
text: {
content: 'Level 2',
},
},
],
},
],
},
},
],
};

(async () => {
Expand Down
96 changes: 91 additions & 5 deletions examples/shared/create-from-template.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,28 @@
const { notion } = require('./index');
const { RateLimit } = require('async-sema');
const _ = require('lodash');
const { argv } = require('yargs');
const { notion } = require('./index');
const { log } = require('../shared/utils');

const limit = RateLimit(3);

// Properties we do not want to try to copy from template
const INVALID_PROP_TYPES = ['formula', 'rollup', 'title'];

// Blocks not supported for creation in the Notion API yet
const INVALID_BLOCK_TYPES = ['child_database'];

function pickValidTypes(objects, invalid_types, checkPresence = true) {
return _.pickBy(objects, (object) => {
return (
!invalid_types.includes(object.type) && !(checkPresence && _.isEmpty(object[object.type]))
);
});
}

function getTemplateProperties(properties) {
return _.reduce(
_.pickBy(properties, (prop) => {
return !INVALID_PROP_TYPES.includes(prop.type) && !_.isEmpty(prop[prop.type]);
}),
pickValidTypes(properties, INVALID_PROP_TYPES),
(props, prop, name) => {
props[name] = _.pick(prop, [prop.type]);
return props;
Expand All @@ -17,7 +31,64 @@ function getTemplateProperties(properties) {
);
}

async function createFromTemplate(template, properties) {
function getBlockValues(blocks) {
return _.map(pickValidTypes(blocks, INVALID_BLOCK_TYPES, false), (block) => {
const definition = {
type: block.type,
[block.type]: block[block.type],
};

if (block.children) {
definition.children = getBlockValues(block.children);
}

return definition;
});
}

async function fetchBlockChildren(blockId, startCursor = null) {
log(`fetchBlockChildren: ${blockId}, ${startCursor}`);

const params = {
block_id: blockId,
page_size: 100,
};

if (startCursor) {
params.start_cursor = startCursor;
}

return await notion.blocks.children.list(params);
}

async function fetchAllBlockChildren(blockId) {
log(`fetchAllBlockChildren: ${blockId}`);

let blocks = [];
let hasMore = true;
let startCursor = null;

while (hasMore) {
await limit();
const response = await fetchBlockChildren(blockId, startCursor);

blocks = blocks.concat(response.results);

hasMore = response.has_more;
startCursor = response.next_cursor;
}

for (const block of blocks) {
if (block.has_children) {
await limit();
block.children = await fetchAllBlockChildren(block.id);
}
}

return blocks;
}

async function createFromTemplate(template, properties, includeBlocks = true) {
if (typeof template === 'string') {
template = await notion.pages.retrieve({ page_id: template });
}
Expand All @@ -30,11 +101,26 @@ async function createFromTemplate(template, properties) {
icon: template.icon,
properties,
};
// log(template);

if (includeBlocks) {
const blocks = await fetchAllBlockChildren(template.id);

if (!_.isEmpty(blocks)) {
params.children = getBlockValues(blocks);
}

// log(blocks);
log(params.children);

// return params;
}

return await notion.pages.create(params);
}

module.exports = {
createFromTemplate,
getBlockValues,
getTemplateProperties,
};
55 changes: 55 additions & 0 deletions examples/wordle/create-game/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
const { notion, yargs } = require('../../shared');
const { createFromTemplate } = require('../../shared/create-from-template');
const titledDate = require('../../shared/titled-date');
const { log } = require('../../shared/utils');
const words = require('./words');

// The "Wordle Words" database ID
const wordsDbId = '6e9aa51b6e284a7280506b595f91bd9c';
// The "Wordle Games" database ID
const gamesDbId = '9e0d31a2f1bb41a1992b4e6f7f122a5f';
// The "-> Wordle Game" template in the same database
const templateId = '2aff60e00a314bffb1a53971c9a756ff';

// Defaults can be supplied via the command line
const argv = yargs.default({
gamesDbId,
templateId,
wordsDbId,
}).argv;

// Pick a word, any word...
const randomWord = words[Math.floor(Math.random() * words.length)];

(async () => {
const {
results: [word],
} = await notion.databases.query({
database_id: argv.wordsDbId,
filter: {
property: 'Word',
text: {
equals: randomWord,
},
},
});

if (!word) {
throw new Error(`"${randomWord}" could not be found in the Wordle Words database`);
}

const params = {
...titledDate('Wordle'),
"Today's Word": {
relation: [
{
id: word.id,
},
],
},
};

const page = await createFromTemplate(argv.templateId, params);

log(page);
})();
Loading