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,298 @@
|
||||
import type { INodeProperties } from 'n8n-workflow';
|
||||
|
||||
export const entryOperations: INodeProperties[] = [
|
||||
{
|
||||
displayName: 'Operation',
|
||||
name: 'operation',
|
||||
noDataExpression: true,
|
||||
type: 'options',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['entry'],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
name: 'Create',
|
||||
value: 'create',
|
||||
description: 'Create an entry',
|
||||
action: 'Create an entry',
|
||||
},
|
||||
{
|
||||
name: 'Delete',
|
||||
value: 'delete',
|
||||
description: 'Delete an entry',
|
||||
action: 'Delete an entry',
|
||||
},
|
||||
{
|
||||
name: 'Get',
|
||||
value: 'get',
|
||||
description: 'Get an entry',
|
||||
action: 'Get an entry',
|
||||
},
|
||||
{
|
||||
name: 'Get Many',
|
||||
value: 'getAll',
|
||||
description: 'Get many entries',
|
||||
action: 'Get many entries',
|
||||
},
|
||||
{
|
||||
name: 'Update',
|
||||
value: 'update',
|
||||
description: 'Update an entry',
|
||||
action: 'Update an entry',
|
||||
},
|
||||
],
|
||||
default: 'get',
|
||||
},
|
||||
];
|
||||
|
||||
export const entryFields: INodeProperties[] = [
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* entry:create */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
{
|
||||
displayName: 'Content Type',
|
||||
name: 'contentType',
|
||||
type: 'string',
|
||||
default: '',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['entry'],
|
||||
operation: ['create'],
|
||||
},
|
||||
},
|
||||
description: 'Name of the content type',
|
||||
},
|
||||
{
|
||||
displayName: 'Columns',
|
||||
name: 'columns',
|
||||
type: 'string',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['entry'],
|
||||
operation: ['create'],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
placeholder: 'id,name,description',
|
||||
description:
|
||||
'Comma-separated list of the properties which should used as columns for the new rows',
|
||||
},
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* entry:delete */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
{
|
||||
displayName: 'Content Type',
|
||||
name: 'contentType',
|
||||
type: 'string',
|
||||
default: '',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['entry'],
|
||||
operation: ['delete'],
|
||||
},
|
||||
},
|
||||
description: 'Name of the content type',
|
||||
},
|
||||
{
|
||||
displayName: 'Entry ID',
|
||||
name: 'entryId',
|
||||
type: 'string',
|
||||
default: '',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['entry'],
|
||||
operation: ['delete'],
|
||||
},
|
||||
},
|
||||
description: 'The ID of the entry to delete',
|
||||
},
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* entry:get */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
{
|
||||
displayName: 'Content Type',
|
||||
name: 'contentType',
|
||||
type: 'string',
|
||||
default: '',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['entry'],
|
||||
operation: ['get'],
|
||||
},
|
||||
},
|
||||
description: 'Name of the content type',
|
||||
},
|
||||
{
|
||||
displayName: 'Entry ID',
|
||||
name: 'entryId',
|
||||
type: 'string',
|
||||
default: '',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['entry'],
|
||||
operation: ['get'],
|
||||
},
|
||||
},
|
||||
description: 'The ID of the entry to get',
|
||||
},
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* entry:getAll */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
{
|
||||
displayName: 'Content Type',
|
||||
name: 'contentType',
|
||||
type: 'string',
|
||||
default: '',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['entry'],
|
||||
operation: ['getAll'],
|
||||
},
|
||||
},
|
||||
description: 'Name of the content type',
|
||||
},
|
||||
{
|
||||
displayName: 'Return All',
|
||||
name: 'returnAll',
|
||||
type: 'boolean',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['entry'],
|
||||
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: {
|
||||
resource: ['entry'],
|
||||
operation: ['getAll'],
|
||||
returnAll: [false],
|
||||
},
|
||||
},
|
||||
typeOptions: {
|
||||
minValue: 1,
|
||||
maxValue: 100,
|
||||
},
|
||||
default: 50,
|
||||
description: 'Max number of results to return',
|
||||
},
|
||||
{
|
||||
displayName: 'Options',
|
||||
name: 'options',
|
||||
type: 'collection',
|
||||
placeholder: 'Add Field',
|
||||
default: {},
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['entry'],
|
||||
operation: ['getAll'],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
displayName: 'Publication State',
|
||||
name: 'publicationState',
|
||||
type: 'options',
|
||||
options: [
|
||||
{
|
||||
name: 'Live',
|
||||
value: 'live',
|
||||
},
|
||||
{
|
||||
name: 'Preview',
|
||||
value: 'preview',
|
||||
},
|
||||
],
|
||||
default: '',
|
||||
description: 'Only select entries matching the publication state provided',
|
||||
},
|
||||
{
|
||||
displayName: 'Sort Fields',
|
||||
name: 'sort',
|
||||
type: 'string',
|
||||
typeOptions: {
|
||||
multipleValues: true,
|
||||
multipleValueButtonText: 'Add Sort Field',
|
||||
},
|
||||
default: '',
|
||||
placeholder: 'name:asc',
|
||||
description:
|
||||
'Name of the fields to sort the data by. By default will be sorted ascendingly. To modify that behavior, you have to add the sort direction after the name of sort field preceded by a colon. For example: <code>name:asc</code>.',
|
||||
},
|
||||
{
|
||||
displayName: 'Where (JSON)',
|
||||
name: 'where',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description:
|
||||
'JSON query to filter the data. <a href="https://strapi.io/documentation/developer-docs/latest/developer-resources/content-api/content-api.html#filters">More info</a>.',
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* entry:update */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
{
|
||||
displayName: 'Content Type',
|
||||
name: 'contentType',
|
||||
type: 'string',
|
||||
default: '',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['entry'],
|
||||
operation: ['update'],
|
||||
},
|
||||
},
|
||||
description: 'Name of the content type',
|
||||
},
|
||||
{
|
||||
displayName: 'Update Key',
|
||||
name: 'updateKey',
|
||||
type: 'string',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['entry'],
|
||||
operation: ['update'],
|
||||
},
|
||||
},
|
||||
default: 'id',
|
||||
required: true,
|
||||
// eslint-disable-next-line n8n-nodes-base/node-param-description-miscased-id
|
||||
description:
|
||||
'Name of the property which decides which rows in the database should be updated. Normally that would be "id".',
|
||||
},
|
||||
{
|
||||
displayName: 'Columns',
|
||||
name: 'columns',
|
||||
type: 'string',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['entry'],
|
||||
operation: ['update'],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
placeholder: 'id,name,description',
|
||||
description:
|
||||
'Comma-separated list of the properties which should used as columns for the new rows',
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,144 @@
|
||||
import type {
|
||||
ICredentialDataDecryptedObject,
|
||||
IDataObject,
|
||||
IExecuteFunctions,
|
||||
IHookFunctions,
|
||||
IHttpRequestMethods,
|
||||
ILoadOptionsFunctions,
|
||||
IRequestOptions,
|
||||
IWebhookFunctions,
|
||||
JsonObject,
|
||||
} from 'n8n-workflow';
|
||||
import { NodeApiError } from 'n8n-workflow';
|
||||
|
||||
import { removeTrailingSlash } from '../../utils/utilities';
|
||||
|
||||
export async function strapiApiRequest(
|
||||
this: IExecuteFunctions | ILoadOptionsFunctions | IHookFunctions | IWebhookFunctions,
|
||||
method: IHttpRequestMethods,
|
||||
resource: string,
|
||||
body: IDataObject = {},
|
||||
qs: IDataObject = {},
|
||||
uri?: string,
|
||||
headers: IDataObject = {},
|
||||
) {
|
||||
const authenticationMethod = this.getNodeParameter('authentication', 0);
|
||||
let credentials: ICredentialDataDecryptedObject;
|
||||
|
||||
if (authenticationMethod === 'password') {
|
||||
credentials = await this.getCredentials('strapiApi');
|
||||
} else {
|
||||
credentials = await this.getCredentials('strapiTokenApi');
|
||||
}
|
||||
|
||||
const url = removeTrailingSlash(credentials.url as string);
|
||||
|
||||
try {
|
||||
const options: IRequestOptions = {
|
||||
headers: {},
|
||||
method,
|
||||
body,
|
||||
qs,
|
||||
uri: uri || credentials.apiVersion === 'v4' ? `${url}/api${resource}` : `${url}${resource}`,
|
||||
json: true,
|
||||
qsStringifyOptions: {
|
||||
arrayFormat: 'indices',
|
||||
},
|
||||
};
|
||||
if (Object.keys(headers).length !== 0) {
|
||||
options.headers = Object.assign({}, options.headers, headers);
|
||||
}
|
||||
if (Object.keys(body).length === 0) {
|
||||
delete options.body;
|
||||
}
|
||||
|
||||
return await this.helpers.requestWithAuthentication.call(
|
||||
this,
|
||||
authenticationMethod === 'password' ? 'strapiApi' : 'strapiTokenApi',
|
||||
options,
|
||||
);
|
||||
} catch (error) {
|
||||
throw new NodeApiError(this.getNode(), error as JsonObject);
|
||||
}
|
||||
}
|
||||
|
||||
export async function getToken(
|
||||
this: IExecuteFunctions | ILoadOptionsFunctions | IHookFunctions | IWebhookFunctions,
|
||||
): Promise<{ jwt: string }> {
|
||||
const credentials = await this.getCredentials('strapiApi');
|
||||
|
||||
const url = removeTrailingSlash(credentials.url as string);
|
||||
|
||||
let options = {} as IRequestOptions;
|
||||
options = {
|
||||
headers: {
|
||||
'content-type': 'application/json',
|
||||
},
|
||||
method: 'POST',
|
||||
body: {
|
||||
identifier: credentials.email,
|
||||
password: credentials.password,
|
||||
},
|
||||
uri: credentials.apiVersion === 'v4' ? `${url}/api/auth/local` : `${url}/auth/local`,
|
||||
json: true,
|
||||
};
|
||||
return await (this.helpers.request(options) as Promise<{ jwt: string }>);
|
||||
}
|
||||
|
||||
export async function strapiApiRequestAllItems(
|
||||
this: IHookFunctions | ILoadOptionsFunctions | IExecuteFunctions,
|
||||
method: IHttpRequestMethods,
|
||||
resource: string,
|
||||
body: IDataObject = {},
|
||||
query: IDataObject = {},
|
||||
headers: IDataObject = {},
|
||||
apiVersion: string = 'v3',
|
||||
) {
|
||||
const returnData: IDataObject[] = [];
|
||||
|
||||
let responseData;
|
||||
if (apiVersion === 'v4') {
|
||||
query['pagination[pageSize]'] = 20;
|
||||
query['pagination[page]'] = 1;
|
||||
do {
|
||||
({ data: responseData } = await strapiApiRequest.call(
|
||||
this,
|
||||
method,
|
||||
resource,
|
||||
body,
|
||||
query,
|
||||
undefined,
|
||||
headers,
|
||||
));
|
||||
query['pagination[page]']++;
|
||||
returnData.push.apply(returnData, responseData as IDataObject[]);
|
||||
} while (responseData.length !== 0);
|
||||
} else {
|
||||
query._limit = 20;
|
||||
query._start = 0;
|
||||
do {
|
||||
responseData = await strapiApiRequest.call(
|
||||
this,
|
||||
method,
|
||||
resource,
|
||||
body,
|
||||
query,
|
||||
undefined,
|
||||
headers,
|
||||
);
|
||||
query._start += query._limit;
|
||||
returnData.push.apply(returnData, responseData as IDataObject[]);
|
||||
} while (responseData.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,18 @@
|
||||
{
|
||||
"node": "n8n-nodes-base.strapi",
|
||||
"nodeVersion": "1.0",
|
||||
"codexVersion": "1.0",
|
||||
"categories": ["Data & Storage", "Marketing"],
|
||||
"resources": {
|
||||
"credentialDocumentation": [
|
||||
{
|
||||
"url": "https://docs.n8n.io/integrations/builtin/credentials/strapi/"
|
||||
}
|
||||
],
|
||||
"primaryDocumentation": [
|
||||
{
|
||||
"url": "https://docs.n8n.io/integrations/builtin/app-nodes/n8n-nodes-base.strapi/"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,405 @@
|
||||
import type {
|
||||
IExecuteFunctions,
|
||||
ICredentialsDecrypted,
|
||||
ICredentialTestFunctions,
|
||||
IDataObject,
|
||||
INodeCredentialTestResult,
|
||||
INodeExecutionData,
|
||||
INodeType,
|
||||
INodeTypeDescription,
|
||||
IRequestOptions,
|
||||
} from 'n8n-workflow';
|
||||
import { NodeConnectionTypes, NodeOperationError } from 'n8n-workflow';
|
||||
|
||||
import { entryFields, entryOperations } from './EntryDescription';
|
||||
import {
|
||||
getToken,
|
||||
strapiApiRequest,
|
||||
strapiApiRequestAllItems,
|
||||
validateJSON,
|
||||
} from './GenericFunctions';
|
||||
import { removeTrailingSlash } from '../../utils/utilities';
|
||||
|
||||
export class Strapi implements INodeType {
|
||||
description: INodeTypeDescription = {
|
||||
displayName: 'Strapi',
|
||||
name: 'strapi',
|
||||
icon: 'file:strapi.svg',
|
||||
group: ['input'],
|
||||
version: 1,
|
||||
subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}',
|
||||
description: 'Consume Strapi API',
|
||||
defaults: {
|
||||
name: 'Strapi',
|
||||
},
|
||||
usableAsTool: true,
|
||||
inputs: [NodeConnectionTypes.Main],
|
||||
outputs: [NodeConnectionTypes.Main],
|
||||
credentials: [
|
||||
{
|
||||
name: 'strapiApi',
|
||||
required: true,
|
||||
testedBy: 'strapiApiTest',
|
||||
displayOptions: {
|
||||
show: {
|
||||
authentication: ['password'],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'strapiTokenApi',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
authentication: ['token'],
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
properties: [
|
||||
{
|
||||
displayName: 'Authentication',
|
||||
name: 'authentication',
|
||||
type: 'options',
|
||||
options: [
|
||||
{
|
||||
name: 'Username & Password',
|
||||
value: 'password',
|
||||
},
|
||||
{
|
||||
name: 'API Token',
|
||||
value: 'token',
|
||||
},
|
||||
],
|
||||
default: 'password',
|
||||
},
|
||||
{
|
||||
displayName: 'Resource',
|
||||
name: 'resource',
|
||||
noDataExpression: true,
|
||||
type: 'options',
|
||||
options: [
|
||||
{
|
||||
name: 'Entry',
|
||||
value: 'entry',
|
||||
},
|
||||
],
|
||||
default: 'entry',
|
||||
},
|
||||
...entryOperations,
|
||||
...entryFields,
|
||||
],
|
||||
};
|
||||
|
||||
methods = {
|
||||
credentialTest: {
|
||||
async strapiApiTest(
|
||||
this: ICredentialTestFunctions,
|
||||
credential: ICredentialsDecrypted,
|
||||
): Promise<INodeCredentialTestResult> {
|
||||
const credentials = credential.data as IDataObject;
|
||||
let options: IRequestOptions = {};
|
||||
|
||||
const url = removeTrailingSlash(credentials.url as string);
|
||||
|
||||
options = {
|
||||
headers: {
|
||||
'content-type': 'application/json',
|
||||
},
|
||||
method: 'POST',
|
||||
body: {
|
||||
identifier: credentials.email,
|
||||
password: credentials.password,
|
||||
},
|
||||
uri: credentials.apiVersion === 'v4' ? `${url}/api/auth/local` : `${url}/auth/local`,
|
||||
json: true,
|
||||
};
|
||||
|
||||
try {
|
||||
await this.helpers.request(options);
|
||||
return {
|
||||
status: 'OK',
|
||||
message: 'Authentication successful',
|
||||
};
|
||||
} catch (error) {
|
||||
return {
|
||||
status: 'Error',
|
||||
message: `Auth settings are not valid: ${error}`,
|
||||
};
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
|
||||
const items = this.getInputData();
|
||||
const returnData: INodeExecutionData[] = [];
|
||||
const length = items.length;
|
||||
const qs: IDataObject = {};
|
||||
const headers: IDataObject = {};
|
||||
let responseData;
|
||||
const resource = this.getNodeParameter('resource', 0);
|
||||
const operation = this.getNodeParameter('operation', 0);
|
||||
|
||||
const authenticationMethod = this.getNodeParameter('authentication', 0);
|
||||
|
||||
let apiVersion: string;
|
||||
|
||||
if (authenticationMethod === 'password') {
|
||||
const { jwt } = await getToken.call(this);
|
||||
apiVersion = (await this.getCredentials('strapiApi')).apiVersion as string;
|
||||
headers.Authorization = `Bearer ${jwt}`;
|
||||
} else {
|
||||
apiVersion = (await this.getCredentials('strapiTokenApi')).apiVersion as string;
|
||||
}
|
||||
|
||||
for (let i = 0; i < length; i++) {
|
||||
try {
|
||||
if (resource === 'entry') {
|
||||
if (operation === 'create') {
|
||||
const body: IDataObject = {};
|
||||
|
||||
const contentType = this.getNodeParameter('contentType', i) as string;
|
||||
|
||||
const columns = this.getNodeParameter('columns', i) as string;
|
||||
|
||||
const columnList = columns.split(',').map((column) => column.trim());
|
||||
|
||||
for (const key of Object.keys(items[i].json)) {
|
||||
if (columnList.includes(key)) {
|
||||
apiVersion === 'v4'
|
||||
? (body.data = items[i].json)
|
||||
: (body[key] = items[i].json[key]);
|
||||
}
|
||||
}
|
||||
responseData = await strapiApiRequest.call(
|
||||
this,
|
||||
'POST',
|
||||
`/${contentType}`,
|
||||
body,
|
||||
qs,
|
||||
undefined,
|
||||
headers,
|
||||
);
|
||||
|
||||
const executionData = this.helpers.constructExecutionMetaData(
|
||||
this.helpers.returnJsonArray(responseData as IDataObject),
|
||||
{ itemData: { item: i } },
|
||||
);
|
||||
|
||||
returnData.push(...executionData);
|
||||
}
|
||||
|
||||
if (operation === 'delete') {
|
||||
const contentType = this.getNodeParameter('contentType', i) as string;
|
||||
|
||||
const entryId = this.getNodeParameter('entryId', i) as string;
|
||||
|
||||
responseData = await strapiApiRequest.call(
|
||||
this,
|
||||
'DELETE',
|
||||
`/${contentType}/${entryId}`,
|
||||
{},
|
||||
qs,
|
||||
undefined,
|
||||
headers,
|
||||
);
|
||||
|
||||
const executionData = this.helpers.constructExecutionMetaData(
|
||||
this.helpers.returnJsonArray(responseData as IDataObject),
|
||||
{ itemData: { item: i } },
|
||||
);
|
||||
|
||||
returnData.push(...executionData);
|
||||
}
|
||||
|
||||
if (operation === 'getAll') {
|
||||
const returnAll = this.getNodeParameter('returnAll', i);
|
||||
|
||||
const contentType = this.getNodeParameter('contentType', i) as string;
|
||||
|
||||
const options = this.getNodeParameter('options', i);
|
||||
|
||||
if (apiVersion === 'v4') {
|
||||
// Sort Option
|
||||
if (options.sort && (options.sort as string[]).length !== 0) {
|
||||
const sortFields = options.sort as string[];
|
||||
qs.sort = sortFields.join(',');
|
||||
}
|
||||
// Filter Option
|
||||
if (options.where) {
|
||||
const query = validateJSON(options.where as string);
|
||||
if (query !== undefined) {
|
||||
qs.filters = query;
|
||||
} else {
|
||||
throw new NodeOperationError(this.getNode(), 'Query must be a valid JSON', {
|
||||
itemIndex: i,
|
||||
});
|
||||
}
|
||||
}
|
||||
// Publication Option
|
||||
if (options.publicationState) {
|
||||
qs.publicationState = options.publicationState as string;
|
||||
}
|
||||
// Limit Option
|
||||
if (returnAll) {
|
||||
responseData = await strapiApiRequestAllItems.call(
|
||||
this,
|
||||
'GET',
|
||||
`/${contentType}`,
|
||||
{},
|
||||
qs,
|
||||
headers,
|
||||
apiVersion,
|
||||
);
|
||||
} else {
|
||||
qs['pagination[pageSize]'] = this.getNodeParameter('limit', i);
|
||||
({ data: responseData } = await strapiApiRequest.call(
|
||||
this,
|
||||
'GET',
|
||||
`/${contentType}`,
|
||||
{},
|
||||
qs,
|
||||
undefined,
|
||||
headers,
|
||||
));
|
||||
}
|
||||
} else {
|
||||
// Sort Option
|
||||
if (options.sort && (options.sort as string[]).length !== 0) {
|
||||
const sortFields = options.sort as string[];
|
||||
qs._sort = sortFields.join(',');
|
||||
}
|
||||
// Filter Option
|
||||
if (options.where) {
|
||||
const query = validateJSON(options.where as string);
|
||||
if (query !== undefined) {
|
||||
qs._where = query;
|
||||
} else {
|
||||
throw new NodeOperationError(this.getNode(), 'Query must be a valid JSON', {
|
||||
itemIndex: i,
|
||||
});
|
||||
}
|
||||
}
|
||||
// Publication Option
|
||||
if (options.publicationState) {
|
||||
qs._publicationState = options.publicationState as string;
|
||||
}
|
||||
// Limit Option
|
||||
if (returnAll) {
|
||||
responseData = await strapiApiRequestAllItems.call(
|
||||
this,
|
||||
'GET',
|
||||
`/${contentType}`,
|
||||
{},
|
||||
qs,
|
||||
headers,
|
||||
apiVersion,
|
||||
);
|
||||
} else {
|
||||
qs._limit = this.getNodeParameter('limit', i);
|
||||
responseData = await strapiApiRequest.call(
|
||||
this,
|
||||
'GET',
|
||||
`/${contentType}`,
|
||||
{},
|
||||
qs,
|
||||
undefined,
|
||||
headers,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const executionData = this.helpers.constructExecutionMetaData(
|
||||
this.helpers.returnJsonArray(responseData as IDataObject),
|
||||
{ itemData: { item: i } },
|
||||
);
|
||||
|
||||
returnData.push(...executionData);
|
||||
}
|
||||
|
||||
if (operation === 'get') {
|
||||
const contentType = this.getNodeParameter('contentType', i) as string;
|
||||
|
||||
const entryId = this.getNodeParameter('entryId', i) as string;
|
||||
|
||||
responseData = await strapiApiRequest.call(
|
||||
this,
|
||||
'GET',
|
||||
`/${contentType}/${entryId}`,
|
||||
{},
|
||||
qs,
|
||||
undefined,
|
||||
headers,
|
||||
);
|
||||
|
||||
if (apiVersion === 'v4') {
|
||||
responseData = responseData.data;
|
||||
}
|
||||
|
||||
const executionData = this.helpers.constructExecutionMetaData(
|
||||
this.helpers.returnJsonArray(responseData as IDataObject),
|
||||
{ itemData: { item: i } },
|
||||
);
|
||||
|
||||
returnData.push(...executionData);
|
||||
}
|
||||
|
||||
if (operation === 'update') {
|
||||
const body: IDataObject = {};
|
||||
|
||||
const contentType = this.getNodeParameter('contentType', i) as string;
|
||||
|
||||
const columns = this.getNodeParameter('columns', i) as string;
|
||||
|
||||
const updateKey = this.getNodeParameter('updateKey', i) as string;
|
||||
|
||||
const columnList = columns.split(',').map((column) => column.trim());
|
||||
|
||||
const entryId = items[i].json[updateKey];
|
||||
|
||||
for (const key of Object.keys(items[i].json)) {
|
||||
if (columnList.includes(key)) {
|
||||
apiVersion === 'v4'
|
||||
? (body.data = items[i].json)
|
||||
: (body[key] = items[i].json[key]);
|
||||
}
|
||||
}
|
||||
|
||||
responseData = await strapiApiRequest.call(
|
||||
this,
|
||||
'PUT',
|
||||
`/${contentType}/${entryId}`,
|
||||
body,
|
||||
qs,
|
||||
undefined,
|
||||
headers,
|
||||
);
|
||||
|
||||
if (apiVersion === 'v4') {
|
||||
responseData = responseData.data;
|
||||
}
|
||||
|
||||
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,32 @@
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"attributes": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"content": {
|
||||
"type": "string"
|
||||
},
|
||||
"createdAt": {
|
||||
"type": "string"
|
||||
},
|
||||
"heading": {
|
||||
"type": "string"
|
||||
},
|
||||
"primaryText": {
|
||||
"type": "string"
|
||||
},
|
||||
"slug": {
|
||||
"type": "string"
|
||||
},
|
||||
"updatedAt": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"id": {
|
||||
"type": "integer"
|
||||
}
|
||||
},
|
||||
"version": 1
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"createdAt": {
|
||||
"type": "string"
|
||||
},
|
||||
"documentId": {
|
||||
"type": "string"
|
||||
},
|
||||
"id": {
|
||||
"type": "integer"
|
||||
},
|
||||
"publishedAt": {
|
||||
"type": "string"
|
||||
},
|
||||
"updatedAt": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"version": 5
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1025" height="1032" fill="none"><path fill="url(#a)" d="M341.328 0v344.061h341.333v344.06h341.329V0z"/><path fill="url(#b)" d="M683 343.725H343v344.732h340z"/><path fill="url(#c)" d="M341.333 344.061H0L341.333 0z"/><path fill="url(#d)" d="M682.367 1031.18V687.457h342.003z"/><circle r="1.796" fill="#956FFF" transform="matrix(1 0 0 -1 365.162 314.663)"/><circle r="1.796" fill="#956FFF" transform="matrix(1 0 0 -1 374.502 314.663)"/><circle r="1.796" fill="#956FFF" transform="matrix(1 0 0 -1 383.843 314.663)"/><circle r="1.796" fill="#956FFF" transform="matrix(1 0 0 -1 393.184 314.663)"/><circle r="1.796" fill="#956FFF" transform="matrix(1 0 0 -1 402.525 314.663)"/><circle r="1.796" fill="#956FFF" transform="matrix(1 0 0 -1 411.866 314.663)"/><circle r="1.796" fill="#956FFF" transform="matrix(1 0 0 -1 421.206 314.663)"/><circle r="1.796" fill="#956FFF" transform="matrix(1 0 0 -1 430.546 314.663)"/><circle r="1.796" fill="#956FFF" transform="matrix(1 0 0 -1 439.887 314.663)"/><circle r="1.796" fill="#956FFF" transform="matrix(1 0 0 -1 449.228 314.663)"/><circle r="1.796" fill="#956FFF" transform="matrix(1 0 0 -1 458.569 314.663)"/><circle r="1.796" fill="#956FFF" transform="matrix(1 0 0 -1 365.162 306.041)"/><circle r="1.796" fill="#956FFF" transform="matrix(1 0 0 -1 374.502 306.041)"/><circle r="1.796" fill="#956FFF" transform="matrix(1 0 0 -1 383.843 306.041)"/><circle r="1.796" fill="#956FFF" transform="matrix(1 0 0 -1 393.184 306.041)"/><circle r="1.796" fill="#956FFF" transform="matrix(1 0 0 -1 402.525 306.041)"/><circle r="1.796" fill="#956FFF" transform="matrix(1 0 0 -1 411.866 306.041)"/><circle r="1.796" fill="#956FFF" transform="matrix(1 0 0 -1 421.206 306.041)"/><circle r="1.796" fill="#956FFF" transform="matrix(1 0 0 -1 430.546 306.041)"/><circle r="1.796" fill="#956FFF" transform="matrix(1 0 0 -1 365.162 297.419)"/><circle r="1.796" fill="#956FFF" transform="matrix(1 0 0 -1 374.502 297.419)"/><circle r="1.796" fill="#956FFF" transform="matrix(1 0 0 -1 383.843 297.419)"/><circle r="1.796" fill="#956FFF" transform="matrix(1 0 0 -1 393.184 297.419)"/><circle r="1.796" fill="#956FFF" transform="matrix(1 0 0 -1 402.525 297.419)"/><circle r="1.796" fill="#956FFF" transform="matrix(1 0 0 -1 365.162 288.796)"/><circle r="1.796" fill="#956FFF" transform="matrix(1 0 0 -1 374.502 288.797)"/><circle r="1.796" fill="#956FFF" transform="matrix(1 0 0 -1 383.843 288.797)"/><circle cx="716.162" cy="638.796" r="1.796" fill="#956FFF"/><circle cx="725.502" cy="638.796" r="1.796" fill="#956FFF"/><circle cx="734.843" cy="638.796" r="1.796" fill="#956FFF"/><circle cx="744.184" cy="638.796" r="1.796" fill="#956FFF"/><circle cx="753.525" cy="638.796" r="1.796" fill="#956FFF"/><circle cx="762.866" cy="638.796" r="1.796" fill="#956FFF"/><circle cx="772.206" cy="638.796" r="1.796" fill="#956FFF"/><circle cx="716.162" cy="647.419" r="1.796" fill="#956FFF"/><circle cx="725.502" cy="647.419" r="1.796" fill="#956FFF"/><circle cx="734.843" cy="647.419" r="1.796" fill="#956FFF"/><circle cx="744.184" cy="647.419" r="1.796" fill="#956FFF"/><circle cx="753.525" cy="647.419" r="1.796" fill="#956FFF"/><circle cx="762.866" cy="647.419" r="1.796" fill="#956FFF"/><circle cx="716.162" cy="656.041" r="1.796" fill="#956FFF"/><circle cx="725.502" cy="656.04" r="1.796" fill="#956FFF"/><circle cx="734.843" cy="656.04" r="1.796" fill="#956FFF"/><circle cx="744.184" cy="656.04" r="1.796" fill="#956FFF"/><circle cx="753.525" cy="656.04" r="1.796" fill="#956FFF"/><circle cx="716.162" cy="664.664" r="1.796" fill="#956FFF"/><circle cx="725.502" cy="664.663" r="1.796" fill="#956FFF"/><circle cx="734.843" cy="664.663" r="1.796" fill="#956FFF"/><defs><linearGradient id="a" x1="1072.36" x2="553.031" y1="-51.407" y2="446.945" gradientUnits="userSpaceOnUse"><stop offset=".021" stop-color="#956FFF"/><stop offset="1" stop-color="#1C1B7E"/></linearGradient><linearGradient id="b" x1="634.365" x2="277.177" y1="396.5" y2="712.901" gradientUnits="userSpaceOnUse"><stop stop-color="#956FFF"/><stop offset="1" stop-color="#1A2670"/></linearGradient><linearGradient id="c" x1="170.667" x2="170.667" y1="0" y2="344.061" gradientUnits="userSpaceOnUse"><stop offset=".021" stop-color="#956FFF"/><stop offset="1" stop-color="#1C1B7E"/></linearGradient><linearGradient id="d" x1="1085.18" x2="695.654" y1="556.22" y2="967.042" gradientUnits="userSpaceOnUse"><stop stop-color="#956FFF"/><stop offset=".839" stop-color="#1C1B7E"/></linearGradient></defs></svg>
|
||||
|
After Width: | Height: | Size: 4.4 KiB |
Reference in New Issue
Block a user