T
TanStack9mo ago
passive-yellow

How to ensure module is imported everywhere (server, client, server functions)

I need to ensure that importExtensions is executed in all contexts. So far I only managed to make it work by importing it in client.tsx, ssr.tsx, and router.tsx, and in router.tsx I also had to make sure to execute it via a global middleware. Is there a simpler approach? router.tsx:
import { importExtensions } from '#app/shared/extensions/imports';
import { createMiddleware, registerGlobalMiddleware } from '@tanstack/start';

const defaultMiddleware = createMiddleware()
.client(({ next, context }) =>
{
importExtensions(false);
return next(context);
})
.server(({ next, context }) =>
{
importExtensions(false);
return next(context);
});

importExtensions();
registerGlobalMiddleware({ middleware: [defaultMiddleware] });
import { importExtensions } from '#app/shared/extensions/imports';
import { createMiddleware, registerGlobalMiddleware } from '@tanstack/start';

const defaultMiddleware = createMiddleware()
.client(({ next, context }) =>
{
importExtensions(false);
return next(context);
})
.server(({ next, context }) =>
{
importExtensions(false);
return next(context);
});

importExtensions();
registerGlobalMiddleware({ middleware: [defaultMiddleware] });
importExtensions:
import '#app/shared/extensions/string-extensions';
import '#app/shared/extensions/zod-extensions';

export const importExtensions = (log = true) =>
{
if (log)
{
console.log('Imported shared extensions.');
}
};
import '#app/shared/extensions/string-extensions';
import '#app/shared/extensions/zod-extensions';

export const importExtensions = (log = true) =>
{
if (log)
{
console.log('Imported shared extensions.');
}
};
6 Replies
sensitive-blue
sensitive-blue9mo ago
what does importExtensions() really do? modify some global objects?
passive-yellow
passive-yellowOP9mo ago
yes, for example zod-extensions:
import type { ZodUnionDef, ZodUnionOptions } from 'zod';
import { z, ZodBoolean, ZodEffects, ZodNumber, ZodString, ZodType, ZodUnion } from 'zod';

declare module 'zod'
{
// eslint-disable-next-line @typescript-eslint/no-namespace
export interface ZodUnion<T extends ZodUnionOptions> extends ZodType<T[number]['_output'], ZodUnionDef<T>, T[number]['_input']>
{
boolean: () => ZodEffects<ZodUnion<[ZodBoolean, ZodNumber, ZodString]>, boolean>;
}
}

z.ZodUnion.prototype.boolean = function() : ZodEffects<ZodUnion<[ZodBoolean, ZodNumber, ZodString]>, boolean>
{
return ...;
};
import type { ZodUnionDef, ZodUnionOptions } from 'zod';
import { z, ZodBoolean, ZodEffects, ZodNumber, ZodString, ZodType, ZodUnion } from 'zod';

declare module 'zod'
{
// eslint-disable-next-line @typescript-eslint/no-namespace
export interface ZodUnion<T extends ZodUnionOptions> extends ZodType<T[number]['_output'], ZodUnionDef<T>, T[number]['_input']>
{
boolean: () => ZodEffects<ZodUnion<[ZodBoolean, ZodNumber, ZodString]>, boolean>;
}
}

z.ZodUnion.prototype.boolean = function() : ZodEffects<ZodUnion<[ZodBoolean, ZodNumber, ZodString]>, boolean>
{
return ...;
};
sensitive-blue
sensitive-blue9mo ago
how do other frameworks handle this? are there any existing APIs for this?
passive-yellow
passive-yellowOP9mo ago
Handle which part specifically? I have only implemented this in a Tanstack Start project. The prototype augmentation is already working correctly in all contexts once I ensure importExtensions is always imported/executed, but I had to do some trial and error not knowing exactly what are all the possible entry points.
sensitive-blue
sensitive-blue9mo ago
I was just wondering e.g. how remix does this or nextjs if they have special APIs to register stuff like that
unwilling-turquoise
unwilling-turquoise9mo ago
out of curiosity, why do this instead of exporting utility functions? generally monkey patching like this has fallen out of favour

Did you find this page helpful?