Skip to content

Commit 1779135

Browse files
committed
Move to ESM and dynamic imports
BREAKING CHANGE: ESM breaks everything, this is no exception
1 parent 0fda225 commit 1779135

26 files changed

+467
-370
lines changed

.gitignore

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ coverage
2626
tsconfig.json
2727
tsconfig.build.json
2828
jest.config.js
29-
.prettierrc.js
30-
.eslintrc.js
3129
.commitlintrc.json
3230
vitest.config.ts
31+
.eslintrc.cjs
32+
.prettierrc.cjs

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
# all: service dbi ts
2121
#
2222

23-
build_dir := $(shell node -e "console.log(require('./package.json').main.replace(/^.\//, '').split('/')[0])")
23+
build_dir := $(shell node -e "console.log(require('./package.json').exports.replace(/^.\//, '').split('/')[0])")
2424
src_files := $(shell find src -name '*.ts')
2525
build_files := $(patsubst src/%.ts,$(build_dir)/%.js,$(src_files))
2626
camel_case_name := $(shell echo $(SERVICE_NAME) | awk -F- '{result=""; for(i=1; i<=NF; i++) result = result toupper(substr($$i,1,1)) substr($$i,2); print result}' | tr -d '\n')

__tests__/config.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ import path from 'path';
33

44
import { describe, expect, test } from 'vitest';
55

6-
import { ConfigurationSchema, insertConfigurationBefore, loadConfiguration } from '../src/config';
7-
import { shortstops } from '../src/config/shortstops';
6+
import { ConfigurationSchema, insertConfigurationBefore, loadConfiguration } from '../src/config/index.js';
7+
import { shortstops } from '../src/config/shortstops.js';
88

99
interface CustomConfig extends ConfigurationSchema {
1010
google: string;

__tests__/fake-serv.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@ import {
88
listen,
99
ServiceStartOptions,
1010
startApp,
11-
} from '../src/index';
11+
} from '../src/index.js';
1212

13-
import { type FakeServLocals, service } from './fake-serv/src/index';
13+
import { type FakeServLocals, service } from './fake-serv/src/index.js';
1414

