first commit
Security: Sync from Public / sync-from-public (push) Has been cancelled
Test: Benchmark Nightly / build (push) Has been cancelled
Test: Benchmark Nightly / Notify Cats on failure (push) Has been cancelled
CI: Python / Checks (push) Has been cancelled
Test: Evals Python / Workflow Comparison Python (push) Has been cancelled
Util: Check Docs URLs / check-docs-urls (push) Has been cancelled
Test: Visual Storybook / Cloudflare Pages (push) Has been cancelled
Test: E2E Performance / build-and-test-performance (push) Has been cancelled
Test: Workflows Nightly / Run Workflow Tests (push) Has been cancelled
Util: Cleanup CI Docker Images / Delete stale CI images (push) Has been cancelled
Test: Benchmark Destroy Env / build (push) Has been cancelled
Util: Update Node Popularity / update-popularity (push) Has been cancelled
Test: E2E Coverage Weekly / Coverage Tests (push) Has been cancelled
Security: Sync from Public / sync-from-public (push) Has been cancelled
Test: Benchmark Nightly / build (push) Has been cancelled
Test: Benchmark Nightly / Notify Cats on failure (push) Has been cancelled
CI: Python / Checks (push) Has been cancelled
Test: Evals Python / Workflow Comparison Python (push) Has been cancelled
Util: Check Docs URLs / check-docs-urls (push) Has been cancelled
Test: Visual Storybook / Cloudflare Pages (push) Has been cancelled
Test: E2E Performance / build-and-test-performance (push) Has been cancelled
Test: Workflows Nightly / Run Workflow Tests (push) Has been cancelled
Util: Cleanup CI Docker Images / Delete stale CI images (push) Has been cancelled
Test: Benchmark Destroy Env / build (push) Has been cancelled
Util: Update Node Popularity / update-popularity (push) Has been cancelled
Test: E2E Coverage Weekly / Coverage Tests (push) Has been cancelled
This commit is contained in:
@@ -0,0 +1,95 @@
|
||||
import type {
|
||||
IDataObject,
|
||||
IExecuteFunctions,
|
||||
IHookFunctions,
|
||||
ILoadOptionsFunctions,
|
||||
JsonObject,
|
||||
IRequestOptions,
|
||||
IHttpRequestMethods,
|
||||
} from 'n8n-workflow';
|
||||
import { NodeApiError } from 'n8n-workflow';
|
||||
|
||||
export async function storyblokApiRequest(
|
||||
this: IHookFunctions | IExecuteFunctions | ILoadOptionsFunctions,
|
||||
method: IHttpRequestMethods,
|
||||
resource: string,
|
||||
body: IDataObject = {},
|
||||
qs: IDataObject = {},
|
||||
option: IDataObject = {},
|
||||
) {
|
||||
const authenticationMethod = this.getNodeParameter('source', 0) as string;
|
||||
|
||||
let options: IRequestOptions = {
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
method,
|
||||
qs,
|
||||
body,
|
||||
uri: '',
|
||||
json: true,
|
||||
};
|
||||
|
||||
options = Object.assign({}, options, option);
|
||||
|
||||
if (Object.keys(options.body).length === 0) {
|
||||
delete options.body;
|
||||
}
|
||||
|
||||
if (authenticationMethod === 'contentApi') {
|
||||
const credentials = await this.getCredentials('storyblokContentApi');
|
||||
|
||||
options.uri = `https://api.storyblok.com${resource}`;
|
||||
|
||||
Object.assign(options.qs ?? {}, { token: credentials.apiKey });
|
||||
} else {
|
||||
const credentials = await this.getCredentials('storyblokManagementApi');
|
||||
|
||||
options.uri = `https://mapi.storyblok.com${resource}`;
|
||||
|
||||
if (options.headers) {
|
||||
Object.assign(options.headers, { Authorization: credentials.accessToken });
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
return await this.helpers.request(options);
|
||||
} catch (error) {
|
||||
throw new NodeApiError(this.getNode(), error as JsonObject);
|
||||
}
|
||||
}
|
||||
|
||||
export async function storyblokApiRequestAllItems(
|
||||
this: IHookFunctions | ILoadOptionsFunctions | IExecuteFunctions,
|
||||
propertyName: string,
|
||||
method: IHttpRequestMethods,
|
||||
resource: string,
|
||||
body: IDataObject = {},
|
||||
query: IDataObject = {},
|
||||
) {
|
||||
const returnData: IDataObject[] = [];
|
||||
|
||||
let responseData;
|
||||
|
||||
query.per_page = 100;
|
||||
|
||||
query.page = 1;
|
||||
|
||||
do {
|
||||
responseData = await storyblokApiRequest.call(this, method, resource, body, query);
|
||||
query.page++;
|
||||
returnData.push.apply(returnData, responseData[propertyName] as IDataObject[]);
|
||||
} while (responseData[propertyName].length !== 0);
|
||||
|
||||
return returnData;
|
||||
}
|
||||
|
||||
export function validateJSON(json: string | undefined): any {
|
||||
let result;
|
||||
try {
|
||||
result = JSON.parse(json!);
|
||||
} catch (exception) {
|
||||
result = undefined;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
import type { INodeProperties } from 'n8n-workflow';
|
||||
|
||||
export const storyContentOperations: INodeProperties[] = [
|
||||
{
|
||||
displayName: 'Operation',
|
||||
name: 'operation',
|
||||
type: 'options',
|
||||
noDataExpression: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
source: ['contentApi'],
|
||||
resource: ['story'],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
name: 'Get',
|
||||
value: 'get',
|
||||
description: 'Get a story',
|
||||
action: 'Get a story',
|
||||
},
|
||||
{
|
||||
name: 'Get Many',
|
||||
value: 'getAll',
|
||||
description: 'Get many stories',
|
||||
action: 'Get many stories',
|
||||
},
|
||||
],
|
||||
default: 'get',
|
||||
},
|
||||
];
|
||||
|
||||
export const storyContentFields: INodeProperties[] = [
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* story:get */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
{
|
||||
displayName: 'Identifier',
|
||||
name: 'identifier',
|
||||
type: 'string',
|
||||
default: '',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
source: ['contentApi'],
|
||||
resource: ['story'],
|
||||
operation: ['get'],
|
||||
},
|
||||
},
|
||||
description: 'The ID or slug of the story to get',
|
||||
},
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* story:getAll */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
{
|
||||
displayName: 'Return All',
|
||||
name: 'returnAll',
|
||||
type: 'boolean',
|
||||
displayOptions: {
|
||||
show: {
|
||||
source: ['contentApi'],
|
||||
resource: ['story'],
|
||||
operation: ['getAll'],
|
||||
},
|
||||
},
|
||||
default: false,
|
||||
description: 'Whether to return all results or only up to a given limit',
|
||||
},
|
||||
{
|
||||
displayName: 'Limit',
|
||||
name: 'limit',
|
||||
type: 'number',
|
||||
displayOptions: {
|
||||
show: {
|
||||
source: ['contentApi'],
|
||||
resource: ['story'],
|
||||
operation: ['getAll'],
|
||||
returnAll: [false],
|
||||
},
|
||||
},
|
||||
typeOptions: {
|
||||
minValue: 1,
|
||||
maxValue: 100,
|
||||
},
|
||||
default: 50,
|
||||
description: 'Max number of results to return',
|
||||
},
|
||||
{
|
||||
displayName: 'Filters',
|
||||
name: 'filters',
|
||||
type: 'collection',
|
||||
placeholder: 'Add Filter',
|
||||
default: {},
|
||||
displayOptions: {
|
||||
show: {
|
||||
source: ['contentApi'],
|
||||
resource: ['story'],
|
||||
operation: ['getAll'],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
displayName: 'Starts With',
|
||||
name: 'starts_with',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'Filter by slug',
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,571 @@
|
||||
import type { INodeProperties } from 'n8n-workflow';
|
||||
|
||||
export const storyManagementOperations: INodeProperties[] = [
|
||||
{
|
||||
displayName: 'Operation',
|
||||
name: 'operation',
|
||||
type: 'options',
|
||||
noDataExpression: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
source: ['managementApi'],
|
||||
resource: ['story'],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
// {
|
||||
// name: 'Create',
|
||||
// value: 'create',
|
||||
// description: 'Create a story',
|
||||
// },
|
||||
{
|
||||
name: 'Delete',
|
||||
value: 'delete',
|
||||
description: 'Delete a story',
|
||||
action: 'Delete a story',
|
||||
},
|
||||
{
|
||||
name: 'Get',
|
||||
value: 'get',
|
||||
description: 'Get a story',
|
||||
action: 'Get a story',
|
||||
},
|
||||
{
|
||||
name: 'Get Many',
|
||||
value: 'getAll',
|
||||
description: 'Get many stories',
|
||||
action: 'Get many stories',
|
||||
},
|
||||
{
|
||||
name: 'Publish',
|
||||
value: 'publish',
|
||||
description: 'Publish a story',
|
||||
action: 'Publish a story',
|
||||
},
|
||||
{
|
||||
name: 'Unpublish',
|
||||
value: 'unpublish',
|
||||
description: 'Unpublish a story',
|
||||
action: 'Unpublish a story',
|
||||
},
|
||||
],
|
||||
default: 'get',
|
||||
},
|
||||
];
|
||||
|
||||
export const storyManagementFields: INodeProperties[] = [
|
||||
// /* -------------------------------------------------------------------------- */
|
||||
// /* story:create */
|
||||
// /* -------------------------------------------------------------------------- */
|
||||
// {
|
||||
// displayName: 'Space ID',
|
||||
// name: 'space',
|
||||
// type: 'options',
|
||||
// typeOptions: {
|
||||
// loadOptionsMethod: 'getSpaces',
|
||||
// },
|
||||
// default: '',
|
||||
// required: true,
|
||||
// displayOptions: {
|
||||
// show: {
|
||||
// source: [
|
||||
// 'managementApi',
|
||||
// ],
|
||||
// resource: [
|
||||
// 'story',
|
||||
// ],
|
||||
// operation: [
|
||||
// 'create',
|
||||
// ],
|
||||
// },
|
||||
// },
|
||||
// description: 'The name of the space.',
|
||||
// },
|
||||
// {
|
||||
// displayName: 'Name',
|
||||
// name: 'name',
|
||||
// type: 'string',
|
||||
// default: '',
|
||||
// required: true,
|
||||
// displayOptions: {
|
||||
// show: {
|
||||
// source: [
|
||||
// 'managementApi',
|
||||
// ],
|
||||
// resource: [
|
||||
// 'story',
|
||||
// ],
|
||||
// operation: [
|
||||
// 'create',
|
||||
// ],
|
||||
// },
|
||||
// },
|
||||
// description: 'The name you give this story.',
|
||||
// },
|
||||
// {
|
||||
// displayName: 'Slug',
|
||||
// name: 'slug',
|
||||
// type: 'string',
|
||||
// default: '',
|
||||
// required: true,
|
||||
// displayOptions: {
|
||||
// show: {
|
||||
// source: [
|
||||
// 'managementApi',
|
||||
// ],
|
||||
// resource: [
|
||||
// 'story',
|
||||
// ],
|
||||
// operation: [
|
||||
// 'create',
|
||||
// ],
|
||||
// },
|
||||
// },
|
||||
// description: 'The slug/path you give this story.',
|
||||
// },
|
||||
// {
|
||||
// displayName: 'JSON Parameters',
|
||||
// name: 'jsonParameters',
|
||||
// type: 'boolean',
|
||||
// default: false,
|
||||
// description: '',
|
||||
// displayOptions: {
|
||||
// show: {
|
||||
// source: [
|
||||
// 'managementApi',
|
||||
// ],
|
||||
// resource: [
|
||||
// 'story',
|
||||
// ],
|
||||
// operation: [
|
||||
// 'create',
|
||||
// ],
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// displayName: 'Additional Fields',
|
||||
// name: 'additionalFields',
|
||||
// type: 'collection',
|
||||
// placeholder: 'Add Field',
|
||||
// displayOptions: {
|
||||
// show: {
|
||||
// source: [
|
||||
// 'managementApi',
|
||||
// ],
|
||||
// resource: [
|
||||
// 'story',
|
||||
// ],
|
||||
// operation: [
|
||||
// 'create',
|
||||
// ],
|
||||
// },
|
||||
// },
|
||||
// default: {},
|
||||
// options: [
|
||||
// {
|
||||
// displayName: 'Content',
|
||||
// name: 'contentUi',
|
||||
// type: 'fixedCollection',
|
||||
// description: 'Add Content',
|
||||
// typeOptions: {
|
||||
// multipleValues: false,
|
||||
// },
|
||||
// displayOptions: {
|
||||
// show: {
|
||||
// '/jsonParameters': [
|
||||
// false,
|
||||
// ],
|
||||
// },
|
||||
// },
|
||||
// placeholder: 'Add Content',
|
||||
// default: '',
|
||||
// options: [
|
||||
// {
|
||||
// displayName: 'Content Data',
|
||||
// name: 'contentValue',
|
||||
// values: [
|
||||
// {
|
||||
// displayName: 'Component',
|
||||
// name: 'component',
|
||||
// type: 'options',
|
||||
// typeOptions: {
|
||||
// loadOptionsMethod: 'getComponents',
|
||||
// loadOptionsDependsOn: [
|
||||
// 'space',
|
||||
// ],
|
||||
// },
|
||||
// default: '',
|
||||
// },
|
||||
// {
|
||||
// displayName: 'Elements',
|
||||
// name: 'elementUi',
|
||||
// type: 'fixedCollection',
|
||||
// description: 'Add Body',
|
||||
// typeOptions: {
|
||||
// multipleValues: true,
|
||||
// },
|
||||
// placeholder: 'Add Element',
|
||||
// default: '',
|
||||
// options: [
|
||||
// {
|
||||
// displayName: 'Element',
|
||||
// name: 'elementValues',
|
||||
// values: [
|
||||
// {
|
||||
// displayName: 'Component',
|
||||
// name: 'component',
|
||||
// type: 'options',
|
||||
// typeOptions: {
|
||||
// loadOptionsMethod: 'getComponents',
|
||||
// loadOptionsDependsOn: [
|
||||
// 'space',
|
||||
// ],
|
||||
// },
|
||||
// default: '',
|
||||
// },
|
||||
// {
|
||||
// displayName: 'Element Data',
|
||||
// name: 'dataUi',
|
||||
// type: 'fixedCollection',
|
||||
// description: 'Add Data',
|
||||
// typeOptions: {
|
||||
// multipleValues: true,
|
||||
// },
|
||||
// placeholder: 'Add Data',
|
||||
// default: '',
|
||||
// options: [
|
||||
// {
|
||||
// displayName: 'Data',
|
||||
// name: 'dataValues',
|
||||
// values: [
|
||||
// {
|
||||
// displayName: 'Key',
|
||||
// name: 'key',
|
||||
// type: 'string',
|
||||
// default: '',
|
||||
// },
|
||||
// {
|
||||
// displayName: 'Value',
|
||||
// name: 'value',
|
||||
// type: 'string',
|
||||
// default: '',
|
||||
// },
|
||||
// ],
|
||||
// },
|
||||
// ],
|
||||
// },
|
||||
// ],
|
||||
// },
|
||||
// ],
|
||||
// },
|
||||
// ],
|
||||
// },
|
||||
// ],
|
||||
// },
|
||||
// {
|
||||
// displayName: 'Content (JSON)',
|
||||
// name: 'contentJson',
|
||||
// type: 'string',
|
||||
// displayOptions: {
|
||||
// show: {
|
||||
// '/jsonParameters': [
|
||||
// true,
|
||||
// ],
|
||||
// },
|
||||
// },
|
||||
// default: '',
|
||||
// },
|
||||
// {
|
||||
// displayName: 'Parent ID',
|
||||
// name: 'parentId',
|
||||
// type: 'string',
|
||||
// default: '',
|
||||
// description: 'Parent story/folder numeric ID.',
|
||||
// },
|
||||
// {
|
||||
// displayName: 'Path',
|
||||
// name: 'path',
|
||||
// type: 'string',
|
||||
// default: '',
|
||||
// description: 'Given real path, used in the preview editor.',
|
||||
// },
|
||||
// {
|
||||
// displayName: 'Is Startpage',
|
||||
// name: 'isStartpage',
|
||||
// type: 'boolean',
|
||||
// default: false,
|
||||
// description: 'Is startpage of current folder.',
|
||||
// },
|
||||
// {
|
||||
// displayName: 'First Published At',
|
||||
// name: 'firstPublishedAt',
|
||||
// type: 'dateTime',
|
||||
// default: '',
|
||||
// description: 'First publishing date.',
|
||||
// },
|
||||
// ],
|
||||
// },
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* story:delete */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
{
|
||||
displayName: 'Space Name or ID',
|
||||
name: 'space',
|
||||
type: 'options',
|
||||
typeOptions: {
|
||||
loadOptionsMethod: 'getSpaces',
|
||||
},
|
||||
default: '',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
source: ['managementApi'],
|
||||
resource: ['story'],
|
||||
operation: ['delete'],
|
||||
},
|
||||
},
|
||||
description:
|
||||
'The name of the space. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.',
|
||||
},
|
||||
{
|
||||
displayName: 'Story ID',
|
||||
name: 'storyId',
|
||||
type: 'string',
|
||||
default: '',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
source: ['managementApi'],
|
||||
resource: ['story'],
|
||||
operation: ['delete'],
|
||||
},
|
||||
},
|
||||
description: 'Numeric ID of the story',
|
||||
},
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* story:get */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
{
|
||||
displayName: 'Space Name or ID',
|
||||
name: 'space',
|
||||
type: 'options',
|
||||
typeOptions: {
|
||||
loadOptionsMethod: 'getSpaces',
|
||||
},
|
||||
default: '',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
source: ['managementApi'],
|
||||
resource: ['story'],
|
||||
operation: ['get'],
|
||||
},
|
||||
},
|
||||
description:
|
||||
'The name of the space. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.',
|
||||
},
|
||||
{
|
||||
displayName: 'Story ID',
|
||||
name: 'storyId',
|
||||
type: 'string',
|
||||
default: '',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
source: ['managementApi'],
|
||||
resource: ['story'],
|
||||
operation: ['get'],
|
||||
},
|
||||
},
|
||||
description: 'Numeric ID of the story',
|
||||
},
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* story:getAll */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
{
|
||||
displayName: 'Space Name or ID',
|
||||
name: 'space',
|
||||
type: 'options',
|
||||
typeOptions: {
|
||||
loadOptionsMethod: 'getSpaces',
|
||||
},
|
||||
default: '',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
source: ['managementApi'],
|
||||
resource: ['story'],
|
||||
operation: ['getAll'],
|
||||
},
|
||||
},
|
||||
description:
|
||||
'The name of the space. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.',
|
||||
},
|
||||
{
|
||||
displayName: 'Return All',
|
||||
name: 'returnAll',
|
||||
type: 'boolean',
|
||||
displayOptions: {
|
||||
show: {
|
||||
source: ['managementApi'],
|
||||
resource: ['story'],
|
||||
operation: ['getAll'],
|
||||
},
|
||||
},
|
||||
default: false,
|
||||
description: 'Whether to return all results or only up to a given limit',
|
||||
},
|
||||
{
|
||||
displayName: 'Limit',
|
||||
name: 'limit',
|
||||
type: 'number',
|
||||
displayOptions: {
|
||||
show: {
|
||||
source: ['managementApi'],
|
||||
resource: ['story'],
|
||||
operation: ['getAll'],
|
||||
returnAll: [false],
|
||||
},
|
||||
},
|
||||
typeOptions: {
|
||||
minValue: 1,
|
||||
maxValue: 100,
|
||||
},
|
||||
default: 50,
|
||||
description: 'Max number of results to return',
|
||||
},
|
||||
{
|
||||
displayName: 'Filters',
|
||||
name: 'filters',
|
||||
type: 'collection',
|
||||
placeholder: 'Add Filter',
|
||||
default: {},
|
||||
displayOptions: {
|
||||
show: {
|
||||
source: ['managementApi'],
|
||||
resource: ['story'],
|
||||
operation: ['getAll'],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
displayName: 'Starts With',
|
||||
name: 'starts_with',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'Filter by slug',
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* story:publish */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
{
|
||||
displayName: 'Space Name or ID',
|
||||
name: 'space',
|
||||
type: 'options',
|
||||
typeOptions: {
|
||||
loadOptionsMethod: 'getSpaces',
|
||||
},
|
||||
default: '',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
source: ['managementApi'],
|
||||
resource: ['story'],
|
||||
operation: ['publish'],
|
||||
},
|
||||
},
|
||||
description:
|
||||
'The name of the space. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.',
|
||||
},
|
||||
{
|
||||
displayName: 'Story ID',
|
||||
name: 'storyId',
|
||||
type: 'string',
|
||||
default: '',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
source: ['managementApi'],
|
||||
resource: ['story'],
|
||||
operation: ['publish'],
|
||||
},
|
||||
},
|
||||
description: 'Numeric ID of the story',
|
||||
},
|
||||
{
|
||||
displayName: 'Options',
|
||||
name: 'options',
|
||||
type: 'collection',
|
||||
placeholder: 'Add option',
|
||||
displayOptions: {
|
||||
show: {
|
||||
source: ['managementApi'],
|
||||
resource: ['story'],
|
||||
operation: ['publish'],
|
||||
},
|
||||
},
|
||||
default: {},
|
||||
options: [
|
||||
{
|
||||
displayName: 'Release ID',
|
||||
name: 'releaseId',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'Numeric ID of release',
|
||||
},
|
||||
{
|
||||
displayName: 'Language',
|
||||
name: 'language',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description:
|
||||
'Language code to publish the story individually (must be enabled in the space settings)',
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* story:unpublish */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
{
|
||||
displayName: 'Space Name or ID',
|
||||
name: 'space',
|
||||
type: 'options',
|
||||
typeOptions: {
|
||||
loadOptionsMethod: 'getSpaces',
|
||||
},
|
||||
default: '',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
source: ['managementApi'],
|
||||
resource: ['story'],
|
||||
operation: ['unpublish'],
|
||||
},
|
||||
},
|
||||
description:
|
||||
'The name of the space. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.',
|
||||
},
|
||||
{
|
||||
displayName: 'Story ID',
|
||||
name: 'storyId',
|
||||
type: 'string',
|
||||
default: '',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
source: ['managementApi'],
|
||||
resource: ['story'],
|
||||
operation: ['unpublish'],
|
||||
},
|
||||
},
|
||||
description: 'Numeric ID of the story',
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"node": "n8n-nodes-base.storyblok",
|
||||
"nodeVersion": "1.0",
|
||||
"codexVersion": "1.0",
|
||||
"categories": ["Data & Storage", "Marketing"],
|
||||
"resources": {
|
||||
"credentialDocumentation": [
|
||||
{
|
||||
"url": "https://docs.n8n.io/integrations/builtin/credentials/storyblok/"
|
||||
}
|
||||
],
|
||||
"primaryDocumentation": [
|
||||
{
|
||||
"url": "https://docs.n8n.io/integrations/builtin/app-nodes/n8n-nodes-base.storyblok/"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,364 @@
|
||||
import type {
|
||||
IExecuteFunctions,
|
||||
IDataObject,
|
||||
ILoadOptionsFunctions,
|
||||
INodeExecutionData,
|
||||
INodePropertyOptions,
|
||||
INodeType,
|
||||
INodeTypeDescription,
|
||||
} from 'n8n-workflow';
|
||||
import { NodeConnectionTypes } from 'n8n-workflow';
|
||||
|
||||
import { storyblokApiRequest, storyblokApiRequestAllItems } from './GenericFunctions';
|
||||
import { storyContentFields, storyContentOperations } from './StoryContentDescription';
|
||||
import { storyManagementFields, storyManagementOperations } from './StoryManagementDescription';
|
||||
|
||||
export class Storyblok implements INodeType {
|
||||
description: INodeTypeDescription = {
|
||||
displayName: 'Storyblok',
|
||||
name: 'storyblok',
|
||||
icon: 'file:storyblok.svg',
|
||||
group: ['output'],
|
||||
version: 1,
|
||||
subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}',
|
||||
description: 'Consume Storyblok API',
|
||||
defaults: {
|
||||
name: 'Storyblok',
|
||||
},
|
||||
usableAsTool: true,
|
||||
inputs: [NodeConnectionTypes.Main],
|
||||
outputs: [NodeConnectionTypes.Main],
|
||||
credentials: [
|
||||
{
|
||||
name: 'storyblokContentApi',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
source: ['contentApi'],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'storyblokManagementApi',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
source: ['managementApi'],
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
properties: [
|
||||
{
|
||||
displayName: 'Source',
|
||||
name: 'source',
|
||||
type: 'options',
|
||||
default: 'contentApi',
|
||||
description: 'Pick where your data comes from, Content or Management API',
|
||||
options: [
|
||||
{
|
||||
name: 'Content API',
|
||||
value: 'contentApi',
|
||||
},
|
||||
{
|
||||
name: 'Management API',
|
||||
value: 'managementApi',
|
||||
},
|
||||
],
|
||||
},
|
||||
// Resources: Content API
|
||||
{
|
||||
displayName: 'Resource',
|
||||
name: 'resource',
|
||||
type: 'options',
|
||||
noDataExpression: true,
|
||||
options: [
|
||||
{
|
||||
name: 'Story',
|
||||
value: 'story',
|
||||
},
|
||||
],
|
||||
default: 'story',
|
||||
displayOptions: {
|
||||
show: {
|
||||
source: ['contentApi'],
|
||||
},
|
||||
},
|
||||
},
|
||||
// Resources: Management API
|
||||
{
|
||||
displayName: 'Resource',
|
||||
name: 'resource',
|
||||
type: 'options',
|
||||
noDataExpression: true,
|
||||
options: [
|
||||
{
|
||||
name: 'Story',
|
||||
value: 'story',
|
||||
},
|
||||
],
|
||||
default: 'story',
|
||||
displayOptions: {
|
||||
show: {
|
||||
source: ['managementApi'],
|
||||
},
|
||||
},
|
||||
},
|
||||
// Content API - Story
|
||||
...storyContentOperations,
|
||||
...storyContentFields,
|
||||
// Management API - Story
|
||||
...storyManagementOperations,
|
||||
...storyManagementFields,
|
||||
],
|
||||
};
|
||||
|
||||
methods = {
|
||||
loadOptions: {
|
||||
async getSpaces(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> {
|
||||
const returnData: INodePropertyOptions[] = [];
|
||||
const { spaces } = await storyblokApiRequest.call(this, 'GET', '/v1/spaces');
|
||||
for (const space of spaces) {
|
||||
returnData.push({
|
||||
name: space.name,
|
||||
value: space.id,
|
||||
});
|
||||
}
|
||||
return returnData;
|
||||
},
|
||||
async getComponents(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> {
|
||||
const returnData: INodePropertyOptions[] = [];
|
||||
const space = this.getCurrentNodeParameter('space') as string;
|
||||
const { components } = await storyblokApiRequest.call(
|
||||
this,
|
||||
'GET',
|
||||
`/v1/spaces/${space}/components`,
|
||||
);
|
||||
for (const component of components) {
|
||||
returnData.push({
|
||||
name: `${component.name} ${component.is_root ? '(root)' : ''}`,
|
||||
value: component.name,
|
||||
});
|
||||
}
|
||||
return returnData;
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
|
||||
const items = this.getInputData();
|
||||
const returnData: INodeExecutionData[] = [];
|
||||
const length = items.length;
|
||||
const qs: IDataObject = {};
|
||||
let responseData;
|
||||
const source = this.getNodeParameter('source', 0) as string;
|
||||
const resource = this.getNodeParameter('resource', 0);
|
||||
const operation = this.getNodeParameter('operation', 0);
|
||||
for (let i = 0; i < length; i++) {
|
||||
try {
|
||||
if (source === 'contentApi') {
|
||||
if (resource === 'story') {
|
||||
if (operation === 'get') {
|
||||
const identifier = this.getNodeParameter('identifier', i) as string;
|
||||
|
||||
responseData = await storyblokApiRequest.call(
|
||||
this,
|
||||
'GET',
|
||||
`/v1/cdn/stories/${identifier}`,
|
||||
);
|
||||
responseData = responseData.story;
|
||||
}
|
||||
if (operation === 'getAll') {
|
||||
const filters = this.getNodeParameter('filters', i);
|
||||
const returnAll = this.getNodeParameter('returnAll', i);
|
||||
Object.assign(qs, filters);
|
||||
|
||||
if (returnAll) {
|
||||
responseData = await storyblokApiRequestAllItems.call(
|
||||
this,
|
||||
'stories',
|
||||
'GET',
|
||||
'/v1/cdn/stories',
|
||||
{},
|
||||
qs,
|
||||
);
|
||||
} else {
|
||||
const limit = this.getNodeParameter('limit', i);
|
||||
qs.per_page = limit;
|
||||
responseData = await storyblokApiRequest.call(
|
||||
this,
|
||||
'GET',
|
||||
'/v1/cdn/stories',
|
||||
{},
|
||||
qs,
|
||||
);
|
||||
responseData = responseData.stories;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (source === 'managementApi') {
|
||||
if (resource === 'story') {
|
||||
// if (operation === 'create') {
|
||||
// const space = this.getNodeParameter('space', i) as string;
|
||||
// const name = this.getNodeParameter('name', i) as string;
|
||||
// const slug = this.getNodeParameter('slug', i) as string;
|
||||
// const jsonParameters = this.getNodeParameter('jsonParameters', i);
|
||||
// const additionalFields = this.getNodeParameter('additionalFields', i);
|
||||
// const body: IDataObject = {
|
||||
// name,
|
||||
// slug,
|
||||
// };
|
||||
|
||||
// if (jsonParameters) {
|
||||
// if (additionalFields.contentJson) {
|
||||
// const json = validateJSON(additionalFields.contentJson as string);
|
||||
// body.content = json;
|
||||
// }
|
||||
// } else {
|
||||
// if (additionalFields.contentUi) {
|
||||
// const contentValue = (additionalFields.contentUi as IDataObject).contentValue as IDataObject;
|
||||
// const content: { component: string, body: IDataObject[] } = { component: '', body: [] };
|
||||
// if (contentValue) {
|
||||
// content.component = contentValue.component as string;
|
||||
// const elementValues = (contentValue.elementUi as IDataObject).elementValues as IDataObject[];
|
||||
// for (const elementValue of elementValues) {
|
||||
// const body: IDataObject = {};
|
||||
// body._uid = uuidv4();
|
||||
// body.component = elementValue.component;
|
||||
// if (elementValue.dataUi) {
|
||||
// const dataValues = (elementValue.dataUi as IDataObject).dataValues as IDataObject[];
|
||||
// for (const dataValue of dataValues) {
|
||||
// body[dataValue.key as string] = dataValue.value;
|
||||
// }
|
||||
// }
|
||||
// content.body.push(body);
|
||||
// }
|
||||
// }
|
||||
// body.content = content;
|
||||
// }
|
||||
// }
|
||||
|
||||
// if (additionalFields.parentId) {
|
||||
// body.parent_id = additionalFields.parentId as string;
|
||||
// }
|
||||
// if (additionalFields.path) {
|
||||
// body.path = additionalFields.path as string;
|
||||
// }
|
||||
// if (additionalFields.isStartpage) {
|
||||
// body.is_startpage = additionalFields.isStartpage as string;
|
||||
// }
|
||||
// if (additionalFields.firstPublishedAt) {
|
||||
// body.first_published_at = additionalFields.firstPublishedAt as string;
|
||||
// }
|
||||
|
||||
// responseData = await storyblokApiRequest.call(this, 'POST', `/v1/spaces/${space}/stories`, { story: body });
|
||||
// responseData = responseData.story;
|
||||
// }
|
||||
if (operation === 'delete') {
|
||||
const space = this.getNodeParameter('space', i) as string;
|
||||
const storyId = this.getNodeParameter('storyId', i) as string;
|
||||
|
||||
responseData = await storyblokApiRequest.call(
|
||||
this,
|
||||
'DELETE',
|
||||
`/v1/spaces/${space}/stories/${storyId}`,
|
||||
);
|
||||
responseData = responseData.story;
|
||||
}
|
||||
if (operation === 'get') {
|
||||
const space = this.getNodeParameter('space', i) as string;
|
||||
const storyId = this.getNodeParameter('storyId', i) as string;
|
||||
|
||||
responseData = await storyblokApiRequest.call(
|
||||
this,
|
||||
'GET',
|
||||
`/v1/spaces/${space}/stories/${storyId}`,
|
||||
);
|
||||
responseData = responseData.story;
|
||||
}
|
||||
if (operation === 'getAll') {
|
||||
const space = this.getNodeParameter('space', i) as string;
|
||||
const filters = this.getNodeParameter('filters', i);
|
||||
const returnAll = this.getNodeParameter('returnAll', i);
|
||||
Object.assign(qs, filters);
|
||||
|
||||
if (returnAll) {
|
||||
responseData = await storyblokApiRequestAllItems.call(
|
||||
this,
|
||||
'stories',
|
||||
'GET',
|
||||
`/v1/spaces/${space}/stories`,
|
||||
{},
|
||||
qs,
|
||||
);
|
||||
} else {
|
||||
const limit = this.getNodeParameter('limit', i);
|
||||
qs.per_page = limit;
|
||||
responseData = await storyblokApiRequest.call(
|
||||
this,
|
||||
'GET',
|
||||
`/v1/spaces/${space}/stories`,
|
||||
{},
|
||||
qs,
|
||||
);
|
||||
responseData = responseData.stories;
|
||||
}
|
||||
}
|
||||
if (operation === 'publish') {
|
||||
const space = this.getNodeParameter('space', i) as string;
|
||||
const storyId = this.getNodeParameter('storyId', i) as string;
|
||||
const options = this.getNodeParameter('options', i);
|
||||
const query: IDataObject = {};
|
||||
// Not sure if these two options work
|
||||
if (options.releaseId) {
|
||||
query.release_id = options.releaseId as string;
|
||||
}
|
||||
if (options.language) {
|
||||
query.lang = options.language as string;
|
||||
}
|
||||
|
||||
responseData = await storyblokApiRequest.call(
|
||||
this,
|
||||
'GET',
|
||||
`/v1/spaces/${space}/stories/${storyId}/publish`,
|
||||
{},
|
||||
query,
|
||||
);
|
||||
responseData = responseData.story;
|
||||
}
|
||||
if (operation === 'unpublish') {
|
||||
const space = this.getNodeParameter('space', i) as string;
|
||||
const storyId = this.getNodeParameter('storyId', i) as string;
|
||||
|
||||
responseData = await storyblokApiRequest.call(
|
||||
this,
|
||||
'GET',
|
||||
`/v1/spaces/${space}/stories/${storyId}/unpublish`,
|
||||
);
|
||||
responseData = responseData.story;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const executionData = this.helpers.constructExecutionMetaData(
|
||||
this.helpers.returnJsonArray(responseData as IDataObject[]),
|
||||
{ itemData: { item: i } },
|
||||
);
|
||||
|
||||
returnData.push(...executionData);
|
||||
} catch (error) {
|
||||
if (this.continueOnFail()) {
|
||||
const executionErrorData = this.helpers.constructExecutionMetaData(
|
||||
this.helpers.returnJsonArray({ error: error.message }),
|
||||
{ itemData: { item: i } },
|
||||
);
|
||||
returnData.push(...executionErrorData);
|
||||
continue;
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
return [returnData];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"content_type": {
|
||||
"type": "string"
|
||||
},
|
||||
"created_at": {
|
||||
"type": "string"
|
||||
},
|
||||
"default_root": {
|
||||
"type": "null"
|
||||
},
|
||||
"deleted_at": {
|
||||
"type": "null"
|
||||
},
|
||||
"disable_fe_editor": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"disble_fe_editor": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"expire_at": {
|
||||
"type": "null"
|
||||
},
|
||||
"full_slug": {
|
||||
"type": "string"
|
||||
},
|
||||
"group_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"id": {
|
||||
"type": "integer"
|
||||
},
|
||||
"is_folder": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"is_startpage": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"last_author": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"friendly_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"id": {
|
||||
"type": "integer"
|
||||
},
|
||||
"userid": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"last_author_id": {
|
||||
"type": "integer"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"path": {
|
||||
"type": "null"
|
||||
},
|
||||
"pinned": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"position": {
|
||||
"type": "integer"
|
||||
},
|
||||
"publish_at": {
|
||||
"type": "null"
|
||||
},
|
||||
"published": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"scheduled_dates": {
|
||||
"type": "null"
|
||||
},
|
||||
"slug": {
|
||||
"type": "string"
|
||||
},
|
||||
"sort_by_date": {
|
||||
"type": "null"
|
||||
},
|
||||
"tag_list": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"unpublished_changes": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"updated_at": {
|
||||
"type": "string"
|
||||
},
|
||||
"uuid": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"version": 1
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="87" height="103"><g fill="#09B3AF"><path d="M51.8 49H31v10h20.3c1.2 0 2.3-.5 3.2-1.3.8-.8 1.3-2 1.3-3.5a6 6 0 0 0-1.1-3.6c-.8-1-1.7-1.6-2.9-1.6m.7-12.1c.9-.6 1.3-1.9 1.3-3.6 0-1.5-.4-2.6-1.1-3.3-.7-.6-1.6-1-2.6-1H31v9h18.7c1 0 2-.5 2.8-1.1"/><path d="M83 0H4.5C2 0 0 2 0 4.4V83c0 2.4 2 3.9 4.4 3.9H16v15.7L30.4 87H83c2.4 0 3.9-1.5 3.9-4V4.5c0-2.4-1.5-4.4-4-4.4zM69.8 63.7c-1 1.8-2.5 3.3-4.3 4.4-1.9 1.2-4 2.3-6.4 2.8-2.4.6-5 1.1-7.7 1.1H16V16h40.2c2 0 3.7.4 5.3 1.3 1.5.8 2.9 1.9 4 3.2a15 15 0 0 1 3.4 9.7c0 2.6-.7 5.1-2 7.5a12.5 12.5 0 0 1-6 5.4c3.2.9 5.7 2.5 7.6 4.8 1.8 2.4 2.7 5.5 2.7 9.4 0 2.5-.5 4.6-1.5 6.4z"/><path d="M51.8 49H31v10h20.3c1.2 0 2.3-.5 3.2-1.3.8-.8 1.3-2 1.3-3.5a6 6 0 0 0-1.1-3.6c-.8-1-1.7-1.6-2.9-1.6m.7-12.1c.9-.6 1.3-1.9 1.3-3.6 0-1.5-.4-2.6-1.1-3.3-.7-.6-1.6-1-2.6-1H31v9h18.7c1 0 2-.5 2.8-1.1"/><path d="M83 0H4.5C2 0 0 2 0 4.4V83c0 2.4 2 3.9 4.4 3.9H16v15.7L30.4 87H83c2.4 0 3.9-1.5 3.9-4V4.5c0-2.4-1.5-4.4-4-4.4zM69.8 63.7c-1 1.8-2.5 3.3-4.3 4.4-1.9 1.2-4 2.3-6.4 2.8-2.4.6-5 1.1-7.7 1.1H16V16h40.2c2 0 3.7.4 5.3 1.3 1.5.8 2.9 1.9 4 3.2a15 15 0 0 1 3.4 9.7c0 2.6-.7 5.1-2 7.5a12.5 12.5 0 0 1-6 5.4c3.2.9 5.7 2.5 7.6 4.8 1.8 2.4 2.7 5.5 2.7 9.4 0 2.5-.5 4.6-1.5 6.4z"/></g></svg>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
Reference in New Issue
Block a user