mirror of
https://github.com/strapi/strapi.git
synced 2025-12-25 14:14:10 +00:00
Migration of providers to ts (#16323)
This commit is contained in:
parent
dff425769a
commit
28d82d3333
@ -6,7 +6,7 @@ import { useIntl } from 'react-intl';
|
||||
|
||||
const RoleRow = ({ id, name, description, usersCount, icons, rowIndex, canUpdate }) => {
|
||||
const { formatMessage } = useIntl();
|
||||
const [, editObject] = icons;
|
||||
const [, editObject] = icons;
|
||||
|
||||
const usersCountText = formatMessage(
|
||||
{
|
||||
@ -20,9 +20,11 @@ const RoleRow = ({ id, name, description, usersCount, icons, rowIndex, canUpdate
|
||||
<Tr
|
||||
aria-rowindex={rowIndex}
|
||||
key={id}
|
||||
{...(canUpdate ? onRowClick({
|
||||
fn: editObject.onClick,
|
||||
}) : {})}
|
||||
{...(canUpdate
|
||||
? onRowClick({
|
||||
fn: editObject.onClick,
|
||||
})
|
||||
: {})}
|
||||
>
|
||||
<Td maxWidth={pxToRem(130)}>
|
||||
<Typography ellipsis textColor="neutral800">
|
||||
@ -59,11 +61,11 @@ RoleRow.propTypes = {
|
||||
usersCount: PropTypes.number.isRequired,
|
||||
icons: PropTypes.array.isRequired,
|
||||
rowIndex: PropTypes.number.isRequired,
|
||||
canUpdate: PropTypes.bool
|
||||
canUpdate: PropTypes.bool,
|
||||
};
|
||||
|
||||
RoleRow.defaultProps = {
|
||||
canUpdate: false
|
||||
canUpdate: false,
|
||||
};
|
||||
|
||||
export default RoleRow;
|
||||
|
||||
@ -4,6 +4,6 @@ module.exports = {
|
||||
preset: '../../../jest-preset.unit.js',
|
||||
testMatch: ['**/__tests__/**/*.test.ts'],
|
||||
transform: {
|
||||
'^.+\\.(t|j)sx?$': ['@swc/jest'],
|
||||
'^.+\\.ts$': ['@swc/jest'],
|
||||
},
|
||||
};
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"noEmit": true,
|
||||
"noEmit": true
|
||||
},
|
||||
"include": ["types", "src"],
|
||||
"exclude": ["node_modules"]
|
||||
|
||||
@ -1,2 +1,3 @@
|
||||
node_modules/
|
||||
.eslintrc.js
|
||||
index.d.ts
|
||||
@ -1,2 +1,3 @@
|
||||
node_modules/
|
||||
.eslintrc.js
|
||||
index.d.ts
|
||||
@ -1,2 +1,3 @@
|
||||
node_modules/
|
||||
.eslintrc.js
|
||||
index.d.ts
|
||||
|
||||
3
packages/core/utils/index.d.ts
vendored
Normal file
3
packages/core/utils/index.d.ts
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
const utils: any;
|
||||
|
||||
export default utils;
|
||||
@ -28,6 +28,7 @@
|
||||
}
|
||||
],
|
||||
"main": "./lib",
|
||||
"types": "./index.d.ts",
|
||||
"directories": {
|
||||
"lib": "./lib"
|
||||
},
|
||||
|
||||
@ -1,2 +1,3 @@
|
||||
node_modules/
|
||||
.eslintrc.js
|
||||
dist/
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
module.exports = {
|
||||
root: true,
|
||||
extends: ['custom/back'],
|
||||
extends: ['custom/typescript'],
|
||||
};
|
||||
|
||||
@ -1,7 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
const schema = require('./schema');
|
||||
|
||||
module.exports = {
|
||||
schema,
|
||||
};
|
||||
@ -27,13 +27,26 @@
|
||||
"url": "https://strapi.io"
|
||||
}
|
||||
],
|
||||
"main": "./lib",
|
||||
"directories": {
|
||||
"lib": "./lib"
|
||||
},
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
"files": [
|
||||
"./dist"
|
||||
],
|
||||
"scripts": {
|
||||
"build": "run -T tsc",
|
||||
"build:ts": "run -T tsc",
|
||||
"watch": "run -T tsc -w --preserveWatchOutput",
|
||||
"clean": "run -T rimraf ./dist",
|
||||
"prepublishOnly": "yarn clean && yarn build",
|
||||
"lint": "run -T eslint ."
|
||||
},
|
||||
"devDependencies": {
|
||||
"eslint-config-custom": "*",
|
||||
"tsconfig": "*"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@strapi/strapi": "^4.9.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.19.1 <=18.x.x",
|
||||
"npm": ">=6.0.0"
|
||||
|
||||
@ -0,0 +1 @@
|
||||
export { default as schema } from './schema';
|
||||
@ -1,6 +1,4 @@
|
||||
'use strict';
|
||||
|
||||
module.exports = {
|
||||
export default {
|
||||
kind: 'collectionType',
|
||||
collectionName: 'strapi_audit_logs',
|
||||
info: {
|
||||
@ -1,9 +1,19 @@
|
||||
'use strict';
|
||||
import type { Strapi } from '@strapi/strapi';
|
||||
import { schema as auditLogContentType } from './content-types/audit-log';
|
||||
|
||||
const auditLogContentType = require('./content-types/audit-log');
|
||||
interface Event {
|
||||
action: string;
|
||||
date: Date;
|
||||
userId: string | number;
|
||||
payload: Record<string, unknown>;
|
||||
}
|
||||
|
||||
const provider = {
|
||||
async register({ strapi }) {
|
||||
interface Log extends Omit<Event, 'userId'> {
|
||||
user: string | number;
|
||||
}
|
||||
|
||||
export = {
|
||||
async register({ strapi }: { strapi: Strapi }) {
|
||||
const contentTypes = strapi.container.get('content-types');
|
||||
if (!contentTypes.keys().includes('admin::audit-log')) {
|
||||
strapi.container.get('content-types').add('admin::', { 'audit-log': auditLogContentType });
|
||||
@ -11,10 +21,10 @@ const provider = {
|
||||
|
||||
// Return the provider object
|
||||
return {
|
||||
async saveEvent(event) {
|
||||
// Rewrite userId key to user
|
||||
const auditLog = { ...event, user: event.userId };
|
||||
delete auditLog.userId;
|
||||
async saveEvent(event: Event) {
|
||||
const { userId, ...rest } = event;
|
||||
|
||||
const auditLog: Log = { ...rest, user: userId };
|
||||
|
||||
// Save to database
|
||||
await strapi.entityService.create('admin::audit-log', { data: auditLog });
|
||||
@ -22,7 +32,7 @@ const provider = {
|
||||
return this;
|
||||
},
|
||||
|
||||
findMany(query) {
|
||||
findMany(query: Record<string, unknown>) {
|
||||
return strapi.entityService.findPage('admin::audit-log', {
|
||||
populate: ['user'],
|
||||
fields: ['action', 'date', 'payload'],
|
||||
@ -30,14 +40,14 @@ const provider = {
|
||||
});
|
||||
},
|
||||
|
||||
findOne(id) {
|
||||
findOne(id: string | number) {
|
||||
return strapi.entityService.findOne('admin::audit-log', id, {
|
||||
populate: ['user'],
|
||||
fields: ['action', 'date', 'payload'],
|
||||
});
|
||||
},
|
||||
|
||||
deleteExpiredEvents(expirationDate) {
|
||||
deleteExpiredEvents(expirationDate: Date) {
|
||||
return strapi.entityService.deleteMany('admin::audit-log', {
|
||||
filters: {
|
||||
date: {
|
||||
@ -49,5 +59,3 @@ const provider = {
|
||||
};
|
||||
},
|
||||
};
|
||||
|
||||
module.exports = provider;
|
||||
8
packages/providers/audit-logs-local/tsconfig.eslint.json
Normal file
8
packages/providers/audit-logs-local/tsconfig.eslint.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"noEmit": true
|
||||
},
|
||||
"include": ["src"],
|
||||
"exclude": ["node_modules"]
|
||||
}
|
||||
8
packages/providers/audit-logs-local/tsconfig.json
Normal file
8
packages/providers/audit-logs-local/tsconfig.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"extends": "tsconfig/base.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "dist"
|
||||
},
|
||||
"include": ["src"],
|
||||
"exclude": ["node_modules", "**/__tests__/**"]
|
||||
}
|
||||
@ -1,2 +1,3 @@
|
||||
node_modules/
|
||||
.eslintrc.js
|
||||
dist/
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
module.exports = {
|
||||
root: true,
|
||||
extends: ['custom/back'],
|
||||
extends: ['custom/typescript'],
|
||||
};
|
||||
|
||||
@ -28,17 +28,27 @@
|
||||
"url": "https://strapi.io"
|
||||
}
|
||||
],
|
||||
"main": "./lib",
|
||||
"directories": {
|
||||
"lib": "./lib"
|
||||
},
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
"files": [
|
||||
"./dist"
|
||||
],
|
||||
"scripts": {
|
||||
"build": "run -T tsc",
|
||||
"build:ts": "run -T tsc",
|
||||
"watch": "run -T tsc -w --preserveWatchOutput",
|
||||
"clean": "run -T rimraf ./dist",
|
||||
"prepublishOnly": "yarn clean && yarn build",
|
||||
"lint": "run -T eslint ."
|
||||
},
|
||||
"dependencies": {
|
||||
"@strapi/utils": "4.9.1",
|
||||
"node-ses": "^3.0.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"eslint-config-custom": "*",
|
||||
"tsconfig": "*"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.19.1 <=18.x.x",
|
||||
"npm": ">=6.0.0"
|
||||
|
||||
@ -1,18 +1,39 @@
|
||||
'use strict';
|
||||
import nodeSES from 'node-ses';
|
||||
import utils from '@strapi/utils';
|
||||
|
||||
const nodeSES = require('node-ses');
|
||||
const { removeUndefined } = require('@strapi/utils');
|
||||
interface Settings {
|
||||
defaultFrom: string;
|
||||
defaultReplyTo: string;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
init(providerOptions = {}, settings = {}) {
|
||||
const client = nodeSES.createClient({ ...providerOptions });
|
||||
interface SendOptions {
|
||||
from?: string;
|
||||
to: string;
|
||||
cc: string;
|
||||
bcc: string;
|
||||
replyTo?: string;
|
||||
subject: string;
|
||||
text: string;
|
||||
html: string;
|
||||
[key: string]: unknown;
|
||||
}
|
||||
|
||||
interface ProviderOptions {
|
||||
key: string;
|
||||
secret: string;
|
||||
amazon?: string;
|
||||
}
|
||||
|
||||
export = {
|
||||
init(providerOptions: ProviderOptions, settings: Settings) {
|
||||
const client = nodeSES.createClient(providerOptions);
|
||||
|
||||
return {
|
||||
send(options) {
|
||||
send(options: SendOptions): Promise<void> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const { from, to, cc, bcc, replyTo, subject, text, html, ...rest } = options;
|
||||
|
||||
const msg = {
|
||||
const msg: nodeSES.sendEmailOptions = {
|
||||
from: from || settings.defaultFrom,
|
||||
to,
|
||||
cc,
|
||||
@ -23,7 +44,8 @@ module.exports = {
|
||||
message: html,
|
||||
...rest,
|
||||
};
|
||||
client.sendEmail(removeUndefined(msg), (err) => {
|
||||
|
||||
client.sendEmail(utils.removeUndefined(msg), (err) => {
|
||||
if (err) {
|
||||
if (err.Message) {
|
||||
// eslint-disable-next-line prefer-promise-reject-errors
|
||||
8
packages/providers/email-amazon-ses/tsconfig.eslint.json
Normal file
8
packages/providers/email-amazon-ses/tsconfig.eslint.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"noEmit": true
|
||||
},
|
||||
"include": ["src"],
|
||||
"exclude": ["node_modules"]
|
||||
}
|
||||
8
packages/providers/email-amazon-ses/tsconfig.json
Normal file
8
packages/providers/email-amazon-ses/tsconfig.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"extends": "tsconfig/base.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "dist"
|
||||
},
|
||||
"include": ["src"],
|
||||
"exclude": ["node_modules", "**/__tests__/**"]
|
||||
}
|
||||
@ -1,2 +1,4 @@
|
||||
node_modules/
|
||||
.eslintrc.js
|
||||
dist/
|
||||
jest.config.js
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
module.exports = {
|
||||
root: true,
|
||||
extends: ['custom/back'],
|
||||
extends: ['custom/typescript'],
|
||||
};
|
||||
|
||||
8
packages/providers/email-mailgun/jest.config.js
Normal file
8
packages/providers/email-mailgun/jest.config.js
Normal file
@ -0,0 +1,8 @@
|
||||
'use strict';
|
||||
|
||||
module.exports = {
|
||||
preset: '../../../jest-preset.unit.js',
|
||||
transform: {
|
||||
'^.+\\.ts$': ['@swc/jest'],
|
||||
},
|
||||
};
|
||||
@ -1,54 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
const formData = require('form-data');
|
||||
const Mailgun = require('mailgun.js');
|
||||
const { removeUndefined } = require('@strapi/utils');
|
||||
|
||||
const optionsMap = {
|
||||
apiKey: { field: 'key', fn: (value) => value },
|
||||
host: { field: 'url', fn: (value) => `https://${value || 'api.mailgun.net'}` },
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
convertProviderOptions(providerOptions = {}) {
|
||||
const newOptions = {};
|
||||
if (typeof providerOptions === 'object') {
|
||||
Object.keys(providerOptions).forEach((key) => {
|
||||
if (Object.keys(optionsMap).includes(key)) {
|
||||
newOptions[optionsMap[key].field] = optionsMap[key].fn(providerOptions[key]);
|
||||
} else {
|
||||
newOptions[key] = providerOptions[key];
|
||||
}
|
||||
});
|
||||
}
|
||||
return newOptions;
|
||||
},
|
||||
|
||||
init(providerOptions = {}, settings = {}) {
|
||||
const defaults = {
|
||||
username: 'api',
|
||||
};
|
||||
const mailgun = new Mailgun(formData);
|
||||
const mg = mailgun.client({ ...defaults, ...this.convertProviderOptions(providerOptions) });
|
||||
|
||||
return {
|
||||
send(options) {
|
||||
const { from, to, cc, bcc, replyTo, subject, text, html, ...rest } = options;
|
||||
|
||||
const data = {
|
||||
from: from || settings.defaultFrom,
|
||||
to,
|
||||
cc,
|
||||
bcc,
|
||||
'h:Reply-To': replyTo || settings.defaultReplyTo,
|
||||
subject,
|
||||
text,
|
||||
html,
|
||||
...rest,
|
||||
};
|
||||
|
||||
return mg.messages.create(providerOptions.domain, removeUndefined(data));
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
@ -28,17 +28,29 @@
|
||||
"url": "https://strapi.io"
|
||||
}
|
||||
],
|
||||
"main": "./lib",
|
||||
"directories": {
|
||||
"lib": "./lib"
|
||||
},
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
"files": [
|
||||
"./dist"
|
||||
],
|
||||
"scripts": {
|
||||
"build": "run -T tsc",
|
||||
"build:ts": "run -T tsc",
|
||||
"watch": "run -T tsc -w --preserveWatchOutput",
|
||||
"clean": "run -T rimraf ./dist",
|
||||
"prepublishOnly": "yarn clean && yarn build",
|
||||
"test:unit": "run -T jest",
|
||||
"test:unit:watch": "run -T jest --watch",
|
||||
"lint": "run -T eslint ."
|
||||
},
|
||||
"dependencies": {
|
||||
"@strapi/utils": "4.9.1",
|
||||
"form-data": "^4.0.0",
|
||||
"mailgun.js": "5.2.2"
|
||||
"mailgun.js": "8.2.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"eslint-config-custom": "*",
|
||||
"tsconfig": "*"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.19.1 <=18.x.x",
|
||||
|
||||
@ -1,9 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
const formData = require('form-data');
|
||||
const Mailgun = require('mailgun.js');
|
||||
|
||||
const provider = require('../index');
|
||||
import formData from 'form-data';
|
||||
import Mailgun from 'mailgun.js';
|
||||
import Options from 'mailgun.js/interfaces/Options';
|
||||
import provider from '../index';
|
||||
|
||||
describe('@strapi/provider-email-mailgun', () => {
|
||||
describe('.convertProviderOptions()', () => {
|
||||
@ -51,6 +49,7 @@ describe('@strapi/provider-email-mailgun', () => {
|
||||
const defaults = {
|
||||
username: 'api',
|
||||
};
|
||||
|
||||
const providerOptions = {
|
||||
key: 'foo',
|
||||
username: 'bar',
|
||||
@ -60,7 +59,7 @@ describe('@strapi/provider-email-mailgun', () => {
|
||||
const mg = mailgun.client({
|
||||
...defaults,
|
||||
...provider.convertProviderOptions(providerOptions),
|
||||
});
|
||||
} as Options);
|
||||
expect(mg).toMatchObject({
|
||||
messages: {
|
||||
request: {
|
||||
@ -76,7 +75,8 @@ describe('@strapi/provider-email-mailgun', () => {
|
||||
it('fails to create a new Mailgun client due to missing key', () => {
|
||||
const defaults = {
|
||||
username: 'api',
|
||||
};
|
||||
} as Options;
|
||||
|
||||
const providerOptions = {
|
||||
username: 'bar',
|
||||
domain: 'baz.example.com',
|
||||
82
packages/providers/email-mailgun/src/index.ts
Normal file
82
packages/providers/email-mailgun/src/index.ts
Normal file
@ -0,0 +1,82 @@
|
||||
import formData from 'form-data';
|
||||
import Mailgun from 'mailgun.js';
|
||||
import utils from '@strapi/utils';
|
||||
import Options from 'mailgun.js/interfaces/Options';
|
||||
import { MailgunMessageData } from 'mailgun.js/interfaces/Messages';
|
||||
|
||||
interface Settings {
|
||||
defaultFrom: string;
|
||||
defaultReplyTo: string;
|
||||
}
|
||||
|
||||
interface SendOptions {
|
||||
from?: string;
|
||||
to: string;
|
||||
cc: string;
|
||||
bcc: string;
|
||||
replyTo?: string;
|
||||
subject: string;
|
||||
text: string;
|
||||
html: string;
|
||||
[key: string]: unknown;
|
||||
}
|
||||
|
||||
interface LegacyOptionMapper {
|
||||
field: string;
|
||||
fn(value: unknown): string;
|
||||
}
|
||||
|
||||
type ProviderOptions = Record<string, unknown>;
|
||||
|
||||
const optionsMap: Record<string, LegacyOptionMapper> = {
|
||||
apiKey: { field: 'key', fn: (value) => `${value}` },
|
||||
host: { field: 'url', fn: (value) => `https://${value || 'api.mailgun.net'}` },
|
||||
};
|
||||
|
||||
export = {
|
||||
convertProviderOptions(providerOptions: ProviderOptions): Record<string, unknown> {
|
||||
const newOptions: Record<string, unknown> = {};
|
||||
if (typeof providerOptions === 'object') {
|
||||
Object.keys(providerOptions).forEach((key) => {
|
||||
if (Object.keys(optionsMap).includes(key)) {
|
||||
newOptions[optionsMap[key].field] = optionsMap[key].fn(providerOptions[key]);
|
||||
} else {
|
||||
newOptions[key] = providerOptions[key];
|
||||
}
|
||||
});
|
||||
}
|
||||
return newOptions;
|
||||
},
|
||||
|
||||
init(providerOptions: ProviderOptions, settings: Settings) {
|
||||
const defaults = {
|
||||
username: 'api',
|
||||
};
|
||||
|
||||
const mailgun = new Mailgun(formData);
|
||||
const mg = mailgun.client({
|
||||
...defaults,
|
||||
...this.convertProviderOptions(providerOptions),
|
||||
} as Options);
|
||||
|
||||
return {
|
||||
send(options: SendOptions) {
|
||||
const { from, to, cc, bcc, replyTo, subject, text, html, ...rest } = options;
|
||||
|
||||
const data = {
|
||||
from: from || settings.defaultFrom,
|
||||
to,
|
||||
cc,
|
||||
bcc,
|
||||
'h:Reply-To': replyTo || settings.defaultReplyTo,
|
||||
subject,
|
||||
text,
|
||||
html,
|
||||
...rest,
|
||||
} as MailgunMessageData;
|
||||
|
||||
return mg.messages.create(providerOptions.domain as string, utils.removeUndefined(data));
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
8
packages/providers/email-mailgun/tsconfig.eslint.json
Normal file
8
packages/providers/email-mailgun/tsconfig.eslint.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"noEmit": true
|
||||
},
|
||||
"include": ["src"],
|
||||
"exclude": ["node_modules"]
|
||||
}
|
||||
8
packages/providers/email-mailgun/tsconfig.json
Normal file
8
packages/providers/email-mailgun/tsconfig.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"extends": "tsconfig/base.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "dist"
|
||||
},
|
||||
"include": ["src"],
|
||||
"exclude": ["node_modules", "**/__tests__/**"]
|
||||
}
|
||||
@ -1,2 +1,3 @@
|
||||
node_modules/
|
||||
.eslintrc.js
|
||||
dist/
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
module.exports = {
|
||||
root: true,
|
||||
extends: ['custom/back'],
|
||||
extends: ['custom/typescript'],
|
||||
};
|
||||
|
||||
@ -41,17 +41,28 @@
|
||||
"email": "git@roschaefer.de"
|
||||
}
|
||||
],
|
||||
"main": "./lib",
|
||||
"directories": {
|
||||
"lib": "./lib"
|
||||
},
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
"files": [
|
||||
"./dist"
|
||||
],
|
||||
"scripts": {
|
||||
"build": "run -T tsc",
|
||||
"build:ts": "run -T tsc",
|
||||
"watch": "run -T tsc -w --preserveWatchOutput",
|
||||
"clean": "run -T rimraf ./dist",
|
||||
"prepublishOnly": "yarn clean && yarn build",
|
||||
"lint": "run -T eslint ."
|
||||
},
|
||||
"dependencies": {
|
||||
"lodash": "4.17.21",
|
||||
"nodemailer": "6.9.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/nodemailer": "6.4.7",
|
||||
"eslint-config-custom": "*",
|
||||
"tsconfig": "*"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.19.1 <=18.x.x",
|
||||
"npm": ">=6.0.0"
|
||||
|
||||
@ -1,11 +1,24 @@
|
||||
'use strict';
|
||||
import _ from 'lodash';
|
||||
import nodemailer, { SendMailOptions } from 'nodemailer';
|
||||
|
||||
/**
|
||||
* Module dependencies
|
||||
*/
|
||||
interface Settings {
|
||||
defaultFrom: string;
|
||||
defaultReplyTo: string;
|
||||
}
|
||||
|
||||
const _ = require('lodash');
|
||||
const nodemailer = require('nodemailer');
|
||||
interface SendOptions {
|
||||
from?: string;
|
||||
to: string;
|
||||
cc: string;
|
||||
bcc: string;
|
||||
replyTo?: string;
|
||||
subject: string;
|
||||
text: string;
|
||||
html: string;
|
||||
[key: string]: unknown;
|
||||
}
|
||||
|
||||
type ProviderOptions = Parameters<typeof nodemailer.createTransport>[0];
|
||||
|
||||
const emailFields = [
|
||||
'from',
|
||||
@ -19,17 +32,17 @@ const emailFields = [
|
||||
'attachments',
|
||||
];
|
||||
|
||||
module.exports = {
|
||||
export = {
|
||||
provider: 'nodemailer',
|
||||
name: 'Nodemailer',
|
||||
|
||||
init(providerOptions = {}, settings = {}) {
|
||||
init(providerOptions: ProviderOptions, settings: Settings) {
|
||||
const transporter = nodemailer.createTransport(providerOptions);
|
||||
|
||||
return {
|
||||
send(options) {
|
||||
send(options: SendOptions) {
|
||||
// Default values.
|
||||
const emailOptions = {
|
||||
const emailOptions: SendMailOptions = {
|
||||
..._.pick(options, emailFields),
|
||||
from: options.from || settings.defaultFrom,
|
||||
replyTo: options.replyTo || settings.defaultReplyTo,
|
||||
8
packages/providers/email-nodemailer/tsconfig.eslint.json
Normal file
8
packages/providers/email-nodemailer/tsconfig.eslint.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"noEmit": true
|
||||
},
|
||||
"include": ["src"],
|
||||
"exclude": ["node_modules"]
|
||||
}
|
||||
8
packages/providers/email-nodemailer/tsconfig.json
Normal file
8
packages/providers/email-nodemailer/tsconfig.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"extends": "tsconfig/base.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "dist"
|
||||
},
|
||||
"include": ["src"],
|
||||
"exclude": ["node_modules", "**/__tests__/**"]
|
||||
}
|
||||
@ -1,2 +1,3 @@
|
||||
node_modules/
|
||||
.eslintrc.js
|
||||
dist/
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
module.exports = {
|
||||
root: true,
|
||||
extends: ['custom/back'],
|
||||
extends: ['custom/typescript'],
|
||||
};
|
||||
|
||||
@ -1,38 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
const sendgrid = require('@sendgrid/mail');
|
||||
const { removeUndefined } = require('@strapi/utils');
|
||||
|
||||
module.exports = {
|
||||
init(providerOptions = {}, settings = {}) {
|
||||
sendgrid.setApiKey(providerOptions.apiKey);
|
||||
|
||||
return {
|
||||
send(options) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const { from, to, cc, bcc, replyTo, subject, text, html, ...rest } = options;
|
||||
|
||||
const msg = {
|
||||
from: from || settings.defaultFrom,
|
||||
to,
|
||||
cc,
|
||||
bcc,
|
||||
replyTo: replyTo || settings.defaultReplyTo,
|
||||
subject,
|
||||
text,
|
||||
html,
|
||||
...rest,
|
||||
};
|
||||
|
||||
sendgrid.send(removeUndefined(msg), (err) => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
} else {
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
@ -28,17 +28,27 @@
|
||||
"url": "https://strapi.io"
|
||||
}
|
||||
],
|
||||
"main": "./lib",
|
||||
"directories": {
|
||||
"lib": "./lib"
|
||||
},
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
"files": [
|
||||
"./dist"
|
||||
],
|
||||
"scripts": {
|
||||
"build": "run -T tsc",
|
||||
"build:ts": "run -T tsc",
|
||||
"watch": "run -T tsc -w --preserveWatchOutput",
|
||||
"clean": "run -T rimraf ./dist",
|
||||
"prepublishOnly": "yarn clean && yarn build",
|
||||
"lint": "run -T eslint ."
|
||||
},
|
||||
"dependencies": {
|
||||
"@sendgrid/mail": "7.7.0",
|
||||
"@strapi/utils": "4.9.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"eslint-config-custom": "*",
|
||||
"tsconfig": "*"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.19.1 <=18.x.x",
|
||||
"npm": ">=6.0.0"
|
||||
|
||||
57
packages/providers/email-sendgrid/src/index.ts
Normal file
57
packages/providers/email-sendgrid/src/index.ts
Normal file
@ -0,0 +1,57 @@
|
||||
import sendgrid, { MailDataRequired } from '@sendgrid/mail';
|
||||
import utils from '@strapi/utils';
|
||||
|
||||
interface Settings {
|
||||
defaultFrom: string;
|
||||
defaultReplyTo: string;
|
||||
}
|
||||
|
||||
interface SendOptions {
|
||||
from?: string;
|
||||
to: string;
|
||||
cc: string;
|
||||
bcc: string;
|
||||
replyTo?: string;
|
||||
subject: string;
|
||||
text: string;
|
||||
html: string;
|
||||
[key: string]: unknown;
|
||||
}
|
||||
|
||||
interface ProviderOptions {
|
||||
apiKey: string;
|
||||
}
|
||||
|
||||
export = {
|
||||
init(providerOptions: ProviderOptions, settings: Settings) {
|
||||
sendgrid.setApiKey(providerOptions.apiKey);
|
||||
|
||||
return {
|
||||
send(options: SendOptions): Promise<void> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const { from, to, cc, bcc, replyTo, subject, text, html, ...rest } = options;
|
||||
|
||||
const msg: MailDataRequired = {
|
||||
from: from || settings.defaultFrom,
|
||||
to,
|
||||
cc,
|
||||
bcc,
|
||||
replyTo: replyTo || settings.defaultReplyTo,
|
||||
subject,
|
||||
text,
|
||||
html,
|
||||
...rest,
|
||||
};
|
||||
|
||||
sendgrid.send(utils.removeUndefined(msg), false, (err) => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
} else {
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
8
packages/providers/email-sendgrid/tsconfig.eslint.json
Normal file
8
packages/providers/email-sendgrid/tsconfig.eslint.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"noEmit": true
|
||||
},
|
||||
"include": ["src"],
|
||||
"exclude": ["node_modules"]
|
||||
}
|
||||
8
packages/providers/email-sendgrid/tsconfig.json
Normal file
8
packages/providers/email-sendgrid/tsconfig.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"extends": "tsconfig/base.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "dist"
|
||||
},
|
||||
"include": ["src"],
|
||||
"exclude": ["node_modules", "**/__tests__/**"]
|
||||
}
|
||||
@ -1,2 +1,3 @@
|
||||
node_modules/
|
||||
.eslintrc.js
|
||||
dist/
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
module.exports = {
|
||||
root: true,
|
||||
extends: ['custom/back'],
|
||||
extends: ['custom/typescript'],
|
||||
};
|
||||
|
||||
@ -27,17 +27,28 @@
|
||||
"url": "https://strapi.io"
|
||||
}
|
||||
],
|
||||
"main": "./lib",
|
||||
"directories": {
|
||||
"lib": "./lib"
|
||||
},
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
"files": [
|
||||
"./dist"
|
||||
],
|
||||
"scripts": {
|
||||
"build": "run -T tsc",
|
||||
"build:ts": "run -T tsc",
|
||||
"watch": "run -T tsc -w --preserveWatchOutput",
|
||||
"clean": "run -T rimraf ./dist",
|
||||
"prepublishOnly": "yarn clean && yarn build",
|
||||
"lint": "run -T eslint ."
|
||||
},
|
||||
"dependencies": {
|
||||
"@strapi/utils": "4.9.1",
|
||||
"sendmail": "^1.6.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/sendmail": "1.4.4",
|
||||
"eslint-config-custom": "*",
|
||||
"tsconfig": "*"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.19.1 <=18.x.x",
|
||||
"npm": ">=6.0.0"
|
||||
|
||||
@ -1,20 +1,38 @@
|
||||
'use strict';
|
||||
import sendmailFactory, { Options, MailInput } from 'sendmail';
|
||||
import utils from '@strapi/utils';
|
||||
|
||||
const sendmailFactory = require('sendmail');
|
||||
const { removeUndefined } = require('@strapi/utils');
|
||||
interface Settings {
|
||||
defaultFrom: string;
|
||||
defaultReplyTo: string;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
init(providerOptions = {}, settings = {}) {
|
||||
interface SendOptions {
|
||||
from?: string;
|
||||
to: string;
|
||||
cc: string;
|
||||
bcc: string;
|
||||
replyTo?: string;
|
||||
subject: string;
|
||||
text: string;
|
||||
html: string;
|
||||
[key: string]: unknown;
|
||||
}
|
||||
|
||||
type ProviderOptions = Options;
|
||||
|
||||
export = {
|
||||
init(providerOptions: ProviderOptions, settings: Settings) {
|
||||
const sendmail = sendmailFactory({
|
||||
silent: true,
|
||||
...providerOptions,
|
||||
});
|
||||
|
||||
return {
|
||||
send(options) {
|
||||
send(options: SendOptions): Promise<void> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const { from, to, cc, bcc, replyTo, subject, text, html, ...rest } = options;
|
||||
|
||||
const msg = {
|
||||
const msg: MailInput = {
|
||||
from: from || settings.defaultFrom,
|
||||
to,
|
||||
cc,
|
||||
@ -26,7 +44,7 @@ module.exports = {
|
||||
...rest,
|
||||
};
|
||||
|
||||
sendmail(removeUndefined(msg), (err) => {
|
||||
sendmail(utils.removeUndefined(msg), (err) => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
} else {
|
||||
8
packages/providers/email-sendmail/tsconfig.eslint.json
Normal file
8
packages/providers/email-sendmail/tsconfig.eslint.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"noEmit": true
|
||||
},
|
||||
"include": ["src"],
|
||||
"exclude": ["node_modules"]
|
||||
}
|
||||
8
packages/providers/email-sendmail/tsconfig.json
Normal file
8
packages/providers/email-sendmail/tsconfig.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"extends": "tsconfig/base.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "dist"
|
||||
},
|
||||
"include": ["src"],
|
||||
"exclude": ["node_modules", "**/__tests__/**"]
|
||||
}
|
||||
@ -1,2 +1,4 @@
|
||||
node_modules/
|
||||
dist/
|
||||
.eslintrc.js
|
||||
jest.config.js
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
module.exports = {
|
||||
root: true,
|
||||
extends: ['custom/back'],
|
||||
extends: ['custom/typescript'],
|
||||
};
|
||||
|
||||
@ -2,4 +2,7 @@
|
||||
|
||||
module.exports = {
|
||||
preset: '../../../jest-preset.unit.js',
|
||||
transform: {
|
||||
'^.+\\.ts$': ['@swc/jest'],
|
||||
},
|
||||
};
|
||||
|
||||
@ -29,11 +29,17 @@
|
||||
"url": "https://strapi.io"
|
||||
}
|
||||
],
|
||||
"main": "./lib",
|
||||
"directories": {
|
||||
"lib": "./lib"
|
||||
},
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
"files": [
|
||||
"./dist"
|
||||
],
|
||||
"scripts": {
|
||||
"build": "run -T tsc",
|
||||
"build:ts": "run -T tsc",
|
||||
"watch": "run -T tsc -w --preserveWatchOutput",
|
||||
"clean": "run -T rimraf ./dist",
|
||||
"prepublishOnly": "yarn clean && yarn build",
|
||||
"test:unit": "run -T jest",
|
||||
"test:unit:watch": "run -T jest --watch",
|
||||
"lint": "run -T eslint ."
|
||||
@ -42,6 +48,11 @@
|
||||
"aws-sdk": "2.1351.0",
|
||||
"lodash": "4.17.21"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jest": "29.2.0",
|
||||
"eslint-config-custom": "*",
|
||||
"tsconfig": "*"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.19.1 <=18.x.x",
|
||||
"npm": ">=6.0.0"
|
||||
|
||||
@ -1,6 +1,4 @@
|
||||
'use strict';
|
||||
|
||||
const { getBucketFromUrl } = require('../utils');
|
||||
import { getBucketFromUrl } from '../utils';
|
||||
|
||||
describe('Test for URLs', () => {
|
||||
test('Virtual hosted style', async () => {
|
||||
@ -1,7 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
const AWS = require('aws-sdk');
|
||||
const awsProvider = require('../index');
|
||||
/* eslint-disable @typescript-eslint/ban-ts-comment */
|
||||
import AWS from 'aws-sdk';
|
||||
import { File } from '@strapi/plugin-upload';
|
||||
import awsProvider from '../index';
|
||||
|
||||
jest.mock('aws-sdk');
|
||||
|
||||
@ -9,26 +9,37 @@ const S3InstanceMock = {
|
||||
upload: jest.fn((params, callback) => callback(null, {})),
|
||||
};
|
||||
|
||||
// @ts-ignore
|
||||
AWS.S3.mockReturnValue(S3InstanceMock);
|
||||
|
||||
describe('AWS-S3 provider', () => {
|
||||
const providerInstance = awsProvider.init({});
|
||||
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
describe('upload', () => {
|
||||
test('Should add url to file object', async () => {
|
||||
const providerInstance = awsProvider.init({
|
||||
s3Options: {
|
||||
params: {
|
||||
Bucket: 'test',
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
S3InstanceMock.upload.mockImplementationOnce((params, callback) =>
|
||||
callback(null, { Location: 'https://validurl.test/tmp/test.json' })
|
||||
);
|
||||
const file = {
|
||||
path: '/tmp/',
|
||||
|
||||
const file: File = {
|
||||
name: 'test',
|
||||
size: 100,
|
||||
url: '',
|
||||
path: 'tmp',
|
||||
hash: 'test',
|
||||
ext: '.json',
|
||||
mime: 'application/json',
|
||||
buffer: '',
|
||||
buffer: Buffer.from(''),
|
||||
};
|
||||
|
||||
await providerInstance.upload(file);
|
||||
@ -39,15 +50,26 @@ describe('AWS-S3 provider', () => {
|
||||
});
|
||||
|
||||
test('Should add to the url the https protocol as it is missing', async () => {
|
||||
const providerInstance = awsProvider.init({
|
||||
s3Options: {
|
||||
params: {
|
||||
Bucket: 'test',
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
S3InstanceMock.upload.mockImplementationOnce((params, callback) =>
|
||||
callback(null, { Location: 'uri.test/tmp/test.json' })
|
||||
);
|
||||
const file = {
|
||||
path: '/tmp/',
|
||||
const file: File = {
|
||||
name: 'test',
|
||||
size: 100,
|
||||
url: '',
|
||||
path: 'tmp',
|
||||
hash: 'test',
|
||||
ext: '.json',
|
||||
mime: 'application/json',
|
||||
buffer: '',
|
||||
buffer: Buffer.from(''),
|
||||
};
|
||||
|
||||
await providerInstance.upload(file);
|
||||
@ -58,17 +80,27 @@ describe('AWS-S3 provider', () => {
|
||||
});
|
||||
|
||||
test('Should prepend the baseUrl to the url of the file object', async () => {
|
||||
const providerInstance = awsProvider.init({ baseUrl: 'https://cdn.test' });
|
||||
const providerInstance = awsProvider.init({
|
||||
baseUrl: 'https://cdn.test',
|
||||
s3Options: {
|
||||
params: {
|
||||
Bucket: 'test',
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
S3InstanceMock.upload.mockImplementationOnce((params, callback) =>
|
||||
callback(null, { Location: 'https://validurl.test' })
|
||||
);
|
||||
const file = {
|
||||
const file: File = {
|
||||
name: 'test',
|
||||
size: 100,
|
||||
url: '',
|
||||
path: 'tmp/test',
|
||||
hash: 'test',
|
||||
ext: '.json',
|
||||
mime: 'application/json',
|
||||
buffer: '',
|
||||
buffer: Buffer.from(''),
|
||||
};
|
||||
|
||||
await providerInstance.upload(file);
|
||||
@ -82,17 +114,26 @@ describe('AWS-S3 provider', () => {
|
||||
const providerInstance = awsProvider.init({
|
||||
baseUrl: 'https://cdn.test',
|
||||
rootPath: 'dir/dir2',
|
||||
s3Options: {
|
||||
params: {
|
||||
Bucket: 'test',
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
S3InstanceMock.upload.mockImplementationOnce((params, callback) =>
|
||||
callback(null, { Location: 'https://validurl.test' })
|
||||
);
|
||||
const file = {
|
||||
|
||||
const file: File = {
|
||||
name: 'test',
|
||||
size: 100,
|
||||
url: '',
|
||||
path: 'tmp/test',
|
||||
hash: 'test',
|
||||
ext: '.json',
|
||||
mime: 'application/json',
|
||||
buffer: '',
|
||||
buffer: Buffer.from(''),
|
||||
};
|
||||
|
||||
await providerInstance.upload(file);
|
||||
@ -1,25 +1,52 @@
|
||||
'use strict';
|
||||
import type { ReadStream } from 'node:fs';
|
||||
import { getOr } from 'lodash/fp';
|
||||
import AWS from 'aws-sdk';
|
||||
import { getBucketFromUrl } from './utils';
|
||||
|
||||
/**
|
||||
* Module dependencies
|
||||
*/
|
||||
interface File {
|
||||
name: string;
|
||||
alternativeText?: string;
|
||||
caption?: string;
|
||||
width?: number;
|
||||
height?: number;
|
||||
formats?: Record<string, unknown>;
|
||||
hash: string;
|
||||
ext?: string;
|
||||
mime: string;
|
||||
size: number;
|
||||
url: string;
|
||||
previewUrl?: string;
|
||||
path?: string;
|
||||
provider?: string;
|
||||
provider_metadata?: Record<string, unknown>;
|
||||
stream?: ReadStream;
|
||||
buffer?: Buffer;
|
||||
}
|
||||
|
||||
/* eslint-disable no-unused-vars */
|
||||
// Public node modules.
|
||||
const { getOr } = require('lodash/fp');
|
||||
// TODO V5: Migrate to aws-sdk v3
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
require('aws-sdk/lib/maintenance_mode_message').suppress = true;
|
||||
const AWS = require('aws-sdk');
|
||||
const { getBucketFromUrl } = require('./utils');
|
||||
|
||||
function assertUrlProtocol(url) {
|
||||
function assertUrlProtocol(url: string) {
|
||||
// Regex to test protocol like "http://", "https://"
|
||||
return /^\w*:\/\//.test(url);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
init({ baseUrl = null, rootPath = null, s3Options, ...legacyS3Options }) {
|
||||
if (legacyS3Options) {
|
||||
interface InitOptions extends Partial<AWS.S3.ClientConfiguration> {
|
||||
baseUrl?: string;
|
||||
rootPath?: string;
|
||||
s3Options: AWS.S3.ClientConfiguration & {
|
||||
params: {
|
||||
Bucket: string; // making it required
|
||||
ACL?: string;
|
||||
signedUrlExpires?: string;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
export = {
|
||||
init({ baseUrl, rootPath, s3Options, ...legacyS3Options }: InitOptions) {
|
||||
if (Object.keys(legacyS3Options).length > 0) {
|
||||
process.emitWarning(
|
||||
"S3 configuration options passed at root level of the plugin's providerOptions is deprecated and will be removed in a future release. Please wrap them inside the 's3Options:{}' property."
|
||||
);
|
||||
@ -34,7 +61,7 @@ module.exports = {
|
||||
|
||||
const filePrefix = rootPath ? `${rootPath.replace(/\/+$/, '')}/` : '';
|
||||
|
||||
const getFileKey = (file) => {
|
||||
const getFileKey = (file: File) => {
|
||||
const path = file.path ? `${file.path}/` : '';
|
||||
|
||||
return `${filePrefix}${path}${file.hash}${file.ext}`;
|
||||
@ -42,48 +69,47 @@ module.exports = {
|
||||
|
||||
const ACL = getOr('public-read', ['params', 'ACL'], config);
|
||||
|
||||
const upload = (file, customParams = {}) =>
|
||||
const upload = (file: File, customParams = {}): Promise<void> =>
|
||||
new Promise((resolve, reject) => {
|
||||
// upload file on S3 bucket
|
||||
const fileKey = getFileKey(file);
|
||||
S3.upload(
|
||||
{
|
||||
Key: fileKey,
|
||||
Body: file.stream || Buffer.from(file.buffer, 'binary'),
|
||||
ACL,
|
||||
ContentType: file.mime,
|
||||
...customParams,
|
||||
},
|
||||
(err, data) => {
|
||||
if (err) {
|
||||
return reject(err);
|
||||
}
|
||||
|
||||
// set the bucket file url
|
||||
if (assertUrlProtocol(data.Location)) {
|
||||
file.url = baseUrl ? `${baseUrl}/${fileKey}` : data.Location;
|
||||
} else {
|
||||
// Default protocol to https protocol
|
||||
file.url = `https://${data.Location}`;
|
||||
}
|
||||
resolve();
|
||||
if (!file.stream && !file.buffer) {
|
||||
reject(new Error('Missing file stream or buffer'));
|
||||
return;
|
||||
}
|
||||
|
||||
const params = {
|
||||
Key: fileKey,
|
||||
Bucket: config.params.Bucket,
|
||||
Body: file.stream || file.buffer,
|
||||
ACL,
|
||||
ContentType: file.mime,
|
||||
...customParams,
|
||||
};
|
||||
|
||||
const onUploaded = (err: Error, data: AWS.S3.ManagedUpload.SendData) => {
|
||||
if (err) {
|
||||
return reject(err);
|
||||
}
|
||||
);
|
||||
|
||||
// set the bucket file url
|
||||
if (assertUrlProtocol(data.Location)) {
|
||||
file.url = baseUrl ? `${baseUrl}/${fileKey}` : data.Location;
|
||||
} else {
|
||||
// Default protocol to https protocol
|
||||
file.url = `https://${data.Location}`;
|
||||
}
|
||||
resolve();
|
||||
};
|
||||
|
||||
S3.upload(params, onUploaded);
|
||||
});
|
||||
|
||||
return {
|
||||
isPrivate() {
|
||||
return ACL === 'private';
|
||||
},
|
||||
/**
|
||||
* @param {Object} file
|
||||
* @param {string} file.path
|
||||
* @param {string} file.hash
|
||||
* @param {string} file.ext
|
||||
* @param {Object} customParams
|
||||
* @returns {Promise<{url: string}>}
|
||||
*/
|
||||
getSignedUrl(file, customParams = {}) {
|
||||
async getSignedUrl(file: File): Promise<{ url: string }> {
|
||||
// Do not sign the url if it does not come from the same bucket.
|
||||
const { bucket } = getBucketFromUrl(file.url);
|
||||
if (bucket !== config.params.Bucket) {
|
||||
@ -109,19 +135,20 @@ module.exports = {
|
||||
);
|
||||
});
|
||||
},
|
||||
uploadStream(file, customParams = {}) {
|
||||
uploadStream(file: File, customParams = {}) {
|
||||
return upload(file, customParams);
|
||||
},
|
||||
upload(file, customParams = {}) {
|
||||
upload(file: File, customParams = {}) {
|
||||
return upload(file, customParams);
|
||||
},
|
||||
delete(file, customParams = {}) {
|
||||
delete(file: File, customParams = {}): Promise<void> {
|
||||
return new Promise((resolve, reject) => {
|
||||
// delete file on S3 bucket
|
||||
const fileKey = getFileKey(file);
|
||||
S3.deleteObject(
|
||||
{
|
||||
Key: fileKey,
|
||||
Bucket: config.params.Bucket,
|
||||
...customParams,
|
||||
},
|
||||
(err) => {
|
||||
@ -1,7 +1,10 @@
|
||||
'use strict';
|
||||
|
||||
const ENDPOINT_PATTERN = /^(.+\.)?s3[.-]([a-z0-9-]+)\./;
|
||||
|
||||
interface BucketInfo {
|
||||
bucket?: string | null;
|
||||
err?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the bucket name from a URL.
|
||||
* See all URL formats in https://docs.aws.amazon.com/AmazonS3/latest/userguide/access-bucket-intro.html
|
||||
@ -9,9 +12,9 @@ const ENDPOINT_PATTERN = /^(.+\.)?s3[.-]([a-z0-9-]+)\./;
|
||||
* @param {string} fileUrl - the URL to parse
|
||||
* @returns {object} result
|
||||
* @returns {string} result.bucket - the bucket name
|
||||
* @returns {string} result.error - if any
|
||||
* @returns {string} result.err - if any
|
||||
*/
|
||||
function getBucketFromUrl(fileUrl) {
|
||||
export function getBucketFromUrl(fileUrl: string): BucketInfo {
|
||||
const uri = new URL(fileUrl);
|
||||
|
||||
// S3://<bucket-name>/<key>
|
||||
@ -59,5 +62,3 @@ function getBucketFromUrl(fileUrl) {
|
||||
// https://<bucket-name>.s3.amazonaws.com/
|
||||
return { bucket: prefix.substring(0, prefix.length - 1) };
|
||||
}
|
||||
|
||||
module.exports = { getBucketFromUrl };
|
||||
8
packages/providers/upload-aws-s3/tsconfig.eslint.json
Normal file
8
packages/providers/upload-aws-s3/tsconfig.eslint.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"noEmit": true
|
||||
},
|
||||
"include": ["src"],
|
||||
"exclude": ["node_modules"]
|
||||
}
|
||||
8
packages/providers/upload-aws-s3/tsconfig.json
Normal file
8
packages/providers/upload-aws-s3/tsconfig.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"extends": "tsconfig/base.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "dist"
|
||||
},
|
||||
"include": ["src"],
|
||||
"exclude": ["node_modules", "**/__tests__/**"]
|
||||
}
|
||||
@ -1,2 +1,4 @@
|
||||
node_modules/
|
||||
dist/
|
||||
.eslintrc.js
|
||||
jest.config.js
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
module.exports = {
|
||||
root: true,
|
||||
extends: ['custom/back'],
|
||||
extends: ['custom/typescript'],
|
||||
};
|
||||
|
||||
@ -28,11 +28,17 @@
|
||||
"url": "https://strapi.io"
|
||||
}
|
||||
],
|
||||
"main": "./lib",
|
||||
"directories": {
|
||||
"lib": "./lib"
|
||||
},
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
"files": [
|
||||
"./dist"
|
||||
],
|
||||
"scripts": {
|
||||
"build": "run -T tsc",
|
||||
"build:ts": "run -T tsc",
|
||||
"watch": "run -T tsc -w --preserveWatchOutput",
|
||||
"clean": "run -T rimraf ./dist",
|
||||
"prepublishOnly": "yarn clean && yarn build",
|
||||
"lint": "run -T eslint ."
|
||||
},
|
||||
"dependencies": {
|
||||
@ -40,6 +46,10 @@
|
||||
"cloudinary": "^1.33.0",
|
||||
"into-stream": "^5.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"eslint-config-custom": "*",
|
||||
"tsconfig": "*"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.19.1 <=18.x.x",
|
||||
"npm": ">=6.0.0"
|
||||
|
||||
@ -1,21 +1,35 @@
|
||||
'use strict';
|
||||
import type { ReadStream } from 'node:fs';
|
||||
import { v2 as cloudinary, ConfigOptions, UploadApiOptions } from 'cloudinary';
|
||||
import intoStream from 'into-stream';
|
||||
import utils from '@strapi/utils';
|
||||
|
||||
/**
|
||||
* Module dependencies
|
||||
*/
|
||||
interface File {
|
||||
name: string;
|
||||
alternativeText?: string;
|
||||
caption?: string;
|
||||
width?: number;
|
||||
height?: number;
|
||||
formats?: Record<string, unknown>;
|
||||
hash: string;
|
||||
ext?: string;
|
||||
mime: string;
|
||||
size: number;
|
||||
url: string;
|
||||
previewUrl?: string;
|
||||
path?: string;
|
||||
provider?: string;
|
||||
provider_metadata?: Record<string, unknown>;
|
||||
stream?: ReadStream;
|
||||
buffer?: Buffer;
|
||||
}
|
||||
|
||||
// Public node modules.
|
||||
const cloudinary = require('cloudinary').v2;
|
||||
const intoStream = require('into-stream');
|
||||
const { PayloadTooLargeError } = require('@strapi/utils').errors;
|
||||
export = {
|
||||
init(options: ConfigOptions) {
|
||||
cloudinary.config(options);
|
||||
|
||||
module.exports = {
|
||||
init(config) {
|
||||
cloudinary.config(config);
|
||||
|
||||
const upload = (file, customConfig = {}) =>
|
||||
new Promise((resolve, reject) => {
|
||||
const config = {
|
||||
const upload = (file: File, customConfig = {}): Promise<void> => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const config: Partial<UploadApiOptions> = {
|
||||
resource_type: 'auto',
|
||||
public_id: file.hash,
|
||||
};
|
||||
@ -33,13 +47,17 @@ module.exports = {
|
||||
(err, image) => {
|
||||
if (err) {
|
||||
if (err.message.includes('File size too large')) {
|
||||
reject(new PayloadTooLargeError());
|
||||
reject(new utils.errors.PayloadTooLargeError());
|
||||
} else {
|
||||
reject(new Error(`Error uploading to cloudinary: ${err.message}`));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!image) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (image.resource_type === 'video') {
|
||||
file.previewUrl = cloudinary.url(`${image.public_id}.gif`, {
|
||||
video_sampling: 6,
|
||||
@ -62,32 +80,41 @@ module.exports = {
|
||||
|
||||
if (file.stream) {
|
||||
file.stream.pipe(uploadStream);
|
||||
} else {
|
||||
} else if (file.buffer) {
|
||||
intoStream(file.buffer).pipe(uploadStream);
|
||||
} else {
|
||||
throw new Error('Missing file stream or buffer');
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
return {
|
||||
uploadStream(file, customConfig = {}) {
|
||||
uploadStream(file: File, customConfig = {}) {
|
||||
return upload(file, customConfig);
|
||||
},
|
||||
upload(file, customConfig = {}) {
|
||||
upload(file: File, customConfig = {}) {
|
||||
return upload(file, customConfig);
|
||||
},
|
||||
async delete(file, customConfig = {}) {
|
||||
async delete(file: File, customConfig = {}) {
|
||||
try {
|
||||
const { resource_type: resourceType, public_id: publicId } = file.provider_metadata;
|
||||
const response = await cloudinary.uploader.destroy(publicId, {
|
||||
const { resource_type: resourceType, public_id: publicId } = file.provider_metadata ?? {};
|
||||
const deleteConfig = {
|
||||
resource_type: (resourceType || 'image') as string,
|
||||
invalidate: true,
|
||||
resource_type: resourceType || 'image',
|
||||
...customConfig,
|
||||
});
|
||||
};
|
||||
|
||||
const response = await cloudinary.uploader.destroy(`${publicId}`, deleteConfig);
|
||||
|
||||
if (response.result !== 'ok' && response.result !== 'not found') {
|
||||
throw new Error(`Error deleting on cloudinary: ${response.result}`);
|
||||
throw new Error(response.result);
|
||||
}
|
||||
} catch (error) {
|
||||
throw new Error(`Error deleting on cloudinary: ${error.message}`);
|
||||
if (error instanceof Error) {
|
||||
throw new Error(`Error deleting on cloudinary: ${error.message}`);
|
||||
}
|
||||
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
};
|
||||
@ -0,0 +1,8 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"noEmit": true
|
||||
},
|
||||
"include": ["src"],
|
||||
"exclude": ["node_modules"]
|
||||
}
|
||||
8
packages/providers/upload-cloudinary/tsconfig.json
Normal file
8
packages/providers/upload-cloudinary/tsconfig.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"extends": "tsconfig/base.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "dist"
|
||||
},
|
||||
"include": ["src"],
|
||||
"exclude": ["node_modules", "**/__tests__/**"]
|
||||
}
|
||||
@ -1,2 +1,4 @@
|
||||
node_modules/
|
||||
dist/
|
||||
.eslintrc.js
|
||||
jest.config.js
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
module.exports = {
|
||||
root: true,
|
||||
extends: ['custom/back'],
|
||||
extends: ['custom/typescript'],
|
||||
};
|
||||
|
||||
@ -2,4 +2,7 @@
|
||||
|
||||
module.exports = {
|
||||
preset: '../../../jest-preset.unit.js',
|
||||
transform: {
|
||||
'^.+\\.ts$': ['@swc/jest'],
|
||||
},
|
||||
};
|
||||
|
||||
@ -27,11 +27,17 @@
|
||||
"url": "https://strapi.io"
|
||||
}
|
||||
],
|
||||
"main": "./lib",
|
||||
"directories": {
|
||||
"lib": "./lib"
|
||||
},
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
"files": [
|
||||
"./dist"
|
||||
],
|
||||
"scripts": {
|
||||
"build": "run -T tsc",
|
||||
"build:ts": "run -T tsc",
|
||||
"watch": "run -T tsc -w --preserveWatchOutput",
|
||||
"clean": "run -T rimraf ./dist",
|
||||
"prepublishOnly": "yarn clean && yarn build",
|
||||
"test:unit": "run -T jest",
|
||||
"test:unit:watch": "run -T jest --watch",
|
||||
"lint": "run -T eslint ."
|
||||
@ -40,6 +46,11 @@
|
||||
"@strapi/utils": "4.9.1",
|
||||
"fs-extra": "10.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jest": "29.2.0",
|
||||
"eslint-config-custom": "*",
|
||||
"tsconfig": "*"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.19.1 <=18.x.x",
|
||||
"npm": ">=6.0.0"
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
'use strict';
|
||||
import type { File } from '@strapi/plugin-upload';
|
||||
import localProvider from '../index';
|
||||
|
||||
jest.mock('fs', () => {
|
||||
return {
|
||||
@ -12,11 +13,9 @@ jest.mock('fs-extra', () => {
|
||||
};
|
||||
});
|
||||
|
||||
const localProvider = require('../index');
|
||||
|
||||
describe('Local provider', () => {
|
||||
beforeAll(() => {
|
||||
globalThis.strapi = globalThis.strapi ?? {};
|
||||
globalThis.strapi = {};
|
||||
globalThis.strapi.dirs = { static: { public: '' } };
|
||||
});
|
||||
|
||||
@ -28,12 +27,15 @@ describe('Local provider', () => {
|
||||
test('Should have relative url to file object', async () => {
|
||||
const providerInstance = localProvider.init({});
|
||||
|
||||
const file = {
|
||||
const file: File = {
|
||||
name: 'test',
|
||||
size: 100,
|
||||
url: '/',
|
||||
path: '/tmp/',
|
||||
hash: 'test',
|
||||
ext: '.json',
|
||||
mime: 'application/json',
|
||||
buffer: '',
|
||||
buffer: Buffer.from(''),
|
||||
};
|
||||
|
||||
await providerInstance.upload(file);
|
||||
2
packages/providers/upload-local/src/global.d.ts
vendored
Normal file
2
packages/providers/upload-local/src/global.d.ts
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
declare const strapi: any;
|
||||
@ -1,27 +1,48 @@
|
||||
'use strict';
|
||||
import { pipeline } from 'stream';
|
||||
import fs, { ReadStream } from 'fs';
|
||||
import path from 'path';
|
||||
import fse from 'fs-extra';
|
||||
import utils from '@strapi/utils';
|
||||
|
||||
/**
|
||||
* Module dependencies
|
||||
*/
|
||||
interface File {
|
||||
name: string;
|
||||
alternativeText?: string;
|
||||
caption?: string;
|
||||
width?: number;
|
||||
height?: number;
|
||||
formats?: Record<string, unknown>;
|
||||
hash: string;
|
||||
ext?: string;
|
||||
mime: string;
|
||||
size: number;
|
||||
url: string;
|
||||
previewUrl?: string;
|
||||
path?: string;
|
||||
provider?: string;
|
||||
provider_metadata?: Record<string, unknown>;
|
||||
stream?: ReadStream;
|
||||
buffer?: Buffer;
|
||||
}
|
||||
|
||||
// Public node modules.
|
||||
const { pipeline } = require('stream');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const fse = require('fs-extra');
|
||||
const {
|
||||
errors: { PayloadTooLargeError },
|
||||
file: { kbytesToBytes, bytesToHumanReadable },
|
||||
} = require('@strapi/utils');
|
||||
const { PayloadTooLargeError } = utils.errors;
|
||||
const { kbytesToBytes, bytesToHumanReadable } = utils.file;
|
||||
|
||||
const UPLOADS_FOLDER_NAME = 'uploads';
|
||||
|
||||
module.exports = {
|
||||
init({ sizeLimit: providerOptionsSizeLimit } = {}) {
|
||||
interface InitOptions {
|
||||
sizeLimit?: number;
|
||||
}
|
||||
|
||||
interface CheckFileSizeOptions {
|
||||
sizeLimit?: number;
|
||||
}
|
||||
|
||||
export = {
|
||||
init({ sizeLimit: providerOptionsSizeLimit }: InitOptions = {}) {
|
||||
// TODO V5: remove providerOptions sizeLimit
|
||||
if (providerOptionsSizeLimit) {
|
||||
process.emitWarning(
|
||||
`[deprecated] In future versions, "sizeLimit" argument will be ignored from upload.config.providerOptions. Move it to upload.config`
|
||||
'[deprecated] In future versions, "sizeLimit" argument will be ignored from upload.config.providerOptions. Move it to upload.config'
|
||||
);
|
||||
}
|
||||
|
||||
@ -34,7 +55,9 @@ module.exports = {
|
||||
}
|
||||
|
||||
return {
|
||||
checkFileSize(file, { sizeLimit } = {}) {
|
||||
checkFileSize(file: File, options: CheckFileSizeOptions) {
|
||||
const { sizeLimit } = options ?? {};
|
||||
|
||||
// TODO V5: remove providerOptions sizeLimit
|
||||
if (providerOptionsSizeLimit) {
|
||||
if (kbytesToBytes(file.size) > providerOptionsSizeLimit)
|
||||
@ -50,10 +73,16 @@ module.exports = {
|
||||
);
|
||||
}
|
||||
},
|
||||
uploadStream(file) {
|
||||
uploadStream(file: File): Promise<void> {
|
||||
if (!file.stream) {
|
||||
return Promise.reject(new Error('Missing file stream'));
|
||||
}
|
||||
|
||||
const { stream } = file;
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
pipeline(
|
||||
file.stream,
|
||||
stream,
|
||||
fs.createWriteStream(path.join(uploadPath, `${file.hash}${file.ext}`)),
|
||||
(err) => {
|
||||
if (err) {
|
||||
@ -67,10 +96,16 @@ module.exports = {
|
||||
);
|
||||
});
|
||||
},
|
||||
upload(file) {
|
||||
upload(file: File): Promise<void> {
|
||||
if (!file.buffer) {
|
||||
return Promise.reject(new Error('Missing file buffer'));
|
||||
}
|
||||
|
||||
const { buffer } = file;
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
// write file in public/assets folder
|
||||
fs.writeFile(path.join(uploadPath, `${file.hash}${file.ext}`), file.buffer, (err) => {
|
||||
fs.writeFile(path.join(uploadPath, `${file.hash}${file.ext}`), buffer, (err) => {
|
||||
if (err) {
|
||||
return reject(err);
|
||||
}
|
||||
@ -81,13 +116,13 @@ module.exports = {
|
||||
});
|
||||
});
|
||||
},
|
||||
delete(file) {
|
||||
delete(file: File): Promise<string | void> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const filePath = path.join(uploadPath, `${file.hash}${file.ext}`);
|
||||
|
||||
if (!fs.existsSync(filePath)) {
|
||||
// eslint-disable-next-line no-promise-executor-return
|
||||
return resolve("File doesn't exist");
|
||||
resolve("File doesn't exist");
|
||||
return;
|
||||
}
|
||||
|
||||
// remove file from public/assets folder
|
||||
8
packages/providers/upload-local/tsconfig.eslint.json
Normal file
8
packages/providers/upload-local/tsconfig.eslint.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"noEmit": true
|
||||
},
|
||||
"include": ["src"],
|
||||
"exclude": ["node_modules"]
|
||||
}
|
||||
8
packages/providers/upload-local/tsconfig.json
Normal file
8
packages/providers/upload-local/tsconfig.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"extends": "tsconfig/base.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "dist"
|
||||
},
|
||||
"include": ["src"],
|
||||
"exclude": ["node_modules", "**/__tests__/**"]
|
||||
}
|
||||
@ -1,7 +1,9 @@
|
||||
{
|
||||
"$schema": "http://json.schemastore.org/tsconfig",
|
||||
"extends": "@tsconfig/node16/tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"declaration": true,
|
||||
"sourceMap": true
|
||||
"sourceMap": true,
|
||||
"esModuleInterop": true
|
||||
}
|
||||
}
|
||||
|
||||
144
yarn.lock
144
yarn.lock
@ -7659,6 +7659,11 @@ __metadata:
|
||||
"@strapi/provider-audit-logs-local@4.9.1, @strapi/provider-audit-logs-local@workspace:packages/providers/audit-logs-local":
|
||||
version: 0.0.0-use.local
|
||||
resolution: "@strapi/provider-audit-logs-local@workspace:packages/providers/audit-logs-local"
|
||||
dependencies:
|
||||
eslint-config-custom: "*"
|
||||
tsconfig: "*"
|
||||
peerDependencies:
|
||||
"@strapi/strapi": ^4.9.0
|
||||
languageName: unknown
|
||||
linkType: soft
|
||||
|
||||
@ -7667,7 +7672,9 @@ __metadata:
|
||||
resolution: "@strapi/provider-email-amazon-ses@workspace:packages/providers/email-amazon-ses"
|
||||
dependencies:
|
||||
"@strapi/utils": 4.9.1
|
||||
eslint-config-custom: "*"
|
||||
node-ses: ^3.0.3
|
||||
tsconfig: "*"
|
||||
languageName: unknown
|
||||
linkType: soft
|
||||
|
||||
@ -7676,8 +7683,10 @@ __metadata:
|
||||
resolution: "@strapi/provider-email-mailgun@workspace:packages/providers/email-mailgun"
|
||||
dependencies:
|
||||
"@strapi/utils": 4.9.1
|
||||
eslint-config-custom: "*"
|
||||
form-data: ^4.0.0
|
||||
mailgun.js: 5.2.2
|
||||
mailgun.js: 8.2.1
|
||||
tsconfig: "*"
|
||||
languageName: unknown
|
||||
linkType: soft
|
||||
|
||||
@ -7685,8 +7694,11 @@ __metadata:
|
||||
version: 0.0.0-use.local
|
||||
resolution: "@strapi/provider-email-nodemailer@workspace:packages/providers/email-nodemailer"
|
||||
dependencies:
|
||||
"@types/nodemailer": 6.4.7
|
||||
eslint-config-custom: "*"
|
||||
lodash: 4.17.21
|
||||
nodemailer: 6.9.1
|
||||
tsconfig: "*"
|
||||
languageName: unknown
|
||||
linkType: soft
|
||||
|
||||
@ -7696,6 +7708,8 @@ __metadata:
|
||||
dependencies:
|
||||
"@sendgrid/mail": 7.7.0
|
||||
"@strapi/utils": 4.9.1
|
||||
eslint-config-custom: "*"
|
||||
tsconfig: "*"
|
||||
languageName: unknown
|
||||
linkType: soft
|
||||
|
||||
@ -7704,7 +7718,10 @@ __metadata:
|
||||
resolution: "@strapi/provider-email-sendmail@workspace:packages/providers/email-sendmail"
|
||||
dependencies:
|
||||
"@strapi/utils": 4.9.1
|
||||
"@types/sendmail": 1.4.4
|
||||
eslint-config-custom: "*"
|
||||
sendmail: ^1.6.1
|
||||
tsconfig: "*"
|
||||
languageName: unknown
|
||||
linkType: soft
|
||||
|
||||
@ -7712,8 +7729,11 @@ __metadata:
|
||||
version: 0.0.0-use.local
|
||||
resolution: "@strapi/provider-upload-aws-s3@workspace:packages/providers/upload-aws-s3"
|
||||
dependencies:
|
||||
"@types/jest": 29.2.0
|
||||
aws-sdk: 2.1351.0
|
||||
eslint-config-custom: "*"
|
||||
lodash: 4.17.21
|
||||
tsconfig: "*"
|
||||
languageName: unknown
|
||||
linkType: soft
|
||||
|
||||
@ -7723,7 +7743,9 @@ __metadata:
|
||||
dependencies:
|
||||
"@strapi/utils": 4.9.1
|
||||
cloudinary: ^1.33.0
|
||||
eslint-config-custom: "*"
|
||||
into-stream: ^5.1.0
|
||||
tsconfig: "*"
|
||||
languageName: unknown
|
||||
linkType: soft
|
||||
|
||||
@ -7732,7 +7754,10 @@ __metadata:
|
||||
resolution: "@strapi/provider-upload-local@workspace:packages/providers/upload-local"
|
||||
dependencies:
|
||||
"@strapi/utils": 4.9.1
|
||||
"@types/jest": 29.2.0
|
||||
eslint-config-custom: "*"
|
||||
fs-extra: 10.0.0
|
||||
tsconfig: "*"
|
||||
languageName: unknown
|
||||
linkType: soft
|
||||
|
||||
@ -8743,6 +8768,15 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@types/nodemailer@npm:6.4.7":
|
||||
version: 6.4.7
|
||||
resolution: "@types/nodemailer@npm:6.4.7"
|
||||
dependencies:
|
||||
"@types/node": "*"
|
||||
checksum: dc2a33a89135e04a5bea4921e8645e8453b90e3c3b05f0646f05071c5951ab697ea49ea1e503a690f04cb0a6abfc54967325c5a4036356793cfbb64ba64fb141
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@types/normalize-package-data@npm:^2.4.0":
|
||||
version: 2.4.1
|
||||
resolution: "@types/normalize-package-data@npm:2.4.1"
|
||||
@ -8865,6 +8899,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@types/sendmail@npm:1.4.4":
|
||||
version: 1.4.4
|
||||
resolution: "@types/sendmail@npm:1.4.4"
|
||||
checksum: aa31facf023af0c888e6a64bfaf742d08efdf1fef4c51efd7e0e547f6f3a2d215f02bdea81f35953cefefadf9a6f1fd516bafc06f4beb708b41570e21c415e3e
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@types/serve-index@npm:^1.9.1":
|
||||
version: 1.9.1
|
||||
resolution: "@types/serve-index@npm:1.9.1"
|
||||
@ -9923,15 +9964,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"abort-controller@npm:^3.0.0":
|
||||
version: 3.0.0
|
||||
resolution: "abort-controller@npm:3.0.0"
|
||||
dependencies:
|
||||
event-target-shim: ^5.0.0
|
||||
checksum: 170bdba9b47b7e65906a28c8ce4f38a7a369d78e2271706f020849c1bfe0ee2067d4261df8bbb66eb84f79208fd5b710df759d64191db58cfba7ce8ef9c54b75
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"accepts@npm:^1.3.5, accepts@npm:^1.3.7, accepts@npm:~1.3.4, accepts@npm:~1.3.5, accepts@npm:~1.3.8":
|
||||
version: 1.3.8
|
||||
resolution: "accepts@npm:1.3.8"
|
||||
@ -10998,6 +11030,17 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"axios@npm:^1.3.3":
|
||||
version: 1.3.5
|
||||
resolution: "axios@npm:1.3.5"
|
||||
dependencies:
|
||||
follow-redirects: ^1.15.0
|
||||
form-data: ^4.0.0
|
||||
proxy-from-env: ^1.1.0
|
||||
checksum: 4d6bcf933b1cdff86d4993752aaeeeedc4a7f7a4b1c942847f6884bb13fc6106610ff826b076acf0b08d8ced55dee9344bb9a11f3624c3e70ab1da1a40bb5506
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"axobject-query@npm:^2.2.0":
|
||||
version: 2.2.0
|
||||
resolution: "axobject-query@npm:2.2.0"
|
||||
@ -11527,7 +11570,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"bluebird@npm:^3.5.5, bluebird@npm:^3.7.2":
|
||||
"bluebird@npm:^3.5.5":
|
||||
version: 3.7.2
|
||||
resolution: "bluebird@npm:3.7.2"
|
||||
checksum: 869417503c722e7dc54ca46715f70e15f4d9c602a423a02c825570862d12935be59ed9c7ba34a9b31f186c017c23cac6b54e35446f8353059c101da73eac22ef
|
||||
@ -13885,7 +13928,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"data-uri-to-buffer@npm:3, data-uri-to-buffer@npm:^3.0.1":
|
||||
"data-uri-to-buffer@npm:3":
|
||||
version: 3.0.1
|
||||
resolution: "data-uri-to-buffer@npm:3.0.1"
|
||||
checksum: c59c3009686a78c071806b72f4810856ec28222f0f4e252aa495ec027ed9732298ceea99c50328cf59b151dd34cbc3ad6150bbb43e41fc56fa19f48c99e9fc30
|
||||
@ -15354,7 +15397,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"eslint-config-custom@4.9.1, eslint-config-custom@workspace:packages/utils/eslint-config-custom":
|
||||
"eslint-config-custom@*, eslint-config-custom@4.9.1, eslint-config-custom@workspace:packages/utils/eslint-config-custom":
|
||||
version: 0.0.0-use.local
|
||||
resolution: "eslint-config-custom@workspace:packages/utils/eslint-config-custom"
|
||||
languageName: unknown
|
||||
@ -15837,13 +15880,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"event-target-shim@npm:^5.0.0":
|
||||
version: 5.0.1
|
||||
resolution: "event-target-shim@npm:5.0.1"
|
||||
checksum: 1ffe3bb22a6d51bdeb6bf6f7cf97d2ff4a74b017ad12284cc9e6a279e727dc30a5de6bb613e5596ff4dc3e517841339ad09a7eec44266eccb1aa201a30448166
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"eventemitter3@npm:^4.0.0, eventemitter3@npm:^4.0.4":
|
||||
version: 4.0.7
|
||||
resolution: "eventemitter3@npm:4.0.7"
|
||||
@ -16294,16 +16330,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"fetch-blob@npm:^2.1.1":
|
||||
version: 2.1.2
|
||||
resolution: "fetch-blob@npm:2.1.2"
|
||||
peerDependenciesMeta:
|
||||
domexception:
|
||||
optional: true
|
||||
checksum: 22d4487ce78ea4e52b432b0057d8d42922d5d93c0374b0bc2692cebdcb11bf8fac4f6d141b31f1633db1e9212effd38385adbd765a2c7412a621307058499214
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"fetch-retry@npm:^5.0.2":
|
||||
version: 5.0.3
|
||||
resolution: "fetch-retry@npm:5.0.3"
|
||||
@ -21264,29 +21290,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"ky-universal@npm:^0.8.2":
|
||||
version: 0.8.2
|
||||
resolution: "ky-universal@npm:0.8.2"
|
||||
dependencies:
|
||||
abort-controller: ^3.0.0
|
||||
node-fetch: 3.0.0-beta.9
|
||||
peerDependencies:
|
||||
ky: ">=0.17.0"
|
||||
web-streams-polyfill: ">=2.0.0"
|
||||
peerDependenciesMeta:
|
||||
web-streams-polyfill:
|
||||
optional: true
|
||||
checksum: 87ed38c5c5a5b4448502fd5a64b68f30db69d366e148e5321cd9c0cb57d616519578ff0ae50146ff92ad037ef5cd77fbc40d893675459eead0d3f13101374570
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"ky@npm:^0.25.1":
|
||||
version: 0.25.1
|
||||
resolution: "ky@npm:0.25.1"
|
||||
checksum: ae1b7bebb48001d00d53e386e077939eeef7398a36b4fb45660f988ddb17d583d077290f2adb9706b4761f9d3b74918eb8d9f45ce799760143e104e1053b33ef
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"language-subtag-registry@npm:~0.3.2":
|
||||
version: 0.3.22
|
||||
resolution: "language-subtag-registry@npm:0.3.22"
|
||||
@ -21999,18 +22002,14 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"mailgun.js@npm:5.2.2":
|
||||
version: 5.2.2
|
||||
resolution: "mailgun.js@npm:5.2.2"
|
||||
"mailgun.js@npm:8.2.1":
|
||||
version: 8.2.1
|
||||
resolution: "mailgun.js@npm:8.2.1"
|
||||
dependencies:
|
||||
axios: ^1.3.3
|
||||
base-64: ^1.0.0
|
||||
bluebird: ^3.7.2
|
||||
ky: ^0.25.1
|
||||
ky-universal: ^0.8.2
|
||||
url-join: ^4.0.1
|
||||
web-streams-polyfill: ^3.0.1
|
||||
webpack-merge: ^5.4.0
|
||||
checksum: 5fa48c4c29ef64d453225c3511a72546e028a40348b71af6a29213997791aa6ab782bddb12690c6488f83112f08df3a44b0d181ef44ef31ecb56f0dc6fa1b6a7
|
||||
checksum: 512b76a8b688cc2b88c14472a2c7c9715dd927c5bb588a6197c2eed8b9effc8edddb3a7c99a1f2993c5f205154b24585db5fa573c15701401759b8702258b944
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@ -23360,16 +23359,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"node-fetch@npm:3.0.0-beta.9":
|
||||
version: 3.0.0-beta.9
|
||||
resolution: "node-fetch@npm:3.0.0-beta.9"
|
||||
dependencies:
|
||||
data-uri-to-buffer: ^3.0.1
|
||||
fetch-blob: ^2.1.1
|
||||
checksum: 586af0910649cb62f1c044ddac41e71c0b0f48133fba406ad5e0fab51baff18f22cd187ea65ef690ceed7386a71910e904348105dc8eae55f907fa94df7e76ca
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"node-forge@npm:^1":
|
||||
version: 1.3.1
|
||||
resolution: "node-forge@npm:1.3.1"
|
||||
@ -30191,7 +30180,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"tsconfig@4.9.1, tsconfig@workspace:packages/utils/tsconfig":
|
||||
"tsconfig@*, tsconfig@4.9.1, tsconfig@workspace:packages/utils/tsconfig":
|
||||
version: 0.0.0-use.local
|
||||
resolution: "tsconfig@workspace:packages/utils/tsconfig"
|
||||
languageName: unknown
|
||||
@ -31283,13 +31272,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"web-streams-polyfill@npm:^3.0.1":
|
||||
version: 3.2.1
|
||||
resolution: "web-streams-polyfill@npm:3.2.1"
|
||||
checksum: b119c78574b6d65935e35098c2afdcd752b84268e18746606af149e3c424e15621b6f1ff0b42b2676dc012fc4f0d313f964b41a4b5031e525faa03997457da02
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"webidl-conversions@npm:^3.0.0":
|
||||
version: 3.0.1
|
||||
resolution: "webidl-conversions@npm:3.0.1"
|
||||
@ -31479,7 +31461,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"webpack-merge@npm:^5.4.0, webpack-merge@npm:^5.7.3":
|
||||
"webpack-merge@npm:^5.7.3":
|
||||
version: 5.8.0
|
||||
resolution: "webpack-merge@npm:5.8.0"
|
||||
dependencies:
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user