Paul
Paul
Explore posts from servers
CDCloudflare Developers
Created by Paul on 6/27/2024 in #workers-help
Shared logic between NextJS app or duplicate the logic?
I naively thought I could share the logic from my nextjs app with my cloudflare workers but the environment variables is causing quite a bit of issues. Even when polyfilling with import * as process from 'node:process'; , whenever I use process.env, the nextjs app doesn't understand "node:process". Is it common to simply duplicate the logic for the cloudflare worker? Even my database calls requires a separate env and it's a bit too integrated. Is it common for folks to duplicate their code logic for CF workers or are people commonly able to reuse logic from their app? Is it common to declare something like globalThis.process = process (imported from node:process) when using cloudflare workers for nextjs and cloudflare worker compatability? I'm currently getting this error when I include import * as process from 'node:process'; in my nextjs app.
Module build failed: UnhandledSchemeError: Reading from "node:process" is not handled by plugins (Unhandled scheme).
Webpack supports "data:" and "file:" URIs by default.
You may need an additional plugin to handle "node:" URIs.
Import trace for requested module:
node:process
Module build failed: UnhandledSchemeError: Reading from "node:process" is not handled by plugins (Unhandled scheme).
Webpack supports "data:" and "file:" URIs by default.
You may need an additional plugin to handle "node:" URIs.
Import trace for requested module:
node:process
1 replies
CDCloudflare Developers
Created by Paul on 6/26/2024 in #workers-help
How to maintain WebSocket client connections in Durable Object?
1) Would it be the correct understanding that in order to use the Durable Objects Hibernation API, I need to extends the DurableObject class? 2) If so, how can I delete a certain clientId on close? In the examples, it doesn't extend the DurableObject class so the handleWebsocketSession method is able to set listeners to delete clientConnectionIds. However, when extending the durableObject class, the webSocketClose and webSocketError methods handle the closing of the client, so I'm not able to refer to the same clientId anymore.. See code below:
5 replies
HHono
Created by Paul on 6/26/2024 in #help
Can the queue only be defined in the root?
When writing a Cloudflare queue with Honojs, it seems the queue needs to be exported as part of the default. This default export cannot be mounted in another route path. Do all queue handlers need to be exported from the root?
2 replies
HHono
Created by Paul on 6/25/2024 in #help
How can I mount Cloudflare Durable Objects to a route?
Durable Objects Docs: https://hono.dev/examples/cloudflare-durable-objects Durable Object example straight from docs. tldr; it's a class.
import { Hono } from 'hono'

export default class Counter {
value: number = 0
state: DurableObjectState
app: Hono = new Hono()

constructor(state: DurableObjectState) {
this.state = state
this.state.blockConcurrencyWhile(async () => {
const stored = await this.state.storage?.get<number>('value')
this.value = stored || 0
})

this.app.get('/increment', async (c) => {
const currentValue = ++this.value
await this.state.storage?.put('value', this.value)
return c.text(currentValue.toString())
})

this.app.get('/decrement', async (c) => {
const currentValue = --this.value
await this.state.storage?.put('value', this.value)
return c.text(currentValue.toString())
})

this.app.get('/', async (c) => {
return c.text(this.value.toString())
})
}

async fetch(request: Request) {
return this.app.fetch(request)
}
}
import { Hono } from 'hono'

export default class Counter {
value: number = 0
state: DurableObjectState
app: Hono = new Hono()

constructor(state: DurableObjectState) {
this.state = state
this.state.blockConcurrencyWhile(async () => {
const stored = await this.state.storage?.get<number>('value')
this.value = stored || 0
})

this.app.get('/increment', async (c) => {
const currentValue = ++this.value
await this.state.storage?.put('value', this.value)
return c.text(currentValue.toString())
})

this.app.get('/decrement', async (c) => {
const currentValue = --this.value
await this.state.storage?.put('value', this.value)
return c.text(currentValue.toString())
})

this.app.get('/', async (c) => {
return c.text(this.value.toString())
})
}

async fetch(request: Request) {
return this.app.fetch(request)
}
}
How can I mount this class on a route?
import durableObject from "./durable-object";

export const app = new Hono();
app.route("/durable-object", durableObject);
import durableObject from "./durable-object";

