Gerbuuun
Gerbuuun
Explore posts from servers
CDCloudflare Developers
Created by Gerbuuun on 5/14/2024 in #workers-help
Programmatic PDF generation on worker
Hi everyone, I've been looking for some way to generate PDFs within a worker script. Currently I use the browser rendering api to create PDFs of a page but according to the dashboard a single invocation takes 6 seconds... There must be a better and faster way right? I looked into the javascript PDF libraries (pdfkit, jspdf, pdf-lib, pdfme, etc.) but these are very limited in their features (I cannot even use a bold font?). I have no experience with Rust but I'm considering this more and more as it seems the only solution? But before I plunge myself into the deep with learning a bit of Rust, I'm curious if there are any other solutions? Will I run into the same problems as javascript (limited features)? Can I improve the speed of puppeteer rendering the PDF? This function renders the pdf on the worker:
export async function generateFromPage(browser: Browser, ticketId: string, lang: string) {
const page = await browser.newPage();
await page.setCookie({ name: 'locale', value: lang, domain: '<redacted>' });
page.on('error', err => console.log(`Browser DO: Error: ${JSON.stringify(err)}`));
page.on('pageerror', err => console.log(`Browser DO: Page Error: ${JSON.stringify(err)}`));

// create a pdf of the ticket page
await page.emulateMediaType('screen');
await page.emulateTimezone('Europe/Amsterdam');
await page.setViewport({ width: 1920, height: 1080 });
console.log(`Creating PDF of ticket page: https://<redacted>/ticket/${ticketId}`);
await page.goto(`https://<redacted>/ticket/${ticketId}`, { waitUntil: ['domcontentloaded', 'load', 'networkidle0'] });
const pdf = await page.pdf({ format: 'A4' });

// Close tab when there is no more work to be done on the page
await page.close();

return {
name: `ticket-${ticketId}.pdf`,
data: pdf,
};
}
export async function generateFromPage(browser: Browser, ticketId: string, lang: string) {
const page = await browser.newPage();
await page.setCookie({ name: 'locale', value: lang, domain: '<redacted>' });
page.on('error', err => console.log(`Browser DO: Error: ${JSON.stringify(err)}`));
page.on('pageerror', err => console.log(`Browser DO: Page Error: ${JSON.stringify(err)}`));

// create a pdf of the ticket page
await page.emulateMediaType('screen');
await page.emulateTimezone('Europe/Amsterdam');
await page.setViewport({ width: 1920, height: 1080 });
console.log(`Creating PDF of ticket page: https://<redacted>/ticket/${ticketId}`);
await page.goto(`https://<redacted>/ticket/${ticketId}`, { waitUntil: ['domcontentloaded', 'load', 'networkidle0'] });
const pdf = await page.pdf({ format: 'A4' });

// Close tab when there is no more work to be done on the page
await page.close();

return {
name: `ticket-${ticketId}.pdf`,
data: pdf,
};
}
6 replies
DTDrizzle Team
Created by Gerbuuun on 5/8/2024 in #help
Database and Drizzle checkpoints are out of sync due to custom migrations.
Hi, Due to some custom written migrations (SQLite table changes iykyk) the latest snapshot and current state of the database are out of sync. Is there a way to get them back in sync?
1 replies
NNuxt
Created by Gerbuuun on 4/21/2024 in #❓・help
Typescript nested generic resolves to unknown
Am I missing something? In the following example, shouldn't the type of result resolve to { test: { title: 'test' } }? Instead it says it's of type Record<string, unknown>
function test<T, K extends { nested: Record<string, T> }>(data: K) {
return data.nested;
}

const testdata = {
nested: {
test: {
title: 'Test',
}
}
}

const result = test(testdata);
function test<T, K extends { nested: Record<string, T> }>(data: K) {
return data.nested;
}

const testdata = {
nested: {
test: {
title: 'Test',
}
}
}

