mirror of
https://github.com/outline/outline.git
synced 2026-08-03 13:27:25 +03:00
chore: babel -> swc (#12821)
* chore: babel -> swc * Add ls guard * PR feedback
This commit is contained in:
@@ -1,70 +0,0 @@
|
||||
{
|
||||
"presets": [
|
||||
[
|
||||
"@babel/preset-react",
|
||||
{
|
||||
"runtime": "automatic"
|
||||
}
|
||||
],
|
||||
"@babel/preset-env",
|
||||
"@babel/preset-typescript"
|
||||
],
|
||||
"plugins": [
|
||||
"babel-plugin-transform-typescript-metadata",
|
||||
[
|
||||
"@babel/plugin-proposal-decorators",
|
||||
{
|
||||
"legacy": true
|
||||
}
|
||||
],
|
||||
"@babel/plugin-transform-class-properties",
|
||||
[
|
||||
"transform-inline-environment-variables",
|
||||
{
|
||||
"include": ["SOURCE_COMMIT", "SOURCE_VERSION"]
|
||||
}
|
||||
],
|
||||
[
|
||||
"module-resolver",
|
||||
{
|
||||
"root": ["./"],
|
||||
"alias": {
|
||||
"@server": "./server",
|
||||
"@shared": "./shared",
|
||||
"~": "./app",
|
||||
"plugins": "./plugins"
|
||||
}
|
||||
}
|
||||
]
|
||||
],
|
||||
"env": {
|
||||
"production": {
|
||||
"plugins": [
|
||||
[
|
||||
"styled-components",
|
||||
{
|
||||
"displayName": false
|
||||
}
|
||||
]
|
||||
],
|
||||
"ignore": ["**/__mocks__", "**/*.test.ts"]
|
||||
},
|
||||
"development": {
|
||||
"ignore": ["**/__mocks__", "**/*.test.ts"]
|
||||
},
|
||||
"test": {
|
||||
"presets": [
|
||||
[
|
||||
"@babel/preset-env",
|
||||
{
|
||||
"corejs": {
|
||||
"version": "3",
|
||||
"proposals": true
|
||||
},
|
||||
"useBuiltIns": "usage"
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"$schema": "https://swc.rs/schema.json",
|
||||
"jsc": {
|
||||
"parser": {
|
||||
"syntax": "typescript",
|
||||
"tsx": true,
|
||||
"decorators": true
|
||||
},
|
||||
"transform": {
|
||||
"legacyDecorator": true,
|
||||
"useDefineForClassFields": false,
|
||||
"react": {
|
||||
"runtime": "automatic"
|
||||
},
|
||||
"optimizer": {
|
||||
"globals": {
|
||||
"envs": ["SOURCE_COMMIT", "SOURCE_VERSION"]
|
||||
}
|
||||
}
|
||||
},
|
||||
"target": "es2020",
|
||||
"keepClassNames": true,
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"@server/*": ["server/*"],
|
||||
"@shared/*": ["shared/*"],
|
||||
"~/*": ["app/*"],
|
||||
"plugins/*": ["plugins/*"]
|
||||
}
|
||||
},
|
||||
"module": {
|
||||
"type": "commonjs"
|
||||
},
|
||||
"sourceMaps": false
|
||||
}
|
||||
@@ -447,7 +447,7 @@ function Lightbox({ images, activeImage, onUpdate, onClose, readOnly }: Props) {
|
||||
`;
|
||||
};
|
||||
animation.current = {
|
||||
...(animation.current ?? {}),
|
||||
...animation.current,
|
||||
zoomOut: undefined,
|
||||
zoomIn: { apply: zoomIn, duration: ANIMATION_DURATION },
|
||||
};
|
||||
@@ -460,7 +460,7 @@ function Lightbox({ images, activeImage, onUpdate, onClose, readOnly }: Props) {
|
||||
to { opacity: 1; }
|
||||
`;
|
||||
animation.current = {
|
||||
...(animation.current ?? {}),
|
||||
...animation.current,
|
||||
fadeIn: { apply: fadeIn, duration: ANIMATION_DURATION },
|
||||
fadeOut: undefined,
|
||||
};
|
||||
@@ -472,7 +472,7 @@ function Lightbox({ images, activeImage, onUpdate, onClose, readOnly }: Props) {
|
||||
to { opacity: 0; }
|
||||
`;
|
||||
animation.current = {
|
||||
...(animation.current ?? {}),
|
||||
...animation.current,
|
||||
fadeIn: undefined,
|
||||
fadeOut: {
|
||||
apply: fadeOut,
|
||||
@@ -574,7 +574,7 @@ function Lightbox({ images, activeImage, onUpdate, onClose, readOnly }: Props) {
|
||||
`;
|
||||
};
|
||||
animation.current = {
|
||||
...(animation.current ?? {}),
|
||||
...animation.current,
|
||||
zoomIn: undefined,
|
||||
zoomOut: {
|
||||
apply: zoomOut,
|
||||
@@ -719,7 +719,7 @@ function Lightbox({ images, activeImage, onUpdate, onClose, readOnly }: Props) {
|
||||
const handleFadeStart = () => {
|
||||
if (animation.current?.fadeIn) {
|
||||
animation.current = {
|
||||
...(animation.current ?? {}),
|
||||
...animation.current,
|
||||
startTime: Date.now(),
|
||||
};
|
||||
}
|
||||
@@ -728,7 +728,7 @@ function Lightbox({ images, activeImage, onUpdate, onClose, readOnly }: Props) {
|
||||
const handleFadeEnd = () => {
|
||||
if (animation.current?.fadeIn) {
|
||||
animation.current = {
|
||||
...(animation.current ?? {}),
|
||||
...animation.current,
|
||||
zoomIn: undefined,
|
||||
fadeIn: undefined,
|
||||
startTime: undefined,
|
||||
|
||||
@@ -42,13 +42,11 @@ export default class ClipboardTextSerializer extends Extension {
|
||||
.filter((node) => node.content.content.length > 1)
|
||||
.some((node) => isList(node, view.state.schema));
|
||||
const hasSingleBlockType =
|
||||
[
|
||||
...new Set(
|
||||
slice.content.content
|
||||
.filter((node) => node.content.content.length > 1)
|
||||
.map((node) => node.type.name)
|
||||
),
|
||||
].length <= 1;
|
||||
new Set(
|
||||
slice.content.content
|
||||
.filter((node) => node.content.content.length > 1)
|
||||
.map((node) => node.type.name)
|
||||
).size <= 1;
|
||||
|
||||
// Use plain text serializer only for "simple" content
|
||||
const usePlainText =
|
||||
|
||||
@@ -66,9 +66,9 @@ describe("deburrWithMap", () => {
|
||||
// even though the Hangul characters between them expand under NFD.
|
||||
for (const ascii of ["a", "b", "c"]) {
|
||||
const index = deburred.indexOf(ascii);
|
||||
expect(text.slice(toOriginalIndex(index), toOriginalIndex(index + 1))).toBe(
|
||||
ascii
|
||||
);
|
||||
expect(
|
||||
text.slice(toOriginalIndex(index), toOriginalIndex(index + 1))
|
||||
).toBe(ascii);
|
||||
}
|
||||
|
||||
// Indices are non-decreasing and the end maps to the original length.
|
||||
|
||||
@@ -147,10 +147,10 @@ const DocumentTitle = React.forwardRef(function DocumentTitle_(
|
||||
if (/\/date\s$/.test(input)) {
|
||||
value = getCurrentDateAsString();
|
||||
ref?.current?.focusAtEnd();
|
||||
} else if (/\/time$/.test(input)) {
|
||||
} else if (input.endsWith("/time")) {
|
||||
value = getCurrentTimeAsString();
|
||||
ref?.current?.focusAtEnd();
|
||||
} else if (/\/datetime$/.test(input)) {
|
||||
} else if (input.endsWith("/datetime")) {
|
||||
value = getCurrentDateTimeAsString();
|
||||
ref?.current?.focusAtEnd();
|
||||
}
|
||||
|
||||
@@ -121,7 +121,7 @@ class ApiClient {
|
||||
data.append("shareId", this.shareId);
|
||||
} else {
|
||||
data = {
|
||||
...(data || {}),
|
||||
...data,
|
||||
shareId: this.shareId,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -39,30 +39,30 @@ async function build() {
|
||||
|
||||
// Compile server and shared
|
||||
console.log("Compiling…");
|
||||
const swc = (src, out) =>
|
||||
execAsync(
|
||||
`yarn swc "${src}" -d "${out}" --strip-leading-paths --extensions .ts,.tsx --ignore "**/*.test.ts,**/*.test.tsx,**/__mocks__/**" --quiet`
|
||||
);
|
||||
|
||||
await Promise.all([
|
||||
execAsync(
|
||||
"yarn babel --extensions .ts,.tsx --quiet -d ./build/server ./server"
|
||||
),
|
||||
execAsync(
|
||||
"yarn babel --extensions .ts,.tsx --quiet -d ./build/shared ./shared"
|
||||
),
|
||||
swc("./server", "./build/server"),
|
||||
swc("./shared", "./build/shared"),
|
||||
]);
|
||||
|
||||
// SWC's --strip-leading-paths removes only the topmost path segment, so a
|
||||
// `plugins/<name>/server` input keeps `<name>/server/…` and lands correctly
|
||||
// under a `./build/plugins` output directory.
|
||||
for (const plugin of d) {
|
||||
const hasServer = existsSync(`./plugins/${plugin}/server`);
|
||||
|
||||
if (hasServer) {
|
||||
await execAsync(
|
||||
`yarn babel --extensions .ts,.tsx --quiet -d "./build/plugins/${plugin}/server" "./plugins/${plugin}/server"`
|
||||
);
|
||||
await swc(`./plugins/${plugin}/server`, "./build/plugins");
|
||||
}
|
||||
|
||||
const hasShared = existsSync(`./plugins/${plugin}/shared`);
|
||||
|
||||
if (hasShared) {
|
||||
await execAsync(
|
||||
`yarn babel --extensions .ts,.tsx --quiet -d "./build/plugins/${plugin}/shared" "./plugins/${plugin}/shared"`
|
||||
);
|
||||
await swc(`./plugins/${plugin}/shared`, "./build/plugins");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-12
@@ -279,15 +279,9 @@
|
||||
"zod": "^4.4.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/cli": "^7.29.7",
|
||||
"@babel/core": "^7.29.7",
|
||||
"@babel/plugin-proposal-decorators": "^7.29.7",
|
||||
"@babel/plugin-transform-class-properties": "^7.29.7",
|
||||
"@babel/preset-env": "^7.29.7",
|
||||
"@babel/preset-react": "^7.29.7",
|
||||
"@babel/preset-typescript": "^7.29.7",
|
||||
"@faker-js/faker": "^8.4.1",
|
||||
"@relative-ci/agent": "^4.3.1",
|
||||
"@swc/cli": "^0.8.1",
|
||||
"@swc/core": "^1.15.32",
|
||||
"@types/addressparser": "^1.0.3",
|
||||
"@types/cookie": "0.6.0",
|
||||
@@ -353,10 +347,6 @@
|
||||
"@types/yauzl": "^2.10.3",
|
||||
"@types/yazl": "^2.4.6",
|
||||
"@vitest/ui": "^4.1.8",
|
||||
"babel-plugin-module-resolver": "^5.0.3",
|
||||
"babel-plugin-styled-components": "^2.3.0",
|
||||
"babel-plugin-transform-inline-environment-variables": "^0.4.4",
|
||||
"babel-plugin-transform-typescript-metadata": "^0.4.0",
|
||||
"browserslist-to-esbuild": "^1.2.0",
|
||||
"concurrently": "^8.2.2",
|
||||
"discord-api-types": "^0.38.48",
|
||||
@@ -376,7 +366,6 @@
|
||||
"terser": "^5.48.0",
|
||||
"typescript": "^6.0.3",
|
||||
"unplugin-swc": "^1.5.9",
|
||||
"vite-plugin-babel": "^1.7.3",
|
||||
"vite-tsconfig-paths": "^6.1.1",
|
||||
"vitest": "^4.1.5"
|
||||
},
|
||||
|
||||
@@ -37,7 +37,7 @@ export default function multipart({
|
||||
);
|
||||
}
|
||||
|
||||
ctx.input = { ...(ctx.input ?? {}), file };
|
||||
ctx.input = { ...ctx.input, file };
|
||||
return next();
|
||||
};
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ export default function validate<T extends z.ZodType<Record<string, unknown>>>(
|
||||
return async function validateMiddleware(ctx: APIContext, next: Next) {
|
||||
try {
|
||||
ctx.input = {
|
||||
...(ctx.input ?? {}),
|
||||
...ctx.input,
|
||||
...schema.parse(ctx.request),
|
||||
};
|
||||
} catch (err) {
|
||||
|
||||
@@ -56,7 +56,7 @@ class AccessRequest extends IdModel<
|
||||
status: AccessRequestStatus;
|
||||
|
||||
@AllowNull
|
||||
@Column
|
||||
@Column(DataType.DATE)
|
||||
respondedAt: Date | null;
|
||||
|
||||
// associations
|
||||
|
||||
@@ -50,7 +50,7 @@ class ApiKey extends ParanoidModel<
|
||||
max: ApiKeyValidation.maxNameLength,
|
||||
msg: `Name must be between ${ApiKeyValidation.minNameLength} and ${ApiKeyValidation.maxNameLength} characters`,
|
||||
})
|
||||
@Column
|
||||
@Column(DataType.STRING)
|
||||
name: string;
|
||||
|
||||
/** A list of scopes that this API key has access to */
|
||||
@@ -63,7 +63,7 @@ class ApiKey extends ParanoidModel<
|
||||
|
||||
/** @deprecated The plain text value of the API key, removed soon. */
|
||||
@Unique
|
||||
@Column
|
||||
@Column(DataType.STRING)
|
||||
secret: string;
|
||||
|
||||
/** The cached plain text value. Only available when creating the API key */
|
||||
@@ -72,23 +72,23 @@ class ApiKey extends ParanoidModel<
|
||||
|
||||
/** The hashed value of the API key */
|
||||
@Unique
|
||||
@Column
|
||||
@Column(DataType.STRING)
|
||||
@SkipChangeset
|
||||
hash: string;
|
||||
|
||||
/** The last 4 characters of the API key */
|
||||
@Column
|
||||
@Column(DataType.STRING)
|
||||
@SkipChangeset
|
||||
last4: string;
|
||||
|
||||
/** The date and time when this API key will expire */
|
||||
@IsDate
|
||||
@Column
|
||||
@Column(DataType.DATE)
|
||||
expiresAt: Date | null;
|
||||
|
||||
/** The date and time when this API key was last used */
|
||||
@IsDate
|
||||
@Column
|
||||
@Column(DataType.DATE)
|
||||
@SkipChangeset
|
||||
lastActiveAt: Date | null;
|
||||
|
||||
@@ -154,7 +154,7 @@ class ApiKey extends ParanoidModel<
|
||||
user: User;
|
||||
|
||||
@ForeignKey(() => User)
|
||||
@Column
|
||||
@Column(DataType.UUID)
|
||||
userId: string;
|
||||
|
||||
// methods
|
||||
|
||||
@@ -45,14 +45,14 @@ class Attachment extends IdModel<
|
||||
max: 4096,
|
||||
msg: "key must be 4096 characters or less",
|
||||
})
|
||||
@Column
|
||||
@Column(DataType.STRING)
|
||||
key: string;
|
||||
|
||||
@Length({
|
||||
max: 255,
|
||||
msg: "contentType must be 255 characters or less",
|
||||
})
|
||||
@Column
|
||||
@Column(DataType.STRING)
|
||||
contentType: string;
|
||||
|
||||
@IsNumeric
|
||||
@@ -61,14 +61,14 @@ class Attachment extends IdModel<
|
||||
|
||||
@Default("public-read")
|
||||
@IsIn([["private", "public-read"]])
|
||||
@Column
|
||||
@Column(DataType.STRING)
|
||||
acl: string;
|
||||
|
||||
@Column
|
||||
@Column(DataType.DATE)
|
||||
@SkipChangeset
|
||||
lastAccessedAt: Date | null;
|
||||
|
||||
@Column
|
||||
@Column(DataType.DATE)
|
||||
expiresAt: Date | null;
|
||||
|
||||
// getters
|
||||
|
||||
@@ -68,18 +68,18 @@ class AuthenticationProvider extends Model<
|
||||
max: 255,
|
||||
msg: "name must be 255 characters or less",
|
||||
})
|
||||
@Column
|
||||
@Column(DataType.STRING)
|
||||
name: string;
|
||||
|
||||
@Default(true)
|
||||
@Column
|
||||
@Column(DataType.BOOLEAN)
|
||||
enabled: boolean;
|
||||
|
||||
@Length({
|
||||
max: 255,
|
||||
msg: "providerId must be 255 characters or less",
|
||||
})
|
||||
@Column
|
||||
@Column(DataType.STRING)
|
||||
providerId: string;
|
||||
|
||||
/** Provider-specific settings such as group sync configuration. */
|
||||
|
||||
@@ -209,7 +209,7 @@ class Collection extends ParanoidModel<
|
||||
msg: `urlId must be 10 characters`,
|
||||
})
|
||||
@Unique
|
||||
@Column
|
||||
@Column(DataType.STRING)
|
||||
urlId: string;
|
||||
|
||||
@NotContainsUrl
|
||||
@@ -217,7 +217,7 @@ class Collection extends ParanoidModel<
|
||||
max: CollectionValidation.maxNameLength,
|
||||
msg: `name must be ${CollectionValidation.maxNameLength} characters or less`,
|
||||
})
|
||||
@Column
|
||||
@Column(DataType.STRING)
|
||||
name: string;
|
||||
|
||||
/**
|
||||
@@ -230,7 +230,7 @@ class Collection extends ParanoidModel<
|
||||
max: CollectionValidation.maxDescriptionLength,
|
||||
msg: `description must be ${CollectionValidation.maxDescriptionLength} characters or less`,
|
||||
})
|
||||
@Column
|
||||
@Column(DataType.STRING)
|
||||
description: string | null;
|
||||
|
||||
/**
|
||||
@@ -240,19 +240,19 @@ class Collection extends ParanoidModel<
|
||||
content: ProsemirrorData | null;
|
||||
|
||||
/** An icon (or) emoji to use as the collection icon. */
|
||||
@Column
|
||||
@Column(DataType.STRING)
|
||||
icon: string | null;
|
||||
|
||||
/** The color of the icon. */
|
||||
@IsHexColor
|
||||
@Column
|
||||
@Column(DataType.STRING)
|
||||
color: string | null;
|
||||
|
||||
@Length({
|
||||
max: ValidateIndex.maxLength,
|
||||
msg: `index must be ${ValidateIndex.maxLength} characters or less`,
|
||||
})
|
||||
@Column
|
||||
@Column(DataType.STRING)
|
||||
index: string | null;
|
||||
|
||||
@IsIn([Object.values(CollectionPermission)])
|
||||
@@ -260,7 +260,7 @@ class Collection extends ParanoidModel<
|
||||
permission: CollectionPermission | null;
|
||||
|
||||
@Default(false)
|
||||
@Column
|
||||
@Column(DataType.BOOLEAN)
|
||||
maintainerApprovalRequired: boolean;
|
||||
|
||||
@Default(null)
|
||||
@@ -268,7 +268,7 @@ class Collection extends ParanoidModel<
|
||||
documentStructure: NavigationNode[] | null;
|
||||
|
||||
@Default(true)
|
||||
@Column
|
||||
@Column(DataType.BOOLEAN)
|
||||
sharing: boolean;
|
||||
|
||||
@Default({ field: "title", direction: "asc" })
|
||||
@@ -299,7 +299,7 @@ class Collection extends ParanoidModel<
|
||||
|
||||
/** Whether the collection is archived, and if so when. */
|
||||
@IsDate
|
||||
@Column
|
||||
@Column(DataType.DATE)
|
||||
archivedAt: Date | null;
|
||||
|
||||
/** The minimum permission level required to manage templates in this collection. */
|
||||
|
||||
+13
-13
@@ -279,40 +279,40 @@ class Document extends ArchivableModel<
|
||||
msg: `urlId must be 10 characters`,
|
||||
})
|
||||
@Unique
|
||||
@Column
|
||||
@Column(DataType.STRING)
|
||||
urlId: string;
|
||||
|
||||
@Length({
|
||||
max: DocumentValidation.maxTitleLength,
|
||||
msg: `Document title must be ${DocumentValidation.maxTitleLength} characters or less`,
|
||||
})
|
||||
@Column
|
||||
@Column(DataType.STRING)
|
||||
title: string;
|
||||
|
||||
@Length({
|
||||
max: DocumentValidation.maxSummaryLength,
|
||||
msg: `Document summary must be ${DocumentValidation.maxSummaryLength} characters or less`,
|
||||
})
|
||||
@Column
|
||||
@Column(DataType.STRING)
|
||||
@SkipChangeset
|
||||
summary: string;
|
||||
|
||||
@Column(DataType.ARRAY(DataType.STRING))
|
||||
previousTitles: string[] = [];
|
||||
previousTitles: string[];
|
||||
|
||||
@IsNumeric
|
||||
@Column(DataType.SMALLINT)
|
||||
version?: number | null;
|
||||
|
||||
@Default(false)
|
||||
@Column
|
||||
@Column(DataType.BOOLEAN)
|
||||
fullWidth: boolean;
|
||||
|
||||
@Default(false)
|
||||
@Column
|
||||
@Column(DataType.BOOLEAN)
|
||||
template: boolean;
|
||||
|
||||
@Column
|
||||
@Column(DataType.BOOLEAN)
|
||||
insightsEnabled: boolean;
|
||||
|
||||
/** The version of the editor last used to edit this document. */
|
||||
@@ -320,16 +320,16 @@ class Document extends ArchivableModel<
|
||||
max: 255,
|
||||
msg: `editorVersion must be 255 characters or less`,
|
||||
})
|
||||
@Column
|
||||
@Column(DataType.STRING)
|
||||
editorVersion: string | null;
|
||||
|
||||
/** An icon to use as the document icon. */
|
||||
@Column
|
||||
@Column(DataType.STRING)
|
||||
icon: string | null;
|
||||
|
||||
/** The color of the icon. */
|
||||
@IsHexColor
|
||||
@Column
|
||||
@Column(DataType.STRING)
|
||||
color: string | null;
|
||||
|
||||
/**
|
||||
@@ -368,7 +368,7 @@ class Document extends ArchivableModel<
|
||||
|
||||
/** Whether this document is part of onboarding. */
|
||||
@Default(false)
|
||||
@Column
|
||||
@Column(DataType.BOOLEAN)
|
||||
isWelcome: boolean;
|
||||
|
||||
/** How many versions there are in the history of this document. */
|
||||
@@ -386,12 +386,12 @@ class Document extends ArchivableModel<
|
||||
|
||||
/** Whether the document is published, and if so when. */
|
||||
@IsDate
|
||||
@Column
|
||||
@Column(DataType.DATE)
|
||||
publishedAt: Date | null;
|
||||
|
||||
/** An array of user IDs that have edited this document. */
|
||||
@Column(DataType.ARRAY(DataType.UUID))
|
||||
collaboratorIds: string[] = [];
|
||||
collaboratorIds: string[];
|
||||
|
||||
// getters
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ class Event extends IdModel<
|
||||
|
||||
/** The originating IP address of the event. */
|
||||
@IsIP
|
||||
@Column
|
||||
@Column(DataType.STRING)
|
||||
ip: string | null;
|
||||
|
||||
/** The type of authentication used to create the event. */
|
||||
|
||||
@@ -27,7 +27,7 @@ class ExternalGroup extends IdModel<
|
||||
max: 255,
|
||||
msg: "externalId must be 255 characters or less",
|
||||
})
|
||||
@Column
|
||||
@Column(DataType.STRING)
|
||||
externalId: string;
|
||||
|
||||
/** The group name as reported by the external provider. */
|
||||
@@ -35,7 +35,7 @@ class ExternalGroup extends IdModel<
|
||||
max: 255,
|
||||
msg: "name must be 255 characters or less",
|
||||
})
|
||||
@Column
|
||||
@Column(DataType.STRING)
|
||||
name: string;
|
||||
|
||||
/** When this record was last synced from the provider. */
|
||||
|
||||
@@ -70,13 +70,13 @@ class FileOperation extends ParanoidModel<
|
||||
@Column(DataType.ENUM(...Object.values(FileOperationState)))
|
||||
state: FileOperationState;
|
||||
|
||||
@Column
|
||||
@Column(DataType.STRING)
|
||||
key: string;
|
||||
|
||||
@Column
|
||||
@Column(DataType.STRING)
|
||||
url?: string | null;
|
||||
|
||||
@Column
|
||||
@Column(DataType.STRING)
|
||||
error: string | null;
|
||||
|
||||
@Column(DataType.BIGINT)
|
||||
|
||||
@@ -69,7 +69,7 @@ class Group extends ParanoidModel<
|
||||
msg: `name must be ${GroupValidation.maxNameLength} characters or less`,
|
||||
})
|
||||
@NotContainsUrl
|
||||
@Column
|
||||
@Column(DataType.STRING)
|
||||
name: string;
|
||||
|
||||
@Length({
|
||||
@@ -80,7 +80,7 @@ class Group extends ParanoidModel<
|
||||
@Column(DataType.TEXT)
|
||||
description: string;
|
||||
|
||||
@Column
|
||||
@Column(DataType.STRING)
|
||||
externalId: string;
|
||||
|
||||
@Column(DataType.BOOLEAN)
|
||||
|
||||
@@ -71,7 +71,7 @@ class Import<T extends ImportableIntegrationService> extends ParanoidModel<
|
||||
@Column(DataType.INTEGER)
|
||||
documentCount: number;
|
||||
|
||||
@Column
|
||||
@Column(DataType.STRING)
|
||||
error: string | null;
|
||||
|
||||
// associations
|
||||
|
||||
@@ -51,7 +51,7 @@ class ImportTask<T extends ImportableIntegrationService> extends IdModel<
|
||||
@Column(DataType.JSONB)
|
||||
output: ImportTaskOutput | null;
|
||||
|
||||
@Column
|
||||
@Column(DataType.STRING)
|
||||
error: string | null;
|
||||
|
||||
// associations
|
||||
|
||||
@@ -114,15 +114,15 @@ class Notification extends Model<
|
||||
id: string;
|
||||
|
||||
@AllowNull
|
||||
@Column
|
||||
@Column(DataType.DATE)
|
||||
emailedAt?: Date | null;
|
||||
|
||||
@AllowNull
|
||||
@Column
|
||||
@Column(DataType.DATE)
|
||||
viewedAt: Date | null;
|
||||
|
||||
@AllowNull
|
||||
@Column
|
||||
@Column(DataType.DATE)
|
||||
archivedAt: Date | null;
|
||||
|
||||
@CreatedAt
|
||||
|
||||
@@ -24,7 +24,7 @@ class Pin extends IdModel<
|
||||
max: 256,
|
||||
msg: `index must be 256 characters or less`,
|
||||
})
|
||||
@Column
|
||||
@Column(DataType.STRING)
|
||||
index: string | null;
|
||||
|
||||
// associations
|
||||
|
||||
@@ -47,7 +47,7 @@ class Revision extends ParanoidModel<
|
||||
max: 255,
|
||||
msg: `editorVersion must be 255 characters or less`,
|
||||
})
|
||||
@Column
|
||||
@Column(DataType.STRING)
|
||||
@SkipChangeset
|
||||
editorVersion: string | null;
|
||||
|
||||
@@ -56,7 +56,7 @@ class Revision extends ParanoidModel<
|
||||
max: DocumentValidation.maxTitleLength,
|
||||
msg: `Revision title must be ${DocumentValidation.maxTitleLength} characters or less`,
|
||||
})
|
||||
@Column
|
||||
@Column(DataType.STRING)
|
||||
@SkipChangeset
|
||||
title: string;
|
||||
|
||||
@@ -65,7 +65,7 @@ class Revision extends ParanoidModel<
|
||||
max: RevisionValidation.maxNameLength,
|
||||
msg: `Revision name must be ${RevisionValidation.maxNameLength} characters or less`,
|
||||
})
|
||||
@Column
|
||||
@Column(DataType.STRING)
|
||||
@SkipChangeset
|
||||
name: string | null;
|
||||
|
||||
@@ -86,13 +86,13 @@ class Revision extends ParanoidModel<
|
||||
content: ProsemirrorData | null;
|
||||
|
||||
/** The icon at the time of the revision. */
|
||||
@Column
|
||||
@Column(DataType.STRING)
|
||||
@SkipChangeset
|
||||
icon: string | null;
|
||||
|
||||
/** The color at the time of the revision. */
|
||||
@IsHexColor
|
||||
@Column
|
||||
@Column(DataType.STRING)
|
||||
@SkipChangeset
|
||||
color: string | null;
|
||||
|
||||
@@ -115,7 +115,7 @@ class Revision extends ParanoidModel<
|
||||
/** Array of user IDs who collaborated on this revision */
|
||||
@Column(DataType.ARRAY(DataType.UUID))
|
||||
@SkipChangeset
|
||||
collaboratorIds: string[] = [];
|
||||
collaboratorIds: string[];
|
||||
|
||||
/**
|
||||
* Get the collaborators for this revision.
|
||||
|
||||
@@ -44,25 +44,25 @@ class SearchQuery extends Model<
|
||||
/**
|
||||
* The number of results returned for this query.
|
||||
*/
|
||||
@Column
|
||||
@Column(DataType.INTEGER)
|
||||
results: number;
|
||||
|
||||
/**
|
||||
* How long the search took to execute, in milliseconds.
|
||||
*/
|
||||
@Column
|
||||
@Column(DataType.INTEGER)
|
||||
duration: number;
|
||||
|
||||
/**
|
||||
* User score for the results for this query, -1 for negative, 1 for positive, null for neutral.
|
||||
*/
|
||||
@Column
|
||||
@Column(DataType.INTEGER)
|
||||
score: number;
|
||||
|
||||
/**
|
||||
* The generated answer to the query, if any.
|
||||
*/
|
||||
@Column
|
||||
@Column(DataType.STRING)
|
||||
answer: string;
|
||||
|
||||
/**
|
||||
|
||||
+13
-13
@@ -110,21 +110,21 @@ class Share extends IdModel<
|
||||
InferAttributes<Share>,
|
||||
Partial<InferCreationAttributes<Share>>
|
||||
> {
|
||||
@Column
|
||||
@Column(DataType.BOOLEAN)
|
||||
published: boolean;
|
||||
|
||||
@Column
|
||||
@Column(DataType.BOOLEAN)
|
||||
includeChildDocuments: boolean;
|
||||
|
||||
@Column
|
||||
@Column(DataType.DATE)
|
||||
revokedAt: Date | null;
|
||||
|
||||
@Column
|
||||
@Column(DataType.DATE)
|
||||
lastAccessedAt: Date | null;
|
||||
|
||||
/** Total count of times the shared link has been accessed */
|
||||
@Default(0)
|
||||
@Column
|
||||
@Column(DataType.INTEGER)
|
||||
views: number;
|
||||
|
||||
@AllowNull
|
||||
@@ -132,29 +132,29 @@ class Share extends IdModel<
|
||||
args: UrlHelper.SHARE_URL_SLUG_REGEX,
|
||||
msg: "Must be only alphanumeric and dashes",
|
||||
})
|
||||
@Column
|
||||
@Column(DataType.STRING)
|
||||
urlId: string | null | undefined;
|
||||
|
||||
@Unique
|
||||
@Length({ max: 255, msg: "domain must be 255 characters or less" })
|
||||
@IsFQDN
|
||||
@Column
|
||||
@Column(DataType.STRING)
|
||||
domain: string | null;
|
||||
|
||||
@Default(false)
|
||||
@Column
|
||||
@Column(DataType.BOOLEAN)
|
||||
allowIndexing: boolean;
|
||||
|
||||
@Default(true)
|
||||
@Column
|
||||
@Column(DataType.BOOLEAN)
|
||||
allowSubscriptions: boolean;
|
||||
|
||||
@Default(false)
|
||||
@Column
|
||||
@Column(DataType.BOOLEAN)
|
||||
showLastUpdated: boolean;
|
||||
|
||||
@Default(false)
|
||||
@Column
|
||||
@Column(DataType.BOOLEAN)
|
||||
showTOC: boolean;
|
||||
|
||||
@AllowNull
|
||||
@@ -162,7 +162,7 @@ class Share extends IdModel<
|
||||
max: ShareValidation.maxTitleLength,
|
||||
msg: `title must be ${ShareValidation.maxTitleLength} characters or less`,
|
||||
})
|
||||
@Column
|
||||
@Column(DataType.STRING)
|
||||
title: string | null;
|
||||
|
||||
@AllowNull
|
||||
@@ -171,7 +171,7 @@ class Share extends IdModel<
|
||||
max: ShareValidation.maxIconUrlLength,
|
||||
msg: `iconUrl must be ${ShareValidation.maxIconUrlLength} characters or less`,
|
||||
})
|
||||
@Column
|
||||
@Column(DataType.STRING)
|
||||
iconUrl: string | null;
|
||||
|
||||
// hooks
|
||||
|
||||
@@ -23,7 +23,7 @@ class Star extends IdModel<
|
||||
max: 256,
|
||||
msg: `index must be 256 characters or less`,
|
||||
})
|
||||
@Column
|
||||
@Column(DataType.STRING)
|
||||
index: string | null;
|
||||
|
||||
// associations
|
||||
|
||||
+12
-12
@@ -85,7 +85,7 @@ class Team extends ParanoidModel<
|
||||
max: TeamValidation.maxNameLength,
|
||||
msg: `Team name must be between 1 and ${TeamValidation.maxNameLength} characters`,
|
||||
})
|
||||
@Column
|
||||
@Column(DataType.STRING)
|
||||
name: string;
|
||||
|
||||
@AllowNull
|
||||
@@ -117,7 +117,7 @@ class Team extends ParanoidModel<
|
||||
args: [RESERVED_SUBDOMAINS],
|
||||
msg: "You chose a restricted word, please try another.",
|
||||
})
|
||||
@Column
|
||||
@Column(DataType.STRING)
|
||||
subdomain: string | null;
|
||||
|
||||
@Unique
|
||||
@@ -126,7 +126,7 @@ class Team extends ParanoidModel<
|
||||
msg: `domain must be ${TeamValidation.maxDomainLength} characters or less`,
|
||||
})
|
||||
@IsFQDN
|
||||
@Column
|
||||
@Column(DataType.STRING)
|
||||
domain: string | null;
|
||||
|
||||
@IsUUID(4)
|
||||
@@ -183,34 +183,34 @@ class Team extends ParanoidModel<
|
||||
}
|
||||
|
||||
@Default(true)
|
||||
@Column
|
||||
@Column(DataType.BOOLEAN)
|
||||
sharing: boolean;
|
||||
|
||||
@Default(false)
|
||||
@Column
|
||||
@Column(DataType.BOOLEAN)
|
||||
inviteRequired: boolean;
|
||||
|
||||
@Column(DataType.JSONB)
|
||||
signupQueryParams: { [key: string]: string } | null;
|
||||
|
||||
@Default(true)
|
||||
@Column
|
||||
@Column(DataType.BOOLEAN)
|
||||
guestSignin: boolean;
|
||||
|
||||
@Default(true)
|
||||
@Column
|
||||
@Column(DataType.BOOLEAN)
|
||||
passkeysEnabled: boolean;
|
||||
|
||||
@Default(true)
|
||||
@Column
|
||||
@Column(DataType.BOOLEAN)
|
||||
documentEmbeds: boolean;
|
||||
|
||||
@Default(true)
|
||||
@Column
|
||||
@Column(DataType.BOOLEAN)
|
||||
memberCollectionCreate: boolean;
|
||||
|
||||
@Default(true)
|
||||
@Column
|
||||
@Column(DataType.BOOLEAN)
|
||||
memberTeamCreate: boolean;
|
||||
|
||||
@Default(UserRole.Member)
|
||||
@@ -237,14 +237,14 @@ class Team extends ParanoidModel<
|
||||
preferences: TeamPreferences | null;
|
||||
|
||||
@IsDate
|
||||
@Column
|
||||
@Column(DataType.DATE)
|
||||
suspendedAt: Date | null;
|
||||
|
||||
@Column(DataType.JSONB)
|
||||
flags: { [key in TeamFlag]?: number } | null;
|
||||
|
||||
@IsDate
|
||||
@Column
|
||||
@Column(DataType.DATE)
|
||||
@SkipChangeset
|
||||
lastActiveAt: Date | null;
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ import emailProviders from "email-providers";
|
||||
import type { InferAttributes, InferCreationAttributes } from "sequelize";
|
||||
import {
|
||||
Column,
|
||||
DataType,
|
||||
Table,
|
||||
BelongsTo,
|
||||
ForeignKey,
|
||||
@@ -36,7 +37,7 @@ class TeamDomain extends IdModel<
|
||||
msg: `name must be ${TeamValidation.maxDomainLength} characters or less`,
|
||||
})
|
||||
@IsFQDN
|
||||
@Column
|
||||
@Column(DataType.STRING)
|
||||
name: string;
|
||||
|
||||
// associations
|
||||
@@ -45,14 +46,14 @@ class TeamDomain extends IdModel<
|
||||
team: Team;
|
||||
|
||||
@ForeignKey(() => Team)
|
||||
@Column
|
||||
@Column(DataType.UUID)
|
||||
teamId: string;
|
||||
|
||||
@BelongsTo(() => User, "createdById")
|
||||
createdBy: User;
|
||||
|
||||
@ForeignKey(() => User)
|
||||
@Column
|
||||
@Column(DataType.UUID)
|
||||
createdById: string;
|
||||
|
||||
// hooks
|
||||
|
||||
@@ -101,22 +101,22 @@ class Template extends ParanoidModel<
|
||||
msg: `urlId must be 10 characters`,
|
||||
})
|
||||
@Unique
|
||||
@Column
|
||||
@Column(DataType.STRING)
|
||||
urlId: string;
|
||||
|
||||
@Length({
|
||||
max: DocumentValidation.maxTitleLength,
|
||||
msg: `Template title must be ${DocumentValidation.maxTitleLength} characters or less`,
|
||||
})
|
||||
@Column
|
||||
@Column(DataType.STRING)
|
||||
title: string;
|
||||
|
||||
@Default(false)
|
||||
@Column
|
||||
@Column(DataType.BOOLEAN)
|
||||
fullWidth: boolean;
|
||||
|
||||
@Default(true)
|
||||
@Column
|
||||
@Column(DataType.BOOLEAN)
|
||||
template: boolean;
|
||||
|
||||
/** The version of the editor last used to edit this template. */
|
||||
@@ -124,7 +124,7 @@ class Template extends ParanoidModel<
|
||||
max: 255,
|
||||
msg: `editorVersion must be 255 characters or less`,
|
||||
})
|
||||
@Column
|
||||
@Column(DataType.STRING)
|
||||
editorVersion: string | null;
|
||||
|
||||
/** An icon to use as the template icon. */
|
||||
@@ -132,16 +132,16 @@ class Template extends ParanoidModel<
|
||||
max: 50,
|
||||
msg: `icon must be 50 characters or less`,
|
||||
})
|
||||
@Column
|
||||
@Column(DataType.STRING)
|
||||
icon: string | null;
|
||||
|
||||
/** The color of the icon. */
|
||||
@IsHexColor
|
||||
@Column
|
||||
@Column(DataType.STRING)
|
||||
color: string | null;
|
||||
|
||||
/** The likely language of the template, in ISO 639-1 format. */
|
||||
@Column
|
||||
@Column(DataType.STRING)
|
||||
language: string | null;
|
||||
|
||||
/**
|
||||
@@ -185,7 +185,7 @@ class Template extends ParanoidModel<
|
||||
|
||||
/** Whether the template is published, and if so when. */
|
||||
@IsDate
|
||||
@Column
|
||||
@Column(DataType.DATE)
|
||||
publishedAt: Date | null;
|
||||
|
||||
// getters
|
||||
|
||||
@@ -144,7 +144,7 @@ class User extends ParanoidModel<
|
||||
max: UserValidation.maxEmailLength,
|
||||
msg: `User email must be between 1 and ${UserValidation.maxEmailLength} characters`,
|
||||
})
|
||||
@Column
|
||||
@Column(DataType.STRING)
|
||||
email: string | null;
|
||||
|
||||
@NotContainsUrl
|
||||
@@ -153,7 +153,7 @@ class User extends ParanoidModel<
|
||||
max: UserValidation.maxNameLength,
|
||||
msg: `User name must be between 1 and ${UserValidation.maxNameLength} characters`,
|
||||
})
|
||||
@Column
|
||||
@Column(DataType.STRING)
|
||||
name: string;
|
||||
|
||||
@Default(UserRole.Member)
|
||||
@@ -165,7 +165,7 @@ class User extends ParanoidModel<
|
||||
jwtSecret: string;
|
||||
|
||||
@IsDate
|
||||
@Column
|
||||
@Column(DataType.DATE)
|
||||
@SkipChangeset
|
||||
lastActiveAt: Date | null;
|
||||
|
||||
@@ -181,7 +181,7 @@ class User extends ParanoidModel<
|
||||
}
|
||||
|
||||
@IsDate
|
||||
@Column
|
||||
@Column(DataType.DATE)
|
||||
@SkipChangeset
|
||||
lastSignedInAt: Date | null;
|
||||
|
||||
@@ -197,12 +197,12 @@ class User extends ParanoidModel<
|
||||
}
|
||||
|
||||
@IsDate
|
||||
@Column
|
||||
@Column(DataType.DATE)
|
||||
@SkipChangeset
|
||||
lastSigninEmailSentAt: Date | null;
|
||||
|
||||
@IsDate
|
||||
@Column
|
||||
@Column(DataType.DATE)
|
||||
suspendedAt: Date | null;
|
||||
|
||||
@Column(DataType.JSONB)
|
||||
|
||||
@@ -39,7 +39,7 @@ class UserAuthentication extends IdModel<
|
||||
@Encrypted
|
||||
refreshToken: string;
|
||||
|
||||
@Column
|
||||
@Column(DataType.STRING)
|
||||
providerId: string;
|
||||
|
||||
@Column(DataType.DATE)
|
||||
|
||||
@@ -84,7 +84,7 @@ class UserMembership extends IdModel<
|
||||
max: 256,
|
||||
msg: `index must be 256 characters or less`,
|
||||
})
|
||||
@Column
|
||||
@Column(DataType.STRING)
|
||||
index: string | null;
|
||||
|
||||
// associations
|
||||
|
||||
@@ -23,14 +23,14 @@ class UserPasskey extends IdModel<
|
||||
> {
|
||||
static eventNamespace = "passkeys";
|
||||
|
||||
@Column
|
||||
@Column(DataType.STRING)
|
||||
credentialId: string;
|
||||
|
||||
@Column(DataType.BLOB)
|
||||
@SkipChangeset
|
||||
credentialPublicKey: Buffer;
|
||||
|
||||
@Column
|
||||
@Column(DataType.STRING)
|
||||
aaguid: string | null;
|
||||
|
||||
@Column(DataType.BIGINT)
|
||||
@@ -46,14 +46,14 @@ class UserPasskey extends IdModel<
|
||||
msg: `Name must be between ${UserPasskeyValidation.minNameLength} and ${UserPasskeyValidation.maxNameLength} characters`,
|
||||
})
|
||||
@NotContainsUrl
|
||||
@Column
|
||||
@Column(DataType.STRING)
|
||||
name: string;
|
||||
|
||||
@Column
|
||||
@Column(DataType.STRING)
|
||||
userAgent: string | null;
|
||||
|
||||
@IsDate
|
||||
@Column
|
||||
@Column(DataType.DATE)
|
||||
@SkipChangeset
|
||||
lastActiveAt: Date | null;
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ class View extends IdModel<
|
||||
InferAttributes<View>,
|
||||
Partial<InferCreationAttributes<View>>
|
||||
> {
|
||||
@Column
|
||||
@Column(DataType.DATE)
|
||||
lastEditingAt: Date | null;
|
||||
|
||||
@Default(1)
|
||||
|
||||
@@ -51,7 +51,7 @@ class WebhookDelivery extends IdModel<
|
||||
webhookSubscription: WebhookSubscription;
|
||||
|
||||
@ForeignKey(() => WebhookSubscription)
|
||||
@Column
|
||||
@Column(DataType.UUID)
|
||||
webhookSubscriptionId: string;
|
||||
}
|
||||
|
||||
|
||||
@@ -114,7 +114,7 @@ class WebhookSubscription extends ParanoidModel<
|
||||
max: WebhookSubscriptionValidation.maxNameLength,
|
||||
msg: `Webhook name must be ${WebhookSubscriptionValidation.maxNameLength} characters or less`,
|
||||
})
|
||||
@Column
|
||||
@Column(DataType.STRING)
|
||||
name: string;
|
||||
|
||||
@IsUrl
|
||||
@@ -123,10 +123,10 @@ class WebhookSubscription extends ParanoidModel<
|
||||
max: WebhookSubscriptionValidation.maxUrlLength,
|
||||
msg: `Webhook url must be ${WebhookSubscriptionValidation.maxUrlLength} characters or less`,
|
||||
})
|
||||
@Column
|
||||
@Column(DataType.STRING)
|
||||
url: string;
|
||||
|
||||
@Column
|
||||
@Column(DataType.BOOLEAN)
|
||||
enabled: boolean;
|
||||
|
||||
@Column(DataType.ARRAY(DataType.STRING))
|
||||
@@ -143,14 +143,14 @@ class WebhookSubscription extends ParanoidModel<
|
||||
createdBy: User;
|
||||
|
||||
@ForeignKey(() => User)
|
||||
@Column
|
||||
@Column(DataType.UUID)
|
||||
createdById: string;
|
||||
|
||||
@BelongsTo(() => Team, "teamId")
|
||||
team: Team;
|
||||
|
||||
@ForeignKey(() => Team)
|
||||
@Column
|
||||
@Column(DataType.UUID)
|
||||
teamId: string;
|
||||
|
||||
// hooks
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { AllowNull, Column, IsDate } from "sequelize-typescript";
|
||||
import { AllowNull, Column, DataType, IsDate } from "sequelize-typescript";
|
||||
import ParanoidModel from "./ParanoidModel";
|
||||
|
||||
class ArchivableModel<
|
||||
@@ -9,7 +9,7 @@ class ArchivableModel<
|
||||
/** Whether the document is archived, and if so when. */
|
||||
@AllowNull
|
||||
@IsDate
|
||||
@Column
|
||||
@Column(DataType.DATE)
|
||||
archivedAt: Date | null;
|
||||
|
||||
/**
|
||||
|
||||
@@ -31,6 +31,11 @@ export default function Fix(target: any): void {
|
||||
}
|
||||
|
||||
Object.defineProperty(this, propertyKey, {
|
||||
// Keep configurable/enumerable so consumers (e.g. sequelize-strict-attributes)
|
||||
// can re-define these accessors; with non-define class fields the property
|
||||
// would otherwise default to non-configurable.
|
||||
configurable: true,
|
||||
enumerable: true,
|
||||
get() {
|
||||
// Safety check for test serialization - getDataValue may not be available
|
||||
// during serialization for inter-process communication
|
||||
@@ -55,6 +60,8 @@ export default function Fix(target: any): void {
|
||||
|
||||
associations.forEach((propertyKey) => {
|
||||
Object.defineProperty(this, propertyKey, {
|
||||
configurable: true,
|
||||
enumerable: true,
|
||||
get() {
|
||||
return this.dataValues[propertyKey];
|
||||
},
|
||||
|
||||
@@ -49,7 +49,7 @@ class OAuthAuthentication extends ParanoidModel<
|
||||
public static refreshTokenPrefix = "ol_rt_";
|
||||
|
||||
@Unique
|
||||
@Column
|
||||
@Column(DataType.STRING)
|
||||
@SkipChangeset
|
||||
accessTokenHash: string;
|
||||
|
||||
@@ -58,11 +58,11 @@ class OAuthAuthentication extends ParanoidModel<
|
||||
accessToken: string | null;
|
||||
|
||||
@IsDate
|
||||
@Column
|
||||
@Column(DataType.DATE)
|
||||
accessTokenExpiresAt: Date;
|
||||
|
||||
@Unique
|
||||
@Column
|
||||
@Column(DataType.STRING)
|
||||
@SkipChangeset
|
||||
refreshTokenHash: string;
|
||||
|
||||
@@ -71,7 +71,7 @@ class OAuthAuthentication extends ParanoidModel<
|
||||
refreshToken: string | null;
|
||||
|
||||
@IsDate
|
||||
@Column
|
||||
@Column(DataType.DATE)
|
||||
refreshTokenExpiresAt: Date;
|
||||
|
||||
/**
|
||||
@@ -91,7 +91,7 @@ class OAuthAuthentication extends ParanoidModel<
|
||||
scope: string[];
|
||||
|
||||
@IsDate
|
||||
@Column
|
||||
@Column(DataType.DATE)
|
||||
@SkipChangeset
|
||||
lastActiveAt: Date;
|
||||
|
||||
|
||||
@@ -37,15 +37,15 @@ class OAuthAuthorizationCode extends IdModel<
|
||||
/** A recognizable prefix for authorization codes. */
|
||||
public static authorizationCodePrefix = "ol_ac_";
|
||||
|
||||
@Column
|
||||
@Column(DataType.STRING)
|
||||
@SkipChangeset
|
||||
authorizationCodeHash: string;
|
||||
|
||||
@Column
|
||||
@Column(DataType.STRING)
|
||||
@SkipChangeset
|
||||
codeChallenge?: string;
|
||||
|
||||
@Column
|
||||
@Column(DataType.STRING)
|
||||
@SkipChangeset
|
||||
codeChallengeMethod?: string;
|
||||
|
||||
@@ -66,7 +66,7 @@ class OAuthAuthorizationCode extends IdModel<
|
||||
scope: string[];
|
||||
|
||||
@Length({ max: OAuthClientValidation.maxRedirectUriLength })
|
||||
@Column
|
||||
@Column(DataType.STRING)
|
||||
redirectUri: string;
|
||||
|
||||
@Column(DataType.DATE)
|
||||
|
||||
@@ -52,7 +52,7 @@ class OAuthClient extends ParanoidModel<
|
||||
max: OAuthClientValidation.maxNameLength,
|
||||
msg: `name must be ${OAuthClientValidation.maxNameLength} characters or less`,
|
||||
})
|
||||
@Column
|
||||
@Column(DataType.STRING)
|
||||
name: string;
|
||||
|
||||
@AllowNull
|
||||
@@ -61,7 +61,7 @@ class OAuthClient extends ParanoidModel<
|
||||
max: OAuthClientValidation.maxDescriptionLength,
|
||||
msg: `description must be ${OAuthClientValidation.maxDescriptionLength} characters or less`,
|
||||
})
|
||||
@Column
|
||||
@Column(DataType.STRING)
|
||||
description: string | null;
|
||||
|
||||
@AllowNull
|
||||
@@ -70,7 +70,7 @@ class OAuthClient extends ParanoidModel<
|
||||
max: OAuthClientValidation.maxDeveloperNameLength,
|
||||
msg: `developerName must be ${OAuthClientValidation.maxDeveloperNameLength} characters or less`,
|
||||
})
|
||||
@Column
|
||||
@Column(DataType.STRING)
|
||||
developerName: string | null;
|
||||
|
||||
@AllowNull
|
||||
@@ -79,7 +79,7 @@ class OAuthClient extends ParanoidModel<
|
||||
max: OAuthClientValidation.maxDeveloperUrlLength,
|
||||
msg: `developerUrl must be ${OAuthClientValidation.maxDeveloperUrlLength} characters or less`,
|
||||
})
|
||||
@Column
|
||||
@Column(DataType.STRING)
|
||||
developerUrl: string | null;
|
||||
|
||||
@AllowNull
|
||||
@@ -88,10 +88,10 @@ class OAuthClient extends ParanoidModel<
|
||||
max: OAuthClientValidation.maxAvatarUrlLength,
|
||||
msg: `avatarUrl must be ${OAuthClientValidation.maxAvatarUrlLength} characters or less`,
|
||||
})
|
||||
@Column
|
||||
@Column(DataType.STRING)
|
||||
avatarUrl: string | null;
|
||||
|
||||
@Column
|
||||
@Column(DataType.STRING)
|
||||
clientId: string;
|
||||
|
||||
@IsIn([Array.from(OAuthClientValidation.clientTypes)])
|
||||
@@ -102,7 +102,7 @@ class OAuthClient extends ParanoidModel<
|
||||
@Encrypted
|
||||
clientSecret: string;
|
||||
|
||||
@Column
|
||||
@Column(DataType.BOOLEAN)
|
||||
published: boolean;
|
||||
|
||||
@ArrayNotEmpty()
|
||||
@@ -124,14 +124,14 @@ class OAuthClient extends ParanoidModel<
|
||||
/** The last time this client was used to make an API request. */
|
||||
@AllowNull
|
||||
@IsDate
|
||||
@Column
|
||||
@Column(DataType.DATE)
|
||||
@SkipChangeset
|
||||
lastActiveAt: Date | null;
|
||||
|
||||
/** SHA-256 hash of the registration access token (RFC 7592). */
|
||||
@AllowNull
|
||||
@Unique
|
||||
@Column
|
||||
@Column(DataType.STRING)
|
||||
registrationAccessTokenHash: string | null;
|
||||
|
||||
/** The cached registration access token. Only available during creation. */
|
||||
|
||||
@@ -78,7 +78,7 @@ export function rewriteAttachmentReferences(
|
||||
|
||||
const transformAttachmentNode = (node: Node): Node => {
|
||||
const json = node.toJSON() as ProsemirrorData;
|
||||
const attrs = { ...(json.attrs ?? {}) };
|
||||
const attrs = { ...json.attrs };
|
||||
|
||||
if (node.type.name === "attachment") {
|
||||
const href = attrs.href as string | undefined;
|
||||
|
||||
@@ -65,7 +65,7 @@ router.post(
|
||||
if (settings !== undefined) {
|
||||
await authenticationProvider.updateWithCtx(ctx, {
|
||||
settings: {
|
||||
...(authenticationProvider.settings ?? {}),
|
||||
...authenticationProvider.settings,
|
||||
...settings,
|
||||
},
|
||||
});
|
||||
|
||||
@@ -4882,13 +4882,11 @@ describe("#documents.users", () => {
|
||||
});
|
||||
|
||||
// add people to group
|
||||
await Promise.all([
|
||||
group.$add("user", ken, {
|
||||
through: {
|
||||
createdById: user.id,
|
||||
},
|
||||
}),
|
||||
]);
|
||||
await group.$add("user", ken, {
|
||||
through: {
|
||||
createdById: user.id,
|
||||
},
|
||||
});
|
||||
|
||||
// add people and groups to collection
|
||||
await Promise.all([
|
||||
|
||||
@@ -11,15 +11,17 @@ export default {
|
||||
|
||||
getPresignedPost: vi.fn().mockReturnValue({}),
|
||||
|
||||
getPresignedPut: vi.fn().mockImplementation(
|
||||
(_key: string, _acl: string, contentLength: number) => ({
|
||||
url: "http://s3mock/presigned-put-url",
|
||||
headers: {
|
||||
"Content-Type": "application/octet-stream",
|
||||
"Content-Length": String(contentLength),
|
||||
"Content-Disposition": "attachment",
|
||||
"Cache-Control": "max-age=31557600",
|
||||
},
|
||||
})
|
||||
),
|
||||
getPresignedPut: vi
|
||||
.fn()
|
||||
.mockImplementation(
|
||||
(_key: string, _acl: string, contentLength: number) => ({
|
||||
url: "http://s3mock/presigned-put-url",
|
||||
headers: {
|
||||
"Content-Type": "application/octet-stream",
|
||||
"Content-Length": String(contentLength),
|
||||
"Content-Disposition": "attachment",
|
||||
"Cache-Control": "max-age=31557600",
|
||||
},
|
||||
})
|
||||
),
|
||||
};
|
||||
|
||||
@@ -110,9 +110,13 @@ export function attachmentTools(server: McpServer, scopes: string[]) {
|
||||
);
|
||||
}
|
||||
|
||||
const curlCommand = `curl -X PUT ${Object.entries(presignedPut.headers)
|
||||
const curlCommand = `curl -X PUT ${Object.entries(
|
||||
presignedPut.headers
|
||||
)
|
||||
.map(([k, v]) => `-H '${k}: ${v}'`)
|
||||
.join(" ")} --data-binary '@/path/to/file' '${presignedPut.url}'`;
|
||||
.join(
|
||||
" "
|
||||
)} --data-binary '@/path/to/file' '${presignedPut.url}'`;
|
||||
|
||||
return success({
|
||||
mode: "put",
|
||||
|
||||
@@ -138,7 +138,7 @@ export default class ZipHelper {
|
||||
const handle: ZipEntryHandle = {
|
||||
fileName,
|
||||
uncompressedSize: entry.uncompressedSize,
|
||||
isDirectory: /\/$/.test(fileName),
|
||||
isDirectory: fileName.endsWith("/"),
|
||||
readBuffer: (maxSize) =>
|
||||
new Promise<Buffer>((res, rej) => {
|
||||
if (entry.uncompressedSize > maxSize) {
|
||||
@@ -339,7 +339,7 @@ export default class ZipHelper {
|
||||
return;
|
||||
}
|
||||
|
||||
if (/\/$/.test(filePath)) {
|
||||
if (filePath.endsWith("/")) {
|
||||
// directory file names end with '/'
|
||||
fs.mkdirp(path.join(outputDir, filePath), (mkErr) =>
|
||||
processNext(mkErr)
|
||||
|
||||
@@ -160,7 +160,7 @@ const insertFiles = async function (
|
||||
schema.nodes.image.create({
|
||||
src,
|
||||
source: upload.source,
|
||||
...(upload.dimensions ?? {}),
|
||||
...upload.dimensions,
|
||||
...options.attrs,
|
||||
})
|
||||
)
|
||||
|
||||
@@ -290,12 +290,15 @@
|
||||
"Never viewed": "Never viewed",
|
||||
"Viewed": "Viewed",
|
||||
"in": "in",
|
||||
"nested document": "nested document",
|
||||
"nested document_plural": "nested documents",
|
||||
"{{ total }} task": "{{ total }} task",
|
||||
"{{ total }} task_plural": "{{ total }} tasks",
|
||||
"{{ completed }} task done": "{{ completed }} task done",
|
||||
"{{ completed }} task done_plural": "{{ completed }} tasks done",
|
||||
"nested document_one": "nested document",
|
||||
"nested document_many": "nested document",
|
||||
"nested document_other": "nested document",
|
||||
"{{ total }} task_one": "{{ total }} task",
|
||||
"{{ total }} task_many": "{{ total }} task",
|
||||
"{{ total }} task_other": "{{ total }} task",
|
||||
"{{ completed }} task done_one": "{{ completed }} task done",
|
||||
"{{ completed }} task done_many": "{{ completed }} task done",
|
||||
"{{ completed }} task done_other": "{{ completed }} task done",
|
||||
"{{ completed }} of {{ total }} tasks": "{{ completed }} of {{ total }} tasks",
|
||||
"Currently editing": "Currently editing",
|
||||
"Currently viewing": "Currently viewing",
|
||||
@@ -335,13 +338,15 @@
|
||||
"Include attachments": "Include attachments",
|
||||
"Including uploaded images and files in the exported data": "Including uploaded images and files in the exported data",
|
||||
"Include private collections": "Include private collections",
|
||||
"{{count}} more user": "{{count}} more user",
|
||||
"{{count}} more user_plural": "{{count}} more users",
|
||||
"{{count}} more user_one": "{{count}} more user",
|
||||
"{{count}} more user_many": "{{count}} more user",
|
||||
"{{count}} more user_other": "{{count}} more user",
|
||||
"Filter options": "Filter options",
|
||||
"Filter": "Filter",
|
||||
"No results": "No results",
|
||||
"{{ count }} members": "{{ count }} member",
|
||||
"{{ count }} members_plural": "{{ count }} members",
|
||||
"{{ count }} members_one": "{{ count }} members",
|
||||
"{{ count }} members_many": "{{ count }} members",
|
||||
"{{ count }} members_other": "{{ count }} members",
|
||||
"{{authorName}} created <3></3>": "{{authorName}} created <3></3>",
|
||||
"Lead": "Lead",
|
||||
"Target date": "Target date",
|
||||
@@ -419,8 +424,9 @@
|
||||
"Allow this app to be installed by other workspaces": "Allow this app to be installed by other workspaces",
|
||||
"{{ username }} reacted with {{ emoji }}": "{{ username }} reacted with {{ emoji }}",
|
||||
"{{ firstUsername }} and {{ secondUsername }} reacted with {{ emoji }}": "{{ firstUsername }} and {{ secondUsername }} reacted with {{ emoji }}",
|
||||
"{{ firstUsername }} and {{ count }} others reacted with {{ emoji }}": "{{ firstUsername }} and {{ count }} other reacted with {{ emoji }}",
|
||||
"{{ firstUsername }} and {{ count }} others reacted with {{ emoji }}_plural": "{{ firstUsername }} and {{ count }} others reacted with {{ emoji }}",
|
||||
"{{ firstUsername }} and {{ count }} others reacted with {{ emoji }}_one": "{{ firstUsername }} and {{ count }} others reacted with {{ emoji }}",
|
||||
"{{ firstUsername }} and {{ count }} others reacted with {{ emoji }}_many": "{{ firstUsername }} and {{ count }} others reacted with {{ emoji }}",
|
||||
"{{ firstUsername }} and {{ count }} others reacted with {{ emoji }}_other": "{{ firstUsername }} and {{ count }} others reacted with {{ emoji }}",
|
||||
"Add reaction": "Add reaction",
|
||||
"Reaction picker": "Reaction picker",
|
||||
"Could not load reactions": "Could not load reactions",
|
||||
@@ -430,8 +436,9 @@
|
||||
"{{ minutes }}m read": "{{ minutes }}m read",
|
||||
"All members": "All members",
|
||||
"Everyone in the workspace": "Everyone in the workspace",
|
||||
"{{ count }} member": "{{ count }} member",
|
||||
"{{ count }} member_plural": "{{ count }} members",
|
||||
"{{ count }} member_one": "{{ count }} member",
|
||||
"{{ count }} member_many": "{{ count }} member",
|
||||
"{{ count }} member_other": "{{ count }} member",
|
||||
"Public link copied to clipboard": "Public link copied to clipboard",
|
||||
"Only lowercase letters, digits and dashes allowed": "Only lowercase letters, digits and dashes allowed",
|
||||
"Sorry, this link has already been used": "Sorry, this link has already been used",
|
||||
@@ -441,10 +448,12 @@
|
||||
"All documents in this collection will be shared on the web, including any new documents added later": "All documents in this collection will be shared on the web, including any new documents added later",
|
||||
"Invite": "Invite",
|
||||
"{{ userName }} was added to the collection": "{{ userName }} was added to the collection",
|
||||
"{{ count }} people added to the collection": "{{ count }} people added to the collection",
|
||||
"{{ count }} people added to the collection_plural": "{{ count }} people added to the collection",
|
||||
"{{ count }} people and {{ count2 }} groups added to the collection": "{{ count }} people and {{ count2 }} groups added to the collection",
|
||||
"{{ count }} people and {{ count2 }} groups added to the collection_plural": "{{ count }} people and {{ count2 }} groups added to the collection",
|
||||
"{{ count }} people added to the collection_one": "{{ count }} people added to the collection",
|
||||
"{{ count }} people added to the collection_many": "{{ count }} people added to the collection",
|
||||
"{{ count }} people added to the collection_other": "{{ count }} people added to the collection",
|
||||
"{{ count }} people and {{ count2 }} groups added to the collection_one": "{{ count }} people and {{ count2 }} groups added to the collection",
|
||||
"{{ count }} people and {{ count2 }} groups added to the collection_many": "{{ count }} people and {{ count2 }} groups added to the collection",
|
||||
"{{ count }} people and {{ count2 }} groups added to the collection_other": "{{ count }} people and {{ count2 }} groups added to the collection",
|
||||
"Switch to dark": "Switch to dark",
|
||||
"Switch to light": "Switch to light",
|
||||
"Subscribe to updates": "Subscribe to updates",
|
||||
@@ -495,10 +504,12 @@
|
||||
"Anyone with the link can access because the parent document, <2>{sharedParent.sourceTitle}</2>, is shared": "Anyone with the link can access because the parent document, <2>{sharedParent.sourceTitle}</2>, is shared",
|
||||
"Nested documents are not shared on the web. Toggle sharing to enable access, this will be the default behavior in the future": "Nested documents are not shared on the web. Toggle sharing to enable access, this will be the default behavior in the future",
|
||||
"{{ userName }} was added to the document": "{{ userName }} was added to the document",
|
||||
"{{ count }} people added to the document": "{{ count }} people added to the document",
|
||||
"{{ count }} people added to the document_plural": "{{ count }} people added to the document",
|
||||
"{{ count }} groups added to the document": "{{ count }} groups added to the document",
|
||||
"{{ count }} groups added to the document_plural": "{{ count }} groups added to the document",
|
||||
"{{ count }} people added to the document_one": "{{ count }} people added to the document",
|
||||
"{{ count }} people added to the document_many": "{{ count }} people added to the document",
|
||||
"{{ count }} people added to the document_other": "{{ count }} people added to the document",
|
||||
"{{ count }} groups added to the document_one": "{{ count }} groups added to the document",
|
||||
"{{ count }} groups added to the document_many": "{{ count }} groups added to the document",
|
||||
"{{ count }} groups added to the document_other": "{{ count }} groups added to the document",
|
||||
"Expand sidebar": "Expand sidebar",
|
||||
"Collapse sidebar": "Collapse sidebar",
|
||||
"Archived collections": "Archived collections",
|
||||
@@ -520,8 +531,9 @@
|
||||
"Could not load starred documents": "Could not load starred documents",
|
||||
"Starred": "Starred",
|
||||
"Up to date": "Up to date",
|
||||
"{{ releasesBehind }} versions behind": "{{ releasesBehind }} version behind",
|
||||
"{{ releasesBehind }} versions behind_plural": "{{ releasesBehind }} versions behind",
|
||||
"{{ releasesBehind }} versions behind_one": "{{ releasesBehind }} versions behind",
|
||||
"{{ releasesBehind }} versions behind_many": "{{ releasesBehind }} versions behind",
|
||||
"{{ releasesBehind }} versions behind_other": "{{ releasesBehind }} versions behind",
|
||||
"Change permissions?": "Change permissions?",
|
||||
"{{ documentName }} cannot be moved within {{ parentDocumentName }}": "{{ documentName }} cannot be moved within {{ parentDocumentName }}",
|
||||
"You can't reorder documents in an alphabetically sorted collection": "You can't reorder documents in an alphabetically sorted collection",
|
||||
@@ -756,14 +768,18 @@
|
||||
"Done editing": "Done editing",
|
||||
"Drop documents to import": "Drop documents to import",
|
||||
"<em>{{ collectionName }}</em> doesn’t contain any\n documents yet.": "<em>{{ collectionName }}</em> doesn’t contain any\n documents yet.",
|
||||
"{{ usersCount }} users and {{ groupsCount }} groups with access": "{{ usersCount }} user and {{ groupsCount }} groups with access",
|
||||
"{{ usersCount }} users and {{ groupsCount }} groups with access_plural": "{{ usersCount }} users and {{ groupsCount }} groups with access",
|
||||
"{{ usersCount }} users and a group have access": "{{ usersCount }} user and a group have access",
|
||||
"{{ usersCount }} users and a group have access_plural": "{{ usersCount }} users and a group have access",
|
||||
"{{ usersCount }} users with access": "{{ usersCount }} user with access",
|
||||
"{{ usersCount }} users with access_plural": "{{ usersCount }} users with access",
|
||||
"{{ groupsCount }} groups with access": "{{ groupsCount }} group with access",
|
||||
"{{ groupsCount }} groups with access_plural": "{{ groupsCount }} groups with access",
|
||||
"{{ usersCount }} users and {{ groupsCount }} groups with access_one": "{{ usersCount }} users and {{ groupsCount }} groups with access",
|
||||
"{{ usersCount }} users and {{ groupsCount }} groups with access_many": "{{ usersCount }} users and {{ groupsCount }} groups with access",
|
||||
"{{ usersCount }} users and {{ groupsCount }} groups with access_other": "{{ usersCount }} users and {{ groupsCount }} groups with access",
|
||||
"{{ usersCount }} users and a group have access_one": "{{ usersCount }} users and a group have access",
|
||||
"{{ usersCount }} users and a group have access_many": "{{ usersCount }} users and a group have access",
|
||||
"{{ usersCount }} users and a group have access_other": "{{ usersCount }} users and a group have access",
|
||||
"{{ usersCount }} users with access_one": "{{ usersCount }} users with access",
|
||||
"{{ usersCount }} users with access_many": "{{ usersCount }} users with access",
|
||||
"{{ usersCount }} users with access_other": "{{ usersCount }} users with access",
|
||||
"{{ groupsCount }} groups with access_one": "{{ groupsCount }} groups with access",
|
||||
"{{ groupsCount }} groups with access_many": "{{ groupsCount }} groups with access",
|
||||
"{{ groupsCount }} groups with access_other": "{{ groupsCount }} groups with access",
|
||||
"Overview": "Overview",
|
||||
"Popular": "Popular",
|
||||
"Recently updated": "Recently updated",
|
||||
@@ -773,10 +789,12 @@
|
||||
"Archived by {{userName}}": "Archived by {{userName}}",
|
||||
"Sorry, an error occurred saving the collection": "Sorry, an error occurred saving the collection",
|
||||
"Add a description": "Add a description",
|
||||
"{{ current }} of {{ count }} changes": "{{ current }} of {{ count }} changes",
|
||||
"{{ current }} of {{ count }} changes_plural": "{{ current }} of {{ count }} changes",
|
||||
"{{ count }} changes": "{{ count }} change",
|
||||
"{{ count }} changes_plural": "{{ count }} changes",
|
||||
"{{ current }} of {{ count }} changes_one": "{{ current }} of {{ count }} changes",
|
||||
"{{ current }} of {{ count }} changes_many": "{{ current }} of {{ count }} changes",
|
||||
"{{ current }} of {{ count }} changes_other": "{{ current }} of {{ count }} changes",
|
||||
"{{ count }} changes_one": "{{ count }} changes",
|
||||
"{{ count }} changes_many": "{{ count }} changes",
|
||||
"{{ count }} changes_other": "{{ count }} changes",
|
||||
"Previous change": "Previous change",
|
||||
"Next change": "Next change",
|
||||
"Error creating comment": "Error creating comment",
|
||||
@@ -792,8 +810,9 @@
|
||||
"Order in doc": "Order in doc",
|
||||
"Resolved": "Resolved",
|
||||
"Sort comments": "Sort comments",
|
||||
"Show {{ count }} reply": "Show {{ count }} reply",
|
||||
"Show {{ count }} reply_plural": "Show {{ count }} replies",
|
||||
"Show {{ count }} reply_one": "Show {{ count }} reply",
|
||||
"Show {{ count }} reply_many": "Show {{ count }} reply",
|
||||
"Show {{ count }} reply_other": "Show {{ count }} reply",
|
||||
"Error updating comment": "Error updating comment",
|
||||
"Document is too large": "Document is too large",
|
||||
"This document has reached the maximum size and can no longer be edited": "This document has reached the maximum size and can no longer be edited",
|
||||
@@ -810,8 +829,9 @@
|
||||
"Offline": "Offline",
|
||||
"Document restored": "Document restored",
|
||||
"Images are still uploading.\nAre you sure you want to discard them?": "Images are still uploading.\nAre you sure you want to discard them?",
|
||||
"{{ count }} comment": "{{ count }} comment",
|
||||
"{{ count }} comment_plural": "{{ count }} comments",
|
||||
"{{ count }} comment_one": "{{ count }} comment",
|
||||
"{{ count }} comment_many": "{{ count }} comment",
|
||||
"{{ count }} comment_other": "{{ count }} comment",
|
||||
"Viewed by": "Viewed by",
|
||||
"only you": "only you",
|
||||
"person": "person",
|
||||
@@ -842,30 +862,36 @@
|
||||
"Revision deleted": "Revision deleted",
|
||||
"Current version": "Current version",
|
||||
"{{userName}} edited": "{{userName}} edited",
|
||||
"{{count}} people": "{{count}} person",
|
||||
"{{count}} people_plural": "{{count}} people",
|
||||
"{{count}} people_one": "{{count}} people",
|
||||
"{{count}} people_many": "{{count}} people",
|
||||
"{{count}} people_other": "{{count}} people",
|
||||
"Source": "Source",
|
||||
"Created": "Created",
|
||||
"Imported from {{ source }}": "Imported from {{ source }}",
|
||||
"Stats": "Stats",
|
||||
"{{ number }} minute read": "{{ number }} minute read",
|
||||
"{{ number }} words": "{{ number }} word",
|
||||
"{{ number }} words_plural": "{{ number }} words",
|
||||
"{{ number }} characters": "{{ number }} character",
|
||||
"{{ number }} characters_plural": "{{ number }} characters",
|
||||
"{{ number }} words_one": "{{ number }} words",
|
||||
"{{ number }} words_many": "{{ number }} words",
|
||||
"{{ number }} words_other": "{{ number }} words",
|
||||
"{{ number }} characters_one": "{{ number }} characters",
|
||||
"{{ number }} characters_many": "{{ number }} characters",
|
||||
"{{ number }} characters_other": "{{ number }} characters",
|
||||
"{{ number }} emoji": "{{ number }} emoji",
|
||||
"No text selected": "No text selected",
|
||||
"{{ number }} words selected": "{{ number }} word selected",
|
||||
"{{ number }} words selected_plural": "{{ number }} words selected",
|
||||
"{{ number }} characters selected": "{{ number }} character selected",
|
||||
"{{ number }} characters selected_plural": "{{ number }} characters selected",
|
||||
"{{ number }} words selected_one": "{{ number }} words selected",
|
||||
"{{ number }} words selected_many": "{{ number }} words selected",
|
||||
"{{ number }} words selected_other": "{{ number }} words selected",
|
||||
"{{ number }} characters selected_one": "{{ number }} characters selected",
|
||||
"{{ number }} characters selected_many": "{{ number }} characters selected",
|
||||
"{{ number }} characters selected_other": "{{ number }} characters selected",
|
||||
"Contributors": "Contributors",
|
||||
"Creator": "Creator",
|
||||
"Last edited": "Last edited",
|
||||
"Previously edited": "Previously edited",
|
||||
"Sorry, the last change could not be persisted – please reload the page": "Sorry, the last change could not be persisted – please reload the page",
|
||||
"{{ count }} days": "{{ count }} day",
|
||||
"{{ count }} days_plural": "{{ count }} days",
|
||||
"{{ count }} days_one": "{{ count }} days",
|
||||
"{{ count }} days_many": "{{ count }} days",
|
||||
"{{ count }} days_other": "{{ count }} days",
|
||||
"This document will be permanently deleted in <2></2> unless restored.": "This document will be permanently deleted in <2></2> unless restored.",
|
||||
"Deleted by {{userName}}": "Deleted by {{userName}}",
|
||||
"Observing {{ userName }}": "Observing {{ userName }}",
|
||||
@@ -880,8 +906,9 @@
|
||||
"Warning": "Warning",
|
||||
"This document is large which may affect performance": "This document is large which may affect performance",
|
||||
"Are you sure about that? Deleting the <em>{{ documentTitle }}</em> document will delete all of its history</em>.": "Are you sure about that? Deleting the <em>{{ documentTitle }}</em> document will delete all of its history</em>.",
|
||||
"Are you sure about that? Deleting the <em>{{ documentTitle }}</em> document will delete all of its history and <em>{{ any }} nested document</em>.": "Are you sure about that? Deleting the <em>{{ documentTitle }}</em> document will delete all of its history and <em>{{ any }} nested document</em>.",
|
||||
"Are you sure about that? Deleting the <em>{{ documentTitle }}</em> document will delete all of its history and <em>{{ any }} nested document</em>._plural": "Are you sure about that? Deleting the <em>{{ documentTitle }}</em> document will delete all of its history and <em>{{ any }} nested documents</em>.",
|
||||
"Are you sure about that? Deleting the <em>{{ documentTitle }}</em> document will delete all of its history and <em>{{ any }} nested document</em>._one": "Are you sure about that? Deleting the <em>{{ documentTitle }}</em> document will delete all of its history and <em>{{ any }} nested document</em>.",
|
||||
"Are you sure about that? Deleting the <em>{{ documentTitle }}</em> document will delete all of its history and <em>{{ any }} nested document</em>._many": "Are you sure about that? Deleting the <em>{{ documentTitle }}</em> document will delete all of its history and <em>{{ any }} nested document</em>.",
|
||||
"Are you sure about that? Deleting the <em>{{ documentTitle }}</em> document will delete all of its history and <em>{{ any }} nested document</em>._other": "Are you sure about that? Deleting the <em>{{ documentTitle }}</em> document will delete all of its history and <em>{{ any }} nested document</em>.",
|
||||
"If you’d like the option of referencing or restoring the {{noun}} in the future, consider archiving it instead.": "If you’d like the option of referencing or restoring the {{noun}} in the future, consider archiving it instead.",
|
||||
"Couldn’t create the document, try again?": "Couldn’t create the document, try again?",
|
||||
"Document permanently deleted": "Document permanently deleted",
|
||||
@@ -913,8 +940,9 @@
|
||||
"Documents with recent activity will appear here": "Documents with recent activity will appear here",
|
||||
"You haven’t created any documents yet": "You haven’t created any documents yet",
|
||||
"Documents you’ve recently viewed will be here for easy access": "Documents you’ve recently viewed will be here for easy access",
|
||||
"{{ count }} invites sent": "{{ count }} invites sent",
|
||||
"{{ count }} invites sent_plural": "{{ count }} invites sent",
|
||||
"{{ count }} invites sent_one": "{{ count }} invites sent",
|
||||
"{{ count }} invites sent_many": "{{ count }} invites sent",
|
||||
"{{ count }} invites sent_other": "{{ count }} invites sent",
|
||||
"Those email addresses are already invited": "Those email addresses are already invited",
|
||||
"Sorry, you can only send {{MAX_INVITES}} invites at a time": "Sorry, you can only send {{MAX_INVITES}} invites at a time",
|
||||
"Invited {{roleName}} will receive access to": "Invited {{roleName}} will receive access to",
|
||||
@@ -1220,6 +1248,7 @@
|
||||
"All sources": "All sources",
|
||||
"Manual": "Manual",
|
||||
"This group is hidden": "This group is hidden",
|
||||
"{{ count }} member": "{{ count }} member",
|
||||
"Synced <2></2>": "Synced <2></2>",
|
||||
"Date created": "Date created",
|
||||
"Crop Image": "Crop Image",
|
||||
@@ -1231,8 +1260,9 @@
|
||||
"Are you sure you want to cancel this import?": "Are you sure you want to cancel this import?",
|
||||
"Canceling": "Canceling",
|
||||
"Canceling this import will discard any progress made. This cannot be undone.": "Canceling this import will discard any progress made. This cannot be undone.",
|
||||
"{{ count }} document imported": "{{ count }} document imported",
|
||||
"{{ count }} document imported_plural": "{{ count }} documents imported",
|
||||
"{{ count }} document imported_one": "{{ count }} document imported",
|
||||
"{{ count }} document imported_many": "{{ count }} document imported",
|
||||
"{{ count }} document imported_other": "{{ count }} document imported",
|
||||
"You can import a zip file that was previously exported from an Outline installation – collections, documents, and images will be imported. In Outline, open <em>Export</em> in the Settings sidebar and click on <em>Export Data</em>.": "You can import a zip file that was previously exported from an Outline installation – collections, documents, and images will be imported. In Outline, open <em>Export</em> in the Settings sidebar and click on <em>Export Data</em>.",
|
||||
"Drag and drop the zip file from the Markdown export option in {{appName}}, or click to upload": "Drag and drop the zip file from the Markdown export option in {{appName}}, or click to upload",
|
||||
"Configure": "Configure",
|
||||
@@ -1780,11 +1810,13 @@
|
||||
"Open": "Open",
|
||||
"Loading": "Loading",
|
||||
"Error loading data": "Error loading data",
|
||||
"Show {{ count }} completed": "Show {{ count }} completed",
|
||||
"Show {{ count }} completed_plural": "Show {{ count }} completed",
|
||||
"Show {{ count }} completed_one": "Show {{ count }} completed",
|
||||
"Show {{ count }} completed_many": "Show {{ count }} completed",
|
||||
"Show {{ count }} completed_other": "Show {{ count }} completed",
|
||||
"Hide completed": "Hide completed",
|
||||
"Write a caption": "Write a caption",
|
||||
"Add title": "Add title",
|
||||
"Add content": "Add content",
|
||||
"Tomorrow": "Tomorrow"
|
||||
"Tomorrow": "Tomorrow",
|
||||
"{{ count }} member_plural": "{{ count }} members"
|
||||
}
|
||||
|
||||
@@ -9,6 +9,11 @@ class Storage {
|
||||
|
||||
public constructor() {
|
||||
try {
|
||||
// Avoid touching the `localStorage` global outside the browser; in Node it
|
||||
// resolves to an experimental Web Storage API that emits a warning on access.
|
||||
if (typeof window === "undefined") {
|
||||
throw new Error("localStorage is not available");
|
||||
}
|
||||
localStorage.setItem("test", "test");
|
||||
localStorage.removeItem("test");
|
||||
this.interface = localStorage;
|
||||
|
||||
+22
-18
@@ -1,5 +1,5 @@
|
||||
import path from "node:path";
|
||||
import babel from "vite-plugin-babel";
|
||||
import swc from "unplugin-swc";
|
||||
import { defineConfig } from "vitest/config";
|
||||
|
||||
const aliases = {
|
||||
@@ -11,28 +11,32 @@ const aliases = {
|
||||
|
||||
const fileMock = path.resolve(__dirname, "./__mocks__/fileMock.js");
|
||||
|
||||
const babelPlugin = () =>
|
||||
babel({
|
||||
include: /\.(t|j)sx?$/,
|
||||
babelConfig: {
|
||||
babelrc: false,
|
||||
configFile: false,
|
||||
sourceMaps: "inline",
|
||||
presets: [
|
||||
["@babel/preset-react", { runtime: "automatic" }],
|
||||
["@babel/preset-typescript", { allowDeclareFields: true }],
|
||||
],
|
||||
plugins: [
|
||||
"babel-plugin-transform-typescript-metadata",
|
||||
["@babel/plugin-proposal-decorators", { legacy: true }],
|
||||
"@babel/plugin-transform-class-properties",
|
||||
],
|
||||
// Mirrors the server build's SWC config (.swcrc). `decoratorMetadata` stays off
|
||||
// because every @Column has an explicit DataType, and emitting it would throw
|
||||
// on the circular model graph; `useDefineForClassFields:false` keeps bare class
|
||||
// fields from shadowing MobX observables. `tsconfigFile:false` stops the plugin
|
||||
// re-deriving (and re-enabling metadata) from tsconfig.json.
|
||||
const swcPlugin = () =>
|
||||
swc.vite({
|
||||
tsconfigFile: false,
|
||||
jsc: {
|
||||
parser: { syntax: "typescript", tsx: true, decorators: true },
|
||||
transform: {
|
||||
legacyDecorator: true,
|
||||
decoratorMetadata: false,
|
||||
useDefineForClassFields: false,
|
||||
react: { runtime: "automatic" },
|
||||
},
|
||||
keepClassNames: true,
|
||||
target: "es2020",
|
||||
},
|
||||
// Preserve ES module syntax so Vite resolves imports (e.g. ./rules → .ts).
|
||||
module: { type: "es6" },
|
||||
});
|
||||
|
||||
const sharedConfig = {
|
||||
resolve: { alias: aliases },
|
||||
plugins: [babelPlugin()],
|
||||
plugins: [swcPlugin()],
|
||||
esbuild: false as const,
|
||||
oxc: false as const,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user