export const app = new Hono();
app.route("/durable-object", durableObject);
Error:
Argument of type 'typeof Counter' is not assignable to parameter of type 'Hono<Env, Schema, string>'.
Type 'typeof Counter' is missing the following properties from type 'Hono<Env, Schema, string>': #private, get, post, put, and 25 more.ts(2345)
Error (TS2345) |
Argument of type
is not assignable to parameter of type
.


Type
is missing the following properties from type
:
#private, get, post, put, and 25 more.
Argument of type 'typeof Counter' is not assignable to parameter of type 'Hono<Env, Schema, string>'.
Type 'typeof Counter' is missing the following properties from type 'Hono<Env, Schema, string>': #private, get, post, put, and 25 more.ts(2345)
Error (TS2345) |
Argument of type
is not assignable to parameter of type
.


Type
is missing the following properties from type
:
#private, get, post, put, and 25 more.
1 replies
DTDrizzle Team
Created by Paul on 6/16/2024 in #help
How can I append a subquery as an array in the main query select?
How can I append a subquery as an array in the main query select? I'm currently using the alternative which is to use relational queries, but when using the db.select() syntax, is it possible to append subqueries or any leftJoins for that matter as an array in the final select?
const subquery = db
.select({
id: myTable1.id,
})
.from(myTable1)
.as("subquery");

const query = db
.select({
id: myTable2.id,
table1Ids: sql`array(${subquery})`.as("table1Ids")
// Error. Syntax error at or near "subquery"
})
.from(myTable2)
.leftJoin(
subquery,
eq(subquery.id, myTable2.table1Id)
);
const subquery = db
.select({
id: myTable1.id,
})
.from(myTable1)
.as("subquery");

const query = db
.select({
id: myTable2.id,
table1Ids: sql`array(${subquery})`.as("table1Ids")
// Error. Syntax error at or near "subquery"
})
.from(myTable2)
.leftJoin(
subquery,
eq(subquery.id, myTable2.table1Id)
);
1 replies
DTDrizzle Team
Created by Paul on 6/3/2024 in #help
How to set a GIN index on the JSONB column?
How can I set a GIN index on the whole jsonb column and also on a single column?
import { sql } from "drizzle-orm";
import { index, jsonb, pgTable } from "drizzle-orm/pg-core";

export const users = pgTable("users", {
metadata: jsonb("metadata").$type<Record<string, any>>(),
}, t => ({
ginIndex: index("gin_idx").on(t.metadata).using(sql`gin`),
ginIndex2: index("gin_idx_2").on(t.metadata).using(sql`GIN ((metadata->'name'))`),
}));
import { sql } from "drizzle-orm";
import { index, jsonb, pgTable } from "drizzle-orm/pg-core";

