Next.js Discord

Discord Forum

NextJS Scripts

Answered
deathlybower959 posted this in #help-forum
Open in Discord
Avatar
trying to run a script in next webpack, to "register" my app modules
am i doing something wrong?

// next.config.mjs
import path from 'path';
import { spawnSync } from 'child_process';

const registerModulesScript = path.join(
  process.cwd(),
  'src/scripts',
  'registerModules.ts'
);

/** @type {import('next').NextConfig} */
const config = {
  webpack: config => {
    spawnSync('ts-node', [registerModulesScript]);

    return config;
  },
};

export default config;


// src/scripts/registerModules.ts
import fs from 'fs';
import path from 'path';

import { registerModule } from '../lib/modules';

const modulesDirectory = path.join(process.cwd(), 'src/app/apps/(modules)');

fs.readdirSync(modulesDirectory).forEach(moduleName => {
  registerModule(moduleName);
});


// src/lib/modules.ts
import path from 'path';

type ITag = 'document' | 'converter' | 'fun' | 'miscellaneous';
export interface IModuleMetadata {
  name: string;
  description: string;
  tags: ITag[];
}

export interface IModule {
  route_name: string;
  metadata: IModuleMetadata;
}

const moduleRegistry: IModule[] = [];

// Function to register modules
export const registerModule = (moduleName: string) => {
  const metadataPath = path.join(
    process.cwd(),
    'src/app/apps/(modules)',
    moduleName,
    'metadata.ts'
  ); // Change file extension to .ts
  const metadata: IModuleMetadata =
    // eslint-disable-next-line @typescript-eslint/no-var-requires
    (require(metadataPath) as { default: IModuleMetadata }).default;

  moduleRegistry.push({
    route_name: moduleName,
    metadata,
  });
};

// Function to get all registered modules
export const getAllModules = () => moduleRegistry;
Answered by deathlybower959
// next.config.mjs
/** @type {import('next').NextConfig} */
const config = {};

export default config;


// src/lib/registerModules.ts
import fs from 'fs';
import path from 'path';

import { registerModules } from './modules';

const modulesDirectory = path.join(process.cwd(), 'src/app/apps/(modules)');

const modules = fs
  .readdirSync(modulesDirectory)
  .filter(entry => fs.statSync(modulesDirectory + '/' + entry).isDirectory());

await registerModules(modules);


// src/lib/modules.ts
type ITag = 'document' | 'converter' | 'fun' | 'miscellaneous';
export interface IModuleMetadata {
  name: string;
  description: string;
  tags: ITag[];
}

export interface IModule {
  route_name: string;
  metadata: IModuleMetadata;
}

let moduleRegistry: IModule[] = [];

// Function to register modules
export const registerModule = async (moduleName: string) => {
  const metadata: IModuleMetadata = (
    (await import(`~/app/apps/(modules)/${moduleName}/metadata.ts`)) as {
      default: IModuleMetadata;
    }
  ).default;
  moduleRegistry.push({
    route_name: moduleName,
    metadata,
  });
};
export const registerModules = async (modules: string[]) => {
  moduleRegistry = [];
  for (const m of modules) {
    await registerModule(m);
  }
};

// Function to get all registered modules
export const getAllModules = () => moduleRegistry;


// src/app/layout.tsx

import '~/lib/registerModules';

// ...

export default function RootLayout() {
  // ...
}
View full answer

2 Replies

Avatar
nvm, i decided to convert it to async using import, run the script in the root layout, and ignore the whole script thing
Avatar
// next.config.mjs
/** @type {import('next').NextConfig} */
const config = {};

export default config;


// src/lib/registerModules.ts
import fs from 'fs';
import path from 'path';

import { registerModules } from './modules';

const modulesDirectory = path.join(process.cwd(), 'src/app/apps/(modules)');

const modules = fs
  .readdirSync(modulesDirectory)
  .filter(entry => fs.statSync(modulesDirectory + '/' + entry).isDirectory());

await registerModules(modules);


// src/lib/modules.ts
type ITag = 'document' | 'converter' | 'fun' | 'miscellaneous';
export interface IModuleMetadata {
  name: string;
  description: string;
  tags: ITag[];
}

export interface IModule {
  route_name: string;
  metadata: IModuleMetadata;
}

let moduleRegistry: IModule[] = [];

// Function to register modules
export const registerModule = async (moduleName: string) => {
  const metadata: IModuleMetadata = (
    (await import(`~/app/apps/(modules)/${moduleName}/metadata.ts`)) as {
      default: IModuleMetadata;
    }
  ).default;
  moduleRegistry.push({
    route_name: moduleName,
    metadata,
  });
};
export const registerModules = async (modules: string[]) => {
  moduleRegistry = [];
  for (const m of modules) {
    await registerModule(m);
  }
};

// Function to get all registered modules
export const getAllModules = () => moduleRegistry;


// src/app/layout.tsx

import '~/lib/registerModules';

// ...

export default function RootLayout() {
  // ...
}
Answer