const result = test(testdata);
Did I reach the limits of Typescript?
7 replies
NNuxt
Created by Gerbuuun on 3/23/2024 in #❓・help
Nuxt Module `runtimeConfig` types.
How do I get the module.ts file to recognize the runtimeConfig type? Obviously it does not exists because there is no nuxt.config.ts but I cannot build the module because of this type error...
export default defineNuxtModule<ModuleOptions>({
meta: {
name: '@gerbuuun/mollie',
version: '0.0.1',
configKey: 'mollie',
compatibility: {
nuxt: '^3.11.1',
},
},
defaults: {
scope: ['organizations.read'],
redirectUrl: '/',
authorizationParams: undefined,
},
setup(options, nuxt) {
const resolver = createResolver(import.meta.url);

const runtimeConfig = nuxt.options.runtimeConfig;
runtimeConfig.mollie = defu(runtimeConfig.mollie, {
scope: options.scope,
redirectUrl: options.redirectUrl,
authorizationParams: options.authorizationParams,
clientId: '',
clientSecret: '',
});

// Server
if (nuxt.options.nitro.imports !== false) {
nuxt.options.nitro.imports = defu(nuxt.options.nitro.imports, {
presets: [
{
from: resolver.resolve('./runtime/server/utils/client'),
imports: ['useMollie'],
},
],
});
}

// Routes
addServerHandler({
handler: resolver.resolve('./runtime/server/api/authorize.get'),
route: '/api/_mollie/authorize',
method: 'GET',
});
addServerHandler({
handler: resolver.resolve('./runtime/server/api/redirect.get'),
route: '/api/_mollie/redirect',
method: 'GET',
});
},
});
export default defineNuxtModule<ModuleOptions>({
meta: {
name: '@gerbuuun/mollie',
version: '0.0.1',
configKey: 'mollie',
compatibility: {
nuxt: '^3.11.1',
},
},
defaults: {
scope: ['organizations.read'],
redirectUrl: '/',
authorizationParams: undefined,
},
setup(options, nuxt) {
const resolver = createResolver(import.meta.url);

const runtimeConfig = nuxt.options.runtimeConfig;
runtimeConfig.mollie = defu(runtimeConfig.mollie, {
scope: options.scope,
redirectUrl: options.redirectUrl,
authorizationParams: options.authorizationParams,
clientId: '',
clientSecret: '',
});

// Server
if (nuxt.options.nitro.imports !== false) {
nuxt.options.nitro.imports = defu(nuxt.options.nitro.imports, {
presets: [
{
from: resolver.resolve('./runtime/server/utils/client'),
imports: ['useMollie'],
},
],
});
}

// Routes
addServerHandler({
handler: resolver.resolve('./runtime/server/api/authorize.get'),
route: '/api/_mollie/authorize',
method: 'GET',
});
addServerHandler({
handler: resolver.resolve('./runtime/server/api/redirect.get'),
route: '/api/_mollie/redirect',
method: 'GET',
});
},
});
8 replies
DTDrizzle Team
Created by Gerbuuun on 7/3/2023 in #help
Drizzle-kit database push connection error
When trying to run drizzle-kit push:mysql to push my schema to Planetscale, I get the following error. Am I missing something?
drizzle-kit push:mysql
drizzle-kit: v0.19.3
drizzle-orm: v0.27.0

No config path provided, using default 'drizzle.config.ts'
Reading config file '/Users/gerbuuun/ghq/github.com/Gerbuuun/my-admin-nuxt/drizzle.config.ts'
/Users/gerbuuun/ghq/github.com/Gerbuuun/my-admin-nuxt/node_modules/.pnpm/[email protected]/node_modules/drizzle-kit/index.cjs:34877
const createConnectionErr = new Error();
^

Error: getaddrinfo ENOTFOUND ${DATABASE_HOST}
at createConnection2 (/Users/gerbuuun/ghq/github.com/Gerbuuun/my-admin-nuxt/node_modules/.pnpm/[email protected]/node_modules/drizzle-kit/index.cjs:34877:35)
at connectToMySQL (/Users/gerbuuun/ghq/github.com/Gerbuuun/my-admin-nuxt/node_modules/.pnpm/[email protected]/node_modules/drizzle-kit/index.cjs:36958:60)
at Command.<anonymous> (/Users/gerbuuun/ghq/github.com/Gerbuuun/my-admin-nuxt/node_modules/.pnpm/[email protected]/node_modules/drizzle-kit/index.cjs:52048:28) {
code: 'ENOTFOUND',
errno: -3008,
sqlState: undefined
}

Node.js v20.2.0
drizzle-kit push:mysql
drizzle-kit: v0.19.3
drizzle-orm: v0.27.0

No config path provided, using default 'drizzle.config.ts'
Reading config file '/Users/gerbuuun/ghq/github.com/Gerbuuun/my-admin-nuxt/drizzle.config.ts'
/Users/gerbuuun/ghq/github.com/Gerbuuun/my-admin-nuxt/node_modules/.pnpm/[email protected]/node_modules/drizzle-kit/index.cjs:34877
const createConnectionErr = new Error();
^

Error: getaddrinfo ENOTFOUND ${DATABASE_HOST}
at createConnection2 (/Users/gerbuuun/ghq/github.com/Gerbuuun/my-admin-nuxt/node_modules/.pnpm/[email protected]/node_modules/drizzle-kit/index.cjs:34877:35)
at connectToMySQL (/Users/gerbuuun/ghq/github.com/Gerbuuun/my-admin-nuxt/node_modules/.pnpm/[email protected]/node_modules/drizzle-kit/index.cjs:36958:60)
at Command.<anonymous> (/Users/gerbuuun/ghq/github.com/Gerbuuun/my-admin-nuxt/node_modules/.pnpm/[email protected]/node_modules/drizzle-kit/index.cjs:52048:28) {
code: 'ENOTFOUND',
errno: -3008,
sqlState: undefined
}

Node.js v20.2.0
This is my drizzle.config.ts
import type { Config } from "drizzle-kit";
import * as dotenv from "dotenv";
dotenv.config();

