ClickHouse / clickhouse-js

Official JS client for ClickHouse DB
https://clickhouse.com
Apache License 2.0
217 stars 26 forks source link

Export `NodeClickHouseClient` as value from `client-node` for verbatimModuleSyntax=true environments #292

Closed matbour closed 2 months ago

matbour commented 2 months ago

Use case

Currently, NodeClickHouseClient is exported as a type in the client-node package.

https://github.com/ClickHouse/clickhouse-js/blob/a332672bfb70d54dfd27ae1f8f5169a6ffeea780/packages/client-node/src/index.ts#L1-L4

While I understand that it is an architecture decision so developers are forced to use the createClient function, it is problematic for dependency injection frameworks such as Nest.js or tsyringe.

In Nest.js, the following code does not work with tsconfig verbatimModuleSyntax=true:

import { createClient } from '@clickhouse/client';
import { NodeClickHouseClient } from '@clickhouse/client';
// ˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆ
// 'ClickHouseClient' resolves to a type-only declaration and must be imported using a type-only import when 'verbatimModuleSyntax' is enabled

@Module({
  providers: [
    {
      provide: NodeClickHouseClient,
      useFactory: () => {
        return createClient({
          url: process.env.CLICKHOUSE_URL,
          clickhouse_settings: {
            async_insert: 1,
            wait_for_async_insert: 1,
          },
        });
      },
    },
  ],
  exports: [NodeClickHouseClient],
})
export default class ClickHouseModule {}

Describe the solution you'd like

I would like to export the ClickhouseClient as a value instead of type:

-export type {
-  NodeClickHouseClient as ClickHouseClient,
-  QueryResult,
+export {
+  NodeClickHouseClient as ClickHouseClient,
+  type QueryResult,
} from './client'

Describe the alternatives you've considered

My current workaround is to import { NodeClickHouseClient } from '@clickhouse/client/dist/client.js', which is far from ideal.

import { createClient } from '@clickhouse/client';
import { NodeClickHouseClient } from '@clickhouse/client/dist/index.js';

@Module({
  providers: [
    {
      provide: NodeClickHouseClient,
      useFactory: () => {
        return createClient({
          url: process.env.CLICKHOUSE_URL,
          clickhouse_settings: {
            async_insert: 1,
            wait_for_async_insert: 1,
          },
        });
      },
    },
  ],
  exports: [NodeClickHouseClient],
})
export default class ClickHouseModule {}

Additional context

Happy to submit a PR that goes into this direction if approved.

slvrtrn commented 2 months ago

If it helps, let's change the export. Could you make a PR? For consistency, it can also be exported similarly in the web version.