1515
function httpRequest(options: http.RequestOptions) {
1616
return new Promise((resolve, reject) => {

__tests__/fake-serv/src/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import type { Service, ServiceLocals } from '../../../src/types';
2-
import { useService } from '../../../src';
1+
import type { Service, ServiceLocals } from '../../../src/types.js';
2+
import { useService } from '../../../src/index.js';
33

44
export interface FakeServLocals extends ServiceLocals {
55
services: {

package.json

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22
"name": "@openapi-typescript-infra/service",
33
"version": "4.10.2",
44
"description": "An opinionated framework for building configuration driven services - web, api, or ob. Uses OpenAPI, pino logging, express, confit, Typescript and vitest.",
5-
"main": "build/index.js",
5+
"exports": "./build/index.js",
6+
"type": "module",
67
"scripts": {
78
"test": "vitest",
89
"lint": "eslint .",
@@ -68,10 +69,10 @@
6869
"@opentelemetry/instrumentation-http": "^0.53.0",
6970
"@opentelemetry/instrumentation-ioredis": "^0.43.0",
7071
"@opentelemetry/instrumentation-net": "^0.39.0",
71-
"@opentelemetry/instrumentation-pg": "^0.45.1",
72+
"@opentelemetry/instrumentation-pg": "^0.46.0",
7273
"@opentelemetry/instrumentation-pino": "^0.42.0",
7374
"@opentelemetry/instrumentation-undici": "^0.6.0",
74-
"@opentelemetry/resource-detector-container": "^0.4.3",
75+
"@opentelemetry/resource-detector-container": "^0.4.4",
7576
"@opentelemetry/resource-detector-gcp": "^0.29.12",
7677
"@opentelemetry/sdk-node": "^0.53.0",
7778
"@opentelemetry/semantic-conventions": "^1.27.0",
@@ -82,11 +83,11 @@
8283
"dotenv": "^16.4.5",
8384
"express": "^5.0.1",
8485
"express-openapi-validator": "^5.3.7",
85-
"glob": "^8.1.0",
86+
"glob": "^11.0.0",
8687
"lodash": "^4.17.21",
8788
"minimist": "^1.2.8",
88-
"pino": "^9.4.0",
89-
"read-pkg-up": "^7.0.1",
89+
"pino": "^9.5.0",
90+
"read-package-up": "^11.0.0",
9091
"request-ip": "^3.3.0"
9192
},
9293
"devDependencies": {
@@ -99,25 +100,25 @@
99100
"@semantic-release/release-notes-generator": "^14.0.1",
100101
"@types/cookie-parser": "^1.4.7",
101102
"@types/express": "^5.0.0",
102-
"@types/glob": "^8.1.0",
103103
"@types/lodash": "^4.17.10",
104104
"@types/minimist": "^1.2.5",
105-
"@types/node": "^20.16.11",
105+
"@types/node": "^22.7.6",
106106
"@types/request-ip": "^0.0.41",
107107
"@types/supertest": "^6.0.2",
108-
"@typescript-eslint/eslint-plugin": "^6.21.0",
109-
"@typescript-eslint/parser": "^6.21.0",
108+
"@typescript-eslint/eslint-plugin": "^7.18.0",
109+
"@typescript-eslint/parser": "^7.18.0",
110110
"coconfig": "^1.5.2",
111111
"eslint": "^8.57.1",
112112
"eslint-config-prettier": "^9.1.0",
113+
"eslint-import-resolver-typescript": "^3.6.3",
113114
"eslint-plugin-import": "^2.31.0",
114-
"pino-pretty": "^11.2.2",
115+
"pino-pretty": "^11.3.0",
115116
"pinst": "^3.0.0",
116117
"supertest": "^7.0.0",
117118
"ts-node": "^10.9.2",
118119
"tsconfig-paths": "^4.2.0",
119120
"typescript": "^5.6.3",
120-
"vitest": "^2.1.2"
121+
"vitest": "^2.1.3"
121122
},
122123
"resolutions": {
123124
"qs": "^6.11.0"

src/bin/start-service.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
#!/usr/bin/env node
22
import minimist from 'minimist';
33

4-
import { serviceRepl } from '../development/repl';
5-
import { isDev } from '../env';
6-
import { bootstrap } from '../bootstrap';
4+
import { serviceRepl } from '../development/repl.js';
5+
import { isDev } from '../env.js';
6+
import { bootstrap } from '../bootstrap.js';
77

88
/**
99
* built - forces the use of the build directory. Defaults to true in stage/prod, not in dev

src/bootstrap.ts

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,21 @@
11
import path from 'node:path';
22
import assert from 'node:assert';
33

4-
import dotenv from 'dotenv';
5-
import readPackageUp from 'read-pkg-up';
6-
import type { NormalizedPackageJson } from 'read-pkg-up';
4+
import { config } from 'dotenv';
5+
import { readPackageUp } from 'read-package-up';
6+
import type { NormalizedPackageJson } from 'read-package-up';
77

8-
import type { AnyServiceLocals, RequestLocals, ServiceLocals, ServiceStartOptions } from './types';
9-
import { isDev } from './env';
10-
import { startWithTelemetry } from './telemetry/index';
11-
import { ConfigurationSchema } from './config/schema';
8+
import type { AnyServiceLocals, RequestLocals, ServiceLocals, ServiceStartOptions } from './types.js';
9+
import { isDev } from './env.js';
10+
import { startWithTelemetry } from './telemetry/index.js';
11+
import { ConfigurationSchema } from './config/schema.js';
1212

1313
interface BootstrapArguments {
14-
// The name of the service, else discovered via read-pkg-up
14+
// The name of the service, else discovered via read-package-up
1515
name?: string;
1616
// The name of the file with the service function, relative to root
1717
main?: string;
18-
// Root directory of the app, else discovered via read-pkg-up
18+
// Root directory of the app, else discovered via read-package-up
1919
root?: string;
2020
// Use built directory. Omitting lets us determine a sensible default
2121
built?: boolean;
@@ -25,7 +25,7 @@ interface BootstrapArguments {
2525
telemetry?: boolean;
2626
// Don't bind to http port or expose metrics
2727
nobind?: boolean;
28-
// The version of the app, else discovered via read-pkg-up
28+
// The version of the app, else discovered via read-package-up
2929
version?: string;
3030
}
3131

@@ -84,11 +84,6 @@ export async function bootstrap<
8484
// eslint-disable-next-line import/no-extraneous-dependencies
8585
const { register } = await import('ts-node');
8686
register();
87-
try {
88-
require('tsconfig-paths/register');
89-
} catch (error) {
90-
// No action needed
91-
}
9287
if (main) {
9388
entrypoint = main.replace(/^(\.?\/?)(build|dist)\//, '$1src/').replace(/\.js$/, '.ts');
9489
} else {
@@ -102,7 +97,7 @@ export async function bootstrap<
10297
entrypoint = './build/index.js';
10398
}
10499

105-
dotenv.config();
100+
config();
106101

107102
const absoluteEntrypoint = path.resolve(rootDirectory, entrypoint);
108103
if (argv?.telemetry) {
@@ -117,7 +112,7 @@ export async function bootstrap<
117112

118113
// This needs to be required for TS on-the-fly to work
119114
// eslint-disable-next-line global-require, import/no-dynamic-require, @typescript-eslint/no-var-requires
120-
const impl = require(absoluteEntrypoint);
115+
const impl = await import(absoluteEntrypoint);
121116
const opts: ServiceStartOptions<SLocals, RLocals> = {
122117
name,
123118
version,

src/config/index.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@ import {
99
confit,
1010
} from '@sesamecare-oss/confit';
1111

12-
import { getAvailablePort } from '../development/port-finder';
12+
import { getAvailablePort } from '../development/port-finder.js';
1313

14-
import type { ConfigurationSchema } from './schema';
14+
import type { ConfigurationSchema } from './schema.js';
1515

1616
// Order matters here.
1717
const ENVIRONMENTS = ['production', 'staging', 'test', 'development'] as const;
@@ -121,5 +121,5 @@ export function insertConfigurationBefore(
121121
return copy;
122122
}
123123

124-
export * from './schema';
125-
export * from './validation';
124+
export * from './schema.js';
125+
export * from './validation.js';

src/config/validation.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { ConfigurationSchema } from './schema';
1+
import { ConfigurationSchema } from './schema.js';
22

33
export interface ConfigValidationError {
44
path: string;

0 commit comments

Comments
 (0)