diff --git a/apps/bridge-frontend/app/(main)/[...segment]/@create/page.tsx b/apps/bridge-frontend/app/(main)/[...segment]/@create/page.tsx
index 3973926..bc5b6b8 100644
--- a/apps/bridge-frontend/app/(main)/[...segment]/@create/page.tsx
+++ b/apps/bridge-frontend/app/(main)/[...segment]/@create/page.tsx
@@ -1,10 +1,11 @@
import { Create } from "@link-stack/bridge-ui";
type PageProps = {
- params: { segment: string[] };
+ params: Promise<{ segment: string[] }>;
};
-export default function Page({ params: { segment } }: PageProps) {
+export default async function Page({ params }: PageProps) {
+ const { segment } = await params;
const service = segment[0];
return ;
diff --git a/apps/bridge-frontend/app/(main)/[...segment]/@detail/page.tsx b/apps/bridge-frontend/app/(main)/[...segment]/@detail/page.tsx
index 0b1f49c..e857b7d 100644
--- a/apps/bridge-frontend/app/(main)/[...segment]/@detail/page.tsx
+++ b/apps/bridge-frontend/app/(main)/[...segment]/@detail/page.tsx
@@ -1,11 +1,12 @@
import { db } from "@link-stack/bridge-common";
import { serviceConfig, Detail } from "@link-stack/bridge-ui";
-type Props = {
- params: { segment: string[] };
+type PageProps = {
+ params: Promise<{ segment: string[] }>;
};
-export default async function Page({ params: { segment } }: Props) {
+export default async function Page({ params }: PageProps) {
+ const { segment } = await params;
const service = segment[0];
const id = segment?.[1];
diff --git a/apps/bridge-frontend/app/(main)/[...segment]/@edit/page.tsx b/apps/bridge-frontend/app/(main)/[...segment]/@edit/page.tsx
index 59977eb..82c8052 100644
--- a/apps/bridge-frontend/app/(main)/[...segment]/@edit/page.tsx
+++ b/apps/bridge-frontend/app/(main)/[...segment]/@edit/page.tsx
@@ -2,10 +2,11 @@ import { db } from "@link-stack/bridge-common";
import { serviceConfig, Edit } from "@link-stack/bridge-ui";
type PageProps = {
- params: { segment: string[] };
+ params: Promise<{ segment: string[] }>;
};
-export default async function Page({ params: { segment } }: PageProps) {
+export default async function Page({ params }: PageProps) {
+ const { segment } = await params;
const service = segment[0];
const id = segment?.[1];
diff --git a/apps/bridge-frontend/app/(main)/[...segment]/page.tsx b/apps/bridge-frontend/app/(main)/[...segment]/page.tsx
index e248a86..7b4fc03 100644
--- a/apps/bridge-frontend/app/(main)/[...segment]/page.tsx
+++ b/apps/bridge-frontend/app/(main)/[...segment]/page.tsx
@@ -2,12 +2,13 @@ import { db } from "@link-stack/bridge-common";
import { serviceConfig, List } from "@link-stack/bridge-ui";
type PageProps = {
- params: {
+ params: Promise<{
segment: string[];
- };
+ }>;
};
-export default async function Page({ params: { segment } }: PageProps) {
+export default async function Page({ params }: PageProps) {
+ const { segment } = await params;
const service = segment[0];
if (!service) return null;
diff --git a/apps/bridge-frontend/package.json b/apps/bridge-frontend/package.json
index b5797a6..1d7d21e 100644
--- a/apps/bridge-frontend/package.json
+++ b/apps/bridge-frontend/package.json
@@ -1,6 +1,6 @@
{
"name": "@link-stack/bridge-frontend",
- "version": "2.2.0",
+ "version": "3.1.0",
"type": "module",
"scripts": {
"dev": "next dev",
@@ -13,28 +13,30 @@
"migrate:down:one": "tsx database/migrate.ts down:one"
},
"dependencies": {
- "@auth/kysely-adapter": "^1.5.2",
+ "@auth/kysely-adapter": "^1.7.4",
+ "@mui/icons-material": "^6",
+ "@mui/material": "^6",
+ "@mui/material-nextjs": "^6",
+ "@mui/x-license": "^7.26.0",
"@link-stack/bridge-common": "*",
"@link-stack/bridge-ui": "*",
- "@link-stack/ui": "*",
- "@mui/icons-material": "^5",
- "@mui/material": "^5",
- "@mui/material-nextjs": "^5",
- "@mui/x-license": "^7.18.0",
- "next": "^14.2.23",
- "next-auth": "^4.24.8",
- "react": "18.3.1",
- "react-dom": "18.3.1",
+ "next": "15.1.7",
+ "next-auth": "^4.24.11",
+ "react": "19.0.0",
+ "react-dom": "19.0.0",
"sharp": "^0.33.5",
- "tsx": "^4.19.1"
+ "tsx": "^4.19.3",
+ "@link-stack/ui": "*"
},
"devDependencies": {
"@link-stack/eslint-config": "*",
"@link-stack/typescript-config": "*",
"@types/node": "^22",
- "@types/pg": "^8.11.10",
- "@types/react": "^18",
- "@types/react-dom": "^18",
+ "@types/pg": "^8.11.11",
+ "@types/react": "^19",
+ "@types/react-dom": "^19",
+ "@link-stack/eslint-config": "*",
+ "@link-stack/typescript-config": "*",
"typescript": "^5"
}
}
diff --git a/apps/bridge-frontend/public/robots.txt b/apps/bridge-frontend/public/robots.txt
new file mode 100644
index 0000000..1f53798
--- /dev/null
+++ b/apps/bridge-frontend/public/robots.txt
@@ -0,0 +1,2 @@
+User-agent: *
+Disallow: /
diff --git a/apps/bridge-frontend/tsconfig.json b/apps/bridge-frontend/tsconfig.json
index e700859..22be23b 100644
--- a/apps/bridge-frontend/tsconfig.json
+++ b/apps/bridge-frontend/tsconfig.json
@@ -1,6 +1,10 @@
{
"compilerOptions": {
- "lib": ["dom", "dom.iterable", "esnext"],
+ "lib": [
+ "dom",
+ "dom.iterable",
+ "esnext"
+ ],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
@@ -14,14 +18,24 @@
"jsx": "preserve",
"incremental": true,
"paths": {
- "@/*": ["./*"]
+ "@/*": [
+ "./*"
+ ]
},
"plugins": [
{
"name": "next"
}
- ]
+ ],
+ "target": "ES2017"
},
- "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
- "exclude": ["node_modules"]
+ "include": [
+ "next-env.d.ts",
+ "**/*.ts",
+ "**/*.tsx",
+ ".next/types/**/*.ts"
+ ],
+ "exclude": [
+ "node_modules"
+ ]
}
diff --git a/apps/bridge-migrations/migrate.ts b/apps/bridge-migrations/migrate.ts
index 2e6281b..d06b606 100644
--- a/apps/bridge-migrations/migrate.ts
+++ b/apps/bridge-migrations/migrate.ts
@@ -72,7 +72,7 @@ export const migrate = async (arg: string) => {
results?.forEach((it) => {
if (it.status === "Success") {
- console.log(
+ console.info(
`Migration "${it.migrationName} ${it.direction.toLowerCase()}" was executed successfully`,
);
} else if (it.status === "Error") {
diff --git a/apps/bridge-migrations/package.json b/apps/bridge-migrations/package.json
index c3a10b6..369801d 100644
--- a/apps/bridge-migrations/package.json
+++ b/apps/bridge-migrations/package.json
@@ -1,6 +1,6 @@
{
"name": "@link-stack/bridge-migrations",
- "version": "2.2.0",
+ "version": "3.1.0",
"type": "module",
"scripts": {
"migrate:up:all": "tsx migrate.ts up:all",
@@ -9,14 +9,14 @@
"migrate:down:one": "tsx migrate.ts down:one"
},
"dependencies": {
- "dotenv": "^16.4.5",
- "kysely": "0.26.1",
- "pg": "^8.13.0",
- "tsx": "^4.19.1"
+ "dotenv": "^16.4.7",
+ "kysely": "0.27.5",
+ "pg": "^8.13.3",
+ "tsx": "^4.19.3"
},
"devDependencies": {
"@types/node": "^22",
- "@types/pg": "^8.11.10",
+ "@types/pg": "^8.11.11",
"@link-stack/eslint-config": "*",
"@link-stack/typescript-config": "*",
"typescript": "^5"
diff --git a/apps/bridge-whatsapp/package.json b/apps/bridge-whatsapp/package.json
index a998164..0999ce1 100644
--- a/apps/bridge-whatsapp/package.json
+++ b/apps/bridge-whatsapp/package.json
@@ -1,26 +1,26 @@
{
"name": "@link-stack/bridge-whatsapp",
- "version": "2.2.0",
+ "version": "3.1.0",
"main": "build/main/index.js",
"author": "Darren Clarke ",
"license": "AGPL-3.0-or-later",
"dependencies": {
"@adiwajshing/keyed-db": "0.2.4",
- "@hapi/hapi": "^21.3.10",
+ "@hapi/hapi": "^21.3.12",
"@hapipal/schmervice": "^3.0.0",
"@hapipal/toys": "^4.0.0",
- "@whiskeysockets/baileys": "^6.7.8",
+ "@whiskeysockets/baileys": "^6.7.13",
"hapi-pino": "^12.1.0",
- "link-preview-js": "^3.0.5"
+ "link-preview-js": "^3.0.14"
},
"devDependencies": {
"@link-stack/eslint-config": "*",
"@link-stack/jest-config": "*",
"@link-stack/typescript-config": "*",
"@types/node": "*",
- "dotenv-cli": "^7.4.2",
- "tsx": "^4.19.1",
- "typescript": "^5.6.2"
+ "dotenv-cli": "^8.0.0",
+ "tsx": "^4.19.3",
+ "typescript": "^5.7.3"
},
"scripts": {
"build": "tsc -p tsconfig.json",
diff --git a/apps/bridge-whatsapp/src/routes.ts b/apps/bridge-whatsapp/src/routes.ts
index 10c9757..9219bf0 100644
--- a/apps/bridge-whatsapp/src/routes.ts
+++ b/apps/bridge-whatsapp/src/routes.ts
@@ -26,7 +26,6 @@ export const SendMessageRoute = withDefaults({
description: "Send a message",
async handler(request: Hapi.Request, _h: Hapi.ResponseToolkit) {
const { id } = request.params;
- console.log({ payload: request.payload });
const { phoneNumber, message } = request.payload as MessageRequest;
const whatsappService = getService(request);
await whatsappService.send(id, phoneNumber, message as string);
diff --git a/apps/bridge-whatsapp/src/service.ts b/apps/bridge-whatsapp/src/service.ts
index 4f6eafa..1fcc881 100644
--- a/apps/bridge-whatsapp/src/service.ts
+++ b/apps/bridge-whatsapp/src/service.ts
@@ -57,7 +57,7 @@ export default class WhatsappService extends Service {
try {
connection.end(null);
} catch (error) {
- console.log(error);
+ console.error(error);
}
}
this.connections = {};
@@ -92,27 +92,27 @@ export default class WhatsappService extends Service {
isNewLogin,
} = update;
if (qr) {
- console.log("got qr code");
+ console.info("got qr code");
const botDirectory = this.getBotDirectory(botID);
const qrPath = `${botDirectory}/qr.txt`;
fs.writeFileSync(qrPath, qr, "utf8");
} else if (isNewLogin) {
- console.log("got new login");
+ console.info("got new login");
const botDirectory = this.getBotDirectory(botID);
const verifiedFile = `${botDirectory}/verified`;
fs.writeFileSync(verifiedFile, "");
} else if (connectionState === "open") {
- console.log("opened connection");
+ console.info("opened connection");
} else if (connectionState === "close") {
- console.log("connection closed due to ", lastDisconnect?.error);
+ console.info("connection closed due to ", lastDisconnect?.error);
const disconnectStatusCode = (lastDisconnect?.error as any)?.output
?.statusCode;
if (disconnectStatusCode === DisconnectReason.restartRequired) {
- console.log("reconnecting after got new login");
+ console.info("reconnecting after got new login");
await this.createConnection(botID, server, options);
authCompleteCallback?.();
} else if (disconnectStatusCode !== DisconnectReason.loggedOut) {
- console.log("reconnecting");
+ console.info("reconnecting");
await this.sleep(pause);
pause *= 2;
this.createConnection(botID, server, options);
@@ -121,12 +121,12 @@ export default class WhatsappService extends Service {
}
if (events["creds.update"]) {
- console.log("creds update");
+ console.info("creds update");
await saveCreds();
}
if (events["messages.upsert"]) {
- console.log("messages upsert");
+ console.info("messages upsert");
const upsert = events["messages.upsert"];
const { messages } = upsert;
if (messages) {
@@ -143,13 +143,13 @@ export default class WhatsappService extends Service {
const baseDirectory = this.getBaseDirectory();
const botIDs = fs.readdirSync(baseDirectory);
- console.log({ botIDs });
+
for await (const botID of botIDs) {
const directory = this.getBotDirectory(botID);
const verifiedFile = `${directory}/verified`;
if (fs.existsSync(verifiedFile)) {
const { version, isLatest } = await fetchLatestBaileysVersion();
- console.log(`using WA v${version.join(".")}, isLatest: ${isLatest}`);
+ console.info(`using WA v${version.join(".")}, isLatest: ${isLatest}`);
await this.createConnection(botID, this.server, {
browser: WhatsappService.browserDescription,
@@ -169,7 +169,10 @@ export default class WhatsappService extends Service {
message,
messageTimestamp,
} = webMessageInfo;
- console.log(webMessageInfo);
+ console.info("Message type debug");
+ for (const key in message) {
+ console.info(key, !!message[key as keyof proto.IMessage]);
+ }
const isValidMessage =
message && remoteJid !== "status@broadcast" && !fromMe;
if (isValidMessage) {
diff --git a/apps/bridge-worker/graphile.config.ts b/apps/bridge-worker/graphile.config.ts
index 8b550c7..9367a65 100644
--- a/apps/bridge-worker/graphile.config.ts
+++ b/apps/bridge-worker/graphile.config.ts
@@ -4,8 +4,12 @@ import type {} from "graphile-worker";
const preset: GraphileConfig.Preset = {
worker: {
connectionString: process.env.DATABASE_URL,
- maxPoolSize: 10,
- pollInterval: 2000,
+ maxPoolSize: process.env.BRIDGE_WORKER_POOL_SIZE
+ ? parseInt(process.env.BRIDGE_WORKER_POOL_SIZE, 10)
+ : 10,
+ pollInterval: process.env.BRIDGE_WORKER_POLL_INTERVAL
+ ? parseInt(process.env.BRIDGE_WORKER_POLL_INTERVAL, 10)
+ : 2000,
fileExtensions: [".ts"],
},
};
diff --git a/apps/bridge-worker/index.ts b/apps/bridge-worker/index.ts
index 5a7dbd5..a0cb1d8 100644
--- a/apps/bridge-worker/index.ts
+++ b/apps/bridge-worker/index.ts
@@ -6,13 +6,20 @@ const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const startWorker = async () => {
- console.log("Starting worker...");
- console.log(process.env);
+ console.info("Starting worker...");
+
await run({
connectionString: process.env.DATABASE_URL,
- concurrency: 10,
noHandleSignals: false,
- pollInterval: 1000,
+ concurrency: process.env.BRIDGE_WORKER_CONCURRENCY
+ ? parseInt(process.env.BRIDGE_WORKER_CONCURRENCY, 10)
+ : 10,
+ maxPoolSize: process.env.BRIDGE_WORKER_POOL_SIZE
+ ? parseInt(process.env.BRIDGE_WORKER_POOL_SIZE, 10)
+ : 10,
+ pollInterval: process.env.BRIDGE_WORKER_POLL_INTERVAL
+ ? parseInt(process.env.BRIDGE_WORKER_POLL_INTERVAL, 10)
+ : 1000,
taskDirectory: `${__dirname}/tasks`,
crontabFile: `${__dirname}/crontab`,
});
diff --git a/apps/bridge-worker/lib/common.ts b/apps/bridge-worker/lib/common.ts
index 26e4aeb..ff167b3 100644
--- a/apps/bridge-worker/lib/common.ts
+++ b/apps/bridge-worker/lib/common.ts
@@ -62,9 +62,8 @@ export const createZammadTicket = async (
},
});
} catch (error: any) {
- console.log(Object.keys(error));
if (error.isBoom) {
- console.log(error.output);
+ console.error(error.output);
throw new Error("Failed to create zamamd ticket");
}
}
diff --git a/apps/bridge-worker/lib/media-convert.ts b/apps/bridge-worker/lib/media-convert.ts
index bc6a22a..587e893 100644
--- a/apps/bridge-worker/lib/media-convert.ts
+++ b/apps/bridge-worker/lib/media-convert.ts
@@ -25,7 +25,7 @@ const defaultAudioConvertOpts = {
**/
export const convert = (
input: Buffer,
- opts?: AudioConvertOpts
+ opts?: AudioConvertOpts,
): Promise => {
const settings = { ...defaultAudioConvertOpts, ...opts };
return new Promise((resolve, reject) => {
@@ -35,12 +35,8 @@ export const convert = (
.audioCodec(settings.audioCodec)
.audioBitrate(settings.bitrate)
.toFormat(settings.format)
- .on("error", (err, stdout, stderr) => {
+ .on("error", (err, _stdout, _stderr) => {
console.error(err.message);
- console.log("FFMPEG OUTPUT");
- console.log(stdout);
- console.log("FFMPEG ERROR");
- console.log(stderr);
reject(err);
})
.on("end", () => {
@@ -66,8 +62,12 @@ export const selfCheck = (): Promise => {
resolve(false);
}
- const preds = R.map(requiredCodecs, (codec) => (available: any) =>
- available[codec] && available[codec].canDemux && available[codec].canMux
+ const preds = R.map(
+ requiredCodecs,
+ (codec) => (available: any) =>
+ available[codec] &&
+ available[codec].canDemux &&
+ available[codec].canMux,
);
resolve(R.allPass(codecs, preds));
@@ -79,6 +79,6 @@ export const assertFfmpegAvailable = async (): Promise => {
const r = await selfCheck();
if (!r)
throw new Error(
- `ffmpeg is not installed, could not be located, or does not support the required codecs: ${requiredCodecs}`
+ `ffmpeg is not installed, could not be located, or does not support the required codecs: ${requiredCodecs}`,
);
};
diff --git a/apps/bridge-worker/package.json b/apps/bridge-worker/package.json
index aa162e9..2e09e60 100644
--- a/apps/bridge-worker/package.json
+++ b/apps/bridge-worker/package.json
@@ -1,6 +1,6 @@
{
"name": "@link-stack/bridge-worker",
- "version": "2.2.0",
+ "version": "3.1.0",
"type": "module",
"main": "build/main/index.js",
"author": "Darren Clarke ",
@@ -16,14 +16,14 @@
"@link-stack/signal-api": "*",
"fluent-ffmpeg": "^2.1.3",
"graphile-worker": "^0.16.6",
- "remeda": "^2.14.0",
- "twilio": "^5.3.2"
+ "remeda": "^2.20.2",
+ "twilio": "^5.4.5"
},
"devDependencies": {
- "@types/fluent-ffmpeg": "^2.1.26",
- "dotenv-cli": "^7.4.2",
+ "@types/fluent-ffmpeg": "^2.1.27",
+ "dotenv-cli": "^8.0.0",
"@link-stack/eslint-config": "*",
"@link-stack/typescript-config": "*",
- "typescript": "^5.6.2"
+ "typescript": "^5.7.3"
}
}
diff --git a/apps/bridge-worker/tasks/common/notify-webhooks.ts b/apps/bridge-worker/tasks/common/notify-webhooks.ts
index 0ed2c17..3d81f93 100644
--- a/apps/bridge-worker/tasks/common/notify-webhooks.ts
+++ b/apps/bridge-worker/tasks/common/notify-webhooks.ts
@@ -19,13 +19,11 @@ const notifyWebhooksTask = async (
for (const webhook of webhooks) {
const { endpointUrl, httpMethod, headers } = webhook;
const finalHeaders = { "Content-Type": "application/json", ...headers };
- console.log({ endpointUrl, httpMethod, headers, finalHeaders });
const result = await fetch(endpointUrl, {
method: httpMethod,
headers: finalHeaders,
body: JSON.stringify(payload),
});
- console.log(result);
}
};
diff --git a/apps/bridge-worker/tasks/facebook/send-facebook-message.ts b/apps/bridge-worker/tasks/facebook/send-facebook-message.ts
index 3f28fc8..9190e11 100644
--- a/apps/bridge-worker/tasks/facebook/send-facebook-message.ts
+++ b/apps/bridge-worker/tasks/facebook/send-facebook-message.ts
@@ -31,7 +31,6 @@ const sendFacebookMessageTask = async (
headers: { "Content-Type": "application/json" },
body: JSON.stringify(outgoingMessage),
});
- console.log({ response });
} catch (error) {
console.error({ error });
throw error;
diff --git a/apps/bridge-worker/tasks/fetch-signal-messages.ts b/apps/bridge-worker/tasks/fetch-signal-messages.ts
index 1044107..fd920fb 100644
--- a/apps/bridge-worker/tasks/fetch-signal-messages.ts
+++ b/apps/bridge-worker/tasks/fetch-signal-messages.ts
@@ -46,7 +46,6 @@ const processMessage = async ({
message: msg,
}: ProcessMessageArgs): Promise[]> => {
const { envelope } = msg;
- console.log(envelope);
const { source, sourceUuid, dataMessage } = envelope;
if (!dataMessage) return [];
@@ -125,7 +124,6 @@ const fetchSignalMessagesTask = async ({
phoneNumber,
message,
});
- console.log({ formattedMessages });
for (const formattedMessage of formattedMessages) {
if (formattedMessage.to !== formattedMessage.from) {
await worker.addJob(
diff --git a/apps/bridge-worker/tasks/leafcutter/import-label-studio.ts b/apps/bridge-worker/tasks/leafcutter/import-label-studio.ts
index cb1857e..4f50066 100644
--- a/apps/bridge-worker/tasks/leafcutter/import-label-studio.ts
+++ b/apps/bridge-worker/tasks/leafcutter/import-label-studio.ts
@@ -36,7 +36,6 @@ const getZammadTickets = async (
{ headers },
);
const tickets: any = await rawTickets.json();
- console.log({ tickets });
if (!tickets || tickets.length === 0) {
return [shouldContinue, docs];
}
@@ -49,23 +48,9 @@ const getZammadTickets = async (
shouldContinue = true;
if (source_closed_at <= minUpdatedTimestamp) {
- console.log(`Skipping ticket`, {
- source_id,
- source_updated_at,
- source_closed_at,
- minUpdatedTimestamp,
- });
continue;
}
-
- console.log(`Processing ticket`, {
- source_id,
- source_updated_at,
- source_closed_at,
- minUpdatedTimestamp,
- });
-
- const rawArticles = await fetch(
+ const rawArticles = await fetch(
`${zammadApiUrl}/ticket_articles/by_ticket/${source_id}`,
{ headers },
);
@@ -178,8 +163,6 @@ const sendToLabelStudio = async (tickets: FormattedZammadTicket[]) => {
body: JSON.stringify([ticket]),
});
const importResult = await res.json();
-
- console.log(JSON.stringify(importResult, undefined, 2));
}
};
*/
@@ -201,7 +184,6 @@ const importLabelStudioTask = async (): Promise => {
await sendToLabelStudio(tickets);
const lastTicket = tickets.pop();
const newLastTimestamp = lastTicket.data.source_closed_at;
- console.log({ newLastTimestamp });
await db.settings.upsert(settingName, {
minUpdatedTimestamp: newLastTimestamp,
});
diff --git a/apps/bridge-worker/tasks/leafcutter/import-leafcutter.ts b/apps/bridge-worker/tasks/leafcutter/import-leafcutter.ts
index a3c3e4e..f410ca7 100644
--- a/apps/bridge-worker/tasks/leafcutter/import-leafcutter.ts
+++ b/apps/bridge-worker/tasks/leafcutter/import-leafcutter.ts
@@ -43,14 +43,11 @@ const getLabelStudioTickets = async (
page_size: "50",
page: `${page}`,
});
- console.log({ url: `${labelStudioApiUrl}/projects/1/tasks?${ticketsQuery}` });
const res = await fetch(
`${labelStudioApiUrl}/projects/1/tasks?${ticketsQuery}`,
{ headers },
);
- console.log({ res });
const tasksResult: any = await res.json();
- console.log({ tasksResult });
return tasksResult;
};
@@ -63,14 +60,11 @@ const fetchFromLabelStudio = async (
for await (const page of pages) {
const docs = await getLabelStudioTickets(page + 1);
- console.log({ page, docs });
if (docs && docs.length > 0) {
for (const doc of docs) {
const updatedAt = new Date(doc.updated_at);
- console.log({ updatedAt, minUpdatedTimestamp });
if (updatedAt > minUpdatedTimestamp) {
- console.log(`Adding doc`, { doc });
allDocs.push(doc);
}
}
@@ -79,7 +73,6 @@ const fetchFromLabelStudio = async (
}
}
- console.log({ allDocs });
return allDocs;
};
@@ -93,9 +86,7 @@ const sendToLeafcutter = async (tickets: LabelStudioTicket[]) => {
},
} = config;
- console.log({ tickets });
const filteredTickets = tickets.filter((ticket) => ticket.is_labeled);
- console.log({ filteredTickets });
const finalTickets: LeafcutterTicket[] = filteredTickets.map((ticket) => {
const {
id,
@@ -131,8 +122,7 @@ const sendToLeafcutter = async (tickets: LabelStudioTicket[]) => {
};
});
- console.log("Sending to Leafcutter");
- console.log({ finalTickets });
+ console.info("Sending to Leafcutter");
const result = await fetch(opensearchApiUrl, {
method: "POST",
@@ -157,15 +147,7 @@ const importLeafcutterTask = async (): Promise => {
? new Date(res.value.minUpdatedTimestamp as string)
: new Date("2023-03-01");
const newLastTimestamp = new Date();
- console.log({
- contributorName,
- settingName,
- res,
- startTimestamp,
- newLastTimestamp,
- });
const tickets = await fetchFromLabelStudio(startTimestamp);
- console.log({ tickets });
await sendToLeafcutter(tickets);
await db.settings.upsert(settingName, {
minUpdatedTimestamp: newLastTimestamp,
diff --git a/apps/bridge-worker/tasks/signal/receive-signal-message.ts b/apps/bridge-worker/tasks/signal/receive-signal-message.ts
index b1688ea..a75b7cb 100644
--- a/apps/bridge-worker/tasks/signal/receive-signal-message.ts
+++ b/apps/bridge-worker/tasks/signal/receive-signal-message.ts
@@ -23,7 +23,6 @@ const receiveSignalMessageTask = async ({
filename,
mimeType,
}: ReceiveSignalMessageTaskOptions): Promise => {
- console.log({ token, to, from });
const worker = await getWorkerUtils();
const row = await db
.selectFrom("SignalBot")
diff --git a/apps/bridge-worker/tasks/signal/send-signal-message.ts b/apps/bridge-worker/tasks/signal/send-signal-message.ts
index 4150300..8426709 100644
--- a/apps/bridge-worker/tasks/signal/send-signal-message.ts
+++ b/apps/bridge-worker/tasks/signal/send-signal-message.ts
@@ -13,7 +13,6 @@ const sendSignalMessageTask = async ({
to,
message,
}: SendSignalMessageTaskOptions): Promise => {
- console.log({ token, to });
const bot = await db
.selectFrom("SignalBot")
.selectAll()
@@ -34,7 +33,6 @@ const sendSignalMessageTask = async ({
message,
},
});
- console.log({ response });
} catch (error) {
console.error({ error });
throw error;
diff --git a/apps/bridge-worker/tasks/whatsapp/receive-whatsapp-message.ts b/apps/bridge-worker/tasks/whatsapp/receive-whatsapp-message.ts
index 024c70e..48adc6f 100644
--- a/apps/bridge-worker/tasks/whatsapp/receive-whatsapp-message.ts
+++ b/apps/bridge-worker/tasks/whatsapp/receive-whatsapp-message.ts
@@ -23,8 +23,6 @@ const receiveWhatsappMessageTask = async ({
filename,
mimeType,
}: ReceiveWhatsappMessageTaskOptions): Promise => {
- console.log({ token, to, from });
-
const worker = await getWorkerUtils();
const row = await db
.selectFrom("WhatsappBot")
diff --git a/apps/bridge-worker/tasks/whatsapp/send-whatsapp-message.ts b/apps/bridge-worker/tasks/whatsapp/send-whatsapp-message.ts
index 509371f..b04543a 100644
--- a/apps/bridge-worker/tasks/whatsapp/send-whatsapp-message.ts
+++ b/apps/bridge-worker/tasks/whatsapp/send-whatsapp-message.ts
@@ -25,7 +25,6 @@ const sendWhatsappMessageTask = async ({
headers: { "Content-Type": "application/json" },
body: JSON.stringify(params),
});
- console.log({ result });
} catch (error) {
console.error({ error });
throw new Error("Failed to send message");
diff --git a/apps/leafcutter/app/(main)/about/page.tsx b/apps/leafcutter/app/(main)/about/page.tsx
index b6958b2..1bfad23 100644
--- a/apps/leafcutter/app/(main)/about/page.tsx
+++ b/apps/leafcutter/app/(main)/about/page.tsx
@@ -1,5 +1,10 @@
+import { Suspense } from "react";
import { About } from "@link-stack/leafcutter-ui";
export default function Page() {
- return ;
+ return (
+
+
+
+ );
}
diff --git a/apps/leafcutter/app/(main)/faq/page.tsx b/apps/leafcutter/app/(main)/faq/page.tsx
index 396a9b5..05b57de 100644
--- a/apps/leafcutter/app/(main)/faq/page.tsx
+++ b/apps/leafcutter/app/(main)/faq/page.tsx
@@ -1,5 +1,12 @@
+import { Suspense } from "react";
import { FAQ } from "@link-stack/leafcutter-ui";
-export default function Page() {
- return ;
+export const dynamic = "force-dynamic";
+
+export default async function Page() {
+ return (
+
+
+
+ );
}
diff --git a/apps/leafcutter/app/(main)/layout.tsx b/apps/leafcutter/app/(main)/layout.tsx
index 5b9e9f1..d97fd7b 100644
--- a/apps/leafcutter/app/(main)/layout.tsx
+++ b/apps/leafcutter/app/(main)/layout.tsx
@@ -2,6 +2,8 @@ import { ReactNode } from "react";
import "app/_styles/global.css";
import { InternalLayout } from "../_components/InternalLayout";
+export const dynamic = "force-dynamic";
+
type LayoutProps = {
children: ReactNode;
};
diff --git a/apps/leafcutter/app/(main)/preview/[...visualizationID]/page.tsx b/apps/leafcutter/app/(main)/preview/[...visualizationID]/page.tsx
index 8daaaba..a1a60c6 100644
--- a/apps/leafcutter/app/(main)/preview/[...visualizationID]/page.tsx
+++ b/apps/leafcutter/app/(main)/preview/[...visualizationID]/page.tsx
@@ -69,19 +69,17 @@ export const getServerSideProps: GetServerSideProps = async (
});
});
}
- console.log({ query });
const dataResponse = await client.search({
index: "demo_data",
size: 200,
body: { query },
});
- console.log({ dataResponse });
res.props.data = dataResponse.body.hits.hits.map((hit) => ({
id: hit._id,
...hit._source,
}));
- console.log({ data: res.props.data });
- console.log(res.props.data[0]);
+
+
return res;
};
diff --git a/apps/leafcutter/app/(main)/setup/_components/Setup.tsx b/apps/leafcutter/app/(main)/setup/_components/Setup.tsx
index 1a079ec..7fe08ae 100644
--- a/apps/leafcutter/app/(main)/setup/_components/Setup.tsx
+++ b/apps/leafcutter/app/(main)/setup/_components/Setup.tsx
@@ -13,7 +13,7 @@ export const Setup: FC = () => {
} = useLeafcutterContext();
const router = useRouter();
useLayoutEffect(() => {
- setTimeout(() => router.push("/"), 4000);
+ setTimeout(() => router.push("/"), 2000);
}, [router]);
return (
diff --git a/apps/leafcutter/app/(main)/setup/page.tsx b/apps/leafcutter/app/(main)/setup/page.tsx
index 4e62414..dad2ed0 100644
--- a/apps/leafcutter/app/(main)/setup/page.tsx
+++ b/apps/leafcutter/app/(main)/setup/page.tsx
@@ -1,5 +1,10 @@
+import { Suspense } from "react";
import { Setup } from "./_components/Setup";
export default function Page() {
- return ;
+ return (
+
+
+
+ );
}
diff --git a/apps/leafcutter/app/(main)/visualizations/[...visualizationID]/page.tsx b/apps/leafcutter/app/(main)/visualizations/[...visualizationID]/page.tsx
index 5ef382b..d840ef4 100644
--- a/apps/leafcutter/app/(main)/visualizations/[...visualizationID]/page.tsx
+++ b/apps/leafcutter/app/(main)/visualizations/[...visualizationID]/page.tsx
@@ -22,9 +22,9 @@ const getVisualization = async (visualizationID: string) => {
);
const hit = hits[0];
const visualization = {
- id: hit._id.split(":")[1],
- title: hit._source.visualization.title,
- description: hit._source.visualization.description,
+ id: hit?._id.split(":")[1],
+ title: hit?._source?.visualization.title,
+ description: hit?._source?.visualization.description,
url: `/app/visualize?security_tenant=global#/edit/${
hit._id.split(":")[1]
}?embed=true`,
@@ -34,12 +34,13 @@ const getVisualization = async (visualizationID: string) => {
};
type PageProps = {
- params: {
+ params: Promise<{
visualizationID: string;
- };
+ }>;
};
-export default async function Page({ params: { visualizationID } }: PageProps) {
+export default async function Page({ params }: PageProps) {
+ const { visualizationID } = await params;
const visualization = await getVisualization(visualizationID);
return ;
diff --git a/apps/leafcutter/app/_components/Sidebar.tsx b/apps/leafcutter/app/_components/Sidebar.tsx
index acdcef3..b3c0a43 100644
--- a/apps/leafcutter/app/_components/Sidebar.tsx
+++ b/apps/leafcutter/app/_components/Sidebar.tsx
@@ -48,7 +48,6 @@ const MenuItem = ({
return (
new Client({
- node: baseURL,
- auth: {
- username: process.env.OPENSEARCH_USERNAME!,
- password: process.env.OPENSEARCH_PASSWORD!,
- },
- ssl: {
- rejectUnauthorized: false,
- },
-});
+const createClient = () =>
+ new Client({
+ node: baseURL,
+ auth: {
+ username: process.env.OPENSEARCH_USERNAME!,
+ password: process.env.OPENSEARCH_PASSWORD!,
+ },
+ ssl: {
+ rejectUnauthorized: false,
+ },
+ });
-const createUserClient = (username: string, password: string) => new Client({
- node: baseURL,
- auth: {
- username,
- password,
- },
- ssl: {
- rejectUnauthorized: false,
- },
-});
+const createUserClient = (username: string, password: string) =>
+ new Client({
+ node: baseURL,
+ auth: {
+ username,
+ password,
+ },
+ ssl: {
+ rejectUnauthorized: false,
+ },
+ });
export const checkAuth = async (username: string, password: string) => {
const client = createUserClient(username, password);
@@ -115,7 +117,7 @@ export const getUserMetadata = async (username: string) => {
await client.create({
id: username,
index: userMetadataIndexName,
- body: { username, savedSearches: [] }
+ body: { username, savedSearches: [] },
});
res = await client.get({
@@ -132,7 +134,7 @@ export const saveUserMetadata = async (username: string, metadata: any) => {
await client.update({
id: username,
index: userMetadataIndexName,
- body: { doc: { username, ...metadata } }
+ body: { doc: { username, ...metadata } },
});
};
@@ -181,7 +183,7 @@ const getIndexPattern: any = async (index: string) => {
sort: ["updated_at:desc"],
});
- if (res.body.hits.total.value === 0) {
+ if (res?.body?.hits?.total?.valueOf() === 0) {
// eslint-disable-next-line no-use-before-define
return createCurrentUserIndexPattern(index);
}
@@ -226,7 +228,7 @@ interface createUserVisualizationProps {
}
export const createUserVisualization = async (
- props: createUserVisualizationProps
+ props: createUserVisualizationProps,
) => {
const { email, query, visualizationID, title, description } = props;
const userIndex = await getCurrentUserIndex(email);
@@ -279,7 +281,7 @@ interface updateVisualizationProps {
}
export const updateUserVisualization = async (
- props: updateVisualizationProps
+ props: updateVisualizationProps,
) => {
const { email, id, query, title, description } = props;
const userIndex = await getCurrentUserIndex(email);
@@ -300,8 +302,7 @@ export const updateUserVisualization = async (
body,
});
} catch (e) {
- // eslint-disable-next-line no-console
- console.log({ e });
+ console.error({ e });
}
return id;
@@ -469,10 +470,18 @@ export const performQuery = async (searchQuery: any, limit: number) => {
const results = hits.map((hit: any) => ({
...hit._source,
id: hit._id,
- incident: Array.isArray(hit._source.incident) ? hit._source.incident.join(", ") : hit._source.incident,
- technology: Array.isArray(hit._source.technology) ? hit._source.technology.join(", ") : hit._source.technology,
- targeted_group: Array.isArray(hit._source.targeted_group) ? hit._source.targeted_group.join(", ") : hit._source.targeted_group,
- country: Array.isArray(hit._source.country) ? hit._source.country.join(", ") : hit._source.country,
+ incident: Array.isArray(hit._source.incident)
+ ? hit._source.incident.join(", ")
+ : hit._source.incident,
+ technology: Array.isArray(hit._source.technology)
+ ? hit._source.technology.join(", ")
+ : hit._source.technology,
+ targeted_group: Array.isArray(hit._source.targeted_group)
+ ? hit._source.targeted_group.join(", ")
+ : hit._source.targeted_group,
+ country: Array.isArray(hit._source.country)
+ ? hit._source.country.join(", ")
+ : hit._source.country,
}));
return results;
@@ -570,7 +579,6 @@ export const getTemplates = async (limit: number) => {
},
};
-
const rawResponse = await client.search({
index: globalIndex,
size: limit,
diff --git a/apps/leafcutter/app/api/link/auth/route.ts b/apps/leafcutter/app/api/link/auth/route.ts
index 37b356e..1960382 100644
--- a/apps/leafcutter/app/api/link/auth/route.ts
+++ b/apps/leafcutter/app/api/link/auth/route.ts
@@ -1,15 +1,13 @@
import { NextRequest, NextResponse } from "next/server";
export const GET = async (req: NextRequest) => {
- const validDomains = "localhost";
- console.log({ req });
+ const validDomains = "localhost";
- return NextResponse.json({ response: "ok" });
+ return NextResponse.json({ response: "ok" });
};
export const POST = async (req: NextRequest) => {
- const validDomains = "localhost";
- console.log({ req });
+ const validDomains = "localhost";
- return NextResponse.json({ response: "ok" });
+ return NextResponse.json({ response: "ok" });
};
diff --git a/apps/leafcutter/app/api/trends/recent/route.ts b/apps/leafcutter/app/api/trends/recent/route.ts
index a635d29..d18b657 100644
--- a/apps/leafcutter/app/api/trends/recent/route.ts
+++ b/apps/leafcutter/app/api/trends/recent/route.ts
@@ -2,10 +2,9 @@ import { NextResponse } from "next/server";
import { getTrends } from "app/_lib/opensearch";
export const GET = async () => {
- const results = await getTrends(5);
- console.log({ results });
+ const results = await getTrends(5);
- NextResponse.json(results);
+ NextResponse.json(results);
};
-export const dynamic = 'force-dynamic';
+export const dynamic = "force-dynamic";
diff --git a/apps/leafcutter/app/api/upload/index.ts b/apps/leafcutter/app/api/upload/index.ts
index 4f3223e..afb5298 100644
--- a/apps/leafcutter/app/api/upload/index.ts
+++ b/apps/leafcutter/app/api/upload/index.ts
@@ -15,8 +15,8 @@ export const POST = async (req: NextRequest) => {
rejectUnauthorized: false,
},
headers: {
- authorization
- }
+ authorization,
+ },
});
const succeeded = [];
@@ -28,11 +28,15 @@ export const POST = async (req: NextRequest) => {
const country = ticket.country[0] ?? "none";
// @ts-expect-error
const translatedCountry = taxonomy.country[country]?.display ?? "none";
- const countryDetails: any = unRegions.find((c) => c.name === translatedCountry);
+ const countryDetails: any = unRegions.find(
+ (c) => c.name === translatedCountry,
+ );
const augmentedTicket = {
...ticket,
- region: countryDetails['sub-region']?.toLowerCase().replace(" ", "-") ?? null,
- continent: countryDetails.region?.toLowerCase().replace(" ", "-") ?? null,
+ region:
+ countryDetails["sub-region"]?.toLowerCase().replace(" ", "-") ?? null,
+ continent:
+ countryDetails.region?.toLowerCase().replace(" ", "-") ?? null,
};
const out = await client.create({
id: uuid(),
@@ -40,10 +44,9 @@ export const POST = async (req: NextRequest) => {
refresh: true,
body: augmentedTicket,
});
- console.log(out);
succeeded.push(id);
} catch (e) {
- console.log(e);
+ console.error(e);
failed.push(id);
}
}
@@ -52,4 +55,3 @@ export const POST = async (req: NextRequest) => {
return NextResponse.json(results);
};
-
diff --git a/apps/leafcutter/app/api/visualizations/delete/route.ts b/apps/leafcutter/app/api/visualizations/delete/route.ts
index 2200ed7..20e10b5 100644
--- a/apps/leafcutter/app/api/visualizations/delete/route.ts
+++ b/apps/leafcutter/app/api/visualizations/delete/route.ts
@@ -3,13 +3,13 @@ import { getServerSession } from "next-auth";
import { authOptions } from "app/_lib/auth";
import { deleteUserVisualization } from "app/_lib/opensearch";
-export const POST = async (req: NextRequest, res: NextResponse) => {
- const session = await getServerSession(authOptions);
- const { user: { email } }: any = session;
- const { id } = await req.json();
- await deleteUserVisualization(email as string, id);
+export const POST = async (req: NextRequest) => {
+ const session = await getServerSession(authOptions);
+ const {
+ user: { email },
+ }: any = session;
+ const { id } = await req.json();
+ await deleteUserVisualization(email as string, id);
- return NextResponse.json({ id });
+ return NextResponse.json({ id });
};
-
-
diff --git a/apps/leafcutter/next-env.d.ts b/apps/leafcutter/next-env.d.ts
index 725dd6f..3cd7048 100644
--- a/apps/leafcutter/next-env.d.ts
+++ b/apps/leafcutter/next-env.d.ts
@@ -3,4 +3,4 @@
///
// NOTE: This file should not be edited
-// see https://nextjs.org/docs/app/building-your-application/configuring/typescript for more information.
+// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
diff --git a/apps/leafcutter/next.config.js b/apps/leafcutter/next.config.js
index e8cb203..a57f18f 100644
--- a/apps/leafcutter/next.config.js
+++ b/apps/leafcutter/next.config.js
@@ -1,8 +1,5 @@
module.exports = {
transpilePackages: ["@link-stack/leafcutter-ui", "@link-stack/opensearch-common"],
- experimental: {
- missingSuspenseWithCSRBailout: false,
- },
poweredByHeader: false,
rewrites: async () => ({
fallback: [
diff --git a/apps/leafcutter/package.json b/apps/leafcutter/package.json
index 9c3e062..8905e40 100644
--- a/apps/leafcutter/package.json
+++ b/apps/leafcutter/package.json
@@ -1,6 +1,6 @@
{
"name": "@link-stack/leafcutter",
- "version": "2.2.0",
+ "version": "3.1.0",
"scripts": {
"dev": "next dev -p 3001",
"login": "aws sso login --sso-session cdr",
@@ -13,37 +13,37 @@
"lint": "next lint"
},
"dependencies": {
- "@emotion/cache": "^11.13.1",
- "@emotion/react": "^11.13.3",
+ "@emotion/cache": "^11.14.0",
+ "@emotion/react": "^11.14.0",
"@emotion/server": "^11.11.0",
- "@emotion/styled": "^11.13.0",
+ "@emotion/styled": "^11.14.0",
"@link-stack/leafcutter-ui": "*",
"@link-stack/opensearch-common": "*",
- "@mui/icons-material": "^5",
- "@mui/material": "^5",
- "@mui/material-nextjs": "^5",
- "@mui/x-date-pickers-pro": "^7.18.0",
- "@opensearch-project/opensearch": "^2.12.0",
+ "@mui/icons-material": "^6",
+ "@mui/material": "^6",
+ "@mui/material-nextjs": "^6",
+ "@mui/x-date-pickers-pro": "^7.27.1",
+ "@opensearch-project/opensearch": "^3.4.0",
"date-fns": "^4.1.0",
- "http-proxy-middleware": "^3.0.2",
- "material-ui-popup-state": "^5.3.1",
- "next": "^14.2.23",
- "next-auth": "^4.24.8",
- "react": "18.3.1",
- "react-cookie": "^7.2.0",
+ "http-proxy-middleware": "^3.0.3",
+ "material-ui-popup-state": "^5.3.3",
+ "next": "15.1.7",
+ "next-auth": "^4.24.11",
+ "react": "19.0.0",
+ "react-cookie": "^7.2.2",
"react-cookie-consent": "^9.0.0",
- "react-dom": "18.3.1",
+ "react-dom": "19.0.0",
"react-iframe": "^1.8.5",
"react-polyglot": "^0.7.2",
"sharp": "^0.33.5",
- "uuid": "^10.0.0"
+ "uuid": "^11.1.0"
},
"devDependencies": {
+ "@types/node": "^22.13.5",
+ "@types/react": "19.0.10",
+ "@types/uuid": "^10.0.0",
"@link-stack/eslint-config": "*",
"@link-stack/typescript-config": "*",
- "@types/node": "^22.7.3",
- "@types/react": "18.3.9",
- "@types/uuid": "^10.0.0",
- "typescript": "5.6.2"
+ "typescript": "5.7.3"
}
}
diff --git a/apps/leafcutter/pages/api/proxy/[[...path]].ts b/apps/leafcutter/pages/api/proxy/[[...path]].ts
index 913b7cb..a4c2f38 100644
--- a/apps/leafcutter/pages/api/proxy/[[...path]].ts
+++ b/apps/leafcutter/pages/api/proxy/[[...path]].ts
@@ -24,17 +24,17 @@ const withAuthInfo =
const requestSignature = req.query.signature;
const url = new URL(req.headers.referer as string);
const referrerSignature = url.searchParams.get("signature");
-
- console.log({ requestSignature, referrerSignature });
const isAppPath = !!req.url?.startsWith("/app");
- const isResourcePath = !!req.url?.match(/\/(api|app|bootstrap|3961|ui|translations|internal|login|node_modules)/);
+ const isResourcePath = !!req.url?.match(
+ /\/(api|app|bootstrap|3961|ui|translations|internal|login|node_modules)/,
+ );
if (requestSignature && isAppPath) {
- console.log("Has Signature");
+ console.info("Has Signature");
}
if (referrerSignature && isResourcePath) {
- console.log("Has Signature");
+ console.info("Has Signature");
}
if (!email) {
diff --git a/apps/leafcutter/public/robots.txt b/apps/leafcutter/public/robots.txt
new file mode 100644
index 0000000..1f53798
--- /dev/null
+++ b/apps/leafcutter/public/robots.txt
@@ -0,0 +1,2 @@
+User-agent: *
+Disallow: /
diff --git a/apps/link/app/(login)/login/_components/Login.tsx b/apps/link/app/(login)/login/_components/Login.tsx
index 0cc1234..5faf515 100644
--- a/apps/link/app/(login)/login/_components/Login.tsx
+++ b/apps/link/app/(login)/login/_components/Login.tsx
@@ -23,13 +23,12 @@ import { useSearchParams } from "next/navigation";
type LoginProps = {
session: any;
+ baseURL: string;
};
-export const Login: FC = ({ session }) => {
- const origin =
- typeof window !== "undefined" && window.location.origin
- ? window.location.origin
- : "";
+export const Login: FC = ({ session, baseURL }) => {
+ const origin = baseURL;
+ const callbackUrl = `${origin}/setup`;
const [provider, setProvider] = useState(undefined);
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
@@ -158,7 +157,7 @@ export const Login: FC = ({ session }) => {
sx={buttonStyles}
onClick={() =>
signIn("google", {
- callbackUrl: `${origin}`,
+ callbackUrl,
})
}
>
@@ -174,7 +173,7 @@ export const Login: FC = ({ session }) => {
sx={buttonStyles}
onClick={() =>
signIn("apple", {
- callbackUrl: `${window.location.origin}`,
+ callbackUrl,
})
}
>
@@ -230,7 +229,7 @@ export const Login: FC = ({ session }) => {
signIn("credentials", {
email,
password,
- callbackUrl: `${origin}/setup`,
+ callbackUrl,
})
}
>
diff --git a/apps/link/app/(login)/login/page.tsx b/apps/link/app/(login)/login/page.tsx
index 7bafdbb..ea944ba 100644
--- a/apps/link/app/(login)/login/page.tsx
+++ b/apps/link/app/(login)/login/page.tsx
@@ -9,10 +9,11 @@ export const metadata: Metadata = {
export default async function Page() {
const session = await getSession();
+ const baseURL = process.env.LINK_URL;
return (
Loading...}>
-
+
);
}
diff --git a/apps/link/app/(main)/_components/ClientOnly.tsx b/apps/link/app/(main)/_components/ClientOnly.tsx
index 46e79e8..b669b4f 100644
--- a/apps/link/app/(main)/_components/ClientOnly.tsx
+++ b/apps/link/app/(main)/_components/ClientOnly.tsx
@@ -1,8 +1,9 @@
"use client";
+import { ReactNode } from "react";
import dynamic from "next/dynamic";
-type ClientOnlyProps = { children: JSX.Element };
+type ClientOnlyProps = { children: ReactNode };
const ClientOnly = (props: ClientOnlyProps) => {
const { children } = props;
diff --git a/apps/link/app/(main)/_components/Home.tsx b/apps/link/app/(main)/_components/Home.tsx
index 1a404ae..44332f1 100644
--- a/apps/link/app/(main)/_components/Home.tsx
+++ b/apps/link/app/(main)/_components/Home.tsx
@@ -3,9 +3,10 @@
import { FC } from "react";
import { OpenSearchWrapper } from "@link-stack/leafcutter-ui";
-export const Home: FC = () => (
-
+type HomeProps = {
+ url: string;
+};
+
+export const Home: FC = ({ url }) => (
+
);
diff --git a/apps/link/app/(main)/_components/Sidebar.tsx b/apps/link/app/(main)/_components/Sidebar.tsx
index c099c42..333cfb6 100644
--- a/apps/link/app/(main)/_components/Sidebar.tsx
+++ b/apps/link/app/(main)/_components/Sidebar.tsx
@@ -485,7 +485,25 @@ export const Sidebar: FC = ({
selected={pathname.endsWith("/docs")}
open={open}
/>
- {leafcutterEnabled && (
+
+ {roles.includes("admin") && leafcutterEnabled && (
+
+ )}
+ {false && leafcutterEnabled && (