export const users = pgTable("users", {
metadata: jsonb("metadata").$type<Record<string, any>>(),
}, t => ({
ginIndex: index("gin_idx").on(t.metadata).using(sql`gin`),
ginIndex2: index("gin_idx_2").on(t.metadata).using(sql`GIN ((metadata->'name'))`),
}));
Is currently giving me this only:
CREATE TABLE IF NOT EXISTS "users" (
"metadata" jsonb
);
--> statement-breakpoint
CREATE INDEX IF NOT EXISTS "users_metadata_gin_idx" ON "users" ("metadata");--> statement-breakpoint
CREATE INDEX IF NOT EXISTS "users_metadata_name_gin_idx" ON "users" ("metadata");
CREATE TABLE IF NOT EXISTS "users" (
"metadata" jsonb
);
--> statement-breakpoint
CREATE INDEX IF NOT EXISTS "users_metadata_gin_idx" ON "users" ("metadata");--> statement-breakpoint
CREATE INDEX IF NOT EXISTS "users_metadata_name_gin_idx" ON "users" ("metadata");
3 replies
DTDrizzle Team
Created by Paul on 6/3/2024 in #help
When using a foreignKey({}), is there a way to specify onDelete: "cascade'?
I'm looking to custom name my foreign keys so I need to use the foreignKey() function. However, how can I specify an action: {onDelete: "cacade"} using this function?
userIdReference: foreignKey(
{
columns: [table.userId],
foreignColumns: [users.userId],
name: "accounts_user_id_fk",
},
),
userIdReference: foreignKey(
{
columns: [table.userId],
foreignColumns: [users.userId],
name: "accounts_user_id_fk",
},
),
To my understanding, if I use the .references() method, it doesn't allow for naming foreign keys
userId: integer('user_id').references(() => users.id, { onDelete: 'cascade' })
userId: integer('user_id').references(() => users.id, { onDelete: 'cascade' })
4 replies
CDCloudflare Developers
Created by Paul on 5/30/2024 in #workers-help
Queues taking 25 seconds to be consumed in development. Why?
In local development, when I have an api route that triggers a queue using hono, and the consumer simply console logs the message, for some reason it has a delay of 25 seconds before all the console logs come printing out. Any idea on why that is? I would have thought it would be instant...? Code is written with hono.js This is my producer:
app.get("/test", async c => {
const message = `Test message. Random number: ${Math.floor(Math.random() * 100)}`;
await c.env.WEBSITE_QUEUE.send({
body: message,
});

return c.json({ success: `Queued up this message: ${message}` });
});
app.get("/test", async c => {
const message = `Test message. Random number: ${Math.floor(Math.random() * 100)}`;
await c.env.WEBSITE_QUEUE.send({
body: message,
});

return c.json({ success: `Queued up this message: ${message}` });
});
This is my consumer that simply console.logs the message
export default {
fetch: app.fetch,
async queue(batch: MessageBatch<{ body: string }>, env: Environment) {
for (const message of batch.messages) {
console.log(
`Consuming message: ${JSON.stringify(message.body, null, 2)}`
);
}
},
};
export default {
fetch: app.fetch,
async queue(batch: MessageBatch<{ body: string }>, env: Environment) {
for (const message of batch.messages) {
console.log(
`Consuming message: ${JSON.stringify(message.body, null, 2)}`
);
}
},
};
2 replies
DTDrizzle Team
Created by Paul on 5/25/2024 in #help
General question: Should I use external ids or internal ids when inserting data from a third party?
I'm storing Facebook ads in my database and I'm struggling to figure out whether to use external ids or internal ids. Relevant Stack: Using postgres, drizzle-orm, supabase Background: A facebook ad breaks down into several components: Facebook page, adCreative, ad, locations, 1) On a high level, I could ingest the facebook ad, break it down into it's component parts, add my own internal ids to each and reference each component with the internal ids; OR 2) I could rely mainly on the external ids as indexes (maybe primary key, maybe not), and link them based on these external ids Internal IDs: - Pros: My own data is protected from changes from Facebook - Cons: This makes inserting data in bulk way more sophisticated. Any ad will have the external ids, but I'll need to query for all the fields based on the external id in my database, check if they exist, if not, appending the corresponding internal id to the referencing table for each component. For example, if an ad references a page based on an internal id, I'll need to query for if that external pageId exists, if so, use that page's internalId and add it to the ad so that it is linked properly. External IDs: - Pros: Makes inserting into my database so much easier - Cons: Subject to changes from Facebook (realistically, it will be fine) as my ids are dependent on a third party's ids. I started using internal Ids because chatgpt said internal is better for more control, but the insertion process is really sophisticated and difficult to reason about. Can someone give me some insight, opinion, or recommendation on what they would do?
1 replies
TTCTheo's Typesafe Cult
Created by Paul on 5/25/2024 in #questions
How to manage external ids in my database
I'm storing Facebook ads in my database and I'm struggling to figure out whether to use external ids or internal ids. Relevant Stack: Using postgres, drizzle-orm, supabase Background: A facebook ad breaks down into several components: Facebook page, adCreative, ad, locations, 1) On a high level, I could ingest the facebook ad, break it down into it's component parts, add my own internal ids to each and reference each component with the internal ids; OR 2) I could rely mainly on the external ids as indexes (maybe primary key, maybe not), and link them based on these external ids Internal IDs: - Pros: My own data is protected from changes from Facebook - Cons: This makes inserting data in bulk way more sophisticated. Any ad will have the external ids, but I'll need to query for all the fields based on the external id in my database, check if they exist, if not, appending the corresponding internal id to the referencing table for each component. For example, if an ad references a page based on an internal id, I'll need to query for if that external pageId exists, if so, use that page's internalId and add it to the ad so that it is linked properly. External IDs: - Pros: Makes inserting into my database so much easier - Cons: Subject to changes from Facebook (realistically, it will be fine) as my ids are dependent on a third party's ids. I started using internal Ids because chatgpt said internal is better for more control, but the insertion process is really sophisticated and difficult to reason about. Can someone give me some insight, opinion, or recommendation on what they would do?
2 replies
TTCTheo's Typesafe Cult
Created by Paul on 5/15/2024 in #questions
how to use argon2 on vercel
There seems to be a persistent error when trying to use Argon2 on vercel. The project doesn’t deploy. Has anyone been able to get this working? The only way I made it work was running node 14 but that will be deprecated soon
2 replies
TTCTheo's Typesafe Cult
Created by Paul on 4/22/2024 in #questions
Is Prisma ORM still slow?
I’ve been using drizzle with postgres for a while. Wanted to use mongodb for another project with nextjs. I know prisma improved their data connection speed a bit a while back but is it still slow in real world usage or is it fine now?
11 replies
TTCTheo's Typesafe Cult
Created by Paul on 4/15/2024 in #questions
How can I subscribe to updates in an RSS feed?
I want to subscribe to changes on a shopify store’s RSS feed for their products. It seems extremely compute intensive to fetch the rss url every second or even every hour. I know RSS feeds are meant to be subscribed to so how can I make it so that I can get a trigger and update data in my database whenever the rss feed changes? Essentially how does feedly work under the hood? Ofc I can’t use feedly itself since I need to update my db based on updates in the rss feed
2 replies
DTDrizzle Team
Created by Paul on 12/5/2023 in #help
Does Drizzle-Orm Expose Wrapper Types?
So I want to write a wrapper around drizzle-orm where I can pass in things like a where filter or order filter so in case I ever change to a different ORM I can do so. Does drizzle-orm expose the types for each of these methods? Or is there some example of folks writing a general wrapper around it? For example, type-orm exposes a lot of input option types like below:
import {
FindManyOptions,
FindOneOptions,
FindOperator,
FindOptionsSelect,
FindOptionsWhere,
OrderByCondition
} from "typeorm";

