mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-07-02 02:00:49 +08:00
Compare commits
3 Commits
2135b2e0c8
...
v0.26.6
| Author | SHA1 | Date | |
|---|---|---|---|
| 43704d60fb | |||
| 46e7e35357 | |||
| b98ab495bb |
@@ -62,6 +62,18 @@
|
||||
"concurrency": 10
|
||||
}
|
||||
},
|
||||
"queues.calendar": {
|
||||
"type": "object",
|
||||
"description": "The config for calendar job queue\n@default {\"concurrency\":4}",
|
||||
"properties": {
|
||||
"concurrency": {
|
||||
"type": "number"
|
||||
}
|
||||
},
|
||||
"default": {
|
||||
"concurrency": 4
|
||||
}
|
||||
},
|
||||
"queues.doc": {
|
||||
"type": "object",
|
||||
"description": "The config for doc job queue\n@default {\"concurrency\":1}",
|
||||
@@ -843,7 +855,7 @@
|
||||
"properties": {
|
||||
"google": {
|
||||
"type": "object",
|
||||
"description": "Google Calendar integration config\n@default {\"enabled\":false,\"clientId\":\"\",\"clientSecret\":\"\",\"externalWebhookUrl\":\"\",\"webhookVerificationToken\":\"\"}\n@link https://developers.google.com/calendar/api/guides/push",
|
||||
"description": "Google Calendar integration config\n@default {\"enabled\":false,\"clientId\":\"\",\"clientSecret\":\"\",\"externalWebhookUrl\":\"\",\"webhookVerificationToken\":\"\",\"requestTimeoutMs\":10000}\n@link https://developers.google.com/calendar/api/guides/push",
|
||||
"properties": {
|
||||
"enabled": {
|
||||
"type": "boolean"
|
||||
@@ -859,6 +871,9 @@
|
||||
},
|
||||
"webhookVerificationToken": {
|
||||
"type": "string"
|
||||
},
|
||||
"requestTimeoutMs": {
|
||||
"type": "number"
|
||||
}
|
||||
},
|
||||
"default": {
|
||||
@@ -866,7 +881,8 @@
|
||||
"clientId": "",
|
||||
"clientSecret": "",
|
||||
"externalWebhookUrl": "",
|
||||
"webhookVerificationToken": ""
|
||||
"webhookVerificationToken": "",
|
||||
"requestTimeoutMs": 10000
|
||||
}
|
||||
},
|
||||
"caldav": {
|
||||
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
-- AlterTable
|
||||
ALTER TABLE
|
||||
"calendar_subscriptions"
|
||||
ADD
|
||||
COLUMN "next_sync_at" TIMESTAMPTZ(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
ADD
|
||||
COLUMN "sync_retry_count" INTEGER NOT NULL DEFAULT 0;
|
||||
|
||||
UPDATE
|
||||
"calendar_subscriptions" AS s
|
||||
SET
|
||||
"next_sync_at" = CASE
|
||||
WHEN s."last_sync_at" IS NULL THEN CURRENT_TIMESTAMP
|
||||
ELSE s."last_sync_at" + make_interval(
|
||||
mins => COALESCE(a."refresh_interval_minutes", 30)
|
||||
)
|
||||
END
|
||||
FROM
|
||||
"calendar_accounts" AS a
|
||||
WHERE
|
||||
a."id" = s."account_id";
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "calendar_subscriptions_custom_channel_id_idx" ON "calendar_subscriptions"("custom_channel_id");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "calendar_subscriptions_enabled_next_sync_at_idx" ON "calendar_subscriptions"("enabled", "next_sync_at");
|
||||
@@ -110,7 +110,7 @@
|
||||
"react-dom": "19.2.1",
|
||||
"reflect-metadata": "^0.2.2",
|
||||
"rxjs": "^7.8.2",
|
||||
"semver": "^7.7.3",
|
||||
"semver": "^7.7.4",
|
||||
"ses": "^1.14.0",
|
||||
"socket.io": "^4.8.1",
|
||||
"stripe": "^17.7.0",
|
||||
@@ -138,8 +138,7 @@
|
||||
"@types/nodemailer": "^7.0.0",
|
||||
"@types/on-headers": "^1.0.3",
|
||||
"@types/react": "^19.0.1",
|
||||
"@types/react-dom": "^19.0.2",
|
||||
"@types/semver": "^7.5.8",
|
||||
"@types/semver": "^7.7.1",
|
||||
"@types/sinon": "^21.0.0",
|
||||
"@types/supertest": "^6.0.2",
|
||||
"ava": "^6.4.0",
|
||||
|
||||
@@ -1037,6 +1037,8 @@ model CalendarSubscription {
|
||||
enabled Boolean @default(true)
|
||||
syncToken String? @map("sync_token") @db.Text
|
||||
lastSyncAt DateTime? @map("last_sync_at") @db.Timestamptz(3)
|
||||
nextSyncAt DateTime @default(now()) @map("next_sync_at") @db.Timestamptz(3)
|
||||
syncRetryCount Int @default(0) @map("sync_retry_count")
|
||||
customChannelId String? @map("custom_channel_id") @db.VarChar
|
||||
customResourceId String? @map("custom_resource_id") @db.VarChar
|
||||
channelExpiration DateTime? @map("channel_expiration") @db.Timestamptz(3)
|
||||
@@ -1050,6 +1052,8 @@ model CalendarSubscription {
|
||||
@@unique([accountId, externalCalendarId])
|
||||
@@index([accountId])
|
||||
@@index([provider, externalCalendarId])
|
||||
@@index([customChannelId])
|
||||
@@index([enabled, nextSyncAt])
|
||||
@@map("calendar_subscriptions")
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ import { AppModule } from '../app.module';
|
||||
import {
|
||||
CANARY_CLIENT_VERSION_MAX_AGE_DAYS,
|
||||
ConfigFactory,
|
||||
hasNewerVersion,
|
||||
UseNamedGuard,
|
||||
} from '../base';
|
||||
import { Public } from '../core/auth/guard';
|
||||
@@ -249,3 +250,11 @@ test('should reject old canary date version in canary namespace', async t => {
|
||||
env.NAMESPACE = prevNamespace;
|
||||
}
|
||||
});
|
||||
|
||||
test('should compare release versions for available upgrades', t => {
|
||||
t.false(hasNewerVersion('0.26.5', '0.26.4'));
|
||||
t.false(hasNewerVersion('0.26.5', '0.26.5'));
|
||||
t.true(hasNewerVersion('0.26.5', '0.26.6'));
|
||||
t.true(hasNewerVersion('0.26.5', '0.26.6-beta.1'));
|
||||
t.false(hasNewerVersion('0.26.6-beta.2', '0.26.6-beta.1'));
|
||||
});
|
||||
|
||||
@@ -55,6 +55,14 @@ defineModuleConfig('job', {
|
||||
schema,
|
||||
},
|
||||
|
||||
'queues.calendar': {
|
||||
desc: 'The config for calendar job queue',
|
||||
default: {
|
||||
concurrency: 4,
|
||||
},
|
||||
schema,
|
||||
},
|
||||
|
||||
'queues.doc': {
|
||||
desc: 'The config for doc job queue',
|
||||
default: {
|
||||
|
||||
@@ -28,6 +28,7 @@ export enum Queue {
|
||||
DOC = 'doc',
|
||||
COPILOT = 'copilot',
|
||||
INDEXER = 'indexer',
|
||||
CALENDAR = 'calendar',
|
||||
}
|
||||
|
||||
export const QUEUES = Object.values(Queue);
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import semver from 'semver';
|
||||
|
||||
const DAY_MS = 24 * 60 * 60 * 1000;
|
||||
|
||||
// Example: 2026.2.6-canary.015
|
||||
@@ -89,3 +91,26 @@ export function checkCanaryDateClientVersion(
|
||||
normalized: parsed.normalized,
|
||||
};
|
||||
}
|
||||
|
||||
function normalizeComparableVersion(version: string): string | null {
|
||||
const canary = parseCanaryDateClientVersion(version);
|
||||
return semver.valid(canary?.normalized ?? version.trim(), {
|
||||
loose: true,
|
||||
});
|
||||
}
|
||||
|
||||
export function hasNewerVersion(
|
||||
currentVersion: string,
|
||||
nextVersion: string
|
||||
): boolean {
|
||||
const current = normalizeComparableVersion(currentVersion);
|
||||
const next = normalizeComparableVersion(nextVersion);
|
||||
|
||||
if (!current || !next) {
|
||||
return currentVersion.trim() !== nextVersion.trim();
|
||||
}
|
||||
|
||||
return semver.gt(next, current, {
|
||||
loose: true,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ import {
|
||||
} from '@nestjs/graphql';
|
||||
import { GraphQLJSON, GraphQLJSONObject } from 'graphql-scalars';
|
||||
|
||||
import { Config, URLHelper } from '../../base';
|
||||
import { Config, hasNewerVersion, URLHelper } from '../../base';
|
||||
import { Namespace } from '../../env';
|
||||
import { Feature, type WorkspaceFeatureName } from '../../models';
|
||||
import { CurrentUser, Public } from '../auth';
|
||||
@@ -143,7 +143,7 @@ export class ServerConfigResolver {
|
||||
}>;
|
||||
|
||||
const latest = releases.at(0);
|
||||
if (!latest || latest.name === env.version) {
|
||||
if (!latest || !hasNewerVersion(env.version, latest.name)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -92,7 +92,7 @@ export class CalendarAccountModel extends BaseModel {
|
||||
scope: input.scope ?? null,
|
||||
status: input.status ?? 'active',
|
||||
lastError: input.lastError ?? null,
|
||||
refreshIntervalMinutes: input.refreshIntervalMinutes ?? 60,
|
||||
refreshIntervalMinutes: input.refreshIntervalMinutes ?? 30,
|
||||
};
|
||||
|
||||
const updateData: Prisma.CalendarAccountUncheckedUpdateInput = {
|
||||
|
||||
@@ -17,6 +17,8 @@ export interface UpsertCalendarSubscriptionInput {
|
||||
export interface UpdateCalendarSubscriptionSyncInput {
|
||||
syncToken?: string | null;
|
||||
lastSyncAt?: Date | null;
|
||||
nextSyncAt?: Date;
|
||||
syncRetryCount?: number;
|
||||
}
|
||||
|
||||
export interface UpdateCalendarSubscriptionChannelInput {
|
||||
@@ -81,13 +83,21 @@ export class CalendarSubscriptionModel extends BaseModel {
|
||||
}
|
||||
|
||||
async updateSync(id: string, input: UpdateCalendarSubscriptionSyncInput) {
|
||||
return await this.db.calendarSubscription.update({
|
||||
where: { id },
|
||||
data: {
|
||||
syncToken: input.syncToken ?? null,
|
||||
lastSyncAt: input.lastSyncAt ?? null,
|
||||
},
|
||||
});
|
||||
const data: Prisma.CalendarSubscriptionUncheckedUpdateInput = {};
|
||||
if (input.syncToken !== undefined) {
|
||||
data.syncToken = input.syncToken ?? null;
|
||||
}
|
||||
if (input.lastSyncAt !== undefined) {
|
||||
data.lastSyncAt = input.lastSyncAt ?? null;
|
||||
}
|
||||
if (input.nextSyncAt !== undefined) {
|
||||
data.nextSyncAt = input.nextSyncAt;
|
||||
}
|
||||
if (input.syncRetryCount !== undefined) {
|
||||
data.syncRetryCount = input.syncRetryCount;
|
||||
}
|
||||
|
||||
return await this.db.calendarSubscription.update({ where: { id }, data });
|
||||
}
|
||||
|
||||
async updateChannel(
|
||||
@@ -155,10 +165,16 @@ export class CalendarSubscriptionModel extends BaseModel {
|
||||
});
|
||||
}
|
||||
|
||||
async listAllWithAccountForSync() {
|
||||
async listDueForSync(now: Date, limit: number) {
|
||||
return await this.db.calendarSubscription.findMany({
|
||||
where: { enabled: true },
|
||||
include: { account: true },
|
||||
where: {
|
||||
enabled: true,
|
||||
nextSyncAt: { lte: now },
|
||||
account: { status: 'active' },
|
||||
},
|
||||
select: { id: true },
|
||||
orderBy: { nextSyncAt: 'asc' },
|
||||
take: limit,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -169,13 +185,6 @@ export class CalendarSubscriptionModel extends BaseModel {
|
||||
});
|
||||
}
|
||||
|
||||
async updateLastSyncAt(id: string, lastSyncAt: Date) {
|
||||
return await this.db.calendarSubscription.update({
|
||||
where: { id },
|
||||
data: { lastSyncAt },
|
||||
});
|
||||
}
|
||||
|
||||
async clearSyncTokensByAccount(accountId: string) {
|
||||
return await this.db.calendarSubscription.updateMany({
|
||||
where: { accountId },
|
||||
@@ -200,6 +209,7 @@ export class CalendarSubscriptionModel extends BaseModel {
|
||||
data: {
|
||||
enabled: false,
|
||||
syncToken: null,
|
||||
syncRetryCount: 0,
|
||||
customChannelId: null,
|
||||
customResourceId: null,
|
||||
channelExpiration: null,
|
||||
|
||||
@@ -14,6 +14,7 @@ import type {
|
||||
} from '../../../models';
|
||||
import { Models } from '../../../models';
|
||||
import { CalendarModule } from '../index';
|
||||
import { CalendarCronJobs } from '../cron';
|
||||
import {
|
||||
CalendarProvider,
|
||||
CalendarProviderFactory,
|
||||
@@ -85,6 +86,7 @@ const module = await createModule({
|
||||
],
|
||||
});
|
||||
const calendarService = module.get(CalendarService);
|
||||
const calendarCronJobs = module.get(CalendarCronJobs);
|
||||
const providerFactory = module.get(CalendarProviderFactory);
|
||||
const models = module.get(Models);
|
||||
module.get(CryptoHelper).onConfigInit();
|
||||
@@ -113,6 +115,8 @@ const createSubscription = async (
|
||||
accountId: string,
|
||||
overrides: Partial<UpsertCalendarSubscriptionInput> & {
|
||||
syncToken?: string | null;
|
||||
nextSyncAt?: Date;
|
||||
syncRetryCount?: number;
|
||||
customChannelId?: string | null;
|
||||
customResourceId?: string | null;
|
||||
channelExpiration?: Date | null;
|
||||
@@ -134,6 +138,20 @@ const createSubscription = async (
|
||||
});
|
||||
}
|
||||
|
||||
if (
|
||||
overrides.nextSyncAt !== undefined ||
|
||||
overrides.syncRetryCount !== undefined
|
||||
) {
|
||||
await models.calendarSubscription.updateSync(subscription.id, {
|
||||
...(overrides.nextSyncAt !== undefined
|
||||
? { nextSyncAt: overrides.nextSyncAt }
|
||||
: {}),
|
||||
...(overrides.syncRetryCount !== undefined
|
||||
? { syncRetryCount: overrides.syncRetryCount }
|
||||
: {}),
|
||||
});
|
||||
}
|
||||
|
||||
if (
|
||||
overrides.customChannelId !== undefined ||
|
||||
overrides.customResourceId !== undefined ||
|
||||
@@ -151,6 +169,8 @@ const createSubscription = async (
|
||||
|
||||
test.afterEach.always(() => {
|
||||
mock.reset();
|
||||
module.queue.add.resetHistory();
|
||||
module.queue.remove.resetHistory();
|
||||
});
|
||||
|
||||
test.after.always(async () => {
|
||||
@@ -252,6 +272,9 @@ test('syncSubscription resets invalid sync token and maps events', async t => {
|
||||
const updated = await models.calendarSubscription.get(subscription.id);
|
||||
t.is(updated?.syncToken, 'next-token');
|
||||
t.truthy(updated?.lastSyncAt);
|
||||
t.is(updated?.syncRetryCount, 0);
|
||||
t.truthy(updated?.nextSyncAt);
|
||||
t.true(updated!.nextSyncAt.getTime() > updated!.lastSyncAt!.getTime());
|
||||
|
||||
const events = await models.calendarEvent.listBySubscriptionsInRange(
|
||||
[subscription.id],
|
||||
@@ -493,51 +516,22 @@ test('syncSubscription applies exponential backoff for repeated failures', async
|
||||
mock.method(Date, 'now', () => now);
|
||||
|
||||
await calendarService.syncSubscription(subscription.id);
|
||||
await calendarService.syncSubscription(subscription.id);
|
||||
let updated = await models.calendarSubscription.get(subscription.id);
|
||||
t.is(listEventsMock.mock.callCount(), 1);
|
||||
t.is(updated?.syncRetryCount, 1);
|
||||
t.is(
|
||||
updated?.nextSyncAt.toISOString(),
|
||||
new Date(now + baseDelayMs).toISOString()
|
||||
);
|
||||
|
||||
now += baseDelayMs + 1000;
|
||||
await calendarService.syncSubscription(subscription.id);
|
||||
updated = await models.calendarSubscription.get(subscription.id);
|
||||
t.is(listEventsMock.mock.callCount(), 2);
|
||||
|
||||
now += baseDelayMs + 1000;
|
||||
await calendarService.syncSubscription(subscription.id);
|
||||
t.is(listEventsMock.mock.callCount(), 2);
|
||||
});
|
||||
|
||||
test('syncSubscription skips token refresh while in backoff window', async t => {
|
||||
let now = new Date('2026-01-01T00:00:00.000Z').getTime();
|
||||
mock.method(Date, 'now', () => now);
|
||||
|
||||
const user = await module.create(Mockers.User);
|
||||
const account = await createAccount(user.id, {
|
||||
accessToken: 'expired-access-token',
|
||||
expiresAt: new Date(now - 5 * 60 * 1000),
|
||||
});
|
||||
const subscription = await createSubscription(account.id, {
|
||||
syncToken: 'sync-token',
|
||||
});
|
||||
|
||||
const provider = new MockCalendarProvider();
|
||||
const refreshMock = mock.method(provider, 'refreshTokens', async () => ({
|
||||
accessToken: `refreshed-${randomUUID()}`,
|
||||
}));
|
||||
const listEventsMock = mock.method(provider, 'listEvents', async () => {
|
||||
throw new Error('upstream timeout');
|
||||
});
|
||||
mock.method(providerFactory, 'get', () => provider);
|
||||
|
||||
const baseDelayMs = 5 * 60 * 1000;
|
||||
|
||||
await calendarService.syncSubscription(subscription.id);
|
||||
await calendarService.syncSubscription(subscription.id);
|
||||
t.is(refreshMock.mock.callCount(), 1);
|
||||
t.is(listEventsMock.mock.callCount(), 1);
|
||||
|
||||
now += baseDelayMs + 1000;
|
||||
await calendarService.syncSubscription(subscription.id);
|
||||
t.is(refreshMock.mock.callCount(), 2);
|
||||
t.is(listEventsMock.mock.callCount(), 2);
|
||||
t.is(updated?.syncRetryCount, 2);
|
||||
t.is(
|
||||
updated?.nextSyncAt.toISOString(),
|
||||
new Date(now + baseDelayMs * 2).toISOString()
|
||||
);
|
||||
});
|
||||
|
||||
test('syncSubscription renews webhook channel when expiring', async t => {
|
||||
@@ -599,3 +593,73 @@ test('syncSubscription renews webhook channel when expiring', async t => {
|
||||
t.is(updated?.customResourceId, 'new-resource');
|
||||
t.truthy(updated?.channelExpiration);
|
||||
});
|
||||
|
||||
test('syncSubscription keeps schedule moving when webhook renewal fails', async t => {
|
||||
const now = new Date('2026-01-01T00:00:00.000Z').getTime();
|
||||
mock.method(Date, 'now', () => now);
|
||||
|
||||
const user = await module.create(Mockers.User);
|
||||
const account = await createAccount(user.id, {
|
||||
refreshIntervalMinutes: 60,
|
||||
});
|
||||
const subscription = await createSubscription(account.id, {
|
||||
syncToken: 'sync-token',
|
||||
channelExpiration: new Date(Date.now() + 60 * 60 * 1000),
|
||||
});
|
||||
|
||||
const provider = new MockCalendarProvider();
|
||||
mock.method(provider, 'listEvents', async () => ({
|
||||
events: [],
|
||||
nextSyncToken: 'next-sync',
|
||||
}));
|
||||
mock.method(provider, 'watchCalendar', async () => {
|
||||
throw new Error('watch failed');
|
||||
});
|
||||
mock.method(providerFactory, 'get', () => provider);
|
||||
|
||||
await calendarService.syncSubscription(subscription.id);
|
||||
|
||||
const updated = await models.calendarSubscription.get(subscription.id);
|
||||
t.truthy(updated?.lastSyncAt);
|
||||
t.is(updated?.syncRetryCount, 0);
|
||||
t.is(
|
||||
updated?.nextSyncAt.toISOString(),
|
||||
new Date(now + 15 * 60 * 1000).toISOString()
|
||||
);
|
||||
});
|
||||
|
||||
test('pollAccounts skips when nothing is due', async t => {
|
||||
mock.method(models.calendarSubscription, 'listDueForSync', async () => []);
|
||||
|
||||
await calendarCronJobs.pollAccounts();
|
||||
|
||||
t.is(module.queue.count('calendar.syncSubscription'), 0);
|
||||
});
|
||||
|
||||
test('pollAccounts enqueues due subscriptions only', async t => {
|
||||
mock.method(models.calendarSubscription, 'listDueForSync', async () => [
|
||||
{ id: 'due-subscription-a' },
|
||||
{ id: 'due-subscription-b' },
|
||||
]);
|
||||
|
||||
await calendarCronJobs.pollAccounts();
|
||||
|
||||
t.is(module.queue.count('calendar.syncSubscription'), 2);
|
||||
t.deepEqual(
|
||||
module.queue.add
|
||||
.getCalls()
|
||||
.map(call => [call.args[0], call.args[1], call.args[2]]),
|
||||
[
|
||||
[
|
||||
'calendar.syncSubscription',
|
||||
{ subscriptionId: 'due-subscription-a', reason: 'polling' },
|
||||
{ jobId: 'due-subscription-a' },
|
||||
],
|
||||
[
|
||||
'calendar.syncSubscription',
|
||||
{ subscriptionId: 'due-subscription-b', reason: 'polling' },
|
||||
{ jobId: 'due-subscription-b' },
|
||||
],
|
||||
]
|
||||
);
|
||||
});
|
||||
|
||||
@@ -8,6 +8,7 @@ export interface CalendarGoogleConfig {
|
||||
clientSecret: string;
|
||||
externalWebhookUrl?: string;
|
||||
webhookVerificationToken?: string;
|
||||
requestTimeoutMs?: number;
|
||||
}
|
||||
|
||||
export type CalendarCalDAVAuthType = 'auto' | 'basic' | 'digest';
|
||||
@@ -49,6 +50,7 @@ const schema: JSONSchema = {
|
||||
clientSecret: { type: 'string' },
|
||||
externalWebhookUrl: { type: 'string' },
|
||||
webhookVerificationToken: { type: 'string' },
|
||||
requestTimeoutMs: { type: 'number' },
|
||||
},
|
||||
};
|
||||
|
||||
@@ -88,6 +90,7 @@ defineModuleConfig('calendar', {
|
||||
clientSecret: '',
|
||||
externalWebhookUrl: '',
|
||||
webhookVerificationToken: '',
|
||||
requestTimeoutMs: 10_000,
|
||||
},
|
||||
schema,
|
||||
shape: z.object({
|
||||
@@ -101,6 +104,7 @@ defineModuleConfig('calendar', {
|
||||
.or(z.string().length(0))
|
||||
.optional(),
|
||||
webhookVerificationToken: z.string().optional(),
|
||||
requestTimeoutMs: z.number().int().positive().optional(),
|
||||
}),
|
||||
link: 'https://developers.google.com/calendar/api/guides/push',
|
||||
},
|
||||
|
||||
@@ -1,61 +1,33 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { Cron, CronExpression } from '@nestjs/schedule';
|
||||
|
||||
import { JobQueue } from '../../base';
|
||||
import { Models } from '../../models';
|
||||
import { CalendarService } from './service';
|
||||
|
||||
const CALENDAR_POLL_BATCH_SIZE = 200;
|
||||
|
||||
@Injectable()
|
||||
export class CalendarCronJobs {
|
||||
constructor(
|
||||
private readonly models: Models,
|
||||
private readonly calendar: CalendarService
|
||||
private readonly queue: JobQueue
|
||||
) {}
|
||||
|
||||
@Cron(CronExpression.EVERY_MINUTE)
|
||||
async pollAccounts() {
|
||||
const subscriptions =
|
||||
await this.models.calendarSubscription.listAllWithAccountForSync();
|
||||
const subscriptions = await this.models.calendarSubscription.listDueForSync(
|
||||
new Date(),
|
||||
CALENDAR_POLL_BATCH_SIZE
|
||||
);
|
||||
|
||||
const accountDueAt = new Map<
|
||||
string,
|
||||
{ refreshInterval: number; lastSyncAt: Date | null }
|
||||
>();
|
||||
|
||||
for (const subscription of subscriptions) {
|
||||
const interval = subscription.account.refreshIntervalMinutes ?? 60;
|
||||
const lastSyncAt = subscription.lastSyncAt ?? null;
|
||||
const existing = accountDueAt.get(subscription.accountId);
|
||||
if (!existing) {
|
||||
accountDueAt.set(subscription.accountId, {
|
||||
refreshInterval: interval,
|
||||
lastSyncAt,
|
||||
});
|
||||
continue;
|
||||
}
|
||||
|
||||
const earliest =
|
||||
existing.lastSyncAt && lastSyncAt
|
||||
? existing.lastSyncAt < lastSyncAt
|
||||
? existing.lastSyncAt
|
||||
: lastSyncAt
|
||||
: (existing.lastSyncAt ?? lastSyncAt);
|
||||
accountDueAt.set(subscription.accountId, {
|
||||
refreshInterval: interval,
|
||||
lastSyncAt: earliest,
|
||||
});
|
||||
}
|
||||
|
||||
const now = Date.now();
|
||||
await Promise.allSettled(
|
||||
Array.from(accountDueAt.entries()).map(([accountId, info]) => {
|
||||
if (
|
||||
!info.lastSyncAt ||
|
||||
now - info.lastSyncAt.getTime() >= info.refreshInterval * 60 * 1000
|
||||
) {
|
||||
return this.calendar.syncAccount(accountId);
|
||||
}
|
||||
return Promise.resolve();
|
||||
})
|
||||
subscriptions.map(({ id }) =>
|
||||
this.queue.add(
|
||||
'calendar.syncSubscription',
|
||||
{ subscriptionId: id, reason: 'polling' },
|
||||
{ jobId: id }
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import { PermissionModule } from '../../core/permission';
|
||||
import { WorkspaceModule } from '../../core/workspaces';
|
||||
import { CalendarController } from './controller';
|
||||
import { CalendarCronJobs } from './cron';
|
||||
import { CalendarJob } from './job';
|
||||
import { CalendarOAuthService } from './oauth';
|
||||
import { CalendarProviderFactory, CalendarProviders } from './providers';
|
||||
import {
|
||||
@@ -25,6 +26,7 @@ import { CalendarService } from './service';
|
||||
...CalendarProviders,
|
||||
CalendarProviderFactory,
|
||||
CalendarService,
|
||||
CalendarJob,
|
||||
CalendarOAuthService,
|
||||
CalendarCronJobs,
|
||||
CalendarServerConfigResolver,
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { OnJob } from '../../base';
|
||||
import { CalendarService } from './service';
|
||||
|
||||
declare global {
|
||||
interface Jobs {
|
||||
'calendar.syncSubscription': {
|
||||
subscriptionId: string;
|
||||
reason?: 'polling' | 'webhook' | 'on-demand';
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class CalendarJob {
|
||||
constructor(private readonly calendar: CalendarService) {}
|
||||
|
||||
@OnJob('calendar.syncSubscription')
|
||||
async syncSubscription({
|
||||
subscriptionId,
|
||||
reason,
|
||||
}: Jobs['calendar.syncSubscription']) {
|
||||
await this.calendar.syncSubscription(subscriptionId, { reason });
|
||||
}
|
||||
}
|
||||
@@ -152,10 +152,28 @@ export abstract class CalendarProvider {
|
||||
}
|
||||
}
|
||||
|
||||
protected get requestTimeoutMs() {
|
||||
const timeout = (this.config as { requestTimeoutMs?: number } | undefined)
|
||||
?.requestTimeoutMs;
|
||||
return typeof timeout === 'number' && timeout > 0 ? timeout : undefined;
|
||||
}
|
||||
|
||||
protected withTimeout(signal?: AbortSignal | null) {
|
||||
const timeoutMs = this.requestTimeoutMs;
|
||||
if (!timeoutMs) return signal;
|
||||
|
||||
const timeoutSignal = AbortSignal.timeout(timeoutMs);
|
||||
if (!signal) return timeoutSignal;
|
||||
|
||||
return AbortSignal.any([signal, timeoutSignal]);
|
||||
}
|
||||
|
||||
protected async fetchJson<T>(url: string, init?: RequestInit) {
|
||||
const response = await fetch(url, {
|
||||
headers: { Accept: 'application/json', ...init?.headers },
|
||||
...init,
|
||||
signal: this.withTimeout(init?.signal),
|
||||
headers: { ...init?.headers, Accept: 'application/json' },
|
||||
});
|
||||
const body = await response.text();
|
||||
if (!response.ok) {
|
||||
|
||||
@@ -329,6 +329,7 @@ export class GoogleCalendarProvider extends CalendarProvider {
|
||||
|
||||
private async fetchWithTokenHandling<T>(url: string, accessToken: string) {
|
||||
const response = await fetch(url, {
|
||||
signal: this.withTimeout(),
|
||||
headers: {
|
||||
Accept: 'application/json',
|
||||
Authorization: `Bearer ${accessToken}`,
|
||||
|
||||
@@ -8,11 +8,11 @@ import { addDays, subDays } from 'date-fns';
|
||||
import {
|
||||
CalendarProviderRequestError,
|
||||
Config,
|
||||
exponentialBackoffDelay,
|
||||
GraphqlBadRequest,
|
||||
Mutex,
|
||||
JobQueue,
|
||||
URLHelper,
|
||||
} from '../../base';
|
||||
import { SessionRedis } from '../../base/redis';
|
||||
import { Models } from '../../models';
|
||||
import type { CalendarCalDAVProviderPreset } from './config';
|
||||
import {
|
||||
@@ -28,10 +28,10 @@ import type { LinkCalDAVAccountInput } from './types';
|
||||
const TOKEN_REFRESH_SKEW_MS = 60 * 1000;
|
||||
const DEFAULT_PAST_DAYS = 90;
|
||||
const DEFAULT_FUTURE_DAYS = 180;
|
||||
const SYNC_FAILURE_BACKOFF_KEY_PREFIX = 'calendar:sync:backoff:';
|
||||
const SYNC_FAILURE_BACKOFF_BASE_MS = 5 * 60 * 1000;
|
||||
const SYNC_FAILURE_BACKOFF_MAX_MS = 6 * 60 * 60 * 1000;
|
||||
const SYNC_FAILURE_BACKOFF_TTL_SECONDS = 24 * 60 * 60;
|
||||
const DEFAULT_REFRESH_INTERVAL_MINUTES = 30;
|
||||
const CHANNEL_RENEW_RETRY_MS = 15 * 60 * 1000;
|
||||
|
||||
@Injectable()
|
||||
export class CalendarService {
|
||||
@@ -41,8 +41,7 @@ export class CalendarService {
|
||||
constructor(
|
||||
private readonly models: Models,
|
||||
private readonly providerFactory: CalendarProviderFactory<CalendarProvider>,
|
||||
private readonly mutex: Mutex,
|
||||
private readonly redis: SessionRedis,
|
||||
private readonly queue: JobQueue,
|
||||
private readonly config: Config,
|
||||
private readonly url: URLHelper
|
||||
) {}
|
||||
@@ -85,10 +84,24 @@ export class CalendarService {
|
||||
return null;
|
||||
}
|
||||
|
||||
return await this.models.calendarAccount.updateRefreshInterval(
|
||||
accountId,
|
||||
refreshIntervalMinutes
|
||||
const updatedAccount =
|
||||
await this.models.calendarAccount.updateRefreshInterval(
|
||||
accountId,
|
||||
refreshIntervalMinutes
|
||||
);
|
||||
const subscriptions =
|
||||
await this.models.calendarSubscription.listByAccountForSync(accountId);
|
||||
await Promise.all(
|
||||
subscriptions.map(subscription =>
|
||||
this.models.calendarSubscription.updateSync(subscription.id, {
|
||||
nextSyncAt: this.calculateNextSyncAt(
|
||||
subscription.lastSyncAt ?? this.now(),
|
||||
refreshIntervalMinutes
|
||||
),
|
||||
})
|
||||
)
|
||||
);
|
||||
return updatedAccount;
|
||||
}
|
||||
|
||||
async unlinkAccount(userId: string, accountId: string) {
|
||||
@@ -313,25 +326,6 @@ export class CalendarService {
|
||||
return;
|
||||
}
|
||||
|
||||
const now = Date.now();
|
||||
const backoff = await this.getSyncFailureBackoff(subscription.id);
|
||||
if (backoff && now < backoff.nextRetryAt.getTime()) {
|
||||
return;
|
||||
}
|
||||
|
||||
await using lock = await this.mutex.acquire(
|
||||
`calendar:subscription:${subscriptionId}`
|
||||
);
|
||||
if (!lock) {
|
||||
return;
|
||||
}
|
||||
|
||||
const lockedNow = Date.now();
|
||||
const lockedBackoff = await this.getSyncFailureBackoff(subscription.id);
|
||||
if (lockedBackoff && lockedNow < lockedBackoff.nextRetryAt.getTime()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const provider = this.providerFactory.get(
|
||||
account.provider as CalendarProviderName
|
||||
);
|
||||
@@ -415,29 +409,28 @@ export class CalendarService {
|
||||
}
|
||||
|
||||
if (synced) {
|
||||
await this.clearSyncFailureBackoff(subscription.id);
|
||||
await this.ensureWebhookChannel(subscription, provider, accessToken);
|
||||
const syncedAt = this.now();
|
||||
let nextSyncAt = this.calculateNextSyncAt(
|
||||
syncedAt,
|
||||
account.refreshIntervalMinutes
|
||||
);
|
||||
|
||||
try {
|
||||
await this.ensureWebhookChannel(subscription, provider, accessToken);
|
||||
} catch (error) {
|
||||
nextSyncAt = this.calculateChannelRetryAt(nextSyncAt);
|
||||
this.logger.warn(
|
||||
`Failed to ensure webhook channel for subscription ${subscription.id}`,
|
||||
this.toError(error)
|
||||
);
|
||||
}
|
||||
|
||||
await this.models.calendarSubscription.updateSync(subscription.id, {
|
||||
lastSyncAt: syncedAt,
|
||||
nextSyncAt,
|
||||
syncRetryCount: 0,
|
||||
});
|
||||
}
|
||||
|
||||
await this.models.calendarSubscription.updateLastSyncAt(
|
||||
subscription.id,
|
||||
new Date()
|
||||
);
|
||||
}
|
||||
|
||||
async syncAccount(accountId: string) {
|
||||
const account = await this.models.calendarAccount.get(accountId);
|
||||
if (!account || account.status !== 'active') {
|
||||
return;
|
||||
}
|
||||
|
||||
const subscriptions =
|
||||
await this.models.calendarSubscription.listByAccountForSync(accountId);
|
||||
await Promise.allSettled(
|
||||
subscriptions.map(subscription =>
|
||||
this.syncSubscription(subscription.id, { reason: 'polling' })
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
async listWorkspaceEvents(params: {
|
||||
@@ -455,9 +448,18 @@ export class CalendarService {
|
||||
params.to
|
||||
);
|
||||
|
||||
const subscriptions =
|
||||
await this.models.calendarSubscription.listWithAccounts(subscriptionIds);
|
||||
const staleSubscriptions = subscriptions.filter(
|
||||
subscription =>
|
||||
subscription.enabled &&
|
||||
subscription.account.status === 'active' &&
|
||||
subscription.nextSyncAt.getTime() <= this.nowMs()
|
||||
);
|
||||
|
||||
Promise.allSettled(
|
||||
subscriptionIds.map(subscriptionId =>
|
||||
this.syncSubscription(subscriptionId, { reason: 'on-demand' })
|
||||
staleSubscriptions.map(subscription =>
|
||||
this.enqueueSyncSubscription(subscription.id, 'on-demand')
|
||||
)
|
||||
).catch(error => {
|
||||
this.logger.warn('Calendar on-demand sync failed', error as Error);
|
||||
@@ -513,7 +515,7 @@ export class CalendarService {
|
||||
return;
|
||||
}
|
||||
|
||||
await this.syncSubscription(subscription.id, { reason: 'webhook' });
|
||||
await this.enqueueSyncSubscription(subscription.id, 'webhook');
|
||||
}
|
||||
|
||||
getWebhookToken() {
|
||||
@@ -747,7 +749,7 @@ export class CalendarService {
|
||||
}
|
||||
|
||||
private getSyncWindow() {
|
||||
const now = new Date();
|
||||
const now = this.now();
|
||||
return {
|
||||
timeMin: subDays(now, DEFAULT_PAST_DAYS).toISOString(),
|
||||
timeMax: addDays(now, DEFAULT_FUTURE_DAYS).toISOString(),
|
||||
@@ -767,7 +769,7 @@ export class CalendarService {
|
||||
if (
|
||||
accessToken &&
|
||||
account.expiresAt &&
|
||||
account.expiresAt.getTime() > Date.now() + TOKEN_REFRESH_SKEW_MS
|
||||
account.expiresAt.getTime() > this.nowMs() + TOKEN_REFRESH_SKEW_MS
|
||||
) {
|
||||
return { accessToken };
|
||||
}
|
||||
@@ -831,7 +833,7 @@ export class CalendarService {
|
||||
return;
|
||||
}
|
||||
|
||||
const renewThreshold = Date.now() + 24 * 60 * 60 * 1000;
|
||||
const renewThreshold = this.nowMs() + 24 * 60 * 60 * 1000;
|
||||
if (
|
||||
subscription.channelExpiration &&
|
||||
subscription.channelExpiration.getTime() > renewThreshold
|
||||
@@ -873,6 +875,7 @@ export class CalendarService {
|
||||
subscription: {
|
||||
id: string;
|
||||
externalCalendarId: string;
|
||||
syncRetryCount: number;
|
||||
customChannelId: string | null;
|
||||
customResourceId: string | null;
|
||||
};
|
||||
@@ -895,7 +898,6 @@ export class CalendarService {
|
||||
}
|
||||
|
||||
if (this.isTokenInvalidError(params.error)) {
|
||||
await this.clearSyncFailureBackoff(params.subscription.id);
|
||||
await this.models.calendarAccount.invalidateAndPurge(
|
||||
params.account.id,
|
||||
this.formatSyncError(params.error)
|
||||
@@ -903,18 +905,14 @@ export class CalendarService {
|
||||
return;
|
||||
}
|
||||
|
||||
const backoff = await this.bumpSyncFailureBackoff(params.subscription.id);
|
||||
const interval = params.account.refreshIntervalMinutes ?? 60;
|
||||
const lastSyncAt = this.calculateLastSyncAtForRetry(
|
||||
backoff.nextRetryAt,
|
||||
interval
|
||||
);
|
||||
await this.models.calendarSubscription.updateLastSyncAt(
|
||||
params.subscription.id,
|
||||
lastSyncAt
|
||||
);
|
||||
const attempt = params.subscription.syncRetryCount + 1;
|
||||
const nextRetryAt = this.calculateFailureRetryAt(attempt);
|
||||
await this.models.calendarSubscription.updateSync(params.subscription.id, {
|
||||
nextSyncAt: nextRetryAt,
|
||||
syncRetryCount: attempt,
|
||||
});
|
||||
this.logger.warn(
|
||||
`Calendar sync failed for subscription ${params.subscription.id}, attempt ${backoff.attempt}, next retry at ${backoff.nextRetryAt.toISOString()}`,
|
||||
`Calendar sync failed for subscription ${params.subscription.id}, attempt ${attempt}, next retry at ${nextRetryAt.toISOString()}`,
|
||||
this.toError(params.error)
|
||||
);
|
||||
}
|
||||
@@ -927,15 +925,6 @@ export class CalendarService {
|
||||
return status === 404;
|
||||
}
|
||||
|
||||
private calculateLastSyncAtForRetry(
|
||||
nextRetryAt: Date,
|
||||
refreshIntervalMinutes: number
|
||||
) {
|
||||
// Cron schedules by `now - lastSyncAt >= refreshInterval`, so back-calculate
|
||||
// a synthetic lastSyncAt to defer the next attempt to `nextRetryAt`.
|
||||
return new Date(nextRetryAt.getTime() - refreshIntervalMinutes * 60 * 1000);
|
||||
}
|
||||
|
||||
private async disableSubscription(params: {
|
||||
subscriptionId: string;
|
||||
provider: CalendarProvider;
|
||||
@@ -966,68 +955,52 @@ export class CalendarService {
|
||||
await this.models.calendarSubscription.disableAndPurge(
|
||||
params.subscriptionId
|
||||
);
|
||||
await this.clearSyncFailureBackoff(params.subscriptionId);
|
||||
}
|
||||
|
||||
private getSyncFailureBackoffKey(subscriptionId: string) {
|
||||
return `${SYNC_FAILURE_BACKOFF_KEY_PREFIX}${subscriptionId}`;
|
||||
}
|
||||
|
||||
private async getSyncFailureBackoff(subscriptionId: string) {
|
||||
const key = this.getSyncFailureBackoffKey(subscriptionId);
|
||||
const value = await this.redis.get(key);
|
||||
if (!value) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
const parsed = JSON.parse(value) as {
|
||||
attempt?: number;
|
||||
nextRetryAt?: string;
|
||||
};
|
||||
if (!parsed.attempt || !parsed.nextRetryAt) {
|
||||
return null;
|
||||
async enqueueSyncSubscription(
|
||||
subscriptionId: string,
|
||||
reason: 'polling' | 'webhook' | 'on-demand'
|
||||
) {
|
||||
await this.queue.add(
|
||||
'calendar.syncSubscription',
|
||||
{
|
||||
subscriptionId,
|
||||
reason,
|
||||
},
|
||||
{
|
||||
jobId: subscriptionId,
|
||||
}
|
||||
const nextRetryAt = new Date(parsed.nextRetryAt);
|
||||
if (Number.isNaN(nextRetryAt.getTime())) {
|
||||
return null;
|
||||
}
|
||||
return {
|
||||
attempt: parsed.attempt,
|
||||
nextRetryAt,
|
||||
};
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
private async bumpSyncFailureBackoff(subscriptionId: string) {
|
||||
const state = await this.getSyncFailureBackoff(subscriptionId);
|
||||
const attempt = (state?.attempt ?? 0) + 1;
|
||||
const delay = Math.min(
|
||||
SYNC_FAILURE_BACKOFF_BASE_MS * 2 ** (attempt - 1),
|
||||
SYNC_FAILURE_BACKOFF_MAX_MS
|
||||
);
|
||||
const nextRetryAt = new Date(Date.now() + delay);
|
||||
const key = this.getSyncFailureBackoffKey(subscriptionId);
|
||||
await this.redis.set(
|
||||
key,
|
||||
JSON.stringify({
|
||||
attempt,
|
||||
nextRetryAt: nextRetryAt.toISOString(),
|
||||
}),
|
||||
'EX',
|
||||
SYNC_FAILURE_BACKOFF_TTL_SECONDS
|
||||
);
|
||||
return {
|
||||
attempt,
|
||||
nextRetryAt,
|
||||
};
|
||||
private calculateNextSyncAt(base: Date, refreshIntervalMinutes?: number) {
|
||||
const intervalMinutes =
|
||||
refreshIntervalMinutes ?? DEFAULT_REFRESH_INTERVAL_MINUTES;
|
||||
return new Date(base.getTime() + intervalMinutes * 60 * 1000);
|
||||
}
|
||||
|
||||
private async clearSyncFailureBackoff(subscriptionId: string) {
|
||||
const key = this.getSyncFailureBackoffKey(subscriptionId);
|
||||
await this.redis.del(key);
|
||||
private calculateChannelRetryAt(nextSyncAt: Date) {
|
||||
return new Date(
|
||||
Math.min(nextSyncAt.getTime(), this.nowMs() + CHANNEL_RENEW_RETRY_MS)
|
||||
);
|
||||
}
|
||||
|
||||
private calculateFailureRetryAt(attempt: number) {
|
||||
return new Date(
|
||||
this.nowMs() +
|
||||
exponentialBackoffDelay(attempt - 1, {
|
||||
baseDelayMs: SYNC_FAILURE_BACKOFF_BASE_MS,
|
||||
maxDelayMs: SYNC_FAILURE_BACKOFF_MAX_MS,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
private now() {
|
||||
return new Date(this.nowMs());
|
||||
}
|
||||
|
||||
private nowMs() {
|
||||
return Date.now();
|
||||
}
|
||||
|
||||
private formatSyncError(error: unknown) {
|
||||
|
||||
@@ -33,19 +33,37 @@ test('should not index workspace if indexer is disabled', async t => {
|
||||
const count = module.queue.count('indexer.indexWorkspace');
|
||||
|
||||
// @ts-expect-error ignore missing fields
|
||||
await indexerEvent.indexWorkspace({ id: 'test-workspace' });
|
||||
await indexerEvent.indexWorkspace({
|
||||
workspaceId: 'test-workspace',
|
||||
docId: 'test-workspace',
|
||||
});
|
||||
|
||||
t.is(module.queue.count('indexer.indexWorkspace'), count);
|
||||
});
|
||||
|
||||
test('should index workspace if indexer is enabled', async t => {
|
||||
test('should index workspace when root snapshot is updated', async t => {
|
||||
// @ts-expect-error ignore missing fields
|
||||
await indexerEvent.indexWorkspace({ id: 'test-workspace' });
|
||||
await indexerEvent.indexWorkspace({
|
||||
workspaceId: 'test-workspace',
|
||||
docId: 'test-workspace',
|
||||
});
|
||||
|
||||
const { payload } = await module.queue.waitFor('indexer.indexWorkspace');
|
||||
t.is(payload.workspaceId, 'test-workspace');
|
||||
});
|
||||
|
||||
test('should not index workspace when non-root snapshot is updated', async t => {
|
||||
const count = module.queue.count('indexer.indexWorkspace');
|
||||
|
||||
// @ts-expect-error ignore missing fields
|
||||
await indexerEvent.indexWorkspace({
|
||||
workspaceId: 'test-workspace',
|
||||
docId: 'child-doc',
|
||||
});
|
||||
|
||||
t.is(module.queue.count('indexer.indexWorkspace'), count);
|
||||
});
|
||||
|
||||
test('should not delete workspace if indexer is disabled', async t => {
|
||||
Sinon.stub(config.indexer, 'enabled').value(false);
|
||||
const count = module.queue.count('indexer.deleteWorkspace');
|
||||
|
||||
@@ -29,21 +29,20 @@ export class IndexerEvent {
|
||||
);
|
||||
}
|
||||
|
||||
@OnEvent('workspace.updated')
|
||||
async indexWorkspace({ id }: Events['workspace.updated']) {
|
||||
@OnEvent('doc.snapshot.updated')
|
||||
async indexWorkspace({ workspaceId, docId }: Events['doc.snapshot.updated']) {
|
||||
if (!this.config.indexer.enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (workspaceId !== docId) {
|
||||
return;
|
||||
}
|
||||
|
||||
await this.queue.add(
|
||||
'indexer.indexWorkspace',
|
||||
{
|
||||
workspaceId: id,
|
||||
},
|
||||
{
|
||||
jobId: `indexWorkspace/${id}`,
|
||||
priority: 100,
|
||||
}
|
||||
{ workspaceId },
|
||||
{ jobId: `indexWorkspace/${workspaceId}`, priority: 100 }
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -27,6 +27,10 @@
|
||||
"type": "Object",
|
||||
"desc": "The config for copilot job queue"
|
||||
},
|
||||
"queues.calendar": {
|
||||
"type": "Object",
|
||||
"desc": "The config for calendar job queue"
|
||||
},
|
||||
"queues.doc": {
|
||||
"type": "Object",
|
||||
"desc": "The config for doc job queue"
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
"pl": 98,
|
||||
"pt-BR": 96,
|
||||
"ru": 98,
|
||||
"sv-SE": 97,
|
||||
"sv-SE": 96,
|
||||
"uk": 96,
|
||||
"ur": 2,
|
||||
"zh-Hans": 98,
|
||||
|
||||
@@ -1034,8 +1034,7 @@ __metadata:
|
||||
"@types/nodemailer": "npm:^7.0.0"
|
||||
"@types/on-headers": "npm:^1.0.3"
|
||||
"@types/react": "npm:^19.0.1"
|
||||
"@types/react-dom": "npm:^19.0.2"
|
||||
"@types/semver": "npm:^7.5.8"
|
||||
"@types/semver": "npm:^7.7.1"
|
||||
"@types/sinon": "npm:^21.0.0"
|
||||
"@types/supertest": "npm:^6.0.2"
|
||||
ai: "npm:^5.0.118"
|
||||
@@ -1078,7 +1077,7 @@ __metadata:
|
||||
react-email: "npm:^4.3.2"
|
||||
reflect-metadata: "npm:^0.2.2"
|
||||
rxjs: "npm:^7.8.2"
|
||||
semver: "npm:^7.7.3"
|
||||
semver: "npm:^7.7.4"
|
||||
ses: "npm:^1.14.0"
|
||||
sinon: "npm:^21.0.1"
|
||||
socket.io: "npm:^4.8.1"
|
||||
@@ -6220,17 +6219,17 @@ __metadata:
|
||||
linkType: hard
|
||||
|
||||
"@graphql-tools/graphql-file-loader@npm:^8.0.0":
|
||||
version: 8.0.19
|
||||
resolution: "@graphql-tools/graphql-file-loader@npm:8.0.19"
|
||||
version: 8.1.12
|
||||
resolution: "@graphql-tools/graphql-file-loader@npm:8.1.12"
|
||||
dependencies:
|
||||
"@graphql-tools/import": "npm:7.0.18"
|
||||
"@graphql-tools/utils": "npm:^10.8.6"
|
||||
"@graphql-tools/import": "npm:^7.1.12"
|
||||
"@graphql-tools/utils": "npm:^11.0.0"
|
||||
globby: "npm:^11.0.3"
|
||||
tslib: "npm:^2.4.0"
|
||||
unixify: "npm:^1.0.0"
|
||||
peerDependencies:
|
||||
graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0
|
||||
checksum: 10/f7b8871582fdb925ba4b54463bdad651777a53769eafbf1febe1783ab25208a1c787fa2f3a16caabee0f9c1621adad47df539973539c57037f748c6c9d4ef103
|
||||
checksum: 10/774f6c14e511d91ded6b7c338bd55bb31c3c5256af14799ae117f4580f6b7341fef3ca85e83d559b4400e0e933d04cb22d6c29390bf774e38d3d03b009203795
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -6251,48 +6250,48 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@graphql-tools/import@npm:7.0.18":
|
||||
version: 7.0.18
|
||||
resolution: "@graphql-tools/import@npm:7.0.18"
|
||||
"@graphql-tools/import@npm:^7.1.12":
|
||||
version: 7.1.12
|
||||
resolution: "@graphql-tools/import@npm:7.1.12"
|
||||
dependencies:
|
||||
"@graphql-tools/utils": "npm:^10.8.6"
|
||||
"@graphql-tools/utils": "npm:^11.0.0"
|
||||
resolve-from: "npm:5.0.0"
|
||||
tslib: "npm:^2.4.0"
|
||||
peerDependencies:
|
||||
graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0
|
||||
checksum: 10/739086fcaffefa8efa38648477fd4aea41a87b5fa3f78552a2a7b6249dce1d84d84e164e61c73811d6ce9e8f5754b6bab675f7255482bf5ba080f83759a37138
|
||||
checksum: 10/9c65b2fb5221e20955ae865454ff89fa9910e0282416e9f60826b3dc512c3b4cc71dba8784eecc574925486390c2e31e0b51d284781710df9f865c15811866f3
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@graphql-tools/json-file-loader@npm:^8.0.0":
|
||||
version: 8.0.18
|
||||
resolution: "@graphql-tools/json-file-loader@npm:8.0.18"
|
||||
version: 8.0.26
|
||||
resolution: "@graphql-tools/json-file-loader@npm:8.0.26"
|
||||
dependencies:
|
||||
"@graphql-tools/utils": "npm:^10.8.6"
|
||||
"@graphql-tools/utils": "npm:^11.0.0"
|
||||
globby: "npm:^11.0.3"
|
||||
tslib: "npm:^2.4.0"
|
||||
unixify: "npm:^1.0.0"
|
||||
peerDependencies:
|
||||
graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0
|
||||
checksum: 10/a2e6e37c0565674c18aa6c4d5574924fefda441c3bbfd40ff123ab747c6f542f99d3669f204c2f616a3cecdd8cb76a9d827bf50af13faf4a299e54f1577a9136
|
||||
checksum: 10/6e4dc44a9aa3cdd3f7b958b50d98a26e56fb5cc9fab2667011ec12c82685016f269350d6ba2e45dcc7e6d71f8df7d1c4002edb55ce8896ba3e705cad14645ac1
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@graphql-tools/load@npm:^8.1.0":
|
||||
version: 8.1.0
|
||||
resolution: "@graphql-tools/load@npm:8.1.0"
|
||||
version: 8.1.8
|
||||
resolution: "@graphql-tools/load@npm:8.1.8"
|
||||
dependencies:
|
||||
"@graphql-tools/schema": "npm:^10.0.23"
|
||||
"@graphql-tools/utils": "npm:^10.8.6"
|
||||
"@graphql-tools/schema": "npm:^10.0.31"
|
||||
"@graphql-tools/utils": "npm:^11.0.0"
|
||||
p-limit: "npm:3.1.0"
|
||||
tslib: "npm:^2.4.0"
|
||||
peerDependencies:
|
||||
graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0
|
||||
checksum: 10/4601dda7eb32cb8afed2379102ad82f8a948e478f42c7b1f354a3468ca8dfcdcc2a89e6c6ebcbb574c77eaa80d47f20c27230bdcd6c2d0a3600fa1d6a450cc95
|
||||
checksum: 10/a9b24c8d9fc52ebf2b5e0d5dc99212e61704cfe0a07b17a5be3329c391ae01f710e0a2ca6b73b41379e9bee55210c0466d5dfb378a9e3cbe051062a69a07d616
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@graphql-tools/merge@npm:9.0.24, @graphql-tools/merge@npm:^9.0.0, @graphql-tools/merge@npm:^9.0.24":
|
||||
"@graphql-tools/merge@npm:9.0.24":
|
||||
version: 9.0.24
|
||||
resolution: "@graphql-tools/merge@npm:9.0.24"
|
||||
dependencies:
|
||||
@@ -6316,6 +6315,18 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@graphql-tools/merge@npm:^9.0.0, @graphql-tools/merge@npm:^9.0.24, @graphql-tools/merge@npm:^9.1.7":
|
||||
version: 9.1.7
|
||||
resolution: "@graphql-tools/merge@npm:9.1.7"
|
||||
dependencies:
|
||||
"@graphql-tools/utils": "npm:^11.0.0"
|
||||
tslib: "npm:^2.4.0"
|
||||
peerDependencies:
|
||||
graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0
|
||||
checksum: 10/e0b77dfc16e91d7c2450df0b57a85a93e11f0f67e37e396bcf04275d1db8ed1b7257c763ebe6e7f122041d81f00d6aa954fbec531fa6c0b449d195a9aff199cc
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@graphql-tools/optimize@npm:^2.0.0":
|
||||
version: 2.0.0
|
||||
resolution: "@graphql-tools/optimize@npm:2.0.0"
|
||||
@@ -6366,7 +6377,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@graphql-tools/schema@npm:10.0.23, @graphql-tools/schema@npm:^10.0.0, @graphql-tools/schema@npm:^10.0.11, @graphql-tools/schema@npm:^10.0.23":
|
||||
"@graphql-tools/schema@npm:10.0.23":
|
||||
version: 10.0.23
|
||||
resolution: "@graphql-tools/schema@npm:10.0.23"
|
||||
dependencies:
|
||||
@@ -6379,6 +6390,19 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@graphql-tools/schema@npm:^10.0.0, @graphql-tools/schema@npm:^10.0.11, @graphql-tools/schema@npm:^10.0.31":
|
||||
version: 10.0.31
|
||||
resolution: "@graphql-tools/schema@npm:10.0.31"
|
||||
dependencies:
|
||||
"@graphql-tools/merge": "npm:^9.1.7"
|
||||
"@graphql-tools/utils": "npm:^11.0.0"
|
||||
tslib: "npm:^2.4.0"
|
||||
peerDependencies:
|
||||
graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0
|
||||
checksum: 10/5b775736f8b8454319e07cadc7d41bc5c9cc804a393490aaffd1bb7f59afddb02b498837e870bf98db4a1a989a721d5d8e2fd2b97409d078bac14503c2d4f9cb
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@graphql-tools/schema@npm:^9.0.0":
|
||||
version: 9.0.19
|
||||
resolution: "@graphql-tools/schema@npm:9.0.19"
|
||||
@@ -6430,6 +6454,20 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@graphql-tools/utils@npm:^11.0.0":
|
||||
version: 11.0.0
|
||||
resolution: "@graphql-tools/utils@npm:11.0.0"
|
||||
dependencies:
|
||||
"@graphql-typed-document-node/core": "npm:^3.1.1"
|
||||
"@whatwg-node/promise-helpers": "npm:^1.0.0"
|
||||
cross-inspect: "npm:1.0.1"
|
||||
tslib: "npm:^2.4.0"
|
||||
peerDependencies:
|
||||
graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0
|
||||
checksum: 10/4cc7577ab85d60908a1d5d448071b318791b798f571cd4b8e4289e0e0eeae9d7183b661a1a7d5da3cedaf5f9b62b936031e3a90d2e17a1c50acbd95d9106ba3c
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@graphql-tools/utils@npm:^9.2.1":
|
||||
version: 9.2.1
|
||||
resolution: "@graphql-tools/utils@npm:9.2.1"
|
||||
@@ -9898,6 +9936,15 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@opentelemetry/api-logs@npm:0.213.0":
|
||||
version: 0.213.0
|
||||
resolution: "@opentelemetry/api-logs@npm:0.213.0"
|
||||
dependencies:
|
||||
"@opentelemetry/api": "npm:^1.3.0"
|
||||
checksum: 10/9b2d030d8534520f23e3903ccf64dc479fb4d37fcf5ca265ca7de439ec8dd5c849aaa62068278cd97879da7c9528e34c7162cc7bbd025dd8d74667843adc151f
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@opentelemetry/api@npm:1.9.0, @opentelemetry/api@npm:^1.3.0, @opentelemetry/api@npm:^1.9.0":
|
||||
version: 1.9.0
|
||||
resolution: "@opentelemetry/api@npm:1.9.0"
|
||||
@@ -9917,7 +9964,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@opentelemetry/context-async-hooks@npm:2.5.0, @opentelemetry/context-async-hooks@npm:^2.2.0":
|
||||
"@opentelemetry/context-async-hooks@npm:2.5.0":
|
||||
version: 2.5.0
|
||||
resolution: "@opentelemetry/context-async-hooks@npm:2.5.0"
|
||||
peerDependencies:
|
||||
@@ -9926,6 +9973,15 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@opentelemetry/context-async-hooks@npm:2.6.0, @opentelemetry/context-async-hooks@npm:^2.2.0":
|
||||
version: 2.6.0
|
||||
resolution: "@opentelemetry/context-async-hooks@npm:2.6.0"
|
||||
peerDependencies:
|
||||
"@opentelemetry/api": ">=1.0.0 <1.10.0"
|
||||
checksum: 10/a1f746fb9bb25b4c40c0da4cc68a7412e82f120a6ddc80dcf0117432418e64c947527bca87895ebce4211a09992863a75a0f5b5f8e7185a573244cccb4809c42
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@opentelemetry/core@npm:2.2.0":
|
||||
version: 2.2.0
|
||||
resolution: "@opentelemetry/core@npm:2.2.0"
|
||||
@@ -9937,7 +9993,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@opentelemetry/core@npm:2.5.0, @opentelemetry/core@npm:^2.0.0, @opentelemetry/core@npm:^2.2.0":
|
||||
"@opentelemetry/core@npm:2.5.0":
|
||||
version: 2.5.0
|
||||
resolution: "@opentelemetry/core@npm:2.5.0"
|
||||
dependencies:
|
||||
@@ -9948,6 +10004,17 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@opentelemetry/core@npm:2.6.0, @opentelemetry/core@npm:^2.0.0, @opentelemetry/core@npm:^2.2.0":
|
||||
version: 2.6.0
|
||||
resolution: "@opentelemetry/core@npm:2.6.0"
|
||||
dependencies:
|
||||
"@opentelemetry/semantic-conventions": "npm:^1.29.0"
|
||||
peerDependencies:
|
||||
"@opentelemetry/api": ">=1.0.0 <1.10.0"
|
||||
checksum: 10/21c017cc68fe7836d06ecac31abeba6ad610dd42e9c1cb9562cd13eed3f644c48111a1fc7d00dfc2b7cc179d40f059482c69c978c24352ac0c605f30686a01a4
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@opentelemetry/exporter-logs-otlp-grpc@npm:0.211.0":
|
||||
version: 0.211.0
|
||||
resolution: "@opentelemetry/exporter-logs-otlp-grpc@npm:0.211.0"
|
||||
@@ -10477,7 +10544,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@opentelemetry/instrumentation@npm:0.211.0, @opentelemetry/instrumentation@npm:>=0.52.0 <1, @opentelemetry/instrumentation@npm:^0.211.0":
|
||||
"@opentelemetry/instrumentation@npm:0.211.0, @opentelemetry/instrumentation@npm:^0.211.0":
|
||||
version: 0.211.0
|
||||
resolution: "@opentelemetry/instrumentation@npm:0.211.0"
|
||||
dependencies:
|
||||
@@ -10490,6 +10557,19 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@opentelemetry/instrumentation@npm:>=0.52.0 <1":
|
||||
version: 0.213.0
|
||||
resolution: "@opentelemetry/instrumentation@npm:0.213.0"
|
||||
dependencies:
|
||||
"@opentelemetry/api-logs": "npm:0.213.0"
|
||||
import-in-the-middle: "npm:^3.0.0"
|
||||
require-in-the-middle: "npm:^8.0.0"
|
||||
peerDependencies:
|
||||
"@opentelemetry/api": ^1.3.0
|
||||
checksum: 10/69baeaae0c5836ede140485530954d32c8d20d864340f7d57b43a6e3ef9c10394d29a1884dd2b076512aec896039a1ea02f698282649b5aa3fa59b13bca00f97
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@opentelemetry/otlp-exporter-base@npm:0.211.0":
|
||||
version: 0.211.0
|
||||
resolution: "@opentelemetry/otlp-exporter-base@npm:0.211.0"
|
||||
@@ -10562,7 +10642,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@opentelemetry/resources@npm:2.5.0, @opentelemetry/resources@npm:^2.2.0":
|
||||
"@opentelemetry/resources@npm:2.5.0":
|
||||
version: 2.5.0
|
||||
resolution: "@opentelemetry/resources@npm:2.5.0"
|
||||
dependencies:
|
||||
@@ -10574,6 +10654,18 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@opentelemetry/resources@npm:2.6.0, @opentelemetry/resources@npm:^2.2.0":
|
||||
version: 2.6.0
|
||||
resolution: "@opentelemetry/resources@npm:2.6.0"
|
||||
dependencies:
|
||||
"@opentelemetry/core": "npm:2.6.0"
|
||||
"@opentelemetry/semantic-conventions": "npm:^1.29.0"
|
||||
peerDependencies:
|
||||
"@opentelemetry/api": ">=1.3.0 <1.10.0"
|
||||
checksum: 10/837e76911d013e52c1c0cd8da6f2912818fcc107fd1c6fcb2ec8faa6e617b802e0eef1aa53bd4417c7a77c96ea02b6f5bbdccb9ff411ef8efeff49c2e02d9443
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@opentelemetry/sdk-logs@npm:0.211.0":
|
||||
version: 0.211.0
|
||||
resolution: "@opentelemetry/sdk-logs@npm:0.211.0"
|
||||
@@ -10587,7 +10679,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@opentelemetry/sdk-metrics@npm:2.5.0, @opentelemetry/sdk-metrics@npm:^2.2.0":
|
||||
"@opentelemetry/sdk-metrics@npm:2.5.0":
|
||||
version: 2.5.0
|
||||
resolution: "@opentelemetry/sdk-metrics@npm:2.5.0"
|
||||
dependencies:
|
||||
@@ -10599,6 +10691,18 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@opentelemetry/sdk-metrics@npm:^2.2.0":
|
||||
version: 2.6.0
|
||||
resolution: "@opentelemetry/sdk-metrics@npm:2.6.0"
|
||||
dependencies:
|
||||
"@opentelemetry/core": "npm:2.6.0"
|
||||
"@opentelemetry/resources": "npm:2.6.0"
|
||||
peerDependencies:
|
||||
"@opentelemetry/api": ">=1.9.0 <1.10.0"
|
||||
checksum: 10/5fd1254ab86cdb6573999f3c5d60b8332fb3a2b7d50d1befcfd9d8ef021d5e9e405e31394f7aa4a106a4546bd6308a652a78cd9a35d6fbe56e44984d605cb5d5
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@opentelemetry/sdk-node@npm:^0.211.0":
|
||||
version: 0.211.0
|
||||
resolution: "@opentelemetry/sdk-node@npm:0.211.0"
|
||||
@@ -10633,7 +10737,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@opentelemetry/sdk-trace-base@npm:2.5.0, @opentelemetry/sdk-trace-base@npm:^2.2.0":
|
||||
"@opentelemetry/sdk-trace-base@npm:2.5.0":
|
||||
version: 2.5.0
|
||||
resolution: "@opentelemetry/sdk-trace-base@npm:2.5.0"
|
||||
dependencies:
|
||||
@@ -10646,7 +10750,20 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@opentelemetry/sdk-trace-node@npm:2.5.0, @opentelemetry/sdk-trace-node@npm:^2.2.0":
|
||||
"@opentelemetry/sdk-trace-base@npm:2.6.0, @opentelemetry/sdk-trace-base@npm:^2.2.0":
|
||||
version: 2.6.0
|
||||
resolution: "@opentelemetry/sdk-trace-base@npm:2.6.0"
|
||||
dependencies:
|
||||
"@opentelemetry/core": "npm:2.6.0"
|
||||
"@opentelemetry/resources": "npm:2.6.0"
|
||||
"@opentelemetry/semantic-conventions": "npm:^1.29.0"
|
||||
peerDependencies:
|
||||
"@opentelemetry/api": ">=1.3.0 <1.10.0"
|
||||
checksum: 10/8ca3c1c4d7a95ec8a28ab5237162e31334216a59408e9d9d10ad51f5709911a405699ad69f445c212aad55fb6cc2c70f473b835e9e52bf4ed63f237c4d1813af
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@opentelemetry/sdk-trace-node@npm:2.5.0":
|
||||
version: 2.5.0
|
||||
resolution: "@opentelemetry/sdk-trace-node@npm:2.5.0"
|
||||
dependencies:
|
||||
@@ -10659,6 +10776,19 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@opentelemetry/sdk-trace-node@npm:^2.2.0":
|
||||
version: 2.6.0
|
||||
resolution: "@opentelemetry/sdk-trace-node@npm:2.6.0"
|
||||
dependencies:
|
||||
"@opentelemetry/context-async-hooks": "npm:2.6.0"
|
||||
"@opentelemetry/core": "npm:2.6.0"
|
||||
"@opentelemetry/sdk-trace-base": "npm:2.6.0"
|
||||
peerDependencies:
|
||||
"@opentelemetry/api": ">=1.0.0 <1.10.0"
|
||||
checksum: 10/b1576f44198ae18ab36dea92e5c254eb6a96ca5793a5adbb96a01c586dd992e3532eb291c9ea225e2cd6979f7f6dd3fca2fad56ab360ba573f8b3bfb462dd2aa
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@opentelemetry/semantic-conventions@npm:^1.22.0, @opentelemetry/semantic-conventions@npm:^1.24.0, @opentelemetry/semantic-conventions@npm:^1.27.0, @opentelemetry/semantic-conventions@npm:^1.29.0, @opentelemetry/semantic-conventions@npm:^1.30.0, @opentelemetry/semantic-conventions@npm:^1.33.0, @opentelemetry/semantic-conventions@npm:^1.33.1, @opentelemetry/semantic-conventions@npm:^1.34.0, @opentelemetry/semantic-conventions@npm:^1.36.0, @opentelemetry/semantic-conventions@npm:^1.37.0, @opentelemetry/semantic-conventions@npm:^1.38.0":
|
||||
version: 1.39.0
|
||||
resolution: "@opentelemetry/semantic-conventions@npm:1.39.0"
|
||||
@@ -17305,10 +17435,10 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@types/semver@npm:^7, @types/semver@npm:^7.5.8":
|
||||
version: 7.7.0
|
||||
resolution: "@types/semver@npm:7.7.0"
|
||||
checksum: 10/ee4514c6c852b1c38f951239db02f9edeea39f5310fad9396a00b51efa2a2d96b3dfca1ae84c88181ea5b7157c57d32d7ef94edacee36fbf975546396b85ba5b
|
||||
"@types/semver@npm:^7, @types/semver@npm:^7.7.1":
|
||||
version: 7.7.1
|
||||
resolution: "@types/semver@npm:7.7.1"
|
||||
checksum: 10/8f09e7e6ca3ded67d78ba7a8f7535c8d9cf8ced83c52e7f3ac3c281fe8c689c3fe475d199d94390dc04fc681d51f2358b430bb7b2e21c62de24f2bee2c719068
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -18402,12 +18532,12 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"acorn@npm:^8.11.0, acorn@npm:^8.14.0, acorn@npm:^8.15.0, acorn@npm:^8.6.0, acorn@npm:^8.7.1, acorn@npm:^8.8.1, acorn@npm:^8.8.2":
|
||||
version: 8.15.0
|
||||
resolution: "acorn@npm:8.15.0"
|
||||
"acorn@npm:^8.11.0, acorn@npm:^8.15.0, acorn@npm:^8.16.0, acorn@npm:^8.6.0, acorn@npm:^8.7.1, acorn@npm:^8.8.1, acorn@npm:^8.8.2":
|
||||
version: 8.16.0
|
||||
resolution: "acorn@npm:8.16.0"
|
||||
bin:
|
||||
acorn: bin/acorn
|
||||
checksum: 10/77f2de5051a631cf1729c090e5759148459cdb76b5f5c70f890503d629cf5052357b0ce783c0f976dd8a93c5150f59f6d18df1def3f502396a20f81282482fa4
|
||||
checksum: 10/690c673bb4d61b38ef82795fab58526471ad7f7e67c0e40c4ff1e10ecd80ce5312554ef633c9995bfc4e6d170cef165711f9ca9e49040b62c0c66fbf2dd3df2b
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -18603,10 +18733,10 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"ansi-regex@npm:^6.0.1":
|
||||
version: 6.1.0
|
||||
resolution: "ansi-regex@npm:6.1.0"
|
||||
checksum: 10/495834a53b0856c02acd40446f7130cb0f8284f4a39afdab20d5dc42b2e198b1196119fe887beed8f9055c4ff2055e3b2f6d4641d0be018cdfb64fedf6fc1aac
|
||||
"ansi-regex@npm:^6.2.2":
|
||||
version: 6.2.2
|
||||
resolution: "ansi-regex@npm:6.2.2"
|
||||
checksum: 10/9b17ce2c6daecc75bcd5966b9ad672c23b184dc3ed9bf3c98a0702f0d2f736c15c10d461913568f2cf527a5e64291c7473358885dd493305c84a1cfed66ba94f
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -18627,9 +18757,9 @@ __metadata:
|
||||
linkType: hard
|
||||
|
||||
"ansi-styles@npm:^6.0.0, ansi-styles@npm:^6.1.0, ansi-styles@npm:^6.2.1":
|
||||
version: 6.2.1
|
||||
resolution: "ansi-styles@npm:6.2.1"
|
||||
checksum: 10/70fdf883b704d17a5dfc9cde206e698c16bcd74e7f196ab821511651aee4f9f76c9514bdfa6ca3a27b5e49138b89cb222a28caf3afe4567570139577f991df32
|
||||
version: 6.2.3
|
||||
resolution: "ansi-styles@npm:6.2.3"
|
||||
checksum: 10/c49dad7639f3e48859bd51824c93b9eb0db628afc243c51c3dd2410c4a15ede1a83881c6c7341aa2b159c4f90c11befb38f2ba848c07c66c9f9de4bcd7cb9f30
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -19347,12 +19477,12 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"brace-expansion@npm:^2.0.1":
|
||||
version: 2.0.1
|
||||
resolution: "brace-expansion@npm:2.0.1"
|
||||
"brace-expansion@npm:^2.0.1, brace-expansion@npm:^2.0.2":
|
||||
version: 2.0.2
|
||||
resolution: "brace-expansion@npm:2.0.2"
|
||||
dependencies:
|
||||
balanced-match: "npm:^1.0.0"
|
||||
checksum: 10/a61e7cd2e8a8505e9f0036b3b6108ba5e926b4b55089eeb5550cd04a471fe216c96d4fe7e4c7f995c728c554ae20ddfc4244cad10aef255e72b62930afd233d1
|
||||
checksum: 10/01dff195e3646bc4b0d27b63d9bab84d2ebc06121ff5013ad6e5356daa5a9d6b60fa26cf73c74797f2dc3fbec112af13578d51f75228c1112b26c790a87b0488
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -19834,9 +19964,9 @@ __metadata:
|
||||
linkType: hard
|
||||
|
||||
"chalk@npm:^5.0.1, chalk@npm:^5.3.0, chalk@npm:^5.4.1":
|
||||
version: 5.4.1
|
||||
resolution: "chalk@npm:5.4.1"
|
||||
checksum: 10/29df3ffcdf25656fed6e95962e2ef86d14dfe03cd50e7074b06bad9ffbbf6089adbb40f75c00744d843685c8d008adaf3aed31476780312553caf07fa86e5bc7
|
||||
version: 5.6.2
|
||||
resolution: "chalk@npm:5.6.2"
|
||||
checksum: 10/1b2f48f6fba1370670d5610f9cd54c391d6ede28f4b7062dd38244ea5768777af72e5be6b74fb6c6d54cb84c4a2dff3f3afa9b7cb5948f7f022cfd3d087989e0
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -20152,10 +20282,10 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"cjs-module-lexer@npm:^1.2.2":
|
||||
version: 1.4.3
|
||||
resolution: "cjs-module-lexer@npm:1.4.3"
|
||||
checksum: 10/d2b92f919a2dedbfd61d016964fce8da0035f827182ed6839c97cac56e8a8077cfa6a59388adfe2bc588a19cef9bbe830d683a76a6e93c51f65852062cfe2591
|
||||
"cjs-module-lexer@npm:^2.2.0":
|
||||
version: 2.2.0
|
||||
resolution: "cjs-module-lexer@npm:2.2.0"
|
||||
checksum: 10/fc8eb5c1919504366d8260a150d93c4e857740e770467dc59ca0cc34de4b66c93075559a5af65618f359187866b1be40e036f4e1a1bab2f1e06001c216415f74
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -21781,9 +21911,9 @@ __metadata:
|
||||
linkType: hard
|
||||
|
||||
"dayjs@npm:^1.11.13, dayjs@npm:^1.11.18":
|
||||
version: 1.11.18
|
||||
resolution: "dayjs@npm:1.11.18"
|
||||
checksum: 10/7d29a90834cf4da2feb437c2f34b8235c3f94493a06d2f1bf9f506f1fa49eadf796f26e1d685b9fe8cb5e75ce6ee067825115e196f1af3d07b3552ff857bfc39
|
||||
version: 1.11.20
|
||||
resolution: "dayjs@npm:1.11.20"
|
||||
checksum: 10/5347533f21a55b8bb1b1ef559be9b805514c3a8fb7e68b75fb7e73808131c59e70909c073aa44ce8a0d159195cd110cdd4081cf87ab96cb06fee3edacae791c6
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -22271,14 +22401,14 @@ __metadata:
|
||||
linkType: hard
|
||||
|
||||
"dompurify@npm:^3.2.5, dompurify@npm:^3.3.0":
|
||||
version: 3.3.0
|
||||
resolution: "dompurify@npm:3.3.0"
|
||||
version: 3.3.3
|
||||
resolution: "dompurify@npm:3.3.3"
|
||||
dependencies:
|
||||
"@types/trusted-types": "npm:^2.0.7"
|
||||
dependenciesMeta:
|
||||
"@types/trusted-types":
|
||||
optional: true
|
||||
checksum: 10/d8782b10a0454344476936c91038d06c9450b3e3ada2ceb8f722525e6b54e64d847939b9f35bf385facd4139f0a2eaf7f5553efce351f8e9295620570875f002
|
||||
checksum: 10/4cc9c539ed7136d46c6577613b8e20871c2b6165db01dfbd2a3c11c75f9e339c496ac6519a1c3190115def8cadae3720bef0417fc43fa28802c7407bab174da9
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -23937,7 +24067,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"file-type@npm:21.3.0, file-type@npm:^21.0.0":
|
||||
"file-type@npm:21.3.0":
|
||||
version: 21.3.0
|
||||
resolution: "file-type@npm:21.3.0"
|
||||
dependencies:
|
||||
@@ -23949,6 +24079,18 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"file-type@npm:^21.0.0":
|
||||
version: 21.3.3
|
||||
resolution: "file-type@npm:21.3.3"
|
||||
dependencies:
|
||||
"@tokenizer/inflate": "npm:^0.4.1"
|
||||
strtok3: "npm:^10.3.4"
|
||||
token-types: "npm:^6.1.1"
|
||||
uint8array-extras: "npm:^1.4.0"
|
||||
checksum: 10/7a900a89b7e9f65cfff4d489bc4ad9311d749dd3bae3da753b681dbd1d4bf5fff204c0fa78e620076ccbbc1225f0e25330cd5653342bc78bf6b272015153ea23
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"file-uri-to-path@npm:1.0.0":
|
||||
version: 1.0.0
|
||||
resolution: "file-uri-to-path@npm:1.0.0"
|
||||
@@ -24567,10 +24709,10 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"get-east-asian-width@npm:^1.0.0":
|
||||
version: 1.3.0
|
||||
resolution: "get-east-asian-width@npm:1.3.0"
|
||||
checksum: 10/8e8e779eb28701db7fdb1c8cab879e39e6ae23f52dadd89c8aed05869671cee611a65d4f8557b83e981428623247d8bc5d0c7a4ef3ea7a41d826e73600112ad8
|
||||
"get-east-asian-width@npm:^1.0.0, get-east-asian-width@npm:^1.3.1":
|
||||
version: 1.5.0
|
||||
resolution: "get-east-asian-width@npm:1.5.0"
|
||||
checksum: 10/60bc34cd1e975055ab99f0f177e31bed3e516ff7cee9c536474383954a976abaa6b94a51d99ad158ef1e372790fa096cab7d07f166bb0778f6587954c0fbe946
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -25854,14 +25996,26 @@ __metadata:
|
||||
linkType: hard
|
||||
|
||||
"import-in-the-middle@npm:^2, import-in-the-middle@npm:^2.0.0":
|
||||
version: 2.0.0
|
||||
resolution: "import-in-the-middle@npm:2.0.0"
|
||||
version: 2.0.6
|
||||
resolution: "import-in-the-middle@npm:2.0.6"
|
||||
dependencies:
|
||||
acorn: "npm:^8.14.0"
|
||||
acorn: "npm:^8.15.0"
|
||||
acorn-import-attributes: "npm:^1.9.5"
|
||||
cjs-module-lexer: "npm:^1.2.2"
|
||||
module-details-from-path: "npm:^1.0.3"
|
||||
checksum: 10/badb8359552f1e9fedc8569299dd1937e802256ce0fe6aa9cb348bca6f217f06e16a3ca46f889bfcb66028a096a1956674d257de9e809db4271ca0e508521c30
|
||||
cjs-module-lexer: "npm:^2.2.0"
|
||||
module-details-from-path: "npm:^1.0.4"
|
||||
checksum: 10/8be80d7f2d4ad34e5eb1082925ee2e90844edb65359cad0f5d8e934a09fafeca10e66f50d0b07570bd6b877ff678755d3c2d36d05258cc3541e39fa6aae6ae56
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"import-in-the-middle@npm:^3.0.0":
|
||||
version: 3.0.0
|
||||
resolution: "import-in-the-middle@npm:3.0.0"
|
||||
dependencies:
|
||||
acorn: "npm:^8.15.0"
|
||||
acorn-import-attributes: "npm:^1.9.5"
|
||||
cjs-module-lexer: "npm:^2.2.0"
|
||||
module-details-from-path: "npm:^1.0.4"
|
||||
checksum: 10/0bf1f22d00a080e7f651db8c5d136aa4aca6829397769f22fb544a67d9117b1c78590f180a690eb19eb0cfb4a558beac66b6508d346cccc91e1e5f75c934e9de
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -26245,11 +26399,11 @@ __metadata:
|
||||
linkType: hard
|
||||
|
||||
"is-fullwidth-code-point@npm:^5.0.0":
|
||||
version: 5.0.0
|
||||
resolution: "is-fullwidth-code-point@npm:5.0.0"
|
||||
version: 5.1.0
|
||||
resolution: "is-fullwidth-code-point@npm:5.1.0"
|
||||
dependencies:
|
||||
get-east-asian-width: "npm:^1.0.0"
|
||||
checksum: 10/8dfb2d2831b9e87983c136f5c335cd9d14c1402973e357a8ff057904612ed84b8cba196319fabedf9aefe4639e14fe3afe9d9966d1d006ebeb40fe1fed4babe5
|
||||
get-east-asian-width: "npm:^1.3.1"
|
||||
checksum: 10/4700d8a82cb71bd2a2955587b2823c36dc4660eadd4047bfbd070821ddbce8504fc5f9b28725567ecddf405b1e06c6692c9b719f65df6af9ec5262bc11393a6a
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -27089,13 +27243,13 @@ __metadata:
|
||||
linkType: hard
|
||||
|
||||
"katex@npm:^0.16.0, katex@npm:^0.16.22, katex@npm:^0.16.27":
|
||||
version: 0.16.27
|
||||
resolution: "katex@npm:0.16.27"
|
||||
version: 0.16.38
|
||||
resolution: "katex@npm:0.16.38"
|
||||
dependencies:
|
||||
commander: "npm:^8.3.0"
|
||||
bin:
|
||||
katex: cli.js
|
||||
checksum: 10/7666ae11c6c1238626bffaf1a526af6ff679114d62293bf2f0e29f8a34d8e961c0edcb686c5b628158ec92a143b4bef5d83539c81b29a63c7dcf0bdb4544eec9
|
||||
checksum: 10/e9103def114d9d08ab216864e66b68e6f50a6360fdc5aa29d8edeee430e1618dd7551b9f080e9c591b3ee24c18fe6910b8fe0c89c7c4b1109abd2b63e223fbc5
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -27986,9 +28140,9 @@ __metadata:
|
||||
linkType: hard
|
||||
|
||||
"lru-cache@npm:^11.0.0":
|
||||
version: 11.1.0
|
||||
resolution: "lru-cache@npm:11.1.0"
|
||||
checksum: 10/5011011675ca98428902de774d0963b68c3a193cd959347cb63b781dad4228924124afab82159fd7b8b4db18285d9aff462b877b8f6efd2b41604f806c1d9db4
|
||||
version: 11.2.7
|
||||
resolution: "lru-cache@npm:11.2.7"
|
||||
checksum: 10/fbff4b8dee8189dde9b52cdfb3ea89b4c9cec094c1538cd30d1f47299477ff312efdb35f7994477ec72328f8e754e232b26a143feda1bd1f79ff22da6664d2c5
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -29127,11 +29281,11 @@ __metadata:
|
||||
linkType: hard
|
||||
|
||||
"minimatch@npm:^9.0.0, minimatch@npm:^9.0.3, minimatch@npm:^9.0.4, minimatch@npm:^9.0.5":
|
||||
version: 9.0.6
|
||||
resolution: "minimatch@npm:9.0.6"
|
||||
version: 9.0.9
|
||||
resolution: "minimatch@npm:9.0.9"
|
||||
dependencies:
|
||||
brace-expansion: "npm:^5.0.2"
|
||||
checksum: 10/c7a46134aaf349f386de9a3f6c5b48c53bc3a4e2ef4b8b6365184504e28cc31cc261a388e181648cbc756b40e213dbce115c8087a47eff8f54ee28d62bc17b08
|
||||
brace-expansion: "npm:^2.0.2"
|
||||
checksum: 10/b91fad937deaffb68a45a2cb731ff3cff1c3baf9b6469c879477ed16f15c8f4ce39d63a3f75c2455107c2fdff0f3ab597d97dc09e2e93b883aafcf926ef0c8f9
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -29234,9 +29388,9 @@ __metadata:
|
||||
linkType: hard
|
||||
|
||||
"minipass@npm:^5.0.0 || ^6.0.2 || ^7.0.0, minipass@npm:^7.0.2, minipass@npm:^7.0.3, minipass@npm:^7.0.4, minipass@npm:^7.1.2":
|
||||
version: 7.1.2
|
||||
resolution: "minipass@npm:7.1.2"
|
||||
checksum: 10/c25f0ee8196d8e6036661104bacd743785b2599a21de5c516b32b3fa2b83113ac89a2358465bc04956baab37ffb956ae43be679b2262bf7be15fce467ccd7950
|
||||
version: 7.1.3
|
||||
resolution: "minipass@npm:7.1.3"
|
||||
checksum: 10/175e4d5e20980c3cd316ae82d2c031c42f6c746467d8b1905b51060a0ba4461441a0c25bb67c025fd9617f9a3873e152c7b543c6b5ac83a1846be8ade80dffd6
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -29280,14 +29434,14 @@ __metadata:
|
||||
linkType: hard
|
||||
|
||||
"mlly@npm:^1.4.2, mlly@npm:^1.7.1, mlly@npm:^1.7.4":
|
||||
version: 1.7.4
|
||||
resolution: "mlly@npm:1.7.4"
|
||||
version: 1.8.1
|
||||
resolution: "mlly@npm:1.8.1"
|
||||
dependencies:
|
||||
acorn: "npm:^8.14.0"
|
||||
pathe: "npm:^2.0.1"
|
||||
pkg-types: "npm:^1.3.0"
|
||||
ufo: "npm:^1.5.4"
|
||||
checksum: 10/1b36163d38c2331f8ae480e6a11da3d15927a2148d729fcd9df6d0059ca74869aa693931bd1f762f82eb534b84c921bdfbc036eb0e4da4faeb55f1349d254f35
|
||||
acorn: "npm:^8.16.0"
|
||||
pathe: "npm:^2.0.3"
|
||||
pkg-types: "npm:^1.3.1"
|
||||
ufo: "npm:^1.6.3"
|
||||
checksum: 10/8e424f0615d09adfb7d59ad8f0c8245df275cd05e483a4631a1b2c5dd7e09913a9ce8182bc1562d569941ecee25ab03f4429284265471f562da1dd308008e237
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -29433,7 +29587,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"multer@npm:2.0.2, multer@npm:^2.0.2":
|
||||
"multer@npm:2.0.2":
|
||||
version: 2.0.2
|
||||
resolution: "multer@npm:2.0.2"
|
||||
dependencies:
|
||||
@@ -29448,6 +29602,18 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"multer@npm:^2.0.2":
|
||||
version: 2.1.1
|
||||
resolution: "multer@npm:2.1.1"
|
||||
dependencies:
|
||||
append-field: "npm:^1.0.0"
|
||||
busboy: "npm:^1.6.0"
|
||||
concat-stream: "npm:^2.0.0"
|
||||
type-is: "npm:^1.6.18"
|
||||
checksum: 10/fb22868caaed37d725715c14c60b740b81665265da3a026bb61954414f65b99f76b360128413b8a2a7cc1a95ecae28a42bf831fe172bb79682d19ec105b556bd
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"multicast-dns@npm:^7.2.5":
|
||||
version: 7.2.5
|
||||
resolution: "multicast-dns@npm:7.2.5"
|
||||
@@ -30483,9 +30649,9 @@ __metadata:
|
||||
linkType: hard
|
||||
|
||||
"p-map@npm:^7.0.2, p-map@npm:^7.0.3":
|
||||
version: 7.0.3
|
||||
resolution: "p-map@npm:7.0.3"
|
||||
checksum: 10/2ef48ccfc6dd387253d71bf502604f7893ed62090b2c9d73387f10006c342606b05233da0e4f29388227b61eb5aeface6197e166520c465c234552eeab2fe633
|
||||
version: 7.0.4
|
||||
resolution: "p-map@npm:7.0.4"
|
||||
checksum: 10/ef48c3b2e488f31c693c9fcc0df0ef76518cf6426a495cf9486ebbb0fd7f31aef7f90e96f72e0070c0ff6e3177c9318f644b512e2c29e3feee8d7153fcb6782e
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -30825,12 +30991,12 @@ __metadata:
|
||||
linkType: hard
|
||||
|
||||
"path-scurry@npm:^2.0.0":
|
||||
version: 2.0.0
|
||||
resolution: "path-scurry@npm:2.0.0"
|
||||
version: 2.0.2
|
||||
resolution: "path-scurry@npm:2.0.2"
|
||||
dependencies:
|
||||
lru-cache: "npm:^11.0.0"
|
||||
minipass: "npm:^7.1.2"
|
||||
checksum: 10/285ae0c2d6c34ae91dc1d5378ede21981c9a2f6de1ea9ca5a88b5a270ce9763b83dbadc7a324d512211d8d36b0c540427d3d0817030849d97a60fa840a2c59ec
|
||||
checksum: 10/2b4257422bcb870a4c2d205b3acdbb213a72f5e2250f61c80f79c9d014d010f82bdf8584441612c8e1fa4eb098678f5704a66fa8377d72646bad4be38e57a2c3
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -30848,7 +31014,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"path-to-regexp@npm:8.3.0, path-to-regexp@npm:^8.0.0, path-to-regexp@npm:^8.3.0":
|
||||
"path-to-regexp@npm:8.3.0":
|
||||
version: 8.3.0
|
||||
resolution: "path-to-regexp@npm:8.3.0"
|
||||
checksum: 10/568f148fc64f5fd1ecebf44d531383b28df924214eabf5f2570dce9587a228e36c37882805ff02d71c6209b080ea3ee6a4d2b712b5df09741b67f1f3cf91e55a
|
||||
@@ -30862,6 +31028,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"path-to-regexp@npm:^8.0.0, path-to-regexp@npm:^8.3.0":
|
||||
version: 8.4.0
|
||||
resolution: "path-to-regexp@npm:8.4.0"
|
||||
checksum: 10/6864561ceacaece330a2213c6eb21505519673a65b4249e0e5d518984528f93b302b8bf85ccafc4f9d7f359f919d8b118dc00fdb0b26ded3d21e8802cffdfcb8
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"path-to-regexp@npm:~0.1.12":
|
||||
version: 0.1.12
|
||||
resolution: "path-to-regexp@npm:0.1.12"
|
||||
@@ -31076,7 +31249,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"pkg-types@npm:^1.2.0, pkg-types@npm:^1.3.0, pkg-types@npm:^1.3.1":
|
||||
"pkg-types@npm:^1.2.0, pkg-types@npm:^1.3.1":
|
||||
version: 1.3.1
|
||||
resolution: "pkg-types@npm:1.3.1"
|
||||
dependencies:
|
||||
@@ -31651,11 +31824,11 @@ __metadata:
|
||||
linkType: hard
|
||||
|
||||
"pretty-ms@npm:^9.0.0, pretty-ms@npm:^9.2.0":
|
||||
version: 9.2.0
|
||||
resolution: "pretty-ms@npm:9.2.0"
|
||||
version: 9.3.0
|
||||
resolution: "pretty-ms@npm:9.3.0"
|
||||
dependencies:
|
||||
parse-ms: "npm:^4.0.0"
|
||||
checksum: 10/a65a1d81560867f4f7128862fdbf0e1c2d3c5607bf75cae7758bf8111e2c4b744be46e084704125a38ba918bb43defa7a53aaff0f48c5c2d95367d3148c980d9
|
||||
checksum: 10/beb4e04dc17071885b827e3f33d36be279791f2f36a8c29a45c77e59979dad79a5d7e5211922c72a3f6f109bb64a707d70fcdba6746e077122afcd88ce202e98
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -33431,9 +33604,9 @@ __metadata:
|
||||
linkType: hard
|
||||
|
||||
"sax@npm:>=0.6.0, sax@npm:^1.2.4, sax@npm:^1.4.1":
|
||||
version: 1.4.1
|
||||
resolution: "sax@npm:1.4.1"
|
||||
checksum: 10/b1c784b545019187b53a0c28edb4f6314951c971e2963a69739c6ce222bfbc767e54d320e689352daba79b7d5e06d22b5d7113b99336219d6e93718e2f99d335
|
||||
version: 1.5.0
|
||||
resolution: "sax@npm:1.5.0"
|
||||
checksum: 10/9012ff37dda7a7ac5da45db2143b04036103e8bef8d586c3023afd5df6caf0ebd7f38017eee344ad2e2247eded7d38e9c42cf291d8dd91781352900ac0fd2d9f
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -33523,7 +33696,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"semver@npm:7.7.4, semver@npm:^7.0.0, semver@npm:^7.1.1, semver@npm:^7.1.3, semver@npm:^7.2.1, semver@npm:^7.3.2, semver@npm:^7.3.5, semver@npm:^7.3.8, semver@npm:^7.5.3, semver@npm:^7.5.4, semver@npm:^7.6.0, semver@npm:^7.6.2, semver@npm:^7.6.3, semver@npm:^7.7.1, semver@npm:^7.7.2, semver@npm:^7.7.3, semver@npm:~7.7.3":
|
||||
"semver@npm:7.7.4, semver@npm:^7.0.0, semver@npm:^7.1.1, semver@npm:^7.1.3, semver@npm:^7.2.1, semver@npm:^7.3.2, semver@npm:^7.3.5, semver@npm:^7.3.8, semver@npm:^7.5.3, semver@npm:^7.5.4, semver@npm:^7.6.0, semver@npm:^7.6.2, semver@npm:^7.6.3, semver@npm:^7.7.1, semver@npm:^7.7.2, semver@npm:^7.7.3, semver@npm:^7.7.4, semver@npm:~7.7.3":
|
||||
version: 7.7.4
|
||||
resolution: "semver@npm:7.7.4"
|
||||
bin:
|
||||
@@ -34511,11 +34684,11 @@ __metadata:
|
||||
linkType: hard
|
||||
|
||||
"strip-ansi@npm:^7.0.1, strip-ansi@npm:^7.1.0":
|
||||
version: 7.1.0
|
||||
resolution: "strip-ansi@npm:7.1.0"
|
||||
version: 7.2.0
|
||||
resolution: "strip-ansi@npm:7.2.0"
|
||||
dependencies:
|
||||
ansi-regex: "npm:^6.0.1"
|
||||
checksum: 10/475f53e9c44375d6e72807284024ac5d668ee1d06010740dec0b9744f2ddf47de8d7151f80e5f6190fc8f384e802fdf9504b76a7e9020c9faee7103623338be2
|
||||
ansi-regex: "npm:^6.2.2"
|
||||
checksum: 10/96da3bc6d73cfba1218625a3d66cf7d37a69bf0920d8735b28f9eeaafcdb6c1fe8440e1ae9eb1ba0ca355dbe8702da872e105e2e939fa93e7851b3cb5dd7d316
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -35144,9 +35317,9 @@ __metadata:
|
||||
linkType: hard
|
||||
|
||||
"tinyexec@npm:^1.0.0, tinyexec@npm:^1.0.1":
|
||||
version: 1.0.1
|
||||
resolution: "tinyexec@npm:1.0.1"
|
||||
checksum: 10/1f3c3281912d4ab168e067baf46627bb85a803eba0bcea113bba9fe8bdfdcc279cad08052a600d4b8fb603dd57e1af0c500e50a5e7e6b29b2574c88556f41fa6
|
||||
version: 1.0.4
|
||||
resolution: "tinyexec@npm:1.0.4"
|
||||
checksum: 10/ccebe4044eef6fa5050929df7862fda70b4fb700f15d94aef8ae6109b9d194dbc3a990125d99944fd25b90fe2115e1927f055b909a604c571a81b647ede5757a
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -35676,10 +35849,10 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"ufo@npm:^1.5.4":
|
||||
version: 1.6.1
|
||||
resolution: "ufo@npm:1.6.1"
|
||||
checksum: 10/088a68133b93af183b093e5a8730a40fe7fd675d3dc0656ea7512f180af45c92300c294f14d4d46d4b2b553e3e52d3b13d4856b9885e620e7001edf85531234e
|
||||
"ufo@npm:^1.5.4, ufo@npm:^1.6.3":
|
||||
version: 1.6.3
|
||||
resolution: "ufo@npm:1.6.3"
|
||||
checksum: 10/79803984f3e414567273a666183d6a50d1bec0d852100a98f55c1e393cb705e3b88033e04029dd651714e6eec99e1b00f54fdc13f32404968251a16f8898cfe5
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -37022,8 +37195,8 @@ __metadata:
|
||||
linkType: hard
|
||||
|
||||
"ws@npm:^8.17.1, ws@npm:^8.18.0, ws@npm:^8.18.2, ws@npm:^8.18.3":
|
||||
version: 8.19.0
|
||||
resolution: "ws@npm:8.19.0"
|
||||
version: 8.20.0
|
||||
resolution: "ws@npm:8.20.0"
|
||||
peerDependencies:
|
||||
bufferutil: ^4.0.1
|
||||
utf-8-validate: ">=5.0.2"
|
||||
@@ -37032,7 +37205,7 @@ __metadata:
|
||||
optional: true
|
||||
utf-8-validate:
|
||||
optional: true
|
||||
checksum: 10/26e4901e93abaf73af9f26a93707c95b4845e91a7a347ec8c569e6e9be7f9df066f6c2b817b2d685544e208207898a750b78461e6e8d810c11a370771450c31b
|
||||
checksum: 10/b7ab934b21ffdea9f25a5af5097e8c1ec7625db553bca026c5a23e35b7c236f3fb89782f2b57fab9da553864512f9aa7d245827ef998d26ffa1b2187a19a6d10
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
|
||||
Reference in New Issue
Block a user