chore: flatten the app workspace
This commit is contained in:
parent
5b19bcd324
commit
f6b71023ec
31 changed files with 373 additions and 475 deletions
11
.gitignore
vendored
11
.gitignore
vendored
|
|
@ -1,18 +1,18 @@
|
|||
node_modules/
|
||||
dist/
|
||||
|
||||
# generated at publish time from apps/mnswpr/README.md (see scripts/publish-lib.js)
|
||||
packages/mnswpr/README.md
|
||||
|
||||
.claude
|
||||
|
||||
# Production / local Firebase config values are not committed — set them as
|
||||
# Netlify env vars, or keep them in a local, gitignored env file. Dev values
|
||||
# live in the committed apps/mnswpr/.env.development (public, non-secret keys).
|
||||
# live in the committed .env.development (public, non-secret keys).
|
||||
.env.production
|
||||
.env.local
|
||||
.env.*.local
|
||||
|
||||
# Netlify CLI site link (written by `netlify link`)
|
||||
.netlify/
|
||||
|
||||
# Firebase emulator artifacts
|
||||
firebase-debug.log
|
||||
firestore-debug.log
|
||||
|
|
@ -22,6 +22,3 @@ ui-debug.log
|
|||
*~
|
||||
*swo
|
||||
*swp
|
||||
|
||||
# TEMPORARY - or unnecesary if done
|
||||
apps/mnswpr/MIGRATION.md
|
||||
|
|
|
|||
66
AGENTS.md
66
AGENTS.md
|
|
@ -6,27 +6,27 @@ Guidance for AI coding agents working in this repository.
|
|||
|
||||
Classic Minesweeper as a vanilla web game — no framework, no TypeScript (JSDoc + `// @ts-check` only). Deployed at [mnswpr.com](https://mnswpr.com) (Netlify), with a Firestore-backed leaderboard.
|
||||
|
||||
**This repo is only the app.** The engine, leaderboard, and shared services (`@cozy-games/mnswpr`, `@cozy-games/leaderboard`, `@cozy-games/utils`) live in [ayo-run/cozy-games](https://github.com/ayo-run/cozy-games) and are consumed here **from npm** — there is no local `packages/` to edit. A change to game mechanics, leaderboard internals, or the shared services belongs in that repo and arrives here as a version bump in `apps/mnswpr/package.json`.
|
||||
**This repo is only the app.** The engine, leaderboard, and shared services (`@cozy-games/mnswpr`, `@cozy-games/leaderboard`, `@cozy-games/utils`) live in [ayo-run/cozy-games](https://github.com/ayo-run/cozy-games) and are consumed here **from npm** — there is no local `packages/` to edit. A change to game mechanics, leaderboard internals, or the shared services belongs in that repo and arrives here as a version bump in `package.json`.
|
||||
|
||||
Structurally it is still a pnpm workspace (`pnpm-workspace.yaml` → `apps/*`) with a single member, `apps/mnswpr`, so app scripts are addressed with pnpm's `-F` filter.
|
||||
Structurally it is a single package at the repo root — no workspace, no `apps/` nesting. Every script runs from the root with plain `pnpm run <script>`.
|
||||
|
||||
## Commands
|
||||
|
||||
Workspace-wide commands run from the root; app commands target the app with pnpm's `-F` filter. `pnpm dev` and `pnpm build` are root aliases for the two most common ones.
|
||||
All commands run from the repo root.
|
||||
|
||||
```bash
|
||||
pnpm i # install (pnpm is required — this is a pnpm workspace)
|
||||
pnpm i # install (pnpm is required)
|
||||
pnpm test # run the Vitest suite once (jsdom)
|
||||
pnpm test:watch # run Vitest in watch mode
|
||||
pnpm lint # eslint . (JS + CSS); runs automatically on pre-commit
|
||||
pnpm lint:fix # eslint --fix
|
||||
pnpm scan:secrets # secretlint over the tree
|
||||
|
||||
pnpm -F mnswpr run dev # Firestore emulator + auto-seed + dev server (emulators:exec) — most common; needs JDK 21+
|
||||
pnpm -F mnswpr run dev:no-db # plain vite, no emulator (UI-only work / no JDK)
|
||||
pnpm -F mnswpr run build # build the website -> apps/mnswpr/dist
|
||||
pnpm -F mnswpr run preview # serve the production build
|
||||
pnpm -F mnswpr run build:preview # build the app and serve the production preview
|
||||
pnpm run dev # Firestore emulator + auto-seed + dev server (emulators:exec) — most common; needs JDK 21+
|
||||
pnpm run dev:no-db # plain vite, no emulator (UI-only work / no JDK)
|
||||
pnpm run build # build the website -> dist
|
||||
pnpm run preview # serve the production build
|
||||
pnpm run build:preview # build the app and serve the production preview
|
||||
```
|
||||
|
||||
Run a single test file or name: `pnpm vitest run scripts/test/check-content.test.js` · `pnpm vitest run -t 'partial name'`.
|
||||
|
|
@ -35,7 +35,7 @@ Run a single test file or name: `pnpm vitest run scripts/test/check-content.test
|
|||
|
||||
**Every infra operation — provision, deploy hosting, deploy DB, manage env — is doable from the CLI, and every configuration/schema is codified in-repo.** Nothing lives only in a web dashboard. There are two distinct layers, both owned by the app:
|
||||
|
||||
**1. App infra *config* — declarative, committed, deployed state.** These files ARE the source of truth; deploying just pushes them up. For `mnswpr`, all under `apps/mnswpr/`:
|
||||
**1. App infra *config* — declarative, committed, deployed state.** These files ARE the source of truth; deploying just pushes them up. All at the repo root:
|
||||
|
||||
| File | Codifies |
|
||||
| --- | --- |
|
||||
|
|
@ -46,50 +46,52 @@ Run a single test file or name: `pnpm vitest run scripts/test/check-content.test
|
|||
| `netlify.toml` | Netlify hosting: build command, publish dir, redirects, headers, build env |
|
||||
| `.env.example` | The full env-var contract; real prod values are set as Netlify env vars via CLI, never committed |
|
||||
|
||||
**2. App infra *tools* — the CLIs that act on that config.** They are versioned **devDependencies** of the app (not `npx`-on-demand, not global installs), so `pnpm install` pins them and every machine gets the same version. `mnswpr` depends on `firebase-tools` and `netlify-cli`; its scripts call the `firebase`/`netlify` binaries directly (pnpm puts the app's `node_modules/.bin` on `PATH`). A future app using a different stack (Postgres, a different host) declares *its* CLIs as *its* devDependencies and backs the same generic script names — so `pnpm -F <name> run deploy:db` stays uniform.
|
||||
**2. App infra *tools* — the CLIs that act on that config.** They are versioned **devDependencies** (not `npx`-on-demand, not global installs), so `pnpm install` pins them and every machine gets the same version. The app depends on `firebase-tools` and `netlify-cli`; its scripts call the `firebase`/`netlify` binaries directly (pnpm puts `node_modules/.bin` on `PATH`).
|
||||
|
||||
Each app **owns its infra scripts** in its own `package.json` under generic, tech-agnostic names (`deploy:db`, not `deploy:firestore`) — run them by targeting the app with pnpm's `-F` filter (no root wrapper scripts):
|
||||
Infra scripts live in `package.json` under generic, tech-agnostic names (`deploy:db`, not `deploy:firestore`), so swapping the underlying stack doesn't change the command you type:
|
||||
|
||||
```bash
|
||||
pnpm -F mnswpr run db:start # local DB emulator (mnswpr -> Firestore), standalone
|
||||
pnpm -F mnswpr run db:seed # seed the running local emulator
|
||||
pnpm -F mnswpr run db:stop # kill a stray/orphaned Firestore emulator holding :8080
|
||||
pnpm -F mnswpr run deploy:db # deploy DB rules/indexes (-> firebase deploy --only firestore)
|
||||
pnpm -F mnswpr run deploy:site # build + deploy hosting (-> netlify deploy --prod --dir=dist)
|
||||
pnpm run db:start # local DB emulator (mnswpr -> Firestore), standalone
|
||||
pnpm run db:seed # seed the running local emulator
|
||||
pnpm run db:stop # kill a stray/orphaned Firestore emulator holding :8080
|
||||
pnpm run deploy:db # deploy DB rules/indexes (-> firebase deploy --only firestore)
|
||||
pnpm run deploy:site # build + deploy hosting (-> netlify deploy --prod --dir=dist)
|
||||
```
|
||||
|
||||
**One-time per app / per machine (all CLI, no dashboard):**
|
||||
|
||||
```bash
|
||||
pnpm -F mnswpr exec firebase login # auth the Firebase CLI
|
||||
pnpm -F mnswpr exec netlify login # auth the Netlify CLI
|
||||
pnpm -F mnswpr exec netlify link # bind the app dir to its Netlify site (writes .netlify/, gitignored)
|
||||
pnpm exec firebase login # auth the Firebase CLI
|
||||
pnpm exec netlify login # auth the Netlify CLI
|
||||
pnpm exec netlify link # bind the app dir to its Netlify site (writes .netlify/, gitignored)
|
||||
```
|
||||
|
||||
**Managing hosting env vars via CLI** (keeps prod Firebase keys + `VITE_LB_NAMESPACE=mw` out of git while still reproducible):
|
||||
|
||||
```bash
|
||||
pnpm -F mnswpr exec netlify env:set VITE_LB_NAMESPACE mw # set one var
|
||||
pnpm -F mnswpr exec netlify env:import .env.production # bulk-import from a local (gitignored) env file
|
||||
pnpm -F mnswpr exec netlify env:list # inspect what's set
|
||||
pnpm exec netlify env:set VITE_LB_NAMESPACE mw # set one var
|
||||
pnpm exec netlify env:import .env.production # bulk-import from a local (gitignored) env file
|
||||
pnpm exec netlify env:list # inspect what's set
|
||||
```
|
||||
|
||||
**Non-npm tools get a setup script instead of a devDependency.** The Firestore emulator needs **Java** (it's a JVM program), which isn't an npm package — so `pnpm install` runs a root `postinstall` (`scripts/ensure-java.mjs`) that installs a user-local Temurin JRE 21 into `~/.local` without `sudo` when `java` is missing — idempotent, non-fatal, and auto-skipped on `CI` / `SKIP_JRE_SETUP` / unsupported platforms. Any future infra tool that isn't on npm follows the same pattern (a checked-in setup script), never a manual install step.
|
||||
|
||||
Tests run under **Vitest** with a jsdom environment (root config in `vitest.config.js`), which collects `apps/**/test/**/*.test.js` and `scripts/test/**/*.test.js`. Today only `scripts/test/` exists (the content scanner); app-level tests go in `apps/mnswpr/test/`. Engine and shared-package tests live in the cozy-games repo, not here. For anything visual or input-timing related, verify by running `pnpm -F mnswpr run dev` and playing.
|
||||
Tests run under **Vitest** with a jsdom environment (config in `vitest.config.js`), which collects `test/**/*.test.js` and `scripts/test/**/*.test.js`. Today only `scripts/test/` exists (the content scanner); app-level tests go in `test/`. Engine and shared-package tests live in the cozy-games repo, not here. For anything visual or input-timing related, verify by running `pnpm run dev` and playing.
|
||||
|
||||
Node version: `.nvmrc` pins `lts/*`.
|
||||
|
||||
## Repository layout
|
||||
|
||||
`pnpm-workspace.yaml` declares `apps/*`; `apps/mnswpr/` (package name `mnswpr`) is the only member.
|
||||
A single package (`mnswpr`) rooted at the repo root.
|
||||
|
||||
- **`apps/mnswpr/`** — the mnswpr.com website. `main.js` composes the npm packages; `index.html` + `main.css` are the shell; `modules/` holds the two app-owned services; `scripts/` holds app scripts (dev seeding, legends export); `docs/` documents the backend. Owns its infra config (`firebase.json`, `firestore.rules`, `.firebaserc`, `netlify.toml`).
|
||||
- **`scripts/`** — repo-level tooling: `check-content.mjs` (content policy scanner, tested in `scripts/test/`) and `ensure-java.mjs` (postinstall JRE bootstrap).
|
||||
- **root** — the mnswpr.com website. `main.js` composes the npm packages; `index.html` + `main.css` are the shell. Infra config lives here too (`firebase.json`, `firestore.rules`, `.firebaserc`, `netlify.toml`, `vite.config.js`).
|
||||
- **`modules/`** — the two app-owned services (`user/`, `nickname/`).
|
||||
- **`docs/`** — backend documentation (Firestore data model, env migration).
|
||||
- **`scripts/`** — tooling: `seed-dev-scores.js` and `export-legends.js` (app scripts), plus `check-content.mjs` (content policy scanner, tested in `scripts/test/`) and `ensure-java.mjs` (postinstall JRE bootstrap).
|
||||
|
||||
## Architecture
|
||||
|
||||
`apps/mnswpr/main.js` is ~75 lines and is the whole app: it wires three npm packages together and owns nothing else.
|
||||
`main.js` is ~75 lines and is the whole app: it wires three npm packages together and owns nothing else.
|
||||
|
||||
**The engine is decoupled from the app via two hooks.** `new mnswpr(appId, version, hooks)` is a constructor function that imperatively builds a `<table>` grid in the DOM. It knows nothing about Firebase or leaderboards. The app injects behavior through:
|
||||
|
||||
|
|
@ -112,18 +114,18 @@ The engine-internal notes below describe code that lives in the cozy-games repo
|
|||
|
||||
## Leaderboard / Firebase
|
||||
|
||||
Storage goes through `FirebaseAdapter` from `@cozy-games/leaderboard`; this repo supplies only configuration. Full data model, security rules, environments, and deployment: `apps/mnswpr/docs/firebase-leaderboards.md`.
|
||||
Storage goes through `FirebaseAdapter` from `@cozy-games/leaderboard`; this repo supplies only configuration. Full data model, security rules, environments, and deployment: `docs/firebase-leaderboards.md`.
|
||||
|
||||
**Firebase config comes from `VITE_FIREBASE_*` env vars** — dev values are committed in `apps/mnswpr/.env.development`, production values are Netlify env vars. For a client-only Firebase app the API key is **not a secret** (access is governed by `firestore.rules`), so don't treat the committed dev config as a leaked credential or try to hide it.
|
||||
**Firebase config comes from `VITE_FIREBASE_*` env vars** — dev values are committed in `.env.development`, production values are Netlify env vars. For a client-only Firebase app the API key is **not a secret** (access is governed by `firestore.rules`), so don't treat the committed dev config as a leaked credential or try to hide it.
|
||||
|
||||
**Namespace guards production.** `VITE_LB_NAMESPACE` selects the Firestore collection prefix and defaults to `mw-test`, so a missing env var can never write into the production board (`mw`). `VITE_FIRESTORE_EMULATOR=1` (set in `.env.development`) points dev at the local emulator; production builds always use real Firestore.
|
||||
|
||||
App-owned modules in `apps/mnswpr/modules/`: `UserService` (`user/user.js`) derives a non-cryptographic `browserId` fingerprint from navigator/screen properties to attribute scores without accounts; `NicknameService` (`nickname/nickname.js`) prompts for a display name on first visit and renders the greeting bar.
|
||||
App-owned modules in `modules/`: `UserService` (`user/user.js`) derives a non-cryptographic `browserId` fingerprint from navigator/screen properties to attribute scores without accounts; `NicknameService` (`nickname/nickname.js`) prompts for a display name on first visit and renders the greeting bar.
|
||||
|
||||
## Conventions
|
||||
|
||||
- **Code style is enforced by ESLint Stylistic**, not Prettier: 2-space indent, single quotes, **no semicolons**, no trailing commas, spaces inside `{ braces }` but not `[brackets]`. Run `pnpm lint:fix` before committing. Both `**/*.js` and `**/*.css` are linted (CSS via `@eslint/css`).
|
||||
- `apps/mnswpr/modules/` uses ES classes; `scripts/` uses plain functions. Match the surrounding style of the file you edit.
|
||||
- `modules/` uses ES classes; `scripts/` uses plain functions. Match the surrounding style of the file you edit.
|
||||
- **Content policy.** Commit messages, branch names, PR text, and contributed lines are checked by `scripts/check-content.mjs` (hooks + the `Checks` workflow) against `.repo-policy.json`. Write commit messages in plain project voice; no tool-attribution trailers or footers, no `Co-Authored-By:` line for anyone outside the policy's `allowedCoAuthors`, no session links.
|
||||
- The same scanner matches text against a maintainer-managed reserved-terms list. Findings report a location and a masked preview, never the term. If one flags your change, reword it or ask a maintainer — don't edit `.repo-policy.json`.
|
||||
- **Source stays JS + JSDoc (`// @ts-check`)** — no TypeScript. Nothing is published from this repo, so there is no type-generation step here; the `.d.ts` files shipped by `@cozy-games/*` are generated in the cozy-games repo.
|
||||
|
|
|
|||
|
|
@ -10,8 +10,8 @@ develop, test, and submit changes.
|
|||
|
||||
- **Node.js** — the version pinned in [`.nvmrc`](.nvmrc) (`lts/*`). With
|
||||
[nvm](https://github.com/nvm-sh/nvm): `nvm use`.
|
||||
- **pnpm** — this is a [pnpm](https://pnpm.io) workspace; **pnpm is required**
|
||||
(npm/yarn will not work). The repo pins its pnpm version via the
|
||||
- **pnpm** — **pnpm is required** (npm/yarn will not work). The repo pins its
|
||||
pnpm version via the
|
||||
`packageManager` field, so the simplest way to get the right one is Corepack:
|
||||
`corepack enable`.
|
||||
- **Java (JDK 11+, 21 recommended)** — only needed to run the local Firestore
|
||||
|
|
@ -22,46 +22,43 @@ develop, test, and submit changes.
|
|||
|
||||
## Project Structure
|
||||
|
||||
- `apps/` - Playable games (each deploys independently)
|
||||
- `packages/` - Shared, publishable libraries
|
||||
- `sites/` - Docs (Astro Starlight) and UI demos — placeholders for now
|
||||
This repo is a single package at the root — the mnswpr.com web app. `main.js`
|
||||
and `index.html` are the app itself, `modules/` holds the app-owned services,
|
||||
`scripts/` holds tooling, and `docs/` documents the backend. The game engine and
|
||||
leaderboard come from npm ([ayo-run/cozy-games](https://github.com/ayo-run/cozy-games));
|
||||
there is no local `packages/` to edit.
|
||||
|
||||
Each app owns its own backend config (e.g. mnswpr's Firestore rules live in
|
||||
`apps/mnswpr/`); the shared packages stay backend-agnostic.
|
||||
Backend config (Firestore rules, Firebase project aliases, Netlify hosting) is
|
||||
committed at the root — see [AGENTS.md](AGENTS.md) "Infra".
|
||||
|
||||
## Setup
|
||||
|
||||
```bash
|
||||
pnpm i # install all workspace dependencies
|
||||
pnpm i # install dependencies
|
||||
```
|
||||
|
||||
## Workspace commands (run from the repo root)
|
||||
## Commands (all run from the repo root)
|
||||
|
||||
```bash
|
||||
pnpm test # run the whole test suite once (Vitest, jsdom)
|
||||
pnpm test:watch # tests in watch mode
|
||||
pnpm lint # eslint (JS + CSS)
|
||||
pnpm lint:fix # eslint --fix
|
||||
pnpm build:lib # build the publishable engine -> packages/mnswpr/dist
|
||||
```
|
||||
|
||||
## Running a game locally
|
||||
|
||||
Apps aren't run from the root — target one by name with pnpm's `-F` filter. Apps
|
||||
are named `<name>` (e.g. `mnswpr`), so every app runs the same way
|
||||
(`pnpm -F <name> run <script>`):
|
||||
## Running the game locally
|
||||
|
||||
```bash
|
||||
pnpm -F mnswpr run dev # Vite dev server + Firestore emulator (auto-seeded) — needs Java
|
||||
pnpm -F mnswpr run dev:no-db # Vite only, no emulator (UI work, or no Java)
|
||||
pnpm -F mnswpr run build # build the app -> apps/mnswpr/dist
|
||||
pnpm -F mnswpr run preview # preview the production build
|
||||
pnpm run dev # Vite dev server + Firestore emulator (auto-seeded) — needs Java
|
||||
pnpm run dev:no-db # Vite only, no emulator (UI work, or no Java)
|
||||
pnpm run build # build the app -> dist
|
||||
pnpm run preview # preview the production build
|
||||
```
|
||||
|
||||
## Tests
|
||||
|
||||
Tests run under **Vitest** with a **jsdom** environment and live next to the code
|
||||
they exercise (`packages/*/test/`). They drive real behavior — e.g. mounting the
|
||||
they exercise (`test/`, `scripts/test/`). They drive real behavior — e.g. mounting the
|
||||
game and dispatching DOM events — not just isolated unit calls. Run `pnpm test`
|
||||
(or `pnpm test:watch`) before opening a PR, and add tests for new behavior.
|
||||
|
||||
|
|
@ -75,8 +72,7 @@ Style is enforced by **ESLint (Stylistic)**, not Prettier:
|
|||
|
||||
Run `pnpm lint:fix` before committing. The codebase is **plain JavaScript with
|
||||
JSDoc + `// @ts-check`** — no TypeScript. Match the style and patterns of the file
|
||||
you're editing (the game engine uses plain functions and closures; `packages/utils`
|
||||
and the app modules use ES classes).
|
||||
you're editing (`modules/` uses ES classes; `scripts/` uses plain functions).
|
||||
|
||||
A **pre-commit hook** runs the linter and a secret scan automatically — commits
|
||||
fail if either does. Keep credentials and any `.env.production` out of commits.
|
||||
|
|
@ -89,22 +85,19 @@ devDependencies) — no web dashboards. For mnswpr (Firestore + Netlify), the lo
|
|||
DB emulator is all a contributor needs:
|
||||
|
||||
```bash
|
||||
pnpm -F mnswpr run db:start # start the local Firestore emulator (standalone) — needs Java
|
||||
pnpm -F mnswpr run db:seed # seed the running emulator with sample data
|
||||
pnpm -F mnswpr run db:stop # stop a stray emulator holding :8080
|
||||
pnpm run db:start # start the local Firestore emulator (standalone) — needs Java
|
||||
pnpm run db:seed # seed the running emulator with sample data
|
||||
pnpm run db:stop # stop a stray emulator holding :8080
|
||||
```
|
||||
|
||||
Deploy scripts (`deploy:db`, `deploy:site`) also exist but require project
|
||||
credentials, so they're for maintainers. See
|
||||
[apps/mnswpr/README.md](apps/mnswpr/README.md) and that app's `docs/` for the full
|
||||
backend reference.
|
||||
credentials, so they're for maintainers. See [README.md](README.md) and
|
||||
[`docs/`](docs/) for the full backend reference.
|
||||
|
||||
## Project structure & decisions
|
||||
## Project structure
|
||||
|
||||
The repo layout is in the [README](README.md#layout). Significant architecture
|
||||
choices are recorded in [`docs/decisions/`](docs/decisions/) — worth a read before
|
||||
a large change. Shared packages stay backend-agnostic; each app owns its own
|
||||
backend config.
|
||||
The repo layout and architecture are documented in [AGENTS.md](AGENTS.md) —
|
||||
worth a read before a large change.
|
||||
|
||||
## Submitting changes
|
||||
|
||||
|
|
|
|||
163
README.md
163
README.md
|
|
@ -1,29 +1,156 @@
|
|||
# mnswpr
|
||||
# Play Minesweeper Online for Free
|
||||
[](https://app.netlify.com/sites/mnswpr/deploys)
|
||||
|
||||
The [mnswpr.com](https://mnswpr.com) web app — classic Minesweeper in the browser.
|
||||
Play it here: [mnswpr.com](https://mnswpr.com). This is the classic game **Minesweeper** built with vanilla web technologies (i.e., no framework dependency).
|
||||
|
||||

|
||||

|
||||
|
||||
This repo is the game app. The shared, reusable modules it builds on
|
||||
(`@cozy-games/mnswpr`, `@cozy-games/leaderboard`, `@cozy-games/utils`, and the
|
||||
rest of the `@cozy-games/*` family) live in their own repo:
|
||||
[ayo-run/cozy-games](https://github.com/ayo-run/cozy-games), and are consumed
|
||||
here from npm.
|
||||
## How to Play
|
||||
|
||||
The goal is to reveal every safe cell without detonating a mine. Your **first click is always safe**.
|
||||
|
||||
- **Left click** — reveal a cell
|
||||
- **Right click** — flag / unflag a suspected mine
|
||||
- **Left + right click together** (chording) — reveal the neighbors of a satisfied number
|
||||
- **Touch** — tap to reveal, long-press to flag
|
||||
|
||||
|
||||
## Ways to Use
|
||||
|
||||
The web is a wonderful, free, and open platform to create and distribute value. You can use **mnswpr** in different ways:
|
||||
|
||||
- as a deployed [web app](https://mnswpr.com)
|
||||
- as a [library](https://npmx.dev/package/@cozy-games/mnswpr) with `npm i @cozy-games/mnswpr`
|
||||
- as a `web component` (coming soon).
|
||||
|
||||
Using it as a library takes only a few lines — mount it onto any element by `id`:
|
||||
|
||||
```js
|
||||
import '@cozy-games/mnswpr/mnswpr.css'
|
||||
import mnswpr from '@cozy-games/mnswpr'
|
||||
|
||||
const game = new mnswpr('app')
|
||||
game.initialize()
|
||||
```
|
||||
|
||||
## Tooling
|
||||
The project has gone through years of existence. It started from 2019 when tooling was massively different. I have [modernized it](https://elk.zone/social.ayco.io/@ayo/116333804543330938) since and have witnessed how much easier and faster it is to build now - even without web frameworks or LLMs!
|
||||
|
||||
As of now the tooling I use are:
|
||||
- [Vite](https://vite.dev/) for bundling and development server
|
||||
- [Eslint](https://eslint.org) for JS linting & [CSS linting](https://eslint.org/blog/2025/02/eslint-css-support/)
|
||||
- [ESLint Stylistic](https://eslint.style) for JS formatting
|
||||
- [Husky](https://typicode.github.io/husky/) for git hooks
|
||||
- [PNPM](https://pnpm.io/installation) for dependency management
|
||||
- and a bunch of automation using scripts and Continuous Integration actions
|
||||
|
||||
Because a big part of this project's purpose is to track how the software development industry evolves — and because it has come a long way in modernizing along the way — I now also use it as a **playground for coding agents**. It's a small, framework-free, well-scoped codebase, which makes it a great sandbox to see how AI agents read, reason about, and change real code. To help them get their bearings quickly, the repo ships an [`AGENTS.md`](./AGENTS.md) describing the architecture and conventions.
|
||||
|
||||
## Development
|
||||
|
||||
Technology Stack: HTML, JS, and CSS; [Google Firebase](https://firebase.google.com) for leader board store; [Netlify](https://netlify.com) for hosting
|
||||
|
||||
To start development, you need [`node`](https://nodejs.org/en/download). I highly recommend [`pnpm`](https://pnpm.io/installation) to be used as well. Once you know you have this, you can do the following:
|
||||
1. Install dependencies: `pnpm i`
|
||||
2. Start the dev server: `pnpm run dev`
|
||||
|
||||
The rest of the everyday commands:
|
||||
|
||||
```bash
|
||||
pnpm test # run the Vitest suite
|
||||
pnpm lint # ESLint (JS + CSS)
|
||||
pnpm lint:fix # ESLint with autofix
|
||||
pnpm run build # build the website
|
||||
pnpm run preview # serve the production build
|
||||
```
|
||||
|
||||
The game engine and leaderboard are consumed from npm — they live in
|
||||
[ayo-run/cozy-games](https://github.com/ayo-run/cozy-games), not here.
|
||||
|
||||
### Leaderboard (local Firestore emulator)
|
||||
|
||||
The leader board is backed by [Google Firestore](https://firebase.google.com). For local development the app talks to the **Firestore emulator** by default — fully local, no cloud, no deploy. The flag `VITE_FIRESTORE_EMULATOR=1` is already set in `.env.development`.
|
||||
|
||||
`dev` is the whole loop in one command — it wraps Vite in `firebase emulators:exec`, so the Firestore emulator (on :8080, + UI) comes up, gets **seeded with sample scores automatically**, and the app dev server starts against it; everything shuts down when you stop it. (Each `dev` starts a fresh in-memory emulator, so the auto-seed writes exactly one clean set every time — no accumulation.) `firebase-tools` is a pinned **devDependency** of this app (installed by `pnpm install`, invoked as the `firebase` binary), so the only extra prerequisite is **Java** — the Firestore emulator is a Java program (`java -jar cloud-firestore-emulator-*.jar`), and firebase-tools does not bundle a JRE.
|
||||
|
||||
**Usually automatic.** `pnpm install` runs a root `postinstall` ([`scripts/ensure-java.mjs`](../../scripts/ensure-java.mjs)) that installs a user-local Temurin JRE 21 into `~/.local` (no `sudo`) when `java` isn't already on your PATH. It's idempotent and never fails the install, and it skips when `CI` or `SKIP_JRE_SETUP=1` is set, or on unsupported platforms.
|
||||
|
||||
If that skipped and you need Java (or prefer a system-wide install), do it manually — **install a JRE (Java 11+; 21 recommended):**
|
||||
|
||||
```bash
|
||||
# Debian / Ubuntu / Pop!_OS
|
||||
sudo apt update && sudo apt install -y openjdk-21-jre-headless
|
||||
|
||||
# Fedora
|
||||
sudo dnf install -y java-21-openjdk-headless
|
||||
|
||||
# macOS (Homebrew)
|
||||
brew install openjdk@21
|
||||
|
||||
java -version # verify: should print "openjdk 21.x" (or 11+)
|
||||
```
|
||||
|
||||
No `sudo`? Install a JRE into your home directory instead (no root needed):
|
||||
|
||||
```bash
|
||||
curl -fsSL -o /tmp/jre21.tgz "https://api.adoptium.net/v3/binary/latest/21/ga/linux/x64/jre/hotspot/normal/eclipse"
|
||||
mkdir -p ~/.local/lib && tar xzf /tmp/jre21.tgz -C ~/.local/lib
|
||||
ln -sf ~/.local/lib/jdk-21*-jre/bin/java ~/.local/bin/java # ~/.local/bin is already on PATH
|
||||
java -version
|
||||
```
|
||||
|
||||
Without Java, `dev` and `db:start` fail with `Could not spawn 'java -version'`. Install it to a permanent location — a JRE unpacked under `/tmp` disappears when the OS cleans temp files. Then just:
|
||||
|
||||
```bash
|
||||
pnpm run dev # emulator (:8080 + UI) + auto-seed + app dev server — one command
|
||||
```
|
||||
|
||||
That's the everyday loop. The other DB scripts are for when you want to run pieces separately:
|
||||
|
||||
```bash
|
||||
pnpm run db:start # emulator only (stays up across app restarts); pair with dev:no-db
|
||||
pnpm run db:seed # seed a separately-running emulator (what dev does for you)
|
||||
pnpm run db:stop # kill a stray/orphaned emulator holding :8080
|
||||
```
|
||||
|
||||
To skip the emulator entirely — for quick UI-only work, or if you don't have a JDK — run `pnpm run dev:no-db` (plain Vite) and set `VITE_FIRESTORE_EMULATOR=` (empty) in a local, gitignored `.env.local`; the app then uses the cloud `mw-test` namespace instead.
|
||||
|
||||
See [`docs/firebase-leaderboards.md`](./docs/firebase-leaderboards.md) for the full data model, security rules, environments, and deployment.
|
||||
|
||||
## Contributing
|
||||
|
||||
Setup, running the game locally, testing, code style, and local infra all live
|
||||
in **[CONTRIBUTING.md](CONTRIBUTING.md)**. In short — this is a
|
||||
[pnpm](https://pnpm.io) workspace:
|
||||
Contributions are welcome! See [`AGENTS.md`](./AGENTS.md) for the architecture, conventions, and release workflow before opening a pull request.
|
||||
|
||||
## You just want to play?
|
||||
|
||||
*👉 The live site is here: [mnswpr.com](https://mnswpr.com)*
|
||||
|
||||
## Background
|
||||
One day, while working in my home office, I heard loud and fast mouse clicks coming from our bedroom. It's my wife, playing her favorite game (Minesweeper) on a crappy website full of advertisements.
|
||||
|
||||
I can't allow this, it's a security issue. 🤣
|
||||
|
||||
But it is also an opportunity.
|
||||
|
||||
I wanted to give her the same game, with a similar leader board she can dominate. And this is also a chance for me to dig deeper into vanilla JS.
|
||||
|
||||
Can I make a page with complex interactions (more on this later) without any library dependency?
|
||||
|
||||
## What I have learned:
|
||||
1. JS is awesome ✨
|
||||
1. We don't always *need* JS frameworks (or TS) ✨
|
||||
1. Even subtle UI changes *can improve* user gameplay experience ✨
|
||||
1. There's more ways to break your app than you are initially aware of ✨
|
||||
1. Competition motivates users to use your app more ✨
|
||||
1. Hash in bundled filenames helps avoid issues with browser caching (when shipping versions fast) ✨
|
||||
|
||||
```bash
|
||||
pnpm i # install
|
||||
pnpm test # run the test suite
|
||||
pnpm -F mnswpr run dev # run the Minesweeper app locally
|
||||
```
|
||||
|
||||
See [apps/mnswpr/README.md](apps/mnswpr/README.md) for the game itself.
|
||||
|
||||
## License
|
||||
|
||||
MIT © Ayo Ayco
|
||||
[MIT](../../LICENSE)
|
||||
|
||||
---
|
||||
|
||||
_Just keep building._<br>
|
||||
_A project by [Ayo](https://ayo.ayco.io)_
|
||||
|
|
|
|||
|
|
@ -1,153 +0,0 @@
|
|||
# Play Minesweeper Online for Free
|
||||
[](https://app.netlify.com/sites/mnswpr/deploys)
|
||||
|
||||
Play it here: [mnswpr.com](https://mnswpr.com). This is the classic game **Minesweeper** built with vanilla web technologies (i.e., no framework dependency).
|
||||
|
||||

|
||||
|
||||
## How to Play
|
||||
|
||||
The goal is to reveal every safe cell without detonating a mine. Your **first click is always safe**.
|
||||
|
||||
- **Left click** — reveal a cell
|
||||
- **Right click** — flag / unflag a suspected mine
|
||||
- **Left + right click together** (chording) — reveal the neighbors of a satisfied number
|
||||
- **Touch** — tap to reveal, long-press to flag
|
||||
|
||||
|
||||
## Ways to Use
|
||||
|
||||
The web is a wonderful, free, and open platform to create and distribute value. You can use **mnswpr** in different ways:
|
||||
|
||||
- as a deployed [web app](https://mnswpr.com)
|
||||
- as a [library](https://npmx.dev/package/@cozy-games/mnswpr) with `npm i @cozy-games/mnswpr`
|
||||
- as a `web component` (coming soon).
|
||||
|
||||
Using it as a library takes only a few lines — mount it onto any element by `id`:
|
||||
|
||||
```js
|
||||
import '@cozy-games/mnswpr/mnswpr.css'
|
||||
import mnswpr from '@cozy-games/mnswpr'
|
||||
|
||||
const game = new mnswpr('app')
|
||||
game.initialize()
|
||||
```
|
||||
|
||||
## Tooling
|
||||
The project has gone through years of existence. It started from 2019 when tooling was massively different. I have [modernized it](https://elk.zone/social.ayco.io/@ayo/116333804543330938) since and have witnessed how much easier and faster it is to build now - even without web frameworks or LLMs!
|
||||
|
||||
As of now the tooling I use are:
|
||||
- [Vite](https://vite.dev/) for bundling and development server
|
||||
- [Eslint](https://eslint.org) for JS linting & [CSS linting](https://eslint.org/blog/2025/02/eslint-css-support/)
|
||||
- [ESLint Stylistic](https://eslint.style) for JS formatting
|
||||
- [Husky](https://typicode.github.io/husky/) for git hooks
|
||||
- [PNPM](https://pnpm.io/installation) for dependency & workspace management
|
||||
- and a bunch of automation using scripts and Continuous Integration actions
|
||||
|
||||
Because a big part of this project's purpose is to track how the software development industry evolves — and because it has come a long way in modernizing along the way — I now also use it as a **playground for coding agents**. It's a small, framework-free, well-scoped codebase, which makes it a great sandbox to see how AI agents read, reason about, and change real code. To help them get their bearings quickly, the repo ships an [`AGENTS.md`](./AGENTS.md) describing the architecture and conventions.
|
||||
|
||||
## Development
|
||||
|
||||
Technology Stack: HTML, JS, and CSS; [Google Firebase](https://firebase.google.com) for leader board store; [Netlify](https://netlify.com) for hosting
|
||||
|
||||
To start development, you need [`node`](https://nodejs.org/en/download). I highly recommend [`pnpm`](https://pnpm.io/installation) to be used as well. Once you know you have this, you can do the following:
|
||||
1. Install dependencies: `pnpm i`
|
||||
2. Start the dev server: `pnpm -F mnswpr run dev`
|
||||
|
||||
The rest of the everyday commands:
|
||||
|
||||
```bash
|
||||
pnpm test # run the Vitest suite (workspace-wide)
|
||||
pnpm lint # ESLint (JS + CSS)
|
||||
pnpm lint:fix # ESLint with autofix
|
||||
pnpm -F mnswpr run build # build the website
|
||||
pnpm build:lib # build the publishable library
|
||||
```
|
||||
|
||||
### Leaderboard (local Firestore emulator)
|
||||
|
||||
The leader board is backed by [Google Firestore](https://firebase.google.com). For local development the app talks to the **Firestore emulator** by default — fully local, no cloud, no deploy. The flag `VITE_FIRESTORE_EMULATOR=1` is already set in `app/.env.development`.
|
||||
|
||||
`dev` is the whole loop in one command — it wraps Vite in `firebase emulators:exec`, so the Firestore emulator (on :8080, + UI) comes up, gets **seeded with sample scores automatically**, and the app dev server starts against it; everything shuts down when you stop it. (Each `dev` starts a fresh in-memory emulator, so the auto-seed writes exactly one clean set every time — no accumulation.) `firebase-tools` is a pinned **devDependency** of this app (installed by `pnpm install`, invoked as the `firebase` binary), so the only extra prerequisite is **Java** — the Firestore emulator is a Java program (`java -jar cloud-firestore-emulator-*.jar`), and firebase-tools does not bundle a JRE.
|
||||
|
||||
**Usually automatic.** `pnpm install` runs a root `postinstall` ([`scripts/ensure-java.mjs`](../../scripts/ensure-java.mjs)) that installs a user-local Temurin JRE 21 into `~/.local` (no `sudo`) when `java` isn't already on your PATH. It's idempotent and never fails the install, and it skips when `CI` or `SKIP_JRE_SETUP=1` is set, or on unsupported platforms.
|
||||
|
||||
If that skipped and you need Java (or prefer a system-wide install), do it manually — **install a JRE (Java 11+; 21 recommended):**
|
||||
|
||||
```bash
|
||||
# Debian / Ubuntu / Pop!_OS
|
||||
sudo apt update && sudo apt install -y openjdk-21-jre-headless
|
||||
|
||||
# Fedora
|
||||
sudo dnf install -y java-21-openjdk-headless
|
||||
|
||||
# macOS (Homebrew)
|
||||
brew install openjdk@21
|
||||
|
||||
java -version # verify: should print "openjdk 21.x" (or 11+)
|
||||
```
|
||||
|
||||
No `sudo`? Install a JRE into your home directory instead (no root needed):
|
||||
|
||||
```bash
|
||||
curl -fsSL -o /tmp/jre21.tgz "https://api.adoptium.net/v3/binary/latest/21/ga/linux/x64/jre/hotspot/normal/eclipse"
|
||||
mkdir -p ~/.local/lib && tar xzf /tmp/jre21.tgz -C ~/.local/lib
|
||||
ln -sf ~/.local/lib/jdk-21*-jre/bin/java ~/.local/bin/java # ~/.local/bin is already on PATH
|
||||
java -version
|
||||
```
|
||||
|
||||
Without Java, `dev` and `db:start` fail with `Could not spawn 'java -version'`. Install it to a permanent location — a JRE unpacked under `/tmp` disappears when the OS cleans temp files. Then just:
|
||||
|
||||
```bash
|
||||
pnpm -F mnswpr run dev # emulator (:8080 + UI) + auto-seed + app dev server — one command
|
||||
```
|
||||
|
||||
That's the everyday loop. The other DB scripts are for when you want to run pieces separately:
|
||||
|
||||
```bash
|
||||
pnpm -F mnswpr run db:start # emulator only (stays up across app restarts); pair with dev:no-db
|
||||
pnpm -F mnswpr run db:seed # seed a separately-running emulator (what dev does for you)
|
||||
pnpm -F mnswpr run db:stop # kill a stray/orphaned emulator holding :8080
|
||||
```
|
||||
|
||||
To skip the emulator entirely — for quick UI-only work, or if you don't have a JDK — run `pnpm -F mnswpr run dev:no-db` (plain Vite) and set `VITE_FIRESTORE_EMULATOR=` (empty) in a local, gitignored `app/.env.local`; the app then uses the cloud `mw-test` namespace instead.
|
||||
|
||||
See [`docs/firebase-leaderboards.md`](./docs/firebase-leaderboards.md) for the full data model, security rules, environments, and deployment.
|
||||
|
||||
## Contributing
|
||||
|
||||
Contributions are welcome! See [`AGENTS.md`](./AGENTS.md) for the architecture, conventions, and release workflow before opening a pull request.
|
||||
|
||||
## You just want to play?
|
||||
|
||||
*👉 The live site is here: [mnswpr.com](https://mnswpr.com)*
|
||||
|
||||
## Background
|
||||
One day, while working in my home office, I heard loud and fast mouse clicks coming from our bedroom. It's my wife, playing her favorite game (Minesweeper) on a crappy website full of advertisements.
|
||||
|
||||
I can't allow this, it's a security issue. 🤣
|
||||
|
||||
But it is also an opportunity.
|
||||
|
||||
I wanted to give her the same game, with a similar leader board she can dominate. And this is also a chance for me to dig deeper into vanilla JS.
|
||||
|
||||
Can I make a page with complex interactions (more on this later) without any library dependency?
|
||||
|
||||
## What I have learned:
|
||||
1. JS is awesome ✨
|
||||
1. We don't always *need* JS frameworks (or TS) ✨
|
||||
1. Even subtle UI changes *can improve* user gameplay experience ✨
|
||||
1. There's more ways to break your app than you are initially aware of ✨
|
||||
1. Competition motivates users to use your app more ✨
|
||||
1. Hash in bundled filenames helps avoid issues with browser caching (when shipping versions fast) ✨
|
||||
|
||||
|
||||
|
||||
## License
|
||||
|
||||
[MIT](../../LICENSE)
|
||||
|
||||
---
|
||||
|
||||
_Just keep building._<br>
|
||||
_A project by [Ayo](https://ayo.ayco.io)_
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
{
|
||||
"name": "mnswpr",
|
||||
"version": "0.0.1",
|
||||
"description": "the mnswpr.com web app",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"main": "main.js",
|
||||
"scripts": {
|
||||
"dev": "firebase emulators:exec --only firestore --ui \"node scripts/seed-dev-scores.js; vite\"",
|
||||
"dev:no-db": "vite",
|
||||
"build": "vite build",
|
||||
"preview": "vite preview",
|
||||
"build:preview": "npm run build && npm run preview",
|
||||
"deploy:db": "firebase deploy --only firestore",
|
||||
"deploy:site": "npm run build && netlify deploy --prod --dir=dist",
|
||||
"db:start": "firebase emulators:start --only firestore",
|
||||
"db:seed": "FIRESTORE_EMULATOR_HOST=127.0.0.1:8080 node scripts/seed-dev-scores.js",
|
||||
"db:stop": "pkill -f '[c]loud-firestore-emulator'; pkill -f '[f]irebase.* emulators:'; true"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@cozy-games/mnswpr": "^0.5.4",
|
||||
"@cozy-games/leaderboard": "^0.1.1",
|
||||
"@cozy-games/utils": "^0.0.3",
|
||||
"firebase": "^12.11.0",
|
||||
"firebase-tools": "^15.22.4",
|
||||
"netlify-cli": "^26.1.0",
|
||||
"web-component-base": "^5.0.0"
|
||||
},
|
||||
"author": "Ayo Ayco"
|
||||
}
|
||||
|
|
@ -103,21 +103,21 @@ so run it as the `firebase` binary via pnpm — no global install, no `npx`. The
|
|||
Firebase project already exists — no need to create it.
|
||||
|
||||
```bash
|
||||
pnpm -F mnswpr exec firebase login
|
||||
pnpm exec firebase login
|
||||
```
|
||||
|
||||
### Deploy rules + indexes
|
||||
|
||||
The `deploy:db` script (`pnpm -F mnswpr run deploy:db`) deploys everything under
|
||||
The `deploy:db` script (`pnpm run deploy:db`) deploys everything under
|
||||
`firestore` to the **default** project. To target a specific project or a subset,
|
||||
call the CLI directly:
|
||||
|
||||
```bash
|
||||
# production (default alias 'prod')
|
||||
pnpm -F mnswpr exec firebase deploy --only firestore:rules,firestore:indexes --project prod
|
||||
pnpm exec firebase deploy --only firestore:rules,firestore:indexes --project prod
|
||||
|
||||
# development database
|
||||
pnpm -F mnswpr exec firebase deploy --only firestore:rules,firestore:indexes --project dev
|
||||
pnpm exec firebase deploy --only firestore:rules,firestore:indexes --project dev
|
||||
```
|
||||
|
||||
> ⚠️ Deploying **replaces** whatever rules currently live in the Console. The
|
||||
|
|
@ -142,7 +142,7 @@ locally (so you validate them before deploying). The flag
|
|||
Everyday dev loop:
|
||||
|
||||
```bash
|
||||
pnpm -F mnswpr run dev # emulator (+ UI) on :8080, auto-seeded with sample scores, + app dev server
|
||||
pnpm run dev # emulator (+ UI) on :8080, auto-seeded with sample scores, + app dev server
|
||||
```
|
||||
|
||||
`dev` seeds the fresh emulator for you (via `emulators:exec "node scripts/seed-dev-scores.js; vite"`). Use the standalone `db:start` / `db:seed` scripts only when running the emulator separately from the app.
|
||||
|
|
@ -175,17 +175,16 @@ Everything above is doable via the CLI. If you can't use it:
|
|||
## Legends (frozen hall of fame)
|
||||
|
||||
The old all-time leaders are preserved as a **fully-rendered static page** —
|
||||
[`app/legends.html`](../app/legends.html). The records are baked straight into the
|
||||
[`legends.html`](../legends.html). The records are baked straight into the
|
||||
HTML with times pre-formatted; there is **no JavaScript and no Firebase** at page
|
||||
load. The data never changes.
|
||||
|
||||
The page is generated by [`scripts/export-legends.js`](../scripts/export-legends.js),
|
||||
which snapshots `mw-leaders/{level}/games` and writes the whole `legends.html`.
|
||||
It only needs re-running if you ever want to regenerate. Because `firebase` is an
|
||||
app-workspace dependency, run it so Node can resolve it:
|
||||
It only needs re-running if you ever want to regenerate. Run it from the repo root:
|
||||
|
||||
```bash
|
||||
(cd app && node ../scripts/export-legends.js)
|
||||
node scripts/export-legends.js
|
||||
```
|
||||
|
||||
The Firebase config for this one-off is hardcoded in the script (public keys).
|
||||
|
|
@ -139,8 +139,8 @@ Both aliases target the one project we actually have:
|
|||
|
||||
### 7. Deploy & verify
|
||||
|
||||
1. `pnpm -F mnswpr exec firebase deploy --only firestore:rules,firestore:indexes --project prod`
|
||||
2. Set the Netlify env vars via CLI: `pnpm -F mnswpr exec netlify env:import .env.production` (or `netlify env:set VITE_LB_NAMESPACE mw` + each `VITE_FIREBASE_*`).
|
||||
1. `pnpm exec firebase deploy --only firestore:rules,firestore:indexes --project prod`
|
||||
2. Set the Netlify env vars via CLI: `pnpm exec netlify env:import .env.production` (or `netlify env:set VITE_LB_NAMESPACE mw` + each `VITE_FIREBASE_*`).
|
||||
3. `pnpm dev`, win a game → confirm the write lands in **`mw-test-scores`**, and
|
||||
the prod `mw-scores` is untouched (Firestore console).
|
||||
4. Confirm reads on both `mw-scores` and `mw-test-scores` succeed under the new
|
||||
|
|
@ -16,7 +16,7 @@ rules_version = '2'
|
|||
// block is guarded by a regex on the captured collection name.
|
||||
//
|
||||
// Deploy with (see docs/firebase-leaderboards.md):
|
||||
// pnpm -F mnswpr exec firebase deploy --only firestore:rules --project prod
|
||||
// pnpm exec firebase deploy --only firestore:rules --project prod
|
||||
service cloud.firestore {
|
||||
match /databases/{database}/documents {
|
||||
|
||||
|
|
@ -1,13 +1,12 @@
|
|||
# Netlify hosting config for mnswpr.com — the app-level, declarative hosting
|
||||
# state, codified here so hosting is reproducible from the repo and deployed via
|
||||
# CLI (`pnpm -F mnswpr run deploy:site`), never the web dashboard. This file is
|
||||
# CLI (`pnpm run deploy:site`), never the web dashboard. This file is
|
||||
# app infra *config*; the CLI that reads it (`netlify-cli`) is app infra *tooling*
|
||||
# and lives in this app's devDependencies. See AGENTS.md "Infra".
|
||||
|
||||
# The `deploy:site` script pre-builds locally and uploads `dist` via the CLI, so
|
||||
# this [build] block is only exercised when Netlify builds the site from git
|
||||
# (dashboard "base directory" = apps/mnswpr). It is a pnpm workspace, so
|
||||
# `pnpm install` from here installs the whole monorepo before building.
|
||||
# (dashboard "base directory" = the repo root — no longer `apps/mnswpr`).
|
||||
[build]
|
||||
command = "pnpm install --frozen-lockfile && pnpm run build"
|
||||
publish = "dist"
|
||||
|
|
@ -18,7 +17,7 @@
|
|||
# git-triggered builds; local CLI builds read app/.env.production instead.
|
||||
# Firebase VITE_* keys are public but are set as Netlify env vars (via
|
||||
# `netlify env:set` / `netlify env:import`, not the dashboard) to keep prod
|
||||
# values out of git — see apps/mnswpr/.env.example.
|
||||
# values out of git — see .env.example.
|
||||
VITE_LB_NAMESPACE = "mw"
|
||||
|
||||
# Pretty URL for the frozen Legends page (built as /legends.html).
|
||||
26
package.json
26
package.json
|
|
@ -1,20 +1,29 @@
|
|||
{
|
||||
"name": "cozy-games",
|
||||
"name": "mnswpr",
|
||||
"version": "0.0.1",
|
||||
"private": true,
|
||||
"description": "mnswpr — the mnswpr.com web app",
|
||||
"description": "mnswpr \u2014 the mnswpr.com web app",
|
||||
"author": "Ayo Ayco",
|
||||
"type": "module",
|
||||
"main": "main.js",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/ayo-run/mnswpr"
|
||||
},
|
||||
"homepage": "https://mnswpr.com",
|
||||
"scripts": {
|
||||
"dev": "firebase emulators:exec --only firestore --ui \"node scripts/seed-dev-scores.js; vite\"",
|
||||
"dev:no-db": "vite",
|
||||
"build": "vite build",
|
||||
"preview": "vite preview",
|
||||
"build:preview": "pnpm run build && pnpm run preview",
|
||||
"test": "vitest run",
|
||||
"dev": "pnpm -F mnswpr dev",
|
||||
"test:watch": "vitest",
|
||||
"build": "pnpm -F mnswpr build",
|
||||
"deploy:db": "firebase deploy --only firestore",
|
||||
"deploy:site": "pnpm run build && netlify deploy --prod --dir=dist",
|
||||
"db:start": "firebase emulators:start --only firestore",
|
||||
"db:seed": "FIRESTORE_EMULATOR_HOST=127.0.0.1:8080 node scripts/seed-dev-scores.js",
|
||||
"db:stop": "pkill -f '[c]loud-firestore-emulator'; pkill -f '[f]irebase.* emulators:'; true",
|
||||
"postinstall": "node scripts/ensure-java.mjs",
|
||||
"prepare": "husky",
|
||||
"lint": "eslint .",
|
||||
|
|
@ -22,20 +31,27 @@
|
|||
"scan:secrets": "secretlint --secretlintignore .secretlintignore \"**/*\""
|
||||
},
|
||||
"devDependencies": {
|
||||
"@cozy-games/leaderboard": "^0.1.1",
|
||||
"@cozy-games/mnswpr": "^0.5.4",
|
||||
"@cozy-games/utils": "^0.0.3",
|
||||
"@eslint/css": "^1.1.0",
|
||||
"@eslint/js": "^10.0.1",
|
||||
"@secretlint/secretlint-rule-preset-recommend": "^13.0.2",
|
||||
"@stylistic/eslint-plugin": "^5.10.0",
|
||||
"bumpp": "^11.0.1",
|
||||
"eslint": "^10.1.0",
|
||||
"firebase": "^12.11.0",
|
||||
"firebase-tools": "^15.22.4",
|
||||
"globals": "^17.4.0",
|
||||
"husky": "^9.1.7",
|
||||
"jsdom": "^29.1.1",
|
||||
"netlify-cli": "^26.1.0",
|
||||
"secretlint": "^13.0.2",
|
||||
"simple-git": "^3.33.0",
|
||||
"typescript": "^5.9.3",
|
||||
"vite": "^8.0.16",
|
||||
"vitest": "^4.1.9"
|
||||
"vitest": "^4.1.9",
|
||||
"web-component-base": "^5.0.0"
|
||||
},
|
||||
"packageManager": "pnpm@11.9.0+sha512.bd682d5d03fe525ef7c9fd6780c6884d1e756ac4c9c9fe00c538782824310dcf90e3ddc4f53835f06dfaebd5085e41855e0bcbb3b60de2ac5bbab89e5036f03b"
|
||||
}
|
||||
|
|
|
|||
284
pnpm-lock.yaml
284
pnpm-lock.yaml
|
|
@ -7,51 +7,6 @@ settings:
|
|||
importers:
|
||||
|
||||
.:
|
||||
devDependencies:
|
||||
'@eslint/css':
|
||||
specifier: ^1.1.0
|
||||
version: 1.1.0
|
||||
'@eslint/js':
|
||||
specifier: ^10.0.1
|
||||
version: 10.0.1(eslint@10.1.0(jiti@2.6.1)(supports-color@10.2.2))
|
||||
'@secretlint/secretlint-rule-preset-recommend':
|
||||
specifier: ^13.0.2
|
||||
version: 13.0.2
|
||||
'@stylistic/eslint-plugin':
|
||||
specifier: ^5.10.0
|
||||
version: 5.10.0(eslint@10.1.0(jiti@2.6.1)(supports-color@10.2.2))
|
||||
bumpp:
|
||||
specifier: ^11.0.1
|
||||
version: 11.0.1
|
||||
eslint:
|
||||
specifier: ^10.1.0
|
||||
version: 10.1.0(jiti@2.6.1)(supports-color@10.2.2)
|
||||
globals:
|
||||
specifier: ^17.4.0
|
||||
version: 17.4.0
|
||||
husky:
|
||||
specifier: ^9.1.7
|
||||
version: 9.1.7
|
||||
jsdom:
|
||||
specifier: ^29.1.1
|
||||
version: 29.1.1
|
||||
secretlint:
|
||||
specifier: ^13.0.2
|
||||
version: 13.0.2(supports-color@10.2.2)
|
||||
simple-git:
|
||||
specifier: ^3.33.0
|
||||
version: 3.33.0(supports-color@10.2.2)
|
||||
typescript:
|
||||
specifier: ^5.9.3
|
||||
version: 5.9.3
|
||||
vite:
|
||||
specifier: ^8.0.16
|
||||
version: 8.0.16(@types/node@25.5.2)(esbuild@0.28.0)(jiti@2.6.1)(yaml@2.8.3)
|
||||
vitest:
|
||||
specifier: ^4.1.9
|
||||
version: 4.1.9(@opentelemetry/api@1.9.1)(@types/node@25.5.2)(jsdom@29.1.1)(vite@8.0.16(@types/node@25.5.2)(esbuild@0.28.0)(jiti@2.6.1)(yaml@2.8.3))
|
||||
|
||||
apps/mnswpr:
|
||||
devDependencies:
|
||||
'@cozy-games/leaderboard':
|
||||
specifier: ^0.1.1
|
||||
|
|
@ -62,15 +17,57 @@ importers:
|
|||
'@cozy-games/utils':
|
||||
specifier: ^0.0.3
|
||||
version: 0.0.3
|
||||
'@eslint/css':
|
||||
specifier: ^1.1.0
|
||||
version: 1.1.0
|
||||
'@eslint/js':
|
||||
specifier: ^10.0.1
|
||||
version: 10.0.1(eslint@10.1.0(jiti@2.6.1))
|
||||
'@secretlint/secretlint-rule-preset-recommend':
|
||||
specifier: ^13.0.2
|
||||
version: 13.0.2
|
||||
'@stylistic/eslint-plugin':
|
||||
specifier: ^5.10.0
|
||||
version: 5.10.0(eslint@10.1.0(jiti@2.6.1))
|
||||
bumpp:
|
||||
specifier: ^11.0.1
|
||||
version: 11.0.1
|
||||
eslint:
|
||||
specifier: ^10.1.0
|
||||
version: 10.1.0(jiti@2.6.1)
|
||||
firebase:
|
||||
specifier: ^12.11.0
|
||||
version: 12.11.0
|
||||
firebase-tools:
|
||||
specifier: ^15.22.4
|
||||
version: 15.22.4(@types/node@25.5.2)(supports-color@10.2.2)
|
||||
version: 15.22.4(@types/node@25.5.2)
|
||||
globals:
|
||||
specifier: ^17.4.0
|
||||
version: 17.4.0
|
||||
husky:
|
||||
specifier: ^9.1.7
|
||||
version: 9.1.7
|
||||
jsdom:
|
||||
specifier: ^29.1.1
|
||||
version: 29.1.1
|
||||
netlify-cli:
|
||||
specifier: ^26.1.0
|
||||
version: 26.1.0(@types/node@25.5.2)(picomatch@4.0.4)(supports-color@10.2.2)
|
||||
version: 26.1.0(@types/node@25.5.2)(picomatch@4.0.5)
|
||||
secretlint:
|
||||
specifier: ^13.0.2
|
||||
version: 13.0.2
|
||||
simple-git:
|
||||
specifier: ^3.33.0
|
||||
version: 3.33.0
|
||||
typescript:
|
||||
specifier: ^5.9.3
|
||||
version: 5.9.3
|
||||
vite:
|
||||
specifier: ^8.0.16
|
||||
version: 8.0.16(@types/node@25.5.2)(esbuild@0.28.0)(jiti@2.6.1)(yaml@2.8.3)
|
||||
vitest:
|
||||
specifier: ^4.1.9
|
||||
version: 4.1.9(@opentelemetry/api@1.9.1)(@types/node@25.5.2)(jsdom@29.1.1)(vite@8.0.16(@types/node@25.5.2)(esbuild@0.28.0)(jiti@2.6.1)(yaml@2.8.3))
|
||||
web-component-base:
|
||||
specifier: ^5.0.0
|
||||
version: 5.0.0
|
||||
|
|
@ -1607,39 +1604,24 @@ packages:
|
|||
'@protobufjs/base64@1.1.2':
|
||||
resolution: {integrity: sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==}
|
||||
|
||||
'@protobufjs/codegen@2.0.4':
|
||||
resolution: {integrity: sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==}
|
||||
|
||||
'@protobufjs/codegen@2.0.5':
|
||||
resolution: {integrity: sha512-zgXFLzW3Ap33e6d0Wlj4MGIm6Ce8O89n/apUaGNB/jx+hw+ruWEp7EwGUshdLKVRCxZW12fp9r40E1mQrf/34g==}
|
||||
|
||||
'@protobufjs/eventemitter@1.1.0':
|
||||
resolution: {integrity: sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==}
|
||||
|
||||
'@protobufjs/eventemitter@1.1.1':
|
||||
resolution: {integrity: sha512-vW1GmwMZNnL+gMRaovlh9yZX74kc+TTU3FObkkurpMaRtBfLP3ldjS9KQWlwZgraRE0+dheEEoAxdzcJQ8eXZg==}
|
||||
|
||||
'@protobufjs/fetch@1.1.0':
|
||||
resolution: {integrity: sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==}
|
||||
|
||||
'@protobufjs/fetch@1.1.1':
|
||||
resolution: {integrity: sha512-GpptLrs57adMSuHi3VNj0mAF8dwh36LMaYF6XyJ6JMWlVsc+t42tm1HSEDmOs3A8fC9yyeisgLhsTVQokOZ0zw==}
|
||||
|
||||
'@protobufjs/float@1.0.2':
|
||||
resolution: {integrity: sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==}
|
||||
|
||||
'@protobufjs/inquire@1.1.0':
|
||||
resolution: {integrity: sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==}
|
||||
|
||||
'@protobufjs/path@1.1.2':
|
||||
resolution: {integrity: sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==}
|
||||
|
||||
'@protobufjs/pool@1.1.0':
|
||||
resolution: {integrity: sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==}
|
||||
|
||||
'@protobufjs/utf8@1.1.0':
|
||||
resolution: {integrity: sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==}
|
||||
|
||||
'@protobufjs/utf8@1.1.1':
|
||||
resolution: {integrity: sha512-oOAWABowe8EAbMyWKM0tYDKi8Yaox52D+HWZhAIJqQXbqe0xI/GV7FhLWqlEKreMkfDjshR5FKgi3mnle0h6Eg==}
|
||||
|
||||
|
|
@ -5273,10 +5255,6 @@ packages:
|
|||
resolution: {integrity: sha512-E1sbAYg3aEbXrq0n1ojJkRHQJGE1kaE/O6GLA94y8rnJBfgvOPTOd1b9hOceQK1FFZI9qMh1vBERCyO2ifubcw==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
protobufjs@7.5.4:
|
||||
resolution: {integrity: sha512-CvexbZtbov6jW2eXAvLukXjXUW1TzFaivC46BpWc/3BpcCysb5Vffu+B3XHMm8lVEuy2Mm4XGex8hBSg1yapPg==}
|
||||
engines: {node: '>=12.0.0'}
|
||||
|
||||
protobufjs@7.6.4:
|
||||
resolution: {integrity: sha512-RJJPTTpvFfHcWLkIa2JFWK4XvtSzS0yEWDmunqHXli1h3JlkbcQZXDZdcWxv+JK3Xsl5/UFDPZ0iGm7DAengYw==}
|
||||
engines: {node: '>=12.0.0'}
|
||||
|
|
@ -6910,14 +6888,14 @@ snapshots:
|
|||
'@esbuild/win32-x64@0.28.0':
|
||||
optional: true
|
||||
|
||||
'@eslint-community/eslint-utils@4.9.1(eslint@10.1.0(jiti@2.6.1)(supports-color@10.2.2))':
|
||||
'@eslint-community/eslint-utils@4.9.1(eslint@10.1.0(jiti@2.6.1))':
|
||||
dependencies:
|
||||
eslint: 10.1.0(jiti@2.6.1)(supports-color@10.2.2)
|
||||
eslint: 10.1.0(jiti@2.6.1)
|
||||
eslint-visitor-keys: 3.4.3
|
||||
|
||||
'@eslint-community/regexpp@4.12.2': {}
|
||||
|
||||
'@eslint/config-array@0.23.3(supports-color@10.2.2)':
|
||||
'@eslint/config-array@0.23.3':
|
||||
dependencies:
|
||||
'@eslint/object-schema': 3.0.3
|
||||
debug: 4.4.3(supports-color@10.2.2)
|
||||
|
|
@ -6944,9 +6922,9 @@ snapshots:
|
|||
'@eslint/css-tree': 3.6.9
|
||||
'@eslint/plugin-kit': 0.6.1
|
||||
|
||||
'@eslint/js@10.0.1(eslint@10.1.0(jiti@2.6.1)(supports-color@10.2.2))':
|
||||
'@eslint/js@10.0.1(eslint@10.1.0(jiti@2.6.1))':
|
||||
optionalDependencies:
|
||||
eslint: 10.1.0(jiti@2.6.1)(supports-color@10.2.2)
|
||||
eslint: 10.1.0(jiti@2.6.1)
|
||||
|
||||
'@eslint/object-schema@3.0.3': {}
|
||||
|
||||
|
|
@ -7380,7 +7358,7 @@ snapshots:
|
|||
dependencies:
|
||||
lodash.camelcase: 4.3.0
|
||||
long: 5.3.2
|
||||
protobufjs: 7.5.4
|
||||
protobufjs: 7.6.4
|
||||
yargs: 17.7.2
|
||||
|
||||
'@grpc/proto-loader@0.8.1':
|
||||
|
|
@ -7658,7 +7636,7 @@ snapshots:
|
|||
|
||||
'@jsdevtools/ono@7.1.3': {}
|
||||
|
||||
'@kwsites/file-exists@1.1.1(supports-color@10.2.2)':
|
||||
'@kwsites/file-exists@1.1.1':
|
||||
dependencies:
|
||||
debug: 4.4.3(supports-color@10.2.2)
|
||||
transitivePeerDependencies:
|
||||
|
|
@ -7743,7 +7721,7 @@ snapshots:
|
|||
yaml: 2.8.3
|
||||
yargs: 17.7.2
|
||||
|
||||
'@netlify/build@35.15.0(@opentelemetry/api@1.9.1)(@types/node@25.5.2)(picomatch@4.0.4)':
|
||||
'@netlify/build@35.15.0(@opentelemetry/api@1.9.1)(@types/node@25.5.2)(picomatch@4.0.5)':
|
||||
dependencies:
|
||||
'@bugsnag/js': 8.9.0
|
||||
'@netlify/blobs': 10.7.9(supports-color@10.2.2)
|
||||
|
|
@ -7762,7 +7740,7 @@ snapshots:
|
|||
ansis: 4.3.1
|
||||
clean-stack: 5.3.0
|
||||
execa: 8.0.1
|
||||
fdir: 6.5.0(picomatch@4.0.4)
|
||||
fdir: 6.5.0(picomatch@4.0.5)
|
||||
figures: 6.1.0
|
||||
filter-obj: 6.1.0
|
||||
hot-shots: 11.4.0
|
||||
|
|
@ -7872,7 +7850,7 @@ snapshots:
|
|||
semver: 7.7.4
|
||||
tmp-promise: 3.0.3
|
||||
|
||||
'@netlify/dev@4.18.9(supports-color@10.2.2)':
|
||||
'@netlify/dev@4.18.9':
|
||||
dependencies:
|
||||
'@netlify/ai': 0.4.2
|
||||
'@netlify/blobs': 10.7.9(supports-color@10.2.2)
|
||||
|
|
@ -7880,9 +7858,9 @@ snapshots:
|
|||
'@netlify/database-dev': 0.10.1
|
||||
'@netlify/dev-utils': 4.4.6
|
||||
'@netlify/edge-functions-dev': 1.0.22
|
||||
'@netlify/functions-dev': 1.3.1(supports-color@10.2.2)
|
||||
'@netlify/functions-dev': 1.3.1
|
||||
'@netlify/headers': 2.1.11
|
||||
'@netlify/images': 1.3.10(@netlify/blobs@10.7.9(supports-color@10.2.2))
|
||||
'@netlify/images': 1.3.10(@netlify/blobs@10.7.9)
|
||||
'@netlify/redirects': 3.1.13
|
||||
'@netlify/runtime': 4.1.25
|
||||
'@netlify/static': 3.1.10
|
||||
|
|
@ -7955,7 +7933,7 @@ snapshots:
|
|||
dependencies:
|
||||
'@netlify/types': 2.8.0
|
||||
|
||||
'@netlify/functions-dev@1.3.1(supports-color@10.2.2)':
|
||||
'@netlify/functions-dev@1.3.1':
|
||||
dependencies:
|
||||
'@netlify/blobs': 10.7.9(supports-color@10.2.2)
|
||||
'@netlify/dev-utils': 4.4.6
|
||||
|
|
@ -7963,7 +7941,7 @@ snapshots:
|
|||
'@netlify/zip-it-and-ship-it': 14.7.1(supports-color@10.2.2)
|
||||
cron-parser: 4.9.0
|
||||
decache: 4.6.2
|
||||
extract-zip: 2.0.1(supports-color@10.2.2)
|
||||
extract-zip: 2.0.1
|
||||
is-stream: 4.0.1
|
||||
jwt-decode: 4.0.0
|
||||
lambda-local: 2.2.0
|
||||
|
|
@ -8015,9 +7993,9 @@ snapshots:
|
|||
dependencies:
|
||||
'@netlify/headers-parser': 9.0.3
|
||||
|
||||
'@netlify/images@1.3.10(@netlify/blobs@10.7.9(supports-color@10.2.2))':
|
||||
'@netlify/images@1.3.10(@netlify/blobs@10.7.9)':
|
||||
dependencies:
|
||||
ipx: 3.1.1(@netlify/blobs@10.7.9(supports-color@10.2.2))
|
||||
ipx: 3.1.1(@netlify/blobs@10.7.9)
|
||||
transitivePeerDependencies:
|
||||
- '@azure/app-configuration'
|
||||
- '@azure/cosmos'
|
||||
|
|
@ -8407,7 +8385,7 @@ snapshots:
|
|||
'@pnpm/network.ca-file': 1.0.2
|
||||
config-chain: 1.1.13
|
||||
|
||||
'@pnpm/tabtab@0.5.4(supports-color@10.2.2)':
|
||||
'@pnpm/tabtab@0.5.4':
|
||||
dependencies:
|
||||
debug: 4.4.3(supports-color@10.2.2)
|
||||
enquirer: 2.4.1
|
||||
|
|
@ -8420,33 +8398,20 @@ snapshots:
|
|||
|
||||
'@protobufjs/base64@1.1.2': {}
|
||||
|
||||
'@protobufjs/codegen@2.0.4': {}
|
||||
|
||||
'@protobufjs/codegen@2.0.5': {}
|
||||
|
||||
'@protobufjs/eventemitter@1.1.0': {}
|
||||
|
||||
'@protobufjs/eventemitter@1.1.1': {}
|
||||
|
||||
'@protobufjs/fetch@1.1.0':
|
||||
dependencies:
|
||||
'@protobufjs/aspromise': 1.1.2
|
||||
'@protobufjs/inquire': 1.1.0
|
||||
|
||||
'@protobufjs/fetch@1.1.1':
|
||||
dependencies:
|
||||
'@protobufjs/aspromise': 1.1.2
|
||||
|
||||
'@protobufjs/float@1.0.2': {}
|
||||
|
||||
'@protobufjs/inquire@1.1.0': {}
|
||||
|
||||
'@protobufjs/path@1.1.2': {}
|
||||
|
||||
'@protobufjs/pool@1.1.0': {}
|
||||
|
||||
'@protobufjs/utf8@1.1.0': {}
|
||||
|
||||
'@protobufjs/utf8@1.1.1': {}
|
||||
|
||||
'@quansync/fs@1.0.0':
|
||||
|
|
@ -8516,18 +8481,18 @@ snapshots:
|
|||
dependencies:
|
||||
'@secretlint/types': 13.0.2
|
||||
|
||||
'@secretlint/config-loader@13.0.2(supports-color@10.2.2)':
|
||||
'@secretlint/config-loader@13.0.2':
|
||||
dependencies:
|
||||
'@secretlint/profiler': 13.0.2
|
||||
'@secretlint/resolver': 13.0.2
|
||||
'@secretlint/types': 13.0.2
|
||||
ajv: 8.20.0
|
||||
debug: 4.4.3(supports-color@10.2.2)
|
||||
rc-config-loader: 4.1.4(supports-color@10.2.2)
|
||||
rc-config-loader: 4.1.4
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@secretlint/core@13.0.2(supports-color@10.2.2)':
|
||||
'@secretlint/core@13.0.2':
|
||||
dependencies:
|
||||
'@secretlint/profiler': 13.0.2
|
||||
'@secretlint/types': 13.0.2
|
||||
|
|
@ -8552,10 +8517,10 @@ snapshots:
|
|||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@secretlint/node@13.0.2(supports-color@10.2.2)':
|
||||
'@secretlint/node@13.0.2':
|
||||
dependencies:
|
||||
'@secretlint/config-loader': 13.0.2(supports-color@10.2.2)
|
||||
'@secretlint/core': 13.0.2(supports-color@10.2.2)
|
||||
'@secretlint/config-loader': 13.0.2
|
||||
'@secretlint/core': 13.0.2
|
||||
'@secretlint/formatter': 13.0.2
|
||||
'@secretlint/profiler': 13.0.2
|
||||
'@secretlint/source-creator': 13.0.2
|
||||
|
|
@ -8603,11 +8568,11 @@ snapshots:
|
|||
|
||||
'@standard-schema/spec@1.1.0': {}
|
||||
|
||||
'@stylistic/eslint-plugin@5.10.0(eslint@10.1.0(jiti@2.6.1)(supports-color@10.2.2))':
|
||||
'@stylistic/eslint-plugin@5.10.0(eslint@10.1.0(jiti@2.6.1))':
|
||||
dependencies:
|
||||
'@eslint-community/eslint-utils': 4.9.1(eslint@10.1.0(jiti@2.6.1)(supports-color@10.2.2))
|
||||
'@eslint-community/eslint-utils': 4.9.1(eslint@10.1.0(jiti@2.6.1))
|
||||
'@typescript-eslint/types': 8.58.0
|
||||
eslint: 10.1.0(jiti@2.6.1)(supports-color@10.2.2)
|
||||
eslint: 10.1.0(jiti@2.6.1)
|
||||
eslint-visitor-keys: 4.2.1
|
||||
espree: 10.4.0
|
||||
estraverse: 5.3.0
|
||||
|
|
@ -10031,11 +9996,11 @@ snapshots:
|
|||
|
||||
eslint-visitor-keys@5.0.1: {}
|
||||
|
||||
eslint@10.1.0(jiti@2.6.1)(supports-color@10.2.2):
|
||||
eslint@10.1.0(jiti@2.6.1):
|
||||
dependencies:
|
||||
'@eslint-community/eslint-utils': 4.9.1(eslint@10.1.0(jiti@2.6.1)(supports-color@10.2.2))
|
||||
'@eslint-community/eslint-utils': 4.9.1(eslint@10.1.0(jiti@2.6.1))
|
||||
'@eslint-community/regexpp': 4.12.2
|
||||
'@eslint/config-array': 0.23.3(supports-color@10.2.2)
|
||||
'@eslint/config-array': 0.23.3
|
||||
'@eslint/config-helpers': 0.5.3
|
||||
'@eslint/core': 1.1.1
|
||||
'@eslint/plugin-kit': 0.6.1
|
||||
|
|
@ -10258,7 +10223,7 @@ snapshots:
|
|||
|
||||
extend@3.0.2: {}
|
||||
|
||||
extract-zip@2.0.1(supports-color@10.2.2):
|
||||
extract-zip@2.0.1:
|
||||
dependencies:
|
||||
debug: 4.4.3(supports-color@10.2.2)
|
||||
get-stream: 5.2.0
|
||||
|
|
@ -10435,7 +10400,7 @@ snapshots:
|
|||
locate-path: 8.0.0
|
||||
unicorn-magic: 0.3.0
|
||||
|
||||
firebase-tools@15.22.4(@types/node@25.5.2)(supports-color@10.2.2):
|
||||
firebase-tools@15.22.4(@types/node@25.5.2):
|
||||
dependencies:
|
||||
'@apphosting/common': 0.0.8
|
||||
'@electric-sql/pglite': 0.3.16
|
||||
|
|
@ -10466,7 +10431,7 @@ snapshots:
|
|||
form-data: 4.0.6
|
||||
fs-extra: 10.1.0
|
||||
fuzzy: 0.1.3
|
||||
gaxios: 6.7.1(supports-color@10.2.2)
|
||||
gaxios: 6.7.1
|
||||
glob: 10.5.0
|
||||
google-auth-library: 9.15.1
|
||||
ignore: 7.0.5
|
||||
|
|
@ -10486,9 +10451,9 @@ snapshots:
|
|||
pg: 8.22.0
|
||||
pg-gateway: 0.3.0-beta.4
|
||||
pglite-2: '@electric-sql/pglite@0.2.17'
|
||||
portfinder: 1.0.38(supports-color@10.2.2)
|
||||
portfinder: 1.0.38
|
||||
progress: 2.0.3
|
||||
proxy-agent: 6.5.0(supports-color@10.2.2)
|
||||
proxy-agent: 6.5.0
|
||||
retry: 0.13.1
|
||||
semver: 7.7.4
|
||||
sql-formatter: 15.8.2
|
||||
|
|
@ -10499,7 +10464,7 @@ snapshots:
|
|||
tcp-port-used: 1.0.3
|
||||
tmp: 0.2.7
|
||||
triple-beam: 1.4.1
|
||||
universal-analytics: 0.5.4(supports-color@10.2.2)
|
||||
universal-analytics: 0.5.4
|
||||
update-notifier-cjs: 5.1.7
|
||||
winston: 3.19.0
|
||||
winston-transport: 4.9.0
|
||||
|
|
@ -10564,7 +10529,7 @@ snapshots:
|
|||
dependencies:
|
||||
from2: 2.3.0
|
||||
|
||||
follow-redirects@1.16.0(debug@4.4.3(supports-color@10.2.2)):
|
||||
follow-redirects@1.16.0(debug@4.4.3):
|
||||
optionalDependencies:
|
||||
debug: 4.4.3(supports-color@10.2.2)
|
||||
|
||||
|
|
@ -10627,7 +10592,7 @@ snapshots:
|
|||
|
||||
fuzzy@0.1.3: {}
|
||||
|
||||
gaxios@6.7.1(supports-color@10.2.2):
|
||||
gaxios@6.7.1:
|
||||
dependencies:
|
||||
extend: 3.0.2
|
||||
https-proxy-agent: 7.0.6(supports-color@10.2.2)
|
||||
|
|
@ -10657,7 +10622,7 @@ snapshots:
|
|||
|
||||
gcp-metadata@6.1.1:
|
||||
dependencies:
|
||||
gaxios: 6.7.1(supports-color@10.2.2)
|
||||
gaxios: 6.7.1
|
||||
google-logging-utils: 0.0.2
|
||||
json-bigint: 1.0.0
|
||||
transitivePeerDependencies:
|
||||
|
|
@ -10667,7 +10632,7 @@ snapshots:
|
|||
gcp-metadata@8.1.2:
|
||||
dependencies:
|
||||
gaxios: 7.1.5
|
||||
google-logging-utils: 1.1.3
|
||||
google-logging-utils: 1.1.4
|
||||
json-bigint: 1.0.0
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
|
@ -10734,7 +10699,7 @@ snapshots:
|
|||
es-errors: 1.3.0
|
||||
get-intrinsic: 1.3.0
|
||||
|
||||
get-uri@6.0.5(supports-color@10.2.2):
|
||||
get-uri@6.0.5:
|
||||
dependencies:
|
||||
basic-ftp: 5.3.1
|
||||
data-uri-to-buffer: 6.0.2
|
||||
|
|
@ -10834,7 +10799,7 @@ snapshots:
|
|||
dependencies:
|
||||
base64-js: 1.5.1
|
||||
ecdsa-sig-formatter: 1.0.11
|
||||
gaxios: 6.7.1(supports-color@10.2.2)
|
||||
gaxios: 6.7.1
|
||||
gcp-metadata: 6.1.1
|
||||
gtoken: 7.1.0
|
||||
jws: 4.0.1
|
||||
|
|
@ -10852,7 +10817,7 @@ snapshots:
|
|||
node-fetch: 3.3.2
|
||||
object-hash: 3.0.0
|
||||
proto3-json-serializer: 3.0.4
|
||||
protobufjs: 7.5.4
|
||||
protobufjs: 7.6.4
|
||||
retry-request: 8.0.3
|
||||
rimraf: 5.0.10
|
||||
transitivePeerDependencies:
|
||||
|
|
@ -10883,7 +10848,7 @@ snapshots:
|
|||
|
||||
gtoken@7.1.0:
|
||||
dependencies:
|
||||
gaxios: 6.7.1(supports-color@10.2.2)
|
||||
gaxios: 6.7.1
|
||||
jws: 4.0.1
|
||||
transitivePeerDependencies:
|
||||
- encoding
|
||||
|
|
@ -10900,7 +10865,7 @@ snapshots:
|
|||
dependencies:
|
||||
cookie-es: 1.2.3
|
||||
crossws: 0.3.5
|
||||
defu: 6.1.6
|
||||
defu: 6.1.7
|
||||
destr: 2.0.5
|
||||
iron-webcrypto: 1.2.1
|
||||
node-mock-http: 1.0.4
|
||||
|
|
@ -10987,21 +10952,21 @@ snapshots:
|
|||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
http-proxy-middleware@3.0.7(supports-color@10.2.2):
|
||||
http-proxy-middleware@3.0.7:
|
||||
dependencies:
|
||||
'@types/http-proxy': 1.17.17
|
||||
debug: 4.4.3(supports-color@10.2.2)
|
||||
http-proxy: 1.18.1(debug@4.4.3(supports-color@10.2.2))
|
||||
http-proxy: 1.18.1(debug@4.4.3)
|
||||
is-glob: 4.0.3
|
||||
is-plain-object: 5.0.0
|
||||
micromatch: 4.0.8
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
http-proxy@1.18.1(debug@4.4.3(supports-color@10.2.2)):
|
||||
http-proxy@1.18.1(debug@4.4.3):
|
||||
dependencies:
|
||||
eventemitter3: 4.0.7
|
||||
follow-redirects: 1.16.0(debug@4.4.3(supports-color@10.2.2))
|
||||
follow-redirects: 1.16.0(debug@4.4.3)
|
||||
requires-port: 1.0.0
|
||||
transitivePeerDependencies:
|
||||
- debug
|
||||
|
|
@ -11015,7 +10980,7 @@ snapshots:
|
|||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
https-proxy-agent@8.0.0(supports-color@10.2.2):
|
||||
https-proxy-agent@8.0.0:
|
||||
dependencies:
|
||||
agent-base: 8.0.0
|
||||
debug: 4.4.3(supports-color@10.2.2)
|
||||
|
|
@ -11117,12 +11082,12 @@ snapshots:
|
|||
|
||||
ipaddr.js@2.4.0: {}
|
||||
|
||||
ipx@3.1.1(@netlify/blobs@10.7.9(supports-color@10.2.2)):
|
||||
ipx@3.1.1(@netlify/blobs@10.7.9):
|
||||
dependencies:
|
||||
'@fastify/accept-negotiator': 2.0.1
|
||||
citty: 0.1.6
|
||||
consola: 3.4.2
|
||||
defu: 6.1.6
|
||||
defu: 6.1.7
|
||||
destr: 2.0.5
|
||||
etag: 1.8.1
|
||||
h3: 1.15.11
|
||||
|
|
@ -11133,7 +11098,7 @@ snapshots:
|
|||
sharp: 0.34.5
|
||||
svgo: 4.0.1
|
||||
ufo: 1.6.4
|
||||
unstorage: 1.17.5(@netlify/blobs@10.7.9(supports-color@10.2.2))
|
||||
unstorage: 1.17.5(@netlify/blobs@10.7.9)
|
||||
xss: 1.0.15
|
||||
transitivePeerDependencies:
|
||||
- '@azure/app-configuration'
|
||||
|
|
@ -11920,28 +11885,28 @@ snapshots:
|
|||
|
||||
negotiator@1.0.0: {}
|
||||
|
||||
netlify-cli@26.1.0(@types/node@25.5.2)(picomatch@4.0.4)(supports-color@10.2.2):
|
||||
netlify-cli@26.1.0(@types/node@25.5.2)(picomatch@4.0.5):
|
||||
dependencies:
|
||||
'@fastify/static': 9.1.3
|
||||
'@netlify/ai': 0.4.2
|
||||
'@netlify/api': 14.0.19
|
||||
'@netlify/blobs': 10.7.9(supports-color@10.2.2)
|
||||
'@netlify/build': 35.15.0(@opentelemetry/api@1.9.1)(@types/node@25.5.2)(picomatch@4.0.4)
|
||||
'@netlify/build': 35.15.0(@opentelemetry/api@1.9.1)(@types/node@25.5.2)(picomatch@4.0.5)
|
||||
'@netlify/build-info': 10.5.1
|
||||
'@netlify/config': 24.6.0
|
||||
'@netlify/dev': 4.18.9(supports-color@10.2.2)
|
||||
'@netlify/dev': 4.18.9
|
||||
'@netlify/dev-utils': 4.4.6
|
||||
'@netlify/edge-bundler': 14.10.3
|
||||
'@netlify/edge-functions': 3.0.8
|
||||
'@netlify/edge-functions-bootstrap': 2.17.1
|
||||
'@netlify/headers-parser': 9.0.3
|
||||
'@netlify/images': 1.3.10(@netlify/blobs@10.7.9(supports-color@10.2.2))
|
||||
'@netlify/images': 1.3.10(@netlify/blobs@10.7.9)
|
||||
'@netlify/local-functions-proxy': 2.0.3
|
||||
'@netlify/redirect-parser': 15.0.4
|
||||
'@netlify/zip-it-and-ship-it': 14.7.1(supports-color@10.2.2)
|
||||
'@octokit/rest': 22.0.1
|
||||
'@opentelemetry/api': 1.9.1
|
||||
'@pnpm/tabtab': 0.5.4(supports-color@10.2.2)
|
||||
'@pnpm/tabtab': 0.5.4
|
||||
ansi-escapes: 7.3.0
|
||||
ansi-to-html: 0.7.2
|
||||
ascii-table: 0.0.9
|
||||
|
|
@ -11974,9 +11939,9 @@ snapshots:
|
|||
get-port: 5.1.1
|
||||
git-repo-info: 2.1.1
|
||||
gitconfiglocal: 2.1.0
|
||||
http-proxy: 1.18.1(debug@4.4.3(supports-color@10.2.2))
|
||||
http-proxy-middleware: 3.0.7(supports-color@10.2.2)
|
||||
https-proxy-agent: 8.0.0(supports-color@10.2.2)
|
||||
http-proxy: 1.18.1(debug@4.4.3)
|
||||
http-proxy-middleware: 3.0.7
|
||||
https-proxy-agent: 8.0.0
|
||||
inquirer: 8.2.7(@types/node@25.5.2)
|
||||
inquirer-autocomplete-prompt: 1.4.0(inquirer@8.2.7(@types/node@25.5.2))
|
||||
is-docker: 4.0.0
|
||||
|
|
@ -12325,12 +12290,12 @@ snapshots:
|
|||
|
||||
p-wait-for@6.0.0: {}
|
||||
|
||||
pac-proxy-agent@7.2.0(supports-color@10.2.2):
|
||||
pac-proxy-agent@7.2.0:
|
||||
dependencies:
|
||||
'@tootallnate/quickjs-emscripten': 0.23.0
|
||||
agent-base: 7.1.4
|
||||
debug: 4.4.3(supports-color@10.2.2)
|
||||
get-uri: 6.0.5(supports-color@10.2.2)
|
||||
get-uri: 6.0.5
|
||||
http-proxy-agent: 7.0.2
|
||||
https-proxy-agent: 7.0.6(supports-color@10.2.2)
|
||||
pac-resolver: 7.0.1
|
||||
|
|
@ -12512,7 +12477,7 @@ snapshots:
|
|||
|
||||
pluralize@8.0.0: {}
|
||||
|
||||
portfinder@1.0.38(supports-color@10.2.2):
|
||||
portfinder@1.0.38:
|
||||
dependencies:
|
||||
async: 3.2.6
|
||||
debug: 4.4.3(supports-color@10.2.2)
|
||||
|
|
@ -12598,22 +12563,7 @@ snapshots:
|
|||
|
||||
proto3-json-serializer@3.0.4:
|
||||
dependencies:
|
||||
protobufjs: 7.5.4
|
||||
|
||||
protobufjs@7.5.4:
|
||||
dependencies:
|
||||
'@protobufjs/aspromise': 1.1.2
|
||||
'@protobufjs/base64': 1.1.2
|
||||
'@protobufjs/codegen': 2.0.4
|
||||
'@protobufjs/eventemitter': 1.1.0
|
||||
'@protobufjs/fetch': 1.1.0
|
||||
'@protobufjs/float': 1.0.2
|
||||
'@protobufjs/inquire': 1.1.0
|
||||
'@protobufjs/path': 1.1.2
|
||||
'@protobufjs/pool': 1.1.0
|
||||
'@protobufjs/utf8': 1.1.0
|
||||
'@types/node': 25.5.2
|
||||
long: 5.3.2
|
||||
protobufjs: 7.6.4
|
||||
|
||||
protobufjs@7.6.4:
|
||||
dependencies:
|
||||
|
|
@ -12634,14 +12584,14 @@ snapshots:
|
|||
forwarded: 0.2.0
|
||||
ipaddr.js: 1.9.1
|
||||
|
||||
proxy-agent@6.5.0(supports-color@10.2.2):
|
||||
proxy-agent@6.5.0:
|
||||
dependencies:
|
||||
agent-base: 7.1.4
|
||||
debug: 4.4.3(supports-color@10.2.2)
|
||||
http-proxy-agent: 7.0.2
|
||||
https-proxy-agent: 7.0.6(supports-color@10.2.2)
|
||||
lru-cache: 7.18.3
|
||||
pac-proxy-agent: 7.2.0(supports-color@10.2.2)
|
||||
pac-proxy-agent: 7.2.0
|
||||
proxy-from-env: 1.1.0
|
||||
socks-proxy-agent: 8.0.5
|
||||
transitivePeerDependencies:
|
||||
|
|
@ -12713,7 +12663,7 @@ snapshots:
|
|||
iconv-lite: 0.7.2
|
||||
unpipe: 1.0.0
|
||||
|
||||
rc-config-loader@4.1.4(supports-color@10.2.2):
|
||||
rc-config-loader@4.1.4:
|
||||
dependencies:
|
||||
debug: 4.4.3(supports-color@10.2.2)
|
||||
js-yaml: 4.3.0
|
||||
|
|
@ -12981,11 +12931,11 @@ snapshots:
|
|||
dependencies:
|
||||
xmlchars: 2.2.0
|
||||
|
||||
secretlint@13.0.2(supports-color@10.2.2):
|
||||
secretlint@13.0.2:
|
||||
dependencies:
|
||||
'@secretlint/config-creator': 13.0.2
|
||||
'@secretlint/formatter': 13.0.2
|
||||
'@secretlint/node': 13.0.2(supports-color@10.2.2)
|
||||
'@secretlint/node': 13.0.2
|
||||
'@secretlint/profiler': 13.0.2
|
||||
'@secretlint/resolver': 13.0.2
|
||||
'@secretlint/walker': 13.0.2
|
||||
|
|
@ -13157,9 +13107,9 @@ snapshots:
|
|||
|
||||
signal-exit@4.1.0: {}
|
||||
|
||||
simple-git@3.33.0(supports-color@10.2.2):
|
||||
simple-git@3.33.0:
|
||||
dependencies:
|
||||
'@kwsites/file-exists': 1.1.1(supports-color@10.2.2)
|
||||
'@kwsites/file-exists': 1.1.1
|
||||
'@kwsites/promise-deferred': 1.1.1
|
||||
debug: 4.4.3(supports-color@10.2.2)
|
||||
transitivePeerDependencies:
|
||||
|
|
@ -13711,7 +13661,7 @@ snapshots:
|
|||
dependencies:
|
||||
crypto-random-string: 2.0.0
|
||||
|
||||
universal-analytics@0.5.4(supports-color@10.2.2):
|
||||
universal-analytics@0.5.4:
|
||||
dependencies:
|
||||
debug: 4.4.3(supports-color@10.2.2)
|
||||
uuid: 14.0.1
|
||||
|
|
@ -13734,7 +13684,7 @@ snapshots:
|
|||
|
||||
unpipe@1.0.0: {}
|
||||
|
||||
unstorage@1.17.5(@netlify/blobs@10.7.9(supports-color@10.2.2)):
|
||||
unstorage@1.17.5(@netlify/blobs@10.7.9):
|
||||
dependencies:
|
||||
anymatch: 3.1.3
|
||||
chokidar: 5.0.0
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
packages:
|
||||
- "apps/*"
|
||||
# Not a workspace — this repo is a single package at the root. pnpm 11 reads its
|
||||
# settings from this file, so it stays for `allowBuilds` / `minimumReleaseAgeExclude`.
|
||||
allowBuilds:
|
||||
'@firebase/util': false
|
||||
'@parcel/watcher': false
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
|
@ -1,6 +1,6 @@
|
|||
/**
|
||||
* Post-install convenience: make a Java runtime available for the Firebase
|
||||
* Firestore emulator (used by `pnpm -F mnswpr dev` / `db:start`). The emulator is
|
||||
* Firestore emulator (used by `pnpm run dev` / `db:start`). The emulator is
|
||||
* a Java program and firebase-tools does not bundle a JRE.
|
||||
*
|
||||
* Installs a Temurin JRE 21 into the user's home (~/.local) WITHOUT sudo and
|
||||
|
|
@ -9,7 +9,7 @@
|
|||
* - non-fatal: never fails `pnpm install` — on any problem it warns, exits 0
|
||||
* - opt-out: set SKIP_JRE_SETUP=1 (also auto-skips when CI is set)
|
||||
* Only Linux/macOS on x64/arm64 are auto-handled; anything else prints manual
|
||||
* instructions (see apps/mnswpr/README.md).
|
||||
* instructions (see README.md).
|
||||
*/
|
||||
import { spawnSync } from 'node:child_process'
|
||||
import { existsSync, mkdirSync, readdirSync, rmSync, symlinkSync, writeFileSync } from 'node:fs'
|
||||
|
|
@ -24,7 +24,7 @@ try {
|
|||
await main()
|
||||
} catch (err) {
|
||||
warn(`skipped (${err?.message || err}).`)
|
||||
warn('The Firestore emulator needs Java 11+ — install it manually, see apps/mnswpr/README.md.')
|
||||
warn('The Firestore emulator needs Java 11+ — install it manually, see README.md.')
|
||||
}
|
||||
process.exit(0)
|
||||
|
||||
|
|
@ -36,11 +36,11 @@ async function main() {
|
|||
const adoptOs = { linux: 'linux', darwin: 'mac' }[platform()]
|
||||
const adoptArch = { x64: 'x64', arm64: 'aarch64' }[arch()]
|
||||
if (!adoptOs || !adoptArch) {
|
||||
warn(`no auto-install for ${platform()}/${arch()} — install a JRE 21 manually (apps/mnswpr/README.md).`)
|
||||
warn(`no auto-install for ${platform()}/${arch()} — install a JRE 21 manually (README.md).`)
|
||||
return
|
||||
}
|
||||
if (!hasTool('tar')) {
|
||||
warn('`tar` not found — cannot unpack the JRE. Install Java manually (apps/mnswpr/README.md).')
|
||||
warn('`tar` not found — cannot unpack the JRE. Install Java manually (README.md).')
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,9 +4,8 @@
|
|||
* a FULLY-RENDERED, static page — no runtime JS, no Firebase at page load.
|
||||
*
|
||||
* The data never changes, so the page is a frozen artifact. Re-run only if you
|
||||
* ever need to regenerate it. Because `firebase` is an app-workspace dependency,
|
||||
* run it so Node can resolve it, e.g. from the app directory:
|
||||
* (cd apps/mnswpr && node scripts/export-legends.js)
|
||||
* ever need to regenerate it. Run it from the repo root:
|
||||
* node scripts/export-legends.js
|
||||
*/
|
||||
import { writeFileSync } from 'node:fs'
|
||||
import { resolve, dirname } from 'node:path'
|
||||
|
|
@ -13,10 +13,9 @@
|
|||
* firestore.rules to be deployed first (they permit writes to
|
||||
* `mw-test-scores`), else every write returns permission-denied:
|
||||
* npx firebase deploy --only firestore:rules --project dev
|
||||
* (cd apps/mnswpr && node scripts/seed-dev-scores.js)
|
||||
* node scripts/seed-dev-scores.js
|
||||
*
|
||||
* `firebase` is an app-workspace dependency, so run it from the app directory so
|
||||
* Node can resolve it. Optional namespace override: LB_NAMESPACE=mw-test.
|
||||
* Run from the repo root. Optional namespace override: LB_NAMESPACE=mw-test.
|
||||
*/
|
||||
import { initializeApp } from 'firebase/app'
|
||||
import { getFirestore, connectFirestoreEmulator, doc, collection, setDoc } from 'firebase/firestore/lite'
|
||||
0
apps/mnswpr/vite-env.d.ts → vite-env.d.ts
vendored
0
apps/mnswpr/vite-env.d.ts → vite-env.d.ts
vendored
|
|
@ -3,6 +3,6 @@ import { defineConfig } from 'vitest/config'
|
|||
export default defineConfig({
|
||||
test: {
|
||||
environment: 'jsdom',
|
||||
include: ['apps/**/test/**/*.test.js', 'scripts/test/**/*.test.js']
|
||||
include: ['test/**/*.test.js', 'scripts/test/**/*.test.js']
|
||||
}
|
||||
})
|
||||
|
|
|
|||
Loading…
Reference in a new issue