import { FindOptionsOrder } from "typeorm/find-options/FindOptionsOrder";
import { FindOptionsRelations } from "typeorm/find-options/FindOptionsRelations";
import {
FindManyOptions,
FindOneOptions,
FindOperator,
FindOptionsSelect,
FindOptionsWhere,
OrderByCondition
} from "typeorm";

import { FindOptionsOrder } from "typeorm/find-options/FindOptionsOrder";
import { FindOptionsRelations } from "typeorm/find-options/FindOptionsRelations";
5 replies
DTDrizzle Team
Created by Paul on 11/12/2023 in #help
How to implement Row Level Security in Postgres?
In my chat app, I have chats and messages. There are multiple messages in each chat. I'm trying to prevent user1 from editing user2's messages. ChatGPT suggests row-level security like the following
-- Enable row-level security on the messages table
ALTER TABLE messages ENABLE ROW LEVEL SECURITY;

-- Create a policy that allows users to access only their own messages
CREATE POLICY messages_user_policy
FOR ALL
USING (current_setting('app.user_id')::text = chat_id);

-- Set the current user ID when connecting to the database
SET app.user_id = 'user1';

-- Now, when querying the messages table, only messages belonging to 'user1' will be returned
SELECT * FROM messages;
-- Enable row-level security on the messages table
ALTER TABLE messages ENABLE ROW LEVEL SECURITY;

-- Create a policy that allows users to access only their own messages
CREATE POLICY messages_user_policy
FOR ALL
USING (current_setting('app.user_id')::text = chat_id);

-- Set the current user ID when connecting to the database
SET app.user_id = 'user1';

