refactor: migrate to ES modules
package.json type=module, tsconfig module/moduleResolution=NodeNext, target es2022, explicit .js on all relative imports. Center: jsonwebtoken & bcryptjs switched to default imports (ESM/CJS interop). Verified: builds, boots, full auth + plugin round-trip work under ESM. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -2,6 +2,7 @@
|
|||||||
"name": "fabric-backend-center",
|
"name": "fabric-backend-center",
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
|
"type": "module",
|
||||||
"description": "Fabric Identity Hub (Center service)",
|
"description": "Fabric Identity Hub (Center service)",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "tsc -p tsconfig.build.json",
|
"build": "tsc -p tsconfig.build.json",
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
import { Module } from '@nestjs/common';
|
import { Module } from '@nestjs/common';
|
||||||
import { APP_GUARD } from '@nestjs/core';
|
import { APP_GUARD } from '@nestjs/core';
|
||||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||||
import { buildTypeOrmConfig } from './database.config';
|
import { buildTypeOrmConfig } from './database.config.js';
|
||||||
import { HealthController } from './common/health.controller';
|
import { HealthController } from './common/health.controller.js';
|
||||||
import { MetricsController } from './common/metrics.controller';
|
import { MetricsController } from './common/metrics.controller.js';
|
||||||
import { MetricsService } from './common/metrics.service';
|
import { MetricsService } from './common/metrics.service.js';
|
||||||
import { AuthModule } from './auth/auth.module';
|
import { AuthModule } from './auth/auth.module.js';
|
||||||
import { NodesModule } from './nodes/nodes.module';
|
import { NodesModule } from './nodes/nodes.module.js';
|
||||||
import { AuditModule } from './audit/audit.module';
|
import { AuditModule } from './audit/audit.module.js';
|
||||||
import { CenterApiKeyGuard } from './common/center-api-key.guard';
|
import { CenterApiKeyGuard } from './common/center-api-key.guard.js';
|
||||||
import { GuildNode } from './entities/guild-node.entity';
|
import { GuildNode } from './entities/guild-node.entity.js';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { Global, Module } from '@nestjs/common';
|
import { Global, Module } from '@nestjs/common';
|
||||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||||
import { AuditLog } from '../entities/audit-log.entity';
|
import { AuditLog } from '../entities/audit-log.entity.js';
|
||||||
import { AuditService } from './audit.service';
|
import { AuditService } from './audit.service.js';
|
||||||
|
|
||||||
@Global()
|
@Global()
|
||||||
@Module({
|
@Module({
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { Injectable } from '@nestjs/common';
|
import { Injectable } from '@nestjs/common';
|
||||||
import { InjectRepository } from '@nestjs/typeorm';
|
import { InjectRepository } from '@nestjs/typeorm';
|
||||||
import { Repository } from 'typeorm';
|
import { Repository } from 'typeorm';
|
||||||
import { AuditLog } from '../entities/audit-log.entity';
|
import { AuditLog } from '../entities/audit-log.entity.js';
|
||||||
|
|
||||||
export type AuditWriteInput = {
|
export type AuditWriteInput = {
|
||||||
action: string;
|
action: string;
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import { Body, Controller, Get, Headers, Param, Patch, Post, UnauthorizedException } from '@nestjs/common';
|
import { Body, Controller, Get, Headers, Param, Patch, Post, UnauthorizedException } from '@nestjs/common';
|
||||||
import { AuthService } from './auth.service';
|
import { AuthService } from './auth.service.js';
|
||||||
import { LoginDto } from './dto.login.dto';
|
import { LoginDto } from './dto.login.dto.js';
|
||||||
import { RefreshDto } from './dto.refresh.dto';
|
import { RefreshDto } from './dto.refresh.dto.js';
|
||||||
import { LogoutDto } from './dto.logout.dto';
|
import { LogoutDto } from './dto.logout.dto.js';
|
||||||
import { UpdateMeDto } from './dto.update-me.dto';
|
import { UpdateMeDto } from './dto.update-me.dto.js';
|
||||||
|
|
||||||
function bearer(authorization?: string): string {
|
function bearer(authorization?: string): string {
|
||||||
return authorization?.startsWith('Bearer ') ? authorization.slice(7) : '';
|
return authorization?.startsWith('Bearer ') ? authorization.slice(7) : '';
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import { Module } from '@nestjs/common';
|
import { Module } from '@nestjs/common';
|
||||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||||
import { AuthController } from './auth.controller';
|
import { AuthController } from './auth.controller.js';
|
||||||
import { AuthService } from './auth.service';
|
import { AuthService } from './auth.service.js';
|
||||||
import { User } from '../entities/user.entity';
|
import { User } from '../entities/user.entity.js';
|
||||||
import { GuildNode } from '../entities/guild-node.entity';
|
import { GuildNode } from '../entities/guild-node.entity.js';
|
||||||
import { GuildUser } from '../entities/guild-user.entity';
|
import { GuildUser } from '../entities/guild-user.entity.js';
|
||||||
import { UserApiKey } from '../entities/user-api-key.entity';
|
import { UserApiKey } from '../entities/user-api-key.entity.js';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [TypeOrmModule.forFeature([User, GuildNode, GuildUser, UserApiKey])],
|
imports: [TypeOrmModule.forFeature([User, GuildNode, GuildUser, UserApiKey])],
|
||||||
|
|||||||
@@ -5,17 +5,17 @@ import {
|
|||||||
} from '@nestjs/common';
|
} from '@nestjs/common';
|
||||||
import { InjectRepository } from '@nestjs/typeorm';
|
import { InjectRepository } from '@nestjs/typeorm';
|
||||||
import { Repository } from 'typeorm';
|
import { Repository } from 'typeorm';
|
||||||
import * as bcrypt from 'bcryptjs';
|
import bcrypt from 'bcryptjs';
|
||||||
import * as jwt from 'jsonwebtoken';
|
import jwt from 'jsonwebtoken';
|
||||||
import { randomBytes } from 'crypto';
|
import { randomBytes } from 'crypto';
|
||||||
import { User } from '../entities/user.entity';
|
import { User } from '../entities/user.entity.js';
|
||||||
import { GuildNode } from '../entities/guild-node.entity';
|
import { GuildNode } from '../entities/guild-node.entity.js';
|
||||||
import { GuildUser } from '../entities/guild-user.entity';
|
import { GuildUser } from '../entities/guild-user.entity.js';
|
||||||
import { UserApiKey } from '../entities/user-api-key.entity';
|
import { UserApiKey } from '../entities/user-api-key.entity.js';
|
||||||
import { RegisterDto } from './dto.register.dto';
|
import { RegisterDto } from './dto.register.dto.js';
|
||||||
import { LoginDto } from './dto.login.dto';
|
import { LoginDto } from './dto.login.dto.js';
|
||||||
import { AuditService } from '../audit/audit.service';
|
import { AuditService } from '../audit/audit.service.js';
|
||||||
import { parseDurationToSeconds } from './token.util';
|
import { parseDurationToSeconds } from './token.util.js';
|
||||||
|
|
||||||
function signAccessToken(userId: string, email: string): string {
|
function signAccessToken(userId: string, email: string): string {
|
||||||
const secret = process.env.FABRIC_BACKEND_CENTER_JWT_ACCESS_SECRET as string;
|
const secret = process.env.FABRIC_BACKEND_CENTER_JWT_ACCESS_SECRET as string;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { describe, expect, it } from 'vitest';
|
import { describe, expect, it } from 'vitest';
|
||||||
import { parseDurationToSeconds } from './token.util';
|
import { parseDurationToSeconds } from './token.util.js';
|
||||||
|
|
||||||
describe('parseDurationToSeconds', () => {
|
describe('parseDurationToSeconds', () => {
|
||||||
it('parses time units', () => {
|
it('parses time units', () => {
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import 'reflect-metadata';
|
import 'reflect-metadata';
|
||||||
import { NestFactory } from '@nestjs/core';
|
import { NestFactory } from '@nestjs/core';
|
||||||
import { AppModule } from './app.module';
|
import { AppModule } from './app.module.js';
|
||||||
import { AuthService } from './auth/auth.service';
|
import { AuthService } from './auth/auth.service.js';
|
||||||
import { NodeAdminService } from './nodes/node-admin.service';
|
import { NodeAdminService } from './nodes/node-admin.service.js';
|
||||||
|
|
||||||
function getArg(flag: string): string | null {
|
function getArg(flag: string): string | null {
|
||||||
const idx = process.argv.indexOf(flag);
|
const idx = process.argv.indexOf(flag);
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import { CanActivate, ExecutionContext, Injectable, UnauthorizedException } from '@nestjs/common';
|
import { CanActivate, ExecutionContext, Injectable, UnauthorizedException } from '@nestjs/common';
|
||||||
import { InjectRepository } from '@nestjs/typeorm';
|
import { InjectRepository } from '@nestjs/typeorm';
|
||||||
import { Repository } from 'typeorm';
|
import { Repository } from 'typeorm';
|
||||||
import * as bcrypt from 'bcryptjs';
|
import bcrypt from 'bcryptjs';
|
||||||
import { GuildNode } from '../entities/guild-node.entity';
|
import { GuildNode } from '../entities/guild-node.entity.js';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class CenterApiKeyGuard implements CanActivate {
|
export class CenterApiKeyGuard implements CanActivate {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { Controller, Get } from '@nestjs/common';
|
import { Controller, Get } from '@nestjs/common';
|
||||||
import { MetricsService } from './metrics.service';
|
import { MetricsService } from './metrics.service.js';
|
||||||
|
|
||||||
@Controller('metrics')
|
@Controller('metrics')
|
||||||
export class MetricsController {
|
export class MetricsController {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { randomUUID } from 'crypto';
|
import { randomUUID } from 'crypto';
|
||||||
import { NextFunction, Request, Response } from 'express';
|
import { NextFunction, Request, Response } from 'express';
|
||||||
import { MetricsService } from './metrics.service';
|
import { MetricsService } from './metrics.service.js';
|
||||||
|
|
||||||
type ReqWithId = Request & { requestId?: string };
|
type ReqWithId = Request & { requestId?: string };
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import 'reflect-metadata';
|
import 'reflect-metadata';
|
||||||
import { DataSource, DataSourceOptions } from 'typeorm';
|
import { DataSource, DataSourceOptions } from 'typeorm';
|
||||||
import { buildTypeOrmConfig } from './database.config';
|
import { buildTypeOrmConfig } from './database.config.js';
|
||||||
|
|
||||||
const cfg = buildTypeOrmConfig();
|
const cfg = buildTypeOrmConfig();
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import { TypeOrmModuleOptions } from '@nestjs/typeorm';
|
import { TypeOrmModuleOptions } from '@nestjs/typeorm';
|
||||||
import { User } from './entities/user.entity';
|
import { User } from './entities/user.entity.js';
|
||||||
import { GuildNode } from './entities/guild-node.entity';
|
import { GuildNode } from './entities/guild-node.entity.js';
|
||||||
import { AuditLog } from './entities/audit-log.entity';
|
import { AuditLog } from './entities/audit-log.entity.js';
|
||||||
import { GuildUser } from './entities/guild-user.entity';
|
import { GuildUser } from './entities/guild-user.entity.js';
|
||||||
import { UserApiKey } from './entities/user-api-key.entity';
|
import { UserApiKey } from './entities/user-api-key.entity.js';
|
||||||
|
|
||||||
export const buildTypeOrmConfig = (): TypeOrmModuleOptions => ({
|
export const buildTypeOrmConfig = (): TypeOrmModuleOptions => ({
|
||||||
type: 'mysql',
|
type: 'mysql',
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ describe('center integration (mysql + api)', () => {
|
|||||||
let app: INestApplication;
|
let app: INestApplication;
|
||||||
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
const { AppModule } = await import('./app.module');
|
const { AppModule } = await import('./app.module.js');
|
||||||
const moduleRef = await Test.createTestingModule({
|
const moduleRef = await Test.createTestingModule({
|
||||||
imports: [AppModule],
|
imports: [AppModule],
|
||||||
}).compile();
|
}).compile();
|
||||||
|
|||||||
@@ -2,9 +2,9 @@ import 'reflect-metadata';
|
|||||||
import { ValidationPipe } from '@nestjs/common';
|
import { ValidationPipe } from '@nestjs/common';
|
||||||
import { NestFactory } from '@nestjs/core';
|
import { NestFactory } from '@nestjs/core';
|
||||||
import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger';
|
import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger';
|
||||||
import { AppModule } from './app.module';
|
import { AppModule } from './app.module.js';
|
||||||
import { createRequestContextMiddleware } from './common/request-context.middleware';
|
import { createRequestContextMiddleware } from './common/request-context.middleware.js';
|
||||||
import { MetricsService } from './common/metrics.service';
|
import { MetricsService } from './common/metrics.service.js';
|
||||||
|
|
||||||
function requireEnv(name: string): string {
|
function requireEnv(name: string): string {
|
||||||
const value = process.env[name];
|
const value = process.env[name];
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import { ConflictException, Injectable } from '@nestjs/common';
|
import { ConflictException, Injectable } from '@nestjs/common';
|
||||||
import { InjectRepository } from '@nestjs/typeorm';
|
import { InjectRepository } from '@nestjs/typeorm';
|
||||||
import { Repository } from 'typeorm';
|
import { Repository } from 'typeorm';
|
||||||
import * as bcrypt from 'bcryptjs';
|
import bcrypt from 'bcryptjs';
|
||||||
import { randomBytes } from 'crypto';
|
import { randomBytes } from 'crypto';
|
||||||
import { GuildNode } from '../entities/guild-node.entity';
|
import { GuildNode } from '../entities/guild-node.entity.js';
|
||||||
import { AuditService } from '../audit/audit.service';
|
import { AuditService } from '../audit/audit.service.js';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class NodeAdminService {
|
export class NodeAdminService {
|
||||||
|
|||||||
@@ -12,9 +12,9 @@ import {
|
|||||||
} from '@nestjs/common';
|
} from '@nestjs/common';
|
||||||
import { InjectRepository } from '@nestjs/typeorm';
|
import { InjectRepository } from '@nestjs/typeorm';
|
||||||
import { Repository } from 'typeorm';
|
import { Repository } from 'typeorm';
|
||||||
import { GuildNode } from '../entities/guild-node.entity';
|
import { GuildNode } from '../entities/guild-node.entity.js';
|
||||||
import { AuditService } from '../audit/audit.service';
|
import { AuditService } from '../audit/audit.service.js';
|
||||||
import { UpdateNodeStatusDto } from './dto.update-node-status.dto';
|
import { UpdateNodeStatusDto } from './dto.update-node-status.dto.js';
|
||||||
|
|
||||||
@Controller('nodes')
|
@Controller('nodes')
|
||||||
export class NodesController {
|
export class NodesController {
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import { Module } from '@nestjs/common';
|
import { Module } from '@nestjs/common';
|
||||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||||
import { NodesController } from './nodes.controller';
|
import { NodesController } from './nodes.controller.js';
|
||||||
import { GuildNode } from '../entities/guild-node.entity';
|
import { GuildNode } from '../entities/guild-node.entity.js';
|
||||||
import { NodeAdminService } from './node-admin.service';
|
import { NodeAdminService } from './node-admin.service.js';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [TypeOrmModule.forFeature([GuildNode])],
|
imports: [TypeOrmModule.forFeature([GuildNode])],
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"module": "commonjs",
|
"module": "NodeNext",
|
||||||
"target": "es2020",
|
"moduleResolution": "NodeNext",
|
||||||
|
"target": "es2022",
|
||||||
"strict": true,
|
"strict": true,
|
||||||
"esModuleInterop": true,
|
"esModuleInterop": true,
|
||||||
"experimentalDecorators": true,
|
"experimentalDecorators": true,
|
||||||
|
|||||||
Reference in New Issue
Block a user