mirror of
https://github.com/supermemoryai/supermemory.git
synced 2026-08-28 05:25:33 +00:00
Fix: notion integration
This commit is contained in:
parent
9998ed25b9
commit
c34a3352ac
4 changed files with 49 additions and 93 deletions
|
|
@ -1,29 +1,27 @@
|
|||
import { z } from "zod";
|
||||
import { Context, Hono } from "hono";
|
||||
import { type Context, Hono } from "hono";
|
||||
import { auth } from "./auth";
|
||||
import { logger } from "hono/logger";
|
||||
import { timing } from "hono/timing";
|
||||
import { Env, Variables } from "./types";
|
||||
import type { Env, Variables } from "./types";
|
||||
import { zValidator } from "@hono/zod-validator";
|
||||
import { database } from "@supermemory/db";
|
||||
import { waitlist } from "@supermemory/db/schema";
|
||||
import { cors } from "hono/cors";
|
||||
import { ContentWorkflow } from "./workflow";
|
||||
import { Resend } from "resend";
|
||||
import { RedirectStatusCode, StatusCode } from "hono/utils/http-status";
|
||||
import { LandingPage } from "./components/landing";
|
||||
import user from "./routes/user";
|
||||
import spacesRoute from "./routes/spaces";
|
||||
import actions from "./routes/actions";
|
||||
import memories from "./routes/memories";
|
||||
import integrations from "./routes/integrations";
|
||||
import { fromHono, OpenAPIRoute } from "chanfana";
|
||||
import { fromHono } from "chanfana";
|
||||
import {
|
||||
cloudflareRateLimiter,
|
||||
DurableObjectRateLimiter,
|
||||
DurableObjectStore,
|
||||
} from "@hono-rate-limiter/cloudflare";
|
||||
import { ConfigType, GeneralConfigType, rateLimiter } from "hono-rate-limiter";
|
||||
import type { ConfigType, GeneralConfigType, rateLimiter } from "hono-rate-limiter";
|
||||
|
||||
// Create base Hono app first
|
||||
const honoApp = new Hono<{ Variables: Variables; Bindings: Env }>();
|
||||
|
|
@ -94,9 +92,7 @@ app.use("/v1/*", (c, next) => {
|
|||
common: {
|
||||
standardHeaders: "draft-6",
|
||||
keyGenerator: (c: Context) =>
|
||||
(user?.uuid ?? c.req.header("cf-connecting-ip")) +
|
||||
"-" +
|
||||
new Date().getDate(), // day so that limit gets reset every day
|
||||
`${user?.uuid ?? c.req.header("cf-connecting-ip")}-${new Date().getDate()}`, // day so that limit gets reset every day
|
||||
store: new DurableObjectStore({ namespace: c.env.RATE_LIMITER }),
|
||||
} as GeneralConfigType<ConfigType>,
|
||||
};
|
||||
|
|
@ -145,7 +141,7 @@ app.all("/api/*", async (c) => {
|
|||
const newPath = path.replace("/api", "/v1");
|
||||
|
||||
// Preserve query parameters and build target URL
|
||||
const redirectUrl = "https://api.supermemory.ai" + newPath + url.search;
|
||||
const redirectUrl = `https://api.supermemory.ai${newPath}${url.search}`;
|
||||
|
||||
// Use c.redirect() for a proper redirect
|
||||
return c.redirect(redirectUrl);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { Hono } from "hono";
|
||||
import { Env, Variables } from "../types";
|
||||
import type { Env, Variables } from "../types";
|
||||
import { getDecryptedKV } from "encrypt-workers-kv";
|
||||
import { getAllNotionPageContents } from "../utils/notion";
|
||||
import { and, eq, or } from "@supermemory/db";
|
||||
|
|
|
|||
|
|
@ -1,6 +1,4 @@
|
|||
*,
|
||||
::before,
|
||||
::after {
|
||||
*, ::before, ::after {
|
||||
--tw-border-spacing-x: 0;
|
||||
--tw-border-spacing-y: 0;
|
||||
--tw-translate-x: 0;
|
||||
|
|
@ -132,7 +130,7 @@
|
|||
|
||||
::before,
|
||||
::after {
|
||||
--tw-content: "";
|
||||
--tw-content: '';
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -154,11 +152,9 @@ html,
|
|||
-moz-tab-size: 4;
|
||||
/* 3 */
|
||||
-o-tab-size: 4;
|
||||
tab-size: 4;
|
||||
tab-size: 4;
|
||||
/* 3 */
|
||||
font-family:
|
||||
ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji",
|
||||
"Segoe UI Symbol", "Noto Color Emoji";
|
||||
font-family: ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
|
||||
/* 4 */
|
||||
font-feature-settings: normal;
|
||||
/* 5 */
|
||||
|
|
@ -201,7 +197,7 @@ Add the correct text decoration in Chrome, Edge, and Safari.
|
|||
|
||||
abbr:where([title]) {
|
||||
-webkit-text-decoration: underline dotted;
|
||||
text-decoration: underline dotted;
|
||||
text-decoration: underline dotted;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -247,9 +243,7 @@ code,
|
|||
kbd,
|
||||
samp,
|
||||
pre {
|
||||
font-family:
|
||||
ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono",
|
||||
"Courier New", monospace;
|
||||
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
|
||||
/* 1 */
|
||||
font-feature-settings: normal;
|
||||
/* 2 */
|
||||
|
|
@ -350,9 +344,9 @@ select {
|
|||
*/
|
||||
|
||||
button,
|
||||
input:where([type="button"]),
|
||||
input:where([type="reset"]),
|
||||
input:where([type="submit"]) {
|
||||
input:where([type='button']),
|
||||
input:where([type='reset']),
|
||||
input:where([type='submit']) {
|
||||
-webkit-appearance: button;
|
||||
/* 1 */
|
||||
background-color: transparent;
|
||||
|
|
@ -399,7 +393,7 @@ Correct the cursor style of increment and decrement buttons in Safari.
|
|||
2. Correct the outline style in Safari.
|
||||
*/
|
||||
|
||||
[type="search"] {
|
||||
[type='search'] {
|
||||
-webkit-appearance: textfield;
|
||||
/* 1 */
|
||||
outline-offset: -2px;
|
||||
|
|
@ -492,8 +486,7 @@ textarea {
|
|||
2. Set the default placeholder color to the user's configured gray 400 color.
|
||||
*/
|
||||
|
||||
input::-moz-placeholder,
|
||||
textarea::-moz-placeholder {
|
||||
input::-moz-placeholder, textarea::-moz-placeholder {
|
||||
opacity: 1;
|
||||
/* 1 */
|
||||
color: #9ca3af;
|
||||
|
|
@ -590,9 +583,7 @@ video {
|
|||
|
||||
body {
|
||||
background-color: hsl(var(--background));
|
||||
font-family:
|
||||
ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji",
|
||||
"Segoe UI Symbol", "Noto Color Emoji";
|
||||
font-family: ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
|
||||
color: hsl(var(--foreground));
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
|
|
@ -835,29 +826,21 @@ body {
|
|||
|
||||
.translate-x-\[-50\%\] {
|
||||
--tw-translate-x: -50%;
|
||||
transform: translate(var(--tw-translate-x), var(--tw-translate-y))
|
||||
rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y))
|
||||
scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
|
||||
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
|
||||
}
|
||||
|
||||
.translate-y-\[-50\%\] {
|
||||
--tw-translate-y: -50%;
|
||||
transform: translate(var(--tw-translate-x), var(--tw-translate-y))
|
||||
rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y))
|
||||
scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
|
||||
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
|
||||
}
|
||||
|
||||
.rotate-180 {
|
||||
--tw-rotate: 180deg;
|
||||
transform: translate(var(--tw-translate-x), var(--tw-translate-y))
|
||||
rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y))
|
||||
scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
|
||||
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
|
||||
}
|
||||
|
||||
.transform {
|
||||
transform: translate(var(--tw-translate-x), var(--tw-translate-y))
|
||||
rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y))
|
||||
scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
|
||||
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
|
|
@ -876,8 +859,8 @@ body {
|
|||
|
||||
.select-none {
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
user-select: none;
|
||||
-moz-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.flex-col {
|
||||
|
|
@ -1340,39 +1323,26 @@ body {
|
|||
|
||||
.shadow {
|
||||
--tw-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);
|
||||
--tw-shadow-colored:
|
||||
0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color);
|
||||
box-shadow:
|
||||
var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000),
|
||||
var(--tw-shadow);
|
||||
--tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color);
|
||||
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
|
||||
}
|
||||
|
||||
.shadow-lg {
|
||||
--tw-shadow:
|
||||
0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
|
||||
--tw-shadow-colored:
|
||||
0 10px 15px -3px var(--tw-shadow-color),
|
||||
0 4px 6px -4px var(--tw-shadow-color);
|
||||
box-shadow:
|
||||
var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000),
|
||||
var(--tw-shadow);
|
||||
--tw-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
|
||||
--tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);
|
||||
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
|
||||
}
|
||||
|
||||
.shadow-md {
|
||||
--tw-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
|
||||
--tw-shadow-colored:
|
||||
0 4px 6px -1px var(--tw-shadow-color), 0 2px 4px -2px var(--tw-shadow-color);
|
||||
box-shadow:
|
||||
var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000),
|
||||
var(--tw-shadow);
|
||||
--tw-shadow-colored: 0 4px 6px -1px var(--tw-shadow-color), 0 2px 4px -2px var(--tw-shadow-color);
|
||||
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
|
||||
}
|
||||
|
||||
.shadow-sm {
|
||||
--tw-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05);
|
||||
--tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color);
|
||||
box-shadow:
|
||||
var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000),
|
||||
var(--tw-shadow);
|
||||
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
|
||||
}
|
||||
|
||||
.outline-none {
|
||||
|
|
@ -1389,9 +1359,7 @@ body {
|
|||
}
|
||||
|
||||
.filter {
|
||||
filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast)
|
||||
var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate)
|
||||
var(--tw-sepia) var(--tw-drop-shadow);
|
||||
filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);
|
||||
}
|
||||
|
||||
.transition-all {
|
||||
|
|
@ -1401,8 +1369,7 @@ body {
|
|||
}
|
||||
|
||||
.transition-colors {
|
||||
transition-property:
|
||||
color, background-color, border-color, text-decoration-color, fill, stroke;
|
||||
transition-property: color, background-color, border-color, text-decoration-color, fill, stroke;
|
||||
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
||||
transition-duration: 150ms;
|
||||
}
|
||||
|
|
@ -1501,13 +1468,9 @@ body {
|
|||
}
|
||||
|
||||
.focus\:ring-2:focus {
|
||||
--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0
|
||||
var(--tw-ring-offset-width) var(--tw-ring-offset-color);
|
||||
--tw-ring-shadow: var(--tw-ring-inset) 0 0 0
|
||||
calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);
|
||||
box-shadow:
|
||||
var(--tw-ring-offset-shadow), var(--tw-ring-shadow),
|
||||
var(--tw-shadow, 0 0 #0000);
|
||||
--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
|
||||
--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);
|
||||
box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
|
||||
}
|
||||
|
||||
.focus\:ring-ring:focus {
|
||||
|
|
@ -1524,13 +1487,9 @@ body {
|
|||
}
|
||||
|
||||
.focus-visible\:ring-1:focus-visible {
|
||||
--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0
|
||||
var(--tw-ring-offset-width) var(--tw-ring-offset-color);
|
||||
--tw-ring-shadow: var(--tw-ring-inset) 0 0 0
|
||||
calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);
|
||||
box-shadow:
|
||||
var(--tw-ring-offset-shadow), var(--tw-ring-shadow),
|
||||
var(--tw-shadow, 0 0 #0000);
|
||||
--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
|
||||
--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);
|
||||
box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
|
||||
}
|
||||
|
||||
.focus-visible\:ring-ring:focus-visible {
|
||||
|
|
@ -1620,9 +1579,7 @@ body {
|
|||
color: hsl(var(--muted-foreground));
|
||||
}
|
||||
|
||||
.\[\&_\[cmdk-group\]\:not\(\[hidden\]\)_\~\[cmdk-group\]\]\:pt-0
|
||||
[cmdk-group]:not([hidden])
|
||||
~ [cmdk-group] {
|
||||
.\[\&_\[cmdk-group\]\:not\(\[hidden\]\)_\~\[cmdk-group\]\]\:pt-0 [cmdk-group]:not([hidden]) ~[cmdk-group] {
|
||||
padding-top: 0px;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -351,6 +351,11 @@ app.all("/auth/notion/callback", zValidator("query", z.object({ code: z.string()
|
|||
|
||||
const notionCredentials = btoa(`${c.env.NOTION_CLIENT_ID}:${c.env.NOTION_CLIENT_SECRET}`);
|
||||
|
||||
const redirectUri = c.env.NODE_ENV === "development"
|
||||
? "http://localhost:3000/auth/notion/callback"
|
||||
: "https://supermemory.ai/auth/notion/callback";
|
||||
console.log(redirectUri)
|
||||
|
||||
const response = await fetch("https://api.notion.com/v1/oauth/token", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
|
|
@ -360,10 +365,7 @@ app.all("/auth/notion/callback", zValidator("query", z.object({ code: z.string()
|
|||
body: JSON.stringify({
|
||||
grant_type: "authorization_code",
|
||||
code: code,
|
||||
redirect_uri:
|
||||
c.env.NODE_ENV === "production"
|
||||
? "https://supermemory.ai/auth/notion/callback"
|
||||
: "http://localhost:3000/auth/notion/callback",
|
||||
redirect_uri: redirectUri,
|
||||
}),
|
||||
});
|
||||
|
||||
|
|
@ -381,6 +383,7 @@ app.all("/auth/notion/callback", zValidator("query", z.object({ code: z.string()
|
|||
const success = !(data as any).error;
|
||||
|
||||
if (!success) {
|
||||
console.error("Failed to get Notion access token:", data, (data as any).error);
|
||||
return c.redirect(`/?error=${(data as any).error}`);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue