DiamondDragon
DiamondDragon
Explore posts from servers
DTDrizzle Team
Created by DiamondDragon on 12/21/2024 in #help
Drizzle produces wrong branded type using Zod
It appears using brands with Drizzle Zod doesn't work correct?
//? Files *//
const fileIdSchema = z.string().uuid().brand<'FileId'>()
type FileId = z.infer<typeof fileIdSchema>
export const files = pgTable('files', {
id: uuid()
.primaryKey()
.$defaultFn(() => uuidv7())
.$type<FileId>(),
name: varchar({ length: 255 }).notNull(),

})
//? Files *//
const fileIdSchema = z.string().uuid().brand<'FileId'>()
type FileId = z.infer<typeof fileIdSchema>
export const files = pgTable('files', {
id: uuid()
.primaryKey()
.$defaultFn(() => uuidv7())
.$type<FileId>(),
name: varchar({ length: 255 }).notNull(),

})
type fileInternal = typeof files.$inferSelect
type fileInternal = {
name: string;
id: string & BRAND<"FileId">;
....
}
type fileInternal = typeof files.$inferSelect
type fileInternal = {
name: string;
id: string & BRAND<"FileId">;
....
}
export const zodFilesInsertSchema = createInsertSchema(files)
export type FilesInsert = z.infer<typeof zodFilesInsertSchema>
type FilesInsert = {
name: string;
id: {
[x: number]: string;
length: number;
[Symbol.iterator]: {};
charAt: {};
...
[BRAND]: {
FileId: boolean;
};
} | undefined;

}
export const zodFilesInsertSchema = createInsertSchema(files)
export type FilesInsert = z.infer<typeof zodFilesInsertSchema>
type FilesInsert = {
name: string;
id: {
[x: number]: string;
length: number;
[Symbol.iterator]: {};
charAt: {};
...
[BRAND]: {
FileId: boolean;
};
} | undefined;

}
So effectively anytime you use your return value produced by db.insert().returning()and pass the ID field (branded) to another param that expects the branded FileId, you get an error like
Type '{ [x: number]: string; [BRAND]: { FileId: boolean; }; [Symbol.iterator]: {}; length: number; toString: {}; concat: {}; slice: {}; indexOf: {}; lastIndexOf: {}; includes: {}; at: {}; charAt: {}; charCodeAt: {}; ... 40 more ...; valueOf: {}; }' is not assignable to type 'string & BRAND<"FileId">'.
Type '{ [x: number]: string; [BRAND]: { FileId: boolean; }; [Symbol.iterator]: {}; length: number; toString: {}; concat: {}; slice: {}; indexOf: {}; lastIndexOf: {}; includes: {}; at: {}; charAt: {}; charCodeAt: {}; ... 40 more ...; valueOf: {}; }' is not assignable to type 'string'.
Type '{ [x: number]: string; [BRAND]: { FileId: boolean; }; [Symbol.iterator]: {}; length: number; toString: {}; concat: {}; slice: {}; indexOf: {}; lastIndexOf: {}; includes: {}; at: {}; charAt: {}; charCodeAt: {}; ... 40 more ...; valueOf: {}; }' is not assignable to type 'string & BRAND<"FileId">'.
Type '{ [x: number]: string; [BRAND]: { FileId: boolean; }; [Symbol.iterator]: {}; length: number; toString: {}; concat: {}; slice: {}; indexOf: {}; lastIndexOf: {}; includes: {}; at: {}; charAt: {}; charCodeAt: {}; ... 40 more ...; valueOf: {}; }' is not assignable to type 'string'.
6 replies
DTDrizzle Team
Created by DiamondDragon on 12/17/2024 in #help
Can't upsert with onConflictDoUpdate & generatedAlwaysAsIdentity ID columns?
I've noticed the type system doesn't recognize the ID columns (since they are supposed to be autogenerated?) How would one upsert or update? The ID field is not available
export const folders = pgTable('folders', {
id: integer().primaryKey().generatedAlwaysAsIdentity({ startWith: 1000 }),
name: text('name').notNull(),
createdBy: integer('created_by')
.notNull()
.references(() => users.id),
parentFolderId: integer('parent_folder_id').references((): AnyPgColumn => folders.id),
})

