mirror of
https://github.com/fluxerapp/fluxer
synced 2026-10-07 19:22:14 +09:00
build(api): bundle the api instead of transpiling at boot (#2227)
This commit is contained in:
@@ -325,7 +325,7 @@ services:
|
|||||||
limits:
|
limits:
|
||||||
memory: 1536mb
|
memory: 1536mb
|
||||||
working_dir: /usr/src/app/fluxer_api
|
working_dir: /usr/src/app/fluxer_api
|
||||||
command: ["./node_modules/.bin/tsx", "src/WorkerEntrypoint.ts"]
|
command: ["node", "dist/WorkerEntrypoint.js"]
|
||||||
environment:
|
environment:
|
||||||
<<: *fluxer-env
|
<<: *fluxer-env
|
||||||
FLUXER_API_WORKER_MODE: all_lanes
|
FLUXER_API_WORKER_MODE: all_lanes
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ COPY . .
|
|||||||
|
|
||||||
RUN pnpm install --frozen-lockfile
|
RUN pnpm install --frozen-lockfile
|
||||||
RUN pnpm --filter @fluxer/config run --if-present generate
|
RUN pnpm --filter @fluxer/config run --if-present generate
|
||||||
|
RUN pnpm --filter fluxer_api run build
|
||||||
RUN pnpm deploy --legacy --filter=fluxer_api --prod /out
|
RUN pnpm deploy --legacy --filter=fluxer_api --prod /out
|
||||||
|
|
||||||
FROM node:24-bookworm-slim
|
FROM node:24-bookworm-slim
|
||||||
@@ -48,6 +49,7 @@ RUN echo 'deb http://deb.debian.org/debian bookworm-backports main' > /etc/apt/s
|
|||||||
RUN corepack enable && corepack prepare [email protected] --activate
|
RUN corepack enable && corepack prepare [email protected] --activate
|
||||||
|
|
||||||
COPY --from=deploy /out ./
|
COPY --from=deploy /out ./
|
||||||
|
COPY --from=deploy /usr/src/app/fluxer_api/dist ./dist
|
||||||
COPY --from=deploy /usr/src/app/tsconfigs /usr/src/app/tsconfigs
|
COPY --from=deploy /usr/src/app/tsconfigs /usr/src/app/tsconfigs
|
||||||
|
|
||||||
RUN rm -rf pkgs && \
|
RUN rm -rf pkgs && \
|
||||||
@@ -57,7 +59,7 @@ RUN rm -rf pkgs && \
|
|||||||
ENV HOME=/usr/src/app
|
ENV HOME=/usr/src/app
|
||||||
ENV COREPACK_HOME=/usr/src/app/.cache/corepack
|
ENV COREPACK_HOME=/usr/src/app/.cache/corepack
|
||||||
ENV NODE_ENV=production
|
ENV NODE_ENV=production
|
||||||
ENV NODE_OPTIONS="--max-old-space-size=2048"
|
ENV NODE_OPTIONS="--max-old-space-size=2048 --enable-source-maps"
|
||||||
ENV NODE_EXTRA_CA_CERTS=/etc/ssl/certs/ca-certificates.crt
|
ENV NODE_EXTRA_CA_CERTS=/etc/ssl/certs/ca-certificates.crt
|
||||||
ENV BUILD_VERSION=${BUILD_VERSION}
|
ENV BUILD_VERSION=${BUILD_VERSION}
|
||||||
|
|
||||||
@@ -65,4 +67,4 @@ USER 65532:65532
|
|||||||
|
|
||||||
EXPOSE 8080
|
EXPOSE 8080
|
||||||
|
|
||||||
CMD ["./node_modules/.bin/tsx", "src/AppEntrypoint.ts"]
|
CMD ["node", "dist/AppEntrypoint.js"]
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
"build": "node scripts/build.mjs",
|
||||||
"test": "vitest run",
|
"test": "vitest run",
|
||||||
"typecheck": "tsgo --noEmit",
|
"typecheck": "tsgo --noEmit",
|
||||||
"dev": "tsx watch --clear-screen=false src/AppEntrypoint.ts",
|
"dev": "tsx watch --clear-screen=false src/AppEntrypoint.ts",
|
||||||
@@ -17,6 +18,7 @@
|
|||||||
"@bluesky-social/jwk-jose": "catalog:",
|
"@bluesky-social/jwk-jose": "catalog:",
|
||||||
"@bluesky-social/oauth-client-node": "catalog:",
|
"@bluesky-social/oauth-client-node": "catalog:",
|
||||||
"@bufbuild/protobuf": "^2.12.0",
|
"@bufbuild/protobuf": "^2.12.0",
|
||||||
|
"@elastic/elasticsearch": "catalog:",
|
||||||
"@fluxer/config": "workspace:*",
|
"@fluxer/config": "workspace:*",
|
||||||
"@fluxer/constants": "workspace:*",
|
"@fluxer/constants": "workspace:*",
|
||||||
"@fluxer/date_utils": "workspace:*",
|
"@fluxer/date_utils": "workspace:*",
|
||||||
@@ -29,6 +31,9 @@
|
|||||||
"@fluxer/logger": "workspace:*",
|
"@fluxer/logger": "workspace:*",
|
||||||
"@fluxer/schema": "workspace:*",
|
"@fluxer/schema": "workspace:*",
|
||||||
"@fluxer/snowflake": "workspace:*",
|
"@fluxer/snowflake": "workspace:*",
|
||||||
|
"@hono/node-server": "catalog:",
|
||||||
|
"@messageformat/core": "catalog:",
|
||||||
|
"@messageformat/parser": "catalog:",
|
||||||
"@pkgs/cache": "workspace:*",
|
"@pkgs/cache": "workspace:*",
|
||||||
"@pkgs/captcha": "workspace:*",
|
"@pkgs/captcha": "workspace:*",
|
||||||
"@pkgs/cassandra": "workspace:*",
|
"@pkgs/cassandra": "workspace:*",
|
||||||
@@ -49,28 +54,36 @@
|
|||||||
"@pkgs/worker": "workspace:*",
|
"@pkgs/worker": "workspace:*",
|
||||||
"@simplewebauthn/server": "catalog:",
|
"@simplewebauthn/server": "catalog:",
|
||||||
"@types/node": "catalog:",
|
"@types/node": "catalog:",
|
||||||
|
"@vvo/tzdb": "catalog:",
|
||||||
"archiver": "catalog:",
|
"archiver": "catalog:",
|
||||||
"argon2": "catalog:",
|
"argon2": "catalog:",
|
||||||
"bowser": "catalog:",
|
"bowser": "catalog:",
|
||||||
"cassandra-driver": "catalog:",
|
"cassandra-driver": "catalog:",
|
||||||
|
"emoji-regex": "catalog:",
|
||||||
"fast-xml-parser": "catalog:",
|
"fast-xml-parser": "catalog:",
|
||||||
"hi-base32": "catalog:",
|
"hi-base32": "catalog:",
|
||||||
"hono": "catalog:",
|
"hono": "catalog:",
|
||||||
"html-entities": "catalog:",
|
"html-entities": "catalog:",
|
||||||
"idna-uts46-hx": "catalog:",
|
"idna-uts46-hx": "catalog:",
|
||||||
|
"ioredis": "catalog:",
|
||||||
"itty-time": "catalog:",
|
"itty-time": "catalog:",
|
||||||
"jose": "catalog:",
|
"jose": "catalog:",
|
||||||
"livekit-server-sdk": "catalog:",
|
"livekit-server-sdk": "catalog:",
|
||||||
"lodash": "catalog:",
|
"lodash": "catalog:",
|
||||||
"luxon": "catalog:",
|
"luxon": "catalog:",
|
||||||
|
"maxmind": "catalog:",
|
||||||
"mime": "catalog:",
|
"mime": "catalog:",
|
||||||
"nats": "catalog:",
|
"nats": "catalog:",
|
||||||
|
"nodemailer": "catalog:",
|
||||||
|
"pg": "catalog:",
|
||||||
|
"pino": "catalog:",
|
||||||
"sharp": "catalog:",
|
"sharp": "catalog:",
|
||||||
"stripe": "catalog:",
|
"stripe": "catalog:",
|
||||||
"tempy": "catalog:",
|
"tempy": "catalog:",
|
||||||
"transliteration": "catalog:",
|
"transliteration": "catalog:",
|
||||||
"tsx": "catalog:",
|
"tsx": "catalog:",
|
||||||
"uint8array-extras": "catalog:",
|
"uint8array-extras": "catalog:",
|
||||||
|
"validator": "catalog:",
|
||||||
"zod": "catalog:"
|
"zod": "catalog:"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
@@ -78,6 +91,7 @@
|
|||||||
"@types/lodash": "catalog:",
|
"@types/lodash": "catalog:",
|
||||||
"@types/luxon": "catalog:",
|
"@types/luxon": "catalog:",
|
||||||
"@typescript/native-preview": "catalog:",
|
"@typescript/native-preview": "catalog:",
|
||||||
|
"esbuild": "catalog:",
|
||||||
"msw": "catalog:",
|
"msw": "catalog:",
|
||||||
"vite-tsconfig-paths": "catalog:",
|
"vite-tsconfig-paths": "catalog:",
|
||||||
"vitest": "catalog:"
|
"vitest": "catalog:"
|
||||||
|
|||||||
@@ -0,0 +1,87 @@
|
|||||||
|
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
|
||||||
|
import {existsSync, readFileSync, rmSync, statSync} from 'node:fs';
|
||||||
|
import {isBuiltin} from 'node:module';
|
||||||
|
import {dirname, join, resolve} from 'node:path';
|
||||||
|
import {fileURLToPath} from 'node:url';
|
||||||
|
import {build} from 'esbuild';
|
||||||
|
|
||||||
|
const API_ROOT = resolve(dirname(fileURLToPath(import.meta.url)), '..');
|
||||||
|
const REPO_ROOT = resolve(API_ROOT, '..');
|
||||||
|
const OUT_DIR = join(API_ROOT, 'dist');
|
||||||
|
const CANDIDATE_SUFFIXES = ['', '.ts', '.tsx', '.js', '.mjs', '/index.ts', '/index.tsx', '/index.js', '/src/index.ts'];
|
||||||
|
|
||||||
|
const WORKSPACE_ROOTS = {
|
||||||
|
'@app/': join(API_ROOT, 'src'),
|
||||||
|
'@pkgs/': join(API_ROOT, 'pkgs'),
|
||||||
|
'@fluxer/': join(REPO_ROOT, 'packages'),
|
||||||
|
};
|
||||||
|
|
||||||
|
function resolveWorkspacePath(specifier) {
|
||||||
|
for (const [prefix, root] of Object.entries(WORKSPACE_ROOTS)) {
|
||||||
|
if (!specifier.startsWith(prefix)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const base = join(root, specifier.slice(prefix.length));
|
||||||
|
for (const suffix of CANDIDATE_SUFFIXES) {
|
||||||
|
const candidate = `${base}${suffix}`;
|
||||||
|
if (existsSync(candidate) && statSync(candidate).isFile()) {
|
||||||
|
return candidate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new Error(`Unable to resolve workspace import ${specifier}`);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function packageNameOf(specifier) {
|
||||||
|
const segments = specifier.split('/');
|
||||||
|
return specifier.startsWith('@') ? segments.slice(0, 2).join('/') : segments[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
const declaredDependencies = new Set(
|
||||||
|
Object.keys(JSON.parse(readFileSync(join(API_ROOT, 'package.json'), 'utf-8')).dependencies),
|
||||||
|
);
|
||||||
|
const undeclaredDependencies = new Set();
|
||||||
|
|
||||||
|
const workspacePlugin = {
|
||||||
|
name: 'fluxer-workspace',
|
||||||
|
setup(pluginBuild) {
|
||||||
|
pluginBuild.onResolve({filter: /^[^./]/}, (args) => {
|
||||||
|
const workspacePath = resolveWorkspacePath(args.path);
|
||||||
|
if (workspacePath) {
|
||||||
|
return {path: workspacePath};
|
||||||
|
}
|
||||||
|
const packageName = packageNameOf(args.path);
|
||||||
|
if (!isBuiltin(args.path) && !declaredDependencies.has(packageName)) {
|
||||||
|
undeclaredDependencies.add(packageName);
|
||||||
|
}
|
||||||
|
return {path: args.path, external: true};
|
||||||
|
});
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
rmSync(OUT_DIR, {recursive: true, force: true});
|
||||||
|
|
||||||
|
await build({
|
||||||
|
entryPoints: [join(API_ROOT, 'src/AppEntrypoint.ts'), join(API_ROOT, 'src/WorkerEntrypoint.ts')],
|
||||||
|
outdir: OUT_DIR,
|
||||||
|
bundle: true,
|
||||||
|
platform: 'node',
|
||||||
|
format: 'esm',
|
||||||
|
target: 'node24',
|
||||||
|
charset: 'utf8',
|
||||||
|
sourcemap: true,
|
||||||
|
sourcesContent: false,
|
||||||
|
logLevel: 'info',
|
||||||
|
banner: {js: '// SPDX-License-Identifier: AGPL-3.0-or-later'},
|
||||||
|
plugins: [workspacePlugin],
|
||||||
|
});
|
||||||
|
|
||||||
|
if (undeclaredDependencies.size > 0) {
|
||||||
|
const names = [...undeclaredDependencies].sort().join(', ');
|
||||||
|
throw new Error(
|
||||||
|
`The bundle imports packages that fluxer_api does not declare as dependencies: ${names}. ` +
|
||||||
|
'Workspace packages keep their own node_modules, so the bundle cannot reach them from fluxer_api.',
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,14 +1,13 @@
|
|||||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
|
||||||
import * as fs from 'node:fs';
|
import * as fs from 'node:fs';
|
||||||
import * as path from 'node:path';
|
|
||||||
import {fileURLToPath} from 'node:url';
|
|
||||||
import type {Hono} from 'hono';
|
import type {Hono} from 'hono';
|
||||||
import {RateLimitMiddleware} from '../middleware/RateLimitMiddleware';
|
import {RateLimitMiddleware} from '../middleware/RateLimitMiddleware';
|
||||||
import {RateLimitConfigs} from '../RateLimitConfig';
|
import {RateLimitConfigs} from '../RateLimitConfig';
|
||||||
import type {HonoEnv} from '../types/HonoEnv';
|
import type {HonoEnv} from '../types/HonoEnv';
|
||||||
|
import {resolveAssetPath} from '../utils/AssetPaths';
|
||||||
|
|
||||||
const SPEC_PATH = path.join(path.dirname(fileURLToPath(import.meta.url)), 'openapi.json');
|
const SPEC_PATH = resolveAssetPath('openapi', 'openapi.json');
|
||||||
const SPEC_BODY = fs.readFileSync(SPEC_PATH, 'utf-8');
|
const SPEC_BODY = fs.readFileSync(SPEC_PATH, 'utf-8');
|
||||||
|
|
||||||
export function OpenAPIController(app: Hono<HonoEnv>): void {
|
export function OpenAPIController(app: Hono<HonoEnv>): void {
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
|
||||||
|
import {existsSync} from 'node:fs';
|
||||||
|
import {dirname, join} from 'node:path';
|
||||||
|
import {fileURLToPath} from 'node:url';
|
||||||
|
|
||||||
|
function findPackageRoot(startDir: string): string {
|
||||||
|
let current = startDir;
|
||||||
|
while (!existsSync(join(current, 'package.json'))) {
|
||||||
|
const parent = dirname(current);
|
||||||
|
if (parent === current) {
|
||||||
|
throw new Error(`Unable to locate the fluxer_api package root from ${startDir}`);
|
||||||
|
}
|
||||||
|
current = parent;
|
||||||
|
}
|
||||||
|
return current;
|
||||||
|
}
|
||||||
|
|
||||||
|
const PACKAGE_ROOT = findPackageRoot(dirname(fileURLToPath(import.meta.url)));
|
||||||
|
|
||||||
|
export function resolveAssetPath(...segments: Array<string>): string {
|
||||||
|
return join(PACKAGE_ROOT, 'src', 'api', ...segments);
|
||||||
|
}
|
||||||
@@ -2,13 +2,11 @@
|
|||||||
|
|
||||||
import {randomInt} from 'node:crypto';
|
import {randomInt} from 'node:crypto';
|
||||||
import {readFileSync} from 'node:fs';
|
import {readFileSync} from 'node:fs';
|
||||||
import {dirname, resolve} from 'node:path';
|
|
||||||
import {fileURLToPath} from 'node:url';
|
|
||||||
import {UsernameType} from '@fluxer/schema/src/primitives/UserValidators';
|
import {UsernameType} from '@fluxer/schema/src/primitives/UserValidators';
|
||||||
|
import {resolveAssetPath} from './AssetPaths';
|
||||||
|
|
||||||
const WORDS_DIR = resolve(dirname(fileURLToPath(import.meta.url)), '..', 'words');
|
const scales = readFileSync(resolveAssetPath('words', 'scales.txt'), 'utf-8').trim().split('\n').filter(Boolean);
|
||||||
const scales = readFileSync(resolve(WORDS_DIR, 'scales.txt'), 'utf-8').trim().split('\n').filter(Boolean);
|
const tails = readFileSync(resolveAssetPath('words', 'tails.txt'), 'utf-8').trim().split('\n').filter(Boolean);
|
||||||
const tails = readFileSync(resolve(WORDS_DIR, 'tails.txt'), 'utf-8').trim().split('\n').filter(Boolean);
|
|
||||||
|
|
||||||
function capitalize(word: string): string {
|
function capitalize(word: string): string {
|
||||||
return word.charAt(0).toUpperCase() + word.slice(1);
|
return word.charAt(0).toUpperCase() + word.slice(1);
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ import type {RequestCache} from '../middleware/RequestCacheMiddleware';
|
|||||||
import type {Channel} from '../models/Channel';
|
import type {Channel} from '../models/Channel';
|
||||||
import type {Message} from '../models/Message';
|
import type {Message} from '../models/Message';
|
||||||
import type {Webhook} from '../models/Webhook';
|
import type {Webhook} from '../models/Webhook';
|
||||||
|
import {resolveAssetPath} from '../utils/AssetPaths';
|
||||||
import * as RandomUtils from '../utils/RandomUtils';
|
import * as RandomUtils from '../utils/RandomUtils';
|
||||||
import type {IWebhookRepository} from './IWebhookRepository';
|
import type {IWebhookRepository} from './IWebhookRepository';
|
||||||
import {transform as GitHubTransform} from './transformers/GitHubTransformer';
|
import {transform as GitHubTransform} from './transformers/GitHubTransformer';
|
||||||
@@ -620,7 +621,7 @@ export class WebhookService {
|
|||||||
const cacheKey = `webhook:${webhookId}:avatar:${provider}`;
|
const cacheKey = `webhook:${webhookId}:avatar:${provider}`;
|
||||||
const avatarCache = await this.cacheService.get<string | null>(cacheKey);
|
const avatarCache = await this.cacheService.get<string | null>(cacheKey);
|
||||||
if (avatarCache) return avatarCache;
|
if (avatarCache) return avatarCache;
|
||||||
const avatarFile = await fs.readFile(new URL(`../assets/${provider}.webp`, import.meta.url));
|
const avatarFile = await fs.readFile(resolveAssetPath('assets', `${provider}.webp`));
|
||||||
const avatar = await this.avatarService.uploadAvatar({
|
const avatar = await this.avatarService.uploadAvatar({
|
||||||
prefix: 'avatars',
|
prefix: 'avatars',
|
||||||
entityId: webhookId,
|
entityId: webhookId,
|
||||||
|
|||||||
@@ -2,11 +2,7 @@
|
|||||||
|
|
||||||
import {randomInt} from 'node:crypto';
|
import {randomInt} from 'node:crypto';
|
||||||
import * as fs from 'node:fs';
|
import * as fs from 'node:fs';
|
||||||
import * as path from 'node:path';
|
import {resolveAssetPath} from '../utils/AssetPaths';
|
||||||
import {fileURLToPath} from 'node:url';
|
|
||||||
|
|
||||||
const __filename = fileURLToPath(import.meta.url);
|
|
||||||
const __dirname = path.dirname(__filename);
|
|
||||||
|
|
||||||
let tails: Array<string> | undefined;
|
let tails: Array<string> | undefined;
|
||||||
let scales: Array<string> | undefined;
|
let scales: Array<string> | undefined;
|
||||||
@@ -34,9 +30,8 @@ export function generateConnectionId(): string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function initWords(): void {
|
function initWords(): void {
|
||||||
const wordsDir = path.join(__dirname);
|
tails = parseWordsFile(resolveAssetPath('words', 'tails.txt'));
|
||||||
tails = parseWordsFile(path.join(wordsDir, 'tails.txt'));
|
scales = parseWordsFile(resolveAssetPath('words', 'scales.txt'));
|
||||||
scales = parseWordsFile(path.join(wordsDir, 'scales.txt'));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseWordsFile(filePath: string): Array<string> {
|
function parseWordsFile(filePath: string): Array<string> {
|
||||||
|
|||||||
@@ -30,6 +30,22 @@
|
|||||||
".": {
|
".": {
|
||||||
"project": ["scripts/**/*.mjs"]
|
"project": ["scripts/**/*.mjs"]
|
||||||
},
|
},
|
||||||
|
"fluxer_api": {
|
||||||
|
"ignoreDependencies": [
|
||||||
|
"@elastic/elasticsearch",
|
||||||
|
"@hono/node-server",
|
||||||
|
"@messageformat/core",
|
||||||
|
"@messageformat/parser",
|
||||||
|
"@vvo/tzdb",
|
||||||
|
"emoji-regex",
|
||||||
|
"ioredis",
|
||||||
|
"maxmind",
|
||||||
|
"nodemailer",
|
||||||
|
"pg",
|
||||||
|
"pino",
|
||||||
|
"validator"
|
||||||
|
]
|
||||||
|
},
|
||||||
"fluxer_app": {
|
"fluxer_app": {
|
||||||
"entry": ["lingui.config.js", "scripts/build-sw.mjs", "scripts/Generate*.ts"],
|
"entry": ["lingui.config.js", "scripts/build-sw.mjs", "scripts/Generate*.ts"],
|
||||||
"ignoreDependencies": ["@lingui/swc-plugin"]
|
"ignoreDependencies": ["@lingui/swc-plugin"]
|
||||||
|
|||||||
Generated
+42
-10
@@ -440,6 +440,9 @@ importers:
|
|||||||
'@bufbuild/protobuf':
|
'@bufbuild/protobuf':
|
||||||
specifier: ^2.12.0
|
specifier: ^2.12.0
|
||||||
version: 2.12.0
|
version: 2.12.0
|
||||||
|
'@elastic/elasticsearch':
|
||||||
|
specifier: 'catalog:'
|
||||||
|
version: 9.3.2
|
||||||
'@fluxer/config':
|
'@fluxer/config':
|
||||||
specifier: workspace:*
|
specifier: workspace:*
|
||||||
version: link:../packages/config
|
version: link:../packages/config
|
||||||
@@ -476,6 +479,15 @@ importers:
|
|||||||
'@fluxer/snowflake':
|
'@fluxer/snowflake':
|
||||||
specifier: workspace:*
|
specifier: workspace:*
|
||||||
version: link:../packages/snowflake
|
version: link:../packages/snowflake
|
||||||
|
'@hono/node-server':
|
||||||
|
specifier: 'catalog:'
|
||||||
|
version: 1.19.9(patch_hash=8736af0d82dad75a667b7daed93f88c00065adc9a809d526353e290b150827ed)([email protected])
|
||||||
|
'@messageformat/core':
|
||||||
|
specifier: 'catalog:'
|
||||||
|
version: 3.4.0
|
||||||
|
'@messageformat/parser':
|
||||||
|
specifier: 'catalog:'
|
||||||
|
version: 5.1.1
|
||||||
'@pkgs/cache':
|
'@pkgs/cache':
|
||||||
specifier: workspace:*
|
specifier: workspace:*
|
||||||
version: link:pkgs/cache
|
version: link:pkgs/cache
|
||||||
@@ -536,6 +548,9 @@ importers:
|
|||||||
'@types/node':
|
'@types/node':
|
||||||
specifier: 'catalog:'
|
specifier: 'catalog:'
|
||||||
version: 25.3.0
|
version: 25.3.0
|
||||||
|
'@vvo/tzdb':
|
||||||
|
specifier: 'catalog:'
|
||||||
|
version: 6.198.0
|
||||||
archiver:
|
archiver:
|
||||||
specifier: 'catalog:'
|
specifier: 'catalog:'
|
||||||
version: 7.0.1
|
version: 7.0.1
|
||||||
@@ -548,6 +563,9 @@ importers:
|
|||||||
cassandra-driver:
|
cassandra-driver:
|
||||||
specifier: 'catalog:'
|
specifier: 'catalog:'
|
||||||
version: 4.8.0
|
version: 4.8.0
|
||||||
|
emoji-regex:
|
||||||
|
specifier: 'catalog:'
|
||||||
|
version: 10.6.0
|
||||||
fast-xml-parser:
|
fast-xml-parser:
|
||||||
specifier: 'catalog:'
|
specifier: 'catalog:'
|
||||||
version: 5.3.7
|
version: 5.3.7
|
||||||
@@ -563,6 +581,9 @@ importers:
|
|||||||
idna-uts46-hx:
|
idna-uts46-hx:
|
||||||
specifier: 'catalog:'
|
specifier: 'catalog:'
|
||||||
version: 6.1.1
|
version: 6.1.1
|
||||||
|
ioredis:
|
||||||
|
specifier: 'catalog:'
|
||||||
|
version: 5.9.3
|
||||||
itty-time:
|
itty-time:
|
||||||
specifier: 'catalog:'
|
specifier: 'catalog:'
|
||||||
version: 2.0.2
|
version: 2.0.2
|
||||||
@@ -578,12 +599,24 @@ importers:
|
|||||||
luxon:
|
luxon:
|
||||||
specifier: 'catalog:'
|
specifier: 'catalog:'
|
||||||
version: 3.7.2
|
version: 3.7.2
|
||||||
|
maxmind:
|
||||||
|
specifier: 'catalog:'
|
||||||
|
version: 5.0.5
|
||||||
mime:
|
mime:
|
||||||
specifier: 'catalog:'
|
specifier: 'catalog:'
|
||||||
version: 4.1.0
|
version: 4.1.0
|
||||||
nats:
|
nats:
|
||||||
specifier: 'catalog:'
|
specifier: 'catalog:'
|
||||||
version: 2.29.3
|
version: 2.29.3
|
||||||
|
nodemailer:
|
||||||
|
specifier: 'catalog:'
|
||||||
|
version: 8.0.1
|
||||||
|
pg:
|
||||||
|
specifier: 'catalog:'
|
||||||
|
version: 8.16.3
|
||||||
|
pino:
|
||||||
|
specifier: 'catalog:'
|
||||||
|
version: 10.3.1
|
||||||
sharp:
|
sharp:
|
||||||
specifier: 'catalog:'
|
specifier: 'catalog:'
|
||||||
version: 0.34.5
|
version: 0.34.5
|
||||||
@@ -602,6 +635,9 @@ importers:
|
|||||||
uint8array-extras:
|
uint8array-extras:
|
||||||
specifier: 'catalog:'
|
specifier: 'catalog:'
|
||||||
version: 1.5.0
|
version: 1.5.0
|
||||||
|
validator:
|
||||||
|
specifier: 'catalog:'
|
||||||
|
version: 13.15.26
|
||||||
zod:
|
zod:
|
||||||
specifier: 'catalog:'
|
specifier: 'catalog:'
|
||||||
version: 4.3.6
|
version: 4.3.6
|
||||||
@@ -618,6 +654,9 @@ importers:
|
|||||||
'@typescript/native-preview':
|
'@typescript/native-preview':
|
||||||
specifier: 'catalog:'
|
specifier: 'catalog:'
|
||||||
version: 7.0.0-dev.20260224.1
|
version: 7.0.0-dev.20260224.1
|
||||||
|
esbuild:
|
||||||
|
specifier: 'catalog:'
|
||||||
|
version: 0.27.3
|
||||||
msw:
|
msw:
|
||||||
specifier: 'catalog:'
|
specifier: 'catalog:'
|
||||||
version: 2.12.10(@types/[email protected])([email protected])
|
version: 2.12.10(@types/[email protected])([email protected])
|
||||||
@@ -10874,10 +10913,6 @@ packages:
|
|||||||
resolution: {integrity: sha512-4yqz8a3n5HmGTlsbADNtr/dJlhkh/55Rq798G6ibiULcXbDtaLpTl1pvdqcbFfeoj3iSi52lePFM7h9H21cw/A==}
|
resolution: {integrity: sha512-4yqz8a3n5HmGTlsbADNtr/dJlhkh/55Rq798G6ibiULcXbDtaLpTl1pvdqcbFfeoj3iSi52lePFM7h9H21cw/A==}
|
||||||
engines: {node: '>=18.17'}
|
engines: {node: '>=18.17'}
|
||||||
|
|
||||||
[email protected]:
|
|
||||||
resolution: {integrity: sha512-RqslV2Us5BrllB+JeiZnK4peryVTndy9Dnqq62S3yYRRTj0tFQCwEniUy2167skdGOy3vqRzEvl1Dm4sV2ReDg==}
|
|
||||||
engines: {node: '>=20.18.1'}
|
|
||||||
|
|
||||||
[email protected]:
|
[email protected]:
|
||||||
resolution: {integrity: sha512-IDxfleLmmbSskfWSUATiN1nfn2rDuvnMOqb5CWR92iIfojA0Ud+ulOAAEQ57LPr9rWmsreUyf5lwyao+7GNNVw==}
|
resolution: {integrity: sha512-IDxfleLmmbSskfWSUATiN1nfn2rDuvnMOqb5CWR92iIfojA0Ud+ulOAAEQ57LPr9rWmsreUyf5lwyao+7GNNVw==}
|
||||||
engines: {node: '>=20.18.1'}
|
engines: {node: '>=20.18.1'}
|
||||||
@@ -13478,7 +13513,7 @@ snapshots:
|
|||||||
ms: 2.1.3
|
ms: 2.1.3
|
||||||
secure-json-parse: 4.1.0
|
secure-json-parse: 4.1.0
|
||||||
tslib: 2.8.1
|
tslib: 2.8.1
|
||||||
undici: 7.22.0
|
undici: 7.29.0
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
@@ -21182,7 +21217,7 @@ snapshots:
|
|||||||
|
|
||||||
[email protected]:
|
[email protected]:
|
||||||
dependencies:
|
dependencies:
|
||||||
esbuild: 0.27.3
|
esbuild: 0.27.2
|
||||||
get-tsconfig: 4.13.6
|
get-tsconfig: 4.13.6
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
fsevents: 2.3.3
|
fsevents: 2.3.3
|
||||||
@@ -21253,10 +21288,7 @@ snapshots:
|
|||||||
|
|
||||||
[email protected]: {}
|
[email protected]: {}
|
||||||
|
|
||||||
[email protected]2.0: {}
|
[email protected]9.0: {}
|
||||||
|
|
||||||
[email protected]:
|
|
||||||
optional: true
|
|
||||||
|
|
||||||
[email protected]: {}
|
[email protected]: {}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user