114 lines
3.2 KiB
TypeScript
114 lines
3.2 KiB
TypeScript
import {
|
|
convertNxGenerator,
|
|
formatFiles,
|
|
GeneratorCallback,
|
|
joinPathFragments,
|
|
runTasksInSerial,
|
|
Tree,
|
|
updateJson,
|
|
} from '@nx/devkit';
|
|
import { libraryGenerator as reactLibraryGenerator } from '@nx/react/src/generators/library/library';
|
|
import { addTsConfigPath } from '@nx/js';
|
|
|
|
import { nextInitGenerator } from '../init/init';
|
|
import { Schema } from './schema';
|
|
import { normalizeOptions } from './lib/normalize-options';
|
|
|
|
export async function libraryGenerator(host: Tree, rawOptions: Schema) {
|
|
const options = normalizeOptions(host, rawOptions);
|
|
const tasks: GeneratorCallback[] = [];
|
|
const initTask = await nextInitGenerator(host, {
|
|
...options,
|
|
skipFormat: true,
|
|
});
|
|
tasks.push(initTask);
|
|
|
|
const libTask = await reactLibraryGenerator(host, {
|
|
...options,
|
|
compiler: 'swc',
|
|
skipFormat: true,
|
|
});
|
|
tasks.push(libTask);
|
|
|
|
const indexPath = joinPathFragments(
|
|
options.projectRoot,
|
|
'src',
|
|
`index.${options.js ? 'js' : 'ts'}`
|
|
);
|
|
const indexContent = host.read(indexPath, 'utf-8');
|
|
host.write(
|
|
indexPath,
|
|
`// Use this file to export React client components (e.g. those with 'use client' directive) or other non-server utilities\n${indexContent}`
|
|
);
|
|
// Additional entry for Next.js libraries so React Server Components are exported from a separate entry point.
|
|
// This is needed because RSC exported from `src/index.ts` will mark the entire file as server-only and throw an error when used from a client component.
|
|
// See: https://github.com/nrwl/nx/issues/15830
|
|
const serverEntryPath = joinPathFragments(
|
|
options.projectRoot,
|
|
'./src',
|
|
'server.' + (options.js ? 'js' : 'ts')
|
|
);
|
|
host.write(
|
|
joinPathFragments(
|
|
options.projectRoot,
|
|
'src',
|
|
`server.${options.js ? 'js' : 'ts'}`
|
|
),
|
|
`// Use this file to export React server components
|
|
export * from './lib/hello-server';`
|
|
);
|
|
host.write(
|
|
joinPathFragments(
|
|
options.projectRoot,
|
|
'src/lib',
|
|
`hello-server.${options.js ? 'js' : 'tsx'}`
|
|
),
|
|
`// React server components are async so you make database or API calls.
|
|
export async function HelloServer() {
|
|
return <h1>Hello Server</h1>
|
|
}
|
|
`
|
|
);
|
|
addTsConfigPath(host, `${options.importPath}/server`, [serverEntryPath]);
|
|
|
|
updateJson(
|
|
host,
|
|
joinPathFragments(options.projectRoot, 'tsconfig.json'),
|
|
(json) => {
|
|
if (options.style === '@emotion/styled') {
|
|
json.compilerOptions.jsxImportSource = '@emotion/react';
|
|
}
|
|
return json;
|
|
}
|
|
);
|
|
|
|
updateJson(
|
|
host,
|
|
joinPathFragments(options.projectRoot, 'tsconfig.lib.json'),
|
|
(json) => {
|
|
if (!json.files) {
|
|
json.files = [];
|
|
}
|
|
json.files = json.files.map((path: string) => {
|
|
if (path.endsWith('react/typings/image.d.ts')) {
|
|
return path.replace(
|
|
'@nx/react/typings/image.d.ts',
|
|
'@nx/next/typings/image.d.ts'
|
|
);
|
|
}
|
|
return path;
|
|
});
|
|
return json;
|
|
}
|
|
);
|
|
|
|
if (!options.skipFormat) {
|
|
await formatFiles(host);
|
|
}
|
|
|
|
return runTasksInSerial(...tasks);
|
|
}
|
|
|
|
export default libraryGenerator;
|
|
export const librarySchematic = convertNxGenerator(libraryGenerator);
|