const db = createDb()
// no id is available to pass to values per TS
await db.insert(folders).values({ name: 'Test', createdBy: 1000 }).onConflictDoUpdate({
// where is ID passed in?
target: folders.id, // no type error
set: { name: 'Test2' },
})
export const folders = pgTable('folders', {
id: integer().primaryKey().generatedAlwaysAsIdentity({ startWith: 1000 }),
name: text('name').notNull(),
createdBy: integer('created_by')
.notNull()
.references(() => users.id),
parentFolderId: integer('parent_folder_id').references((): AnyPgColumn => folders.id),
})

const db = createDb()
// no id is available to pass to values per TS
await db.insert(folders).values({ name: 'Test', createdBy: 1000 }).onConflictDoUpdate({
// where is ID passed in?
target: folders.id, // no type error
set: { name: 'Test2' },
})
2 replies
CCConvex Community
Created by DiamondDragon on 12/11/2024 in #support-community
Returning data from Tanstack Query useMutation wrapper
No description
3 replies
CCConvex Community
Created by DiamondDragon on 12/3/2024 in #support-community
Zod Unions appear to break `Table` helper (maybe zodToConvex related?)
No description
1 replies
CCConvex Community
Created by DiamondDragon on 12/1/2024 in #support-community
Handling Upserts with Optional System Fields
Not sure if this is the best practice here but didn't appear there's a way of getting the Id field to be optional so it can be passed in for upserts (if it doesn't exist, insert, if it does patch). Not sure if my types are entirely correct but seems to work but happy to hear if anyone else agrees
function upsertDeal(ctx: MutationCtx, args: MakeIdOptional<Deals>) {
if (args._id) { // type _id = string & {} | undefined
return ctx.db.patch(args._id, args)
}

return insertDeal(ctx, args)
}


// Make only _id optional and exclude _creationTime for upserts
export type MakeIdOptional<T> = Omit<T, '_id' | '_creationTime'> & {
_id?: T extends { _id: Id<any> } ? Id<any> : never
}
function upsertDeal(ctx: MutationCtx, args: MakeIdOptional<Deals>) {
if (args._id) { // type _id = string & {} | undefined
return ctx.db.patch(args._id, args)
}

return insertDeal(ctx, args)
}


// Make only _id optional and exclude _creationTime for upserts
export type MakeIdOptional<T> = Omit<T, '_id' | '_creationTime'> & {
_id?: T extends { _id: Id<any> } ? Id<any> : never
}
3 replies
CCConvex Community
Created by DiamondDragon on 11/26/2024 in #support-community
HTTP Path Suffix Not Working?
No description
7 replies
CCConvex Community
Created by DiamondDragon on 10/16/2024 in #support-community
Unable to get Tanstack Trellaux Start working
No description
7 replies
CDCloudflare Developers
Created by DiamondDragon on 9/30/2024 in #workers-help
Error on remote worker: APIError: A request to the Cloudflare API
I'm trying to test out a browser deployed on worker in a DO and getting this error
✘ [ERROR] Error on remote worker: APIError: A request to the Cloudflare API (/accounts/5aa6cae4d0260b6aae9d255f3b63242f/workers/scripts/playground-worker/edge-preview) failed.

at throwFetchError
(/Users/am/Coding/playground/node_modules/wrangler/wrangler-dist/cli.js:159817:18)
at fetchResult
(/Users/am/Coding/playground/node_modules/wrangler/wrangler-dist/cli.js:159730:5)
at process.processTicksAndRejections
(node:internal/process/task_queues:95:5)
at async createPreviewToken
(/Users/am/Coding/playground/node_modules/wrangler/wrangler-dist/cli.js:174177:29)
at async createWorkerPreview
(/Users/am/Coding/playground/node_modules/wrangler/wrangler-dist/cli.js:174198:17)
at async start
(/Users/am/Coding/playground/node_modules/wrangler/wrangler-dist/cli.js:174924:34)
{
text: 'A request to the Cloudflare API
(/accounts/5aa6cae4d0260b6aae9d255f3b63242f/workers/scripts/playground-worker/edge-preview)
failed.',
notes: [
{
text: 'An unknown error has occured. If this
error persists, please file a report in the
workers-sdk GitHub repository
(https://github.com/cloudflare/workers-sdk/issues) or
reach out to your account team. [code: 10002]'
}
],
location: undefined,
kind: 'error',
code: 10002,
accountTag: '5aa6cae4d0260b6aae9d255f3b63242f'
}
✘ [ERROR] Error on remote worker: APIError: A request to the Cloudflare API (/accounts/5aa6cae4d0260b6aae9d255f3b63242f/workers/scripts/playground-worker/edge-preview) failed.

at throwFetchError
(/Users/am/Coding/playground/node_modules/wrangler/wrangler-dist/cli.js:159817:18)
at fetchResult
(/Users/am/Coding/playground/node_modules/wrangler/wrangler-dist/cli.js:159730:5)
at process.processTicksAndRejections
(node:internal/process/task_queues:95:5)
at async createPreviewToken
(/Users/am/Coding/playground/node_modules/wrangler/wrangler-dist/cli.js:174177:29)
at async createWorkerPreview
(/Users/am/Coding/playground/node_modules/wrangler/wrangler-dist/cli.js:174198:17)
at async start
(/Users/am/Coding/playground/node_modules/wrangler/wrangler-dist/cli.js:174924:34)
{
text: 'A request to the Cloudflare API
(/accounts/5aa6cae4d0260b6aae9d255f3b63242f/workers/scripts/playground-worker/edge-preview)
failed.',
notes: [
{
text: 'An unknown error has occured. If this
error persists, please file a report in the
workers-sdk GitHub repository
(https://github.com/cloudflare/workers-sdk/issues) or
reach out to your account team. [code: 10002]'
}
],
location: undefined,
kind: 'error',
code: 10002,
accountTag: '5aa6cae4d0260b6aae9d255f3b63242f'
}
My toml
name = "playground-worker"
main = "src/index.ts"
compatibility_date = "2024-09-23"
compatibility_flags = [ "nodejs_compat" ]

observability = { enabled = true }

workers_dev = false
send_metrics = false
browser = { binding = "MYBROWSER" }

[durable_objects]
bindings = [
{ name = "BROWSER_DO", class_name = "BrowserDurableObject" }
]

[[migrations]]
tag = "v1" # Should be unique for each entry
new_classes = ["BrowserDurableObject"]

[triggers]
# every 5 minutes
crons = ["*/5 * * * *"]
name = "playground-worker"
main = "src/index.ts"
compatibility_date = "2024-09-23"
compatibility_flags = [ "nodejs_compat" ]

observability = { enabled = true }

workers_dev = false
send_metrics = false
browser = { binding = "MYBROWSER" }

[durable_objects]
bindings = [
{ name = "BROWSER_DO", class_name = "BrowserDurableObject" }
]

[[migrations]]
tag = "v1" # Should be unique for each entry
new_classes = ["BrowserDurableObject"]

[triggers]
# every 5 minutes
crons = ["*/5 * * * *"]
6 replies
DTDrizzle Team
Created by DiamondDragon on 9/6/2024 in #help
Drizzle Zod refining not working?
Shouldn't this code for zod make an optional field firstName required? https://drizzle.run/t2zowcjw5f1xbb5ny7zq2j3n
3 replies
DTDrizzle Team
Created by DiamondDragon on 8/31/2024 in #help
Dynamic function get use typed column names using getTableConfig
I have both UUIDs and NanoIDs on every one of my tables. I am considering adding utils to map from uuid -> nanoID & vice versa. how would i make a dynamic function like this? basically under the assumption every table has a id and shortId column which is the nanoid
export async function getUuidFromShortId(table: PgTable, shortId: string) {
const { columns, name, schema } = getTableConfig(table)
const [result] = await db
.select({ id: columns.id })
.from(name)
.where(eq(columns.shortId, shortId))
.limit(1)
return result[0]?.id ?? null
}
export async function getUuidFromShortId(table: PgTable, shortId: string) {
const { columns, name, schema } = getTableConfig(table)
const [result] = await db
.select({ id: columns.id })
.from(name)
.where(eq(columns.shortId, shortId))
.limit(1)
return result[0]?.id ?? null
}
1 replies
CDCloudflare Developers
Created by DiamondDragon on 8/25/2024 in #pages-help
Error using API Create PagesProject with pulumi - Err 'You must set a production branch.'
Calling this from a monorepo. I want to use pulumi to create a pages project/update it
import { PagesProject, type PagesProjectArgs } from '@pulumi/cloudflare'

const projectName = 'spa-cf'
const CLOUDFLARE_ACCOUNT_ID = process.env.CLOUDFLARE_ACCOUNT_ID
const CLOUDFLARE_API_TOKEN = process.env.CLOUDFLARE_API_TOKEN

const pagesProjectConfig: PagesProjectArgs = {
accountId: CLOUDFLARE_ACCOUNT_ID,
name: projectName,
productionBranch: 'main',
buildConfig: {
buildCaching: true,
buildCommand: 'bun run build',
destinationDir: '../apps/spa/dist',
rootDir: '../apps/spa',
},
}

export const pagesProject = new PagesProject(projectName, pagesProjectConfig)

🚀 ~ file: pages.ts:58 ~ createProject ~ url: https://api.cloudflare.com/client/v4/accounts/xxxx/pages/projects
🚀 ~ file: pages.ts:58 ~ createProject ~ request: {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: 'Bearer XXX'
},
body: '{"accountId":"XXXX","name":"spa-cf","productionBranch":"main","buildConfig":{"buildCaching":true,"buildCommand":"bun run build","destinationDir":"../apps/spa/dist","rootDir":"../apps/spa"}}'
import { PagesProject, type PagesProjectArgs } from '@pulumi/cloudflare'

const projectName = 'spa-cf'
const CLOUDFLARE_ACCOUNT_ID = process.env.CLOUDFLARE_ACCOUNT_ID
const CLOUDFLARE_API_TOKEN = process.env.CLOUDFLARE_API_TOKEN

const pagesProjectConfig: PagesProjectArgs = {
accountId: CLOUDFLARE_ACCOUNT_ID,
name: projectName,
productionBranch: 'main',
buildConfig: {
buildCaching: true,
buildCommand: 'bun run build',
destinationDir: '../apps/spa/dist',
rootDir: '../apps/spa',
},
}

export const pagesProject = new PagesProject(projectName, pagesProjectConfig)

🚀 ~ file: pages.ts:58 ~ createProject ~ url: https://api.cloudflare.com/client/v4/accounts/xxxx/pages/projects
🚀 ~ file: pages.ts:58 ~ createProject ~ request: {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: 'Bearer XXX'
},
body: '{"accountId":"XXXX","name":"spa-cf","productionBranch":"main","buildConfig":{"buildCaching":true,"buildCommand":"bun run build","destinationDir":"../apps/spa/dist","rootDir":"../apps/spa"}}'
Initial deployment triggered: {
result: null,
success: false,
errors: [ { code: 8000033, message: 'You must set a production branch.' } ],
messages: []
}
Initial deployment triggered: {
result: null,
success: false,
errors: [ { code: 8000033, message: 'You must set a production branch.' } ],
messages: []
}
4 replies
DTDrizzle Team
Created by DiamondDragon on 6/20/2024 in #help
Use results of a column to pass where conditions elsewhere in the query?
I have a field that stores filters that I parse into the SQL conditions for a where clause. Or at least, that's the goal. That field is in my views table. Is it possible to pass the result of that field in views into a nested where condition?
export async function getTableData(opts: { db: Db; tableShortId: string; viewShortId: string }) {

const { db, tableShortId, viewShortId } = opts

const tableData = await db.query.views.findFirst({
where: and(eq(views.shortId, viewShortId), eq(views.tableId, tableShortId)),
columns: {
shortId: true,
},
with: {
// Get the view for the table
table: {
columns: { shortId: true },
with: {
fields: {
columns: { shortId: true },
},
records: {
//! is it possible to filter records by view.jsonColumn after being parsed
columns: { shortId: true },
with: {
export async function getTableData(opts: { db: Db; tableShortId: string; viewShortId: string }) {

const { db, tableShortId, viewShortId } = opts

const tableData = await db.query.views.findFirst({
where: and(eq(views.shortId, viewShortId), eq(views.tableId, tableShortId)),
columns: {
shortId: true,
},
with: {
// Get the view for the table
table: {
columns: { shortId: true },
with: {
fields: {
columns: { shortId: true },
},
records: {
//! is it possible to filter records by view.jsonColumn after being parsed
columns: { shortId: true },
with: {
1 replies
DTDrizzle Team
Created by DiamondDragon on 6/10/2024 in #help
construction a dynamic query builder generically ?
Ok i'm not really sure how to ask this but I'm trying to allow a user the ability in UI to build out a query builder where they can add many filters with potentially nested filters with AND/OR conjuctions. Like airtable. Anyone have any patterns how to do this? I had attempted to try to construct a mapping on the SQL operators and the drizzle functions but I can't get the types to work . I'm playing aroung just with the sql operator to try making ti work with more raw SQL. trying to wrap my head around this and its a pattern i've seen few apps implement and never seen any code online to use as a guide Ideally a user can do a query in the UI like below and the queries can be constructed dynamically.
Filter employes where
name = john AND
salary >= 50,000 AND
relatedDepartment contains 'billing' AND
( department_city does not contain NYC OR
whatever... equals blah
)
Filter employes where
name = john AND
salary >= 50,000 AND
relatedDepartment contains 'billing' AND
( department_city does not contain NYC OR
whatever... equals blah
)
const operators: Record<OperatorNames, Operator> = {
contains: {
label: 'Contains',
name: 'contains',
sql: 'LIKE',
drizzle: (column: Column, value: string | SQLWrapper): typeof like => {
return like(column, value)
},
},
// other operators...
}
const operators: Record<OperatorNames, Operator> = {
contains: {
label: 'Contains',
name: 'contains',
sql: 'LIKE',
drizzle: (column: Column, value: string | SQLWrapper): typeof like => {
return like(column, value)
},
},
// other operators...
}
1 replies
HHono
Created by DiamondDragon on 6/8/2024 in #help
Serialization of Date?
Is there any suggested guidance on how to handle js/json serialization? I ran into an issue using the hono client where the types break due to a Date being typed as a string after being returned from a hono route I see there are no data transformers provided by hono, so wondering what suggestions there are. https://discord.com/channels/1011308539819597844/1248521918554963979
26 replies
DTDrizzle Team
Created by DiamondDragon on 5/19/2024 in #help
Losing custom $types in pg jsonb using drizzle-zod
Not sure if this is an expected limitation of zod here
export const records = pgTable('records', {
id: uuid('id')
.primaryKey()
.$defaultFn(() => uuidv7()),
tableId: uuid('table_id')
.references(() => tables.id, { onDelete: 'cascade' })
.notNull(),
organizationId: uuid('organization_id')
.references(() => organizations.id, { onDelete: 'cascade' })
.notNull(),
recordByFieldId: jsonb('record_by_field_id').$type<RecordData>(),

})
export const records = pgTable('records', {
id: uuid('id')
.primaryKey()
.$defaultFn(() => uuidv7()),
tableId: uuid('table_id')
.references(() => tables.id, { onDelete: 'cascade' })
.notNull(),
organizationId: uuid('organization_id')
.references(() => organizations.id, { onDelete: 'cascade' })
.notNull(),
recordByFieldId: jsonb('record_by_field_id').$type<RecordData>(),

})
produces using $inferInsert
type Record = {
organizationId: string;
tableId: string;
id?: string;
recordByFieldId?: RecordData | null;
createdAt?: Date;
updatedAt?: Date | null;
}
type Record = {
organizationId: string;
tableId: string;
id?: string;
recordByFieldId?: RecordData | null;
createdAt?: Date;
updatedAt?: Date | null;
}
But when using drizzle zod, i lose RecordData
export const insertRecordSchema = createInsertSchema(records)
export type InsertRecord = z.infer<typeof insertRecordSchema>

// results in
type InsertRecord = {
organizationId: string;
tableId: string;
id?: string;
recordByFieldId?: any;
createdAt?: Date;
updatedAt?: Date | null;
}
export const insertRecordSchema = createInsertSchema(records)
export type InsertRecord = z.infer<typeof insertRecordSchema>

// results in
type InsertRecord = {
organizationId: string;
tableId: string;
id?: string;
recordByFieldId?: any;
createdAt?: Date;
updatedAt?: Date | null;
}
1 replies
CDCloudflare Developers
Created by DiamondDragon on 4/23/2024 in #pages-help
Can't deploy a nextjs pages site in subdirectory
No description
1 replies
DTDrizzle Team
Created by DiamondDragon on 4/17/2024 in #help
Generated SQL error / type error with operations on unique index
No description
1 replies
DTDrizzle Team
Created by DiamondDragon on 4/16/2024 in #help
Drizzle studio shows as blank page on Arc browser
No description
1 replies
CDCloudflare Developers
Created by DiamondDragon on 4/13/2024 in #workers-help
cron not running locally on the trigger specified
I'm using hono here but when i go to http://localhost:8787/__scheduled?cron=***** i see the response log
Hello
[wrangler:inf] GET /__scheduled 200 OK (11ms)
╭─────────────────────────────────────────────────────
Hello
[wrangler:inf] GET /__scheduled 200 OK (11ms)
╭─────────────────────────────────────────────────────
but I dont see anymore subsequent logs of the trigger again. am i doing anything wrong?
async function scheduledHandler(
event: ScheduledEvent,
env: Env,
ctx: ExecutionContext,
) {
const testMessages = [
'Hello',
'Goodbye',
'Welcome',
'Farewell',
'Greetings',
'I am leaving',
]
ctx.waitUntil(
(async () => {
const randomIndex = Math.floor(Math.random() * testMessages.length)
const randomMessage = testMessages[randomIndex]
console.log(randomMessage)
})(),
)
}

export default { fetch: app.fetch.bind(app), scheduled: scheduledHandler }
async function scheduledHandler(
event: ScheduledEvent,
env: Env,
ctx: ExecutionContext,
) {
const testMessages = [
'Hello',
'Goodbye',
'Welcome',
'Farewell',
'Greetings',
'I am leaving',
]
ctx.waitUntil(
(async () => {
const randomIndex = Math.floor(Math.random() * testMessages.length)
const randomMessage = testMessages[randomIndex]
console.log(randomMessage)
})(),
)
}

export default { fetch: app.fetch.bind(app), scheduled: scheduledHandler }
4 replies
CDCloudflare Developers
Created by DiamondDragon on 4/13/2024 in #pages-help
Project is set up for npm but it is currently being run via bun this might lead to build errors
Don't recall using npm when i init the repo but anyways, wondering what settings were set on npm that i should check out if im using bun
❯ nr
✔ script to run › preview
$ bun pages:build && wrangler pages dev .vercel/output/static
$ bunx @cloudflare/next-on-pages
⚡️ @cloudflare/next-on-pages CLI v.1.11.0

⚡️ The project is set up for npm but it is currently being run via bun this might lead to build errors, please be sure to use the same package manager your project uses when running @cloudflare/next-on-pages

⚡️ Detected Package Manager: bun (1.1.1)
⚡️ Preparing project...
⚡️ Project is ready
⚡️ Building project...
▲ Vercel CLI 34.0.0
WARNING: You should not upload the `.next` directory.
▲ Installing dependencies...
▲ removed 3 packages, and changed 96 packages in 18s

156 packages are looking for funding
▲ run `npm fund` for details
▲ Detected Next.js version: 14.2.0
▲ Detected `package-lock.json` generated by npm 7+
▲ Running "npm run build"
> next-cf@0.1.0 build
> next build
▲ ▲ Next.js 14.2.0
- Environments: .env.local
▲ Creating an optimized production build ...
▲ ✓ Compiled successfully
❯ nr
✔ script to run › preview
$ bun pages:build && wrangler pages dev .vercel/output/static
$ bunx @cloudflare/next-on-pages
⚡️ @cloudflare/next-on-pages CLI v.1.11.0

⚡️ The project is set up for npm but it is currently being run via bun this might lead to build errors, please be sure to use the same package manager your project uses when running @cloudflare/next-on-pages

⚡️ Detected Package Manager: bun (1.1.1)
⚡️ Preparing project...
⚡️ Project is ready
⚡️ Building project...
▲ Vercel CLI 34.0.0
WARNING: You should not upload the `.next` directory.
▲ Installing dependencies...
▲ removed 3 packages, and changed 96 packages in 18s

156 packages are looking for funding
▲ run `npm fund` for details
▲ Detected Next.js version: 14.2.0
▲ Detected `package-lock.json` generated by npm 7+
▲ Running "npm run build"
> next-cf@0.1.0 build
> next build
▲ ▲ Next.js 14.2.0
- Environments: .env.local
▲ Creating an optimized production build ...
▲ ✓ Compiled successfully
5 replies