185 lines
6.2 KiB
JavaScript
185 lines
6.2 KiB
JavaScript
#!/usr/bin/env node
|
|
/**
|
|
* Update Notion page properties (for database pages)
|
|
* Usage: update-page-properties.js <page-id> <property-name> <value> [--type select|multi_select|checkbox|number|url|email|date]
|
|
*/
|
|
|
|
const https = require('https');
|
|
|
|
const NOTION_API_KEY = process.env.NOTION_API_KEY;
|
|
const NOTION_VERSION = '2025-09-03';
|
|
|
|
if (!NOTION_API_KEY) {
|
|
console.error('Error: NOTION_API_KEY environment variable not set');
|
|
process.exit(1);
|
|
}
|
|
|
|
function notionRequest(path, method, data) {
|
|
return new Promise((resolve, reject) => {
|
|
const requestData = JSON.stringify(data);
|
|
|
|
const options = {
|
|
hostname: 'api.notion.com',
|
|
port: 443,
|
|
path: path,
|
|
method: method,
|
|
headers: {
|
|
'Authorization': `Bearer ${NOTION_API_KEY}`,
|
|
'Notion-Version': NOTION_VERSION,
|
|
'Content-Type': 'application/json',
|
|
'Content-Length': Buffer.byteLength(requestData)
|
|
}
|
|
};
|
|
|
|
const req = https.request(options, (res) => {
|
|
let body = '';
|
|
res.on('data', (chunk) => body += chunk);
|
|
res.on('end', () => {
|
|
if (res.statusCode >= 200 && res.statusCode < 300) {
|
|
resolve(JSON.parse(body));
|
|
} else {
|
|
const error = JSON.parse(body);
|
|
if (res.statusCode === 404 && error.code === 'object_not_found') {
|
|
reject(new Error('Page not found. Make sure it is shared with your integration.'));
|
|
} else if (res.statusCode === 401) {
|
|
reject(new Error('Authentication failed. Check your NOTION_API_KEY.'));
|
|
} else if (res.statusCode === 400 && error.code === 'validation_error') {
|
|
reject(new Error(`Validation error: ${error.message}. Check property name and type.`));
|
|
} else if (res.statusCode === 429) {
|
|
reject(new Error('Rate limit exceeded. Wait a moment and try again.'));
|
|
} else {
|
|
reject(new Error(`API error (${res.statusCode}): ${error.message || body}`));
|
|
}
|
|
}
|
|
});
|
|
});
|
|
|
|
req.on('error', reject);
|
|
req.write(requestData);
|
|
req.end();
|
|
});
|
|
}
|
|
|
|
function formatPropertyValue(propertyType, value) {
|
|
switch (propertyType) {
|
|
case 'select':
|
|
return { select: { name: value } };
|
|
|
|
case 'multi_select':
|
|
// Value can be comma-separated: "AI,Leadership,Research"
|
|
const tags = value.split(',').map(t => t.trim());
|
|
return { multi_select: tags.map(name => ({ name })) };
|
|
|
|
case 'checkbox':
|
|
const boolValue = value.toLowerCase() === 'true' || value === '1';
|
|
return { checkbox: boolValue };
|
|
|
|
case 'number':
|
|
return { number: parseFloat(value) };
|
|
|
|
case 'url':
|
|
return { url: value };
|
|
|
|
case 'email':
|
|
return { email: value };
|
|
|
|
case 'date':
|
|
// Value can be "2024-01-15" or "2024-01-15,2024-01-20" for range
|
|
const dates = value.split(',').map(d => d.trim());
|
|
return {
|
|
date: {
|
|
start: dates[0],
|
|
end: dates[1] || null
|
|
}
|
|
};
|
|
|
|
case 'rich_text':
|
|
return {
|
|
rich_text: [{ type: 'text', text: { content: value } }]
|
|
};
|
|
|
|
default:
|
|
throw new Error(`Unsupported property type: ${propertyType}. Supported: select, multi_select, checkbox, number, url, email, date, rich_text`);
|
|
}
|
|
}
|
|
|
|
async function updatePageProperties(pageId, propertyName, value, propertyType = 'select') {
|
|
const properties = {};
|
|
properties[propertyName] = formatPropertyValue(propertyType, value);
|
|
|
|
console.error(`Updating page: ${pageId}`);
|
|
console.error(`Property: ${propertyName} (${propertyType})`);
|
|
console.error(`Value: ${value}`);
|
|
|
|
const result = await notionRequest(`/v1/pages/${pageId}`, 'PATCH', { properties });
|
|
|
|
return {
|
|
id: result.id,
|
|
url: result.url,
|
|
updated: result.last_edited_time
|
|
};
|
|
}
|
|
|
|
// Main execution
|
|
(async () => {
|
|
try {
|
|
const args = process.argv.slice(2);
|
|
|
|
if (args.length < 3 || args[0] === '--help') {
|
|
console.log('Usage: update-page-properties.js <page-id> <property-name> <value> [--type <type>]');
|
|
console.log('');
|
|
console.log('Options:');
|
|
console.log(' --type <type> Property type (default: select)');
|
|
console.log('');
|
|
console.log('Supported types:');
|
|
console.log(' select Single choice (e.g., "Complete")');
|
|
console.log(' multi_select Multiple choices, comma-separated (e.g., "AI,Leadership")');
|
|
console.log(' checkbox Boolean (e.g., "true" or "false")');
|
|
console.log(' number Numeric value (e.g., "1200")');
|
|
console.log(' url URL string');
|
|
console.log(' email Email address');
|
|
console.log(' date Date or range (e.g., "2024-01-15" or "2024-01-15,2024-01-20")');
|
|
console.log(' rich_text Text content');
|
|
console.log('');
|
|
console.log('Examples:');
|
|
console.log(' # Set status to Complete');
|
|
console.log(' update-page-properties.js <page-id> Status Complete --type select');
|
|
console.log('');
|
|
console.log(' # Add multiple tags');
|
|
console.log(' update-page-properties.js <page-id> Tags "AI,Leadership,Research" --type multi_select');
|
|
console.log('');
|
|
console.log(' # Set checkbox');
|
|
console.log(' update-page-properties.js <page-id> Published true --type checkbox');
|
|
console.log('');
|
|
console.log(' # Set date');
|
|
console.log(' update-page-properties.js <page-id> "Publish Date" 2024-02-01 --type date');
|
|
console.log('');
|
|
console.log(' # Set URL');
|
|
console.log(' update-page-properties.js <page-id> "Source URL" "https://example.com" --type url');
|
|
process.exit(0);
|
|
}
|
|
|
|
const pageId = args[0];
|
|
const propertyName = args[1];
|
|
const value = args[2];
|
|
let propertyType = 'select';
|
|
|
|
for (let i = 3; i < args.length; i++) {
|
|
if (args[i] === '--type' && args[i + 1]) {
|
|
propertyType = args[i + 1];
|
|
i++;
|
|
}
|
|
}
|
|
|
|
const result = await updatePageProperties(pageId, propertyName, value, propertyType);
|
|
|
|
console.log(JSON.stringify(result, null, 2));
|
|
console.error(`\n✓ Page updated successfully`);
|
|
console.error(` URL: ${result.url}`);
|
|
|
|
} catch (error) {
|
|
console.error('Error:', error.message);
|
|
process.exit(1);
|
|
}
|
|
})();
|