Open joseferben opened 1 year ago
Hi @joseferben, is your example open source? Would like to debug it! Or maybe you can pastebin a pseudocode example or even a blurred screen?
Did you try the latest 0.6.0
version? I've improved type performance there a substantially compared to 0.5.x
.
I had a prototype with what you describe (less feature packed version) but didn't have yet time to fully code it.
What typescript version are you using?
@molszanski It's not (yet) open source, but I can give the container setup code:
So this is the "core" service container:
export default function createContainer<T extends Tables>() {
return createContainerIti()
.add({
config: () => new EnvConfigService(),
replService: () => new REPLService(),
})
.add((ctx) => ({
dashboardService: () => new BullDashboardService(),
redis: () => new RedisService(ctx.config.redisUrl()),
database: () =>
databaseOf<T>(ctx.config.databaseUrl()).database as Kysely<T>,
workerService: () =>
ctx.config.runInEnv<WorkerService>({
production: () =>
new BullWorkerService(
ctx.config.tasksFolder(),
ctx.config.schedulesFolder()
),
test: () => new NoOpWorkerService(),
}),
emailService: () =>
ctx.config.runInEnv({
production: () =>
new ConsoleEmailService(
ctx.config.senderAddress("sender@example.com")
),
// TODO revert
// new PostmarkEmailService(
// ctx.config.postmarkEmailToken(),
// ctx.config.senderAddress(),
// ctx.config.domain()
// ),
test: () =>
new InmemoryEmailService(
ctx.config.senderAddress("sender@example.com")
),
development: () =>
new ConsoleEmailService(
ctx.config.senderAddress("sender@example.com")
),
}),
}))
.add((ctx) => ({
seedService: () =>
new SeedService(
//@ts-ignore
ctx.database,
ctx.config.seedsFolder(),
ctx.config.env()
),
scheduleService: () =>
ctx.config.runInEnv<ScheduleService>({
production: () =>
new BullScheduleService(ctx.redis, ctx.config.schedulesFolder()),
test: () => new NoOpScheduleService(),
}),
}))
.add((ctx) => ({
migrationService: () =>
new MigrationService(
//@ts-ignore
ctx.database,
ctx.config.migrationsFolder()
),
}))
.add((ctx) => ({
//@ts-ignore
userService: () => new UserService(ctx.database),
}))
.add((ctx) => ({
sessionService: () => new SessionService(ctx.userService),
magicLinkService: () =>
new MagicLinkService(
ctx.userService,
ctx.emailService,
ctx.config.magicLinkSecret(),
ctx.config.baseUrl()
),
}))
.add((ctx) => ({
cliService: () =>
new CLIService()
.addCommand(ctx.migrationService.migrate.bind(ctx.migrationService))
.addCommand(
ctx.migrationService.createFile.bind(ctx.migrationService),
"createmigration"
)
.addCommand(ctx.seedService.run.bind(ctx.seedService), "seed")
.addCommand(ctx.replService.repl.bind(ctx.replService))
.addCommand(ctx.workerService.work.bind(ctx.workerService))
.addCommand(
ctx.dashboardService.startServer.bind(ctx.dashboardService),
"dashboard"
),
}));
}
And then the application specific container builds on top:
export function createContainer() {
return libContainer<Tables>()
.upsert(() => ({
config: () => new AppConfigService(),
}))
.add((ctx) => ({
measurementQueue: () =>
ctx.config.runInEnv<QueueService<{ measurementId: string }>>({
production: () =>
new BullQueueService<{ measurementId: string }>(
ctx.redis,
"measurement"
),
test: () =>
new ImmediateQueueService<{ measurementId: string }>(
ctx.config.tasksFolder(),
"measurement"
),
}),
customerService: () => new CustomerService(ctx.database, ctx.userService),
trackingService: () =>
new TrackingService(ctx.emailService, ctx.config.adminEmails()),
}))
.add((ctx) => ({
settingsService: () => new SettingsService(ctx.database),
}))
.add((ctx) => ({
pageService: () => new PageService(ctx.database),
}))
.add((ctx) => ({
reportService: () =>
new ReportService(
ctx.config.reportingIntervall(),
ctx.config.reportConsecutiveMeasurements(),
ctx.config.reportChunkSize(),
ctx.database,
ctx.emailService,
ctx.magicLinkService,
ctx.pageService,
ctx.customerService
),
lighthouseService: () =>
ctx.config.runInEnv({
production: () => new PageSpeedService(ctx.config.pagespeedApiKey()),
development: () => new RandomAlwaysValidLighthouseService(),
test: () => new RandomAlwaysValidLighthouseService(),
}),
}))
.add((ctx) => ({
measurementService: () =>
new MeasurementService(
ctx.config.measurementInterval(),
ctx.database,
ctx.pageService,
ctx.lighthouseService,
ctx.emailService,
ctx.userService,
ctx.magicLinkService,
ctx.measurementQueue
),
}))
.add((ctx) => ({
start: () => () =>
runOnce("start", async () => {
ctx.userService.onInserted((user) => {
ctx.trackingService.onRegistration(user);
});
}),
}));
}
So something like 13 .add()
and 1 .upsert()
. Do you think adding explicit type hints could speed inference up a bit?
Whenever I go container.items.measurementService. <---
Intellisense gets super slow, restarting the TypeScript server helps.
"iti": "^0.6.0",
"typescript": "^4.8.4",
Really cool library thanks a lot for the effort 🙏
Hey! Thank you very much for the test code! I will make a project with a structure like this and check what I can do! I believe I can refactor it a bit so typescript would be able to cache everything better without recomputing types so much
Is your feature request related to a problem? Please describe. Adding a lot of
add(..)
slows down Intellisense to the point that I have to restart the TS server every now and then.Describe the solution you'd like I was wondering whether it would be feasible to provide a version of iti that has less features but provides faster type inference. I haven't dug into the code yet, just wondering whether something like that is out of the question.
What would be an ideal API for your use case? I just need
add()
,upsert()
anditems()
. No async injection or any of that disposal API.