Skip to content

FSHSP-121 Sources copiées autonomes, arborescence à plat, installation en une commande - #43

Open
LBU4SH wants to merge 7 commits into
mainfrom
feat/fshsp-121-schematics-local-sources
Open

FSHSP-121 Sources copiées autonomes, arborescence à plat, installation en une commande#43
LBU4SH wants to merge 7 commits into
mainfrom
feat/fshsp-121-schematics-local-sources

Conversation

@LBU4SH

@LBU4SH LBU4SH commented Aug 17, 2026

Copy link
Copy Markdown
Collaborator

Trois tickets liés, inséparables techniquement : la réécriture des imports a besoin des chemins cibles définitifs, et l'arborescence a besoin de la porte d'entrée finale.

Ticket Objet
FSHSP-119 Bug — les sources copiées importaient depuis node_modules
FSHSP-121 Arborescence aplatie, non-composants sortis de components/
FSHSP-122 Installation en une commande, sans installer le kit

Le bug d'origine

Un composant copié résolvait ses dépendances dans node_modules/@4sh/ui-kit, c'est-à-dire le code compilé. Modifier le ui-icon copié n'avait donc aucun effet sur les composants qui l'utilisent : le modèle « les sources t'appartiennent », seule raison d'être du starter, était annulé. 139 imports concernés.

Trois effets de bord partaient avec : les dépendances copiées n'étaient utilisées par personne (copies mortes, suivies par update pour rien), le bundle embarquait chaque composant deux fois, et du code applicatif dépendait d'une devDependency — cassant en npm ci --omit=dev.

Ce que ça donne

ng add @4sh/ui-kit-schematics

Une commande : fondation, puis sélection interactive des composants, puis npm install.

src/app/shared/
├── components/ui/{catégorie}/{ui-nom}/{ui-nom}.ts   ← uniquement des composants
└── ui-core/{forms|motion|overlay|theming|types}/    ← directives de base, services, utilitaires, types

Les src/lib/ et les barrels public-api.ts disparaissent : ce sont des artefacts de publication ng-packagr, sans objet une fois le fichier chez le consommateur.

@4sh/ui-kit n'entre jamais dans node_modules sur ce parcours — c'est ce qui empêche l'auto-complétion de l'IDE de proposer son code compilé à la place des copies locales. Le mode librairie (npm i @4sh/ui-kit) est inchangé ; chaque README documente son mode et pointe vers l'autre.

Ruptures pour un projet déjà en 0.2.0

  • Les chemins des fichiers copiés changent tous : update ne reconnaîtra pas les anciens. Déplacer les fichiers, ou repartir d'un add propre.
  • npm rm @4sh/ui-kit : les sources copiées n'en dépendent plus.

Le bump en 0.3.0 n'est pas dans cette PR — les entrées sont sous ## [Unreleased], conformément à docs/VERSIONING.md.

Vérifications

Sonde sur les 58 unités, 196 fichiers rendus : 0 import @4sh/ui-kit résiduel, 0 barrel, 0 chemin src/lib/.

Parcours complet sur un projet Angular 22 neuf, ng build lancé sans npm install intercalé :

  • @angular/cdk, fontawesome et style-dictionary installés par le schematic
  • @4sh/ui-kit absent de package.json et de node_modules
  • build vert ; le bundle passe de 216 à 247 kB dès qu'on utilise deux composants copiés, donc templates et SCSS compilent bien depuis les sources locales
  • --skip-install fait l'inverse, vérifié
  • update répond « Rien à mettre à jour » sur un projet à jour

L'import groupé dont les symboles sont dispersés est scindé :

import { UiIcon } from '../../base/ui-icon/ui-icon';
import { UiIconType } from '../../base/ui-icon/ui-icon-families';

Revue

Une passe de revue a trouvé cinq problèmes, tous corrigés dans les deux derniers commits. Le sérieux : en vidant la façade du kit, j'avais supprimé le seul NodePackageInstallTask du dépôt, laissant ng add produire un projet qui ne compilait pas (Could not resolve sur les CSS de CDK et FontAwesome). Ma vérification initiale le masquait en lançant npm install entre le schematic et le build.

Les quatre autres : skipInstall déclaré mais ignoré ; endsWith('public-api.ts') qui écartait silencieusement un *-public-api.ts légitime ; une collision d'aplatissement qui écrasait sans un mot ; et du code mort.

🤖 Generated with Claude Code

LBU4SH added 7 commits August 17, 2026 16:35
…ed units out of components

`src/` and `lib/` delimit a library's published surface: copied into a consumer
app they enclose nothing and buried every component two levels deep. Both go,
along with the `public-api.ts` barrel — a publication surface with no purpose
once the file belongs to the consumer.