-- Now, when querying the messages table, only messages belonging to 'user1' will be returned
SELECT * FROM messages;
Is there any guidance on where/how I can implement this via drizzle-orm? I'm okay to use the "magical" sql function. But.. 1) When defining the policy, is there a place to define it in my pgSchema() call? 2) When querying, can I slot in the SET app.user_id = 'user1'; before querying in my typical query somehow? Oh I guess await db.execute(sqlSET app.user_id = 'user1';) works....? How about question 1 then? I guess also await db.execute(sql``)?
4 replies
DTDrizzle Team
Created by Paul on 10/19/2023 in #help
How to create unique lowercase index?
I'm trying to recreate the following sql statement. I don't think what I'm writing with the where clause is correct. But writing .on(sqllower(domain)) results in a type error. Is there a way to do it in drizzle currently?
create unique index sso_domains_domain_idx on auth.sso_domains using btree (lower(domain)) tablespace pg_default;
create unique index sso_domains_domain_idx on auth.sso_domains using btree (lower(domain)) tablespace pg_default;
export const ssoDomains = authSchema.table(
"sso_domains",
{
domain: text("domain").notNull(),
},
table => ({
ssoDomainsDomainIdx: uniqueIndex("sso_domains_domain_idx").on(table.domain).where(sql`lower(${table.domain.name})`),
})
);
export const ssoDomains = authSchema.table(
"sso_domains",
{
domain: text("domain").notNull(),
},
table => ({
ssoDomainsDomainIdx: uniqueIndex("sso_domains_domain_idx").on(table.domain).where(sql`lower(${table.domain.name})`),
})
);
4 replies
DTDrizzle Team
Created by Paul on 10/19/2023 in #help
Discussion: cuid2 vs ulid?
Is it better to have a sortable primayKey like ulid but leak the creation date? Or a non-sortable and slower one for enhanced security? Which is best for production apps? The section here in the docs references cuid2, but not ulid interestingly. https://orm.drizzle.team/docs/column-types/pg#constraints--defaults
8 replies
TTCTheo's Typesafe Cult
Created by Paul on 9/29/2023 in #questions
Server Actions: Do you need to validate the session when calling Server Actions?
1) When using server actions, there's no need to use csrf tokens anymore right since no external party can call your server action. So it saves this whole step and complication right? 2) When using server actions, if I am storing my sessions in a database, do I still need to check if the user has an active session on every server action mutation? In the past you would need to since anyone can POST to your route. But now with server actions.... only you can call a function on your server right? Therefore, there's no need to validate any database changing function calls in the server action right? Or is that wrong, because someone can manipulate the javascript on the client side to still call the server action? If it still requires validation, I guess it would be a good idea to create a middleware-like server action that validates the user or throws before any mutation right?
3 replies
DTDrizzle Team
Created by Paul on 9/24/2023 in #help
Is it possible to run javascript between database transactions?
In my authentication flow, I need to do the following things on signup 1. Check if user exists 2. Check if email verification token exists 3. If not, create new verification token So.... instead of hitting the database 3 times, I thought it'd be a good idea to hit it once via a transaction. My understanding is that even if just querying twice and updating once, it's still better to do it all in one transaction. But wait.... Inbetween the db calls, I throw errors if the user or token already exists. When I think about it, if the queries are being sent to the database as one transaction and the erros thrown are written in javascript and inbetween those transactions, doesn't that mean the database won't run the code inbetween the transactions? Can someone confirm that this will indeed need to be 3 transactions in order for me to throw properly. I can't do all this in one transaction because the errors won't throw right? Because the database won't receive the javascript. For example (pseudo-code below):
await db.transaction(async tx => {
const hasUser = await tx.query.users.findFirst(...);
if (hasUser) {
throw new Error("User already exists");
}
// ^ This doesn't work right?

const hasToken = await tx.query.token.findFirst(...);
if (hasToken) {
throw new Error("Token already exists");
}
// ^ Neither does this?

const token = await tx.insert(token).values(...);
});
await db.transaction(async tx => {
const hasUser = await tx.query.users.findFirst(...);
if (hasUser) {
throw new Error("User already exists");
}
// ^ This doesn't work right?

const hasToken = await tx.query.token.findFirst(...);
if (hasToken) {
throw new Error("Token already exists");
}
// ^ Neither does this?

const token = await tx.insert(token).values(...);
});
9 replies
TTCTheo's Typesafe Cult
Created by Paul on 9/23/2023 in #questions
Do multiple server actions resolve to one lambda call or is it multiple?
A few questions on server actions in Nextjs 1) Can I have a server action call another server action? I don't see why not. 2) If so, does that result in two lambda functions being invoked or does it just treat it as a function calling another function and in terms of lambdas, it just becomes one lambda instance? Which I think so... 3) If it's just one lambda call, is there a difference between writing "use server" in the second function that the first server function calls? It's just symantics to ensure it's running on the server right? Doesn't really make that much of a difference and it's just safer to put it I guess but it doesn't neccessite that it becomes two lambda calls right? I also note that this is slightly different than the server only directive which protects env variables from being exposed on the client by accident. That is, writing use server is more for the developer to explicitly see that it's running on a server, and multiple server actions with use server can call each other and it's still one lambda call right?
2 replies