export default {
schema: "./database/schema/*",
out: "./drizzle",
driver: "mysql2",
dbCredentials: {
connectionString: process.env.DATABASE_URL as string,
},
} satisfies Config;
import type { Config } from "drizzle-kit";
import * as dotenv from "dotenv";
dotenv.config();

export default {
schema: "./database/schema/*",
out: "./drizzle",
driver: "mysql2",
dbCredentials: {
connectionString: process.env.DATABASE_URL as string,
},
} satisfies Config;
And my .env file looks like this:
# Database
DATABASE_HOST=aws.connect.psdb.cloud
DATABASE_USERNAME=<hidden>
DATABASE_PASSWORD=<hidden>
DATABASE_NAME=<hidden>
DATABASE_URL=mysql://${DATABASE_USERNAME}:${DATABASE_PASSWORD}@${DATABASE_HOST}/${DATABASE_NAME}?ssl={"rejectUnauthorized":true}
# Database
DATABASE_HOST=aws.connect.psdb.cloud
DATABASE_USERNAME=<hidden>
DATABASE_PASSWORD=<hidden>
DATABASE_NAME=<hidden>
DATABASE_URL=mysql://${DATABASE_USERNAME}:${DATABASE_PASSWORD}@${DATABASE_HOST}/${DATABASE_NAME}?ssl={"rejectUnauthorized":true}
4 replies
DTDrizzle Team
Created by Gerbuuun on 4/17/2023 in #help
Syntax error mysql migration using composite primary key
--> statement-breakpoint
CREATE TABLE `member_to_address` (
`member_id` varchar(32) NOT NULL,
`address_id` varchar(32) NOT NULL
);
ALTER TABLE `member_to_address` ADD PRIMARY KEY(`member_id`,`address_id`);
--> statement-breakpoint
CREATE TABLE `member_to_address` (
`member_id` varchar(32) NOT NULL,
`address_id` varchar(32) NOT NULL
);
ALTER TABLE `member_to_address` ADD PRIMARY KEY(`member_id`,`address_id`);
This part of my migration won't run due to:
DatabaseError: syntax error at position 114 near 'ALTER'
at Connection.execute (webpack-internal:///(sc_server)/./node_modules/@planetscale/database/dist/index.js:95:19)
at process.processTicksAndRejections (node:internal/process/task_queues:95:5) {
status: 400,
body: {
message: "syntax error at position 114 near 'ALTER'",
code: 'UNKNOWN'
}
}
DatabaseError: syntax error at position 114 near 'ALTER'
at Connection.execute (webpack-internal:///(sc_server)/./node_modules/@planetscale/database/dist/index.js:95:19)
at process.processTicksAndRejections (node:internal/process/task_queues:95:5) {
status: 400,
body: {
message: "syntax error at position 114 near 'ALTER'",
code: 'UNKNOWN'
}
}
The table looks like this:
export const memberToAddress = mysqlTable(
"member_to_address",
{
memberId: varchar("member_id", { length: 32 }).notNull(),
addressId: varchar("address_id", { length: 32 }).notNull(),
},
(memberToAddress) => ({
cpk: primaryKey(memberToAddress.memberId, memberToAddress.addressId),
memberIdx: index("member_idx").on(memberToAddress.memberId),
addressIdx: index("address_idx").on(memberToAddress.addressId),
})
);
export const memberToAddress = mysqlTable(
"member_to_address",
{
memberId: varchar("member_id", { length: 32 }).notNull(),
addressId: varchar("address_id", { length: 32 }).notNull(),
},
(memberToAddress) => ({
cpk: primaryKey(memberToAddress.memberId, memberToAddress.addressId),
memberIdx: index("member_idx").on(memberToAddress.memberId),
addressIdx: index("address_idx").on(memberToAddress.addressId),
})
);
Where I want to link multiple addresses to a member object. Im using the planetscale-serverless migrator.
8 replies
NNuxt
Created by Gerbuuun on 4/8/2023 in #❓・help
redirect after useFetch redirect response
When I use useFetch on a page to (for example) log in, I return a sendRedirect from the api route like so:
// login.vue
await useFetch("/api/auth/login, {
method: "POST",
body: {
email: "...",
password: "...",
},
});
// login.vue
await useFetch("/api/auth/login, {
method: "POST",
body: {
email: "...",
password: "...",
},
});
// server/api/auth/login.post.ts
export default defineEventHandler(async (event) => {

// Do login stuff...

return sendRedirect(event, "/", 302);
// server/api/auth/login.post.ts
export default defineEventHandler(async (event) => {

// Do login stuff...

return sendRedirect(event, "/", 302);
This redirect, however, does not redirect the app but returns the redirected page as the data in:
const { data } = await useFetch(...);
const { data } = await useFetch(...);
Are redirects supported by the useFetch function? Or do I need to catch the 302 http response and redirect manually? (Same goes for $fetch. I might not quite understand how the function works)
3 replies
NNuxt
Created by Gerbuuun on 12/25/2022 in #❓・help
useFetch adds null to return type
No description
9 replies