Shared bases landed in `components/ui/{category}/_shared/`, which filed services
(`theme.service`) and utilities (`mask-engine`) under `components/`. They move to
`src/app/shared/ui-core/{category}/`, keeping their per-domain grouping.
Component-local files stay next to their component: they serve it alone.

`resolveSpecifier` moves to the registry — the dependency graph and the upcoming
import rewrite must agree on that mapping, so it gets one home.
A copied component resolved its dependencies from node_modules/@4sh/ui-kit —
the compiled code. Editing the copied ui-icon had no effect on the components
using it, which cancels the whole point of copying sources. The 139
`@4sh/ui-kit/*` specifiers are now readdressed to the sibling copies.

Resolving through a barrel means finding the file that actually carries the
symbol, so an import is SPLIT when its symbols are scattered
(`{ UiIcon, UiIconType }` -> ui-icon.ts + ui-icon-families.ts). A symbol absent
from the table aborts the copy naming it, rather than emitting a wrong path;
same for a non-trivial barrel or an unhandled import form.

Also fixes: dead copies nobody imported (yet tracked by `update`), the component
shipping twice in the bundle, and application code depending on a devDependency,
which broke under `npm ci --omit=dev`.
…g the kit

Two commands were needed (`ng add @4sh/ui-kit` for the foundation, then
`ng generate @4sh/ui-kit:add` for the components), and the kit stayed in
node_modules, where the IDE offered its imports instead of the local copies.
Both problems had one cause: the entry point. At `ng add` time the companion was
not yet installed, hence a deferred RunSchematicTask, in which an interactive
prompt does not hold.

Entering through the companion, `ng add @4sh/ui-kit-schematics` chains the
foundation and the component selection, and the kit is never installed at all —
nothing left to auto-import. The copied version is read from the companion's own
`assets/ui-kit-package.json` rather than the consumer's package.json, so
`installedKitVersion` goes away. `--skip-components` lays the foundation alone.

Library mode is untouched: `npm i @4sh/ui-kit` and import from the package. The
kit's facade shrinks to a single ng-add that states which of the two paths was
taken — the alternative, silently installing a package with no source copied,
is the worst outcome for someone reaching for the obvious command. Its ng-add
now saves to dependencies: devDependencies only made sense while it drove the CLI.
The companion's READMEs told the reader never to install it directly — it is now
the entry point, so both were wrong on their central claim. They document the two
consumption modes instead, and why the kit is absent from the starter one.

PUBLISHING and VERSIONING carried a lockstep rationale that no longer holds: the
kit's facade used to require the companion as `^<kit version>`. Nothing references
anything at install time now. The shared number still matters, for a different
reason — it identifies which kit a copied file came from, via the traceability
header and ui-kit.json — and the publish order's justification is rewritten to
match: a partial release no longer breaks consumers, it only misleads them.

The local-testing recipe drops the kit tarball, which the starter path no longer
installs, and gains the two checks worth running afterwards.
…clares

`ng add @4sh/ui-kit-schematics` wrote @angular/cdk and fontawesome into
dependencies and pointed angular.json at their CSS, then installed neither: the
build failed on two `Could not resolve` errors with nothing naming the cause.
`main` scheduled a NodePackageInstallTask in the kit's facade; emptying that
facade removed the only one in the repo, and the companion's ng-add never had it.
`ng add` installs the package you name, not what its schematic adds afterwards.

`--skip-install` now gates that task, instead of being declared and ignored.

Two silent-loss paths in copy, in a module that throws everywhere else:
`endsWith('public-api.ts')` also matched a legitimate `*-public-api.ts` component
file and dropped it; and flattening can map two sources onto one target, where
the second overwrote the first without a word — it now throws, naming both.

Drops `clearExportMapCache`, exported for tests that do not exist.
… the other

The companion's README documented library mode inline — install command and
import sample — which `@4sh/ui-kit` already covers on its own npm page. It now
points there in two lines instead of restating it.

The reverse pointer was missing entirely, and mattered more: the kit's README
only ever described library mode, so now that the starter path enters through the
companion, a reader of the kit's npm page had no way to discover that copying the
sources is an option at all. It gets a short section naming the command and why
the kit is absent from that path.

Also lists `--skip-install`, now that it does something.
UiLink sat in the component's imports without ever appearing in the
template: in drag mode the link is a styled <span> inside the <label>,
since a real interactive element has no place there. Building a project
on copied sources reported NG8113, and ui-file-upload dragged ui-link
into the copy for nothing.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant