Merge pull request 'Bootstrap monorepo pnpm + migration de web-component' (#1) from feat/monorepo-bootstrap into main
Some checks failed
Release / release (push) Failing after 35s
Some checks failed
Release / release (push) Failing after 35s
This commit is contained in:
commit
cb8fbb4b3b
32 changed files with 3120 additions and 1 deletions
8
.changeset/README.md
Normal file
8
.changeset/README.md
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
# Changesets
|
||||
|
||||
Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works
|
||||
with multi-package repos, or single-package repos to help you version and publish your code. You can
|
||||
find the full documentation for it [in our repository](https://github.com/changesets/changesets).
|
||||
|
||||
We have a quick list of common questions to get you started engaging with this project in
|
||||
[our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md).
|
||||
11
.changeset/config.json
Normal file
11
.changeset/config.json
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"$schema": "https://unpkg.com/@changesets/config@3.1.4/schema.json",
|
||||
"changelog": "@changesets/cli/changelog",
|
||||
"commit": false,
|
||||
"fixed": [],
|
||||
"linked": [],
|
||||
"access": "restricted",
|
||||
"baseBranch": "main",
|
||||
"updateInternalDependencies": "patch",
|
||||
"ignore": []
|
||||
}
|
||||
5
.changeset/migrate-web-component-to-monorepo.md
Normal file
5
.changeset/migrate-web-component-to-monorepo.md
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
"@lightweight-sdk/web-component": patch
|
||||
---
|
||||
|
||||
Migration de `web-component` dans le monorepo lightweight-sdk. Aucun changement de comportement : le code source est repris tel quel depuis l'ancien repo `lightweight-sdk-web-component`, seuls l'outillage (Biome, Changesets, publication sur le registre npm privé) et l'organisation du dépôt changent.
|
||||
18
.editorconfig
Normal file
18
.editorconfig
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
root = true
|
||||
|
||||
[*]
|
||||
indent_style = tab
|
||||
indent_size = 2
|
||||
end_of_line = lf
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
|
||||
[*.{yml,yaml}]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
|
||||
[*.md]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
trim_trailing_whitespace = false
|
||||
51
.forgejo/workflows/ci.yml
Normal file
51
.forgejo/workflows/ci.yml
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
name: CI
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
build-lint-test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: "24"
|
||||
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4
|
||||
with:
|
||||
run_install: false
|
||||
|
||||
- name: Get pnpm store directory
|
||||
id: pnpm-cache
|
||||
shell: bash
|
||||
run: echo "STORE_PATH=$(pnpm store path --silent)" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Cache pnpm store
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ${{ steps.pnpm-cache.outputs.STORE_PATH }}
|
||||
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-pnpm-store-
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install --frozen-lockfile
|
||||
|
||||
- name: Lint (Biome)
|
||||
run: pnpm lint
|
||||
|
||||
- name: Build (tsc -b)
|
||||
run: pnpm build
|
||||
|
||||
- name: Test (Vitest)
|
||||
run: pnpm test
|
||||
|
||||
- name: Docs check (TypeDoc validation)
|
||||
run: pnpm docs:check
|
||||
51
.forgejo/workflows/release.yml
Normal file
51
.forgejo/workflows/release.yml
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
# Publie les packages modifiés sur le registre npm privé Forgejo
|
||||
# (https://git.dev.kyuno.fr/api/packages/kyuno/npm/) via Changesets.
|
||||
#
|
||||
# - déclenché sur push vers `main` (typiquement après le merge d'une PR
|
||||
# "Version Packages" générée par `pnpm changeset version`)
|
||||
# - `changeset publish` est idempotent par package : republie uniquement
|
||||
# les packages dont la version locale n'existe pas encore sur le registre
|
||||
# - prérequis côté instance : secret de repo REGISTRY_TOKEN, un jeton
|
||||
# Forgejo avec les scopes write:package + read:package (Settings ->
|
||||
# Applications) - le jeton automatique des Actions n'a pas ce droit
|
||||
# sur cette instance (voir spec/ci-cd.md)
|
||||
|
||||
name: Release
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
release:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: "24"
|
||||
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4
|
||||
with:
|
||||
run_install: false
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install --frozen-lockfile
|
||||
|
||||
- name: Build
|
||||
run: pnpm build
|
||||
|
||||
- name: Configure registry authentication
|
||||
run: echo "//git.dev.kyuno.fr/api/packages/kyuno/npm/:_authToken=${REGISTRY_TOKEN}" >> .npmrc
|
||||
env:
|
||||
REGISTRY_TOKEN: ${{ secrets.REGISTRY_TOKEN }}
|
||||
|
||||
- name: Publish changed packages
|
||||
run: pnpm changeset:publish
|
||||
env:
|
||||
REGISTRY_TOKEN: ${{ secrets.REGISTRY_TOKEN }}
|
||||
1
.gitattributes
vendored
Normal file
1
.gitattributes
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
* text=auto eol=lf
|
||||
15
.gitignore
vendored
Normal file
15
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
node_modules/
|
||||
dist/
|
||||
*.tsbuildinfo
|
||||
docs/api/
|
||||
coverage/
|
||||
*.log
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
.vscode/
|
||||
.env
|
||||
.env.*.local
|
||||
|
||||
# Claude Code (règle CLAUDE.md : ne jamais commit ceci)
|
||||
.claude/
|
||||
CLAUDE.md
|
||||
1
.npmrc
Normal file
1
.npmrc
Normal file
|
|
@ -0,0 +1 @@
|
|||
@lightweight-sdk:registry=https://git.dev.kyuno.fr/api/packages/kyuno/npm/
|
||||
35
README.md
35
README.md
|
|
@ -1,3 +1,36 @@
|
|||
# lightweight-sdk
|
||||
|
||||
Bibliothèque personnelle de packages TypeScript (monorepo pnpm), publiée sur le registre npm privé Forgejo.
|
||||
Bibliothèque personnelle de packages TypeScript, organisée en monorepo pnpm et publiée sur le registre npm privé hébergé sur [git.dev.kyuno.fr](https://git.dev.kyuno.fr/kyuno).
|
||||
|
||||
## Structure
|
||||
|
||||
Les packages sont répartis en trois catégories sous `packages/` :
|
||||
|
||||
- `client/` — packages destinés au navigateur (DOM, composants UI).
|
||||
- `common/` — code isomorphe partagé entre client et server.
|
||||
- `server/` — packages Node/backend, structurés en services modulaires autonomes.
|
||||
|
||||
Voir [`spec/architecture.md`](./spec/architecture.md) pour le détail des choix d'outillage, et [`spec/packages.md`](./spec/packages.md) pour la liste des packages existants.
|
||||
|
||||
## Démarrage
|
||||
|
||||
```bash
|
||||
pnpm install
|
||||
pnpm build
|
||||
pnpm lint
|
||||
pnpm test
|
||||
pnpm docs:check
|
||||
```
|
||||
|
||||
## Créer un nouveau package
|
||||
|
||||
```bash
|
||||
pnpm create-package <client|common|server> <nom-du-package>
|
||||
```
|
||||
|
||||
## Documentation
|
||||
|
||||
- [`spec/architecture.md`](./spec/architecture.md) — vue d'ensemble et choix techniques.
|
||||
- [`spec/conventions.md`](./spec/conventions.md) — conventions de code et traçabilité avec les directives du projet.
|
||||
- [`spec/ci-cd.md`](./spec/ci-cd.md) — CI, versioning (Changesets) et publication sur le registre.
|
||||
- [`spec/packages.md`](./spec/packages.md) — registre des packages du monorepo.
|
||||
|
|
|
|||
62
biome.json
Normal file
62
biome.json
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
{
|
||||
"$schema": "https://biomejs.dev/schemas/2.5.14/schema.json",
|
||||
"vcs": {
|
||||
"enabled": true,
|
||||
"clientKind": "git",
|
||||
"useIgnoreFile": true
|
||||
},
|
||||
"files": {
|
||||
"ignoreUnknown": false
|
||||
},
|
||||
"formatter": {
|
||||
"enabled": true,
|
||||
"indentStyle": "tab",
|
||||
"indentWidth": 2,
|
||||
"lineWidth": 100
|
||||
},
|
||||
"linter": {
|
||||
"enabled": true,
|
||||
"rules": {
|
||||
"preset": "recommended",
|
||||
"style": {
|
||||
"useConsistentMemberAccessibility": {
|
||||
"level": "error",
|
||||
"options": { "accessibility": "explicit" }
|
||||
}
|
||||
},
|
||||
"nursery": {
|
||||
"noFloatingPromises": "error",
|
||||
"noMisusedPromises": "error",
|
||||
"useAwaitThenable": "error"
|
||||
}
|
||||
}
|
||||
},
|
||||
"javascript": {
|
||||
"formatter": {
|
||||
"quoteStyle": "single",
|
||||
"semicolons": "always",
|
||||
"trailingCommas": "all"
|
||||
}
|
||||
},
|
||||
"assist": {
|
||||
"enabled": true,
|
||||
"actions": {
|
||||
"source": {
|
||||
"organizeImports": "on"
|
||||
}
|
||||
}
|
||||
},
|
||||
"overrides": [
|
||||
{
|
||||
"includes": ["packages/client/web-component/src/**"],
|
||||
"formatter": { "enabled": false },
|
||||
"linter": {
|
||||
"rules": {
|
||||
"suspicious": {
|
||||
"noShadowRestrictedNames": "off"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
34
package.json
Normal file
34
package.json
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
{
|
||||
"name": "lightweight-sdk",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"packageManager": "pnpm@12.4.2",
|
||||
"engines": {
|
||||
"node": ">=22"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "tsc -b",
|
||||
"build:clean": "tsc -b --clean",
|
||||
"dev": "tsc -b --watch",
|
||||
"lint": "biome check .",
|
||||
"lint:fix": "biome check --write .",
|
||||
"format": "biome format --write .",
|
||||
"test": "vitest run",
|
||||
"test:watch": "vitest",
|
||||
"docs:check": "typedoc --options typedoc.json --emit none --treatWarningsAsErrors --disableGit",
|
||||
"docs:build": "typedoc --options typedoc.json",
|
||||
"changeset": "changeset",
|
||||
"changeset:version": "changeset version",
|
||||
"changeset:publish": "changeset publish",
|
||||
"create-package": "node ./scripts/create-package.mjs",
|
||||
"ci": "pnpm lint && pnpm build && pnpm test && pnpm docs:check"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@biomejs/biome": "catalog:",
|
||||
"@changesets/cli": "catalog:",
|
||||
"@types/node": "catalog:",
|
||||
"typedoc": "catalog:",
|
||||
"typescript": "catalog:",
|
||||
"vitest": "catalog:"
|
||||
}
|
||||
}
|
||||
48
packages/client/web-component/README.md
Normal file
48
packages/client/web-component/README.md
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
# lightweight-sdk-web-component
|
||||
|
||||
A lightweight library to build web components easily.
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
pnpm add @lightweight-sdk/web-component
|
||||
```
|
||||
|
||||
## Prérequis côté consommateur
|
||||
|
||||
`@LinkToDom` et `@CustomComponent` sont des décorateurs TypeScript "legacy" (signature `(target, key)` / `(constructor)`). Pour les utiliser, ton propre `tsconfig.json` doit activer :
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"compilerOptions": {
|
||||
"experimentalDecorators": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```ts
|
||||
import { AbstractComponent, CustomComponent, LinkToDom } from "@lightweight-sdk/web-component";
|
||||
|
||||
@CustomComponent({
|
||||
tagName: "my-widget",
|
||||
template: "<span ref=\"label\"></span>",
|
||||
})
|
||||
class MyWidget extends AbstractComponent {
|
||||
@LinkToDom("label")
|
||||
private label!: HTMLElement;
|
||||
|
||||
public override init(): void {
|
||||
this.label.textContent = "Hello";
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
- `AbstractComponent` — classe de base à étendre pour déclarer un web component (cycle de vie `init`/`refresh`).
|
||||
- `CustomComponent(params)` — décorateur de classe qui enregistre le custom element et branche le template/Shadow DOM.
|
||||
- `LinkToDom(ref)` — décorateur de propriété qui lie un membre de la classe à l'élément DOM portant l'attribut `ref="..."` correspondant.
|
||||
- `findRefElement(ref, parent?)` — retrouve un élément par son attribut `ref` dans un conteneur donné (`document.body` par défaut).
|
||||
- `ComponentParams`, `LinkedProperty`, `AcceptedHTMLContent` — types associés.
|
||||
28
packages/client/web-component/package.json
Normal file
28
packages/client/web-component/package.json
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
{
|
||||
"name": "@lightweight-sdk/web-component",
|
||||
"version": "0.0.2",
|
||||
"description": "A lightweight library to build web components easily",
|
||||
"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",
|
||||
"validation": {
|
||||
"notExported": false,
|
||||
"invalidLink": false,
|
||||
"notDocumented": false
|
||||
}
|
||||
}
|
||||
}
|
||||
30
packages/client/web-component/src/abstractComponent.ts
Normal file
30
packages/client/web-component/src/abstractComponent.ts
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
import { ComponentParams, CUSTOM_COMPONENT_CONFIG, LinkedProperty } from "./component.type";
|
||||
|
||||
/** Basic class used to declare web components */
|
||||
export class AbstractComponent extends HTMLElement {
|
||||
|
||||
/** List of all the class members linked to a dom element */
|
||||
public __linkedProperties?: LinkedProperty[]
|
||||
/** All the component's params */
|
||||
public [CUSTOM_COMPONENT_CONFIG]?: ComponentParams;
|
||||
|
||||
public connectedCallback(): void {
|
||||
this.init();
|
||||
this.refresh();
|
||||
}
|
||||
|
||||
public disconnectedCallback(): void { }
|
||||
|
||||
/**
|
||||
* Function called in the component's life cycle
|
||||
* Used to init the DOM and the sub components
|
||||
*/
|
||||
public init(): void { }
|
||||
|
||||
/**
|
||||
* Function called in the component's life cycle
|
||||
* Used to refresh the datas, and re render the component
|
||||
* Please be conscious that if you clean THIS as a dom element, the template won't be re rendered again
|
||||
*/
|
||||
public refresh(): void { }
|
||||
}
|
||||
110
packages/client/web-component/src/component.tools.ts
Normal file
110
packages/client/web-component/src/component.tools.ts
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
import { AbstractComponent } from "./abstractComponent";
|
||||
import { ComponentParams, CUSTOM_COMPONENT_CONFIG } from "./component.type";
|
||||
import { findRefElement, parseModuleToHtml } from "./dom.tools";
|
||||
|
||||
// Declare a unique key to store the flag on the prototype.
|
||||
// This symbol is used to uniquely identify and access the DOM link flag,
|
||||
// ensuring there are no conflicts with other properties on the prototype.
|
||||
export const REQUEST_DOM_LINK_KEY = Symbol("requestDomLink");
|
||||
|
||||
interface ConstructorFunction<T> {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
new(...args: any[]): T
|
||||
}
|
||||
|
||||
/**
|
||||
* Define a custom web component using a decorator.
|
||||
* The decorator configures the component's template, styles, and any additional
|
||||
* properties, as well as handling Shadow DOM attachment if specified.
|
||||
* @param p @see {@link ComponentParams}
|
||||
* @returns a constructor factory
|
||||
*/
|
||||
export function CustomComponent<T extends ConstructorFunction<AbstractComponent>>(p: ComponentParams): (constructor: T) => void {
|
||||
return (constructor: T): void => {
|
||||
|
||||
// Create a template element to contain the component's HTML structure, parsed for use.
|
||||
const templateElement = document.createElement('template');
|
||||
templateElement.innerHTML = parseModuleToHtml(p.template);
|
||||
|
||||
// Attach component configuration as a non-writable property on the prototype
|
||||
Object.defineProperty(constructor.prototype, CUSTOM_COMPONENT_CONFIG, {
|
||||
value: p
|
||||
});
|
||||
|
||||
// Save the original connectedCallback, if it exists, to allow for extension.
|
||||
const originalConnectedCallback = constructor.prototype.connectedCallback;
|
||||
|
||||
// Define a custom connectedCallback for the component
|
||||
constructor.prototype.connectedCallback = function (this: AbstractComponent) {
|
||||
|
||||
// If Shadow DOM is specified, attach it and add the template to it
|
||||
if (p.attachToShadow) {
|
||||
// Determine Shadow DOM mode, defaulting to 'open' if boolean true is given.
|
||||
const mode: ShadowRootMode = typeof p.attachToShadow === "boolean" ? "open" : p.attachToShadow;
|
||||
|
||||
// Attach a Shadow DOM if not already attached
|
||||
if (!this.shadowRoot) {
|
||||
this.attachShadow({ mode });
|
||||
}
|
||||
|
||||
// Append the template content to the Shadow DOM
|
||||
if (this.shadowRoot) {
|
||||
this.shadowRoot.appendChild(templateElement.content.cloneNode(true));
|
||||
}
|
||||
} else {
|
||||
// If not using Shadow DOM, insert template content directly into Light DOM
|
||||
this.innerHTML = "";
|
||||
this.appendChild(templateElement.content.cloneNode(true));
|
||||
}
|
||||
|
||||
// Apply any specified CSS classes to the component root element
|
||||
if (p.cssClasses) {
|
||||
this.classList.add(...p.cssClasses);
|
||||
}
|
||||
|
||||
// Process and link properties specified in __linkedProperties to their DOM elements
|
||||
for (const requested of this.__linkedProperties ?? []) {
|
||||
const elt = findRefElement(requested.ref, this);
|
||||
if (elt == null) {
|
||||
throw new Error(`ref ${requested.ref} not found`);
|
||||
}
|
||||
// Attach the found element as a property on the component instance
|
||||
Object.defineProperty(this, requested.property, { value: elt });
|
||||
}
|
||||
|
||||
// Call the original connectedCallback if it exists
|
||||
if (originalConnectedCallback) {
|
||||
originalConnectedCallback.call(this);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
// Register the custom element with the specified tag name
|
||||
window.customElements.define(p.tagName, constructor);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Decorator that flags the class member as a link to a dom element
|
||||
* @param ref
|
||||
*/
|
||||
export function LinkToDom(ref: string) {
|
||||
return function <T extends AbstractComponent>(target: T, key: string | symbol): void {
|
||||
// Si target est indéfini, renvoyer un avertissement
|
||||
if (!target) {
|
||||
throw new Error(`LinkToDom: 'target' is undefined for property ${String(key)}`);
|
||||
}
|
||||
|
||||
// Ajouter un flag `request` pour marquer cette propriété comme liée au DOM
|
||||
if (!target.__linkedProperties) {
|
||||
target.__linkedProperties = [];
|
||||
}
|
||||
|
||||
// Ajouter la propriété à la liste des propriétés liées
|
||||
target.__linkedProperties.push({
|
||||
property: String(key),
|
||||
ref
|
||||
});
|
||||
}
|
||||
}
|
||||
28
packages/client/web-component/src/component.type.ts
Normal file
28
packages/client/web-component/src/component.type.ts
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
|
||||
export const CUSTOM_COMPONENT_CONFIG = "__customComponentConfig"
|
||||
|
||||
/** Abstract component params*/
|
||||
export interface ComponentParams {
|
||||
/**
|
||||
* A tag name that will be used to register the component as a custom element
|
||||
* Should always follow the following format "my-name"
|
||||
* ex: "custom-menu-component"
|
||||
*/
|
||||
tagName: string;
|
||||
/** HTML Template */
|
||||
template?: string;
|
||||
/** Specific style of the component */
|
||||
style?: string;
|
||||
/** Css classes to append */
|
||||
cssClasses?: string[];
|
||||
/** Define if the component should be atatched to the shadow dom */
|
||||
attachToShadow?: boolean | ShadowRootMode
|
||||
}
|
||||
|
||||
/** Map a property key to a html element by it's ref attribute */
|
||||
export interface LinkedProperty {
|
||||
/** The ref attribute value */
|
||||
ref: string;
|
||||
/** The object's property */
|
||||
property: string;
|
||||
}
|
||||
26
packages/client/web-component/src/dom.tools.ts
Normal file
26
packages/client/web-component/src/dom.tools.ts
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
|
||||
/** The attriute used to bind dom to component's members */
|
||||
const REF_ATTRIBUTE = "ref"
|
||||
|
||||
/**
|
||||
* Find an element with the attribute ref= in the given parent (or the entire body)
|
||||
* @param ref the ref attribute's value of the target dom element
|
||||
* @param parent the container used to search the element. document.body by default
|
||||
* @returns the founded html element or undefined
|
||||
*/
|
||||
export function findRefElement(ref: string, parent?: HTMLElement): HTMLElement | undefined {
|
||||
const parentElement = parent ?? document.body;
|
||||
const elt = parentElement.querySelector(`[${REF_ATTRIBUTE}=${ref}]`);
|
||||
|
||||
return elt == null ? undefined : elt as HTMLElement
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the value of ComponentParams.template into a string if it was fetched with required function
|
||||
* @param mod the template value
|
||||
* @returns the template as a string
|
||||
*/
|
||||
export function parseModuleToHtml(mod: any): string {
|
||||
if (mod == null) return "";
|
||||
return "default" in mod ? mod.default as string : "";
|
||||
}
|
||||
2
packages/client/web-component/src/dom.types.ts
Normal file
2
packages/client/web-component/src/dom.types.ts
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
/** Anything that could be append in html*/
|
||||
export type AcceptedHTMLContent = HTMLElement | string
|
||||
6
packages/client/web-component/src/index.ts
Normal file
6
packages/client/web-component/src/index.ts
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
export { AbstractComponent } from "./abstractComponent";
|
||||
export { CustomComponent, LinkToDom } from "./component.tools";
|
||||
export { ComponentParams, LinkedProperty } from "./component.type";
|
||||
export { findRefElement } from "./dom.tools";
|
||||
export { AcceptedHTMLContent } from "./dom.types";
|
||||
|
||||
9
packages/client/web-component/tsconfig.json
Normal file
9
packages/client/web-component/tsconfig.json
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"extends": "../../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"lib": ["ES2022", "DOM", "DOM.Iterable"],
|
||||
"outDir": "./dist",
|
||||
"rootDir": "./src"
|
||||
},
|
||||
"include": ["src/**/*"]
|
||||
}
|
||||
2145
pnpm-lock.yaml
Normal file
2145
pnpm-lock.yaml
Normal file
File diff suppressed because it is too large
Load diff
18
pnpm-workspace.yaml
Normal file
18
pnpm-workspace.yaml
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
packages:
|
||||
- "packages/*/*"
|
||||
|
||||
allowBuilds:
|
||||
esbuild: true
|
||||
|
||||
# human-id@4.1+ est publié en ESM pur ; @changesets/write le require() en CJS
|
||||
# et casse (ERR_REQUIRE_ESM). 4.0.0 est la dernière version CommonJS.
|
||||
overrides:
|
||||
human-id: "4.0.0"
|
||||
|
||||
catalog:
|
||||
typescript: ^5.7.0
|
||||
"@types/node": ^22.10.0
|
||||
vitest: ^2.1.0
|
||||
"@biomejs/biome": ^2.4.0
|
||||
typedoc: ^0.28.0
|
||||
"@changesets/cli": ^2.27.0
|
||||
153
scripts/create-package.mjs
Normal file
153
scripts/create-package.mjs
Normal file
|
|
@ -0,0 +1,153 @@
|
|||
#!/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 {
|
||||
execFileSync('pnpm', ['install'], { cwd: ROOT, stdio: 'inherit' });
|
||||
execFileSync(
|
||||
'pnpm',
|
||||
[
|
||||
'exec',
|
||||
'biome',
|
||||
'check',
|
||||
'--write',
|
||||
`packages/${category}/${name}`,
|
||||
'tsconfig.json',
|
||||
'spec/packages.md',
|
||||
],
|
||||
{ cwd: ROOT, stdio: 'inherit' },
|
||||
);
|
||||
} 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)');
|
||||
39
spec/architecture.md
Normal file
39
spec/architecture.md
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
# Architecture
|
||||
|
||||
## Objectif
|
||||
|
||||
`lightweight-sdk` est un monorepo pnpm destiné à héberger, au fil du temps, des packages TypeScript réutilisables développés par l'auteur pour ses projets personnels. Chaque package est publié indépendamment sur le registre npm privé hébergé sur l'instance Forgejo personnelle (`git.dev.kyuno.fr`), sous le scope `@lightweight-sdk`.
|
||||
|
||||
## Organisation des packages
|
||||
|
||||
Les packages sont répartis en trois catégories sous `packages/`, qui reflètent la distinction Frontend/Backend du [CLAUDE.md](../CLAUDE.md) du projet :
|
||||
|
||||
- **`client/`** — packages destinés au navigateur (DOM, composants UI). Peuvent dépendre de `lib: DOM` dans leur `tsconfig.json`.
|
||||
- **`common/`** — code isomorphe partagé entre `client` et `server` (types, utilitaires purs, constantes). Convention : ne doit dépendre d'aucune API exclusivement DOM ou exclusivement Node, pour rester portable des deux côtés.
|
||||
- **`server/`** — packages Node/backend. Chaque package doit être structuré comme un service modulaire autonome exposant sa propre API (règle "Architecture Backend" du CLAUDE.md).
|
||||
|
||||
Le nom npm d'un package ne reprend pas le préfixe de catégorie (`@lightweight-sdk/web-component`, pas `@lightweight-sdk/client-web-component`) — la catégorie est une convention d'organisation du dépôt, pas une convention de nommage public.
|
||||
|
||||
Un nouveau package se crée avec `pnpm create-package <client|common|server> <nom>` (voir `scripts/create-package.mjs`).
|
||||
|
||||
## Choix d'outillage
|
||||
|
||||
| Aspect | Choix | Pourquoi |
|
||||
|---|---|---|
|
||||
| Gestionnaire de packages | pnpm workspaces + `catalog:` | Centralise les versions des devDependencies partagées dans `pnpm-workspace.yaml` |
|
||||
| Orchestrateur de build | Aucun (pas de Turborepo/Nx) | Un seul package réel au démarrage ; à reconsidérer si le temps de build devient un problème |
|
||||
| Build | `tsc -b` (project references), pas de bundler | Les packages sont consommés via pnpm par d'autres projets Node/TS de l'auteur ; pas besoin de bundle |
|
||||
| Modules | **CommonJS**, résolution `Node10` | Décision explicite : pas d'extension `.js` requise dans les imports relatifs, et le code migré depuis l'ancien repo `web-component` compile sans modification |
|
||||
| Lint + format | [Biome.js](https://biomejs.dev/) | Imposé par le CLAUDE.md du projet |
|
||||
| Documentation de code | [TypeDoc](https://typedoc.org/) en mode validation | Génère la doc API et fait échouer la CI si un export n'a pas de TSDoc (voir `conventions.md`) |
|
||||
| Tests | [Vitest](https://vitest.dev/) | ESM natif, bon support monorepo |
|
||||
| Versioning/publish | [Changesets](https://github.com/changesets/changesets) | Gère des versions indépendantes par package + changelogs, comprend nativement `workspace:*` |
|
||||
| Node cible | 24 (Active LTS) en CI, `engines: ">=22"` | Node 20 est end-of-life depuis avril 2026 |
|
||||
|
||||
## Dépendances entre packages
|
||||
|
||||
Les dépendances internes entre packages du monorepo utilisent le protocole `workspace:*` (résolu localement par pnpm, jamais via le registre distant). Le registre npm privé n'est utilisé que pour la publication et pour la consommation depuis des projets *externes* à ce monorepo.
|
||||
|
||||
## Registre npm privé
|
||||
|
||||
`https://git.dev.kyuno.fr/api/packages/kyuno/npm/` — voir `ci-cd.md` pour le détail de la publication et de l'authentification.
|
||||
46
spec/ci-cd.md
Normal file
46
spec/ci-cd.md
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
# CI/CD
|
||||
|
||||
## Workflows
|
||||
|
||||
Les workflows vivent dans `.forgejo/workflows/` (pas `.github/workflows/` — ce dernier n'est probablement pas surveillé par Forgejo Actions sur cette instance).
|
||||
|
||||
### `ci.yml`
|
||||
|
||||
Déclenché uniquement sur `pull_request` vers `main` (pas de trigger `push` séparé sur la branche source : il ferait tourner la même vérification deux fois sur le même commit dès qu'une PR est ouverte — deux statuts distincts pour un seul résultat logique, et une exposition doublée aux flakys du runner). Étapes : install (`--frozen-lockfile`) → `pnpm lint` → `pnpm build` → `pnpm test` → `pnpm docs:check`. Ne nécessite aucun secret (les dépendances internes entre packages passent par `workspace:*`, résolu localement).
|
||||
|
||||
### `release.yml`
|
||||
|
||||
Déclenché sur `push` vers `main` (typiquement après le merge d'une PR "Version Packages"). Étapes : install → build → ajout dynamique d'une ligne d'authentification dans `.npmrc` (jamais committée) → `pnpm changeset:publish`.
|
||||
|
||||
`changeset publish` est idempotent par package : il republie uniquement les packages dont la version locale n'existe pas encore sur le registre. Un push sur `main` sans bump de version ne publie donc rien.
|
||||
|
||||
## Flux Changesets (versioning + publication)
|
||||
|
||||
1. Pendant une PR de feature, ajouter un changeset : `pnpm changeset` (choisir le(s) package(s) concerné(s), le type de bump, décrire le changement). Le fichier généré dans `.changeset/` est commité avec la PR.
|
||||
2. Quand on est prêt à publier, en local : `pnpm changeset version` — bump les `package.json` concernés et génère/met à jour leurs `CHANGELOG.md`.
|
||||
3. Ouvrir une PR "Version Packages" avec ce résultat, la relire, la merger soi-même (jamais d'auto-merge).
|
||||
4. Le merge sur `main` déclenche `release.yml`, qui publie effectivement sur le registre les packages dont la version a changé.
|
||||
|
||||
Pas de bot automatique type `changesets/action` (spécifique GitHub, incertain sur Forgejo) : le flux est volontairement manuel aux étapes 1-3.
|
||||
|
||||
## Registre npm privé Forgejo
|
||||
|
||||
- URL : `https://git.dev.kyuno.fr/api/packages/kyuno/npm/` (owner Forgejo = `kyuno`, indépendant du scope npm `@lightweight-sdk` — les deux ne sont pas liés).
|
||||
- `.npmrc` (racine, committé) : `@lightweight-sdk:registry=https://git.dev.kyuno.fr/api/packages/kyuno/npm/`.
|
||||
- Authentification : `//git.dev.kyuno.fr/api/packages/kyuno/npm/:_authToken=<token>` — jamais committé, injecté uniquement en CI via le secret `REGISTRY_TOKEN`.
|
||||
- Limite connue : impossible de republier un nom+version déjà existant sur le registre (Changesets gère ça nativement en forçant un bump à chaque publication).
|
||||
|
||||
### Secret `REGISTRY_TOKEN`
|
||||
|
||||
1. Forgejo → Settings → Applications → générer un token avec les scopes `write:package` + `read:package`.
|
||||
2. L'ajouter comme secret de repo nommé `REGISTRY_TOKEN` sur **ce** repo (`lightweight-sdk`) — les secrets de repo ne sont pas partagés entre repos sur cette instance ; celui de `watchparty` ne peut pas être réutilisé tel quel.
|
||||
|
||||
### Troubleshooting : 404 sur un package scopé
|
||||
|
||||
Si `pnpm changeset:publish` échoue avec une 404 sur un nom de package scopé (`@lightweight-sdk/...`), la cause probable est le reverse proxy devant l'instance : npm encode le `/` d'un nom scopé en `%2F`, ce qu'Apache refuse par défaut. Vérifier `AllowEncodedSlashes NoDecode` dans le VirtualHost et `nocanon` sur la directive `ProxyPass`. Ce point n'a pas pu être vérifié depuis l'agent (config réseau propre à l'instance).
|
||||
|
||||
## Pistes futures
|
||||
|
||||
- `git push --follow-tags` après `changeset publish` pour taguer les releases (pas fait par défaut aujourd'hui).
|
||||
- Automatiser l'étape 2 du flux Changesets (PR "Version Packages" ouverte automatiquement) via un workflow `workflow_dispatch` ou planifié.
|
||||
- Protection de branche réelle sur `main` côté Forgejo (l'interdiction de push direct n'est aujourd'hui que conventionnelle, via CLAUDE.md).
|
||||
50
spec/conventions.md
Normal file
50
spec/conventions.md
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
# Conventions
|
||||
|
||||
## Traçabilité des règles CLAUDE.md
|
||||
|
||||
| Règle CLAUDE.md | Mécanisme dans ce repo |
|
||||
|---|---|
|
||||
| Modificateurs d'accès explicites | Biome `useConsistentMemberAccessibility: "explicit"` (partiellement auto-fixable via `pnpm lint:fix`) ✅ |
|
||||
| TSDoc sur chaque fonction/type/interface/classe/membre/méthode | TypeDoc en mode validation (`pnpm docs:check`, bloquant en CI). Biome n'a pas de règle équivalente ✅ (sauf `@lightweight-sdk/web-component`, exclu — voir `packages.md`) |
|
||||
| `.catch()` obligatoire sur toute Promise non-awaited | Biome `noFloatingPromises` / `noMisusedPromises` / `useAwaitThenable` ✅ |
|
||||
| `try/catch` obligatoire autour de chaque `await` individuel | **Aucun linter JS/TS courant ne vérifie ça** (ni Biome ni ESLint). Convention à appliquer soi-même à chaque nouveau package ❌ mécanisme automatique |
|
||||
| Indentation "2 tabulations" | `biome.json` (`indentStyle: "tab"`, `indentWidth: 2`) + `.editorconfig` ⚠️ deux exceptions : les fichiers YAML n'acceptent pas les tabulations (interdit par la spec YAML) → 2 espaces ; le Markdown n'est pas formaté par Biome → 2 espaces par convention manuelle |
|
||||
| Logging exhaustif | Convention à appliquer dans chaque nouveau package (pas de mécanisme automatique — à illustrer dans le code) |
|
||||
| Séparation `.ts`/`.html`/`.scss` (Frontend) | S'applique aux futurs packages `client/` qui rendent des composants concrets avec leur propre template. Ne s'applique pas à `web-component`, qui est une bibliothèque d'abstraction sans template propre (et de toute façon non modifiée, voir `packages.md`) |
|
||||
| Services modulaires autonomes (Backend) | Chaque package `server/` doit exposer sa propre API, indépendante des autres |
|
||||
|
||||
`pnpm lint` (= `biome check .`) tourne **sans** `--error-on-warnings` : les diagnostics de sévérité "warn" restent visibles mais ne font pas échouer la CI. Seules les erreurs bloquent.
|
||||
|
||||
## Imports
|
||||
|
||||
Sous `module: CommonJS` + `moduleResolution: Node10` (voir `architecture.md`), les imports relatifs **n'ont pas besoin** d'extension (`from "./foo"`, pas `from "./foo.js"`).
|
||||
|
||||
## Nommage
|
||||
|
||||
- Dossiers de package et noms npm : kebab-case (`@lightweight-sdk/my-package`).
|
||||
- Classes : PascalCase. Fonctions/variables : camelCase.
|
||||
|
||||
## Tests
|
||||
|
||||
- Colocalisés : `src/foo.ts` + `src/foo.test.ts`.
|
||||
- Environnement Vitest par défaut : `"node"`. Pour un test qui a besoin du DOM, utiliser le pragma en première ligne du fichier : `// @vitest-environment happy-dom` (ajouter `happy-dom` en devDependency le jour où c'est nécessaire).
|
||||
|
||||
## Exemple : convention async/erreurs/logging attendue dans un nouveau package
|
||||
|
||||
```ts
|
||||
import { logger } from './logger';
|
||||
|
||||
/** Fetches and parses the remote config, throwing on failure. */
|
||||
export async function loadConfig(url: string): Promise<Config> {
|
||||
try {
|
||||
const response = await fetch(url);
|
||||
return await response.json();
|
||||
} catch (error) {
|
||||
logger.error('loadConfig failed', { url, error });
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
// Appel fire-and-forget : .catch() obligatoire (pas d'await)
|
||||
void loadConfig(configUrl).catch((error) => logger.error('background config load failed', { error }));
|
||||
```
|
||||
32
spec/packages.md
Normal file
32
spec/packages.md
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
# Registre des packages
|
||||
|
||||
| Package | Catégorie | Version | Statut |
|
||||
|---|---|---|---|
|
||||
| `@lightweight-sdk/web-component` | client | 0.0.2 | migré depuis `lightweight-sdk-web-component`, non modifié |
|
||||
|
||||
## Ajouter un package
|
||||
|
||||
```bash
|
||||
pnpm create-package <client|common|server> <nom-du-package>
|
||||
```
|
||||
|
||||
Le script scaffolde `package.json`, `tsconfig.json`, `src/index.ts` + un test, un `README.md`, ajoute le package aux project references racine et met à jour ce tableau automatiquement. Reste à faire à la main : décrire le package, l'implémenter, et créer un changeset (`pnpm changeset`) quand il est prêt à être publié.
|
||||
|
||||
## Champs `package.json` obligatoires pour tout package du monorepo
|
||||
|
||||
- `name` (`@lightweight-sdk/<nom>`), `version`, `description`
|
||||
- `main` (`dist/index.js`), `types` (`dist/index.d.ts`), `files: ["dist"]`
|
||||
- `engines.node >= 22`
|
||||
- `publishConfig.registry` pointant vers le registre npm privé (`https://git.dev.kyuno.fr/api/packages/kyuno/npm/`)
|
||||
- `typedocOptions.entryPoints` (sauf exception documentée, voir ci-dessous)
|
||||
|
||||
## Observations sur `@lightweight-sdk/web-component` (non traitées, laissées telles quelles)
|
||||
|
||||
Le code source de ce package a été migré strictement à l'identique depuis l'ancien repo `lightweight-sdk-web-component`, sans aucune édition (décision explicite de l'auteur). Quelques points relevés à la lecture, non corrigés, à traiter soi-même dans une PR dédiée si souhaité :
|
||||
|
||||
- `connectedCallback()`/`disconnectedCallback()` (`abstractComponent.ts`), la constante `CUSTOM_COMPONENT_CONFIG` (`component.type.ts`) et `REQUEST_DOM_LINK_KEY` (`component.tools.ts`) n'ont pas de TSDoc complet — c'est pourquoi ce package est exclu de la validation `docs:check` dans `typedoc.json` (`exclude: ["packages/client/web-component/**"]`).
|
||||
- Deux usages de `any` (`ConstructorFunction.new(...args: any[])`, `parseModuleToHtml(mod: any)`) — visibles comme avertissements Biome non bloquants (`noExplicitAny`).
|
||||
- Le paramètre `constructor` dans `component.tools.ts` masque un nom global restreint (`noShadowRestrictedNames`) — désactivé pour ce package via un `overrides` dans `biome.json`.
|
||||
- Le style de formatage d'origine (4 espaces, guillemets doubles) diffère de la config Biome du monorepo (tabulations, guillemets simples) — le formatter Biome est désactivé pour ce package via le même `overrides`.
|
||||
- `REQUEST_DOM_LINK_KEY` semble ne plus être utilisé nulle part dans le code (le mécanisme actif est le tableau `__linkedProperties`) — potentiellement mort, mais pas supprimé.
|
||||
- Quelques typos mineures ("atatched", "attriute") et un commentaire en français dans `LinkToDom` qui ne correspond plus exactement au comportement (`throw` au lieu d'un simple avertissement).
|
||||
18
tsconfig.base.json
Normal file
18
tsconfig.base.json
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2022",
|
||||
"module": "CommonJS",
|
||||
"moduleResolution": "Node10",
|
||||
"strict": true,
|
||||
"declaration": true,
|
||||
"declarationMap": true,
|
||||
"sourceMap": true,
|
||||
"composite": true,
|
||||
"incremental": true,
|
||||
"esModuleInterop": true,
|
||||
"skipLibCheck": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"resolveJsonModule": true,
|
||||
"experimentalDecorators": true
|
||||
}
|
||||
}
|
||||
4
tsconfig.json
Normal file
4
tsconfig.json
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"files": [],
|
||||
"references": [{ "path": "./packages/client/web-component" }]
|
||||
}
|
||||
27
typedoc.json
Normal file
27
typedoc.json
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
{
|
||||
"$schema": "https://typedoc.org/schema.json",
|
||||
"entryPointStrategy": "packages",
|
||||
"entryPoints": ["packages/*/*"],
|
||||
"out": "docs/api",
|
||||
"validation": {
|
||||
"notExported": true,
|
||||
"invalidLink": true,
|
||||
"notDocumented": true
|
||||
},
|
||||
"requiredToBeDocumented": [
|
||||
"Enum",
|
||||
"EnumMember",
|
||||
"Variable",
|
||||
"Function",
|
||||
"Class",
|
||||
"Interface",
|
||||
"Property",
|
||||
"Method",
|
||||
"Accessor",
|
||||
"TypeAlias",
|
||||
"Parameter",
|
||||
"Constructor"
|
||||
],
|
||||
"treatWarningsAsErrors": true,
|
||||
"excludeExternals": true
|
||||
}
|
||||
10
vitest.config.ts
Normal file
10
vitest.config.ts
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
import { defineConfig } from 'vitest/config';
|
||||
|
||||
export default defineConfig({
|
||||
test: {
|
||||
include: ['packages/*/*/src/**/*.test.ts'],
|
||||
exclude: ['**/node_modules/**', '**/dist/**'],
|
||||
environment: 'node',
|
||||
passWithNoTests: true,
|
||||
},
|
||||
});
|
||||
Loading…
Reference in a new issue