Assorted cleanup, minor bug fixes, styling fixes, eslint rules (#5165
* fix: Logic error in toast fix: Remove useless component * fix: Logout not clearing all stores * Add icons to notification settings * Add eslint rule to enforce spaced comment * Add eslint rule for arrow-body-style * Add eslint rule to enforce self-closing components * Add menu to api key settings Fix: Deleting webhook subscription does not remove from UI Split webhook subscriptions into active and inactive Styling updates
This commit is contained in:
@@ -106,8 +106,8 @@ async function teamProvisioner({
|
||||
}
|
||||
|
||||
// We cannot find an existing team, so we create a new one
|
||||
const team = await sequelize.transaction((transaction) => {
|
||||
return teamCreator({
|
||||
const team = await sequelize.transaction((transaction) =>
|
||||
teamCreator({
|
||||
name,
|
||||
domain,
|
||||
subdomain,
|
||||
@@ -115,8 +115,8 @@ async function teamProvisioner({
|
||||
authenticationProviders: [authenticationProvider],
|
||||
ip,
|
||||
transaction,
|
||||
});
|
||||
});
|
||||
})
|
||||
);
|
||||
|
||||
return {
|
||||
team,
|
||||
|
||||
@@ -115,9 +115,10 @@ const teamUpdater = async ({ params, user, team, ip }: TeamUpdaterProps) => {
|
||||
transaction,
|
||||
});
|
||||
if (changes) {
|
||||
const data = changes.reduce((acc, curr) => {
|
||||
return { ...acc, [curr]: team[curr] };
|
||||
}, {});
|
||||
const data = changes.reduce(
|
||||
(acc, curr) => ({ ...acc, [curr]: team[curr] }),
|
||||
{}
|
||||
);
|
||||
|
||||
await Event.create(
|
||||
{
|
||||
|
||||
@@ -5,26 +5,24 @@ import EmptySpace from "./EmptySpace";
|
||||
|
||||
const url = env.CDN_URL ?? env.URL;
|
||||
|
||||
export default () => {
|
||||
return (
|
||||
<Table width="100%">
|
||||
<TBody>
|
||||
<TR>
|
||||
<TD>
|
||||
<EmptySpace height={40} />
|
||||
<img
|
||||
alt={env.APP_NAME}
|
||||
src={
|
||||
env.isCloudHosted()
|
||||
? `${url}/email/header-logo.png`
|
||||
: "cid:header-image"
|
||||
}
|
||||
height="48"
|
||||
width="48"
|
||||
/>
|
||||
</TD>
|
||||
</TR>
|
||||
</TBody>
|
||||
</Table>
|
||||
);
|
||||
};
|
||||
export default () => (
|
||||
<Table width="100%">
|
||||
<TBody>
|
||||
<TR>
|
||||
<TD>
|
||||
<EmptySpace height={40} />
|
||||
<img
|
||||
alt={env.APP_NAME}
|
||||
src={
|
||||
env.isCloudHosted()
|
||||
? `${url}/email/header-logo.png`
|
||||
: "cid:header-image"
|
||||
}
|
||||
height="48"
|
||||
width="48"
|
||||
/>
|
||||
</TD>
|
||||
</TR>
|
||||
</TBody>
|
||||
</Table>
|
||||
);
|
||||
|
||||
@@ -139,22 +139,25 @@ async function start(id: number, disconnect: () => void) {
|
||||
server.listen(normalizedPortFlag || env.PORT || "3000");
|
||||
server.setTimeout(env.REQUEST_TIMEOUT);
|
||||
|
||||
ShutdownHelper.add("server", ShutdownOrder.last, () => {
|
||||
return new Promise((resolve, reject) => {
|
||||
// Calling stop prevents new connections from being accepted and waits for
|
||||
// existing connections to close for the grace period before forcefully
|
||||
// closing them.
|
||||
server.stop((err, gracefully) => {
|
||||
disconnect();
|
||||
ShutdownHelper.add(
|
||||
"server",
|
||||
ShutdownOrder.last,
|
||||
() =>
|
||||
new Promise((resolve, reject) => {
|
||||
// Calling stop prevents new connections from being accepted and waits for
|
||||
// existing connections to close for the grace period before forcefully
|
||||
// closing them.
|
||||
server.stop((err, gracefully) => {
|
||||
disconnect();
|
||||
|
||||
if (err) {
|
||||
reject(err);
|
||||
} else {
|
||||
resolve(gracefully);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
if (err) {
|
||||
reject(err);
|
||||
} else {
|
||||
resolve(gracefully);
|
||||
}
|
||||
});
|
||||
})
|
||||
);
|
||||
|
||||
// Handle shutdown signals
|
||||
process.once("SIGTERM", () => ShutdownHelper.execute());
|
||||
|
||||
@@ -126,9 +126,9 @@ class Logger {
|
||||
}
|
||||
|
||||
if (request) {
|
||||
scope.addEventProcessor((event) => {
|
||||
return Sentry.Handlers.parseRequest(event, request);
|
||||
});
|
||||
scope.addEventProcessor((event) =>
|
||||
Sentry.Handlers.parseRequest(event, request)
|
||||
);
|
||||
}
|
||||
|
||||
Sentry.captureException(error);
|
||||
|
||||
@@ -123,14 +123,13 @@ class AuthenticationProvider extends Model {
|
||||
}
|
||||
};
|
||||
|
||||
enable = (options?: SaveOptions<AuthenticationProvider>) => {
|
||||
return this.update(
|
||||
enable = (options?: SaveOptions<AuthenticationProvider>) =>
|
||||
this.update(
|
||||
{
|
||||
enabled: true,
|
||||
},
|
||||
options
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
export default AuthenticationProvider;
|
||||
|
||||
@@ -477,12 +477,10 @@ class Collection extends ParanoidModel {
|
||||
id: string
|
||||
) => {
|
||||
children = await Promise.all(
|
||||
children.map(async (childDocument) => {
|
||||
return {
|
||||
...childDocument,
|
||||
children: await removeFromChildren(childDocument.children, id),
|
||||
};
|
||||
})
|
||||
children.map(async (childDocument) => ({
|
||||
...childDocument,
|
||||
children: await removeFromChildren(childDocument.children, id),
|
||||
}))
|
||||
);
|
||||
const match = find(children, {
|
||||
id,
|
||||
@@ -562,8 +560,8 @@ class Collection extends ParanoidModel {
|
||||
|
||||
const { id } = updatedDocument;
|
||||
|
||||
const updateChildren = (documents: NavigationNode[]) => {
|
||||
return Promise.all(
|
||||
const updateChildren = (documents: NavigationNode[]) =>
|
||||
Promise.all(
|
||||
documents.map(async (document) => {
|
||||
if (document.id === id) {
|
||||
document = {
|
||||
@@ -577,7 +575,6 @@ class Collection extends ParanoidModel {
|
||||
return document;
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
this.documentStructure = await updateChildren(this.documentStructure);
|
||||
// Sequelize doesn't seem to set the value with splice on JSONB field
|
||||
@@ -619,8 +616,8 @@ class Collection extends ParanoidModel {
|
||||
);
|
||||
} else {
|
||||
// Recursively place document
|
||||
const placeDocument = (documentList: NavigationNode[]) => {
|
||||
return documentList.map((childDocument) => {
|
||||
const placeDocument = (documentList: NavigationNode[]) =>
|
||||
documentList.map((childDocument) => {
|
||||
if (document.parentDocumentId === childDocument.id) {
|
||||
childDocument.children.splice(
|
||||
index !== undefined ? index : childDocument.children.length,
|
||||
@@ -633,7 +630,6 @@ class Collection extends ParanoidModel {
|
||||
|
||||
return childDocument;
|
||||
});
|
||||
};
|
||||
|
||||
this.documentStructure = placeDocument(this.documentStructure);
|
||||
}
|
||||
|
||||
@@ -668,8 +668,8 @@ class Document extends ParanoidModel {
|
||||
};
|
||||
|
||||
// Delete a document, archived or otherwise.
|
||||
delete = (userId: string) => {
|
||||
return this.sequelize.transaction(async (transaction: Transaction) => {
|
||||
delete = (userId: string) =>
|
||||
this.sequelize.transaction(async (transaction: Transaction) => {
|
||||
if (!this.archivedAt && !this.template && this.collectionId) {
|
||||
// delete any children and remove from the document structure
|
||||
const collection = await Collection.findByPk(this.collectionId, {
|
||||
@@ -699,11 +699,8 @@ class Document extends ParanoidModel {
|
||||
);
|
||||
return this;
|
||||
});
|
||||
};
|
||||
|
||||
getTimestamp = () => {
|
||||
return Math.round(new Date(this.updatedAt).getTime() / 1000);
|
||||
};
|
||||
getTimestamp = () => Math.round(new Date(this.updatedAt).getTime() / 1000);
|
||||
|
||||
getSummary = () => {
|
||||
const plainText = DocumentHelper.toPlainText(this);
|
||||
|
||||
@@ -34,39 +34,31 @@ import Fix from "./decorators/Fix";
|
||||
],
|
||||
}))
|
||||
@Scopes(() => ({
|
||||
withCollectionPermissions: (userId: string) => {
|
||||
return {
|
||||
include: [
|
||||
{
|
||||
model: Document.scope("withDrafts"),
|
||||
paranoid: true,
|
||||
as: "document",
|
||||
include: [
|
||||
{
|
||||
attributes: [
|
||||
"id",
|
||||
"permission",
|
||||
"sharing",
|
||||
"teamId",
|
||||
"deletedAt",
|
||||
],
|
||||
model: Collection.scope({
|
||||
method: ["withMembership", userId],
|
||||
}),
|
||||
as: "collection",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
association: "user",
|
||||
paranoid: false,
|
||||
},
|
||||
{
|
||||
association: "team",
|
||||
},
|
||||
],
|
||||
};
|
||||
},
|
||||
withCollectionPermissions: (userId: string) => ({
|
||||
include: [
|
||||
{
|
||||
model: Document.scope("withDrafts"),
|
||||
paranoid: true,
|
||||
as: "document",
|
||||
include: [
|
||||
{
|
||||
attributes: ["id", "permission", "sharing", "teamId", "deletedAt"],
|
||||
model: Collection.scope({
|
||||
method: ["withMembership", userId],
|
||||
}),
|
||||
as: "collection",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
association: "user",
|
||||
paranoid: false,
|
||||
},
|
||||
{
|
||||
association: "team",
|
||||
},
|
||||
],
|
||||
}),
|
||||
}))
|
||||
@Table({ tableName: "shares", modelName: "share" })
|
||||
@Fix
|
||||
|
||||
@@ -202,9 +202,8 @@ class Team extends ParanoidModel {
|
||||
* @param fallback An optional fallback value, defaults to false.
|
||||
* @returns The preference value if set, else undefined
|
||||
*/
|
||||
public getPreference = (preference: TeamPreference, fallback = false) => {
|
||||
return this.preferences?.[preference] ?? fallback;
|
||||
};
|
||||
public getPreference = (preference: TeamPreference, fallback = false) =>
|
||||
this.preferences?.[preference] ?? fallback;
|
||||
|
||||
provisionFirstCollection = async (userId: string) => {
|
||||
await this.sequelize!.transaction(async (transaction) => {
|
||||
|
||||
@@ -286,13 +286,8 @@ class User extends ParanoidModel {
|
||||
* @param type The type of notification event
|
||||
* @returns The current preference
|
||||
*/
|
||||
public subscribedToEventType = (type: NotificationEventType) => {
|
||||
return (
|
||||
this.notificationSettings[type] ??
|
||||
NotificationEventDefaults[type] ??
|
||||
false
|
||||
);
|
||||
};
|
||||
public subscribedToEventType = (type: NotificationEventType) =>
|
||||
this.notificationSettings[type] ?? NotificationEventDefaults[type] ?? false;
|
||||
|
||||
/**
|
||||
* User flags are for storing information on a user record that is not visible
|
||||
@@ -321,9 +316,7 @@ class User extends ParanoidModel {
|
||||
* @param flag The flag to retrieve
|
||||
* @returns The flag value
|
||||
*/
|
||||
public getFlag = (flag: UserFlag) => {
|
||||
return this.flags?.[flag] ?? 0;
|
||||
};
|
||||
public getFlag = (flag: UserFlag) => this.flags?.[flag] ?? 0;
|
||||
|
||||
/**
|
||||
* User flags are for storing information on a user record that is not visible
|
||||
@@ -367,9 +360,8 @@ class User extends ParanoidModel {
|
||||
* @param fallback An optional fallback value, defaults to false.
|
||||
* @returns The preference value if set, else undefined
|
||||
*/
|
||||
public getPreference = (preference: UserPreference, fallback = false) => {
|
||||
return this.preferences?.[preference] ?? fallback;
|
||||
};
|
||||
public getPreference = (preference: UserPreference, fallback = false) =>
|
||||
this.preferences?.[preference] ?? fallback;
|
||||
|
||||
collectionIds = async (options = {}) => {
|
||||
const collectionStubs = await Collection.scope({
|
||||
@@ -448,8 +440,8 @@ class User extends ParanoidModel {
|
||||
* @param expiresAt The time the token will expire at
|
||||
* @returns The session token
|
||||
*/
|
||||
getJwtToken = (expiresAt?: Date) => {
|
||||
return JWT.sign(
|
||||
getJwtToken = (expiresAt?: Date) =>
|
||||
JWT.sign(
|
||||
{
|
||||
id: this.id,
|
||||
expiresAt: expiresAt ? expiresAt.toISOString() : undefined,
|
||||
@@ -457,7 +449,6 @@ class User extends ParanoidModel {
|
||||
},
|
||||
this.jwtSecret
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns a temporary token that is only used for transferring a session
|
||||
@@ -466,8 +457,8 @@ class User extends ParanoidModel {
|
||||
*
|
||||
* @returns The transfer token
|
||||
*/
|
||||
getTransferToken = () => {
|
||||
return JWT.sign(
|
||||
getTransferToken = () =>
|
||||
JWT.sign(
|
||||
{
|
||||
id: this.id,
|
||||
createdAt: new Date().toISOString(),
|
||||
@@ -476,7 +467,6 @@ class User extends ParanoidModel {
|
||||
},
|
||||
this.jwtSecret
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns a temporary token that is only used for logging in from an email
|
||||
@@ -484,8 +474,8 @@ class User extends ParanoidModel {
|
||||
*
|
||||
* @returns The email signin token
|
||||
*/
|
||||
getEmailSigninToken = () => {
|
||||
return JWT.sign(
|
||||
getEmailSigninToken = () =>
|
||||
JWT.sign(
|
||||
{
|
||||
id: this.id,
|
||||
createdAt: new Date().toISOString(),
|
||||
@@ -493,15 +483,14 @@ class User extends ParanoidModel {
|
||||
},
|
||||
this.jwtSecret
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns a list of teams that have a user matching this user's email.
|
||||
*
|
||||
* @returns A promise resolving to a list of teams
|
||||
*/
|
||||
availableTeams = async () => {
|
||||
return Team.findAll({
|
||||
availableTeams = async () =>
|
||||
Team.findAll({
|
||||
include: [
|
||||
{
|
||||
model: this.constructor as typeof User,
|
||||
@@ -510,7 +499,6 @@ class User extends ParanoidModel {
|
||||
},
|
||||
],
|
||||
});
|
||||
};
|
||||
|
||||
demote = async (to: UserRole, options?: SaveOptions<User>) => {
|
||||
const res = await (this.constructor as typeof User).findAndCountAll({
|
||||
@@ -560,12 +548,11 @@ class User extends ParanoidModel {
|
||||
}
|
||||
};
|
||||
|
||||
promote = () => {
|
||||
return this.update({
|
||||
promote = () =>
|
||||
this.update({
|
||||
isAdmin: true,
|
||||
isViewer: false,
|
||||
});
|
||||
};
|
||||
|
||||
// hooks
|
||||
|
||||
|
||||
@@ -192,9 +192,8 @@ export default class DocumentHelper {
|
||||
const dom = new JSDOM(html);
|
||||
const doc = dom.window.document;
|
||||
|
||||
const containsDiffElement = (node: Element | null) => {
|
||||
return node && node.innerHTML.includes("data-operation-index");
|
||||
};
|
||||
const containsDiffElement = (node: Element | null) =>
|
||||
node && node.innerHTML.includes("data-operation-index");
|
||||
|
||||
// We use querySelectorAll to get a static NodeList as we'll be modifying
|
||||
// it as we iterate, rather than getting content.childNodes.
|
||||
|
||||
@@ -90,7 +90,7 @@ export default class ProsemirrorHelper {
|
||||
: "article";
|
||||
|
||||
const rtl = isRTL(node.textContent);
|
||||
const content = <div id="content" className="ProseMirror"></div>;
|
||||
const content = <div id="content" className="ProseMirror" />;
|
||||
const children = (
|
||||
<>
|
||||
{options?.title && <h1 dir={rtl ? "rtl" : "ltr"}>{options.title}</h1>}
|
||||
|
||||
@@ -8,7 +8,6 @@ export default class BacklinksProcessor extends BaseProcessor {
|
||||
static applicableEvents: Event["name"][] = [
|
||||
"documents.publish",
|
||||
"documents.update",
|
||||
//"documents.title_change",
|
||||
"documents.delete",
|
||||
];
|
||||
|
||||
@@ -90,17 +89,6 @@ export default class BacklinksProcessor extends BaseProcessor {
|
||||
break;
|
||||
}
|
||||
|
||||
case "documents.title_change": {
|
||||
// might as well check
|
||||
const { title, previousTitle } = event.data;
|
||||
if (!previousTitle || title === previousTitle) {
|
||||
break;
|
||||
}
|
||||
|
||||
// TODO: Handle re-writing of titles into CRDT
|
||||
break;
|
||||
}
|
||||
|
||||
case "documents.delete": {
|
||||
await Backlink.destroy({
|
||||
where: {
|
||||
|
||||
@@ -5,13 +5,11 @@ import { getTestServer } from "@server/test/support";
|
||||
|
||||
const mockTeamInSessionId = "1e023d05-951c-41c6-9012-c9fa0402e1c3";
|
||||
|
||||
jest.mock("@server/utils/authentication", () => {
|
||||
return {
|
||||
getSessionsInCookie() {
|
||||
return { [mockTeamInSessionId]: {} };
|
||||
},
|
||||
};
|
||||
});
|
||||
jest.mock("@server/utils/authentication", () => ({
|
||||
getSessionsInCookie() {
|
||||
return { [mockTeamInSessionId]: {} };
|
||||
},
|
||||
}));
|
||||
|
||||
const server = getTestServer();
|
||||
|
||||
|
||||
@@ -567,16 +567,16 @@ router.post(
|
||||
}).findByPk(id);
|
||||
authorize(user, "read", collection);
|
||||
|
||||
const fileOperation = await sequelize.transaction(async (transaction) => {
|
||||
return collectionExporter({
|
||||
const fileOperation = await sequelize.transaction(async (transaction) =>
|
||||
collectionExporter({
|
||||
collection,
|
||||
user,
|
||||
team,
|
||||
format,
|
||||
ip: ctx.request.ip,
|
||||
transaction,
|
||||
});
|
||||
});
|
||||
})
|
||||
);
|
||||
|
||||
ctx.body = {
|
||||
success: true,
|
||||
@@ -599,15 +599,15 @@ router.post(
|
||||
|
||||
assertIn(format, Object.values(FileOperationFormat), "Invalid format");
|
||||
|
||||
const fileOperation = await sequelize.transaction(async (transaction) => {
|
||||
return collectionExporter({
|
||||
const fileOperation = await sequelize.transaction(async (transaction) =>
|
||||
collectionExporter({
|
||||
user,
|
||||
team,
|
||||
format,
|
||||
ip: ctx.request.ip,
|
||||
transaction,
|
||||
});
|
||||
});
|
||||
})
|
||||
);
|
||||
|
||||
ctx.body = {
|
||||
success: true,
|
||||
|
||||
@@ -1300,8 +1300,8 @@ router.post(
|
||||
authorize(user, "read", templateDocument);
|
||||
}
|
||||
|
||||
const document = await sequelize.transaction(async (transaction) => {
|
||||
return documentCreator({
|
||||
const document = await sequelize.transaction(async (transaction) =>
|
||||
documentCreator({
|
||||
title,
|
||||
text,
|
||||
publish,
|
||||
@@ -1313,8 +1313,8 @@ router.post(
|
||||
editorVersion,
|
||||
ip: ctx.request.ip,
|
||||
transaction,
|
||||
});
|
||||
});
|
||||
})
|
||||
);
|
||||
|
||||
document.collection = collection;
|
||||
|
||||
|
||||
@@ -58,12 +58,10 @@ router.post(
|
||||
authorize(user, "createTeam", existingTeam);
|
||||
|
||||
const authenticationProviders = existingTeam.authenticationProviders.map(
|
||||
(provider) => {
|
||||
return {
|
||||
name: provider.name,
|
||||
providerId: provider.providerId,
|
||||
};
|
||||
}
|
||||
(provider) => ({
|
||||
name: provider.name,
|
||||
providerId: provider.providerId,
|
||||
})
|
||||
);
|
||||
|
||||
invariant(
|
||||
|
||||
@@ -6,8 +6,8 @@ import { User, Document, Collection, Team } from "@server/models";
|
||||
import onerror from "@server/onerror";
|
||||
import webService from "@server/services/web";
|
||||
|
||||
export const seed = async () => {
|
||||
return sequelize.transaction(async (transaction) => {
|
||||
export const seed = async () =>
|
||||
sequelize.transaction(async (transaction) => {
|
||||
const team = await Team.create(
|
||||
{
|
||||
name: "Team",
|
||||
@@ -97,7 +97,6 @@ export const seed = async () => {
|
||||
team,
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
export function getTestServer() {
|
||||
const app = webService();
|
||||
|
||||
@@ -30,8 +30,8 @@ export function initI18n() {
|
||||
i18n.use(backend).init({
|
||||
compatibilityJSON: "v3",
|
||||
backend: {
|
||||
loadPath: (language: string) => {
|
||||
return path.resolve(
|
||||
loadPath: (language: string) =>
|
||||
path.resolve(
|
||||
path.join(
|
||||
__dirname,
|
||||
"..",
|
||||
@@ -42,8 +42,7 @@ export function initI18n() {
|
||||
unicodeBCP47toCLDR(language),
|
||||
"translation.json"
|
||||
)
|
||||
);
|
||||
},
|
||||
),
|
||||
},
|
||||
preload: languages.map(unicodeCLDRtoBCP47),
|
||||
interpolation: {
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
export const opensearchResponse = (baseUrl: string): string => {
|
||||
return `
|
||||
export const opensearchResponse = (baseUrl: string): string => `
|
||||
<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/" xmlns:moz="http://www.mozilla.org/2006/browser/search/">
|
||||
<ShortName>Outline</ShortName>
|
||||
<Description>Search Outline</Description>
|
||||
@@ -9,4 +8,3 @@ export const opensearchResponse = (baseUrl: string): string => {
|
||||
<moz:SearchForm>${baseUrl}/search</moz:SearchForm>
|
||||
</OpenSearchDescription>
|
||||
`;
|
||||
};
|
||||
|
||||
@@ -23,14 +23,12 @@ if (isProduction) {
|
||||
const returnFileAndImportsFromManifest = (
|
||||
manifest: ManifestStructure,
|
||||
file: string
|
||||
): string[] => {
|
||||
return [
|
||||
manifest[file]["file"],
|
||||
...manifest[file]["imports"].map((entry: string) => {
|
||||
return manifest[entry]["file"];
|
||||
}),
|
||||
];
|
||||
};
|
||||
): string[] => [
|
||||
manifest[file]["file"],
|
||||
...manifest[file]["imports"].map(
|
||||
(entry: string) => manifest[entry]["file"]
|
||||
),
|
||||
];
|
||||
|
||||
Array.from([
|
||||
...returnFileAndImportsFromManifest(manifest, "app/index.tsx"),
|
||||
|
||||
@@ -150,14 +150,13 @@ export const uploadToS3FromUrl = async (
|
||||
}
|
||||
};
|
||||
|
||||
export const deleteFromS3 = (key: string) => {
|
||||
return s3
|
||||
export const deleteFromS3 = (key: string) =>
|
||||
s3
|
||||
.deleteObject({
|
||||
Bucket: AWS_S3_UPLOAD_BUCKET_NAME,
|
||||
Key: key,
|
||||
})
|
||||
.promise();
|
||||
};
|
||||
|
||||
export const getSignedUrl = async (key: string, expiresInMs = 60) => {
|
||||
const isDocker = AWS_S3_UPLOAD_BUCKET_URL.match(/http:\/\/s3:/);
|
||||
|
||||
Reference in New Issue
Block a user