Some checks failed
CI / build-lint-test (pull_request) Failing after 29s
Registre de services en singleton avec injection par decorateurs :
- ServiceRepository : singleton central, uid genere automatiquement
(crypto.randomUUID) a l'enregistrement, une seule instance partagee
par service.
- @RegisterService() : decorateur de classe, instancie et enregistre
automatiquement la classe decoree (constructeur sans argument).
- @Service(target) : decorateur de propriete, injection paresseuse et
memoisee par reference de classe (resolution au premier acces, pas
a la decoration - insensible a l'ordre d'evaluation des modules).
Fix connexe dans tsconfig.base.json : useDefineForClassFields desactive
(target ES2022 l'active par defaut), sinon un champ de classe sans
initialiseur est reinitialise a undefined sur l'instance a la
construction et masque l'accesseur pose sur le prototype par un
decorateur de propriete - touche @Service ici et @LinkToDom dans
web-component. Documente dans spec/architecture.md.
Fix connexe dans scripts/create-package.mjs : execFileSync('pnpm', ...)
ne resout pas le shim .cmd de pnpm sous Windows sans shell: true
(trouve en re-testant le script sur ce package).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
155 lines
4.7 KiB
JavaScript
155 lines
4.7 KiB
JavaScript
#!/usr/bin/env node
|
|
import { execFileSync } from 'node:child_process';
|
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
import { dirname, join } from 'node:path';
|
|
import { fileURLToPath } from 'node:url';
|
|
|
|
const ROOT = dirname(dirname(fileURLToPath(import.meta.url)));
|
|
const CATEGORIES = ['client', 'common', 'server'];
|
|
|
|
/**
|
|
* Prints usage information and exits with an error status.
|
|
* @param {string} message the reason the script is aborting
|
|
*/
|
|
function fail(message) {
|
|
console.error(`Erreur : ${message}`);
|
|
console.error('Usage : pnpm create-package <client|common|server> <nom-du-package>');
|
|
process.exitCode = 1;
|
|
process.exit(1);
|
|
}
|
|
|
|
const [, , category, name] = process.argv;
|
|
|
|
if (!category || !CATEGORIES.includes(category)) {
|
|
fail(`catégorie invalide (attendu : ${CATEGORIES.join(', ')})`);
|
|
}
|
|
if (!name || !/^[a-z][a-z0-9-]*[a-z0-9]$/.test(name)) {
|
|
fail('nom de package invalide (attendu : kebab-case, ex. "my-widget")');
|
|
}
|
|
|
|
const packageDir = join(ROOT, 'packages', category, name);
|
|
if (existsSync(packageDir)) {
|
|
fail(`packages/${category}/${name} existe déjà`);
|
|
}
|
|
|
|
const npmName = `@lightweight-sdk/${name}`;
|
|
const isClient = category === 'client';
|
|
|
|
mkdirSync(join(packageDir, 'src'), { recursive: true });
|
|
|
|
const packageJson = {
|
|
name: npmName,
|
|
version: '0.0.1',
|
|
description: `TODO: décrire le package ${name}.`,
|
|
main: 'dist/index.js',
|
|
types: 'dist/index.d.ts',
|
|
files: ['dist'],
|
|
engines: { node: '>=22' },
|
|
publishConfig: {
|
|
access: 'restricted',
|
|
registry: 'https://git.dev.kyuno.fr/api/packages/kyuno/npm/',
|
|
},
|
|
typedocOptions: {
|
|
entryPoints: ['src/index.ts'],
|
|
readme: 'README.md',
|
|
},
|
|
};
|
|
writeFileSync(join(packageDir, 'package.json'), `${JSON.stringify(packageJson, null, '\t')}\n`);
|
|
|
|
const tsconfig = {
|
|
extends: '../../../tsconfig.base.json',
|
|
compilerOptions: isClient
|
|
? { lib: ['ES2022', 'DOM', 'DOM.Iterable'], outDir: './dist', rootDir: './src' }
|
|
: { outDir: './dist', rootDir: './src' },
|
|
include: ['src/**/*'],
|
|
};
|
|
writeFileSync(join(packageDir, 'tsconfig.json'), `${JSON.stringify(tsconfig, null, '\t')}\n`);
|
|
|
|
const indexTs = `/**
|
|
* Placeholder function for the ${npmName} package — replace with real exports.
|
|
* @param subject the name to greet
|
|
* @returns a greeting for the given subject
|
|
*/
|
|
export function greet(subject: string): string {
|
|
return \`Hello, \${subject}!\`;
|
|
}
|
|
`;
|
|
writeFileSync(join(packageDir, 'src', 'index.ts'), indexTs);
|
|
|
|
const indexTest = `import { describe, expect, it } from 'vitest';
|
|
import { greet } from './index';
|
|
|
|
describe('greet', () => {
|
|
it('greets the given subject', () => {
|
|
expect(greet('world')).toBe('Hello, world!');
|
|
});
|
|
});
|
|
`;
|
|
writeFileSync(join(packageDir, 'src', 'index.test.ts'), indexTest);
|
|
|
|
const commonNote =
|
|
category === 'common'
|
|
? "\n> `common/` doit rester isomorphe : pas d'API exclusivement DOM ou exclusivement Node.\n"
|
|
: '';
|
|
const readme = `# ${npmName}
|
|
${commonNote}
|
|
TODO: décrire le package.
|
|
|
|
## Installation
|
|
|
|
\`\`\`bash
|
|
pnpm add ${npmName}
|
|
\`\`\`
|
|
|
|
## Usage
|
|
|
|
TODO
|
|
`;
|
|
writeFileSync(join(packageDir, 'README.md'), readme);
|
|
|
|
// Édite le tsconfig.json racine (project references)
|
|
const rootTsconfigPath = join(ROOT, 'tsconfig.json');
|
|
const rootTsconfig = JSON.parse(readFileSync(rootTsconfigPath, 'utf8'));
|
|
rootTsconfig.references ??= [];
|
|
rootTsconfig.references.push({ path: `./packages/${category}/${name}` });
|
|
writeFileSync(rootTsconfigPath, `${JSON.stringify(rootTsconfig, null, '\t')}\n`);
|
|
|
|
// Ajoute une ligne au registre des packages
|
|
const packagesSpecPath = join(ROOT, 'spec', 'packages.md');
|
|
const packagesSpec = readFileSync(packagesSpecPath, 'utf8');
|
|
const newRow = `| \`${npmName}\` | ${category} | 0.0.1 | brouillon |\n`;
|
|
writeFileSync(packagesSpecPath, packagesSpec.trimEnd() + '\n' + newRow);
|
|
|
|
console.log(`Package ${npmName} créé dans packages/${category}/${name}/.`);
|
|
|
|
try {
|
|
// shell: true est nécessaire sous Windows, où `pnpm` est un shim .cmd/.ps1
|
|
// que execFileSync ne résout pas via PATHEXT sans passer par un shell.
|
|
execFileSync('pnpm', ['install'], { cwd: ROOT, stdio: 'inherit', shell: true });
|
|
execFileSync(
|
|
'pnpm',
|
|
[
|
|
'exec',
|
|
'biome',
|
|
'check',
|
|
'--write',
|
|
`packages/${category}/${name}`,
|
|
'tsconfig.json',
|
|
'spec/packages.md',
|
|
],
|
|
{ cwd: ROOT, stdio: 'inherit', shell: true },
|
|
);
|
|
} catch (error) {
|
|
console.error('Étape automatique échouée, à relancer toi-même :');
|
|
console.error(' pnpm install');
|
|
console.error(
|
|
` pnpm exec biome check --write packages/${category}/${name} tsconfig.json spec/packages.md`,
|
|
);
|
|
console.error(String(error));
|
|
}
|
|
|
|
console.log('\nProchaines étapes :');
|
|
console.log(` cd packages/${category}/${name}`);
|
|
console.log(' - compléter la description dans package.json et README.md');
|
|
console.log(` - pnpm --filter ${npmName} test`);
|
|
console.log(' - pnpm changeset (une fois prêt à publier)');
|