Compare commits
2
Commits
main
..
46929e2ef5
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
46929e2ef5 | ||
|
|
d66ec03165 |
@@ -1,91 +0,0 @@
|
|||||||
name: CI
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: ['**']
|
|
||||||
tags: ['v*']
|
|
||||||
pull_request:
|
|
||||||
branches: ['**']
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
typecheck:
|
|
||||||
name: TypeScript — type-check
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: '20'
|
|
||||||
cache: 'npm'
|
|
||||||
|
|
||||||
- name: Install
|
|
||||||
run: npm ci
|
|
||||||
|
|
||||||
- name: Type-check (tsc)
|
|
||||||
run: npx tsc --noEmit
|
|
||||||
|
|
||||||
publish:
|
|
||||||
name: Publish — build & push image
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs: [typecheck]
|
|
||||||
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
# Gitea's registry, not registry.netork.io.
|
|
||||||
#
|
|
||||||
# registry.netork.io is plain registry:2 with htpasswd auth, which knows
|
|
||||||
# nothing about repositories: every account that can log in reads and
|
|
||||||
# writes everything on it, including the accounts issued to customer
|
|
||||||
# instances. It keeps the images those instances are meant to pull
|
|
||||||
# (netork/engine, netork/ui, netork/satellite); the marketing site is not
|
|
||||||
# one of them. Gitea scopes packages to their owning account, and no
|
|
||||||
# customer has one. netOrk issue #172.
|
|
||||||
#
|
|
||||||
# REGISTRY_TOKEN is a Gitea access token with write:package — the token
|
|
||||||
# Actions injects per run is scoped to the repository API and the package
|
|
||||||
# registry rejects it outright.
|
|
||||||
- name: Login to registry
|
|
||||||
run: |
|
|
||||||
set -euo pipefail
|
|
||||||
if [ -z "${{ secrets.REGISTRY_TOKEN }}" ]; then
|
|
||||||
echo "::error::REGISTRY_TOKEN is not set (Gitea token with write:package)."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
LOGIN_USER="${{ secrets.REGISTRY_USER }}"
|
|
||||||
[ -n "$LOGIN_USER" ] || LOGIN_USER="${{ github.actor }}"
|
|
||||||
echo "${{ secrets.REGISTRY_TOKEN }}" | docker login git.netork.io -u "$LOGIN_USER" --password-stdin
|
|
||||||
|
|
||||||
- name: Build & push
|
|
||||||
run: |
|
|
||||||
set -euo pipefail
|
|
||||||
SHA=$(git rev-parse --short HEAD)
|
|
||||||
docker build \
|
|
||||||
-t git.netork.io/netork/website:latest \
|
|
||||||
-t git.netork.io/netork/website:main-${SHA} \
|
|
||||||
.
|
|
||||||
docker push git.netork.io/netork/website:latest
|
|
||||||
docker push git.netork.io/netork/website:main-${SHA}
|
|
||||||
|
|
||||||
- name: Logout
|
|
||||||
if: always()
|
|
||||||
run: docker logout git.netork.io
|
|
||||||
|
|
||||||
# The deploy job that used to live here has been removed, deliberately.
|
|
||||||
#
|
|
||||||
# It ran `docker run` against whatever runner picked the job up, which worked
|
|
||||||
# while exactly one runner existed. There are now several (netork-runner-12 on
|
|
||||||
# .12, netork-runner-13 on .13, and the original netork-runner) and none of them
|
|
||||||
# is on 10.7.224.11, where this site actually runs and where the proxy-net it
|
|
||||||
# attaches to lives. The job would therefore have started a second website
|
|
||||||
# container on the wrong host and reported success, while netork.io went on
|
|
||||||
# serving the old one.
|
|
||||||
#
|
|
||||||
# Deployment is now an explicit step: scripts/deploy.sh, run from a workstation,
|
|
||||||
# which targets .11 by name and verifies afterwards that the container really is
|
|
||||||
# on the image that was pulled.
|
|
||||||
#
|
|
||||||
# To get push-to-deploy back, either register a runner on .11 with a label of its
|
|
||||||
# own and pin `runs-on:` to it, or give CI an ssh key for .11. Both are choices
|
|
||||||
# about where a credential lives, so neither was made here.
|
|
||||||
+1
-17
@@ -1,17 +1 @@
|
|||||||
node_modules/
|
node_modules/\ndist/\n.env\n.env.local\n*.local\n.DS_Store
|
||||||
dist/
|
|
||||||
memory/
|
|
||||||
.env
|
|
||||||
.env.local
|
|
||||||
*.local
|
|
||||||
.DS_Store
|
|
||||||
|
|
||||||
# Deploy target + registry token
|
|
||||||
deploy.env
|
|
||||||
|
|
||||||
# Screenshot tooling: bytecode, and database dumps that hold production data
|
|
||||||
__pycache__/
|
|
||||||
*.dump
|
|
||||||
|
|
||||||
# Output of scripts/check/site.py
|
|
||||||
.check/
|
|
||||||
|
|||||||
@@ -10,38 +10,14 @@ get started.
|
|||||||
## Project Purpose
|
## Project Purpose
|
||||||
|
|
||||||
Potential users land here and need to answer three questions in under 10 seconds:
|
Potential users land here and need to answer three questions in under 10 seconds:
|
||||||
1. What is this? — Control instead of drift: define the desired state once,
|
1. What is this?
|
||||||
netOrk finds every deviation and puts it back.
|
2. Is it for me?
|
||||||
2. Is it for me? — IT departments in small and mid-sized companies with mixed
|
3. How do I try it?
|
||||||
hardware (service providers and IT support are secondary).
|
|
||||||
3. What does it cost? — netOrk is free; a licence adds vulnerability data and
|
|
||||||
updates (`/pricing`).
|
|
||||||
|
|
||||||
Everything on the site should serve those three questions.
|
Everything on the site should serve those three questions.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Infrastruktur ändert man woanders — und vorher
|
|
||||||
|
|
||||||
Diese Anwendung läuft auf einer Infrastruktur, die sie sich mit anderen Projekten teilt:
|
|
||||||
Netz, Datenbankcluster, öffentlicher Eingang und Backup gehören keinem Projekt allein.
|
|
||||||
Dokumentiert ist sie in **`git.netork.io/christianmanivong/infrastructure`**, und dort
|
|
||||||
steht in `CLAUDE.md` auch die verbindliche Regel.
|
|
||||||
|
|
||||||
**Kurz: erst dort dokumentieren, ausdrücklich genehmigen lassen, dann ändern.** Nicht
|
|
||||||
umgekehrt, und „ja mach mal" zu einer früheren Frage deckt die nächste Änderung nicht mit
|
|
||||||
ab.
|
|
||||||
|
|
||||||
Betroffen ist alles, was über dieses Repo hinausreicht — Hosts, Netze, Firewall-Regeln,
|
|
||||||
der Patroni-Cluster samt `pg_hba` und DCS-Parametern, pgBackRest, BunkerWeb-Hosts, DNS,
|
|
||||||
CI-Runner, alles, was eine Anwendung auf den geteilten Datenbankcluster umzieht.
|
|
||||||
**Nicht** betroffen: Anwendungscode, Abhängigkeiten und Migrationen innerhalb der eigenen
|
|
||||||
Datenbank.
|
|
||||||
|
|
||||||
Der Grund für die Reihenfolge ist nicht Bürokratie. Die meisten Zwischenfälle dort waren
|
|
||||||
nicht falsche Werte, sondern richtige Werte in der falschen Reihenfolge — und das fällt
|
|
||||||
beim Aufschreiben auf, nicht beim Tippen. Im Zweifel dorthin.
|
|
||||||
|
|
||||||
## Content & Design Source of Truth
|
## Content & Design Source of Truth
|
||||||
|
|
||||||
All product content (features, copy, page structure) is in `docs/`:
|
All product content (features, copy, page structure) is in `docs/`:
|
||||||
@@ -77,19 +53,13 @@ exactly as netOrk's `ui/src/components/ui.tsx` does.
|
|||||||
|
|
||||||
## Design Rules (summary — full detail in docs/DESIGN.md)
|
## Design Rules (summary — full detail in docs/DESIGN.md)
|
||||||
|
|
||||||
- **Light pages, dark product.** Pages are `paper` with `ink`; the only dark
|
- **Dark theme only.** Background `bg-slate-950`. Cards `bg-slate-900`.
|
||||||
surfaces are real netOrk screenshots and code, on the `night` stage.
|
- **Accent color:** `sky-500` / `sky-600` for CTAs, links, highlights.
|
||||||
- One accent, `accent` (sky-700), for links, eyebrows and focus. Buttons are ink.
|
- **No light mode toggle.** Ever.
|
||||||
- Font: Inter Variable, self-hosted via `@fontsource-variable/inter`. No Google
|
- Font stack: system default (Tailwind sans). No Google Fonts.
|
||||||
Fonts, no request to any other origin.
|
- All interactive elements use `transition-colors` — no layout shifts.
|
||||||
- Layout from `src/components/ui.tsx`: split sections, ruled lists, numbered
|
- Screenshots/mockups of the actual app use a `border border-slate-700 rounded-xl
|
||||||
steps, bands. No card grids, no icon tiles, no centred text blocks.
|
overflow-hidden` wrapper to frame them against the dark background.
|
||||||
- Motion: `transition-colors` only — no layout shifts.
|
|
||||||
- **Screenshots are real.** Taken from the anonymised demo copy with
|
|
||||||
`scripts/screenshots/capture.py`, cropped to what the text talks about, at most
|
|
||||||
four on the site. No mockups, no edited data, no clicks that fake a state.
|
|
||||||
- **Less text.** Word budgets per page are in docs/PAGES.md and checked by
|
|
||||||
`scripts/check/site.py`.
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -117,9 +87,7 @@ netork-website/
|
|||||||
|
|
||||||
## Tone of Voice
|
## Tone of Voice
|
||||||
|
|
||||||
- Direct and technical — audience is the admins of an IT department, not executives.
|
- Direct and technical — audience is engineers, not executives.
|
||||||
- One message: control instead of drift. Everything else supports it.
|
|
||||||
- No marketing fluff ("revolutionize", "empower", "seamless").
|
- No marketing fluff ("revolutionize", "empower", "seamless").
|
||||||
- Show, don't tell — a real screenshot beats three sentences of prose.
|
- Show, don't tell — a screenshot or code block beats three sentences of prose.
|
||||||
- Website copy exists in **English and German** (German addresses readers with
|
- German is fine for internal docs; the website copy is in **English**.
|
||||||
"ihr"); the language follows the browser until the visitor chooses.
|
|
||||||
|
|||||||
Vendored
+1
File diff suppressed because one or more lines are too long
Vendored
+78
File diff suppressed because one or more lines are too long
Vendored
+18
@@ -0,0 +1,18 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en" class="scroll-smooth">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<meta name="description" content="netOrk — self-hosted network orchestration for heterogeneous infrastructure. Discover, monitor, and manage routers, switches, firewalls, and servers from a single UI." />
|
||||||
|
<title>netOrk — Network Orchestration Platform</title>
|
||||||
|
<link rel="icon" href="/logo.png" />
|
||||||
|
<meta property="og:image" content="/logo.png" />
|
||||||
|
<meta property="og:title" content="netOrk — Network Orchestration Platform" />
|
||||||
|
<meta property="og:description" content="Self-hosted network orchestration for heterogeneous infrastructure." />
|
||||||
|
<script type="module" crossorigin src="/assets/index-F6soxE0Z.js"></script>
|
||||||
|
<link rel="stylesheet" crossorigin href="/assets/index-BKmpE_Rp.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="root"></div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
Vendored
BIN
Binary file not shown.
|
After Width: | Height: | Size: 1.9 MiB |
+2
-1
@@ -1,6 +1,7 @@
|
|||||||
services:
|
services:
|
||||||
netork-website:
|
netork-website:
|
||||||
image: registry.netork.io/netork/website:latest
|
build: .
|
||||||
|
image: netork-website:latest
|
||||||
container_name: netork-website
|
container_name: netork-website
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
expose:
|
expose:
|
||||||
|
|||||||
+279
-59
@@ -1,78 +1,298 @@
|
|||||||
# netOrk website — design system
|
# netOrk — Visual Identity & Design System
|
||||||
|
|
||||||
**Light pages, dark product.** The site is calm paper with ink; the only dark
|
This document defines the visual identity of netOrk and must be followed
|
||||||
surfaces are real screenshots of netOrk and code, set on a "stage". References:
|
exactly when building the website. The goal is zero visual discontinuity
|
||||||
Linear/Vercel for precision, Tailscale/Netbird for friendliness.
|
between the product UI and the marketing site.
|
||||||
|
|
||||||
Tokens live in `tailwind.config.js`, building blocks in `src/components/ui.tsx`.
|
---
|
||||||
If a page needs something that is not there, it probably needs less instead.
|
|
||||||
|
|
||||||
## Colour
|
## Logo Assets
|
||||||
|
|
||||||
| Token | Value | Use |
|
The logo file is in `public/` — use it directly, do not recreate.
|
||||||
|
|
||||||
|
| File | Format | Size | Use |
|
||||||
|
|---|---|---|---|
|
||||||
|
| `public/logo.png` | PNG | 1024×1024, RGBA | Nav logo, OG image, hero, press kit, favicon fallback |
|
||||||
|
|
||||||
|
### Usage in `<img>` (nav, hero)
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
<img src="/logo.png" alt="netOrk" className="h-8 w-8" />
|
||||||
|
```
|
||||||
|
|
||||||
|
For the nav, pair it with the wordmark:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
<a href="/" className="flex items-center gap-2.5">
|
||||||
|
<img src="/logo.png" alt="" className="h-7 w-7" aria-hidden="true" />
|
||||||
|
<span className="font-semibold text-slate-100 tracking-tight">
|
||||||
|
net<span className="text-sky-400">Ork</span>
|
||||||
|
</span>
|
||||||
|
</a>
|
||||||
|
```
|
||||||
|
|
||||||
|
Use `net<span class="text-sky-400">Ork</span>` consistently — the `Ork` part
|
||||||
|
in sky-400 ties the wordmark to the accent color.
|
||||||
|
|
||||||
|
### `<head>` references
|
||||||
|
|
||||||
|
```html
|
||||||
|
<link rel="icon" href="/logo.png" />
|
||||||
|
<meta property="og:image" content="/logo.png" />
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Core Principle
|
||||||
|
|
||||||
|
**The website looks like a dark-mode dev tool, not a SaaS landing page.**
|
||||||
|
No gradients, no floating orbs, no animated hero blobs. The aesthetic is
|
||||||
|
deliberate, minimal, and technical — consistent with the product itself.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Color Palette
|
||||||
|
|
||||||
|
All colors are Tailwind CSS v3 classes. Do not use hex values directly —
|
||||||
|
always use Tailwind class names to stay consistent.
|
||||||
|
|
||||||
|
### Backgrounds
|
||||||
|
|
||||||
|
| Layer | Class | Usage |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| `paper` / `paper-2` | `#FAFAF9` / `#F3F3F0` | page / band |
|
| Page / outermost | `bg-slate-950` | Body, full-bleed sections |
|
||||||
| `line` / `line-strong` | `#E6E6E3` / `#D4D4D0` | hairlines |
|
| Card / panel | `bg-slate-900` | Content cards, code blocks, feature boxes |
|
||||||
| `ink` / `ink-soft` / `ink-muted` / `ink-faint` | `#0E1116` … `#9AA0A8` | headings / body / secondary / quiet |
|
| Elevated element | `bg-slate-800` | Hover states, dropdowns, table rows on hover |
|
||||||
| `night` | `#020617` | screenshot and code stage — the netOrk UI's own background |
|
| Border | `border-slate-700` | Between sections, card outlines |
|
||||||
| `accent` (`hover`, `soft`) | `#0369A1` | links, eyebrows, numbers, focus ring (5.7:1 on paper) |
|
| Subtle border | `border-slate-800` | Inside cards, dividers |
|
||||||
| `drift` / `sync` | `#B45309` / `#15803D` | status: deviates / matches; never the only signal |
|
|
||||||
|
|
||||||
No gradients, no glow, no second accent. Buttons are ink, not accent.
|
### Text
|
||||||
|
|
||||||
## Type
|
| Role | Class |
|
||||||
|
|
||||||
Inter Variable, self-hosted through `@fontsource-variable/inter` (bundled by
|
|
||||||
Vite; the site makes no request to anyone else). Scale:
|
|
||||||
|
|
||||||
| Class | Use |
|
|
||||||
|---|---|
|
|---|---|
|
||||||
| `text-display` | the home headline only |
|
| Primary | `text-slate-100` |
|
||||||
| `text-h1` | one per page, in `PageHeader` |
|
| Secondary / muted | `text-slate-400` |
|
||||||
| `text-h2` | section headings |
|
| Tertiary / placeholder | `text-slate-500` |
|
||||||
| `text-h3` | row terms, plan names |
|
| Accent (interactive) | `text-sky-400` |
|
||||||
| `text-lead` | the paragraph under a heading |
|
| Danger | `text-red-400` |
|
||||||
| `text-eyebrow` + `uppercase text-accent` | the small line above a heading |
|
|
||||||
|
|
||||||
Everything is left-aligned. Headings balance and hyphenate (`<html lang>` is
|
### Accent (Interactive / CTA)
|
||||||
set per language). Text columns stay within `max-w-measure` (38rem).
|
|
||||||
|
|
||||||
## Layout
|
| State | Class |
|
||||||
|
|---|---|
|
||||||
|
| Default button | `bg-sky-600 text-white` |
|
||||||
|
| Hover | `hover:bg-sky-500` |
|
||||||
|
| Link / inline | `text-sky-400 hover:text-sky-300` |
|
||||||
|
| Active indicator | `text-sky-400` |
|
||||||
|
| Focus ring | `focus:ring-sky-500` |
|
||||||
|
|
||||||
- Container `max-w-page` (72rem), `px-5 sm:px-8`. Sections `py-20 md:py-28`.
|
### Semantic Colors
|
||||||
- **Split**: heading on the left five columns, content on the right. The
|
|
||||||
default section.
|
|
||||||
- **RuleList**: rows divided by hairlines, term and body; one or two columns.
|
|
||||||
This replaces every card grid.
|
|
||||||
- **Steps**: numbered rows (`01`, `02`, `03`) in mono accent.
|
|
||||||
- **Band**: `bg-paper-2` with hairlines, for the hardware strip and the closing
|
|
||||||
call to action (`CtaBand`).
|
|
||||||
- **Stage**: `bg-night`, `rounded-2xl`, `shadow-stage` — screenshots (`Shot`)
|
|
||||||
and code (`CodeBlock`).
|
|
||||||
|
|
||||||
Not used: icon tiles, pills for names, cards, centred text blocks, fake browser
|
| Meaning | Color |
|
||||||
windows, emoji. Motion is `transition-colors` only.
|
|---|---|
|
||||||
|
| Success / active | `text-green-400`, `bg-green-500/20` |
|
||||||
|
| Warning / caution | `text-yellow-400`, `bg-yellow-500/20` |
|
||||||
|
| Danger / error | `text-red-400`, `bg-red-500/20` |
|
||||||
|
| Info / neutral | `text-blue-400`, `bg-blue-500/20` |
|
||||||
|
|
||||||
## Screenshots
|
### Status Badge Pattern
|
||||||
|
|
||||||
Only real screenshots of netOrk, from the anonymised demo copy
|
```tsx
|
||||||
(`scripts/demo`), taken by `scripts/screenshots/capture.py` and published as
|
// Active / online
|
||||||
WebP in `public/screenshots/`. Their sizes are written to
|
<span className="text-xs font-medium px-2 py-0.5 rounded-full bg-green-500/20 text-green-400">
|
||||||
`src/data/screenshots.json`, which `Shot` reads.
|
active
|
||||||
|
</span>
|
||||||
|
|
||||||
- At most four different images on the site. Each is cropped to the one thing
|
// Offline
|
||||||
the text next to it talks about (`clip` or `element` in `shots.py`).
|
<span className="text-xs font-medium px-2 py-0.5 rounded-full bg-red-500/20 text-red-400">
|
||||||
- Cropping shows less of a real screen; it never changes what is on it. No
|
offline
|
||||||
edited data, no clicks that fake a state, no mockups.
|
</span>
|
||||||
- A crop that does not read on a phone gets a `-narrow` variant (`Shot narrow=`).
|
|
||||||
- Every image has an alt text and a caption that says what is true in it.
|
|
||||||
|
|
||||||
## Wordmark
|
// Warning
|
||||||
|
<span className="text-xs font-medium px-2 py-0.5 rounded-full bg-yellow-500/20 text-yellow-400">
|
||||||
|
warning
|
||||||
|
</span>
|
||||||
|
```
|
||||||
|
|
||||||
Text only: `net<span class="text-accent">Ork</span>` in ink. `public/logo.png`
|
---
|
||||||
is the favicon and OG image; it does not sit well on a light background.
|
|
||||||
|
|
||||||
## Glossary marks
|
## Typography
|
||||||
|
|
||||||
Terms from `src/glossary/terms.ts` get a dotted underline and a dark tooltip
|
Font stack: Tailwind default sans-serif (`font-sans`). **No Google Fonts.**
|
||||||
(`linkify`). Not on the homepage — short copy there stays unmarked.
|
The product uses system fonts; the website must match.
|
||||||
|
|
||||||
|
| Element | Classes |
|
||||||
|
|---|---|
|
||||||
|
| Hero heading | `text-4xl md:text-6xl font-bold text-slate-100 leading-tight` |
|
||||||
|
| Section heading | `text-2xl md:text-3xl font-bold text-slate-100` |
|
||||||
|
| Subsection heading | `text-xl font-semibold text-slate-200` |
|
||||||
|
| Body text | `text-base text-slate-400 leading-relaxed` |
|
||||||
|
| Small / label | `text-sm text-slate-400` |
|
||||||
|
| Tiny / tag | `text-xs font-medium text-slate-500` |
|
||||||
|
| Code / monospace | `font-mono text-sky-400` |
|
||||||
|
| Accent text | `text-sky-400` |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Spacing & Layout
|
||||||
|
|
||||||
|
- Max content width: `max-w-7xl mx-auto px-6`
|
||||||
|
- Section padding: `py-24` (desktop), `py-16` (mobile)
|
||||||
|
- Card padding: `p-6`
|
||||||
|
- Gap between grid items: `gap-6` or `gap-8`
|
||||||
|
- All layouts are mobile-first; use `md:` and `lg:` breakpoints.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Components
|
||||||
|
|
||||||
|
### Primary CTA Button
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
<a
|
||||||
|
href="/docs/getting-started"
|
||||||
|
className="inline-flex items-center gap-2 px-6 py-3 rounded-lg
|
||||||
|
bg-sky-600 hover:bg-sky-500 text-white font-medium
|
||||||
|
transition-colors"
|
||||||
|
>
|
||||||
|
Get started
|
||||||
|
</a>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Secondary / Ghost Button
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
<a
|
||||||
|
href="/features"
|
||||||
|
className="inline-flex items-center gap-2 px-6 py-3 rounded-lg
|
||||||
|
border border-slate-700 hover:border-slate-500
|
||||||
|
text-slate-300 hover:text-slate-100
|
||||||
|
transition-colors"
|
||||||
|
>
|
||||||
|
See all features
|
||||||
|
</a>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Feature Card
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
<div className="rounded-xl border border-slate-800 bg-slate-900 p-6">
|
||||||
|
<div className="mb-4 flex h-10 w-10 items-center justify-center
|
||||||
|
rounded-lg bg-sky-600/10">
|
||||||
|
{/* Heroicon SVG, className="h-5 w-5 text-sky-400" */}
|
||||||
|
</div>
|
||||||
|
<h3 className="mb-2 text-lg font-semibold text-slate-100">Feature name</h3>
|
||||||
|
<p className="text-sm text-slate-400 leading-relaxed">
|
||||||
|
Description of the feature in one to three sentences.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Screenshot Frame
|
||||||
|
|
||||||
|
App screenshots must be wrapped in this frame to integrate naturally
|
||||||
|
against the dark background:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
<div className="rounded-xl border border-slate-700 overflow-hidden shadow-2xl">
|
||||||
|
<img src="/screenshots/device-list.png" alt="Device inventory" className="w-full" />
|
||||||
|
</div>
|
||||||
|
```
|
||||||
|
|
||||||
|
Optionally add a browser chrome header above the image:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
<div className="flex items-center gap-1.5 border-b border-slate-700 bg-slate-800 px-4 py-2.5">
|
||||||
|
<span className="h-2.5 w-2.5 rounded-full bg-red-500/70" />
|
||||||
|
<span className="h-2.5 w-2.5 rounded-full bg-yellow-500/70" />
|
||||||
|
<span className="h-2.5 w-2.5 rounded-full bg-green-500/70" />
|
||||||
|
<span className="ml-4 text-xs text-slate-500 font-mono">netork.local</span>
|
||||||
|
</div>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Code Block
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
<pre className="rounded-xl border border-slate-800 bg-slate-900 p-6
|
||||||
|
font-mono text-sm text-slate-300 overflow-x-auto">
|
||||||
|
<code>{`bash scripts/deploy.sh 192.168.1.1`}</code>
|
||||||
|
</pre>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Driver / Integration Badge
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
<span className="inline-flex items-center gap-1.5 px-3 py-1 rounded-full
|
||||||
|
border border-slate-700 bg-slate-900
|
||||||
|
text-xs font-medium text-slate-300">
|
||||||
|
OpenWRT
|
||||||
|
</span>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Section Divider
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
<div className="border-t border-slate-800" />
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Navigation
|
||||||
|
|
||||||
|
- Sticky top nav: `sticky top-0 z-10 bg-slate-900/80 backdrop-blur
|
||||||
|
border-b border-slate-800`
|
||||||
|
- Logo: left-aligned. Product name in `font-semibold text-slate-100`,
|
||||||
|
optionally prefixed with a small icon.
|
||||||
|
- Nav links: `text-sm text-slate-400 hover:text-slate-100 transition-colors`
|
||||||
|
- Active link: `text-slate-100`
|
||||||
|
- CTA in nav: small primary button `px-4 py-1.5 text-sm`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Animations & Transitions
|
||||||
|
|
||||||
|
- **Hover states:** always `transition-colors` (not `transition-all`).
|
||||||
|
- **No JavaScript animations** on initial page load — no entrance animations,
|
||||||
|
no scroll-triggered reveals via IntersectionObserver.
|
||||||
|
- Scroll behavior: `scroll-smooth` on `<html>` for anchor links.
|
||||||
|
- No parallax, no floating elements, no auto-playing videos.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Logo / Wordmark
|
||||||
|
|
||||||
|
The netOrk wordmark uses the following convention in the product:
|
||||||
|
- Lowercase `n`, uppercase `O`: **netOrk**
|
||||||
|
- Monospace context: `font-mono text-sky-400`
|
||||||
|
- Heading context: `font-bold text-slate-100` with `Ork` potentially in
|
||||||
|
`text-sky-400` if desired for emphasis
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Iconography
|
||||||
|
|
||||||
|
Use Heroicons (inline SVG). Sizes:
|
||||||
|
- Feature card icons: `h-5 w-5`
|
||||||
|
- Nav / button icons: `h-4 w-4`
|
||||||
|
- Hero / large decorative: `h-8 w-8` or `h-10 w-10`
|
||||||
|
|
||||||
|
All icons: `text-sky-400` in feature contexts, `text-slate-400` in
|
||||||
|
secondary/muted contexts.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## tailwind.config.js
|
||||||
|
|
||||||
|
No custom theme extensions needed. The default Tailwind v3 slate + sky
|
||||||
|
palette covers everything. The config only needs content paths:
|
||||||
|
|
||||||
|
```js
|
||||||
|
/** @type {import('tailwindcss').Config} */
|
||||||
|
export default {
|
||||||
|
content: ['./index.html', './src/**/*.{js,ts,jsx,tsx}'],
|
||||||
|
theme: {
|
||||||
|
extend: {},
|
||||||
|
},
|
||||||
|
plugins: [],
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|||||||
+321
-65
@@ -1,83 +1,339 @@
|
|||||||
# netOrk website — pages
|
# netOrk Website — Page Structure & Content Plan
|
||||||
|
|
||||||
**Audience:** IT departments in small and mid-sized companies — a small team,
|
This document defines every page of the website: its purpose, section
|
||||||
mixed hardware (OPNsense, HPE ProCurve/Aruba, TP-Link JetStream, OpenWrt,
|
structure, and draft copy. Use this as the brief for implementation.
|
||||||
Proxmox, Linux), NIS2 on the agenda. Service providers and IT support are
|
|
||||||
secondary and get their own page each.
|
|
||||||
|
|
||||||
**One message:** control instead of drift — define the desired state once;
|
---
|
||||||
netOrk notices every change, shows what deviates and puts it back.
|
|
||||||
|
|
||||||
**One goal:** buy a licence. netOrk itself is free; the licence adds
|
## Page Overview
|
||||||
vulnerability data and image updates.
|
|
||||||
|
|
||||||
All copy is in `src/i18n/translations.ts`, English and German (German uses
|
| Route | Page | Priority |
|
||||||
"ihr"). The language follows the browser until someone chooses. Every claim
|
|
||||||
must be backed by `docs/PRODUCT.md`; automatic fixing exists for access point
|
|
||||||
profiles, so the site says "every deviation", never "every device fixes itself".
|
|
||||||
|
|
||||||
## Word budgets (English, text in `<main>`)
|
|
||||||
|
|
||||||
`scripts/check/site.py` counts them; Home over budget fails the check.
|
|
||||||
|
|
||||||
| Page | Route | Budget |
|
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| Home | `/` | 400 |
|
| `/` | Landing (Home) | P0 — build first |
|
||||||
| Pricing | `/pricing` | 300 |
|
| `/features` | Full feature list | P1 |
|
||||||
| NIS2 | `/nis2` | 550 |
|
| `/drivers` | Supported devices | P1 |
|
||||||
| Plugins | `/plugins` | 450 |
|
| `/docs/getting-started` | Installation guide | P1 |
|
||||||
| Persona ×3 | `/for/it-department`, `/for/it-support`, `/for/msp` | 320 |
|
| `/docs/architecture` | Technical overview | P2 |
|
||||||
| Getting started | `/docs/getting-started` | 80 |
|
| `/plugins` | Plugin system | P2 |
|
||||||
| Glossary, Impressum, Datenschutz | `/glossary`, `/impressum`, `/datenschutz` | — |
|
|
||||||
|
|
||||||
Old routes redirect (in `App.tsx` and as 301 in `nginx.conf`): `/features` →
|
---
|
||||||
`/#included`, `/drivers` → `/#hardware`, `/roadmap` and `/docs/architecture` → `/`.
|
|
||||||
|
|
||||||
## Home
|
## `/` — Landing Page
|
||||||
|
|
||||||
1. **Hero** — "Control instead of drift." The drift comparison of an access
|
### Section 1 — Hero
|
||||||
point (`drift`, `drift-narrow` on phones) with a caption saying what is in it.
|
|
||||||
2. **How it works** (`#how`) — Define → Detect → Fix, three steps.
|
|
||||||
3. **Hardware** (`#hardware`) — two lines of names: "desired state and fixes"
|
|
||||||
and "inventory and monitoring"; a note on the untested NAPALM drivers.
|
|
||||||
4. **Vulnerabilities, with a licence** — the triage queue (`vulnerabilities`),
|
|
||||||
link to Pricing.
|
|
||||||
5. **Also in the box** (`#included`) — eight terms, one short line each; a NIS2
|
|
||||||
row with a link.
|
|
||||||
6. **Closing band** — "netOrk is free. The licence adds the data."
|
|
||||||
|
|
||||||
## Pricing
|
**Purpose:** Answer "what is this?" in 5 seconds.
|
||||||
|
|
||||||
The free core as one row, then Starter / Pro / Enterprise, each "on request"
|
**Layout:** Full-width, centered. Heading + subheading + two CTAs + hero
|
||||||
with a "Buy a licence" button to the licence portal (`src/data/plans.ts`). Plan
|
screenshot below.
|
||||||
differences come from the licence server's plan defaults; the KB request limit
|
|
||||||
stays off the page until it has a unit. Four questions below, and the note that
|
|
||||||
there is no public installer yet.
|
|
||||||
|
|
||||||
## Persona pages
|
**Heading:**
|
||||||
|
```
|
||||||
|
Network orchestration
|
||||||
|
for heterogeneous infrastructure.
|
||||||
|
```
|
||||||
|
(`text-slate-100` for first line, second line in `text-sky-400` or keep
|
||||||
|
both `text-slate-100` — designer decides.)
|
||||||
|
|
||||||
One template (`Persona.tsx`): header, three problems, five ways netOrk helps
|
**Subheading:**
|
||||||
(desired state and drift first), the shared closing band. The IT-department
|
```
|
||||||
page shows the drift screenshot. The service-provider page says where it
|
netOrk discovers, monitors, and manages your routers, switches, access
|
||||||
stops today.
|
points, firewalls, and servers from a single UI — regardless of vendor.
|
||||||
|
No SaaS dependency. Runs on your infrastructure.
|
||||||
|
```
|
||||||
|
|
||||||
## NIS2
|
**CTAs:**
|
||||||
|
- Primary: `Get started →` → `/docs/getting-started`
|
||||||
|
- Secondary: `View features` → `/features`
|
||||||
|
|
||||||
Article by article (eight rows plus one "out of scope"), a dot and a word for
|
**Hero visual:** Full-width screenshot of the device inventory page
|
||||||
coverage, what netOrk records along the way, the audit log screenshot. States
|
(dark UI visible, framed with the browser chrome component from DESIGN.md).
|
||||||
plainly that netOrk does not make anyone compliant.
|
|
||||||
|
|
||||||
## Plugins, Glossary, Getting started, Impressum, Datenschutz
|
---
|
||||||
|
|
||||||
Plugins: the five included ones with the hosts they talk to, how to write one,
|
### Section 2 — Problem Statement
|
||||||
one code example. Glossary: every term from `src/glossary/terms.ts` with a
|
|
||||||
category index. Getting started: "no public installer yet", write to us.
|
|
||||||
Impressum and Datenschutz: **placeholders** — the final text must replace the
|
|
||||||
yellow box before netork.io goes live.
|
|
||||||
|
|
||||||
## Navigation and footer
|
**Purpose:** Make the pain relatable.
|
||||||
|
|
||||||
Nav: wordmark · Who it's for ▾ · NIS2 · Plugins · Pricing · DE/EN · "Buy a
|
**Layout:** Single centered paragraph or short 3-column stat row.
|
||||||
licence". Below `lg` a menu button. Footer: product links, persona links,
|
|
||||||
contact, "no cookies, no tracking, no requests to anyone else", © line with
|
**Copy:**
|
||||||
Impressum and Datenschutz.
|
```
|
||||||
|
Managing a mixed network means juggling a different admin UI for every
|
||||||
|
vendor — one for OPNsense, one for HP ProCurve, one for OpenWRT, one for
|
||||||
|
Proxmox. Config changes happen directly on devices with no audit trail.
|
||||||
|
You find out something drifted when it breaks.
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Section 3 — Core Capabilities (3-up)
|
||||||
|
|
||||||
|
**Purpose:** Communicate the three main things netOrk does.
|
||||||
|
|
||||||
|
**Layout:** 3 columns, each with icon + heading + 2–3 sentences.
|
||||||
|
|
||||||
|
**Card 1 — Discover & Inventory**
|
||||||
|
- Icon: `MagnifyingGlassIcon`
|
||||||
|
- Heading: `Discover everything on your network`
|
||||||
|
- Copy: `ICMP sweep, SNMP scan, and HTTP probing find devices before you
|
||||||
|
add them. Fingerprinting identifies vendor and platform automatically.
|
||||||
|
Adopt results into your inventory with a single click.`
|
||||||
|
|
||||||
|
**Card 2 — Monitor & Alert**
|
||||||
|
- Icon: `ChartBarIcon` or `SignalIcon`
|
||||||
|
- Heading: `Poll device state continuously`
|
||||||
|
- Copy: `Every device is polled on a configurable interval via NAPALM.
|
||||||
|
Interface status, ARP tables, DHCP leases, VLAN membership, Docker
|
||||||
|
containers, and SNMP health metrics — all in one place.`
|
||||||
|
|
||||||
|
**Card 3 — Configure & Enforce**
|
||||||
|
- Icon: `WrenchScrewdriverIcon`
|
||||||
|
- Heading: `Detect drift. Fix it.`
|
||||||
|
- Copy: `Define desired state in netOrk. On every poll, device config is
|
||||||
|
compared against it. Drifted devices get a warning; a one-click fix
|
||||||
|
stream applies the correction and shows you live SSH output.`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Section 4 — Driver Grid
|
||||||
|
|
||||||
|
**Purpose:** Show breadth of vendor support.
|
||||||
|
|
||||||
|
**Layout:** Centered heading + wrapping badge grid.
|
||||||
|
|
||||||
|
**Heading:** `Works with your hardware`
|
||||||
|
|
||||||
|
**Subheading:**
|
||||||
|
```
|
||||||
|
netOrk ships with custom NAPALM drivers for 11 device types, plus all
|
||||||
|
built-in NAPALM drivers. New drivers follow a documented registration
|
||||||
|
pattern.
|
||||||
|
```
|
||||||
|
|
||||||
|
**Badge list** (see `docs/PRODUCT.md` — driver table):
|
||||||
|
OpenWRT, OPNsense, Proxmox VE, Linux, HP ProCurve / Aruba, TP-Link Jetstream,
|
||||||
|
Netgear, Fritz!Box, Zyxel, OpenMediaVault, Sonos,
|
||||||
|
Cisco IOS, Arista EOS, Juniper JunOS
|
||||||
|
|
||||||
|
Each badge uses the `Driver / Integration Badge` component from DESIGN.md.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Section 5 — Screenshot Walkthrough (alternating)
|
||||||
|
|
||||||
|
**Purpose:** Show the UI concretely. Three alternating image + text rows.
|
||||||
|
|
||||||
|
**Row 1 — Left text, right screenshot**
|
||||||
|
- Heading: `Device detail at a glance`
|
||||||
|
- Copy: `Hostname, IP, vendor, OS version, last poll time, and active
|
||||||
|
warnings on one card. Tabbed detail view for interfaces, LLDP neighbors,
|
||||||
|
ARP table, VLAN membership, packages, services, and scheduled jobs.`
|
||||||
|
- Screenshot: DeviceDetailPage
|
||||||
|
|
||||||
|
**Row 2 — Right text, left screenshot**
|
||||||
|
- Heading: `Intent-based VLAN and SSID management`
|
||||||
|
- Copy: `Define VLAN names and SSID settings once. netOrk compares them
|
||||||
|
against every polled device and pushes corrections automatically via
|
||||||
|
UCI (OpenWRT) or the device's native API.`
|
||||||
|
- Screenshot: VlansPage or WirelessPage
|
||||||
|
|
||||||
|
**Row 3 — Left text, right screenshot**
|
||||||
|
- Heading: `Security visibility per device`
|
||||||
|
- Copy: `Wazuh agent status, CVE counts by severity, and recent alerts
|
||||||
|
— all linked to the device record. One-click agent install if the
|
||||||
|
agent is missing. Graylog syslog forwarding status with auto-fix.`
|
||||||
|
- Screenshot: SecurityTab inside DeviceDetailPage
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Section 6 — Plugin System (brief)
|
||||||
|
|
||||||
|
**Purpose:** Signal extensibility without going deep.
|
||||||
|
|
||||||
|
**Layout:** Dark card, left-aligned.
|
||||||
|
|
||||||
|
**Heading:** `Built to extend`
|
||||||
|
|
||||||
|
**Copy:**
|
||||||
|
```
|
||||||
|
Integrations (Wazuh, Graylog, CrowdSec, apt-cacher-ng) are plugins
|
||||||
|
that register into the plugin system — they can be enabled or disabled
|
||||||
|
per deployment without code changes. Adding a new integration follows
|
||||||
|
a documented pattern with a hook bus, typed metadata, and a plugin
|
||||||
|
registry.
|
||||||
|
```
|
||||||
|
|
||||||
|
**CTA:** `Plugin system docs →` → `/plugins`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Section 7 — Deployment (quick)
|
||||||
|
|
||||||
|
**Purpose:** Answer "how do I run this?" without going into detail.
|
||||||
|
|
||||||
|
**Layout:** Code block + short description.
|
||||||
|
|
||||||
|
**Heading:** `Self-hosted. One command.`
|
||||||
|
|
||||||
|
**Copy:**
|
||||||
|
```
|
||||||
|
netOrk runs in Docker Compose. Five containers: API, two worker pools,
|
||||||
|
a Beat scheduler, and an nginx UI server. No external dependencies beyond
|
||||||
|
Redis and PostgreSQL.
|
||||||
|
```
|
||||||
|
|
||||||
|
**Code block:**
|
||||||
|
```bash
|
||||||
|
# Clone + configure
|
||||||
|
git clone https://gitea.example.com/netork/netork.git
|
||||||
|
cp .env.example .env
|
||||||
|
# edit .env (DB URL, Redis password, secret key)
|
||||||
|
|
||||||
|
# Deploy
|
||||||
|
bash scripts/deploy.sh 192.168.1.10
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Section 8 — CTA Footer
|
||||||
|
|
||||||
|
**Layout:** Centered, full-width dark section.
|
||||||
|
|
||||||
|
**Heading:** `Start managing your network.`
|
||||||
|
|
||||||
|
**CTA:** `Read the docs →` → `/docs/getting-started`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## `/features` — Full Feature List
|
||||||
|
|
||||||
|
**Purpose:** Comprehensive reference for people who want to evaluate in depth.
|
||||||
|
|
||||||
|
**Layout:** Vertical list of expandable sections (or just long-scroll with
|
||||||
|
sticky section nav). One section per capability area.
|
||||||
|
|
||||||
|
**Sections** (map directly to feature list in `docs/PRODUCT.md`):
|
||||||
|
1. Device Management
|
||||||
|
2. Discovery
|
||||||
|
3. Supported Drivers (full table)
|
||||||
|
4. Networking & Inventory
|
||||||
|
5. Configuration Management & Drift
|
||||||
|
6. Scheduled Operations
|
||||||
|
7. Monitoring & Health
|
||||||
|
8. Security Integrations
|
||||||
|
9. DNS Management
|
||||||
|
10. Access Control (RBAC)
|
||||||
|
11. NetBox Sync
|
||||||
|
12. Developer Experience
|
||||||
|
|
||||||
|
Each section: `text-xl font-semibold text-slate-200` heading +
|
||||||
|
feature items as a clean list with `text-slate-400` body.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## `/drivers` — Supported Devices
|
||||||
|
|
||||||
|
**Purpose:** One-page reference for "does netOrk support my device?"
|
||||||
|
|
||||||
|
**Layout:** Full table + short description per driver.
|
||||||
|
|
||||||
|
**Table columns:** Driver name | Device type | Capabilities | Status
|
||||||
|
|
||||||
|
**Capabilities** — checkmarks or tags for:
|
||||||
|
- `get_facts` `get_interfaces` `get_lldp` `get_vlans` `get_ssids`
|
||||||
|
`get_health_metrics` `get_docker` `scheduled_reboot` `config_push`
|
||||||
|
|
||||||
|
**Status:** `stable` / `beta` / `community` as a badge.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## `/docs/getting-started` — Installation
|
||||||
|
|
||||||
|
**Purpose:** Get someone from zero to a running instance.
|
||||||
|
|
||||||
|
**Sections:**
|
||||||
|
|
||||||
|
1. **Prerequisites**
|
||||||
|
- Docker + Docker Compose
|
||||||
|
- A PostgreSQL instance (or use the bundled profile)
|
||||||
|
- Redis
|
||||||
|
- A Linux host reachable by SSH from the server
|
||||||
|
|
||||||
|
2. **Quick start**
|
||||||
|
```bash
|
||||||
|
git clone ...
|
||||||
|
cp .env.example .env
|
||||||
|
# Edit .env
|
||||||
|
bash scripts/deploy.sh <server-ip>
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **First run**
|
||||||
|
- Navigate to `http://<server-ip>`
|
||||||
|
- Complete the setup wizard (creates admin user)
|
||||||
|
- Add your first device
|
||||||
|
|
||||||
|
4. **Adding a device**
|
||||||
|
- Fill in hostname/IP, driver, and credentials
|
||||||
|
- Click Poll to verify connectivity
|
||||||
|
- Set a poll interval for continuous monitoring
|
||||||
|
|
||||||
|
5. **Next steps**
|
||||||
|
- Configure NetBox sync
|
||||||
|
- Set up Wazuh integration
|
||||||
|
- Enable scheduled reboots for OpenWRT APs
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## `/docs/architecture` — Technical Overview
|
||||||
|
|
||||||
|
**Purpose:** Give engineers the mental model before they look at code.
|
||||||
|
|
||||||
|
**Content:** Essentially the one-paragraph summary from `docs/PRODUCT.md`
|
||||||
|
expanded into a readable overview with the architecture diagram (ASCII or SVG).
|
||||||
|
|
||||||
|
**Sections:**
|
||||||
|
1. Overview (request → FastAPI → DB / Celery worker)
|
||||||
|
2. Driver system (NAPALM + custom drivers + registry)
|
||||||
|
3. Task queues (which queue does what)
|
||||||
|
4. Plugin system (register → hook bus → router mount)
|
||||||
|
5. Data model (UUID PKs, JSONB snapshots, intent-vs-state)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## `/plugins` — Plugin System
|
||||||
|
|
||||||
|
**Purpose:** Explain extensibility to potential contributors.
|
||||||
|
|
||||||
|
**Sections:**
|
||||||
|
1. What is a plugin? (metadata, router, tasks, hooks)
|
||||||
|
2. Built-in plugins (Wazuh, Graylog, CrowdSec, apt-cacher)
|
||||||
|
3. Writing a plugin (step-by-step with code snippets)
|
||||||
|
4. Hook bus (fire / call / transform)
|
||||||
|
5. Plugin registry and enable/disable
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Global Layout
|
||||||
|
|
||||||
|
### Navigation (all pages)
|
||||||
|
|
||||||
|
```
|
||||||
|
[ netOrk ] Features Drivers Docs ▾ Plugins [ Get started ]
|
||||||
|
```
|
||||||
|
|
||||||
|
`Docs` is a dropdown: Getting Started / Architecture
|
||||||
|
|
||||||
|
### Footer
|
||||||
|
|
||||||
|
```
|
||||||
|
netOrk — self-hosted network orchestration
|
||||||
|
|
||||||
|
Links: Resources: Legal:
|
||||||
|
Features Getting Started MIT License
|
||||||
|
Drivers Architecture Privacy (none collected)
|
||||||
|
Plugins Changelog
|
||||||
|
```
|
||||||
|
|
||||||
|
Footer background: `bg-slate-900 border-t border-slate-800`
|
||||||
|
Footer text: `text-sm text-slate-500`
|
||||||
|
|||||||
+20
-234
@@ -1,22 +1,5 @@
|
|||||||
# netOrk — Product Description
|
# netOrk — Product Description
|
||||||
|
|
||||||
## Positioning (since 2026-09)
|
|
||||||
|
|
||||||
- **Message:** control instead of drift. Define once how the network should be
|
|
||||||
set up; netOrk notices every change on access points, switches and firewalls,
|
|
||||||
shows what deviates and puts it back. Automatic fixing exists for access point
|
|
||||||
profiles; firewall profiles are compared and applied on demand; switch VLANs
|
|
||||||
are provisioned centrally; every configuration change is versioned in Git and
|
|
||||||
flagged when netOrk did not make it.
|
|
||||||
- **Primary audience:** IT departments in small and mid-sized companies.
|
|
||||||
- **Licence model:** netOrk itself is free. A licence (Starter / Pro /
|
|
||||||
Enterprise, price on request, sold through the licence portal) adds
|
|
||||||
vulnerability data from the netOrk Knowledge Base and image updates. One key
|
|
||||||
per netOrk instance; no limits on devices, sites or users. Plan differences:
|
|
||||||
vulnerability history 90 days / 1 year / 10 years, match evidence and CWE
|
|
||||||
details from Pro, the edge update channel for Enterprise. Source:
|
|
||||||
license-server plan defaults, mirrored in `src/data/plans.ts`.
|
|
||||||
|
|
||||||
## One-liner
|
## One-liner
|
||||||
|
|
||||||
**netOrk is a self-hosted network orchestration platform that discovers,
|
**netOrk is a self-hosted network orchestration platform that discovers,
|
||||||
@@ -82,25 +65,6 @@ hardware and want operational visibility beyond what consumer dashboards offer.
|
|||||||
8. **Self-hosted, no SaaS** — Runs in Docker Compose. Your data stays on your
|
8. **Self-hosted, no SaaS** — Runs in Docker Compose. Your data stays on your
|
||||||
infrastructure. No telemetry, no cloud dependency.
|
infrastructure. No telemetry, no cloud dependency.
|
||||||
|
|
||||||
9. **NIS2 evidence foundation** — NIS2 Art. 21 mandates asset inventory, patch
|
|
||||||
management, access control, and audit trails. netOrk produces all of these as
|
|
||||||
day-to-day operational outputs: full device inventory, per-device update status,
|
|
||||||
Wazuh CVE tracking, EOL firmware/OS flagging, RBAC with MFA, Git-backed config
|
|
||||||
snapshots with diff/restore, config drift detection, and a complete audit log.
|
|
||||||
|
|
||||||
10. **Build your own view** — Configurable, shareable dashboards: pick from 13
|
|
||||||
widgets, arrange them on a WYSIWYG grid, and share the result with colleagues
|
|
||||||
who can subscribe to the live version or clone their own copy.
|
|
||||||
|
|
||||||
11. **From zero to managed in one flow** — Provision a Cloud-Init VM on a
|
|
||||||
Proxmox hypervisor, assign Ansible roles to configure it, and netOrk
|
|
||||||
auto-links it as a Device — no separate tools, no manual SSH-and-copy.
|
|
||||||
|
|
||||||
12. **Reach sites netOrk can't touch directly** — Deploy a lightweight
|
|
||||||
Satellite agent to poll devices locally at a disconnected or firewalled
|
|
||||||
site and sync results back over HTTPS; scheduled fixes route through it
|
|
||||||
the same way they do for directly reachable devices.
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Feature List
|
## Feature List
|
||||||
@@ -112,223 +76,64 @@ hardware and want operational visibility beyond what consumer dashboards offer.
|
|||||||
- Vendor/model/OS auto-populated from NAPALM `get_facts()`
|
- Vendor/model/OS auto-populated from NAPALM `get_facts()`
|
||||||
- Site assignment with FK to structured Site records
|
- Site assignment with FK to structured Site records
|
||||||
- AP Profile assignment for grouped OpenWRT config
|
- AP Profile assignment for grouped OpenWRT config
|
||||||
- Web SSH terminal: sessions log in with each user's own SSH key, never the
|
|
||||||
device's shared account; opened and refused sessions are recorded. Sessions
|
|
||||||
are movable, dockable windows that survive navigating away
|
|
||||||
- A device can hold several roles at once (e.g. storage + hypervisor + Linux)
|
|
||||||
- One device per address per site; duplicates are refused (VMs exempt)
|
|
||||||
- Business criticality per device and site, used in vulnerability ranking
|
|
||||||
|
|
||||||
### Discovery
|
### Discovery
|
||||||
- ICMP ping sweep, SNMP scan, HTTP/HTTPS probing
|
- ICMP ping sweep, SNMP scan, HTTP/HTTPS probing
|
||||||
- Device fingerprinting: vendor + platform confidence scoring
|
- Device fingerprinting: vendor + platform confidence scoring
|
||||||
- FQDN resolution (reverse DNS)
|
- FQDN resolution (reverse DNS)
|
||||||
- Manual adoption from scan results (no auto-create to avoid inventory noise)
|
- Manual adoption from scan results (no auto-create to avoid inventory noise)
|
||||||
- Discovery jobs in a sortable, filterable table, grouped per site
|
|
||||||
- LAN Scan: ping sweep from netOrk, each site satellite and every firewall;
|
|
||||||
live results with MAC and manufacturer; a finished scan becomes a discovery
|
|
||||||
job in one step
|
|
||||||
|
|
||||||
### VM Provisioning
|
|
||||||
- Cloud-Init based VM creation directly from a hypervisor's VMs tab — no
|
|
||||||
manual template or VMID setup
|
|
||||||
- Multi-distro image catalog: Debian 12, Ubuntu 22.04/24.04/26.04,
|
|
||||||
Fedora 42/43/44, with Ubuntu and Fedora releases synced automatically as
|
|
||||||
new versions ship
|
|
||||||
- Pick a target VLAN and an IP from its subnet — netOrk creates the DHCP
|
|
||||||
reservation automatically
|
|
||||||
- Cloud-init provisions a real Linux user with an SSH key, plus configurable
|
|
||||||
bootstrap toggles (SNMP, QEMU guest agent)
|
|
||||||
- Reusable provisioning templates for repeatable bootstrap settings
|
|
||||||
- The new VM is auto-linked as a netOrk Device and its hostname assigned to
|
|
||||||
a DNS zone once bootstrap finishes
|
|
||||||
- Deploy progress shown as a live step checklist in the UI
|
|
||||||
- Delete a VM and its linked netOrk Device together, gated behind a
|
|
||||||
name-confirmation prompt
|
|
||||||
|
|
||||||
### Supported Device Drivers
|
### Supported Device Drivers
|
||||||
Custom NAPALM drivers for all of the following:
|
Custom NAPALM drivers for all of the following:
|
||||||
|
|
||||||
| Driver | Device type |
|
| Driver | Device type |
|
||||||
|---|---|
|
|---|---|
|
||||||
| `fritzbox` | AVM Fritz!Box routers (read-only) |
|
| `openwrt` | OpenWRT access points |
|
||||||
| `hpe_officeconnect` | HPE OfficeConnect 1820 / 1920S switches |
|
|
||||||
| `linux` | Generic Linux servers |
|
|
||||||
| `netgear_plus` | Netgear Plus switches (web UI) |
|
|
||||||
| `netgear_smart` | Netgear Smart Managed Pro switches |
|
|
||||||
| `openmediavault` | OpenMediaVault NAS |
|
|
||||||
| `openwrt` | OpenWrt routers and access points |
|
|
||||||
| `opnsense` | OPNsense firewalls |
|
| `opnsense` | OPNsense firewalls |
|
||||||
| `procurve` | HPE ProCurve / Aruba switches |
|
|
||||||
| `proxmox` | Proxmox VE hypervisors |
|
| `proxmox` | Proxmox VE hypervisors |
|
||||||
| `qnap_qts` | QNAP NAS on QTS |
|
| `linux` | Generic Linux servers |
|
||||||
|
| `procurve` | HP ProCurve / Aruba switches |
|
||||||
|
| `tplink_jetstream` | TP-Link Jetstream managed switches |
|
||||||
|
| `netgear` | Netgear switches |
|
||||||
|
| `fritzbox` | AVM Fritz!Box routers |
|
||||||
|
| `zyxel` | Zyxel switches |
|
||||||
|
| `openmediavault` | OpenMediaVault NAS |
|
||||||
| `sonos` | Sonos speakers |
|
| `sonos` | Sonos speakers |
|
||||||
| `tplink_jetstream` | TP-Link JetStream managed switches |
|
|
||||||
| `yealink` | Yealink IP phones |
|
|
||||||
| `zyxel` | Zyxel VMG routers (not switches) |
|
|
||||||
|
|
||||||
The built-in NAPALM drivers (Cisco IOS/IOS-XE/NX-OS, Arista EOS, Juniper JunOS)
|
Plus all built-in NAPALM drivers: Cisco IOS/IOS-XE/NX-OS, Arista EOS, Juniper JunOS.
|
||||||
are installed but not tested with netOrk and get none of its driver-specific
|
|
||||||
features. Capability matrix (audited against v0.28.0): see `src/pages/Drivers.tsx`.
|
|
||||||
Reboot from netOrk actually restarts only OpenWrt and Proxmox.
|
|
||||||
|
|
||||||
### Networking & Inventory
|
### Networking & Inventory
|
||||||
- Interface browser with IPv4/IPv6 addresses, MAC, speed, MTU
|
- Interface browser with IPv4/IPv6 addresses, MAC, speed, MTU
|
||||||
- LLDP neighbor discovery and topology graph, plus links derived from switch
|
- LLDP neighbor discovery and topology graph
|
||||||
MAC tables (drawn dashed)
|
|
||||||
- Radio problems between the access points of a site are reported
|
|
||||||
- ARP table and DHCP lease browser per device
|
- ARP table and DHCP lease browser per device
|
||||||
- Subnet browser with interface-to-subnet assignments
|
- Subnet browser with interface-to-subnet assignments
|
||||||
- VLAN list grouped by site; per-VLAN device membership view
|
- VLAN list grouped by site; per-VLAN device membership view
|
||||||
- SSID management with push to OpenWRT APs via UCI
|
- SSID management with push to OpenWRT APs via UCI
|
||||||
- Per-SSID MAC access control lists (whitelist / blacklist) pushed to every
|
|
||||||
AP broadcasting the SSID, quick-add straight from the Connected Clients list
|
|
||||||
- MAC ACL state is a first-class drift item — covered by the same drift
|
|
||||||
detection, scheduled auto-fix, and warning aggregation as any other config
|
|
||||||
drift
|
|
||||||
- Dedicated Access Control Lists tab on the Wireless page listing every SSID
|
|
||||||
with its ACL editor inline
|
|
||||||
|
|
||||||
### Configuration Management
|
### Configuration Management
|
||||||
- Config drift detection: desired state (DB) vs device state (poll snapshot)
|
- Config drift detection: desired state (DB) vs device state (poll snapshot)
|
||||||
- One-click drift fix stream with live SSH output in the browser
|
- One-click drift fix stream with live SSH output in the browser
|
||||||
- UCI-based config push for OpenWRT (VLAN names, SSID settings, radio config)
|
- UCI-based config push for OpenWRT (VLAN names, SSID settings, radio config)
|
||||||
- AP profile system: country code, HT/VHT mode, 802.11r, NTP, syslog, SSH port
|
- AP profile system: country code, HT/VHT mode, 802.11r, NTP, syslog, SSH port
|
||||||
- Configuration backup & versioning: every poll captures a config snapshot into
|
|
||||||
a local Git repository, with full history and a side-by-side diff viewer
|
|
||||||
between any two points in time
|
|
||||||
- One-click config restore for OPNsense from any prior snapshot
|
|
||||||
- Unauthorised configuration changes are surfaced as a device warning
|
|
||||||
- netOrk's own config pushes (drift fixes, ACL provisioning) are recognized
|
|
||||||
and auto-accepted as the new baseline — never mistaken for an unauthorized
|
|
||||||
change
|
|
||||||
|
|
||||||
### Configuration Automation (Ansible)
|
|
||||||
- Reusable Ansible roles and playbooks stored and edited directly in
|
|
||||||
netOrk — no separate git checkout
|
|
||||||
- 16 built-in roles ready to assign: base, ubuntu, docker, adguard, zoraxy,
|
|
||||||
portainer, watchtower, uptime-kuma, vaultwarden, stalwart, bulwark, searxng,
|
|
||||||
postiz, listmonk, wireguard, fail2ban
|
|
||||||
- Roles state their resource needs; undersized hosts are refused with a reason
|
|
||||||
- Automatic dependency resolution — assigning `docker` pulls in `base`
|
|
||||||
automatically, no manual role ordering
|
|
||||||
- Built-in roles can't be deleted but are fully editable; customizations
|
|
||||||
survive upgrades, and only untouched files auto-heal on bugfixes
|
|
||||||
- `ansible-doc`-backed autocomplete while writing roles and playbooks
|
|
||||||
- Upload your own role as an archive
|
|
||||||
- Device-level role assignment with a dedicated Ansible tab on the device
|
|
||||||
detail page
|
|
||||||
- Run history per device, snapshotting the exact role/playbook content
|
|
||||||
that was executed
|
|
||||||
- Wired into VM provisioning: assign roles at VM-creation time and they
|
|
||||||
run automatically after boot
|
|
||||||
|
|
||||||
### Scheduled Operations
|
### Scheduled Operations
|
||||||
- Scheduled reboots for OpenWRT APs with per-site concurrency lock
|
- Scheduled reboots for OpenWRT APs with per-site concurrency lock
|
||||||
- Failback cron script written to device for netOrk-unreachable scenarios
|
- Failback cron script written to device for netOrk-unreachable scenarios
|
||||||
- Scheduled config drift fixes with time-window enforcement
|
- Scheduled config drift fixes with time-window enforcement
|
||||||
- Package update scheduling and one-click apply
|
- Package update scheduling and one-click apply
|
||||||
- Wake-on-LAN via a firewall's driver (OPNsense today) — saved WOL targets
|
|
||||||
with on-demand "Wake now" and recurring schedules; save a seen host as a
|
|
||||||
target directly from the DHCP/ARP tabs
|
|
||||||
|
|
||||||
### Satellite Deployments
|
|
||||||
- Lightweight Docker agent deployed at a site netOrk can't reach directly —
|
|
||||||
polls devices locally and syncs results back to Central over HTTPS
|
|
||||||
- Deployed in one flow via VM provisioning: pick a hypervisor and site,
|
|
||||||
netOrk provisions the VM and installs the satellite container automatically
|
|
||||||
- Central automatically skips direct polling for any device at a site with
|
|
||||||
an online, heartbeating satellite — no manual per-site toggling
|
|
||||||
- Scheduled/on-demand reboots and the SNMP auto-fix flow run through the
|
|
||||||
same command channel whether a device is directly reachable or behind a
|
|
||||||
satellite
|
|
||||||
- Discovery jobs at a satellite-covered site scan locally through the same
|
|
||||||
command channel, instead of failing to reach the subnet from Central
|
|
||||||
- Not yet satellite-covered: SNMP health-metric polling still runs from
|
|
||||||
Central, and WebSSH console access isn't available through a satellite
|
|
||||||
|
|
||||||
### Monitoring & Health
|
### Monitoring & Health
|
||||||
- SNMP health metrics (CPU, memory, interface counters) via `get_health_metrics()`
|
- SNMP health metrics (CPU, memory, interface counters) via `get_health_metrics()`
|
||||||
- Per-device warning system with severity levels (error / warning / info)
|
- Per-device warning system with severity levels (error / warning / info)
|
||||||
- One-click Ack on any warning — clears it immediately and writes an audit log
|
- Docker container and image status (Proxmox/Linux)
|
||||||
entry; for config-change warnings the current state is accepted as the new
|
|
||||||
baseline
|
|
||||||
- Docker container and image status (Linux, OpenMediaVault, QNAP)
|
|
||||||
- Service status and start/stop/restart (systemd)
|
- Service status and start/stop/restart (systemd)
|
||||||
- VM/container list with OS device cross-linking (Proxmox)
|
- VM/container list with OS device cross-linking (Proxmox)
|
||||||
- Per-device availability windows — suppress OFFLINE status and poll-failure
|
|
||||||
warnings during expected downtime (e.g. a nightly power-off); opt-in,
|
|
||||||
unconfigured devices are unaffected
|
|
||||||
- OPNsense: BGP neighbor status polling and display, with a peer-down warning
|
|
||||||
- OPNsense: TLS certificate monitoring for the Trust store, with
|
|
||||||
expiring-soon / expired warnings
|
|
||||||
- OPNsense: Dynamic DNS service-down warning (os-ddclient)
|
|
||||||
- Service checks about once a minute (DNS, NTP, VPN tunnels, core daemons,
|
|
||||||
gateways), derived automatically; three failures before an alert; can run
|
|
||||||
from satellites, including a DHCP check
|
|
||||||
- Site reachability: polling pauses behind a dead tunnel, one warning names
|
|
||||||
it, everything is re-polled when it returns
|
|
||||||
|
|
||||||
### Dashboards
|
|
||||||
- Configurable, shareable dashboards — build your own from a widget picker
|
|
||||||
instead of a fixed layout
|
|
||||||
- WYSIWYG grid-layout editor: drag, resize, and arrange widgets on a canvas
|
|
||||||
- 18 widget types: stats, device warnings, recently updated devices, network
|
|
||||||
topology, EOL status, config drift summary, Wazuh security alerts, audit log
|
|
||||||
activity, discovery jobs status, upcoming scheduled actions, DNS zones
|
|
||||||
overview, site overview, config snapshot history, managed services,
|
|
||||||
certificate expiry, outdated Docker images, firewall profile deployment
|
|
||||||
status, service checks
|
|
||||||
- Multi-instance widgets with independent per-widget settings
|
|
||||||
- Share a dashboard with specific users; recipients can subscribe to the
|
|
||||||
owner's live version or clone it into their own editable copy
|
|
||||||
- Favorite dashboards for quick access from the main menu; set any dashboard
|
|
||||||
as your home view
|
|
||||||
|
|
||||||
### Notifications
|
|
||||||
- Signal messages for everything netOrk watches; each person registers their
|
|
||||||
own number, administrators pair netOrk once via QR code
|
|
||||||
- One message per site outage, daily summary for recurring items, hourly
|
|
||||||
bundling, quiet hours per number, mute per kind, full history with reasons
|
|
||||||
|
|
||||||
### DHCP
|
|
||||||
- DHCP reservations: import from the firewall, validated, diff, then apply
|
|
||||||
(adds and updates only)
|
|
||||||
- DHCP subnets (Kea on OPNsense) with options and search domains; settings
|
|
||||||
that break a network are refused
|
|
||||||
|
|
||||||
### Managed Services
|
|
||||||
- Every container-based service across devices with endpoints, TLS
|
|
||||||
certificates and access rules
|
|
||||||
- Compose editor with masked secrets and automatic backup snapshot; redeploy
|
|
||||||
is a separate confirmed step
|
|
||||||
- Zoraxy vhosts editable and written back; PostgreSQL databases listed
|
|
||||||
|
|
||||||
### Security Assessment
|
|
||||||
- Security tab per device: TLS/SSH grades A–F, installed software and
|
|
||||||
container images matched against known vulnerabilities, hardening benchmarks
|
|
||||||
- Ratings adjusted to the device (local access, trusted network, not running,
|
|
||||||
not booted kernel; raised when exploited in the wild)
|
|
||||||
- Kernel reboot recommendation with the vulnerabilities it would clear
|
|
||||||
- Exposure from firewall rules; internet-visible ports and abuse reports for
|
|
||||||
own public addresses; on-demand hardening audit and web scan
|
|
||||||
- Vulnerability data from the netOrk Knowledge Base (licence required)
|
|
||||||
|
|
||||||
### Vulnerability Management
|
|
||||||
- Triage queue across all devices, one row per vulnerability, ordered by
|
|
||||||
remediation deadline, exploitation, severity, likelihood, criticality, spread
|
|
||||||
- Decisions (not applicable / accept until / defer until / fixed) with a
|
|
||||||
mandatory reason; accept and not-applicable need an elevated permission
|
|
||||||
- Deferred and accepted items return by themselves; ignored ones go overdue
|
|
||||||
- Daily reassessment verifies fixes and reopens regressions
|
|
||||||
|
|
||||||
### Security Integrations (plugins)
|
### Security Integrations (plugins)
|
||||||
- **Wazuh** — agent enrollment tracking, vulnerability counts (by severity),
|
- **Wazuh** — agent enrollment tracking, vulnerability counts (by severity),
|
||||||
recent alert history, CIS benchmark scores, one-click agent install fix stream
|
recent alert history, CIS benchmark scores, one-click agent install fix stream
|
||||||
- **Graylog** — rsyslog forwarding status per device, one-click fix to write rule
|
- **Graylog** — rsyslog forwarding status per device, one-click fix to write rule
|
||||||
- **CrowdSec** — org-level decisions, remediation metrics, top attack scenarios
|
- **CrowdSec** — org-level decisions, remediation metrics, top attack scenarios
|
||||||
- **EOL Tracking** — flags devices running end-of-life or soon-to-be-end-of-life
|
|
||||||
firmware/OS via the endoflife.date API, checked daily
|
|
||||||
|
|
||||||
### DNS
|
### DNS
|
||||||
- DNS zone management with authoritative device assignment
|
- DNS zone management with authoritative device assignment
|
||||||
@@ -336,26 +141,11 @@ Reboot from netOrk actually restarts only OpenWrt and Proxmox.
|
|||||||
- PTR record provisioning to reverse zones
|
- PTR record provisioning to reverse zones
|
||||||
- Pending job queue for zone changes when device is unreachable
|
- Pending job queue for zone changes when device is unreachable
|
||||||
|
|
||||||
### RADIUS Management
|
|
||||||
- Global FreeRADIUS server, NAS client, and user management — no site
|
|
||||||
scoping, usable from any site's SSIDs/APs
|
|
||||||
- Changes push to the device via the driver and are only stored after the
|
|
||||||
device confirms — avoids drift between netOrk's view and the actual
|
|
||||||
FreeRADIUS config
|
|
||||||
- Dedicated server list and detail page (NAS clients / users tabs) under
|
|
||||||
the Wireless section
|
|
||||||
- SSID 802.1X integration (auto-provisioning a NAS client from an SSID's
|
|
||||||
RADIUS server) is a deliberate follow-up, not included yet
|
|
||||||
|
|
||||||
### Access Control
|
### Access Control
|
||||||
- JWT authentication with remember-me (localStorage) or session-only (sessionStorage)
|
- JWT authentication with remember-me (localStorage) or session-only (sessionStorage)
|
||||||
- Two-factor authentication (MFA/TOTP) — authenticator app at login, backup
|
|
||||||
codes for emergencies, session invalidation on TOTP changes, enforceable
|
|
||||||
per role
|
|
||||||
- RBAC with four built-in roles: viewer / operator / engineer / administrator
|
- RBAC with four built-in roles: viewer / operator / engineer / administrator
|
||||||
- Custom roles with any permission combination
|
- Custom roles with any permission combination
|
||||||
- Full audit log of all orchestration actions, filterable by date range,
|
- Full audit log of all orchestration actions
|
||||||
user, action, or resource — export to CSV or PDF
|
|
||||||
|
|
||||||
### NetBox Sync
|
### NetBox Sync
|
||||||
- Pushes vendor, model, OS version, status to NetBox dcim.devices
|
- Pushes vendor, model, OS version, status to NetBox dcim.devices
|
||||||
@@ -373,15 +163,11 @@ Reboot from netOrk actually restarts only OpenWrt and Proxmox.
|
|||||||
|
|
||||||
## Architecture in One Paragraph
|
## Architecture in One Paragraph
|
||||||
|
|
||||||
netOrk runs as a set of Docker containers: a FastAPI API server, three Celery
|
netOrk runs as five Docker containers: a FastAPI API server, two Celery worker
|
||||||
worker pools (general, poll, and Ansible), a Celery Beat scheduler, and an
|
pools (general + poll), a Celery Beat scheduler, and an nginx UI server. Redis
|
||||||
nginx UI server. Redis is the broker. PostgreSQL stores all state. Device
|
is the broker. PostgreSQL stores all state. Device communication is always
|
||||||
communication is always blocking I/O executed in Celery workers — FastAPI
|
blocking I/O executed in Celery workers — FastAPI request handlers are
|
||||||
request handlers are async-only for DB and quick operations. Custom NAPALM
|
async-only for DB and quick operations. Custom NAPALM drivers live in `vendor/`
|
||||||
drivers live in `vendor/` as editable packages and self-register via
|
as editable packages and self-register via `@register_driver`. The plugin system
|
||||||
`@register_driver`. The plugin system (`netork/plugins/`) provides a hook bus,
|
(`netork/plugins/`) provides a hook bus, a plugin registry with enable/disable
|
||||||
a plugin registry with enable/disable state in the DB, and a documented
|
state in the DB, and a documented pattern for adding integrations.
|
||||||
pattern for adding integrations. For sites Central can't reach directly, a
|
|
||||||
separate Satellite container polls devices locally and syncs results back
|
|
||||||
over HTTPS; Central dispatches actions (reboots, SNMP fixes) to it through a
|
|
||||||
generic command channel, transparently to the UI.
|
|
||||||
|
|||||||
+5
-6
@@ -1,15 +1,14 @@
|
|||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html lang="de" class="motion-safe:scroll-smooth">
|
<html lang="en" class="scroll-smooth">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<meta name="theme-color" content="#FAFAF9" />
|
<meta name="description" content="netOrk — self-hosted network orchestration for heterogeneous infrastructure. Discover, monitor, and manage routers, switches, firewalls, and servers from a single UI." />
|
||||||
<meta name="description" content="netOrk: define once how your network should be set up. It notices every change on access points, switches and firewalls, shows what deviates and puts it back. Self-hosted, across vendors." />
|
<title>netOrk — Network Orchestration Platform</title>
|
||||||
<title>netOrk — Control instead of drift</title>
|
|
||||||
<link rel="icon" href="/logo.png" />
|
<link rel="icon" href="/logo.png" />
|
||||||
<meta property="og:image" content="/logo.png" />
|
<meta property="og:image" content="/logo.png" />
|
||||||
<meta property="og:title" content="netOrk — Control instead of drift" />
|
<meta property="og:title" content="netOrk — Network Orchestration Platform" />
|
||||||
<meta property="og:description" content="Self-hosted network automation for IT teams: one desired state, every deviation found and fixed." />
|
<meta property="og:description" content="Self-hosted network orchestration for heterogeneous infrastructure." />
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="root"></div>
|
<div id="root"></div>
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
# Memory Index
|
||||||
|
|
||||||
|
- [Project Setup](project-setup.md) — netork-website is a Vite/React/TS/Tailwind SPA served via nginx in Docker, behind Zoraxy reverse proxy on proxy-net
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
---
|
||||||
|
name: project-setup
|
||||||
|
description: Tech stack, Docker setup, and deployment model for the netork-website project
|
||||||
|
metadata:
|
||||||
|
type: project
|
||||||
|
---
|
||||||
|
|
||||||
|
React 18 + TypeScript + Vite + Tailwind CSS v3 SPA. Heroicons via @heroicons/react (renders inline SVG).
|
||||||
|
|
||||||
|
**Docker:** Multi-stage Dockerfile (node:20-alpine build → nginx:alpine serve). nginx.conf handles SPA routing via try_files + gzip + immutable cache headers.
|
||||||
|
|
||||||
|
**docker-compose.yml:** Service `netork-website`, `expose: ["80"]` only (no host port binding), joins `proxy-net` (external network). SSL terminated by Zoraxy which proxies to `netork-website:80` on proxy-net.
|
||||||
|
|
||||||
|
**Why:** Zoraxy is the reverse proxy on the same Docker network; no host port needed.
|
||||||
|
|
||||||
|
**How to apply:** When adding/changing the Docker setup, keep no host port binding. Zoraxy target is `netork-website:80`.
|
||||||
|
|
||||||
|
**Pages built:** `/` (Home, all 8 sections with mock UI), `/features`, `/drivers`, `/docs/getting-started`. Remaining P2 pages (`/docs/architecture`, `/plugins`) not yet built.
|
||||||
|
|
||||||
|
**Screenshots:** `public/screenshots/` exists but is empty. Home page uses mock UI components instead of real screenshots until actual screenshots are dropped in.
|
||||||
|
|
||||||
|
**Logo:** `public/logo.png` must be placed manually — referenced in nav, footer, favicon, OG image.
|
||||||
-10
@@ -9,16 +9,6 @@ server {
|
|||||||
gzip_min_length 1024;
|
gzip_min_length 1024;
|
||||||
gzip_vary on;
|
gzip_vary on;
|
||||||
|
|
||||||
# Relative Location headers: TLS ends at Zoraxy, so an absolute redirect
|
|
||||||
# built here would point at http://.
|
|
||||||
absolute_redirect off;
|
|
||||||
|
|
||||||
# Pages folded into the homepage (see App.tsx for the same list client-side).
|
|
||||||
location = /features { return 301 /#included; }
|
|
||||||
location = /drivers { return 301 /#hardware; }
|
|
||||||
location = /roadmap { return 301 /; }
|
|
||||||
location = /docs/architecture { return 301 /; }
|
|
||||||
|
|
||||||
# SPA fallback — all routes resolve to index.html
|
# SPA fallback — all routes resolve to index.html
|
||||||
location / {
|
location / {
|
||||||
try_files $uri $uri/ /index.html;
|
try_files $uri $uri/ /index.html;
|
||||||
|
|||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
../autoprefixer/bin/autoprefixer
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
../baseline-browser-mapping/dist/cli.cjs
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
../browserslist/cli.js
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
../cssesc/bin/cssesc
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
../esbuild/bin/esbuild
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
../jiti/bin/jiti.js
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
../jsesc/bin/jsesc
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
../json5/lib/cli.js
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
../loose-envify/cli.js
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
../nanoid/bin/nanoid.cjs
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
../@babel/parser/bin/babel-parser.js
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
../resolve/bin/resolve
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
../rollup/dist/bin/rollup
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
../semver/bin/semver.js
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
../sucrase/bin/sucrase
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
../sucrase/bin/sucrase-node
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
../tailwindcss/lib/cli.js
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
../tailwindcss/lib/cli.js
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
../typescript/bin/tsc
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
../typescript/bin/tsserver
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
../update-browserslist-db/cli.js
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
../vite/bin/vite.js
|
||||||
+1990
File diff suppressed because it is too large
Load Diff
+128
@@ -0,0 +1,128 @@
|
|||||||
|
declare namespace QuickLRU {
|
||||||
|
interface Options<KeyType, ValueType> {
|
||||||
|
/**
|
||||||
|
The maximum number of milliseconds an item should remain in the cache.
|
||||||
|
|
||||||
|
@default Infinity
|
||||||
|
|
||||||
|
By default, `maxAge` will be `Infinity`, which means that items will never expire.
|
||||||
|
Lazy expiration upon the next write or read call.
|
||||||
|
|
||||||
|
Individual expiration of an item can be specified by the `set(key, value, maxAge)` method.
|
||||||
|
*/
|
||||||
|
readonly maxAge?: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
The maximum number of items before evicting the least recently used items.
|
||||||
|
*/
|
||||||
|
readonly maxSize: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Called right before an item is evicted from the cache.
|
||||||
|
|
||||||
|
Useful for side effects or for items like object URLs that need explicit cleanup (`revokeObjectURL`).
|
||||||
|
*/
|
||||||
|
onEviction?: (key: KeyType, value: ValueType) => void;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
declare class QuickLRU<KeyType, ValueType>
|
||||||
|
implements Iterable<[KeyType, ValueType]> {
|
||||||
|
/**
|
||||||
|
The stored item count.
|
||||||
|
*/
|
||||||
|
readonly size: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Simple ["Least Recently Used" (LRU) cache](https://en.m.wikipedia.org/wiki/Cache_replacement_policies#Least_Recently_Used_.28LRU.29).
|
||||||
|
|
||||||
|
The instance is [`iterable`](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Iteration_protocols) so you can use it directly in a [`for…of`](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Statements/for...of) loop.
|
||||||
|
|
||||||
|
@example
|
||||||
|
```
|
||||||
|
import QuickLRU = require('quick-lru');
|
||||||
|
|
||||||
|
const lru = new QuickLRU({maxSize: 1000});
|
||||||
|
|
||||||
|
lru.set('🦄', '🌈');
|
||||||
|
|
||||||
|
lru.has('🦄');
|
||||||
|
//=> true
|
||||||
|
|
||||||
|
lru.get('🦄');
|
||||||
|
//=> '🌈'
|
||||||
|
```
|
||||||
|
*/
|
||||||
|
constructor(options: QuickLRU.Options<KeyType, ValueType>);
|
||||||
|
|
||||||
|
[Symbol.iterator](): IterableIterator<[KeyType, ValueType]>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Set an item. Returns the instance.
|
||||||
|
|
||||||
|
Individual expiration of an item can be specified with the `maxAge` option. If not specified, the global `maxAge` value will be used in case it is specified in the constructor, otherwise the item will never expire.
|
||||||
|
|
||||||
|
@returns The list instance.
|
||||||
|
*/
|
||||||
|
set(key: KeyType, value: ValueType, options?: {maxAge?: number}): this;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Get an item.
|
||||||
|
|
||||||
|
@returns The stored item or `undefined`.
|
||||||
|
*/
|
||||||
|
get(key: KeyType): ValueType | undefined;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Check if an item exists.
|
||||||
|
*/
|
||||||
|
has(key: KeyType): boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Get an item without marking it as recently used.
|
||||||
|
|
||||||
|
@returns The stored item or `undefined`.
|
||||||
|
*/
|
||||||
|
peek(key: KeyType): ValueType | undefined;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Delete an item.
|
||||||
|
|
||||||
|
@returns `true` if the item is removed or `false` if the item doesn't exist.
|
||||||
|
*/
|
||||||
|
delete(key: KeyType): boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Delete all items.
|
||||||
|
*/
|
||||||
|
clear(): void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Update the `maxSize` in-place, discarding items as necessary. Insertion order is mostly preserved, though this is not a strong guarantee.
|
||||||
|
|
||||||
|
Useful for on-the-fly tuning of cache sizes in live systems.
|
||||||
|
*/
|
||||||
|
resize(maxSize: number): void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Iterable for all the keys.
|
||||||
|
*/
|
||||||
|
keys(): IterableIterator<KeyType>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Iterable for all the values.
|
||||||
|
*/
|
||||||
|
values(): IterableIterator<ValueType>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Iterable for all entries, starting with the oldest (ascending in recency).
|
||||||
|
*/
|
||||||
|
entriesAscending(): IterableIterator<[KeyType, ValueType]>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Iterable for all entries, starting with the newest (descending in recency).
|
||||||
|
*/
|
||||||
|
entriesDescending(): IterableIterator<[KeyType, ValueType]>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export = QuickLRU;
|
||||||
+263
@@ -0,0 +1,263 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
class QuickLRU {
|
||||||
|
constructor(options = {}) {
|
||||||
|
if (!(options.maxSize && options.maxSize > 0)) {
|
||||||
|
throw new TypeError('`maxSize` must be a number greater than 0');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof options.maxAge === 'number' && options.maxAge === 0) {
|
||||||
|
throw new TypeError('`maxAge` must be a number greater than 0');
|
||||||
|
}
|
||||||
|
|
||||||
|
this.maxSize = options.maxSize;
|
||||||
|
this.maxAge = options.maxAge || Infinity;
|
||||||
|
this.onEviction = options.onEviction;
|
||||||
|
this.cache = new Map();
|
||||||
|
this.oldCache = new Map();
|
||||||
|
this._size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
_emitEvictions(cache) {
|
||||||
|
if (typeof this.onEviction !== 'function') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const [key, item] of cache) {
|
||||||
|
this.onEviction(key, item.value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_deleteIfExpired(key, item) {
|
||||||
|
if (typeof item.expiry === 'number' && item.expiry <= Date.now()) {
|
||||||
|
if (typeof this.onEviction === 'function') {
|
||||||
|
this.onEviction(key, item.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.delete(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
_getOrDeleteIfExpired(key, item) {
|
||||||
|
const deleted = this._deleteIfExpired(key, item);
|
||||||
|
if (deleted === false) {
|
||||||
|
return item.value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_getItemValue(key, item) {
|
||||||
|
return item.expiry ? this._getOrDeleteIfExpired(key, item) : item.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
_peek(key, cache) {
|
||||||
|
const item = cache.get(key);
|
||||||
|
|
||||||
|
return this._getItemValue(key, item);
|
||||||
|
}
|
||||||
|
|
||||||
|
_set(key, value) {
|
||||||
|
this.cache.set(key, value);
|
||||||
|
this._size++;
|
||||||
|
|
||||||
|
if (this._size >= this.maxSize) {
|
||||||
|
this._size = 0;
|
||||||
|
this._emitEvictions(this.oldCache);
|
||||||
|
this.oldCache = this.cache;
|
||||||
|
this.cache = new Map();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_moveToRecent(key, item) {
|
||||||
|
this.oldCache.delete(key);
|
||||||
|
this._set(key, item);
|
||||||
|
}
|
||||||
|
|
||||||
|
* _entriesAscending() {
|
||||||
|
for (const item of this.oldCache) {
|
||||||
|
const [key, value] = item;
|
||||||
|
if (!this.cache.has(key)) {
|
||||||
|
const deleted = this._deleteIfExpired(key, value);
|
||||||
|
if (deleted === false) {
|
||||||
|
yield item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const item of this.cache) {
|
||||||
|
const [key, value] = item;
|
||||||
|
const deleted = this._deleteIfExpired(key, value);
|
||||||
|
if (deleted === false) {
|
||||||
|
yield item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
get(key) {
|
||||||
|
if (this.cache.has(key)) {
|
||||||
|
const item = this.cache.get(key);
|
||||||
|
|
||||||
|
return this._getItemValue(key, item);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.oldCache.has(key)) {
|
||||||
|
const item = this.oldCache.get(key);
|
||||||
|
if (this._deleteIfExpired(key, item) === false) {
|
||||||
|
this._moveToRecent(key, item);
|
||||||
|
return item.value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
set(key, value, {maxAge = this.maxAge === Infinity ? undefined : Date.now() + this.maxAge} = {}) {
|
||||||
|
if (this.cache.has(key)) {
|
||||||
|
this.cache.set(key, {
|
||||||
|
value,
|
||||||
|
maxAge
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this._set(key, {value, expiry: maxAge});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
has(key) {
|
||||||
|
if (this.cache.has(key)) {
|
||||||
|
return !this._deleteIfExpired(key, this.cache.get(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.oldCache.has(key)) {
|
||||||
|
return !this._deleteIfExpired(key, this.oldCache.get(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
peek(key) {
|
||||||
|
if (this.cache.has(key)) {
|
||||||
|
return this._peek(key, this.cache);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.oldCache.has(key)) {
|
||||||
|
return this._peek(key, this.oldCache);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
delete(key) {
|
||||||
|
const deleted = this.cache.delete(key);
|
||||||
|
if (deleted) {
|
||||||
|
this._size--;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.oldCache.delete(key) || deleted;
|
||||||
|
}
|
||||||
|
|
||||||
|
clear() {
|
||||||
|
this.cache.clear();
|
||||||
|
this.oldCache.clear();
|
||||||
|
this._size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
resize(newSize) {
|
||||||
|
if (!(newSize && newSize > 0)) {
|
||||||
|
throw new TypeError('`maxSize` must be a number greater than 0');
|
||||||
|
}
|
||||||
|
|
||||||
|
const items = [...this._entriesAscending()];
|
||||||
|
const removeCount = items.length - newSize;
|
||||||
|
if (removeCount < 0) {
|
||||||
|
this.cache = new Map(items);
|
||||||
|
this.oldCache = new Map();
|
||||||
|
this._size = items.length;
|
||||||
|
} else {
|
||||||
|
if (removeCount > 0) {
|
||||||
|
this._emitEvictions(items.slice(0, removeCount));
|
||||||
|
}
|
||||||
|
|
||||||
|
this.oldCache = new Map(items.slice(removeCount));
|
||||||
|
this.cache = new Map();
|
||||||
|
this._size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.maxSize = newSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
* keys() {
|
||||||
|
for (const [key] of this) {
|
||||||
|
yield key;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
* values() {
|
||||||
|
for (const [, value] of this) {
|
||||||
|
yield value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
* [Symbol.iterator]() {
|
||||||
|
for (const item of this.cache) {
|
||||||
|
const [key, value] = item;
|
||||||
|
const deleted = this._deleteIfExpired(key, value);
|
||||||
|
if (deleted === false) {
|
||||||
|
yield [key, value.value];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const item of this.oldCache) {
|
||||||
|
const [key, value] = item;
|
||||||
|
if (!this.cache.has(key)) {
|
||||||
|
const deleted = this._deleteIfExpired(key, value);
|
||||||
|
if (deleted === false) {
|
||||||
|
yield [key, value.value];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
* entriesDescending() {
|
||||||
|
let items = [...this.cache];
|
||||||
|
for (let i = items.length - 1; i >= 0; --i) {
|
||||||
|
const item = items[i];
|
||||||
|
const [key, value] = item;
|
||||||
|
const deleted = this._deleteIfExpired(key, value);
|
||||||
|
if (deleted === false) {
|
||||||
|
yield [key, value.value];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
items = [...this.oldCache];
|
||||||
|
for (let i = items.length - 1; i >= 0; --i) {
|
||||||
|
const item = items[i];
|
||||||
|
const [key, value] = item;
|
||||||
|
if (!this.cache.has(key)) {
|
||||||
|
const deleted = this._deleteIfExpired(key, value);
|
||||||
|
if (deleted === false) {
|
||||||
|
yield [key, value.value];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
* entriesAscending() {
|
||||||
|
for (const [key, value] of this._entriesAscending()) {
|
||||||
|
yield [key, value.value];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
get size() {
|
||||||
|
if (!this._size) {
|
||||||
|
return this.oldCache.size;
|
||||||
|
}
|
||||||
|
|
||||||
|
let oldCacheSize = 0;
|
||||||
|
for (const key of this.oldCache.keys()) {
|
||||||
|
if (!this.cache.has(key)) {
|
||||||
|
oldCacheSize++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Math.min(this._size + oldCacheSize, this.maxSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = QuickLRU;
|
||||||
+9
@@ -0,0 +1,9 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
+43
@@ -0,0 +1,43 @@
|
|||||||
|
{
|
||||||
|
"name": "@alloc/quick-lru",
|
||||||
|
"version": "5.2.0",
|
||||||
|
"description": "Simple “Least Recently Used” (LRU) cache",
|
||||||
|
"license": "MIT",
|
||||||
|
"repository": "sindresorhus/quick-lru",
|
||||||
|
"funding": "https://github.com/sponsors/sindresorhus",
|
||||||
|
"author": {
|
||||||
|
"name": "Sindre Sorhus",
|
||||||
|
"email": "sindresorhus@gmail.com",
|
||||||
|
"url": "https://sindresorhus.com"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"test": "xo && nyc ava && tsd"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"index.js",
|
||||||
|
"index.d.ts"
|
||||||
|
],
|
||||||
|
"keywords": [
|
||||||
|
"lru",
|
||||||
|
"quick",
|
||||||
|
"cache",
|
||||||
|
"caching",
|
||||||
|
"least",
|
||||||
|
"recently",
|
||||||
|
"used",
|
||||||
|
"fast",
|
||||||
|
"map",
|
||||||
|
"hash",
|
||||||
|
"buffer"
|
||||||
|
],
|
||||||
|
"devDependencies": {
|
||||||
|
"ava": "^2.0.0",
|
||||||
|
"coveralls": "^3.0.3",
|
||||||
|
"nyc": "^15.0.0",
|
||||||
|
"tsd": "^0.11.0",
|
||||||
|
"xo": "^0.26.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
+139
@@ -0,0 +1,139 @@
|
|||||||
|
# quick-lru [](https://travis-ci.org/sindresorhus/quick-lru) [](https://coveralls.io/github/sindresorhus/quick-lru?branch=master)
|
||||||
|
|
||||||
|
> Simple [“Least Recently Used” (LRU) cache](https://en.m.wikipedia.org/wiki/Cache_replacement_policies#Least_Recently_Used_.28LRU.29)
|
||||||
|
|
||||||
|
Useful when you need to cache something and limit memory usage.
|
||||||
|
|
||||||
|
Inspired by the [`hashlru` algorithm](https://github.com/dominictarr/hashlru#algorithm), but instead uses [`Map`](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Map) to support keys of any type, not just strings, and values can be `undefined`.
|
||||||
|
|
||||||
|
## Install
|
||||||
|
|
||||||
|
```
|
||||||
|
$ npm install quick-lru
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
```js
|
||||||
|
const QuickLRU = require('quick-lru');
|
||||||
|
|
||||||
|
const lru = new QuickLRU({maxSize: 1000});
|
||||||
|
|
||||||
|
lru.set('🦄', '🌈');
|
||||||
|
|
||||||
|
lru.has('🦄');
|
||||||
|
//=> true
|
||||||
|
|
||||||
|
lru.get('🦄');
|
||||||
|
//=> '🌈'
|
||||||
|
```
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
### new QuickLRU(options?)
|
||||||
|
|
||||||
|
Returns a new instance.
|
||||||
|
|
||||||
|
### options
|
||||||
|
|
||||||
|
Type: `object`
|
||||||
|
|
||||||
|
#### maxSize
|
||||||
|
|
||||||
|
*Required*\
|
||||||
|
Type: `number`
|
||||||
|
|
||||||
|
The maximum number of items before evicting the least recently used items.
|
||||||
|
|
||||||
|
#### maxAge
|
||||||
|
|
||||||
|
Type: `number`\
|
||||||
|
Default: `Infinity`
|
||||||
|
|
||||||
|
The maximum number of milliseconds an item should remain in cache.
|
||||||
|
By default maxAge will be Infinity, which means that items will never expire.
|
||||||
|
|
||||||
|
Lazy expiration happens upon the next `write` or `read` call.
|
||||||
|
|
||||||
|
Individual expiration of an item can be specified by the `set(key, value, options)` method.
|
||||||
|
|
||||||
|
#### onEviction
|
||||||
|
|
||||||
|
*Optional*\
|
||||||
|
Type: `(key, value) => void`
|
||||||
|
|
||||||
|
Called right before an item is evicted from the cache.
|
||||||
|
|
||||||
|
Useful for side effects or for items like object URLs that need explicit cleanup (`revokeObjectURL`).
|
||||||
|
|
||||||
|
### Instance
|
||||||
|
|
||||||
|
The instance is [`iterable`](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Iteration_protocols) so you can use it directly in a [`for…of`](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Statements/for...of) loop.
|
||||||
|
|
||||||
|
Both `key` and `value` can be of any type.
|
||||||
|
|
||||||
|
#### .set(key, value, options?)
|
||||||
|
|
||||||
|
Set an item. Returns the instance.
|
||||||
|
|
||||||
|
Individual expiration of an item can be specified with the `maxAge` option. If not specified, the global `maxAge` value will be used in case it is specified on the constructor, otherwise the item will never expire.
|
||||||
|
|
||||||
|
#### .get(key)
|
||||||
|
|
||||||
|
Get an item.
|
||||||
|
|
||||||
|
#### .has(key)
|
||||||
|
|
||||||
|
Check if an item exists.
|
||||||
|
|
||||||
|
#### .peek(key)
|
||||||
|
|
||||||
|
Get an item without marking it as recently used.
|
||||||
|
|
||||||
|
#### .delete(key)
|
||||||
|
|
||||||
|
Delete an item.
|
||||||
|
|
||||||
|
Returns `true` if the item is removed or `false` if the item doesn't exist.
|
||||||
|
|
||||||
|
#### .clear()
|
||||||
|
|
||||||
|
Delete all items.
|
||||||
|
|
||||||
|
#### .resize(maxSize)
|
||||||
|
|
||||||
|
Update the `maxSize`, discarding items as necessary. Insertion order is mostly preserved, though this is not a strong guarantee.
|
||||||
|
|
||||||
|
Useful for on-the-fly tuning of cache sizes in live systems.
|
||||||
|
|
||||||
|
#### .keys()
|
||||||
|
|
||||||
|
Iterable for all the keys.
|
||||||
|
|
||||||
|
#### .values()
|
||||||
|
|
||||||
|
Iterable for all the values.
|
||||||
|
|
||||||
|
#### .entriesAscending()
|
||||||
|
|
||||||
|
Iterable for all entries, starting with the oldest (ascending in recency).
|
||||||
|
|
||||||
|
#### .entriesDescending()
|
||||||
|
|
||||||
|
Iterable for all entries, starting with the newest (descending in recency).
|
||||||
|
|
||||||
|
#### .size
|
||||||
|
|
||||||
|
The stored item count.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<div align="center">
|
||||||
|
<b>
|
||||||
|
<a href="https://tidelift.com/subscription/pkg/npm-quick-lru?utm_source=npm-quick-lru&utm_medium=referral&utm_campaign=readme">Get professional support for this package with a Tidelift subscription</a>
|
||||||
|
</b>
|
||||||
|
<br>
|
||||||
|
<sub>
|
||||||
|
Tidelift helps make open source sustainable for maintainers while giving companies<br>assurances about security, maintenance, and licensing for their dependencies.
|
||||||
|
</sub>
|
||||||
|
</div>
|
||||||
+22
@@ -0,0 +1,22 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2014-present Sebastian McKenzie and other contributors
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
a copy of this software and associated documentation files (the
|
||||||
|
"Software"), to deal in the Software without restriction, including
|
||||||
|
without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be
|
||||||
|
included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
+19
@@ -0,0 +1,19 @@
|
|||||||
|
# @babel/code-frame
|
||||||
|
|
||||||
|
> Generate errors that contain a code frame that point to source locations.
|
||||||
|
|
||||||
|
See our website [@babel/code-frame](https://babeljs.io/docs/babel-code-frame) for more information.
|
||||||
|
|
||||||
|
## Install
|
||||||
|
|
||||||
|
Using npm:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
npm install --save-dev @babel/code-frame
|
||||||
|
```
|
||||||
|
|
||||||
|
or using yarn:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
yarn add @babel/code-frame --dev
|
||||||
|
```
|
||||||
+217
@@ -0,0 +1,217 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
Object.defineProperty(exports, '__esModule', { value: true });
|
||||||
|
|
||||||
|
var picocolors = require('picocolors');
|
||||||
|
var jsTokens = require('js-tokens');
|
||||||
|
var helperValidatorIdentifier = require('@babel/helper-validator-identifier');
|
||||||
|
|
||||||
|
function isColorSupported() {
|
||||||
|
return (typeof process === "object" && (process.env.FORCE_COLOR === "0" || process.env.FORCE_COLOR === "false") ? false : picocolors.isColorSupported
|
||||||
|
);
|
||||||
|
}
|
||||||
|
const compose = (f, g) => v => f(g(v));
|
||||||
|
function buildDefs(colors) {
|
||||||
|
return {
|
||||||
|
keyword: colors.cyan,
|
||||||
|
capitalized: colors.yellow,
|
||||||
|
jsxIdentifier: colors.yellow,
|
||||||
|
punctuator: colors.yellow,
|
||||||
|
number: colors.magenta,
|
||||||
|
string: colors.green,
|
||||||
|
regex: colors.magenta,
|
||||||
|
comment: colors.gray,
|
||||||
|
invalid: compose(compose(colors.white, colors.bgRed), colors.bold),
|
||||||
|
gutter: colors.gray,
|
||||||
|
marker: compose(colors.red, colors.bold),
|
||||||
|
message: compose(colors.red, colors.bold),
|
||||||
|
reset: colors.reset
|
||||||
|
};
|
||||||
|
}
|
||||||
|
const defsOn = buildDefs(picocolors.createColors(true));
|
||||||
|
const defsOff = buildDefs(picocolors.createColors(false));
|
||||||
|
function getDefs(enabled) {
|
||||||
|
return enabled ? defsOn : defsOff;
|
||||||
|
}
|
||||||
|
|
||||||
|
const sometimesKeywords = new Set(["as", "async", "from", "get", "of", "set"]);
|
||||||
|
const NEWLINE$1 = /\r\n|[\n\r\u2028\u2029]/;
|
||||||
|
const BRACKET = /^[()[\]{}]$/;
|
||||||
|
let tokenize;
|
||||||
|
const JSX_TAG = /^[a-z][\w-]*$/i;
|
||||||
|
const getTokenType = function (token, offset, text) {
|
||||||
|
if (token.type === "name") {
|
||||||
|
const tokenValue = token.value;
|
||||||
|
if (helperValidatorIdentifier.isKeyword(tokenValue) || helperValidatorIdentifier.isStrictReservedWord(tokenValue, true) || sometimesKeywords.has(tokenValue)) {
|
||||||
|
return "keyword";
|
||||||
|
}
|
||||||
|
if (JSX_TAG.test(tokenValue) && (text[offset - 1] === "<" || text.slice(offset - 2, offset) === "</")) {
|
||||||
|
return "jsxIdentifier";
|
||||||
|
}
|
||||||
|
const firstChar = String.fromCodePoint(tokenValue.codePointAt(0));
|
||||||
|
if (firstChar !== firstChar.toLowerCase()) {
|
||||||
|
return "capitalized";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (token.type === "punctuator" && BRACKET.test(token.value)) {
|
||||||
|
return "bracket";
|
||||||
|
}
|
||||||
|
if (token.type === "invalid" && (token.value === "@" || token.value === "#")) {
|
||||||
|
return "punctuator";
|
||||||
|
}
|
||||||
|
return token.type;
|
||||||
|
};
|
||||||
|
tokenize = function* (text) {
|
||||||
|
let match;
|
||||||
|
while (match = jsTokens.default.exec(text)) {
|
||||||
|
const token = jsTokens.matchToToken(match);
|
||||||
|
yield {
|
||||||
|
type: getTokenType(token, match.index, text),
|
||||||
|
value: token.value
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
function highlight(text) {
|
||||||
|
if (text === "") return "";
|
||||||
|
const defs = getDefs(true);
|
||||||
|
let highlighted = "";
|
||||||
|
for (const {
|
||||||
|
type,
|
||||||
|
value
|
||||||
|
} of tokenize(text)) {
|
||||||
|
if (type in defs) {
|
||||||
|
highlighted += value.split(NEWLINE$1).map(str => defs[type](str)).join("\n");
|
||||||
|
} else {
|
||||||
|
highlighted += value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return highlighted;
|
||||||
|
}
|
||||||
|
|
||||||
|
let deprecationWarningShown = false;
|
||||||
|
const NEWLINE = /\r\n|[\n\r\u2028\u2029]/;
|
||||||
|
function getMarkerLines(loc, source, opts, startLineBaseZero) {
|
||||||
|
const startLoc = Object.assign({
|
||||||
|
column: 0,
|
||||||
|
line: -1
|
||||||
|
}, loc.start);
|
||||||
|
const endLoc = Object.assign({}, startLoc, loc.end);
|
||||||
|
const {
|
||||||
|
linesAbove = 2,
|
||||||
|
linesBelow = 3
|
||||||
|
} = opts || {};
|
||||||
|
const startLine = startLoc.line - startLineBaseZero;
|
||||||
|
const startColumn = startLoc.column;
|
||||||
|
const endLine = endLoc.line - startLineBaseZero;
|
||||||
|
const endColumn = endLoc.column;
|
||||||
|
let start = Math.max(startLine - (linesAbove + 1), 0);
|
||||||
|
let end = Math.min(source.length, endLine + linesBelow);
|
||||||
|
if (startLine === -1) {
|
||||||
|
start = 0;
|
||||||
|
}
|
||||||
|
if (endLine === -1) {
|
||||||
|
end = source.length;
|
||||||
|
}
|
||||||
|
const lineDiff = endLine - startLine;
|
||||||
|
const markerLines = {};
|
||||||
|
if (lineDiff) {
|
||||||
|
for (let i = 0; i <= lineDiff; i++) {
|
||||||
|
const lineNumber = i + startLine;
|
||||||
|
if (!startColumn) {
|
||||||
|
markerLines[lineNumber] = true;
|
||||||
|
} else if (i === 0) {
|
||||||
|
const sourceLength = source[lineNumber - 1].length;
|
||||||
|
markerLines[lineNumber] = [startColumn, sourceLength - startColumn + 1];
|
||||||
|
} else if (i === lineDiff) {
|
||||||
|
markerLines[lineNumber] = [0, endColumn];
|
||||||
|
} else {
|
||||||
|
const sourceLength = source[lineNumber - i].length;
|
||||||
|
markerLines[lineNumber] = [0, sourceLength];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (startColumn === endColumn) {
|
||||||
|
if (startColumn) {
|
||||||
|
markerLines[startLine] = [startColumn, 0];
|
||||||
|
} else {
|
||||||
|
markerLines[startLine] = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
markerLines[startLine] = [startColumn, endColumn - startColumn];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
start,
|
||||||
|
end,
|
||||||
|
markerLines
|
||||||
|
};
|
||||||
|
}
|
||||||
|
function codeFrameColumns(rawLines, loc, opts = {}) {
|
||||||
|
const shouldHighlight = opts.forceColor || isColorSupported() && opts.highlightCode;
|
||||||
|
const startLineBaseZero = (opts.startLine || 1) - 1;
|
||||||
|
const defs = getDefs(shouldHighlight);
|
||||||
|
const lines = rawLines.split(NEWLINE);
|
||||||
|
const {
|
||||||
|
start,
|
||||||
|
end,
|
||||||
|
markerLines
|
||||||
|
} = getMarkerLines(loc, lines, opts, startLineBaseZero);
|
||||||
|
const hasColumns = loc.start && typeof loc.start.column === "number";
|
||||||
|
const numberMaxWidth = String(end + startLineBaseZero).length;
|
||||||
|
const highlightedLines = shouldHighlight ? highlight(rawLines) : rawLines;
|
||||||
|
let frame = highlightedLines.split(NEWLINE, end).slice(start, end).map((line, index) => {
|
||||||
|
const number = start + 1 + index;
|
||||||
|
const paddedNumber = ` ${number + startLineBaseZero}`.slice(-numberMaxWidth);
|
||||||
|
const gutter = ` ${paddedNumber} |`;
|
||||||
|
const hasMarker = markerLines[number];
|
||||||
|
const lastMarkerLine = !markerLines[number + 1];
|
||||||
|
if (hasMarker) {
|
||||||
|
let markerLine = "";
|
||||||
|
if (Array.isArray(hasMarker)) {
|
||||||
|
const markerSpacing = line.slice(0, Math.max(hasMarker[0] - 1, 0)).replace(/[^\t]/g, " ");
|
||||||
|
const numberOfMarkers = hasMarker[1] || 1;
|
||||||
|
markerLine = ["\n ", defs.gutter(gutter.replace(/\d/g, " ")), " ", markerSpacing, defs.marker("^").repeat(numberOfMarkers)].join("");
|
||||||
|
if (lastMarkerLine && opts.message) {
|
||||||
|
markerLine += " " + defs.message(opts.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return [defs.marker(">"), defs.gutter(gutter), line.length > 0 ? ` ${line}` : "", markerLine].join("");
|
||||||
|
} else {
|
||||||
|
return ` ${defs.gutter(gutter)}${line.length > 0 ? ` ${line}` : ""}`;
|
||||||
|
}
|
||||||
|
}).join("\n");
|
||||||
|
if (opts.message && !hasColumns) {
|
||||||
|
frame = `${" ".repeat(numberMaxWidth + 1)}${opts.message}\n${frame}`;
|
||||||
|
}
|
||||||
|
if (shouldHighlight) {
|
||||||
|
return defs.reset(frame);
|
||||||
|
} else {
|
||||||
|
return frame;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function index (rawLines, lineNumber, colNumber, opts = {}) {
|
||||||
|
if (!deprecationWarningShown) {
|
||||||
|
deprecationWarningShown = true;
|
||||||
|
const message = "Passing lineNumber and colNumber is deprecated to @babel/code-frame. Please use `codeFrameColumns`.";
|
||||||
|
if (process.emitWarning) {
|
||||||
|
process.emitWarning(message, "DeprecationWarning");
|
||||||
|
} else {
|
||||||
|
const deprecationError = new Error(message);
|
||||||
|
deprecationError.name = "DeprecationWarning";
|
||||||
|
console.warn(new Error(message));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
colNumber = Math.max(colNumber, 0);
|
||||||
|
const location = {
|
||||||
|
start: {
|
||||||
|
column: colNumber,
|
||||||
|
line: lineNumber
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return codeFrameColumns(rawLines, location, opts);
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.codeFrameColumns = codeFrameColumns;
|
||||||
|
exports.default = index;
|
||||||
|
exports.highlight = highlight;
|
||||||
|
//# sourceMappingURL=index.js.map
|
||||||
+1
File diff suppressed because one or more lines are too long
+32
@@ -0,0 +1,32 @@
|
|||||||
|
{
|
||||||
|
"name": "@babel/code-frame",
|
||||||
|
"version": "7.29.7",
|
||||||
|
"description": "Generate errors that contain a code frame that point to source locations.",
|
||||||
|
"author": "The Babel Team (https://babel.dev/team)",
|
||||||
|
"homepage": "https://babel.dev/docs/en/next/babel-code-frame",
|
||||||
|
"bugs": "https://github.com/babel/babel/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen",
|
||||||
|
"license": "MIT",
|
||||||
|
"publishConfig": {
|
||||||
|
"access": "public"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/babel/babel.git",
|
||||||
|
"directory": "packages/babel-code-frame"
|
||||||
|
},
|
||||||
|
"main": "./lib/index.js",
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/helper-validator-identifier": "^7.29.7",
|
||||||
|
"js-tokens": "^4.0.0",
|
||||||
|
"picocolors": "^1.1.1"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"charcodes": "^0.2.0",
|
||||||
|
"import-meta-resolve": "^4.1.0",
|
||||||
|
"strip-ansi": "^4.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.9.0"
|
||||||
|
},
|
||||||
|
"type": "commonjs"
|
||||||
|
}
|
||||||
+22
@@ -0,0 +1,22 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2014-present Sebastian McKenzie and other contributors
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
a copy of this software and associated documentation files (the
|
||||||
|
"Software"), to deal in the Software without restriction, including
|
||||||
|
without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be
|
||||||
|
included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
+19
@@ -0,0 +1,19 @@
|
|||||||
|
# @babel/compat-data
|
||||||
|
|
||||||
|
> The compat-data to determine required Babel plugins
|
||||||
|
|
||||||
|
See our website [@babel/compat-data](https://babeljs.io/docs/babel-compat-data) for more information.
|
||||||
|
|
||||||
|
## Install
|
||||||
|
|
||||||
|
Using npm:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
npm install --save @babel/compat-data
|
||||||
|
```
|
||||||
|
|
||||||
|
or using yarn:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
yarn add @babel/compat-data
|
||||||
|
```
|
||||||
+2
@@ -0,0 +1,2 @@
|
|||||||
|
// Todo (Babel 8): remove this file as Babel 8 drop support of core-js 2
|
||||||
|
module.exports = require("./data/corejs2-built-ins.json");
|
||||||
+2
@@ -0,0 +1,2 @@
|
|||||||
|
// Todo (Babel 8): remove this file now that it is included in babel-plugin-polyfill-corejs3
|
||||||
|
module.exports = require("./data/corejs3-shipped-proposals.json");
|
||||||
+2120
File diff suppressed because it is too large
Load Diff
+5
@@ -0,0 +1,5 @@
|
|||||||
|
[
|
||||||
|
"esnext.promise.all-settled",
|
||||||
|
"esnext.string.match-all",
|
||||||
|
"esnext.global-this"
|
||||||
|
]
|
||||||
+18
@@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
"es6.module": {
|
||||||
|
"chrome": "61",
|
||||||
|
"and_chr": "61",
|
||||||
|
"edge": "16",
|
||||||
|
"firefox": "60",
|
||||||
|
"and_ff": "60",
|
||||||
|
"node": "13.2.0",
|
||||||
|
"opera": "48",
|
||||||
|
"op_mob": "45",
|
||||||
|
"safari": "10.1",
|
||||||
|
"ios": "10.3",
|
||||||
|
"samsung": "8.2",
|
||||||
|
"android": "61",
|
||||||
|
"electron": "2.0",
|
||||||
|
"ios_saf": "10.3"
|
||||||
|
}
|
||||||
|
}
|
||||||
+38
@@ -0,0 +1,38 @@
|
|||||||
|
{
|
||||||
|
"transform-async-to-generator": [
|
||||||
|
"bugfix/transform-async-arrows-in-class"
|
||||||
|
],
|
||||||
|
"transform-parameters": [
|
||||||
|
"bugfix/transform-edge-default-parameters",
|
||||||
|
"bugfix/transform-safari-id-destructuring-collision-in-function-expression"
|
||||||
|
],
|
||||||
|
"transform-function-name": [
|
||||||
|
"bugfix/transform-edge-function-name"
|
||||||
|
],
|
||||||
|
"transform-block-scoping": [
|
||||||
|
"bugfix/transform-safari-block-shadowing",
|
||||||
|
"bugfix/transform-safari-for-shadowing"
|
||||||
|
],
|
||||||
|
"transform-destructuring": [
|
||||||
|
"bugfix/transform-safari-rest-destructuring-rhs-array"
|
||||||
|
],
|
||||||
|
"transform-template-literals": [
|
||||||
|
"bugfix/transform-tagged-template-caching"
|
||||||
|
],
|
||||||
|
"transform-optional-chaining": [
|
||||||
|
"bugfix/transform-v8-spread-parameters-in-optional-chaining"
|
||||||
|
],
|
||||||
|
"proposal-optional-chaining": [
|
||||||
|
"bugfix/transform-v8-spread-parameters-in-optional-chaining"
|
||||||
|
],
|
||||||
|
"transform-class-properties": [
|
||||||
|
"bugfix/transform-v8-static-class-fields-redefine-readonly",
|
||||||
|
"bugfix/transform-firefox-class-in-computed-class-key",
|
||||||
|
"bugfix/transform-safari-class-field-initializer-scope"
|
||||||
|
],
|
||||||
|
"proposal-class-properties": [
|
||||||
|
"bugfix/transform-v8-static-class-fields-redefine-readonly",
|
||||||
|
"bugfix/transform-firefox-class-in-computed-class-key",
|
||||||
|
"bugfix/transform-safari-class-field-initializer-scope"
|
||||||
|
]
|
||||||
|
}
|
||||||
+231
@@ -0,0 +1,231 @@
|
|||||||
|
{
|
||||||
|
"bugfix/transform-async-arrows-in-class": {
|
||||||
|
"chrome": "55",
|
||||||
|
"opera": "42",
|
||||||
|
"edge": "15",
|
||||||
|
"firefox": "52",
|
||||||
|
"safari": "11",
|
||||||
|
"node": "7.6",
|
||||||
|
"deno": "1",
|
||||||
|
"ios": "11",
|
||||||
|
"samsung": "6",
|
||||||
|
"opera_mobile": "42",
|
||||||
|
"electron": "1.6"
|
||||||
|
},
|
||||||
|
"bugfix/transform-edge-default-parameters": {
|
||||||
|
"chrome": "49",
|
||||||
|
"opera": "36",
|
||||||
|
"edge": "18",
|
||||||
|
"firefox": "52",
|
||||||
|
"safari": "10",
|
||||||
|
"node": "6",
|
||||||
|
"deno": "1",
|
||||||
|
"ios": "10",
|
||||||
|
"samsung": "5",
|
||||||
|
"opera_mobile": "36",
|
||||||
|
"electron": "0.37"
|
||||||
|
},
|
||||||
|
"bugfix/transform-edge-function-name": {
|
||||||
|
"chrome": "51",
|
||||||
|
"opera": "38",
|
||||||
|
"edge": "79",
|
||||||
|
"firefox": "53",
|
||||||
|
"safari": "10",
|
||||||
|
"node": "6.5",
|
||||||
|
"deno": "1",
|
||||||
|
"ios": "10",
|
||||||
|
"samsung": "5",
|
||||||
|
"rhino": "1.9",
|
||||||
|
"opera_mobile": "41",
|
||||||
|
"electron": "1.2"
|
||||||
|
},
|
||||||
|
"bugfix/transform-safari-block-shadowing": {
|
||||||
|
"chrome": "49",
|
||||||
|
"opera": "36",
|
||||||
|
"edge": "12",
|
||||||
|
"firefox": "44",
|
||||||
|
"safari": "11",
|
||||||
|
"node": "6",
|
||||||
|
"deno": "1",
|
||||||
|
"ie": "11",
|
||||||
|
"ios": "11",
|
||||||
|
"samsung": "5",
|
||||||
|
"opera_mobile": "36",
|
||||||
|
"electron": "0.37"
|
||||||
|
},
|
||||||
|
"bugfix/transform-safari-for-shadowing": {
|
||||||
|
"chrome": "49",
|
||||||
|
"opera": "36",
|
||||||
|
"edge": "12",
|
||||||
|
"firefox": "4",
|
||||||
|
"safari": "11",
|
||||||
|
"node": "6",
|
||||||
|
"deno": "1",
|
||||||
|
"ie": "11",
|
||||||
|
"ios": "11",
|
||||||
|
"samsung": "5",
|
||||||
|
"rhino": "1.7.13",
|
||||||
|
"opera_mobile": "36",
|
||||||
|
"electron": "0.37"
|
||||||
|
},
|
||||||
|
"bugfix/transform-safari-id-destructuring-collision-in-function-expression": {
|
||||||
|
"chrome": "49",
|
||||||
|
"opera": "36",
|
||||||
|
"edge": "14",
|
||||||
|
"firefox": "2",
|
||||||
|
"safari": "16.3",
|
||||||
|
"node": "6",
|
||||||
|
"deno": "1",
|
||||||
|
"ios": "16.3",
|
||||||
|
"samsung": "5",
|
||||||
|
"opera_mobile": "36",
|
||||||
|
"electron": "0.37"
|
||||||
|
},
|
||||||
|
"bugfix/transform-safari-rest-destructuring-rhs-array": {
|
||||||
|
"chrome": "49",
|
||||||
|
"opera": "36",
|
||||||
|
"edge": "14",
|
||||||
|
"firefox": "34",
|
||||||
|
"safari": "14.1",
|
||||||
|
"node": "6",
|
||||||
|
"deno": "1",
|
||||||
|
"ios": "14.5",
|
||||||
|
"samsung": "5",
|
||||||
|
"opera_mobile": "36",
|
||||||
|
"electron": "0.37"
|
||||||
|
},
|
||||||
|
"bugfix/transform-tagged-template-caching": {
|
||||||
|
"chrome": "41",
|
||||||
|
"opera": "28",
|
||||||
|
"edge": "12",
|
||||||
|
"firefox": "34",
|
||||||
|
"safari": "13",
|
||||||
|
"node": "4",
|
||||||
|
"deno": "1",
|
||||||
|
"ios": "13",
|
||||||
|
"samsung": "3.4",
|
||||||
|
"rhino": "1.7.14",
|
||||||
|
"opera_mobile": "28",
|
||||||
|
"electron": "0.21"
|
||||||
|
},
|
||||||
|
"bugfix/transform-v8-spread-parameters-in-optional-chaining": {
|
||||||
|
"chrome": "91",
|
||||||
|
"opera": "77",
|
||||||
|
"edge": "91",
|
||||||
|
"firefox": "74",
|
||||||
|
"safari": "13.1",
|
||||||
|
"node": "16.9",
|
||||||
|
"deno": "1.9",
|
||||||
|
"ios": "13.4",
|
||||||
|
"samsung": "16",
|
||||||
|
"opera_mobile": "64",
|
||||||
|
"electron": "13.0"
|
||||||
|
},
|
||||||
|
"transform-optional-chaining": {
|
||||||
|
"chrome": "80",
|
||||||
|
"opera": "67",
|
||||||
|
"edge": "80",
|
||||||
|
"firefox": "74",
|
||||||
|
"safari": "13.1",
|
||||||
|
"node": "14",
|
||||||
|
"deno": "1",
|
||||||
|
"ios": "13.4",
|
||||||
|
"samsung": "13",
|
||||||
|
"rhino": "1.8",
|
||||||
|
"opera_mobile": "57",
|
||||||
|
"electron": "8.0"
|
||||||
|
},
|
||||||
|
"proposal-optional-chaining": {
|
||||||
|
"chrome": "80",
|
||||||
|
"opera": "67",
|
||||||
|
"edge": "80",
|
||||||
|
"firefox": "74",
|
||||||
|
"safari": "13.1",
|
||||||
|
"node": "14",
|
||||||
|
"deno": "1",
|
||||||
|
"ios": "13.4",
|
||||||
|
"samsung": "13",
|
||||||
|
"rhino": "1.8",
|
||||||
|
"opera_mobile": "57",
|
||||||
|
"electron": "8.0"
|
||||||
|
},
|
||||||
|
"transform-parameters": {
|
||||||
|
"chrome": "49",
|
||||||
|
"opera": "36",
|
||||||
|
"edge": "15",
|
||||||
|
"firefox": "52",
|
||||||
|
"safari": "10",
|
||||||
|
"node": "6",
|
||||||
|
"deno": "1",
|
||||||
|
"ios": "10",
|
||||||
|
"samsung": "5",
|
||||||
|
"opera_mobile": "36",
|
||||||
|
"electron": "0.37"
|
||||||
|
},
|
||||||
|
"transform-async-to-generator": {
|
||||||
|
"chrome": "55",
|
||||||
|
"opera": "42",
|
||||||
|
"edge": "15",
|
||||||
|
"firefox": "52",
|
||||||
|
"safari": "10.1",
|
||||||
|
"node": "7.6",
|
||||||
|
"deno": "1",
|
||||||
|
"ios": "10.3",
|
||||||
|
"samsung": "6",
|
||||||
|
"opera_mobile": "42",
|
||||||
|
"electron": "1.6"
|
||||||
|
},
|
||||||
|
"transform-template-literals": {
|
||||||
|
"chrome": "41",
|
||||||
|
"opera": "28",
|
||||||
|
"edge": "13",
|
||||||
|
"firefox": "34",
|
||||||
|
"safari": "9",
|
||||||
|
"node": "4",
|
||||||
|
"deno": "1",
|
||||||
|
"ios": "9",
|
||||||
|
"samsung": "3.4",
|
||||||
|
"rhino": "1.9",
|
||||||
|
"opera_mobile": "28",
|
||||||
|
"electron": "0.21"
|
||||||
|
},
|
||||||
|
"transform-function-name": {
|
||||||
|
"chrome": "51",
|
||||||
|
"opera": "38",
|
||||||
|
"edge": "14",
|
||||||
|
"firefox": "53",
|
||||||
|
"safari": "10",
|
||||||
|
"node": "6.5",
|
||||||
|
"deno": "1",
|
||||||
|
"ios": "10",
|
||||||
|
"samsung": "5",
|
||||||
|
"opera_mobile": "41",
|
||||||
|
"electron": "1.2"
|
||||||
|
},
|
||||||
|
"transform-destructuring": {
|
||||||
|
"chrome": "51",
|
||||||
|
"opera": "38",
|
||||||
|
"edge": "15",
|
||||||
|
"firefox": "53",
|
||||||
|
"safari": "10",
|
||||||
|
"node": "6.5",
|
||||||
|
"deno": "1",
|
||||||
|
"ios": "10",
|
||||||
|
"samsung": "5",
|
||||||
|
"opera_mobile": "41",
|
||||||
|
"electron": "1.2"
|
||||||
|
},
|
||||||
|
"transform-block-scoping": {
|
||||||
|
"chrome": "50",
|
||||||
|
"opera": "37",
|
||||||
|
"edge": "14",
|
||||||
|
"firefox": "53",
|
||||||
|
"safari": "10",
|
||||||
|
"node": "6",
|
||||||
|
"deno": "1",
|
||||||
|
"ios": "10",
|
||||||
|
"samsung": "5",
|
||||||
|
"opera_mobile": "37",
|
||||||
|
"electron": "1.1"
|
||||||
|
}
|
||||||
|
}
|
||||||
+843
@@ -0,0 +1,843 @@
|
|||||||
|
{
|
||||||
|
"transform-explicit-resource-management": {
|
||||||
|
"chrome": "141",
|
||||||
|
"edge": "141",
|
||||||
|
"firefox": "141",
|
||||||
|
"node": "25",
|
||||||
|
"electron": "39.0"
|
||||||
|
},
|
||||||
|
"transform-duplicate-named-capturing-groups-regex": {
|
||||||
|
"chrome": "126",
|
||||||
|
"opera": "112",
|
||||||
|
"edge": "126",
|
||||||
|
"firefox": "129",
|
||||||
|
"safari": "17.4",
|
||||||
|
"node": "23",
|
||||||
|
"ios": "17.4",
|
||||||
|
"rhino": "1.9",
|
||||||
|
"electron": "31.0"
|
||||||
|
},
|
||||||
|
"transform-regexp-modifiers": {
|
||||||
|
"chrome": "125",
|
||||||
|
"opera": "111",
|
||||||
|
"edge": "125",
|
||||||
|
"firefox": "132",
|
||||||
|
"node": "23",
|
||||||
|
"samsung": "27",
|
||||||
|
"electron": "31.0"
|
||||||
|
},
|
||||||
|
"transform-unicode-sets-regex": {
|
||||||
|
"chrome": "112",
|
||||||
|
"opera": "98",
|
||||||
|
"edge": "112",
|
||||||
|
"firefox": "116",
|
||||||
|
"safari": "17",
|
||||||
|
"node": "20",
|
||||||
|
"deno": "1.32",
|
||||||
|
"ios": "17",
|
||||||
|
"samsung": "23",
|
||||||
|
"opera_mobile": "75",
|
||||||
|
"electron": "24.0"
|
||||||
|
},
|
||||||
|
"bugfix/transform-v8-static-class-fields-redefine-readonly": {
|
||||||
|
"chrome": "98",
|
||||||
|
"opera": "84",
|
||||||
|
"edge": "98",
|
||||||
|
"firefox": "75",
|
||||||
|
"safari": "15",
|
||||||
|
"node": "12",
|
||||||
|
"deno": "1.18",
|
||||||
|
"ios": "15",
|
||||||
|
"samsung": "11",
|
||||||
|
"opera_mobile": "52",
|
||||||
|
"electron": "17.0"
|
||||||
|
},
|
||||||
|
"bugfix/transform-firefox-class-in-computed-class-key": {
|
||||||
|
"chrome": "74",
|
||||||
|
"opera": "62",
|
||||||
|
"edge": "79",
|
||||||
|
"firefox": "126",
|
||||||
|
"safari": "16",
|
||||||
|
"node": "12",
|
||||||
|
"deno": "1",
|
||||||
|
"ios": "16",
|
||||||
|
"samsung": "11",
|
||||||
|
"opera_mobile": "53",
|
||||||
|
"electron": "6.0"
|
||||||
|
},
|
||||||
|
"bugfix/transform-safari-class-field-initializer-scope": {
|
||||||
|
"chrome": "74",
|
||||||
|
"opera": "62",
|
||||||
|
"edge": "79",
|
||||||
|
"firefox": "69",
|
||||||
|
"safari": "16",
|
||||||
|
"node": "12",
|
||||||
|
"deno": "1",
|
||||||
|
"ios": "16",
|
||||||
|
"samsung": "11",
|
||||||
|
"opera_mobile": "53",
|
||||||
|
"electron": "6.0"
|
||||||
|
},
|
||||||
|
"transform-class-static-block": {
|
||||||
|
"chrome": "94",
|
||||||
|
"opera": "80",
|
||||||
|
"edge": "94",
|
||||||
|
"firefox": "93",
|
||||||
|
"safari": "16.4",
|
||||||
|
"node": "16.11",
|
||||||
|
"deno": "1.14",
|
||||||
|
"ios": "16.4",
|
||||||
|
"samsung": "17",
|
||||||
|
"opera_mobile": "66",
|
||||||
|
"electron": "15.0"
|
||||||
|
},
|
||||||
|
"proposal-class-static-block": {
|
||||||
|
"chrome": "94",
|
||||||
|
"opera": "80",
|
||||||
|
"edge": "94",
|
||||||
|
"firefox": "93",
|
||||||
|
"safari": "16.4",
|
||||||
|
"node": "16.11",
|
||||||
|
"deno": "1.14",
|
||||||
|
"ios": "16.4",
|
||||||
|
"samsung": "17",
|
||||||
|
"opera_mobile": "66",
|
||||||
|
"electron": "15.0"
|
||||||
|
},
|
||||||
|
"transform-private-property-in-object": {
|
||||||
|
"chrome": "91",
|
||||||
|
"opera": "77",
|
||||||
|
"edge": "91",
|
||||||
|
"firefox": "90",
|
||||||
|
"safari": "15",
|
||||||
|
"node": "16.9",
|
||||||
|
"deno": "1.9",
|
||||||
|
"ios": "15",
|
||||||
|
"samsung": "16",
|
||||||
|
"opera_mobile": "64",
|
||||||
|
"electron": "13.0"
|
||||||
|
},
|
||||||
|
"proposal-private-property-in-object": {
|
||||||
|
"chrome": "91",
|
||||||
|
"opera": "77",
|
||||||
|
"edge": "91",
|
||||||
|
"firefox": "90",
|
||||||
|
"safari": "15",
|
||||||
|
"node": "16.9",
|
||||||
|
"deno": "1.9",
|
||||||
|
"ios": "15",
|
||||||
|
"samsung": "16",
|
||||||
|
"opera_mobile": "64",
|
||||||
|
"electron": "13.0"
|
||||||
|
},
|
||||||
|
"transform-class-properties": {
|
||||||
|
"chrome": "74",
|
||||||
|
"opera": "62",
|
||||||
|
"edge": "79",
|
||||||
|
"firefox": "90",
|
||||||
|
"safari": "14.1",
|
||||||
|
"node": "12",
|
||||||
|
"deno": "1",
|
||||||
|
"ios": "14.5",
|
||||||
|
"samsung": "11",
|
||||||
|
"opera_mobile": "53",
|
||||||
|
"electron": "6.0"
|
||||||
|
},
|
||||||
|
"proposal-class-properties": {
|
||||||
|
"chrome": "74",
|
||||||
|
"opera": "62",
|
||||||
|
"edge": "79",
|
||||||
|
"firefox": "90",
|
||||||
|
"safari": "14.1",
|
||||||
|
"node": "12",
|
||||||
|
"deno": "1",
|
||||||
|
"ios": "14.5",
|
||||||
|
"samsung": "11",
|
||||||
|
"opera_mobile": "53",
|
||||||
|
"electron": "6.0"
|
||||||
|
},
|
||||||
|
"transform-private-methods": {
|
||||||
|
"chrome": "84",
|
||||||
|
"opera": "70",
|
||||||
|
"edge": "84",
|
||||||
|
"firefox": "90",
|
||||||
|
"safari": "15",
|
||||||
|
"node": "14.6",
|
||||||
|
"deno": "1",
|
||||||
|
"ios": "15",
|
||||||
|
"samsung": "14",
|
||||||
|
"opera_mobile": "60",
|
||||||
|
"electron": "10.0"
|
||||||
|
},
|
||||||
|
"proposal-private-methods": {
|
||||||
|
"chrome": "84",
|
||||||
|
"opera": "70",
|
||||||
|
"edge": "84",
|
||||||
|
"firefox": "90",
|
||||||
|
"safari": "15",
|
||||||
|
"node": "14.6",
|
||||||
|
"deno": "1",
|
||||||
|
"ios": "15",
|
||||||
|
"samsung": "14",
|
||||||
|
"opera_mobile": "60",
|
||||||
|
"electron": "10.0"
|
||||||
|
},
|
||||||
|
"transform-numeric-separator": {
|
||||||
|
"chrome": "75",
|
||||||
|
"opera": "62",
|
||||||
|
"edge": "79",
|
||||||
|
"firefox": "70",
|
||||||
|
"safari": "13",
|
||||||
|
"node": "12.5",
|
||||||
|
"deno": "1",
|
||||||
|
"ios": "13",
|
||||||
|
"samsung": "11",
|
||||||
|
"rhino": "1.7.14",
|
||||||
|
"opera_mobile": "54",
|
||||||
|
"electron": "6.0"
|
||||||
|
},
|
||||||
|
"proposal-numeric-separator": {
|
||||||
|
"chrome": "75",
|
||||||
|
"opera": "62",
|
||||||
|
"edge": "79",
|
||||||
|
"firefox": "70",
|
||||||
|
"safari": "13",
|
||||||
|
"node": "12.5",
|
||||||
|
"deno": "1",
|
||||||
|
"ios": "13",
|
||||||
|
"samsung": "11",
|
||||||
|
"rhino": "1.7.14",
|
||||||
|
"opera_mobile": "54",
|
||||||
|
"electron": "6.0"
|
||||||
|
},
|
||||||
|
"transform-logical-assignment-operators": {
|
||||||
|
"chrome": "85",
|
||||||
|
"opera": "71",
|
||||||
|
"edge": "85",
|
||||||
|
"firefox": "79",
|
||||||
|
"safari": "14",
|
||||||
|
"node": "15",
|
||||||
|
"deno": "1.2",
|
||||||
|
"ios": "14",
|
||||||
|
"samsung": "14",
|
||||||
|
"opera_mobile": "60",
|
||||||
|
"electron": "10.0"
|
||||||
|
},
|
||||||
|
"proposal-logical-assignment-operators": {
|
||||||
|
"chrome": "85",
|
||||||
|
"opera": "71",
|
||||||
|
"edge": "85",
|
||||||
|
"firefox": "79",
|
||||||
|
"safari": "14",
|
||||||
|
"node": "15",
|
||||||
|
"deno": "1.2",
|
||||||
|
"ios": "14",
|
||||||
|
"samsung": "14",
|
||||||
|
"opera_mobile": "60",
|
||||||
|
"electron": "10.0"
|
||||||
|
},
|
||||||
|
"transform-nullish-coalescing-operator": {
|
||||||
|
"chrome": "80",
|
||||||
|
"opera": "67",
|
||||||
|
"edge": "80",
|
||||||
|
"firefox": "72",
|
||||||
|
"safari": "13.1",
|
||||||
|
"node": "14",
|
||||||
|
"deno": "1",
|
||||||
|
"ios": "13.4",
|
||||||
|
"samsung": "13",
|
||||||
|
"rhino": "1.8",
|
||||||
|
"opera_mobile": "57",
|
||||||
|
"electron": "8.0"
|
||||||
|
},
|
||||||
|
"proposal-nullish-coalescing-operator": {
|
||||||
|
"chrome": "80",
|
||||||
|
"opera": "67",
|
||||||
|
"edge": "80",
|
||||||
|
"firefox": "72",
|
||||||
|
"safari": "13.1",
|
||||||
|
"node": "14",
|
||||||
|
"deno": "1",
|
||||||
|
"ios": "13.4",
|
||||||
|
"samsung": "13",
|
||||||
|
"rhino": "1.8",
|
||||||
|
"opera_mobile": "57",
|
||||||
|
"electron": "8.0"
|
||||||
|
},
|
||||||
|
"transform-optional-chaining": {
|
||||||
|
"chrome": "91",
|
||||||
|
"opera": "77",
|
||||||
|
"edge": "91",
|
||||||
|
"firefox": "74",
|
||||||
|
"safari": "13.1",
|
||||||
|
"node": "16.9",
|
||||||
|
"deno": "1.9",
|
||||||
|
"ios": "13.4",
|
||||||
|
"samsung": "16",
|
||||||
|
"opera_mobile": "64",
|
||||||
|
"electron": "13.0"
|
||||||
|
},
|
||||||
|
"proposal-optional-chaining": {
|
||||||
|
"chrome": "91",
|
||||||
|
"opera": "77",
|
||||||
|
"edge": "91",
|
||||||
|
"firefox": "74",
|
||||||
|
"safari": "13.1",
|
||||||
|
"node": "16.9",
|
||||||
|
"deno": "1.9",
|
||||||
|
"ios": "13.4",
|
||||||
|
"samsung": "16",
|
||||||
|
"opera_mobile": "64",
|
||||||
|
"electron": "13.0"
|
||||||
|
},
|
||||||
|
"transform-json-strings": {
|
||||||
|
"chrome": "66",
|
||||||
|
"opera": "53",
|
||||||
|
"edge": "79",
|
||||||
|
"firefox": "62",
|
||||||
|
"safari": "12",
|
||||||
|
"node": "10",
|
||||||
|
"deno": "1",
|
||||||
|
"ios": "12",
|
||||||
|
"samsung": "9",
|
||||||
|
"rhino": "1.7.14",
|
||||||
|
"opera_mobile": "47",
|
||||||
|
"electron": "3.0"
|
||||||
|
},
|
||||||
|
"proposal-json-strings": {
|
||||||
|
"chrome": "66",
|
||||||
|
"opera": "53",
|
||||||
|
"edge": "79",
|
||||||
|
"firefox": "62",
|
||||||
|
"safari": "12",
|
||||||
|
"node": "10",
|
||||||
|
"deno": "1",
|
||||||
|
"ios": "12",
|
||||||
|
"samsung": "9",
|
||||||
|
"rhino": "1.7.14",
|
||||||
|
"opera_mobile": "47",
|
||||||
|
"electron": "3.0"
|
||||||
|
},
|
||||||
|
"transform-optional-catch-binding": {
|
||||||
|
"chrome": "66",
|
||||||
|
"opera": "53",
|
||||||
|
"edge": "79",
|
||||||
|
"firefox": "58",
|
||||||
|
"safari": "11.1",
|
||||||
|
"node": "10",
|
||||||
|
"deno": "1",
|
||||||
|
"ios": "11.3",
|
||||||
|
"samsung": "9",
|
||||||
|
"opera_mobile": "47",
|
||||||
|
"electron": "3.0"
|
||||||
|
},
|
||||||
|
"proposal-optional-catch-binding": {
|
||||||
|
"chrome": "66",
|
||||||
|
"opera": "53",
|
||||||
|
"edge": "79",
|
||||||
|
"firefox": "58",
|
||||||
|
"safari": "11.1",
|
||||||
|
"node": "10",
|
||||||
|
"deno": "1",
|
||||||
|
"ios": "11.3",
|
||||||
|
"samsung": "9",
|
||||||
|
"opera_mobile": "47",
|
||||||
|
"electron": "3.0"
|
||||||
|
},
|
||||||
|
"transform-parameters": {
|
||||||
|
"chrome": "49",
|
||||||
|
"opera": "36",
|
||||||
|
"edge": "18",
|
||||||
|
"firefox": "52",
|
||||||
|
"safari": "16.3",
|
||||||
|
"node": "6",
|
||||||
|
"deno": "1",
|
||||||
|
"ios": "16.3",
|
||||||
|
"samsung": "5",
|
||||||
|
"opera_mobile": "36",
|
||||||
|
"electron": "0.37"
|
||||||
|
},
|
||||||
|
"transform-async-generator-functions": {
|
||||||
|
"chrome": "63",
|
||||||
|
"opera": "50",
|
||||||
|
"edge": "79",
|
||||||
|
"firefox": "57",
|
||||||
|
"safari": "12",
|
||||||
|
"node": "10",
|
||||||
|
"deno": "1",
|
||||||
|
"ios": "12",
|
||||||
|
"samsung": "8",
|
||||||
|
"opera_mobile": "46",
|
||||||
|
"electron": "3.0"
|
||||||
|
},
|
||||||
|
"proposal-async-generator-functions": {
|
||||||
|
"chrome": "63",
|
||||||
|
"opera": "50",
|
||||||
|
"edge": "79",
|
||||||
|
"firefox": "57",
|
||||||
|
"safari": "12",
|
||||||
|
"node": "10",
|
||||||
|
"deno": "1",
|
||||||
|
"ios": "12",
|
||||||
|
"samsung": "8",
|
||||||
|
"opera_mobile": "46",
|
||||||
|
"electron": "3.0"
|
||||||
|
},
|
||||||
|
"transform-object-rest-spread": {
|
||||||
|
"chrome": "60",
|
||||||
|
"opera": "47",
|
||||||
|
"edge": "79",
|
||||||
|
"firefox": "55",
|
||||||
|
"safari": "11.1",
|
||||||
|
"node": "8.3",
|
||||||
|
"deno": "1",
|
||||||
|
"ios": "11.3",
|
||||||
|
"samsung": "8",
|
||||||
|
"opera_mobile": "44",
|
||||||
|
"electron": "2.0"
|
||||||
|
},
|
||||||
|
"proposal-object-rest-spread": {
|
||||||
|
"chrome": "60",
|
||||||
|
"opera": "47",
|
||||||
|
"edge": "79",
|
||||||
|
"firefox": "55",
|
||||||
|
"safari": "11.1",
|
||||||
|
"node": "8.3",
|
||||||
|
"deno": "1",
|
||||||
|
"ios": "11.3",
|
||||||
|
"samsung": "8",
|
||||||
|
"opera_mobile": "44",
|
||||||
|
"electron": "2.0"
|
||||||
|
},
|
||||||
|
"transform-dotall-regex": {
|
||||||
|
"chrome": "62",
|
||||||
|
"opera": "49",
|
||||||
|
"edge": "79",
|
||||||
|
"firefox": "78",
|
||||||
|
"safari": "11.1",
|
||||||
|
"node": "8.10",
|
||||||
|
"deno": "1",
|
||||||
|
"ios": "11.3",
|
||||||
|
"samsung": "8",
|
||||||
|
"rhino": "1.7.15",
|
||||||
|
"opera_mobile": "46",
|
||||||
|
"electron": "3.0"
|
||||||
|
},
|
||||||
|
"transform-unicode-property-regex": {
|
||||||
|
"chrome": "64",
|
||||||
|
"opera": "51",
|
||||||
|
"edge": "79",
|
||||||
|
"firefox": "78",
|
||||||
|
"safari": "11.1",
|
||||||
|
"node": "10",
|
||||||
|
"deno": "1",
|
||||||
|
"ios": "11.3",
|
||||||
|
"samsung": "9",
|
||||||
|
"rhino": "1.9",
|
||||||
|
"opera_mobile": "47",
|
||||||
|
"electron": "3.0"
|
||||||
|
},
|
||||||
|
"proposal-unicode-property-regex": {
|
||||||
|
"chrome": "64",
|
||||||
|
"opera": "51",
|
||||||
|
"edge": "79",
|
||||||
|
"firefox": "78",
|
||||||
|
"safari": "11.1",
|
||||||
|
"node": "10",
|
||||||
|
"deno": "1",
|
||||||
|
"ios": "11.3",
|
||||||
|
"samsung": "9",
|
||||||
|
"rhino": "1.9",
|
||||||
|
"opera_mobile": "47",
|
||||||
|
"electron": "3.0"
|
||||||
|
},
|
||||||
|
"transform-named-capturing-groups-regex": {
|
||||||
|
"chrome": "64",
|
||||||
|
"opera": "51",
|
||||||
|
"edge": "79",
|
||||||
|
"firefox": "78",
|
||||||
|
"safari": "11.1",
|
||||||
|
"node": "10",
|
||||||
|
"deno": "1",
|
||||||
|
"ios": "11.3",
|
||||||
|
"samsung": "9",
|
||||||
|
"rhino": "1.9",
|
||||||
|
"opera_mobile": "47",
|
||||||
|
"electron": "3.0"
|
||||||
|
},
|
||||||
|
"transform-async-to-generator": {
|
||||||
|
"chrome": "55",
|
||||||
|
"opera": "42",
|
||||||
|
"edge": "15",
|
||||||
|
"firefox": "52",
|
||||||
|
"safari": "11",
|
||||||
|
"node": "7.6",
|
||||||
|
"deno": "1",
|
||||||
|
"ios": "11",
|
||||||
|
"samsung": "6",
|
||||||
|
"opera_mobile": "42",
|
||||||
|
"electron": "1.6"
|
||||||
|
},
|
||||||
|
"transform-exponentiation-operator": {
|
||||||
|
"chrome": "52",
|
||||||
|
"opera": "39",
|
||||||
|
"edge": "14",
|
||||||
|
"firefox": "52",
|
||||||
|
"safari": "10.1",
|
||||||
|
"node": "7",
|
||||||
|
"deno": "1",
|
||||||
|
"ios": "10.3",
|
||||||
|
"samsung": "6",
|
||||||
|
"rhino": "1.7.14",
|
||||||
|
"opera_mobile": "41",
|
||||||
|
"electron": "1.3"
|
||||||
|
},
|
||||||
|
"transform-template-literals": {
|
||||||
|
"chrome": "41",
|
||||||
|
"opera": "28",
|
||||||
|
"edge": "13",
|
||||||
|
"firefox": "34",
|
||||||
|
"safari": "13",
|
||||||
|
"node": "4",
|
||||||
|
"deno": "1",
|
||||||
|
"ios": "13",
|
||||||
|
"samsung": "3.4",
|
||||||
|
"rhino": "1.9",
|
||||||
|
"opera_mobile": "28",
|
||||||
|
"electron": "0.21"
|
||||||
|
},
|
||||||
|
"transform-literals": {
|
||||||
|
"chrome": "44",
|
||||||
|
"opera": "31",
|
||||||
|
"edge": "12",
|
||||||
|
"firefox": "53",
|
||||||
|
"safari": "9",
|
||||||
|
"node": "4",
|
||||||
|
"deno": "1",
|
||||||
|
"ios": "9",
|
||||||
|
"samsung": "4",
|
||||||
|
"rhino": "1.7.15",
|
||||||
|
"opera_mobile": "32",
|
||||||
|
"electron": "0.30"
|
||||||
|
},
|
||||||
|
"transform-function-name": {
|
||||||
|
"chrome": "51",
|
||||||
|
"opera": "38",
|
||||||
|
"edge": "79",
|
||||||
|
"firefox": "53",
|
||||||
|
"safari": "10",
|
||||||
|
"node": "6.5",
|
||||||
|
"deno": "1",
|
||||||
|
"ios": "10",
|
||||||
|
"samsung": "5",
|
||||||
|
"opera_mobile": "41",
|
||||||
|
"electron": "1.2"
|
||||||
|
},
|
||||||
|
"transform-arrow-functions": {
|
||||||
|
"chrome": "47",
|
||||||
|
"opera": "34",
|
||||||
|
"edge": "13",
|
||||||
|
"firefox": "43",
|
||||||
|
"safari": "10",
|
||||||
|
"node": "6",
|
||||||
|
"deno": "1",
|
||||||
|
"ios": "10",
|
||||||
|
"samsung": "5",
|
||||||
|
"rhino": "1.7.13",
|
||||||
|
"opera_mobile": "34",
|
||||||
|
"electron": "0.36"
|
||||||
|
},
|
||||||
|
"transform-block-scoped-functions": {
|
||||||
|
"chrome": "41",
|
||||||
|
"opera": "28",
|
||||||
|
"edge": "12",
|
||||||
|
"firefox": "46",
|
||||||
|
"safari": "10",
|
||||||
|
"node": "4",
|
||||||
|
"deno": "1",
|
||||||
|
"ie": "11",
|
||||||
|
"ios": "10",
|
||||||
|
"samsung": "3.4",
|
||||||
|
"opera_mobile": "28",
|
||||||
|
"electron": "0.21"
|
||||||
|
},
|
||||||
|
"transform-classes": {
|
||||||
|
"chrome": "46",
|
||||||
|
"opera": "33",
|
||||||
|
"edge": "13",
|
||||||
|
"firefox": "45",
|
||||||
|
"safari": "10",
|
||||||
|
"node": "5",
|
||||||
|
"deno": "1",
|
||||||
|
"ios": "10",
|
||||||
|
"samsung": "5",
|
||||||
|
"opera_mobile": "33",
|
||||||
|
"electron": "0.36"
|
||||||
|
},
|
||||||
|
"transform-object-super": {
|
||||||
|
"chrome": "46",
|
||||||
|
"opera": "33",
|
||||||
|
"edge": "13",
|
||||||
|
"firefox": "45",
|
||||||
|
"safari": "10",
|
||||||
|
"node": "5",
|
||||||
|
"deno": "1",
|
||||||
|
"ios": "10",
|
||||||
|
"samsung": "5",
|
||||||
|
"opera_mobile": "33",
|
||||||
|
"electron": "0.36"
|
||||||
|
},
|
||||||
|
"transform-shorthand-properties": {
|
||||||
|
"chrome": "43",
|
||||||
|
"opera": "30",
|
||||||
|
"edge": "12",
|
||||||
|
"firefox": "33",
|
||||||
|
"safari": "9",
|
||||||
|
"node": "4",
|
||||||
|
"deno": "1",
|
||||||
|
"ios": "9",
|
||||||
|
"samsung": "4",
|
||||||
|
"rhino": "1.7.14",
|
||||||
|
"opera_mobile": "30",
|
||||||
|
"electron": "0.27"
|
||||||
|
},
|
||||||
|
"transform-duplicate-keys": {
|
||||||
|
"chrome": "42",
|
||||||
|
"opera": "29",
|
||||||
|
"edge": "12",
|
||||||
|
"firefox": "34",
|
||||||
|
"safari": "9",
|
||||||
|
"node": "4",
|
||||||
|
"deno": "1",
|
||||||
|
"ios": "9",
|
||||||
|
"samsung": "3.4",
|
||||||
|
"opera_mobile": "29",
|
||||||
|
"electron": "0.25"
|
||||||
|
},
|
||||||
|
"transform-computed-properties": {
|
||||||
|
"chrome": "44",
|
||||||
|
"opera": "31",
|
||||||
|
"edge": "12",
|
||||||
|
"firefox": "34",
|
||||||
|
"safari": "7.1",
|
||||||
|
"node": "4",
|
||||||
|
"deno": "1",
|
||||||
|
"ios": "8",
|
||||||
|
"samsung": "4",
|
||||||
|
"rhino": "1.8",
|
||||||
|
"opera_mobile": "32",
|
||||||
|
"electron": "0.30"
|
||||||
|
},
|
||||||
|
"transform-for-of": {
|
||||||
|
"chrome": "51",
|
||||||
|
"opera": "38",
|
||||||
|
"edge": "15",
|
||||||
|
"firefox": "53",
|
||||||
|
"safari": "10",
|
||||||
|
"node": "6.5",
|
||||||
|
"deno": "1",
|
||||||
|
"ios": "10",
|
||||||
|
"samsung": "5",
|
||||||
|
"opera_mobile": "41",
|
||||||
|
"electron": "1.2"
|
||||||
|
},
|
||||||
|
"transform-sticky-regex": {
|
||||||
|
"chrome": "49",
|
||||||
|
"opera": "36",
|
||||||
|
"edge": "13",
|
||||||
|
"firefox": "3",
|
||||||
|
"safari": "10",
|
||||||
|
"node": "6",
|
||||||
|
"deno": "1",
|
||||||
|
"ios": "10",
|
||||||
|
"samsung": "5",
|
||||||
|
"rhino": "1.7.15",
|
||||||
|
"opera_mobile": "36",
|
||||||
|
"electron": "0.37"
|
||||||
|
},
|
||||||
|
"transform-unicode-escapes": {
|
||||||
|
"chrome": "44",
|
||||||
|
"opera": "31",
|
||||||
|
"edge": "12",
|
||||||
|
"firefox": "53",
|
||||||
|
"safari": "9",
|
||||||
|
"node": "4",
|
||||||
|
"deno": "1",
|
||||||
|
"ios": "9",
|
||||||
|
"samsung": "4",
|
||||||
|
"rhino": "1.7.15",
|
||||||
|
"opera_mobile": "32",
|
||||||
|
"electron": "0.30"
|
||||||
|
},
|
||||||
|
"transform-unicode-regex": {
|
||||||
|
"chrome": "50",
|
||||||
|
"opera": "37",
|
||||||
|
"edge": "13",
|
||||||
|
"firefox": "46",
|
||||||
|
"safari": "12",
|
||||||
|
"node": "6",
|
||||||
|
"deno": "1",
|
||||||
|
"ios": "12",
|
||||||
|
"samsung": "5",
|
||||||
|
"opera_mobile": "37",
|
||||||
|
"electron": "1.1"
|
||||||
|
},
|
||||||
|
"transform-spread": {
|
||||||
|
"chrome": "46",
|
||||||
|
"opera": "33",
|
||||||
|
"edge": "13",
|
||||||
|
"firefox": "45",
|
||||||
|
"safari": "10",
|
||||||
|
"node": "5",
|
||||||
|
"deno": "1",
|
||||||
|
"ios": "10",
|
||||||
|
"samsung": "5",
|
||||||
|
"opera_mobile": "33",
|
||||||
|
"electron": "0.36"
|
||||||
|
},
|
||||||
|
"transform-destructuring": {
|
||||||
|
"chrome": "51",
|
||||||
|
"opera": "38",
|
||||||
|
"edge": "15",
|
||||||
|
"firefox": "53",
|
||||||
|
"safari": "14.1",
|
||||||
|
"node": "6.5",
|
||||||
|
"deno": "1",
|
||||||
|
"ios": "14.5",
|
||||||
|
"samsung": "5",
|
||||||
|
"opera_mobile": "41",
|
||||||
|
"electron": "1.2"
|
||||||
|
},
|
||||||
|
"transform-block-scoping": {
|
||||||
|
"chrome": "50",
|
||||||
|
"opera": "37",
|
||||||
|
"edge": "14",
|
||||||
|
"firefox": "53",
|
||||||
|
"safari": "11",
|
||||||
|
"node": "6",
|
||||||
|
"deno": "1",
|
||||||
|
"ios": "11",
|
||||||
|
"samsung": "5",
|
||||||
|
"opera_mobile": "37",
|
||||||
|
"electron": "1.1"
|
||||||
|
},
|
||||||
|
"transform-typeof-symbol": {
|
||||||
|
"chrome": "48",
|
||||||
|
"opera": "35",
|
||||||
|
"edge": "12",
|
||||||
|
"firefox": "36",
|
||||||
|
"safari": "9",
|
||||||
|
"node": "6",
|
||||||
|
"deno": "1",
|
||||||
|
"ios": "9",
|
||||||
|
"samsung": "5",
|
||||||
|
"rhino": "1.8",
|
||||||
|
"opera_mobile": "35",
|
||||||
|
"electron": "0.37"
|
||||||
|
},
|
||||||
|
"transform-new-target": {
|
||||||
|
"chrome": "46",
|
||||||
|
"opera": "33",
|
||||||
|
"edge": "14",
|
||||||
|
"firefox": "41",
|
||||||
|
"safari": "10",
|
||||||
|
"node": "5",
|
||||||
|
"deno": "1",
|
||||||
|
"ios": "10",
|
||||||
|
"samsung": "5",
|
||||||
|
"opera_mobile": "33",
|
||||||
|
"electron": "0.36"
|
||||||
|
},
|
||||||
|
"transform-regenerator": {
|
||||||
|
"chrome": "50",
|
||||||
|
"opera": "37",
|
||||||
|
"edge": "13",
|
||||||
|
"firefox": "53",
|
||||||
|
"safari": "10",
|
||||||
|
"node": "6",
|
||||||
|
"deno": "1",
|
||||||
|
"ios": "10",
|
||||||
|
"samsung": "5",
|
||||||
|
"opera_mobile": "37",
|
||||||
|
"electron": "1.1"
|
||||||
|
},
|
||||||
|
"transform-member-expression-literals": {
|
||||||
|
"chrome": "7",
|
||||||
|
"opera": "12",
|
||||||
|
"edge": "12",
|
||||||
|
"firefox": "2",
|
||||||
|
"safari": "5.1",
|
||||||
|
"node": "0.4",
|
||||||
|
"deno": "1",
|
||||||
|
"ie": "9",
|
||||||
|
"android": "4",
|
||||||
|
"ios": "6",
|
||||||
|
"phantom": "1.9",
|
||||||
|
"samsung": "1",
|
||||||
|
"rhino": "1.7.13",
|
||||||
|
"opera_mobile": "12",
|
||||||
|
"electron": "0.20"
|
||||||
|
},
|
||||||
|
"transform-property-literals": {
|
||||||
|
"chrome": "7",
|
||||||
|
"opera": "12",
|
||||||
|
"edge": "12",
|
||||||
|
"firefox": "2",
|
||||||
|
"safari": "5.1",
|
||||||
|
"node": "0.4",
|
||||||
|
"deno": "1",
|
||||||
|
"ie": "9",
|
||||||
|
"android": "4",
|
||||||
|
"ios": "6",
|
||||||
|
"phantom": "1.9",
|
||||||
|
"samsung": "1",
|
||||||
|
"rhino": "1.7.13",
|
||||||
|
"opera_mobile": "12",
|
||||||
|
"electron": "0.20"
|
||||||
|
},
|
||||||
|
"transform-reserved-words": {
|
||||||
|
"chrome": "13",
|
||||||
|
"opera": "10.50",
|
||||||
|
"edge": "12",
|
||||||
|
"firefox": "2",
|
||||||
|
"safari": "3.1",
|
||||||
|
"node": "0.6",
|
||||||
|
"deno": "1",
|
||||||
|
"ie": "9",
|
||||||
|
"android": "4.4",
|
||||||
|
"ios": "6",
|
||||||
|
"phantom": "1.9",
|
||||||
|
"samsung": "1",
|
||||||
|
"rhino": "1.7.13",
|
||||||
|
"opera_mobile": "10.1",
|
||||||
|
"electron": "0.20"
|
||||||
|
},
|
||||||
|
"transform-export-namespace-from": {
|
||||||
|
"chrome": "72",
|
||||||
|
"deno": "1.0",
|
||||||
|
"edge": "79",
|
||||||
|
"firefox": "80",
|
||||||
|
"node": "13.2.0",
|
||||||
|
"opera": "60",
|
||||||
|
"opera_mobile": "51",
|
||||||
|
"safari": "14.1",
|
||||||
|
"ios": "14.5",
|
||||||
|
"samsung": "11.0",
|
||||||
|
"android": "72",
|
||||||
|
"electron": "5.0"
|
||||||
|
},
|
||||||
|
"proposal-export-namespace-from": {
|
||||||
|
"chrome": "72",
|
||||||
|
"deno": "1.0",
|
||||||
|
"edge": "79",
|
||||||
|
"firefox": "80",
|
||||||
|
"node": "13.2.0",
|
||||||
|
"opera": "60",
|
||||||
|
"opera_mobile": "51",
|
||||||
|
"safari": "14.1",
|
||||||
|
"ios": "14.5",
|
||||||
|
"samsung": "11.0",
|
||||||
|
"android": "72",
|
||||||
|
"electron": "5.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
+2
@@ -0,0 +1,2 @@
|
|||||||
|
// Todo (Babel 8): remove this file, in Babel 8 users import the .json directly
|
||||||
|
module.exports = require("./data/native-modules.json");
|
||||||
+2
@@ -0,0 +1,2 @@
|
|||||||
|
// Todo (Babel 8): remove this file, in Babel 8 users import the .json directly
|
||||||
|
module.exports = require("./data/overlapping-plugins.json");
|
||||||
+40
@@ -0,0 +1,40 @@
|
|||||||
|
{
|
||||||
|
"name": "@babel/compat-data",
|
||||||
|
"version": "7.29.7",
|
||||||
|
"author": "The Babel Team (https://babel.dev/team)",
|
||||||
|
"license": "MIT",
|
||||||
|
"description": "The compat-data to determine required Babel plugins",
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/babel/babel.git",
|
||||||
|
"directory": "packages/babel-compat-data"
|
||||||
|
},
|
||||||
|
"publishConfig": {
|
||||||
|
"access": "public"
|
||||||
|
},
|
||||||
|
"exports": {
|
||||||
|
"./plugins": "./plugins.js",
|
||||||
|
"./native-modules": "./native-modules.js",
|
||||||
|
"./corejs2-built-ins": "./corejs2-built-ins.js",
|
||||||
|
"./corejs3-shipped-proposals": "./corejs3-shipped-proposals.js",
|
||||||
|
"./overlapping-plugins": "./overlapping-plugins.js",
|
||||||
|
"./plugin-bugfixes": "./plugin-bugfixes.js"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"build-data": "./scripts/download-compat-table.sh && node ./scripts/build-data.mjs && node ./scripts/build-modules-support.mjs && node ./scripts/build-bugfixes-targets.mjs"
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"babel",
|
||||||
|
"compat-table",
|
||||||
|
"compat-data"
|
||||||
|
],
|
||||||
|
"devDependencies": {
|
||||||
|
"@mdn/browser-compat-data": "^6.0.8",
|
||||||
|
"core-js-compat": "^3.48.0",
|
||||||
|
"electron-to-chromium": "^1.5.278"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.9.0"
|
||||||
|
},
|
||||||
|
"type": "commonjs"
|
||||||
|
}
|
||||||
+2
@@ -0,0 +1,2 @@
|
|||||||
|
// Todo (Babel 8): remove this file, in Babel 8 users import the .json directly
|
||||||
|
module.exports = require("./data/plugin-bugfixes.json");
|
||||||
+2
@@ -0,0 +1,2 @@
|
|||||||
|
// Todo (Babel 8): remove this file, in Babel 8 users import the .json directly
|
||||||
|
module.exports = require("./data/plugins.json");
|
||||||
+22
@@ -0,0 +1,22 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2014-present Sebastian McKenzie and other contributors
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
a copy of this software and associated documentation files (the
|
||||||
|
"Software"), to deal in the Software without restriction, including
|
||||||
|
without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be
|
||||||
|
included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
+19
@@ -0,0 +1,19 @@
|
|||||||
|
# @babel/core
|
||||||
|
|
||||||
|
> Babel compiler core.
|
||||||
|
|
||||||
|
See our website [@babel/core](https://babeljs.io/docs/babel-core) for more information or the [issues](https://github.com/babel/babel/issues?utf8=%E2%9C%93&q=is%3Aissue+label%3A%22pkg%3A%20core%22+is%3Aopen) associated with this package.
|
||||||
|
|
||||||
|
## Install
|
||||||
|
|
||||||
|
Using npm:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
npm install --save-dev @babel/core
|
||||||
|
```
|
||||||
|
|
||||||
|
or using yarn:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
yarn add @babel/core --dev
|
||||||
|
```
|
||||||
+5
@@ -0,0 +1,5 @@
|
|||||||
|
"use strict";
|
||||||
|
|
||||||
|
0 && 0;
|
||||||
|
|
||||||
|
//# sourceMappingURL=cache-contexts.js.map
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
{"version":3,"names":[],"sources":["../../src/config/cache-contexts.ts"],"sourcesContent":["import type { ConfigContext } from \"./config-chain.ts\";\nimport type {\n CallerMetadata,\n TargetsListOrObject,\n} from \"./validation/options.ts\";\n\nexport type { ConfigContext as FullConfig };\n\nexport type FullPreset = {\n targets: TargetsListOrObject;\n} & ConfigContext;\nexport type FullPlugin = {\n assumptions: Record<string, boolean>;\n} & FullPreset;\n\n// Context not including filename since it is used in places that cannot\n// process 'ignore'/'only' and other filename-based logic.\nexport type SimpleConfig = {\n envName: string;\n caller: CallerMetadata | undefined;\n};\nexport type SimplePreset = {\n targets: TargetsListOrObject;\n} & SimpleConfig;\nexport type SimplePlugin = {\n assumptions: Record<string, boolean>;\n} & SimplePreset;\n"],"mappings":"","ignoreList":[]}
|
||||||
+261
@@ -0,0 +1,261 @@
|
|||||||
|
"use strict";
|
||||||
|
|
||||||
|
Object.defineProperty(exports, "__esModule", {
|
||||||
|
value: true
|
||||||
|
});
|
||||||
|
exports.assertSimpleType = assertSimpleType;
|
||||||
|
exports.makeStrongCache = makeStrongCache;
|
||||||
|
exports.makeStrongCacheSync = makeStrongCacheSync;
|
||||||
|
exports.makeWeakCache = makeWeakCache;
|
||||||
|
exports.makeWeakCacheSync = makeWeakCacheSync;
|
||||||
|
function _gensync() {
|
||||||
|
const data = require("gensync");
|
||||||
|
_gensync = function () {
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
var _async = require("../gensync-utils/async.js");
|
||||||
|
var _util = require("./util.js");
|
||||||
|
const synchronize = gen => {
|
||||||
|
return _gensync()(gen).sync;
|
||||||
|
};
|
||||||
|
function* genTrue() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
function makeWeakCache(handler) {
|
||||||
|
return makeCachedFunction(WeakMap, handler);
|
||||||
|
}
|
||||||
|
function makeWeakCacheSync(handler) {
|
||||||
|
return synchronize(makeWeakCache(handler));
|
||||||
|
}
|
||||||
|
function makeStrongCache(handler) {
|
||||||
|
return makeCachedFunction(Map, handler);
|
||||||
|
}
|
||||||
|
function makeStrongCacheSync(handler) {
|
||||||
|
return synchronize(makeStrongCache(handler));
|
||||||
|
}
|
||||||
|
function makeCachedFunction(CallCache, handler) {
|
||||||
|
const callCacheSync = new CallCache();
|
||||||
|
const callCacheAsync = new CallCache();
|
||||||
|
const futureCache = new CallCache();
|
||||||
|
return function* cachedFunction(arg, data) {
|
||||||
|
const asyncContext = yield* (0, _async.isAsync)();
|
||||||
|
const callCache = asyncContext ? callCacheAsync : callCacheSync;
|
||||||
|
const cached = yield* getCachedValueOrWait(asyncContext, callCache, futureCache, arg, data);
|
||||||
|
if (cached.valid) return cached.value;
|
||||||
|
const cache = new CacheConfigurator(data);
|
||||||
|
const handlerResult = handler(arg, cache);
|
||||||
|
let finishLock;
|
||||||
|
let value;
|
||||||
|
if ((0, _util.isIterableIterator)(handlerResult)) {
|
||||||
|
value = yield* (0, _async.onFirstPause)(handlerResult, () => {
|
||||||
|
finishLock = setupAsyncLocks(cache, futureCache, arg);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
value = handlerResult;
|
||||||
|
}
|
||||||
|
updateFunctionCache(callCache, cache, arg, value);
|
||||||
|
if (finishLock) {
|
||||||
|
futureCache.delete(arg);
|
||||||
|
finishLock.release(value);
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
function* getCachedValue(cache, arg, data) {
|
||||||
|
const cachedValue = cache.get(arg);
|
||||||
|
if (cachedValue) {
|
||||||
|
for (const {
|
||||||
|
value,
|
||||||
|
valid
|
||||||
|
} of cachedValue) {
|
||||||
|
if (yield* valid(data)) return {
|
||||||
|
valid: true,
|
||||||
|
value
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
valid: false,
|
||||||
|
value: null
|
||||||
|
};
|
||||||
|
}
|
||||||
|
function* getCachedValueOrWait(asyncContext, callCache, futureCache, arg, data) {
|
||||||
|
const cached = yield* getCachedValue(callCache, arg, data);
|
||||||
|
if (cached.valid) {
|
||||||
|
return cached;
|
||||||
|
}
|
||||||
|
if (asyncContext) {
|
||||||
|
const cached = yield* getCachedValue(futureCache, arg, data);
|
||||||
|
if (cached.valid) {
|
||||||
|
const value = yield* (0, _async.waitFor)(cached.value.promise);
|
||||||
|
return {
|
||||||
|
valid: true,
|
||||||
|
value
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
valid: false,
|
||||||
|
value: null
|
||||||
|
};
|
||||||
|
}
|
||||||
|
function setupAsyncLocks(config, futureCache, arg) {
|
||||||
|
const finishLock = new Lock();
|
||||||
|
updateFunctionCache(futureCache, config, arg, finishLock);
|
||||||
|
return finishLock;
|
||||||
|
}
|
||||||
|
function updateFunctionCache(cache, config, arg, value) {
|
||||||
|
if (!config.configured()) config.forever();
|
||||||
|
let cachedValue = cache.get(arg);
|
||||||
|
config.deactivate();
|
||||||
|
switch (config.mode()) {
|
||||||
|
case "forever":
|
||||||
|
cachedValue = [{
|
||||||
|
value,
|
||||||
|
valid: genTrue
|
||||||
|
}];
|
||||||
|
cache.set(arg, cachedValue);
|
||||||
|
break;
|
||||||
|
case "invalidate":
|
||||||
|
cachedValue = [{
|
||||||
|
value,
|
||||||
|
valid: config.validator()
|
||||||
|
}];
|
||||||
|
cache.set(arg, cachedValue);
|
||||||
|
break;
|
||||||
|
case "valid":
|
||||||
|
if (cachedValue) {
|
||||||
|
cachedValue.push({
|
||||||
|
value,
|
||||||
|
valid: config.validator()
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
cachedValue = [{
|
||||||
|
value,
|
||||||
|
valid: config.validator()
|
||||||
|
}];
|
||||||
|
cache.set(arg, cachedValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class CacheConfigurator {
|
||||||
|
constructor(data) {
|
||||||
|
this._active = true;
|
||||||
|
this._never = false;
|
||||||
|
this._forever = false;
|
||||||
|
this._invalidate = false;
|
||||||
|
this._configured = false;
|
||||||
|
this._pairs = [];
|
||||||
|
this._data = void 0;
|
||||||
|
this._data = data;
|
||||||
|
}
|
||||||
|
simple() {
|
||||||
|
return makeSimpleConfigurator(this);
|
||||||
|
}
|
||||||
|
mode() {
|
||||||
|
if (this._never) return "never";
|
||||||
|
if (this._forever) return "forever";
|
||||||
|
if (this._invalidate) return "invalidate";
|
||||||
|
return "valid";
|
||||||
|
}
|
||||||
|
forever() {
|
||||||
|
if (!this._active) {
|
||||||
|
throw new Error("Cannot change caching after evaluation has completed.");
|
||||||
|
}
|
||||||
|
if (this._never) {
|
||||||
|
throw new Error("Caching has already been configured with .never()");
|
||||||
|
}
|
||||||
|
this._forever = true;
|
||||||
|
this._configured = true;
|
||||||
|
}
|
||||||
|
never() {
|
||||||
|
if (!this._active) {
|
||||||
|
throw new Error("Cannot change caching after evaluation has completed.");
|
||||||
|
}
|
||||||
|
if (this._forever) {
|
||||||
|
throw new Error("Caching has already been configured with .forever()");
|
||||||
|
}
|
||||||
|
this._never = true;
|
||||||
|
this._configured = true;
|
||||||
|
}
|
||||||
|
using(handler) {
|
||||||
|
if (!this._active) {
|
||||||
|
throw new Error("Cannot change caching after evaluation has completed.");
|
||||||
|
}
|
||||||
|
if (this._never || this._forever) {
|
||||||
|
throw new Error("Caching has already been configured with .never or .forever()");
|
||||||
|
}
|
||||||
|
this._configured = true;
|
||||||
|
const key = handler(this._data);
|
||||||
|
const fn = (0, _async.maybeAsync)(handler, `You appear to be using an async cache handler, but Babel has been called synchronously`);
|
||||||
|
if ((0, _async.isThenable)(key)) {
|
||||||
|
return key.then(key => {
|
||||||
|
this._pairs.push([key, fn]);
|
||||||
|
return key;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
this._pairs.push([key, fn]);
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
invalidate(handler) {
|
||||||
|
this._invalidate = true;
|
||||||
|
return this.using(handler);
|
||||||
|
}
|
||||||
|
validator() {
|
||||||
|
const pairs = this._pairs;
|
||||||
|
return function* (data) {
|
||||||
|
for (const [key, fn] of pairs) {
|
||||||
|
if (key !== (yield* fn(data))) return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
deactivate() {
|
||||||
|
this._active = false;
|
||||||
|
}
|
||||||
|
configured() {
|
||||||
|
return this._configured;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function makeSimpleConfigurator(cache) {
|
||||||
|
function cacheFn(val) {
|
||||||
|
if (typeof val === "boolean") {
|
||||||
|
if (val) cache.forever();else cache.never();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
return cache.using(() => assertSimpleType(val()));
|
||||||
|
}
|
||||||
|
cacheFn.forever = () => cache.forever();
|
||||||
|
cacheFn.never = () => cache.never();
|
||||||
|
cacheFn.using = cb => cache.using(() => assertSimpleType(cb()));
|
||||||
|
cacheFn.invalidate = cb => cache.invalidate(() => assertSimpleType(cb()));
|
||||||
|
return cacheFn;
|
||||||
|
}
|
||||||
|
function assertSimpleType(value) {
|
||||||
|
if ((0, _async.isThenable)(value)) {
|
||||||
|
throw new Error(`You appear to be using an async cache handler, ` + `which your current version of Babel does not support. ` + `We may add support for this in the future, ` + `but if you're on the most recent version of @babel/core and still ` + `seeing this error, then you'll need to synchronously handle your caching logic.`);
|
||||||
|
}
|
||||||
|
if (value != null && typeof value !== "string" && typeof value !== "boolean" && typeof value !== "number") {
|
||||||
|
throw new Error("Cache keys must be either string, boolean, number, null, or undefined.");
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
class Lock {
|
||||||
|
constructor() {
|
||||||
|
this.released = false;
|
||||||
|
this.promise = void 0;
|
||||||
|
this._resolve = void 0;
|
||||||
|
this.promise = new Promise(resolve => {
|
||||||
|
this._resolve = resolve;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
release(value) {
|
||||||
|
this.released = true;
|
||||||
|
this._resolve(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
0 && 0;
|
||||||
|
|
||||||
|
//# sourceMappingURL=caching.js.map
|
||||||
+1
File diff suppressed because one or more lines are too long
+469
@@ -0,0 +1,469 @@
|
|||||||
|
"use strict";
|
||||||
|
|
||||||
|
Object.defineProperty(exports, "__esModule", {
|
||||||
|
value: true
|
||||||
|
});
|
||||||
|
exports.buildPresetChain = buildPresetChain;
|
||||||
|
exports.buildPresetChainWalker = void 0;
|
||||||
|
exports.buildRootChain = buildRootChain;
|
||||||
|
function _path() {
|
||||||
|
const data = require("path");
|
||||||
|
_path = function () {
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
function _debug() {
|
||||||
|
const data = require("debug");
|
||||||
|
_debug = function () {
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
var _options = require("./validation/options.js");
|
||||||
|
var _patternToRegex = require("./pattern-to-regex.js");
|
||||||
|
var _printer = require("./printer.js");
|
||||||
|
var _rewriteStackTrace = require("../errors/rewrite-stack-trace.js");
|
||||||
|
var _configError = require("../errors/config-error.js");
|
||||||
|
var _index = require("./files/index.js");
|
||||||
|
var _caching = require("./caching.js");
|
||||||
|
var _configDescriptors = require("./config-descriptors.js");
|
||||||
|
const debug = _debug()("babel:config:config-chain");
|
||||||
|
function* buildPresetChain(arg, context) {
|
||||||
|
const chain = yield* buildPresetChainWalker(arg, context);
|
||||||
|
if (!chain) return null;
|
||||||
|
return {
|
||||||
|
plugins: dedupDescriptors(chain.plugins),
|
||||||
|
presets: dedupDescriptors(chain.presets),
|
||||||
|
options: chain.options.map(o => createConfigChainOptions(o)),
|
||||||
|
files: new Set()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
const buildPresetChainWalker = exports.buildPresetChainWalker = makeChainWalker({
|
||||||
|
root: preset => loadPresetDescriptors(preset),
|
||||||
|
env: (preset, envName) => loadPresetEnvDescriptors(preset)(envName),
|
||||||
|
overrides: (preset, index) => loadPresetOverridesDescriptors(preset)(index),
|
||||||
|
overridesEnv: (preset, index, envName) => loadPresetOverridesEnvDescriptors(preset)(index)(envName),
|
||||||
|
createLogger: () => () => {}
|
||||||
|
});
|
||||||
|
const loadPresetDescriptors = (0, _caching.makeWeakCacheSync)(preset => buildRootDescriptors(preset, preset.alias, _configDescriptors.createUncachedDescriptors));
|
||||||
|
const loadPresetEnvDescriptors = (0, _caching.makeWeakCacheSync)(preset => (0, _caching.makeStrongCacheSync)(envName => buildEnvDescriptors(preset, preset.alias, _configDescriptors.createUncachedDescriptors, envName)));
|
||||||
|
const loadPresetOverridesDescriptors = (0, _caching.makeWeakCacheSync)(preset => (0, _caching.makeStrongCacheSync)(index => buildOverrideDescriptors(preset, preset.alias, _configDescriptors.createUncachedDescriptors, index)));
|
||||||
|
const loadPresetOverridesEnvDescriptors = (0, _caching.makeWeakCacheSync)(preset => (0, _caching.makeStrongCacheSync)(index => (0, _caching.makeStrongCacheSync)(envName => buildOverrideEnvDescriptors(preset, preset.alias, _configDescriptors.createUncachedDescriptors, index, envName))));
|
||||||
|
function* buildRootChain(opts, context) {
|
||||||
|
let configReport, babelRcReport;
|
||||||
|
const programmaticLogger = new _printer.ConfigPrinter();
|
||||||
|
const programmaticChain = yield* loadProgrammaticChain({
|
||||||
|
options: opts,
|
||||||
|
dirname: context.cwd
|
||||||
|
}, context, undefined, programmaticLogger);
|
||||||
|
if (!programmaticChain) return null;
|
||||||
|
const programmaticReport = yield* programmaticLogger.output();
|
||||||
|
let configFile;
|
||||||
|
if (typeof opts.configFile === "string") {
|
||||||
|
configFile = yield* (0, _index.loadConfig)(opts.configFile, context.cwd, context.envName, context.caller);
|
||||||
|
} else if (opts.configFile !== false) {
|
||||||
|
configFile = yield* (0, _index.findRootConfig)(context.root, context.envName, context.caller);
|
||||||
|
}
|
||||||
|
let {
|
||||||
|
babelrc,
|
||||||
|
babelrcRoots
|
||||||
|
} = opts;
|
||||||
|
let babelrcRootsDirectory = context.cwd;
|
||||||
|
const configFileChain = emptyChain();
|
||||||
|
const configFileLogger = new _printer.ConfigPrinter();
|
||||||
|
if (configFile) {
|
||||||
|
const validatedFile = validateConfigFile(configFile);
|
||||||
|
const result = yield* loadFileChain(validatedFile, context, undefined, configFileLogger);
|
||||||
|
if (!result) return null;
|
||||||
|
configReport = yield* configFileLogger.output();
|
||||||
|
if (babelrc === undefined) {
|
||||||
|
babelrc = validatedFile.options.babelrc;
|
||||||
|
}
|
||||||
|
if (babelrcRoots === undefined) {
|
||||||
|
babelrcRootsDirectory = validatedFile.dirname;
|
||||||
|
babelrcRoots = validatedFile.options.babelrcRoots;
|
||||||
|
}
|
||||||
|
mergeChain(configFileChain, result);
|
||||||
|
}
|
||||||
|
let ignoreFile, babelrcFile;
|
||||||
|
let isIgnored = false;
|
||||||
|
const fileChain = emptyChain();
|
||||||
|
if ((babelrc === true || babelrc === undefined) && typeof context.filename === "string") {
|
||||||
|
const pkgData = yield* (0, _index.findPackageData)(context.filename);
|
||||||
|
if (pkgData && babelrcLoadEnabled(context, pkgData, babelrcRoots, babelrcRootsDirectory)) {
|
||||||
|
({
|
||||||
|
ignore: ignoreFile,
|
||||||
|
config: babelrcFile
|
||||||
|
} = yield* (0, _index.findRelativeConfig)(pkgData, context.envName, context.caller));
|
||||||
|
if (ignoreFile) {
|
||||||
|
fileChain.files.add(ignoreFile.filepath);
|
||||||
|
}
|
||||||
|
if (ignoreFile && shouldIgnore(context, ignoreFile.ignore, null, ignoreFile.dirname)) {
|
||||||
|
isIgnored = true;
|
||||||
|
}
|
||||||
|
if (babelrcFile && !isIgnored) {
|
||||||
|
const validatedFile = validateBabelrcFile(babelrcFile);
|
||||||
|
const babelrcLogger = new _printer.ConfigPrinter();
|
||||||
|
const result = yield* loadFileChain(validatedFile, context, undefined, babelrcLogger);
|
||||||
|
if (!result) {
|
||||||
|
isIgnored = true;
|
||||||
|
} else {
|
||||||
|
babelRcReport = yield* babelrcLogger.output();
|
||||||
|
mergeChain(fileChain, result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (babelrcFile && isIgnored) {
|
||||||
|
fileChain.files.add(babelrcFile.filepath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (context.showConfig) {
|
||||||
|
console.log(`Babel configs on "${context.filename}" (ascending priority):\n` + [configReport, babelRcReport, programmaticReport].filter(x => !!x).join("\n\n") + "\n-----End Babel configs-----");
|
||||||
|
}
|
||||||
|
const chain = mergeChain(mergeChain(mergeChain(emptyChain(), configFileChain), fileChain), programmaticChain);
|
||||||
|
return {
|
||||||
|
plugins: isIgnored ? [] : dedupDescriptors(chain.plugins),
|
||||||
|
presets: isIgnored ? [] : dedupDescriptors(chain.presets),
|
||||||
|
options: isIgnored ? [] : chain.options.map(o => createConfigChainOptions(o)),
|
||||||
|
fileHandling: isIgnored ? "ignored" : "transpile",
|
||||||
|
ignore: ignoreFile || undefined,
|
||||||
|
babelrc: babelrcFile || undefined,
|
||||||
|
config: configFile || undefined,
|
||||||
|
files: chain.files
|
||||||
|
};
|
||||||
|
}
|
||||||
|
function babelrcLoadEnabled(context, pkgData, babelrcRoots, babelrcRootsDirectory) {
|
||||||
|
if (typeof babelrcRoots === "boolean") return babelrcRoots;
|
||||||
|
const absoluteRoot = context.root;
|
||||||
|
if (babelrcRoots === undefined) {
|
||||||
|
return pkgData.directories.includes(absoluteRoot);
|
||||||
|
}
|
||||||
|
let babelrcPatterns = babelrcRoots;
|
||||||
|
if (!Array.isArray(babelrcPatterns)) {
|
||||||
|
babelrcPatterns = [babelrcPatterns];
|
||||||
|
}
|
||||||
|
babelrcPatterns = babelrcPatterns.map(pat => {
|
||||||
|
return typeof pat === "string" ? _path().resolve(babelrcRootsDirectory, pat) : pat;
|
||||||
|
});
|
||||||
|
if (babelrcPatterns.length === 1 && babelrcPatterns[0] === absoluteRoot) {
|
||||||
|
return pkgData.directories.includes(absoluteRoot);
|
||||||
|
}
|
||||||
|
return babelrcPatterns.some(pat => {
|
||||||
|
if (typeof pat === "string") {
|
||||||
|
pat = (0, _patternToRegex.default)(pat, babelrcRootsDirectory);
|
||||||
|
}
|
||||||
|
return pkgData.directories.some(directory => {
|
||||||
|
return matchPattern(pat, babelrcRootsDirectory, directory, context);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const validateConfigFile = (0, _caching.makeWeakCacheSync)(file => ({
|
||||||
|
filepath: file.filepath,
|
||||||
|
dirname: file.dirname,
|
||||||
|
options: (0, _options.validate)("configfile", file.options, file.filepath)
|
||||||
|
}));
|
||||||
|
const validateBabelrcFile = (0, _caching.makeWeakCacheSync)(file => ({
|
||||||
|
filepath: file.filepath,
|
||||||
|
dirname: file.dirname,
|
||||||
|
options: (0, _options.validate)("babelrcfile", file.options, file.filepath)
|
||||||
|
}));
|
||||||
|
const validateExtendFile = (0, _caching.makeWeakCacheSync)(file => ({
|
||||||
|
filepath: file.filepath,
|
||||||
|
dirname: file.dirname,
|
||||||
|
options: (0, _options.validate)("extendsfile", file.options, file.filepath)
|
||||||
|
}));
|
||||||
|
const loadProgrammaticChain = makeChainWalker({
|
||||||
|
root: input => buildRootDescriptors(input, "base", _configDescriptors.createCachedDescriptors),
|
||||||
|
env: (input, envName) => buildEnvDescriptors(input, "base", _configDescriptors.createCachedDescriptors, envName),
|
||||||
|
overrides: (input, index) => buildOverrideDescriptors(input, "base", _configDescriptors.createCachedDescriptors, index),
|
||||||
|
overridesEnv: (input, index, envName) => buildOverrideEnvDescriptors(input, "base", _configDescriptors.createCachedDescriptors, index, envName),
|
||||||
|
createLogger: (input, context, baseLogger) => buildProgrammaticLogger(input, context, baseLogger)
|
||||||
|
});
|
||||||
|
const loadFileChainWalker = makeChainWalker({
|
||||||
|
root: file => loadFileDescriptors(file),
|
||||||
|
env: (file, envName) => loadFileEnvDescriptors(file)(envName),
|
||||||
|
overrides: (file, index) => loadFileOverridesDescriptors(file)(index),
|
||||||
|
overridesEnv: (file, index, envName) => loadFileOverridesEnvDescriptors(file)(index)(envName),
|
||||||
|
createLogger: (file, context, baseLogger) => buildFileLogger(file.filepath, context, baseLogger)
|
||||||
|
});
|
||||||
|
function* loadFileChain(input, context, files, baseLogger) {
|
||||||
|
const chain = yield* loadFileChainWalker(input, context, files, baseLogger);
|
||||||
|
chain == null || chain.files.add(input.filepath);
|
||||||
|
return chain;
|
||||||
|
}
|
||||||
|
const loadFileDescriptors = (0, _caching.makeWeakCacheSync)(file => buildRootDescriptors(file, file.filepath, _configDescriptors.createUncachedDescriptors));
|
||||||
|
const loadFileEnvDescriptors = (0, _caching.makeWeakCacheSync)(file => (0, _caching.makeStrongCacheSync)(envName => buildEnvDescriptors(file, file.filepath, _configDescriptors.createUncachedDescriptors, envName)));
|
||||||
|
const loadFileOverridesDescriptors = (0, _caching.makeWeakCacheSync)(file => (0, _caching.makeStrongCacheSync)(index => buildOverrideDescriptors(file, file.filepath, _configDescriptors.createUncachedDescriptors, index)));
|
||||||
|
const loadFileOverridesEnvDescriptors = (0, _caching.makeWeakCacheSync)(file => (0, _caching.makeStrongCacheSync)(index => (0, _caching.makeStrongCacheSync)(envName => buildOverrideEnvDescriptors(file, file.filepath, _configDescriptors.createUncachedDescriptors, index, envName))));
|
||||||
|
function buildFileLogger(filepath, context, baseLogger) {
|
||||||
|
if (!baseLogger) {
|
||||||
|
return () => {};
|
||||||
|
}
|
||||||
|
return baseLogger.configure(context.showConfig, _printer.ChainFormatter.Config, {
|
||||||
|
filepath
|
||||||
|
});
|
||||||
|
}
|
||||||
|
function buildRootDescriptors({
|
||||||
|
dirname,
|
||||||
|
options
|
||||||
|
}, alias, descriptors) {
|
||||||
|
return descriptors(dirname, options, alias);
|
||||||
|
}
|
||||||
|
function buildProgrammaticLogger(_, context, baseLogger) {
|
||||||
|
var _context$caller;
|
||||||
|
if (!baseLogger) {
|
||||||
|
return () => {};
|
||||||
|
}
|
||||||
|
return baseLogger.configure(context.showConfig, _printer.ChainFormatter.Programmatic, {
|
||||||
|
callerName: (_context$caller = context.caller) == null ? void 0 : _context$caller.name
|
||||||
|
});
|
||||||
|
}
|
||||||
|
function buildEnvDescriptors({
|
||||||
|
dirname,
|
||||||
|
options
|
||||||
|
}, alias, descriptors, envName) {
|
||||||
|
var _options$env;
|
||||||
|
const opts = (_options$env = options.env) == null ? void 0 : _options$env[envName];
|
||||||
|
return opts ? descriptors(dirname, opts, `${alias}.env["${envName}"]`) : null;
|
||||||
|
}
|
||||||
|
function buildOverrideDescriptors({
|
||||||
|
dirname,
|
||||||
|
options
|
||||||
|
}, alias, descriptors, index) {
|
||||||
|
var _options$overrides;
|
||||||
|
const opts = (_options$overrides = options.overrides) == null ? void 0 : _options$overrides[index];
|
||||||
|
if (!opts) throw new Error("Assertion failure - missing override");
|
||||||
|
return descriptors(dirname, opts, `${alias}.overrides[${index}]`);
|
||||||
|
}
|
||||||
|
function buildOverrideEnvDescriptors({
|
||||||
|
dirname,
|
||||||
|
options
|
||||||
|
}, alias, descriptors, index, envName) {
|
||||||
|
var _options$overrides2, _override$env;
|
||||||
|
const override = (_options$overrides2 = options.overrides) == null ? void 0 : _options$overrides2[index];
|
||||||
|
if (!override) throw new Error("Assertion failure - missing override");
|
||||||
|
const opts = (_override$env = override.env) == null ? void 0 : _override$env[envName];
|
||||||
|
return opts ? descriptors(dirname, opts, `${alias}.overrides[${index}].env["${envName}"]`) : null;
|
||||||
|
}
|
||||||
|
function makeChainWalker({
|
||||||
|
root,
|
||||||
|
env,
|
||||||
|
overrides,
|
||||||
|
overridesEnv,
|
||||||
|
createLogger
|
||||||
|
}) {
|
||||||
|
return function* chainWalker(input, context, files = new Set(), baseLogger) {
|
||||||
|
const {
|
||||||
|
dirname
|
||||||
|
} = input;
|
||||||
|
const flattenedConfigs = [];
|
||||||
|
const rootOpts = root(input);
|
||||||
|
if (configIsApplicable(rootOpts, dirname, context, input.filepath)) {
|
||||||
|
flattenedConfigs.push({
|
||||||
|
config: rootOpts,
|
||||||
|
envName: undefined,
|
||||||
|
index: undefined
|
||||||
|
});
|
||||||
|
const envOpts = env(input, context.envName);
|
||||||
|
if (envOpts && configIsApplicable(envOpts, dirname, context, input.filepath)) {
|
||||||
|
flattenedConfigs.push({
|
||||||
|
config: envOpts,
|
||||||
|
envName: context.envName,
|
||||||
|
index: undefined
|
||||||
|
});
|
||||||
|
}
|
||||||
|
(rootOpts.options.overrides || []).forEach((_, index) => {
|
||||||
|
const overrideOps = overrides(input, index);
|
||||||
|
if (configIsApplicable(overrideOps, dirname, context, input.filepath)) {
|
||||||
|
flattenedConfigs.push({
|
||||||
|
config: overrideOps,
|
||||||
|
index,
|
||||||
|
envName: undefined
|
||||||
|
});
|
||||||
|
const overrideEnvOpts = overridesEnv(input, index, context.envName);
|
||||||
|
if (overrideEnvOpts && configIsApplicable(overrideEnvOpts, dirname, context, input.filepath)) {
|
||||||
|
flattenedConfigs.push({
|
||||||
|
config: overrideEnvOpts,
|
||||||
|
index,
|
||||||
|
envName: context.envName
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (flattenedConfigs.some(({
|
||||||
|
config: {
|
||||||
|
options: {
|
||||||
|
ignore,
|
||||||
|
only
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}) => shouldIgnore(context, ignore, only, dirname))) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
const chain = emptyChain();
|
||||||
|
const logger = createLogger(input, context, baseLogger);
|
||||||
|
for (const {
|
||||||
|
config,
|
||||||
|
index,
|
||||||
|
envName
|
||||||
|
} of flattenedConfigs) {
|
||||||
|
if (!(yield* mergeExtendsChain(chain, config.options, dirname, context, files, baseLogger))) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
logger(config, index, envName);
|
||||||
|
yield* mergeChainOpts(chain, config);
|
||||||
|
}
|
||||||
|
return chain;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
function* mergeExtendsChain(chain, opts, dirname, context, files, baseLogger) {
|
||||||
|
if (opts.extends === undefined) return true;
|
||||||
|
const file = yield* (0, _index.loadConfig)(opts.extends, dirname, context.envName, context.caller);
|
||||||
|
if (files.has(file)) {
|
||||||
|
throw new Error(`Configuration cycle detected loading ${file.filepath}.\n` + `File already loaded following the config chain:\n` + Array.from(files, file => ` - ${file.filepath}`).join("\n"));
|
||||||
|
}
|
||||||
|
files.add(file);
|
||||||
|
const fileChain = yield* loadFileChain(validateExtendFile(file), context, files, baseLogger);
|
||||||
|
files.delete(file);
|
||||||
|
if (!fileChain) return false;
|
||||||
|
mergeChain(chain, fileChain);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
function mergeChain(target, source) {
|
||||||
|
target.options.push(...source.options);
|
||||||
|
target.plugins.push(...source.plugins);
|
||||||
|
target.presets.push(...source.presets);
|
||||||
|
for (const file of source.files) {
|
||||||
|
target.files.add(file);
|
||||||
|
}
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
function* mergeChainOpts(target, {
|
||||||
|
options,
|
||||||
|
plugins,
|
||||||
|
presets
|
||||||
|
}) {
|
||||||
|
target.options.push(options);
|
||||||
|
target.plugins.push(...(yield* plugins()));
|
||||||
|
target.presets.push(...(yield* presets()));
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
function emptyChain() {
|
||||||
|
return {
|
||||||
|
options: [],
|
||||||
|
presets: [],
|
||||||
|
plugins: [],
|
||||||
|
files: new Set()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
function createConfigChainOptions(opts) {
|
||||||
|
const options = Object.assign({}, opts);
|
||||||
|
delete options.extends;
|
||||||
|
delete options.env;
|
||||||
|
delete options.overrides;
|
||||||
|
delete options.plugins;
|
||||||
|
delete options.presets;
|
||||||
|
delete options.passPerPreset;
|
||||||
|
delete options.ignore;
|
||||||
|
delete options.only;
|
||||||
|
delete options.test;
|
||||||
|
delete options.include;
|
||||||
|
delete options.exclude;
|
||||||
|
if (hasOwnProperty.call(options, "sourceMap")) {
|
||||||
|
options.sourceMaps = options.sourceMap;
|
||||||
|
delete options.sourceMap;
|
||||||
|
}
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
function dedupDescriptors(items) {
|
||||||
|
const map = new Map();
|
||||||
|
const descriptors = [];
|
||||||
|
for (const item of items) {
|
||||||
|
if (typeof item.value === "function") {
|
||||||
|
const fnKey = item.value;
|
||||||
|
let nameMap = map.get(fnKey);
|
||||||
|
if (!nameMap) {
|
||||||
|
nameMap = new Map();
|
||||||
|
map.set(fnKey, nameMap);
|
||||||
|
}
|
||||||
|
let desc = nameMap.get(item.name);
|
||||||
|
if (!desc) {
|
||||||
|
desc = {
|
||||||
|
value: item
|
||||||
|
};
|
||||||
|
descriptors.push(desc);
|
||||||
|
if (!item.ownPass) nameMap.set(item.name, desc);
|
||||||
|
} else {
|
||||||
|
desc.value = item;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
descriptors.push({
|
||||||
|
value: item
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return descriptors.reduce((acc, desc) => {
|
||||||
|
acc.push(desc.value);
|
||||||
|
return acc;
|
||||||
|
}, []);
|
||||||
|
}
|
||||||
|
function configIsApplicable({
|
||||||
|
options
|
||||||
|
}, dirname, context, configName) {
|
||||||
|
return (options.test === undefined || configFieldIsApplicable(context, options.test, dirname, configName)) && (options.include === undefined || configFieldIsApplicable(context, options.include, dirname, configName)) && (options.exclude === undefined || !configFieldIsApplicable(context, options.exclude, dirname, configName));
|
||||||
|
}
|
||||||
|
function configFieldIsApplicable(context, test, dirname, configName) {
|
||||||
|
const patterns = Array.isArray(test) ? test : [test];
|
||||||
|
return matchesPatterns(context, patterns, dirname, configName);
|
||||||
|
}
|
||||||
|
function ignoreListReplacer(_key, value) {
|
||||||
|
if (value instanceof RegExp) {
|
||||||
|
return String(value);
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
function shouldIgnore(context, ignore, only, dirname) {
|
||||||
|
if (ignore && matchesPatterns(context, ignore, dirname)) {
|
||||||
|
var _context$filename;
|
||||||
|
const message = `No config is applied to "${(_context$filename = context.filename) != null ? _context$filename : "(unknown)"}" because it matches one of \`ignore: ${JSON.stringify(ignore, ignoreListReplacer)}\` from "${dirname}"`;
|
||||||
|
debug(message);
|
||||||
|
if (context.showConfig) {
|
||||||
|
console.log(message);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (only && !matchesPatterns(context, only, dirname)) {
|
||||||
|
var _context$filename2;
|
||||||
|
const message = `No config is applied to "${(_context$filename2 = context.filename) != null ? _context$filename2 : "(unknown)"}" because it fails to match one of \`only: ${JSON.stringify(only, ignoreListReplacer)}\` from "${dirname}"`;
|
||||||
|
debug(message);
|
||||||
|
if (context.showConfig) {
|
||||||
|
console.log(message);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
function matchesPatterns(context, patterns, dirname, configName) {
|
||||||
|
return patterns.some(pattern => matchPattern(pattern, dirname, context.filename, context, configName));
|
||||||
|
}
|
||||||
|
function matchPattern(pattern, dirname, pathToTest, context, configName) {
|
||||||
|
if (typeof pattern === "function") {
|
||||||
|
return !!(0, _rewriteStackTrace.endHiddenCallStack)(pattern)(pathToTest, {
|
||||||
|
dirname,
|
||||||
|
envName: context.envName,
|
||||||
|
caller: context.caller
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (typeof pathToTest !== "string") {
|
||||||
|
throw new _configError.default(`Configuration contains string/RegExp pattern, but no filename was passed to Babel`, configName);
|
||||||
|
}
|
||||||
|
if (typeof pattern === "string") {
|
||||||
|
pattern = (0, _patternToRegex.default)(pattern, dirname);
|
||||||
|
}
|
||||||
|
return pattern.test(pathToTest);
|
||||||
|
}
|
||||||
|
0 && 0;
|
||||||
|
|
||||||
|
//# sourceMappingURL=config-chain.js.map
|
||||||
+1
File diff suppressed because one or more lines are too long
+190
@@ -0,0 +1,190 @@
|
|||||||
|
"use strict";
|
||||||
|
|
||||||
|
Object.defineProperty(exports, "__esModule", {
|
||||||
|
value: true
|
||||||
|
});
|
||||||
|
exports.createCachedDescriptors = createCachedDescriptors;
|
||||||
|
exports.createDescriptor = createDescriptor;
|
||||||
|
exports.createUncachedDescriptors = createUncachedDescriptors;
|
||||||
|
function _gensync() {
|
||||||
|
const data = require("gensync");
|
||||||
|
_gensync = function () {
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
var _functional = require("../gensync-utils/functional.js");
|
||||||
|
var _index = require("./files/index.js");
|
||||||
|
var _item = require("./item.js");
|
||||||
|
var _caching = require("./caching.js");
|
||||||
|
var _resolveTargets = require("./resolve-targets.js");
|
||||||
|
function isEqualDescriptor(a, b) {
|
||||||
|
var _a$file, _b$file, _a$file2, _b$file2;
|
||||||
|
return a.name === b.name && a.value === b.value && a.options === b.options && a.dirname === b.dirname && a.alias === b.alias && a.ownPass === b.ownPass && ((_a$file = a.file) == null ? void 0 : _a$file.request) === ((_b$file = b.file) == null ? void 0 : _b$file.request) && ((_a$file2 = a.file) == null ? void 0 : _a$file2.resolved) === ((_b$file2 = b.file) == null ? void 0 : _b$file2.resolved);
|
||||||
|
}
|
||||||
|
function* handlerOf(value) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
function optionsWithResolvedBrowserslistConfigFile(options, dirname) {
|
||||||
|
if (typeof options.browserslistConfigFile === "string") {
|
||||||
|
options.browserslistConfigFile = (0, _resolveTargets.resolveBrowserslistConfigFile)(options.browserslistConfigFile, dirname);
|
||||||
|
}
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
function createCachedDescriptors(dirname, options, alias) {
|
||||||
|
const {
|
||||||
|
plugins,
|
||||||
|
presets,
|
||||||
|
passPerPreset
|
||||||
|
} = options;
|
||||||
|
return {
|
||||||
|
options: optionsWithResolvedBrowserslistConfigFile(options, dirname),
|
||||||
|
plugins: plugins ? () => createCachedPluginDescriptors(plugins, dirname)(alias) : () => handlerOf([]),
|
||||||
|
presets: presets ? () => createCachedPresetDescriptors(presets, dirname)(alias)(!!passPerPreset) : () => handlerOf([])
|
||||||
|
};
|
||||||
|
}
|
||||||
|
function createUncachedDescriptors(dirname, options, alias) {
|
||||||
|
return {
|
||||||
|
options: optionsWithResolvedBrowserslistConfigFile(options, dirname),
|
||||||
|
plugins: (0, _functional.once)(() => createPluginDescriptors(options.plugins || [], dirname, alias)),
|
||||||
|
presets: (0, _functional.once)(() => createPresetDescriptors(options.presets || [], dirname, alias, !!options.passPerPreset))
|
||||||
|
};
|
||||||
|
}
|
||||||
|
const PRESET_DESCRIPTOR_CACHE = new WeakMap();
|
||||||
|
const createCachedPresetDescriptors = (0, _caching.makeWeakCacheSync)((items, cache) => {
|
||||||
|
const dirname = cache.using(dir => dir);
|
||||||
|
return (0, _caching.makeStrongCacheSync)(alias => (0, _caching.makeStrongCache)(function* (passPerPreset) {
|
||||||
|
const descriptors = yield* createPresetDescriptors(items, dirname, alias, passPerPreset);
|
||||||
|
return descriptors.map(desc => loadCachedDescriptor(PRESET_DESCRIPTOR_CACHE, desc));
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
const PLUGIN_DESCRIPTOR_CACHE = new WeakMap();
|
||||||
|
const createCachedPluginDescriptors = (0, _caching.makeWeakCacheSync)((items, cache) => {
|
||||||
|
const dirname = cache.using(dir => dir);
|
||||||
|
return (0, _caching.makeStrongCache)(function* (alias) {
|
||||||
|
const descriptors = yield* createPluginDescriptors(items, dirname, alias);
|
||||||
|
return descriptors.map(desc => loadCachedDescriptor(PLUGIN_DESCRIPTOR_CACHE, desc));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
const DEFAULT_OPTIONS = {};
|
||||||
|
function loadCachedDescriptor(cache, desc) {
|
||||||
|
const {
|
||||||
|
value,
|
||||||
|
options = DEFAULT_OPTIONS
|
||||||
|
} = desc;
|
||||||
|
if (options === false) return desc;
|
||||||
|
let cacheByOptions = cache.get(value);
|
||||||
|
if (!cacheByOptions) {
|
||||||
|
cacheByOptions = new WeakMap();
|
||||||
|
cache.set(value, cacheByOptions);
|
||||||
|
}
|
||||||
|
let possibilities = cacheByOptions.get(options);
|
||||||
|
if (!possibilities) {
|
||||||
|
possibilities = [];
|
||||||
|
cacheByOptions.set(options, possibilities);
|
||||||
|
}
|
||||||
|
if (!possibilities.includes(desc)) {
|
||||||
|
const matches = possibilities.filter(possibility => isEqualDescriptor(possibility, desc));
|
||||||
|
if (matches.length > 0) {
|
||||||
|
return matches[0];
|
||||||
|
}
|
||||||
|
possibilities.push(desc);
|
||||||
|
}
|
||||||
|
return desc;
|
||||||
|
}
|
||||||
|
function* createPresetDescriptors(items, dirname, alias, passPerPreset) {
|
||||||
|
return yield* createDescriptors("preset", items, dirname, alias, passPerPreset);
|
||||||
|
}
|
||||||
|
function* createPluginDescriptors(items, dirname, alias) {
|
||||||
|
return yield* createDescriptors("plugin", items, dirname, alias);
|
||||||
|
}
|
||||||
|
function* createDescriptors(type, items, dirname, alias, ownPass) {
|
||||||
|
const descriptors = yield* _gensync().all(items.map((item, index) => createDescriptor(item, dirname, {
|
||||||
|
type,
|
||||||
|
alias: `${alias}$${index}`,
|
||||||
|
ownPass: !!ownPass
|
||||||
|
})));
|
||||||
|
assertNoDuplicates(descriptors);
|
||||||
|
return descriptors;
|
||||||
|
}
|
||||||
|
function* createDescriptor(pair, dirname, {
|
||||||
|
type,
|
||||||
|
alias,
|
||||||
|
ownPass
|
||||||
|
}) {
|
||||||
|
const desc = (0, _item.getItemDescriptor)(pair);
|
||||||
|
if (desc) {
|
||||||
|
return desc;
|
||||||
|
}
|
||||||
|
let name;
|
||||||
|
let options;
|
||||||
|
let value = pair;
|
||||||
|
if (Array.isArray(value)) {
|
||||||
|
if (value.length === 3) {
|
||||||
|
[value, options, name] = value;
|
||||||
|
} else {
|
||||||
|
[value, options] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let file = undefined;
|
||||||
|
let filepath = null;
|
||||||
|
if (typeof value === "string") {
|
||||||
|
if (typeof type !== "string") {
|
||||||
|
throw new Error("To resolve a string-based item, the type of item must be given");
|
||||||
|
}
|
||||||
|
const resolver = type === "plugin" ? _index.loadPlugin : _index.loadPreset;
|
||||||
|
const request = value;
|
||||||
|
({
|
||||||
|
filepath,
|
||||||
|
value
|
||||||
|
} = yield* resolver(value, dirname));
|
||||||
|
file = {
|
||||||
|
request,
|
||||||
|
resolved: filepath
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (!value) {
|
||||||
|
throw new Error(`Unexpected falsy value: ${String(value)}`);
|
||||||
|
}
|
||||||
|
if (typeof value === "object" && value.__esModule) {
|
||||||
|
if (value.default) {
|
||||||
|
value = value.default;
|
||||||
|
} else {
|
||||||
|
throw new Error("Must export a default export when using ES6 modules.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (typeof value !== "object" && typeof value !== "function") {
|
||||||
|
throw new Error(`Unsupported format: ${typeof value}. Expected an object or a function.`);
|
||||||
|
}
|
||||||
|
if (filepath !== null && typeof value === "object" && value) {
|
||||||
|
throw new Error(`Plugin/Preset files are not allowed to export objects, only functions. In ${filepath}`);
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
name,
|
||||||
|
alias: filepath || alias,
|
||||||
|
value,
|
||||||
|
options,
|
||||||
|
dirname,
|
||||||
|
ownPass,
|
||||||
|
file
|
||||||
|
};
|
||||||
|
}
|
||||||
|
function assertNoDuplicates(items) {
|
||||||
|
const map = new Map();
|
||||||
|
for (const item of items) {
|
||||||
|
if (typeof item.value !== "function") continue;
|
||||||
|
let nameMap = map.get(item.value);
|
||||||
|
if (!nameMap) {
|
||||||
|
nameMap = new Set();
|
||||||
|
map.set(item.value, nameMap);
|
||||||
|
}
|
||||||
|
if (nameMap.has(item.name)) {
|
||||||
|
const conflicts = items.filter(i => i.value === item.value);
|
||||||
|
throw new Error([`Duplicate plugin/preset detected.`, `If you'd like to use two separate instances of a plugin,`, `they need separate names, e.g.`, ``, ` plugins: [`, ` ['some-plugin', {}],`, ` ['some-plugin', {}, 'some unique name'],`, ` ]`, ``, `Duplicates detected are:`, `${JSON.stringify(conflicts, null, 2)}`].join("\n"));
|
||||||
|
}
|
||||||
|
nameMap.add(item.name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
0 && 0;
|
||||||
|
|
||||||
|
//# sourceMappingURL=config-descriptors.js.map
|
||||||
+1
File diff suppressed because one or more lines are too long
+290
@@ -0,0 +1,290 @@
|
|||||||
|
"use strict";
|
||||||
|
|
||||||
|
Object.defineProperty(exports, "__esModule", {
|
||||||
|
value: true
|
||||||
|
});
|
||||||
|
exports.ROOT_CONFIG_FILENAMES = void 0;
|
||||||
|
exports.findConfigUpwards = findConfigUpwards;
|
||||||
|
exports.findRelativeConfig = findRelativeConfig;
|
||||||
|
exports.findRootConfig = findRootConfig;
|
||||||
|
exports.loadConfig = loadConfig;
|
||||||
|
exports.resolveShowConfigPath = resolveShowConfigPath;
|
||||||
|
function _debug() {
|
||||||
|
const data = require("debug");
|
||||||
|
_debug = function () {
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
function _fs() {
|
||||||
|
const data = require("fs");
|
||||||
|
_fs = function () {
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
function _path() {
|
||||||
|
const data = require("path");
|
||||||
|
_path = function () {
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
function _json() {
|
||||||
|
const data = require("json5");
|
||||||
|
_json = function () {
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
function _gensync() {
|
||||||
|
const data = require("gensync");
|
||||||
|
_gensync = function () {
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
var _caching = require("../caching.js");
|
||||||
|
var _configApi = require("../helpers/config-api.js");
|
||||||
|
var _utils = require("./utils.js");
|
||||||
|
var _moduleTypes = require("./module-types.js");
|
||||||
|
var _patternToRegex = require("../pattern-to-regex.js");
|
||||||
|
var _configError = require("../../errors/config-error.js");
|
||||||
|
var fs = require("../../gensync-utils/fs.js");
|
||||||
|
require("module");
|
||||||
|
var _rewriteStackTrace = require("../../errors/rewrite-stack-trace.js");
|
||||||
|
var _async = require("../../gensync-utils/async.js");
|
||||||
|
const debug = _debug()("babel:config:loading:files:configuration");
|
||||||
|
const ROOT_CONFIG_FILENAMES = exports.ROOT_CONFIG_FILENAMES = ["babel.config.js", "babel.config.cjs", "babel.config.mjs", "babel.config.json", "babel.config.cts", "babel.config.ts", "babel.config.mts"];
|
||||||
|
const RELATIVE_CONFIG_FILENAMES = [".babelrc", ".babelrc.js", ".babelrc.cjs", ".babelrc.mjs", ".babelrc.json", ".babelrc.cts"];
|
||||||
|
const BABELIGNORE_FILENAME = ".babelignore";
|
||||||
|
const runConfig = (0, _caching.makeWeakCache)(function* runConfig(options, cache) {
|
||||||
|
yield* [];
|
||||||
|
return {
|
||||||
|
options: (0, _rewriteStackTrace.endHiddenCallStack)(options)((0, _configApi.makeConfigAPI)(cache)),
|
||||||
|
cacheNeedsConfiguration: !cache.configured()
|
||||||
|
};
|
||||||
|
});
|
||||||
|
function* readConfigCode(filepath, data) {
|
||||||
|
if (!_fs().existsSync(filepath)) return null;
|
||||||
|
let options = yield* (0, _moduleTypes.default)(filepath, (yield* (0, _async.isAsync)()) ? "auto" : "require", "You appear to be using a native ECMAScript module configuration " + "file, which is only supported when running Babel asynchronously " + "or when using the Node.js `--experimental-require-module` flag.", "You appear to be using a configuration file that contains top-level " + "await, which is only supported when running Babel asynchronously.");
|
||||||
|
let cacheNeedsConfiguration = false;
|
||||||
|
if (typeof options === "function") {
|
||||||
|
({
|
||||||
|
options,
|
||||||
|
cacheNeedsConfiguration
|
||||||
|
} = yield* runConfig(options, data));
|
||||||
|
}
|
||||||
|
if (!options || typeof options !== "object" || Array.isArray(options)) {
|
||||||
|
throw new _configError.default(`Configuration should be an exported JavaScript object.`, filepath);
|
||||||
|
}
|
||||||
|
if (typeof options.then === "function") {
|
||||||
|
options.catch == null || options.catch(() => {});
|
||||||
|
throw new _configError.default(`You appear to be using an async configuration, ` + `which your current version of Babel does not support. ` + `We may add support for this in the future, ` + `but if you're on the most recent version of @babel/core and still ` + `seeing this error, then you'll need to synchronously return your config.`, filepath);
|
||||||
|
}
|
||||||
|
if (cacheNeedsConfiguration) throwConfigError(filepath);
|
||||||
|
return buildConfigFileObject(options, filepath);
|
||||||
|
}
|
||||||
|
const cfboaf = new WeakMap();
|
||||||
|
function buildConfigFileObject(options, filepath) {
|
||||||
|
let configFilesByFilepath = cfboaf.get(options);
|
||||||
|
if (!configFilesByFilepath) {
|
||||||
|
cfboaf.set(options, configFilesByFilepath = new Map());
|
||||||
|
}
|
||||||
|
let configFile = configFilesByFilepath.get(filepath);
|
||||||
|
if (!configFile) {
|
||||||
|
configFile = {
|
||||||
|
filepath,
|
||||||
|
dirname: _path().dirname(filepath),
|
||||||
|
options
|
||||||
|
};
|
||||||
|
configFilesByFilepath.set(filepath, configFile);
|
||||||
|
}
|
||||||
|
return configFile;
|
||||||
|
}
|
||||||
|
const packageToBabelConfig = (0, _caching.makeWeakCacheSync)(file => {
|
||||||
|
const babel = file.options.babel;
|
||||||
|
if (babel === undefined) return null;
|
||||||
|
if (typeof babel !== "object" || Array.isArray(babel) || babel === null) {
|
||||||
|
throw new _configError.default(`.babel property must be an object`, file.filepath);
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
filepath: file.filepath,
|
||||||
|
dirname: file.dirname,
|
||||||
|
options: babel
|
||||||
|
};
|
||||||
|
});
|
||||||
|
const readConfigJSON5 = (0, _utils.makeStaticFileCache)((filepath, content) => {
|
||||||
|
let options;
|
||||||
|
try {
|
||||||
|
options = _json().parse(content);
|
||||||
|
} catch (err) {
|
||||||
|
throw new _configError.default(`Error while parsing config - ${err.message}`, filepath);
|
||||||
|
}
|
||||||
|
if (!options) throw new _configError.default(`No config detected`, filepath);
|
||||||
|
if (typeof options !== "object") {
|
||||||
|
throw new _configError.default(`Config returned typeof ${typeof options}`, filepath);
|
||||||
|
}
|
||||||
|
if (Array.isArray(options)) {
|
||||||
|
throw new _configError.default(`Expected config object but found array`, filepath);
|
||||||
|
}
|
||||||
|
delete options.$schema;
|
||||||
|
return {
|
||||||
|
filepath,
|
||||||
|
dirname: _path().dirname(filepath),
|
||||||
|
options
|
||||||
|
};
|
||||||
|
});
|
||||||
|
const readIgnoreConfig = (0, _utils.makeStaticFileCache)((filepath, content) => {
|
||||||
|
const ignoreDir = _path().dirname(filepath);
|
||||||
|
const ignorePatterns = content.split("\n").map(line => line.replace(/#.*$/, "").trim()).filter(Boolean);
|
||||||
|
for (const pattern of ignorePatterns) {
|
||||||
|
if (pattern.startsWith("!")) {
|
||||||
|
throw new _configError.default(`Negation of file paths is not supported.`, filepath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
filepath,
|
||||||
|
dirname: _path().dirname(filepath),
|
||||||
|
ignore: ignorePatterns.map(pattern => (0, _patternToRegex.default)(pattern, ignoreDir))
|
||||||
|
};
|
||||||
|
});
|
||||||
|
function findConfigUpwards(rootDir) {
|
||||||
|
let dirname = rootDir;
|
||||||
|
for (;;) {
|
||||||
|
for (const filename of ROOT_CONFIG_FILENAMES) {
|
||||||
|
if (_fs().existsSync(_path().join(dirname, filename))) {
|
||||||
|
return dirname;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const nextDir = _path().dirname(dirname);
|
||||||
|
if (dirname === nextDir) break;
|
||||||
|
dirname = nextDir;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
function* findRelativeConfig(packageData, envName, caller) {
|
||||||
|
let config = null;
|
||||||
|
let ignore = null;
|
||||||
|
const dirname = _path().dirname(packageData.filepath);
|
||||||
|
for (const loc of packageData.directories) {
|
||||||
|
if (!config) {
|
||||||
|
var _packageData$pkg;
|
||||||
|
config = yield* loadOneConfig(RELATIVE_CONFIG_FILENAMES, loc, envName, caller, ((_packageData$pkg = packageData.pkg) == null ? void 0 : _packageData$pkg.dirname) === loc ? packageToBabelConfig(packageData.pkg) : null);
|
||||||
|
}
|
||||||
|
if (!ignore) {
|
||||||
|
const ignoreLoc = _path().join(loc, BABELIGNORE_FILENAME);
|
||||||
|
ignore = yield* readIgnoreConfig(ignoreLoc);
|
||||||
|
if (ignore) {
|
||||||
|
debug("Found ignore %o from %o.", ignore.filepath, dirname);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
config,
|
||||||
|
ignore
|
||||||
|
};
|
||||||
|
}
|
||||||
|
function findRootConfig(dirname, envName, caller) {
|
||||||
|
return loadOneConfig(ROOT_CONFIG_FILENAMES, dirname, envName, caller);
|
||||||
|
}
|
||||||
|
function* loadOneConfig(names, dirname, envName, caller, previousConfig = null) {
|
||||||
|
const configs = yield* _gensync().all(names.map(filename => readConfig(_path().join(dirname, filename), envName, caller)));
|
||||||
|
const config = configs.reduce((previousConfig, config) => {
|
||||||
|
if (config && previousConfig) {
|
||||||
|
throw new _configError.default(`Multiple configuration files found. Please remove one:\n` + ` - ${_path().basename(previousConfig.filepath)}\n` + ` - ${config.filepath}\n` + `from ${dirname}`);
|
||||||
|
}
|
||||||
|
return config || previousConfig;
|
||||||
|
}, previousConfig);
|
||||||
|
if (config) {
|
||||||
|
debug("Found configuration %o from %o.", config.filepath, dirname);
|
||||||
|
}
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
function* loadConfig(name, dirname, envName, caller) {
|
||||||
|
const filepath = (((v, w) => (v = v.split("."), w = w.split("."), +v[0] > +w[0] || v[0] == w[0] && +v[1] >= +w[1]))(process.versions.node, "8.9") ? require.resolve : (r, {
|
||||||
|
paths: [b]
|
||||||
|
}, M = require("module")) => {
|
||||||
|
let f = M._findPath(r, M._nodeModulePaths(b).concat(b));
|
||||||
|
if (f) return f;
|
||||||
|
f = new Error(`Cannot resolve module '${r}'`);
|
||||||
|
f.code = "MODULE_NOT_FOUND";
|
||||||
|
throw f;
|
||||||
|
})(name, {
|
||||||
|
paths: [dirname]
|
||||||
|
});
|
||||||
|
const conf = yield* readConfig(filepath, envName, caller);
|
||||||
|
if (!conf) {
|
||||||
|
throw new _configError.default(`Config file contains no configuration data`, filepath);
|
||||||
|
}
|
||||||
|
debug("Loaded config %o from %o.", name, dirname);
|
||||||
|
return conf;
|
||||||
|
}
|
||||||
|
function readConfig(filepath, envName, caller) {
|
||||||
|
const ext = _path().extname(filepath);
|
||||||
|
switch (ext) {
|
||||||
|
case ".js":
|
||||||
|
case ".cjs":
|
||||||
|
case ".mjs":
|
||||||
|
case ".ts":
|
||||||
|
case ".cts":
|
||||||
|
case ".mts":
|
||||||
|
return readConfigCode(filepath, {
|
||||||
|
envName,
|
||||||
|
caller
|
||||||
|
});
|
||||||
|
default:
|
||||||
|
return readConfigJSON5(filepath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function* resolveShowConfigPath(dirname) {
|
||||||
|
const targetPath = process.env.BABEL_SHOW_CONFIG_FOR;
|
||||||
|
if (targetPath != null) {
|
||||||
|
const absolutePath = _path().resolve(dirname, targetPath);
|
||||||
|
const stats = yield* fs.stat(absolutePath);
|
||||||
|
if (!stats.isFile()) {
|
||||||
|
throw new Error(`${absolutePath}: BABEL_SHOW_CONFIG_FOR must refer to a regular file, directories are not supported.`);
|
||||||
|
}
|
||||||
|
return absolutePath;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
function throwConfigError(filepath) {
|
||||||
|
throw new _configError.default(`\
|
||||||
|
Caching was left unconfigured. Babel's plugins, presets, and .babelrc.js files can be configured
|
||||||
|
for various types of caching, using the first param of their handler functions:
|
||||||
|
|
||||||
|
module.exports = function(api) {
|
||||||
|
// The API exposes the following:
|
||||||
|
|
||||||
|
// Cache the returned value forever and don't call this function again.
|
||||||
|
api.cache(true);
|
||||||
|
|
||||||
|
// Don't cache at all. Not recommended because it will be very slow.
|
||||||
|
api.cache(false);
|
||||||
|
|
||||||
|
// Cached based on the value of some function. If this function returns a value different from
|
||||||
|
// a previously-encountered value, the plugins will re-evaluate.
|
||||||
|
var env = api.cache(() => process.env.NODE_ENV);
|
||||||
|
|
||||||
|
// If testing for a specific env, we recommend specifics to avoid instantiating a plugin for
|
||||||
|
// any possible NODE_ENV value that might come up during plugin execution.
|
||||||
|
var isProd = api.cache(() => process.env.NODE_ENV === "production");
|
||||||
|
|
||||||
|
// .cache(fn) will perform a linear search though instances to find the matching plugin based
|
||||||
|
// based on previous instantiated plugins. If you want to recreate the plugin and discard the
|
||||||
|
// previous instance whenever something changes, you may use:
|
||||||
|
var isProd = api.cache.invalidate(() => process.env.NODE_ENV === "production");
|
||||||
|
|
||||||
|
// Note, we also expose the following more-verbose versions of the above examples:
|
||||||
|
api.cache.forever(); // api.cache(true)
|
||||||
|
api.cache.never(); // api.cache(false)
|
||||||
|
api.cache.using(fn); // api.cache(fn)
|
||||||
|
|
||||||
|
// Return the value that will be cached.
|
||||||
|
return { };
|
||||||
|
};`, filepath);
|
||||||
|
}
|
||||||
|
0 && 0;
|
||||||
|
|
||||||
|
//# sourceMappingURL=configuration.js.map
|
||||||
+1
File diff suppressed because one or more lines are too long
+6
@@ -0,0 +1,6 @@
|
|||||||
|
module.exports = function import_(filepath) {
|
||||||
|
return import(filepath);
|
||||||
|
};
|
||||||
|
0 && 0;
|
||||||
|
|
||||||
|
//# sourceMappingURL=import.cjs.map
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
{"version":3,"names":["module","exports","import_","filepath"],"sources":["../../../src/config/files/import.cjs"],"sourcesContent":["// We keep this in a separate file so that in older node versions, where\n// import() isn't supported, we can try/catch around the require() call\n// when loading this file.\n\nmodule.exports = function import_(filepath) {\n return import(filepath);\n};\n"],"mappings":"AAIAA,MAAM,CAACC,OAAO,GAAG,SAASC,OAAOA,CAACC,QAAQ,EAAE;EAC1C,OAAO,OAAOA,QAAQ,CAAC;AACzB,CAAC;AAAC","ignoreList":[]}
|
||||||
+58
@@ -0,0 +1,58 @@
|
|||||||
|
"use strict";
|
||||||
|
|
||||||
|
Object.defineProperty(exports, "__esModule", {
|
||||||
|
value: true
|
||||||
|
});
|
||||||
|
exports.ROOT_CONFIG_FILENAMES = void 0;
|
||||||
|
exports.findConfigUpwards = findConfigUpwards;
|
||||||
|
exports.findPackageData = findPackageData;
|
||||||
|
exports.findRelativeConfig = findRelativeConfig;
|
||||||
|
exports.findRootConfig = findRootConfig;
|
||||||
|
exports.loadConfig = loadConfig;
|
||||||
|
exports.loadPlugin = loadPlugin;
|
||||||
|
exports.loadPreset = loadPreset;
|
||||||
|
exports.resolvePlugin = resolvePlugin;
|
||||||
|
exports.resolvePreset = resolvePreset;
|
||||||
|
exports.resolveShowConfigPath = resolveShowConfigPath;
|
||||||
|
function findConfigUpwards(rootDir) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
function* findPackageData(filepath) {
|
||||||
|
return {
|
||||||
|
filepath,
|
||||||
|
directories: [],
|
||||||
|
pkg: null,
|
||||||
|
isPackage: false
|
||||||
|
};
|
||||||
|
}
|
||||||
|
function* findRelativeConfig(pkgData, envName, caller) {
|
||||||
|
return {
|
||||||
|
config: null,
|
||||||
|
ignore: null
|
||||||
|
};
|
||||||
|
}
|
||||||
|
function* findRootConfig(dirname, envName, caller) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
function* loadConfig(name, dirname, envName, caller) {
|
||||||
|
throw new Error(`Cannot load ${name} relative to ${dirname} in a browser`);
|
||||||
|
}
|
||||||
|
function* resolveShowConfigPath(dirname) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
const ROOT_CONFIG_FILENAMES = exports.ROOT_CONFIG_FILENAMES = [];
|
||||||
|
function resolvePlugin(name, dirname) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
function resolvePreset(name, dirname) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
function loadPlugin(name, dirname) {
|
||||||
|
throw new Error(`Cannot load plugin ${name} relative to ${dirname} in a browser`);
|
||||||
|
}
|
||||||
|
function loadPreset(name, dirname) {
|
||||||
|
throw new Error(`Cannot load preset ${name} relative to ${dirname} in a browser`);
|
||||||
|
}
|
||||||
|
0 && 0;
|
||||||
|
|
||||||
|
//# sourceMappingURL=index-browser.js.map
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
{"version":3,"names":["findConfigUpwards","rootDir","findPackageData","filepath","directories","pkg","isPackage","findRelativeConfig","pkgData","envName","caller","config","ignore","findRootConfig","dirname","loadConfig","name","Error","resolveShowConfigPath","ROOT_CONFIG_FILENAMES","exports","resolvePlugin","resolvePreset","loadPlugin","loadPreset"],"sources":["../../../src/config/files/index-browser.ts"],"sourcesContent":["/* c8 ignore start */\n\nimport type { Handler } from \"gensync\";\n\nimport type {\n ConfigFile,\n IgnoreFile,\n RelativeConfig,\n FilePackageData,\n} from \"./types.ts\";\n\nimport type { CallerMetadata } from \"../validation/options.ts\";\n\nexport type { ConfigFile, IgnoreFile, RelativeConfig, FilePackageData };\n\nexport function findConfigUpwards(\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n rootDir: string,\n): string | null {\n return null;\n}\n\n// eslint-disable-next-line require-yield\nexport function* findPackageData(filepath: string): Handler<FilePackageData> {\n return {\n filepath,\n directories: [],\n pkg: null,\n isPackage: false,\n };\n}\n\n// eslint-disable-next-line require-yield\nexport function* findRelativeConfig(\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n pkgData: FilePackageData,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n envName: string,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n caller: CallerMetadata | undefined,\n): Handler<RelativeConfig> {\n return { config: null, ignore: null };\n}\n\n// eslint-disable-next-line require-yield\nexport function* findRootConfig(\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n dirname: string,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n envName: string,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n caller: CallerMetadata | undefined,\n): Handler<ConfigFile | null> {\n return null;\n}\n\n// eslint-disable-next-line require-yield\nexport function* loadConfig(\n name: string,\n dirname: string,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n envName: string,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n caller: CallerMetadata | undefined,\n): Handler<ConfigFile> {\n throw new Error(`Cannot load ${name} relative to ${dirname} in a browser`);\n}\n\n// eslint-disable-next-line require-yield\nexport function* resolveShowConfigPath(\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n dirname: string,\n): Handler<string | null> {\n return null;\n}\n\nexport const ROOT_CONFIG_FILENAMES: string[] = [];\n\ntype Resolved =\n | { loader: \"require\"; filepath: string }\n | { loader: \"import\"; filepath: string };\n\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\nexport function resolvePlugin(name: string, dirname: string): Resolved | null {\n return null;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\nexport function resolvePreset(name: string, dirname: string): Resolved | null {\n return null;\n}\n\nexport function loadPlugin(\n name: string,\n dirname: string,\n): Handler<{\n filepath: string;\n value: unknown;\n}> {\n throw new Error(\n `Cannot load plugin ${name} relative to ${dirname} in a browser`,\n );\n}\n\nexport function loadPreset(\n name: string,\n dirname: string,\n): Handler<{\n filepath: string;\n value: unknown;\n}> {\n throw new Error(\n `Cannot load preset ${name} relative to ${dirname} in a browser`,\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAeO,SAASA,iBAAiBA,CAE/BC,OAAe,EACA;EACf,OAAO,IAAI;AACb;AAGO,UAAUC,eAAeA,CAACC,QAAgB,EAA4B;EAC3E,OAAO;IACLA,QAAQ;IACRC,WAAW,EAAE,EAAE;IACfC,GAAG,EAAE,IAAI;IACTC,SAAS,EAAE;EACb,CAAC;AACH;AAGO,UAAUC,kBAAkBA,CAEjCC,OAAwB,EAExBC,OAAe,EAEfC,MAAkC,EACT;EACzB,OAAO;IAAEC,MAAM,EAAE,IAAI;IAAEC,MAAM,EAAE;EAAK,CAAC;AACvC;AAGO,UAAUC,cAAcA,CAE7BC,OAAe,EAEfL,OAAe,EAEfC,MAAkC,EACN;EAC5B,OAAO,IAAI;AACb;AAGO,UAAUK,UAAUA,CACzBC,IAAY,EACZF,OAAe,EAEfL,OAAe,EAEfC,MAAkC,EACb;EACrB,MAAM,IAAIO,KAAK,CAAC,eAAeD,IAAI,gBAAgBF,OAAO,eAAe,CAAC;AAC5E;AAGO,UAAUI,qBAAqBA,CAEpCJ,OAAe,EACS;EACxB,OAAO,IAAI;AACb;AAEO,MAAMK,qBAA+B,GAAAC,OAAA,CAAAD,qBAAA,GAAG,EAAE;AAO1C,SAASE,aAAaA,CAACL,IAAY,EAAEF,OAAe,EAAmB;EAC5E,OAAO,IAAI;AACb;AAGO,SAASQ,aAAaA,CAACN,IAAY,EAAEF,OAAe,EAAmB;EAC5E,OAAO,IAAI;AACb;AAEO,SAASS,UAAUA,CACxBP,IAAY,EACZF,OAAe,EAId;EACD,MAAM,IAAIG,KAAK,CACb,sBAAsBD,IAAI,gBAAgBF,OAAO,eACnD,CAAC;AACH;AAEO,SAASU,UAAUA,CACxBR,IAAY,EACZF,OAAe,EAId;EACD,MAAM,IAAIG,KAAK,CACb,sBAAsBD,IAAI,gBAAgBF,OAAO,eACnD,CAAC;AACH;AAAC","ignoreList":[]}
|
||||||
+78
@@ -0,0 +1,78 @@
|
|||||||
|
"use strict";
|
||||||
|
|
||||||
|
Object.defineProperty(exports, "__esModule", {
|
||||||
|
value: true
|
||||||
|
});
|
||||||
|
Object.defineProperty(exports, "ROOT_CONFIG_FILENAMES", {
|
||||||
|
enumerable: true,
|
||||||
|
get: function () {
|
||||||
|
return _configuration.ROOT_CONFIG_FILENAMES;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
Object.defineProperty(exports, "findConfigUpwards", {
|
||||||
|
enumerable: true,
|
||||||
|
get: function () {
|
||||||
|
return _configuration.findConfigUpwards;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
Object.defineProperty(exports, "findPackageData", {
|
||||||
|
enumerable: true,
|
||||||
|
get: function () {
|
||||||
|
return _package.findPackageData;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
Object.defineProperty(exports, "findRelativeConfig", {
|
||||||
|
enumerable: true,
|
||||||
|
get: function () {
|
||||||
|
return _configuration.findRelativeConfig;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
Object.defineProperty(exports, "findRootConfig", {
|
||||||
|
enumerable: true,
|
||||||
|
get: function () {
|
||||||
|
return _configuration.findRootConfig;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
Object.defineProperty(exports, "loadConfig", {
|
||||||
|
enumerable: true,
|
||||||
|
get: function () {
|
||||||
|
return _configuration.loadConfig;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
Object.defineProperty(exports, "loadPlugin", {
|
||||||
|
enumerable: true,
|
||||||
|
get: function () {
|
||||||
|
return _plugins.loadPlugin;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
Object.defineProperty(exports, "loadPreset", {
|
||||||
|
enumerable: true,
|
||||||
|
get: function () {
|
||||||
|
return _plugins.loadPreset;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
Object.defineProperty(exports, "resolvePlugin", {
|
||||||
|
enumerable: true,
|
||||||
|
get: function () {
|
||||||
|
return _plugins.resolvePlugin;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
Object.defineProperty(exports, "resolvePreset", {
|
||||||
|
enumerable: true,
|
||||||
|
get: function () {
|
||||||
|
return _plugins.resolvePreset;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
Object.defineProperty(exports, "resolveShowConfigPath", {
|
||||||
|
enumerable: true,
|
||||||
|
get: function () {
|
||||||
|
return _configuration.resolveShowConfigPath;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
var _package = require("./package.js");
|
||||||
|
var _configuration = require("./configuration.js");
|
||||||
|
var _plugins = require("./plugins.js");
|
||||||
|
({});
|
||||||
|
0 && 0;
|
||||||
|
|
||||||
|
//# sourceMappingURL=index.js.map
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
{"version":3,"names":["_package","require","_configuration","_plugins"],"sources":["../../../src/config/files/index.ts"],"sourcesContent":["type indexBrowserType = typeof import(\"./index-browser\");\ntype indexType = typeof import(\"./index\");\n\n// Kind of gross, but essentially asserting that the exports of this module are the same as the\n// exports of index-browser, since this file may be replaced at bundle time with index-browser.\n// eslint-disable-next-line @typescript-eslint/no-unused-expressions\n({}) as any as indexBrowserType as indexType;\n\nexport { findPackageData } from \"./package.ts\";\n\nexport {\n findConfigUpwards,\n findRelativeConfig,\n findRootConfig,\n loadConfig,\n resolveShowConfigPath,\n ROOT_CONFIG_FILENAMES,\n} from \"./configuration.ts\";\nexport type {\n ConfigFile,\n IgnoreFile,\n RelativeConfig,\n FilePackageData,\n} from \"./types.ts\";\nexport {\n loadPlugin,\n loadPreset,\n resolvePlugin,\n resolvePreset,\n} from \"./plugins.ts\";\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAQA,IAAAA,QAAA,GAAAC,OAAA;AAEA,IAAAC,cAAA,GAAAD,OAAA;AAcA,IAAAE,QAAA,GAAAF,OAAA;AAlBA,CAAC,CAAC,CAAC;AAA0C","ignoreList":[]}
|
||||||
+203
@@ -0,0 +1,203 @@
|
|||||||
|
"use strict";
|
||||||
|
|
||||||
|
Object.defineProperty(exports, "__esModule", {
|
||||||
|
value: true
|
||||||
|
});
|
||||||
|
exports.default = loadCodeDefault;
|
||||||
|
exports.supportsESM = void 0;
|
||||||
|
var _async = require("../../gensync-utils/async.js");
|
||||||
|
function _path() {
|
||||||
|
const data = require("path");
|
||||||
|
_path = function () {
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
function _url() {
|
||||||
|
const data = require("url");
|
||||||
|
_url = function () {
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
require("module");
|
||||||
|
function _semver() {
|
||||||
|
const data = require("semver");
|
||||||
|
_semver = function () {
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
function _debug() {
|
||||||
|
const data = require("debug");
|
||||||
|
_debug = function () {
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
var _rewriteStackTrace = require("../../errors/rewrite-stack-trace.js");
|
||||||
|
var _configError = require("../../errors/config-error.js");
|
||||||
|
var _transformFile = require("../../transform-file.js");
|
||||||
|
function asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); }
|
||||||
|
function _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, "next", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, "throw", n); } _next(void 0); }); }; }
|
||||||
|
const debug = _debug()("babel:config:loading:files:module-types");
|
||||||
|
try {
|
||||||
|
var import_ = require("./import.cjs");
|
||||||
|
} catch (_unused) {}
|
||||||
|
const supportsESM = exports.supportsESM = _semver().satisfies(process.versions.node, "^12.17 || >=13.2");
|
||||||
|
const LOADING_CJS_FILES = new Set();
|
||||||
|
function loadCjsDefault(filepath) {
|
||||||
|
if (LOADING_CJS_FILES.has(filepath)) {
|
||||||
|
debug("Auto-ignoring usage of config %o.", filepath);
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
let module;
|
||||||
|
try {
|
||||||
|
LOADING_CJS_FILES.add(filepath);
|
||||||
|
module = (0, _rewriteStackTrace.endHiddenCallStack)(require)(filepath);
|
||||||
|
} finally {
|
||||||
|
LOADING_CJS_FILES.delete(filepath);
|
||||||
|
}
|
||||||
|
return module != null && (module.__esModule || module[Symbol.toStringTag] === "Module") ? module.default || (arguments[1] ? module : undefined) : module;
|
||||||
|
}
|
||||||
|
const loadMjsFromPath = (0, _rewriteStackTrace.endHiddenCallStack)(function () {
|
||||||
|
var _loadMjsFromPath = _asyncToGenerator(function* (filepath) {
|
||||||
|
const url = (0, _url().pathToFileURL)(filepath).toString() + "?import";
|
||||||
|
if (!import_) {
|
||||||
|
throw new _configError.default("Internal error: Native ECMAScript modules aren't supported by this platform.\n", filepath);
|
||||||
|
}
|
||||||
|
return yield import_(url);
|
||||||
|
});
|
||||||
|
function loadMjsFromPath(_x) {
|
||||||
|
return _loadMjsFromPath.apply(this, arguments);
|
||||||
|
}
|
||||||
|
return loadMjsFromPath;
|
||||||
|
}());
|
||||||
|
const tsNotSupportedError = ext => `\
|
||||||
|
You are using a ${ext} config file, but Babel only supports transpiling .cts configs. Either:
|
||||||
|
- Use a .cts config file
|
||||||
|
- Update to Node.js 23.6.0, which has native TypeScript support
|
||||||
|
- Install tsx to transpile ${ext} files on the fly\
|
||||||
|
`;
|
||||||
|
const SUPPORTED_EXTENSIONS = {
|
||||||
|
".js": "unknown",
|
||||||
|
".mjs": "esm",
|
||||||
|
".cjs": "cjs",
|
||||||
|
".ts": "unknown",
|
||||||
|
".mts": "esm",
|
||||||
|
".cts": "cjs"
|
||||||
|
};
|
||||||
|
const asyncModules = new Set();
|
||||||
|
function* loadCodeDefault(filepath, loader, esmError, tlaError) {
|
||||||
|
let async;
|
||||||
|
const ext = _path().extname(filepath);
|
||||||
|
const isTS = ext === ".ts" || ext === ".cts" || ext === ".mts";
|
||||||
|
const type = SUPPORTED_EXTENSIONS[hasOwnProperty.call(SUPPORTED_EXTENSIONS, ext) ? ext : ".js"];
|
||||||
|
const pattern = `${loader} ${type}`;
|
||||||
|
switch (pattern) {
|
||||||
|
case "require cjs":
|
||||||
|
case "auto cjs":
|
||||||
|
if (isTS) {
|
||||||
|
return ensureTsSupport(filepath, ext, () => loadCjsDefault(filepath));
|
||||||
|
} else {
|
||||||
|
return loadCjsDefault(filepath, arguments[2]);
|
||||||
|
}
|
||||||
|
case "auto unknown":
|
||||||
|
case "require unknown":
|
||||||
|
case "require esm":
|
||||||
|
try {
|
||||||
|
if (isTS) {
|
||||||
|
return ensureTsSupport(filepath, ext, () => loadCjsDefault(filepath));
|
||||||
|
} else {
|
||||||
|
return loadCjsDefault(filepath, arguments[2]);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
if (e.code === "ERR_REQUIRE_ASYNC_MODULE" || e.code === "ERR_REQUIRE_CYCLE_MODULE" && asyncModules.has(filepath)) {
|
||||||
|
asyncModules.add(filepath);
|
||||||
|
if (!(async != null ? async : async = yield* (0, _async.isAsync)())) {
|
||||||
|
throw new _configError.default(tlaError, filepath);
|
||||||
|
}
|
||||||
|
} else if (e.code === "ERR_REQUIRE_ESM" || type === "esm") {} else {
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case "auto esm":
|
||||||
|
if (async != null ? async : async = yield* (0, _async.isAsync)()) {
|
||||||
|
const promise = isTS ? ensureTsSupport(filepath, ext, () => loadMjsFromPath(filepath)) : loadMjsFromPath(filepath);
|
||||||
|
return (yield* (0, _async.waitFor)(promise)).default;
|
||||||
|
}
|
||||||
|
if (isTS) {
|
||||||
|
throw new _configError.default(tsNotSupportedError(ext), filepath);
|
||||||
|
} else {
|
||||||
|
throw new _configError.default(esmError, filepath);
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
throw new Error("Internal Babel error: unreachable code.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function ensureTsSupport(filepath, ext, callback) {
|
||||||
|
if (process.features.typescript || require.extensions[".ts"] || require.extensions[".cts"] || require.extensions[".mts"]) {
|
||||||
|
return callback();
|
||||||
|
}
|
||||||
|
if (ext !== ".cts") {
|
||||||
|
throw new _configError.default(tsNotSupportedError(ext), filepath);
|
||||||
|
}
|
||||||
|
const opts = {
|
||||||
|
babelrc: false,
|
||||||
|
configFile: false,
|
||||||
|
sourceType: "unambiguous",
|
||||||
|
sourceMaps: "inline",
|
||||||
|
sourceFileName: _path().basename(filepath),
|
||||||
|
presets: [[getTSPreset(filepath), Object.assign({
|
||||||
|
onlyRemoveTypeImports: true,
|
||||||
|
optimizeConstEnums: true
|
||||||
|
}, {
|
||||||
|
allowDeclareFields: true
|
||||||
|
})]]
|
||||||
|
};
|
||||||
|
let handler = function (m, filename) {
|
||||||
|
if (handler && filename.endsWith(".cts")) {
|
||||||
|
try {
|
||||||
|
return m._compile((0, _transformFile.transformFileSync)(filename, Object.assign({}, opts, {
|
||||||
|
filename
|
||||||
|
})).code, filename);
|
||||||
|
} catch (error) {
|
||||||
|
const packageJson = require("@babel/preset-typescript/package.json");
|
||||||
|
if (_semver().lt(packageJson.version, "7.21.4")) {
|
||||||
|
console.error("`.cts` configuration file failed to load, please try to update `@babel/preset-typescript`.");
|
||||||
|
}
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return require.extensions[".js"](m, filename);
|
||||||
|
};
|
||||||
|
require.extensions[ext] = handler;
|
||||||
|
try {
|
||||||
|
return callback();
|
||||||
|
} finally {
|
||||||
|
if (require.extensions[ext] === handler) delete require.extensions[ext];
|
||||||
|
handler = undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function getTSPreset(filepath) {
|
||||||
|
try {
|
||||||
|
return require("@babel/preset-typescript");
|
||||||
|
} catch (error) {
|
||||||
|
if (error.code !== "MODULE_NOT_FOUND") throw error;
|
||||||
|
let message = "You appear to be using a .cts file as Babel configuration, but the `@babel/preset-typescript` package was not found: please install it!";
|
||||||
|
if (process.versions.pnp) {
|
||||||
|
message += `
|
||||||
|
If you are using Yarn Plug'n'Play, you may also need to add the following configuration to your .yarnrc.yml file:
|
||||||
|
|
||||||
|
packageExtensions:
|
||||||
|
\t"@babel/core@*":
|
||||||
|
\t\tpeerDependencies:
|
||||||
|
\t\t\t"@babel/preset-typescript": "*"
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
throw new _configError.default(message, filepath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
0 && 0;
|
||||||
|
|
||||||
|
//# sourceMappingURL=module-types.js.map
|
||||||
+1
File diff suppressed because one or more lines are too long
+61
@@ -0,0 +1,61 @@
|
|||||||
|
"use strict";
|
||||||
|
|
||||||
|
Object.defineProperty(exports, "__esModule", {
|
||||||
|
value: true
|
||||||
|
});
|
||||||
|
exports.findPackageData = findPackageData;
|
||||||
|
function _path() {
|
||||||
|
const data = require("path");
|
||||||
|
_path = function () {
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
var _utils = require("./utils.js");
|
||||||
|
var _configError = require("../../errors/config-error.js");
|
||||||
|
const PACKAGE_FILENAME = "package.json";
|
||||||
|
const readConfigPackage = (0, _utils.makeStaticFileCache)((filepath, content) => {
|
||||||
|
let options;
|
||||||
|
try {
|
||||||
|
options = JSON.parse(content);
|
||||||
|
} catch (err) {
|
||||||
|
throw new _configError.default(`Error while parsing JSON - ${err.message}`, filepath);
|
||||||
|
}
|
||||||
|
if (!options) throw new Error(`${filepath}: No config detected`);
|
||||||
|
if (typeof options !== "object") {
|
||||||
|
throw new _configError.default(`Config returned typeof ${typeof options}`, filepath);
|
||||||
|
}
|
||||||
|
if (Array.isArray(options)) {
|
||||||
|
throw new _configError.default(`Expected config object but found array`, filepath);
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
filepath,
|
||||||
|
dirname: _path().dirname(filepath),
|
||||||
|
options
|
||||||
|
};
|
||||||
|
});
|
||||||
|
function* findPackageData(filepath) {
|
||||||
|
let pkg = null;
|
||||||
|
const directories = [];
|
||||||
|
let isPackage = true;
|
||||||
|
let dirname = _path().dirname(filepath);
|
||||||
|
while (!pkg && _path().basename(dirname) !== "node_modules") {
|
||||||
|
directories.push(dirname);
|
||||||
|
pkg = yield* readConfigPackage(_path().join(dirname, PACKAGE_FILENAME));
|
||||||
|
const nextLoc = _path().dirname(dirname);
|
||||||
|
if (dirname === nextLoc) {
|
||||||
|
isPackage = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
dirname = nextLoc;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
filepath,
|
||||||
|
directories,
|
||||||
|
pkg,
|
||||||
|
isPackage
|
||||||
|
};
|
||||||
|
}
|
||||||
|
0 && 0;
|
||||||
|
|
||||||
|
//# sourceMappingURL=package.js.map
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
{"version":3,"names":["_path","data","require","_utils","_configError","PACKAGE_FILENAME","readConfigPackage","makeStaticFileCache","filepath","content","options","JSON","parse","err","ConfigError","message","Error","Array","isArray","dirname","path","findPackageData","pkg","directories","isPackage","basename","push","join","nextLoc"],"sources":["../../../src/config/files/package.ts"],"sourcesContent":["import path from \"node:path\";\nimport type { Handler } from \"gensync\";\nimport { makeStaticFileCache } from \"./utils.ts\";\n\nimport type { ConfigFile, FilePackageData } from \"./types.ts\";\n\nimport ConfigError from \"../../errors/config-error.ts\";\n\nconst PACKAGE_FILENAME = \"package.json\";\n\nconst readConfigPackage = makeStaticFileCache(\n (filepath, content): ConfigFile => {\n let options;\n try {\n options = JSON.parse(content) as unknown;\n } catch (err) {\n throw new ConfigError(\n `Error while parsing JSON - ${err.message}`,\n filepath,\n );\n }\n\n if (!options) throw new Error(`${filepath}: No config detected`);\n\n if (typeof options !== \"object\") {\n throw new ConfigError(\n `Config returned typeof ${typeof options}`,\n filepath,\n );\n }\n if (Array.isArray(options)) {\n throw new ConfigError(`Expected config object but found array`, filepath);\n }\n\n return {\n filepath,\n dirname: path.dirname(filepath),\n options,\n };\n },\n);\n\n/**\n * Find metadata about the package that this file is inside of. Resolution\n * of Babel's config requires general package information to decide when to\n * search for .babelrc files\n */\nexport function* findPackageData(filepath: string): Handler<FilePackageData> {\n let pkg = null;\n const directories = [];\n let isPackage = true;\n\n let dirname = path.dirname(filepath);\n while (!pkg && path.basename(dirname) !== \"node_modules\") {\n directories.push(dirname);\n\n pkg = yield* readConfigPackage(path.join(dirname, PACKAGE_FILENAME));\n\n const nextLoc = path.dirname(dirname);\n if (dirname === nextLoc) {\n isPackage = false;\n break;\n }\n dirname = nextLoc;\n }\n\n return { filepath, directories, pkg, isPackage };\n}\n"],"mappings":";;;;;;AAAA,SAAAA,MAAA;EAAA,MAAAC,IAAA,GAAAC,OAAA;EAAAF,KAAA,YAAAA,CAAA;IAAA,OAAAC,IAAA;EAAA;EAAA,OAAAA,IAAA;AAAA;AAEA,IAAAE,MAAA,GAAAD,OAAA;AAIA,IAAAE,YAAA,GAAAF,OAAA;AAEA,MAAMG,gBAAgB,GAAG,cAAc;AAEvC,MAAMC,iBAAiB,GAAG,IAAAC,0BAAmB,EAC3C,CAACC,QAAQ,EAAEC,OAAO,KAAiB;EACjC,IAAIC,OAAO;EACX,IAAI;IACFA,OAAO,GAAGC,IAAI,CAACC,KAAK,CAACH,OAAO,CAAY;EAC1C,CAAC,CAAC,OAAOI,GAAG,EAAE;IACZ,MAAM,IAAIC,oBAAW,CACnB,8BAA8BD,GAAG,CAACE,OAAO,EAAE,EAC3CP,QACF,CAAC;EACH;EAEA,IAAI,CAACE,OAAO,EAAE,MAAM,IAAIM,KAAK,CAAC,GAAGR,QAAQ,sBAAsB,CAAC;EAEhE,IAAI,OAAOE,OAAO,KAAK,QAAQ,EAAE;IAC/B,MAAM,IAAII,oBAAW,CACnB,0BAA0B,OAAOJ,OAAO,EAAE,EAC1CF,QACF,CAAC;EACH;EACA,IAAIS,KAAK,CAACC,OAAO,CAACR,OAAO,CAAC,EAAE;IAC1B,MAAM,IAAII,oBAAW,CAAC,wCAAwC,EAAEN,QAAQ,CAAC;EAC3E;EAEA,OAAO;IACLA,QAAQ;IACRW,OAAO,EAAEC,MAAGA,CAAC,CAACD,OAAO,CAACX,QAAQ,CAAC;IAC/BE;EACF,CAAC;AACH,CACF,CAAC;AAOM,UAAUW,eAAeA,CAACb,QAAgB,EAA4B;EAC3E,IAAIc,GAAG,GAAG,IAAI;EACd,MAAMC,WAAW,GAAG,EAAE;EACtB,IAAIC,SAAS,GAAG,IAAI;EAEpB,IAAIL,OAAO,GAAGC,MAAGA,CAAC,CAACD,OAAO,CAACX,QAAQ,CAAC;EACpC,OAAO,CAACc,GAAG,IAAIF,MAAGA,CAAC,CAACK,QAAQ,CAACN,OAAO,CAAC,KAAK,cAAc,EAAE;IACxDI,WAAW,CAACG,IAAI,CAACP,OAAO,CAAC;IAEzBG,GAAG,GAAG,OAAOhB,iBAAiB,CAACc,MAAGA,CAAC,CAACO,IAAI,CAACR,OAAO,EAAEd,gBAAgB,CAAC,CAAC;IAEpE,MAAMuB,OAAO,GAAGR,MAAGA,CAAC,CAACD,OAAO,CAACA,OAAO,CAAC;IACrC,IAAIA,OAAO,KAAKS,OAAO,EAAE;MACvBJ,SAAS,GAAG,KAAK;MACjB;IACF;IACAL,OAAO,GAAGS,OAAO;EACnB;EAEA,OAAO;IAAEpB,QAAQ;IAAEe,WAAW;IAAED,GAAG;IAAEE;EAAU,CAAC;AAClD;AAAC","ignoreList":[]}
|
||||||
+220
@@ -0,0 +1,220 @@
|
|||||||
|
"use strict";
|
||||||
|
|
||||||
|
Object.defineProperty(exports, "__esModule", {
|
||||||
|
value: true
|
||||||
|
});
|
||||||
|
exports.loadPlugin = loadPlugin;
|
||||||
|
exports.loadPreset = loadPreset;
|
||||||
|
exports.resolvePreset = exports.resolvePlugin = void 0;
|
||||||
|
function _debug() {
|
||||||
|
const data = require("debug");
|
||||||
|
_debug = function () {
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
function _path() {
|
||||||
|
const data = require("path");
|
||||||
|
_path = function () {
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
var _async = require("../../gensync-utils/async.js");
|
||||||
|
var _moduleTypes = require("./module-types.js");
|
||||||
|
function _url() {
|
||||||
|
const data = require("url");
|
||||||
|
_url = function () {
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
var _importMetaResolve = require("../../vendor/import-meta-resolve.js");
|
||||||
|
require("module");
|
||||||
|
function _fs() {
|
||||||
|
const data = require("fs");
|
||||||
|
_fs = function () {
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
const debug = _debug()("babel:config:loading:files:plugins");
|
||||||
|
const EXACT_RE = /^module:/;
|
||||||
|
const BABEL_PLUGIN_PREFIX_RE = /^(?!@|module:|[^/]+\/|babel-plugin-)/;
|
||||||
|
const BABEL_PRESET_PREFIX_RE = /^(?!@|module:|[^/]+\/|babel-preset-)/;
|
||||||
|
const BABEL_PLUGIN_ORG_RE = /^(@babel\/)(?!plugin-|[^/]+\/)/;
|
||||||
|
const BABEL_PRESET_ORG_RE = /^(@babel\/)(?!preset-|[^/]+\/)/;
|
||||||
|
const OTHER_PLUGIN_ORG_RE = /^(@(?!babel\/)[^/]+\/)(?![^/]*babel-plugin(?:-|\/|$)|[^/]+\/)/;
|
||||||
|
const OTHER_PRESET_ORG_RE = /^(@(?!babel\/)[^/]+\/)(?![^/]*babel-preset(?:-|\/|$)|[^/]+\/)/;
|
||||||
|
const OTHER_ORG_DEFAULT_RE = /^(@(?!babel$)[^/]+)$/;
|
||||||
|
const resolvePlugin = exports.resolvePlugin = resolveStandardizedName.bind(null, "plugin");
|
||||||
|
const resolvePreset = exports.resolvePreset = resolveStandardizedName.bind(null, "preset");
|
||||||
|
function* loadPlugin(name, dirname) {
|
||||||
|
const {
|
||||||
|
filepath,
|
||||||
|
loader
|
||||||
|
} = resolvePlugin(name, dirname, yield* (0, _async.isAsync)());
|
||||||
|
const value = yield* requireModule("plugin", loader, filepath);
|
||||||
|
debug("Loaded plugin %o from %o.", name, dirname);
|
||||||
|
return {
|
||||||
|
filepath,
|
||||||
|
value
|
||||||
|
};
|
||||||
|
}
|
||||||
|
function* loadPreset(name, dirname) {
|
||||||
|
const {
|
||||||
|
filepath,
|
||||||
|
loader
|
||||||
|
} = resolvePreset(name, dirname, yield* (0, _async.isAsync)());
|
||||||
|
const value = yield* requireModule("preset", loader, filepath);
|
||||||
|
debug("Loaded preset %o from %o.", name, dirname);
|
||||||
|
return {
|
||||||
|
filepath,
|
||||||
|
value
|
||||||
|
};
|
||||||
|
}
|
||||||
|
function standardizeName(type, name) {
|
||||||
|
if (_path().isAbsolute(name)) return name;
|
||||||
|
const isPreset = type === "preset";
|
||||||
|
return name.replace(isPreset ? BABEL_PRESET_PREFIX_RE : BABEL_PLUGIN_PREFIX_RE, `babel-${type}-`).replace(isPreset ? BABEL_PRESET_ORG_RE : BABEL_PLUGIN_ORG_RE, `$1${type}-`).replace(isPreset ? OTHER_PRESET_ORG_RE : OTHER_PLUGIN_ORG_RE, `$1babel-${type}-`).replace(OTHER_ORG_DEFAULT_RE, `$1/babel-${type}`).replace(EXACT_RE, "");
|
||||||
|
}
|
||||||
|
function* resolveAlternativesHelper(type, name) {
|
||||||
|
const standardizedName = standardizeName(type, name);
|
||||||
|
const {
|
||||||
|
error,
|
||||||
|
value
|
||||||
|
} = yield standardizedName;
|
||||||
|
if (!error) return value;
|
||||||
|
if (error.code !== "MODULE_NOT_FOUND") throw error;
|
||||||
|
if (standardizedName !== name && !(yield name).error) {
|
||||||
|
error.message += `\n- If you want to resolve "${name}", use "module:${name}"`;
|
||||||
|
}
|
||||||
|
if (!(yield standardizeName(type, "@babel/" + name)).error) {
|
||||||
|
error.message += `\n- Did you mean "@babel/${name}"?`;
|
||||||
|
}
|
||||||
|
const oppositeType = type === "preset" ? "plugin" : "preset";
|
||||||
|
if (!(yield standardizeName(oppositeType, name)).error) {
|
||||||
|
error.message += `\n- Did you accidentally pass a ${oppositeType} as a ${type}?`;
|
||||||
|
}
|
||||||
|
if (type === "plugin") {
|
||||||
|
const transformName = standardizedName.replace("-proposal-", "-transform-");
|
||||||
|
if (transformName !== standardizedName && !(yield transformName).error) {
|
||||||
|
error.message += `\n- Did you mean "${transformName}"?`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
error.message += `\n
|
||||||
|
Make sure that all the Babel plugins and presets you are using
|
||||||
|
are defined as dependencies or devDependencies in your package.json
|
||||||
|
file. It's possible that the missing plugin is loaded by a preset
|
||||||
|
you are using that forgot to add the plugin to its dependencies: you
|
||||||
|
can workaround this problem by explicitly adding the missing package
|
||||||
|
to your top-level package.json.
|
||||||
|
`;
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
function tryRequireResolve(id, dirname) {
|
||||||
|
try {
|
||||||
|
if (dirname) {
|
||||||
|
return {
|
||||||
|
error: null,
|
||||||
|
value: (((v, w) => (v = v.split("."), w = w.split("."), +v[0] > +w[0] || v[0] == w[0] && +v[1] >= +w[1]))(process.versions.node, "8.9") ? require.resolve : (r, {
|
||||||
|
paths: [b]
|
||||||
|
}, M = require("module")) => {
|
||||||
|
let f = M._findPath(r, M._nodeModulePaths(b).concat(b));
|
||||||
|
if (f) return f;
|
||||||
|
f = new Error(`Cannot resolve module '${r}'`);
|
||||||
|
f.code = "MODULE_NOT_FOUND";
|
||||||
|
throw f;
|
||||||
|
})(id, {
|
||||||
|
paths: [dirname]
|
||||||
|
})
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
error: null,
|
||||||
|
value: require.resolve(id)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
return {
|
||||||
|
error,
|
||||||
|
value: null
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function tryImportMetaResolve(id, options) {
|
||||||
|
try {
|
||||||
|
return {
|
||||||
|
error: null,
|
||||||
|
value: (0, _importMetaResolve.resolve)(id, options)
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
return {
|
||||||
|
error,
|
||||||
|
value: null
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function resolveStandardizedNameForRequire(type, name, dirname) {
|
||||||
|
const it = resolveAlternativesHelper(type, name);
|
||||||
|
let res = it.next();
|
||||||
|
while (!res.done) {
|
||||||
|
res = it.next(tryRequireResolve(res.value, dirname));
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
loader: "require",
|
||||||
|
filepath: res.value
|
||||||
|
};
|
||||||
|
}
|
||||||
|
function resolveStandardizedNameForImport(type, name, dirname) {
|
||||||
|
const parentUrl = (0, _url().pathToFileURL)(_path().join(dirname, "./babel-virtual-resolve-base.js")).href;
|
||||||
|
const it = resolveAlternativesHelper(type, name);
|
||||||
|
let res = it.next();
|
||||||
|
while (!res.done) {
|
||||||
|
res = it.next(tryImportMetaResolve(res.value, parentUrl));
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
loader: "auto",
|
||||||
|
filepath: (0, _url().fileURLToPath)(res.value)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
function resolveStandardizedName(type, name, dirname, allowAsync) {
|
||||||
|
if (!_moduleTypes.supportsESM || !allowAsync) {
|
||||||
|
return resolveStandardizedNameForRequire(type, name, dirname);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
const resolved = resolveStandardizedNameForImport(type, name, dirname);
|
||||||
|
if (!(0, _fs().existsSync)(resolved.filepath)) {
|
||||||
|
throw Object.assign(new Error(`Could not resolve "${name}" in file ${dirname}.`), {
|
||||||
|
type: "MODULE_NOT_FOUND"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return resolved;
|
||||||
|
} catch (e) {
|
||||||
|
try {
|
||||||
|
return resolveStandardizedNameForRequire(type, name, dirname);
|
||||||
|
} catch (e2) {
|
||||||
|
if (e.type === "MODULE_NOT_FOUND") throw e;
|
||||||
|
if (e2.type === "MODULE_NOT_FOUND") throw e2;
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var LOADING_MODULES = new Set();
|
||||||
|
function* requireModule(type, loader, name) {
|
||||||
|
if (!(yield* (0, _async.isAsync)()) && LOADING_MODULES.has(name)) {
|
||||||
|
throw new Error(`Reentrant ${type} detected trying to load "${name}". This module is not ignored ` + "and is trying to load itself while compiling itself, leading to a dependency cycle. " + 'We recommend adding it to your "ignore" list in your babelrc, or to a .babelignore.');
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
LOADING_MODULES.add(name);
|
||||||
|
return yield* (0, _moduleTypes.default)(name, loader, `You appear to be using a native ECMAScript module ${type}, ` + "which is only supported when running Babel asynchronously " + "or when using the Node.js `--experimental-require-module` flag.", `You appear to be using a ${type} that contains top-level await, ` + "which is only supported when running Babel asynchronously.", true);
|
||||||
|
} catch (err) {
|
||||||
|
err.message = `[BABEL]: ${err.message} (While processing: ${name})`;
|
||||||
|
throw err;
|
||||||
|
} finally {
|
||||||
|
LOADING_MODULES.delete(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
0 && 0;
|
||||||
|
|
||||||
|
//# sourceMappingURL=plugins.js.map
|
||||||
+1
File diff suppressed because one or more lines are too long
+5
@@ -0,0 +1,5 @@
|
|||||||
|
"use strict";
|
||||||
|
|
||||||
|
0 && 0;
|
||||||
|
|
||||||
|
//# sourceMappingURL=types.js.map
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
{"version":3,"names":[],"sources":["../../../src/config/files/types.ts"],"sourcesContent":["import type { InputOptions } from \"../index.ts\";\n\nexport type ConfigFile = {\n filepath: string;\n dirname: string;\n options: InputOptions & { babel?: unknown };\n};\n\nexport type IgnoreFile = {\n filepath: string;\n dirname: string;\n ignore: RegExp[];\n};\n\nexport type RelativeConfig = {\n // The actual config, either from package.json#babel, .babelrc, or\n // .babelrc.js, if there was one.\n config: ConfigFile | null;\n // The .babelignore, if there was one.\n ignore: IgnoreFile | null;\n};\n\nexport type FilePackageData = {\n // The file in the package.\n filepath: string;\n // Any ancestor directories of the file that are within the package.\n directories: string[];\n // The contents of the package.json. May not be found if the package just\n // terminated at a node_modules folder without finding one.\n pkg: ConfigFile | null;\n // True if a package.json or node_modules folder was found while traversing\n // the directory structure.\n isPackage: boolean;\n};\n"],"mappings":"","ignoreList":[]}
|
||||||
+36
@@ -0,0 +1,36 @@
|
|||||||
|
"use strict";
|
||||||
|
|
||||||
|
Object.defineProperty(exports, "__esModule", {
|
||||||
|
value: true
|
||||||
|
});
|
||||||
|
exports.makeStaticFileCache = makeStaticFileCache;
|
||||||
|
var _caching = require("../caching.js");
|
||||||
|
var fs = require("../../gensync-utils/fs.js");
|
||||||
|
function _fs2() {
|
||||||
|
const data = require("fs");
|
||||||
|
_fs2 = function () {
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
function makeStaticFileCache(fn) {
|
||||||
|
return (0, _caching.makeStrongCache)(function* (filepath, cache) {
|
||||||
|
const cached = cache.invalidate(() => fileMtime(filepath));
|
||||||
|
if (cached === null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return fn(filepath, yield* fs.readFile(filepath, "utf8"));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
function fileMtime(filepath) {
|
||||||
|
if (!_fs2().existsSync(filepath)) return null;
|
||||||
|
try {
|
||||||
|
return +_fs2().statSync(filepath).mtime;
|
||||||
|
} catch (e) {
|
||||||
|
if (e.code !== "ENOENT" && e.code !== "ENOTDIR") throw e;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
0 && 0;
|
||||||
|
|
||||||
|
//# sourceMappingURL=utils.js.map
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
{"version":3,"names":["_caching","require","fs","_fs2","data","makeStaticFileCache","fn","makeStrongCache","filepath","cache","cached","invalidate","fileMtime","readFile","nodeFs","existsSync","statSync","mtime","e","code"],"sources":["../../../src/config/files/utils.ts"],"sourcesContent":["import type { Handler } from \"gensync\";\n\nimport { makeStrongCache } from \"../caching.ts\";\nimport type { CacheConfigurator } from \"../caching.ts\";\nimport * as fs from \"../../gensync-utils/fs.ts\";\nimport nodeFs from \"node:fs\";\n\nexport function makeStaticFileCache<T>(\n fn: (filepath: string, contents: string) => T,\n) {\n return makeStrongCache(function* (\n filepath: string,\n cache: CacheConfigurator<void>,\n ): Handler<null | T> {\n const cached = cache.invalidate(() => fileMtime(filepath));\n\n if (cached === null) {\n return null;\n }\n\n return fn(filepath, yield* fs.readFile(filepath, \"utf8\"));\n });\n}\n\nfunction fileMtime(filepath: string): number | null {\n if (!nodeFs.existsSync(filepath)) return null;\n\n try {\n return +nodeFs.statSync(filepath).mtime;\n } catch (e) {\n if (e.code !== \"ENOENT\" && e.code !== \"ENOTDIR\") throw e;\n }\n\n return null;\n}\n"],"mappings":";;;;;;AAEA,IAAAA,QAAA,GAAAC,OAAA;AAEA,IAAAC,EAAA,GAAAD,OAAA;AACA,SAAAE,KAAA;EAAA,MAAAC,IAAA,GAAAH,OAAA;EAAAE,IAAA,YAAAA,CAAA;IAAA,OAAAC,IAAA;EAAA;EAAA,OAAAA,IAAA;AAAA;AAEO,SAASC,mBAAmBA,CACjCC,EAA6C,EAC7C;EACA,OAAO,IAAAC,wBAAe,EAAC,WACrBC,QAAgB,EAChBC,KAA8B,EACX;IACnB,MAAMC,MAAM,GAAGD,KAAK,CAACE,UAAU,CAAC,MAAMC,SAAS,CAACJ,QAAQ,CAAC,CAAC;IAE1D,IAAIE,MAAM,KAAK,IAAI,EAAE;MACnB,OAAO,IAAI;IACb;IAEA,OAAOJ,EAAE,CAACE,QAAQ,EAAE,OAAON,EAAE,CAACW,QAAQ,CAACL,QAAQ,EAAE,MAAM,CAAC,CAAC;EAC3D,CAAC,CAAC;AACJ;AAEA,SAASI,SAASA,CAACJ,QAAgB,EAAiB;EAClD,IAAI,CAACM,KAAKA,CAAC,CAACC,UAAU,CAACP,QAAQ,CAAC,EAAE,OAAO,IAAI;EAE7C,IAAI;IACF,OAAO,CAACM,KAAKA,CAAC,CAACE,QAAQ,CAACR,QAAQ,CAAC,CAACS,KAAK;EACzC,CAAC,CAAC,OAAOC,CAAC,EAAE;IACV,IAAIA,CAAC,CAACC,IAAI,KAAK,QAAQ,IAAID,CAAC,CAACC,IAAI,KAAK,SAAS,EAAE,MAAMD,CAAC;EAC1D;EAEA,OAAO,IAAI;AACb;AAAC","ignoreList":[]}
|
||||||
+312
@@ -0,0 +1,312 @@
|
|||||||
|
"use strict";
|
||||||
|
|
||||||
|
Object.defineProperty(exports, "__esModule", {
|
||||||
|
value: true
|
||||||
|
});
|
||||||
|
exports.default = void 0;
|
||||||
|
function _gensync() {
|
||||||
|
const data = require("gensync");
|
||||||
|
_gensync = function () {
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
var _async = require("../gensync-utils/async.js");
|
||||||
|
var _util = require("./util.js");
|
||||||
|
var context = require("../index.js");
|
||||||
|
var _plugin = require("./plugin.js");
|
||||||
|
var _item = require("./item.js");
|
||||||
|
var _configChain = require("./config-chain.js");
|
||||||
|
var _deepArray = require("./helpers/deep-array.js");
|
||||||
|
function _traverse() {
|
||||||
|
const data = require("@babel/traverse");
|
||||||
|
_traverse = function () {
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
var _caching = require("./caching.js");
|
||||||
|
var _options = require("./validation/options.js");
|
||||||
|
var _plugins = require("./validation/plugins.js");
|
||||||
|
var _configApi = require("./helpers/config-api.js");
|
||||||
|
var _partial = require("./partial.js");
|
||||||
|
var _configError = require("../errors/config-error.js");
|
||||||
|
var _default = exports.default = _gensync()(function* loadFullConfig(inputOpts) {
|
||||||
|
var _opts$assumptions;
|
||||||
|
const result = yield* (0, _partial.default)(inputOpts);
|
||||||
|
if (!result) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
const {
|
||||||
|
options,
|
||||||
|
context,
|
||||||
|
fileHandling
|
||||||
|
} = result;
|
||||||
|
if (fileHandling === "ignored") {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
const optionDefaults = {};
|
||||||
|
const {
|
||||||
|
plugins,
|
||||||
|
presets
|
||||||
|
} = options;
|
||||||
|
if (!plugins || !presets) {
|
||||||
|
throw new Error("Assertion failure - plugins and presets exist");
|
||||||
|
}
|
||||||
|
const presetContext = Object.assign({}, context, {
|
||||||
|
targets: options.targets
|
||||||
|
});
|
||||||
|
const toDescriptor = item => {
|
||||||
|
const desc = (0, _item.getItemDescriptor)(item);
|
||||||
|
if (!desc) {
|
||||||
|
throw new Error("Assertion failure - must be config item");
|
||||||
|
}
|
||||||
|
return desc;
|
||||||
|
};
|
||||||
|
const presetsDescriptors = presets.map(toDescriptor);
|
||||||
|
const initialPluginsDescriptors = plugins.map(toDescriptor);
|
||||||
|
const pluginDescriptorsByPass = [[]];
|
||||||
|
const passes = [];
|
||||||
|
const externalDependencies = [];
|
||||||
|
const ignored = yield* enhanceError(context, function* recursePresetDescriptors(rawPresets, pluginDescriptorsPass) {
|
||||||
|
const presets = [];
|
||||||
|
for (let i = 0; i < rawPresets.length; i++) {
|
||||||
|
const descriptor = rawPresets[i];
|
||||||
|
if (descriptor.options !== false) {
|
||||||
|
try {
|
||||||
|
var preset = yield* loadPresetDescriptor(descriptor, presetContext);
|
||||||
|
} catch (e) {
|
||||||
|
if (e.code === "BABEL_UNKNOWN_OPTION") {
|
||||||
|
(0, _options.checkNoUnwrappedItemOptionPairs)(rawPresets, i, "preset", e);
|
||||||
|
}
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
externalDependencies.push(preset.externalDependencies);
|
||||||
|
if (descriptor.ownPass) {
|
||||||
|
presets.push({
|
||||||
|
preset: preset.chain,
|
||||||
|
pass: []
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
presets.unshift({
|
||||||
|
preset: preset.chain,
|
||||||
|
pass: pluginDescriptorsPass
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (presets.length > 0) {
|
||||||
|
pluginDescriptorsByPass.splice(1, 0, ...presets.map(o => o.pass).filter(p => p !== pluginDescriptorsPass));
|
||||||
|
for (const {
|
||||||
|
preset,
|
||||||
|
pass
|
||||||
|
} of presets) {
|
||||||
|
if (!preset) return true;
|
||||||
|
pass.push(...preset.plugins);
|
||||||
|
const ignored = yield* recursePresetDescriptors(preset.presets, pass);
|
||||||
|
if (ignored) return true;
|
||||||
|
preset.options.forEach(opts => {
|
||||||
|
(0, _util.mergeOptions)(optionDefaults, opts);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})(presetsDescriptors, pluginDescriptorsByPass[0]);
|
||||||
|
if (ignored) return null;
|
||||||
|
const opts = optionDefaults;
|
||||||
|
(0, _util.mergeOptions)(opts, options);
|
||||||
|
const pluginContext = Object.assign({}, presetContext, {
|
||||||
|
assumptions: (_opts$assumptions = opts.assumptions) != null ? _opts$assumptions : {}
|
||||||
|
});
|
||||||
|
yield* enhanceError(context, function* loadPluginDescriptors() {
|
||||||
|
pluginDescriptorsByPass[0].unshift(...initialPluginsDescriptors);
|
||||||
|
for (const descs of pluginDescriptorsByPass) {
|
||||||
|
const pass = [];
|
||||||
|
passes.push(pass);
|
||||||
|
for (let i = 0; i < descs.length; i++) {
|
||||||
|
const descriptor = descs[i];
|
||||||
|
if (descriptor.options !== false) {
|
||||||
|
try {
|
||||||
|
var plugin = yield* loadPluginDescriptor(descriptor, pluginContext);
|
||||||
|
} catch (e) {
|
||||||
|
if (e.code === "BABEL_UNKNOWN_PLUGIN_PROPERTY") {
|
||||||
|
(0, _options.checkNoUnwrappedItemOptionPairs)(descs, i, "plugin", e);
|
||||||
|
}
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
pass.push(plugin);
|
||||||
|
externalDependencies.push(plugin.externalDependencies);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
opts.plugins = passes[0];
|
||||||
|
opts.presets = passes.slice(1).filter(plugins => plugins.length > 0).map(plugins => ({
|
||||||
|
plugins
|
||||||
|
}));
|
||||||
|
opts.passPerPreset = opts.presets.length > 0;
|
||||||
|
return {
|
||||||
|
options: opts,
|
||||||
|
passes: passes,
|
||||||
|
externalDependencies: (0, _deepArray.finalize)(externalDependencies)
|
||||||
|
};
|
||||||
|
});
|
||||||
|
function enhanceError(context, fn) {
|
||||||
|
return function* (arg1, arg2) {
|
||||||
|
try {
|
||||||
|
return yield* fn(arg1, arg2);
|
||||||
|
} catch (e) {
|
||||||
|
if (!e.message.startsWith("[BABEL]")) {
|
||||||
|
var _context$filename;
|
||||||
|
e.message = `[BABEL] ${(_context$filename = context.filename) != null ? _context$filename : "unknown file"}: ${e.message}`;
|
||||||
|
}
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
const makeDescriptorLoader = apiFactory => (0, _caching.makeWeakCache)(function* ({
|
||||||
|
value,
|
||||||
|
options,
|
||||||
|
dirname,
|
||||||
|
alias
|
||||||
|
}, cache) {
|
||||||
|
if (options === false) throw new Error("Assertion failure");
|
||||||
|
options = options || {};
|
||||||
|
const externalDependencies = [];
|
||||||
|
let item = value;
|
||||||
|
if (typeof value === "function") {
|
||||||
|
const factory = (0, _async.maybeAsync)(value, `You appear to be using an async plugin/preset, but Babel has been called synchronously`);
|
||||||
|
const api = Object.assign({}, context, apiFactory(cache, externalDependencies));
|
||||||
|
try {
|
||||||
|
item = yield* factory(api, options, dirname);
|
||||||
|
} catch (e) {
|
||||||
|
if (alias) {
|
||||||
|
e.message += ` (While processing: ${JSON.stringify(alias)})`;
|
||||||
|
}
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!item || typeof item !== "object") {
|
||||||
|
throw new Error("Plugin/Preset did not return an object.");
|
||||||
|
}
|
||||||
|
if ((0, _async.isThenable)(item)) {
|
||||||
|
yield* [];
|
||||||
|
throw new Error(`You appear to be using a promise as a plugin, ` + `which your current version of Babel does not support. ` + `If you're using a published plugin, ` + `you may need to upgrade your @babel/core version. ` + `As an alternative, you can prefix the promise with "await". ` + `(While processing: ${JSON.stringify(alias)})`);
|
||||||
|
}
|
||||||
|
if (externalDependencies.length > 0 && (!cache.configured() || cache.mode() === "forever")) {
|
||||||
|
let error = `A plugin/preset has external untracked dependencies ` + `(${externalDependencies[0]}), but the cache `;
|
||||||
|
if (!cache.configured()) {
|
||||||
|
error += `has not been configured to be invalidated when the external dependencies change. `;
|
||||||
|
} else {
|
||||||
|
error += ` has been configured to never be invalidated. `;
|
||||||
|
}
|
||||||
|
error += `Plugins/presets should configure their cache to be invalidated when the external ` + `dependencies change, for example using \`api.cache.invalidate(() => ` + `statSync(filepath).mtimeMs)\` or \`api.cache.never()\`\n` + `(While processing: ${JSON.stringify(alias)})`;
|
||||||
|
throw new Error(error);
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
value: item,
|
||||||
|
options,
|
||||||
|
dirname,
|
||||||
|
alias,
|
||||||
|
externalDependencies: (0, _deepArray.finalize)(externalDependencies)
|
||||||
|
};
|
||||||
|
});
|
||||||
|
const pluginDescriptorLoader = makeDescriptorLoader(_configApi.makePluginAPI);
|
||||||
|
const presetDescriptorLoader = makeDescriptorLoader(_configApi.makePresetAPI);
|
||||||
|
const instantiatePlugin = (0, _caching.makeWeakCache)(function* ({
|
||||||
|
value,
|
||||||
|
options,
|
||||||
|
dirname,
|
||||||
|
alias,
|
||||||
|
externalDependencies
|
||||||
|
}, cache) {
|
||||||
|
const pluginObj = (0, _plugins.validatePluginObject)(value);
|
||||||
|
const plugin = Object.assign({}, pluginObj);
|
||||||
|
if (plugin.visitor) {
|
||||||
|
plugin.visitor = _traverse().default.explode(Object.assign({}, plugin.visitor));
|
||||||
|
}
|
||||||
|
if (plugin.inherits) {
|
||||||
|
const inheritsDescriptor = {
|
||||||
|
name: undefined,
|
||||||
|
alias: `${alias}$inherits`,
|
||||||
|
value: plugin.inherits,
|
||||||
|
options,
|
||||||
|
dirname
|
||||||
|
};
|
||||||
|
const inherits = yield* (0, _async.forwardAsync)(loadPluginDescriptor, run => {
|
||||||
|
return cache.invalidate(data => run(inheritsDescriptor, data));
|
||||||
|
});
|
||||||
|
plugin.pre = chainMaybeAsync(inherits.pre, plugin.pre);
|
||||||
|
plugin.post = chainMaybeAsync(inherits.post, plugin.post);
|
||||||
|
plugin.manipulateOptions = chainMaybeAsync(inherits.manipulateOptions, plugin.manipulateOptions);
|
||||||
|
plugin.visitor = _traverse().default.visitors.merge([inherits.visitor || {}, plugin.visitor || {}]);
|
||||||
|
if (inherits.externalDependencies.length > 0) {
|
||||||
|
if (externalDependencies.length === 0) {
|
||||||
|
externalDependencies = inherits.externalDependencies;
|
||||||
|
} else {
|
||||||
|
externalDependencies = (0, _deepArray.finalize)([externalDependencies, inherits.externalDependencies]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new _plugin.default(plugin, options, alias, externalDependencies);
|
||||||
|
});
|
||||||
|
function* loadPluginDescriptor(descriptor, context) {
|
||||||
|
if (descriptor.value instanceof _plugin.default) {
|
||||||
|
if (descriptor.options) {
|
||||||
|
throw new Error("Passed options to an existing Plugin instance will not work.");
|
||||||
|
}
|
||||||
|
return descriptor.value;
|
||||||
|
}
|
||||||
|
return yield* instantiatePlugin(yield* pluginDescriptorLoader(descriptor, context), context);
|
||||||
|
}
|
||||||
|
const needsFilename = val => val && typeof val !== "function";
|
||||||
|
const validateIfOptionNeedsFilename = (options, descriptor) => {
|
||||||
|
if (needsFilename(options.test) || needsFilename(options.include) || needsFilename(options.exclude)) {
|
||||||
|
const formattedPresetName = descriptor.name ? `"${descriptor.name}"` : "/* your preset */";
|
||||||
|
throw new _configError.default([`Preset ${formattedPresetName} requires a filename to be set when babel is called directly,`, `\`\`\``, `babel.transformSync(code, { filename: 'file.ts', presets: [${formattedPresetName}] });`, `\`\`\``, `See https://babeljs.io/docs/en/options#filename for more information.`].join("\n"));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const validatePreset = (preset, context, descriptor) => {
|
||||||
|
if (!context.filename) {
|
||||||
|
var _options$overrides;
|
||||||
|
const {
|
||||||
|
options
|
||||||
|
} = preset;
|
||||||
|
validateIfOptionNeedsFilename(options, descriptor);
|
||||||
|
(_options$overrides = options.overrides) == null || _options$overrides.forEach(overrideOptions => validateIfOptionNeedsFilename(overrideOptions, descriptor));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const instantiatePreset = (0, _caching.makeWeakCacheSync)(({
|
||||||
|
value,
|
||||||
|
dirname,
|
||||||
|
alias,
|
||||||
|
externalDependencies
|
||||||
|
}) => {
|
||||||
|
return {
|
||||||
|
options: (0, _options.validate)("preset", value),
|
||||||
|
alias,
|
||||||
|
dirname,
|
||||||
|
externalDependencies
|
||||||
|
};
|
||||||
|
});
|
||||||
|
function* loadPresetDescriptor(descriptor, context) {
|
||||||
|
const preset = instantiatePreset(yield* presetDescriptorLoader(descriptor, context));
|
||||||
|
validatePreset(preset, context, descriptor);
|
||||||
|
return {
|
||||||
|
chain: yield* (0, _configChain.buildPresetChain)(preset, context),
|
||||||
|
externalDependencies: preset.externalDependencies
|
||||||
|
};
|
||||||
|
}
|
||||||
|
function chainMaybeAsync(a, b) {
|
||||||
|
if (!a) return b;
|
||||||
|
if (!b) return a;
|
||||||
|
return function (...args) {
|
||||||
|
const res = a.apply(this, args);
|
||||||
|
if (res && typeof res.then === "function") {
|
||||||
|
return res.then(() => b.apply(this, args));
|
||||||
|
}
|
||||||
|
return b.apply(this, args);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
0 && 0;
|
||||||
|
|
||||||
|
//# sourceMappingURL=full.js.map
|
||||||
+1
File diff suppressed because one or more lines are too long
+85
@@ -0,0 +1,85 @@
|
|||||||
|
"use strict";
|
||||||
|
|
||||||
|
Object.defineProperty(exports, "__esModule", {
|
||||||
|
value: true
|
||||||
|
});
|
||||||
|
exports.makeConfigAPI = makeConfigAPI;
|
||||||
|
exports.makePluginAPI = makePluginAPI;
|
||||||
|
exports.makePresetAPI = makePresetAPI;
|
||||||
|
function _semver() {
|
||||||
|
const data = require("semver");
|
||||||
|
_semver = function () {
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
var _index = require("../../index.js");
|
||||||
|
var _caching = require("../caching.js");
|
||||||
|
function makeConfigAPI(cache) {
|
||||||
|
const env = value => cache.using(data => {
|
||||||
|
if (value === undefined) return data.envName;
|
||||||
|
if (typeof value === "function") {
|
||||||
|
return (0, _caching.assertSimpleType)(value(data.envName));
|
||||||
|
}
|
||||||
|
return (Array.isArray(value) ? value : [value]).some(entry => {
|
||||||
|
if (typeof entry !== "string") {
|
||||||
|
throw new Error("Unexpected non-string value");
|
||||||
|
}
|
||||||
|
return entry === data.envName;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
const caller = cb => cache.using(data => (0, _caching.assertSimpleType)(cb(data.caller)));
|
||||||
|
return {
|
||||||
|
version: _index.version,
|
||||||
|
cache: cache.simple(),
|
||||||
|
env,
|
||||||
|
async: () => false,
|
||||||
|
caller,
|
||||||
|
assertVersion
|
||||||
|
};
|
||||||
|
}
|
||||||
|
function makePresetAPI(cache, externalDependencies) {
|
||||||
|
const targets = () => JSON.parse(cache.using(data => JSON.stringify(data.targets)));
|
||||||
|
const addExternalDependency = ref => {
|
||||||
|
externalDependencies.push(ref);
|
||||||
|
};
|
||||||
|
return Object.assign({}, makeConfigAPI(cache), {
|
||||||
|
targets,
|
||||||
|
addExternalDependency
|
||||||
|
});
|
||||||
|
}
|
||||||
|
function makePluginAPI(cache, externalDependencies) {
|
||||||
|
const assumption = name => cache.using(data => data.assumptions[name]);
|
||||||
|
return Object.assign({}, makePresetAPI(cache, externalDependencies), {
|
||||||
|
assumption
|
||||||
|
});
|
||||||
|
}
|
||||||
|
function assertVersion(range) {
|
||||||
|
if (typeof range === "number") {
|
||||||
|
if (!Number.isInteger(range)) {
|
||||||
|
throw new Error("Expected string or integer value.");
|
||||||
|
}
|
||||||
|
range = `^${range}.0.0-0`;
|
||||||
|
}
|
||||||
|
if (typeof range !== "string") {
|
||||||
|
throw new Error("Expected string or integer value.");
|
||||||
|
}
|
||||||
|
if (range === "*" || _semver().satisfies(_index.version, range)) return;
|
||||||
|
const message = `Requires Babel "${range}", but was loaded with "${_index.version}". ` + `If you are sure you have a compatible version of @babel/core, ` + `it is likely that something in your build process is loading the ` + `wrong version. Inspect the stack trace of this error to look for ` + `the first entry that doesn't mention "@babel/core" or "babel-core" ` + `to see what is calling Babel.`;
|
||||||
|
const limit = Error.stackTraceLimit;
|
||||||
|
if (typeof limit === "number" && limit < 25) {
|
||||||
|
Error.stackTraceLimit = 25;
|
||||||
|
}
|
||||||
|
const err = new Error(message);
|
||||||
|
if (typeof limit === "number") {
|
||||||
|
Error.stackTraceLimit = limit;
|
||||||
|
}
|
||||||
|
throw Object.assign(err, {
|
||||||
|
code: "BABEL_VERSION_UNSUPPORTED",
|
||||||
|
version: _index.version,
|
||||||
|
range
|
||||||
|
});
|
||||||
|
}
|
||||||
|
0 && 0;
|
||||||
|
|
||||||
|
//# sourceMappingURL=config-api.js.map
|
||||||
+1
File diff suppressed because one or more lines are too long
+23
@@ -0,0 +1,23 @@
|
|||||||
|
"use strict";
|
||||||
|
|
||||||
|
Object.defineProperty(exports, "__esModule", {
|
||||||
|
value: true
|
||||||
|
});
|
||||||
|
exports.finalize = finalize;
|
||||||
|
exports.flattenToSet = flattenToSet;
|
||||||
|
function finalize(deepArr) {
|
||||||
|
return Object.freeze(deepArr);
|
||||||
|
}
|
||||||
|
function flattenToSet(arr) {
|
||||||
|
const result = new Set();
|
||||||
|
const stack = [arr];
|
||||||
|
while (stack.length > 0) {
|
||||||
|
for (const el of stack.pop()) {
|
||||||
|
if (Array.isArray(el)) stack.push(el);else result.add(el);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
0 && 0;
|
||||||
|
|
||||||
|
//# sourceMappingURL=deep-array.js.map
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
{"version":3,"names":["finalize","deepArr","Object","freeze","flattenToSet","arr","result","Set","stack","length","el","pop","Array","isArray","push","add"],"sources":["../../../src/config/helpers/deep-array.ts"],"sourcesContent":["export type DeepArray<T> = (T | ReadonlyDeepArray<T>)[];\n\n// Just to make sure that DeepArray<T> is not assignable to ReadonlyDeepArray<T>\ndeclare const __marker: unique symbol;\nexport type ReadonlyDeepArray<T> = readonly (T | ReadonlyDeepArray<T>)[] & {\n [__marker]: true;\n};\n\nexport function finalize<T>(deepArr: DeepArray<T>): ReadonlyDeepArray<T> {\n return Object.freeze(deepArr) as ReadonlyDeepArray<T>;\n}\n\nexport function flattenToSet<T extends string>(\n arr: ReadonlyDeepArray<T>,\n): Set<T> {\n const result = new Set<T>();\n const stack = [arr];\n while (stack.length > 0) {\n for (const el of stack.pop()) {\n if (Array.isArray(el)) stack.push(el as ReadonlyDeepArray<T>);\n else result.add(el as T);\n }\n }\n return result;\n}\n"],"mappings":";;;;;;;AAQO,SAASA,QAAQA,CAAIC,OAAqB,EAAwB;EACvE,OAAOC,MAAM,CAACC,MAAM,CAACF,OAAO,CAAC;AAC/B;AAEO,SAASG,YAAYA,CAC1BC,GAAyB,EACjB;EACR,MAAMC,MAAM,GAAG,IAAIC,GAAG,CAAI,CAAC;EAC3B,MAAMC,KAAK,GAAG,CAACH,GAAG,CAAC;EACnB,OAAOG,KAAK,CAACC,MAAM,GAAG,CAAC,EAAE;IACvB,KAAK,MAAMC,EAAE,IAAIF,KAAK,CAACG,GAAG,CAAC,CAAC,EAAE;MAC5B,IAAIC,KAAK,CAACC,OAAO,CAACH,EAAE,CAAC,EAAEF,KAAK,CAACM,IAAI,CAACJ,EAA0B,CAAC,CAAC,KACzDJ,MAAM,CAACS,GAAG,CAACL,EAAO,CAAC;IAC1B;EACF;EACA,OAAOJ,MAAM;AACf;AAAC","ignoreList":[]}
|
||||||
+12
@@ -0,0 +1,12 @@
|
|||||||
|
"use strict";
|
||||||
|
|
||||||
|
Object.defineProperty(exports, "__esModule", {
|
||||||
|
value: true
|
||||||
|
});
|
||||||
|
exports.getEnv = getEnv;
|
||||||
|
function getEnv(defaultValue = "development") {
|
||||||
|
return process.env.BABEL_ENV || process.env.NODE_ENV || defaultValue;
|
||||||
|
}
|
||||||
|
0 && 0;
|
||||||
|
|
||||||
|
//# sourceMappingURL=environment.js.map
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
{"version":3,"names":["getEnv","defaultValue","process","env","BABEL_ENV","NODE_ENV"],"sources":["../../../src/config/helpers/environment.ts"],"sourcesContent":["export function getEnv(defaultValue: string = \"development\"): string {\n return process.env.BABEL_ENV || process.env.NODE_ENV || defaultValue;\n}\n"],"mappings":";;;;;;AAAO,SAASA,MAAMA,CAACC,YAAoB,GAAG,aAAa,EAAU;EACnE,OAAOC,OAAO,CAACC,GAAG,CAACC,SAAS,IAAIF,OAAO,CAACC,GAAG,CAACE,QAAQ,IAAIJ,YAAY;AACtE;AAAC","ignoreList":[]}
|
||||||
+87
@@ -0,0 +1,87 @@
|
|||||||
|
"use strict";
|
||||||
|
|
||||||
|
Object.defineProperty(exports, "__esModule", {
|
||||||
|
value: true
|
||||||
|
});
|
||||||
|
exports.createConfigItem = createConfigItem;
|
||||||
|
exports.createConfigItemAsync = createConfigItemAsync;
|
||||||
|
exports.createConfigItemSync = createConfigItemSync;
|
||||||
|
Object.defineProperty(exports, "default", {
|
||||||
|
enumerable: true,
|
||||||
|
get: function () {
|
||||||
|
return _full.default;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
exports.loadOptions = loadOptions;
|
||||||
|
exports.loadOptionsAsync = loadOptionsAsync;
|
||||||
|
exports.loadOptionsSync = loadOptionsSync;
|
||||||
|
exports.loadPartialConfig = loadPartialConfig;
|
||||||
|
exports.loadPartialConfigAsync = loadPartialConfigAsync;
|
||||||
|
exports.loadPartialConfigSync = loadPartialConfigSync;
|
||||||
|
function _gensync() {
|
||||||
|
const data = require("gensync");
|
||||||
|
_gensync = function () {
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
var _full = require("./full.js");
|
||||||
|
var _partial = require("./partial.js");
|
||||||
|
var _item = require("./item.js");
|
||||||
|
var _rewriteStackTrace = require("../errors/rewrite-stack-trace.js");
|
||||||
|
const loadPartialConfigRunner = _gensync()(_partial.loadPartialConfig);
|
||||||
|
function loadPartialConfigAsync(...args) {
|
||||||
|
return (0, _rewriteStackTrace.beginHiddenCallStack)(loadPartialConfigRunner.async)(...args);
|
||||||
|
}
|
||||||
|
function loadPartialConfigSync(...args) {
|
||||||
|
return (0, _rewriteStackTrace.beginHiddenCallStack)(loadPartialConfigRunner.sync)(...args);
|
||||||
|
}
|
||||||
|
function loadPartialConfig(opts, callback) {
|
||||||
|
if (callback !== undefined) {
|
||||||
|
(0, _rewriteStackTrace.beginHiddenCallStack)(loadPartialConfigRunner.errback)(opts, callback);
|
||||||
|
} else if (typeof opts === "function") {
|
||||||
|
(0, _rewriteStackTrace.beginHiddenCallStack)(loadPartialConfigRunner.errback)(undefined, opts);
|
||||||
|
} else {
|
||||||
|
return loadPartialConfigSync(opts);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function* loadOptionsImpl(opts) {
|
||||||
|
var _config$options;
|
||||||
|
const config = yield* (0, _full.default)(opts);
|
||||||
|
return (_config$options = config == null ? void 0 : config.options) != null ? _config$options : null;
|
||||||
|
}
|
||||||
|
const loadOptionsRunner = _gensync()(loadOptionsImpl);
|
||||||
|
function loadOptionsAsync(...args) {
|
||||||
|
return (0, _rewriteStackTrace.beginHiddenCallStack)(loadOptionsRunner.async)(...args);
|
||||||
|
}
|
||||||
|
function loadOptionsSync(...args) {
|
||||||
|
return (0, _rewriteStackTrace.beginHiddenCallStack)(loadOptionsRunner.sync)(...args);
|
||||||
|
}
|
||||||
|
function loadOptions(opts, callback) {
|
||||||
|
if (callback !== undefined) {
|
||||||
|
(0, _rewriteStackTrace.beginHiddenCallStack)(loadOptionsRunner.errback)(opts, callback);
|
||||||
|
} else if (typeof opts === "function") {
|
||||||
|
(0, _rewriteStackTrace.beginHiddenCallStack)(loadOptionsRunner.errback)(undefined, opts);
|
||||||
|
} else {
|
||||||
|
return loadOptionsSync(opts);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const createConfigItemRunner = _gensync()(_item.createConfigItem);
|
||||||
|
function createConfigItemAsync(...args) {
|
||||||
|
return (0, _rewriteStackTrace.beginHiddenCallStack)(createConfigItemRunner.async)(...args);
|
||||||
|
}
|
||||||
|
function createConfigItemSync(...args) {
|
||||||
|
return (0, _rewriteStackTrace.beginHiddenCallStack)(createConfigItemRunner.sync)(...args);
|
||||||
|
}
|
||||||
|
function createConfigItem(target, options, callback) {
|
||||||
|
if (callback !== undefined) {
|
||||||
|
(0, _rewriteStackTrace.beginHiddenCallStack)(createConfigItemRunner.errback)(target, options, callback);
|
||||||
|
} else if (typeof options === "function") {
|
||||||
|
(0, _rewriteStackTrace.beginHiddenCallStack)(createConfigItemRunner.errback)(target, undefined, callback);
|
||||||
|
} else {
|
||||||
|
return createConfigItemSync(target, options);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
0 && 0;
|
||||||
|
|
||||||
|
//# sourceMappingURL=index.js.map
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user