Flatten the repo: move everything out of app/ to the root
Now that the CLI and the Next.js app are one package, nesting it inside app/ served no purpose - the repo root itself becomes the published npm package. Merges app/.gitignore and app/README.md into the root versions, drops the now-duplicate app/LICENSE, and updates path references (README, docs/ARCHITECTURE.md, docs/CONFIG_REFERENCE.md, package.json's repository.directory) that assumed the app/ nesting. Also fixes a real bug this surfaced: the in-app docs viewer resolved docs/ relative to process.cwd(), which only worked by accident when the CLI happened to be invoked from app/'s parent directory. A first attempt at fixing it with import.meta.dirname broke instead, for the same cross-module-graph reason config-path resolution already documented - Next compiles Route Handlers through a separate module graph that doesn't preserve source-relative import.meta paths. Fixed by exposing the app root via TRIGGERSHELL_APP_ROOT (set once in server.ts, where import.meta *does* resolve correctly), the same pattern already used for TRIGGERSHELL_CONFIG_PATH. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
30350d80f4
commit
3f379ca2ac
123 files changed
+65
-104
No files matched your search
+34
@@ -1,3 +1,36 @@
|
|||||||
|
# dependencies
|
||||||
|
/node_modules
|
||||||
|
/.pnp
|
||||||
|
.pnp.*
|
||||||
|
.yarn/*
|
||||||
|
!.yarn/patches
|
||||||
|
!.yarn/plugins
|
||||||
|
!.yarn/releases
|
||||||
|
!.yarn/versions
|
||||||
|
|
||||||
|
# testing
|
||||||
|
/coverage
|
||||||
|
|
||||||
|
# next.js
|
||||||
|
/.next/
|
||||||
|
/out/
|
||||||
|
|
||||||
|
# production
|
||||||
|
/build
|
||||||
|
|
||||||
|
# typescript
|
||||||
|
*.tsbuildinfo
|
||||||
|
next-env.d.ts
|
||||||
|
|
||||||
|
# debug
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
.pnpm-debug.log*
|
||||||
|
|
||||||
|
# vercel
|
||||||
|
.vercel
|
||||||
|
|
||||||
# Runtime data (created by `triggershell start` in whatever directory the config lives in)
|
# Runtime data (created by `triggershell start` in whatever directory the config lives in)
|
||||||
.triggershell/
|
.triggershell/
|
||||||
|
|
||||||
@@ -11,5 +44,6 @@
|
|||||||
|
|
||||||
# Editors / OS
|
# Editors / OS
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
*.pem
|
||||||
.idea/
|
.idea/
|
||||||
.vscode/
|
.vscode/
|
||||||
File renamed without changes.
File renamed without changes.
@@ -34,7 +34,7 @@ Edit `triggershell.yml` to add your own scripts (see [Configuration](#configurat
|
|||||||
re-run `triggershell start`.
|
re-run `triggershell start`.
|
||||||
|
|
||||||
> The `triggershell` package isn't published to npm yet. Until it is, build and link a local copy
|
> The `triggershell` package isn't published to npm yet. Until it is, build and link a local copy
|
||||||
> instead: `pnpm --dir app install && pnpm --dir app build && pnpm --dir app link --global`.
|
> instead: `pnpm install && pnpm build && pnpm link --global`.
|
||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
|
|
||||||
@@ -150,21 +150,23 @@ Full reference with request/response shapes and curl examples: [`docs/API.md`](d
|
|||||||
## Development
|
## Development
|
||||||
|
|
||||||
This is the workflow for working on TriggerShell itself, not for installing/running it — it
|
This is the workflow for working on TriggerShell itself, not for installing/running it — it
|
||||||
bypasses the CLI entirely and talks to `app/`'s own scripts directly, with hot reload:
|
bypasses the CLI entirely and talks to the app's own scripts directly, with hot reload. The app is
|
||||||
|
still not meant to be run standalone with `next dev`/`next start`, since it needs the custom server
|
||||||
|
(`server.ts`) for the WebSocket endpoint — `pnpm dev`/`pnpm start` below cover that:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
pnpm --dir app install
|
pnpm install
|
||||||
pnpm --dir app dev # tsx watch server.ts - reads TRIGGERSHELL_CONFIG_PATH from the environment
|
pnpm dev # tsx watch server.ts - reads TRIGGERSHELL_CONFIG_PATH from the environment
|
||||||
pnpm --dir app lint
|
pnpm lint
|
||||||
pnpm --dir app typecheck
|
pnpm typecheck
|
||||||
pnpm --dir app test # CLI unit tests (src/cli/**/*.test.ts)
|
pnpm test # CLI unit tests (src/cli/**/*.test.ts)
|
||||||
pnpm --dir app db:studio # browse the SQLite DB
|
pnpm db:studio # browse the SQLite DB
|
||||||
```
|
```
|
||||||
|
|
||||||
Repo layout:
|
Repo layout — the repo root itself is the published npm package (Next.js app + the `triggershell`
|
||||||
|
CLI in `bin/`/`src/cli/`), alongside:
|
||||||
|
|
||||||
```
|
```
|
||||||
app/ The published npm package: Next.js app + the `triggershell` CLI (bin/, src/cli/) in one
|
|
||||||
examples/ A runnable example config + scripts
|
examples/ A runnable example config + scripts
|
||||||
docs/ Config/architecture/API reference docs
|
docs/ Config/architecture/API reference docs
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -1,41 +0,0 @@
|
|||||||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
|
||||||
|
|
||||||
# dependencies
|
|
||||||
/node_modules
|
|
||||||
/.pnp
|
|
||||||
.pnp.*
|
|
||||||
.yarn/*
|
|
||||||
!.yarn/patches
|
|
||||||
!.yarn/plugins
|
|
||||||
!.yarn/releases
|
|
||||||
!.yarn/versions
|
|
||||||
|
|
||||||
# testing
|
|
||||||
/coverage
|
|
||||||
|
|
||||||
# next.js
|
|
||||||
/.next/
|
|
||||||
/out/
|
|
||||||
|
|
||||||
# production
|
|
||||||
/build
|
|
||||||
|
|
||||||
# misc
|
|
||||||
.DS_Store
|
|
||||||
*.pem
|
|
||||||
|
|
||||||
# debug
|
|
||||||
npm-debug.log*
|
|
||||||
yarn-debug.log*
|
|
||||||
yarn-error.log*
|
|
||||||
.pnpm-debug.log*
|
|
||||||
|
|
||||||
# env files (can opt-in for committing if needed)
|
|
||||||
.env*
|
|
||||||
|
|
||||||
# vercel
|
|
||||||
.vercel
|
|
||||||
|
|
||||||
# typescript
|
|
||||||
*.tsbuildinfo
|
|
||||||
next-env.d.ts
|
|
||||||
-21
@@ -1,21 +0,0 @@
|
|||||||
MIT License
|
|
||||||
|
|
||||||
Copyright (c) 2026 TriggerShell 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.
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
# TriggerShell web app
|
|
||||||
|
|
||||||
This directory is both the Next.js app and the home of the `triggershell` CLI (`bin/triggershell.js`
|
|
||||||
→ `src/cli`) that launches it — together they're published as one npm package. The app is still not
|
|
||||||
meant to be run standalone with `next dev`/`next start`, since it needs a custom server (`server.ts`)
|
|
||||||
for the WebSocket endpoint; use the CLI (`triggershell start`) or the `pnpm` scripts below instead.
|
|
||||||
|
|
||||||
See the [repo root README](../README.md) for how to run TriggerShell end-to-end, and
|
|
||||||
[`../docs/ARCHITECTURE.md`](../docs/ARCHITECTURE.md) for how this app is put together.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
pnpm install
|
|
||||||
pnpm dev # tsx watch server.ts - reads TRIGGERSHELL_CONFIG_PATH from the environment
|
|
||||||
pnpm lint
|
|
||||||
pnpm typecheck
|
|
||||||
pnpm test # CLI unit tests (src/cli/**/*.test.ts)
|
|
||||||
pnpm db:studio # browse the SQLite database
|
|
||||||
```
|
|
||||||
|
|
||||||
Note: this is the contributor workflow for developing TriggerShell itself. End users install and
|
|
||||||
run the published `triggershell` CLI instead (see the root README).
|
|
||||||
File renamed without changes.
File renamed without changes.
@@ -1,8 +1,8 @@
|
|||||||
# Architecture
|
# Architecture
|
||||||
|
|
||||||
```
|
```
|
||||||
triggershell (Node CLI, src/cli) app/ (Next.js, all server logic)
|
triggershell (Node CLI, src/cli) server.ts + src/ (Next.js, all server logic)
|
||||||
─────────────────────────────── ──────────────────────────────
|
─────────────────────────────── ─────────────────────────────────────────
|
||||||
triggershell start server.ts (custom Node server)
|
triggershell start server.ts (custom Node server)
|
||||||
1. resolve + validate the config (loadConfig) ├─ Next.js request handler (pages, API routes)
|
1. resolve + validate the config (loadConfig) ├─ Next.js request handler (pages, API routes)
|
||||||
2. check the port is free ├─ ws.WebSocketServer on /ws/runs
|
2. check the port is free ├─ ws.WebSocketServer on /ws/runs
|
||||||
@@ -24,7 +24,7 @@
|
|||||||
|
|
||||||
## Why a custom Node server
|
## Why a custom Node server
|
||||||
|
|
||||||
Next.js Route Handlers can't host a persistent WebSocket server, so `app/server.ts` wraps Next's
|
Next.js Route Handlers can't host a persistent WebSocket server, so `server.ts` wraps Next's
|
||||||
request handler in a plain `http.createServer` and attaches a `ws.WebSocketServer` via the
|
request handler in a plain `http.createServer` and attaches a `ws.WebSocketServer` via the
|
||||||
`upgrade` event, scoped to `/ws/runs` with its own auth check (Route Handlers get auth via
|
`upgrade` event, scoped to `/ws/runs` with its own auth check (Route Handlers get auth via
|
||||||
`next/headers`'s `cookies()`, which isn't available on a raw `http.IncomingMessage`).
|
`next/headers`'s `cookies()`, which isn't available on a raw `http.IncomingMessage`).
|
||||||
@@ -100,4 +100,4 @@ Every server file that reads the config/DB at request time (`getConfig()`, `getD
|
|||||||
`requireAuth()`) sets `export const dynamic = "force-dynamic"`. Without it, `next build` tries to
|
`requireAuth()`) sets `export const dynamic = "force-dynamic"`. Without it, `next build` tries to
|
||||||
statically prerender pages like `/` at build time, which fails because there's no config file to
|
statically prerender pages like `/` at build time, which fails because there's no config file to
|
||||||
read yet (the config only exists at `triggershell start` runtime, in the user's own project
|
read yet (the config only exists at `triggershell start` runtime, in the user's own project
|
||||||
directory, not `app/`'s).
|
directory, not the package's).
|
||||||
@@ -10,7 +10,7 @@ present) into its environment - without overriding any variable already set in t
|
|||||||
secrets referenced via `${VAR}` don't have to be committed alongside the config. `triggershell
|
secrets referenced via `${VAR}` don't have to be committed alongside the config. `triggershell
|
||||||
init` scaffolds both files together.
|
init` scaffolds both files together.
|
||||||
|
|
||||||
The canonical schema is the Zod schema at `app/src/lib/config/schema.ts` — this document mirrors
|
The canonical schema is the Zod schema at `src/lib/config/schema.ts` — this document mirrors
|
||||||
it. `triggershell validate` loads and validates the config directly against the schema below (no
|
it. `triggershell validate` loads and validates the config directly against the schema below (no
|
||||||
separate pre-flight step).
|
separate pre-flight step).
|
||||||
|
|
||||||
|
|||||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -5,8 +5,7 @@
|
|||||||
"type": "module",
|
"type": "module",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://dev.pivoine.art/valknar/triggershell.git",
|
"url": "https://dev.pivoine.art/valknar/triggershell.git"
|
||||||
"directory": "app"
|
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
"triggershell": "bin/triggershell.js"
|
"triggershell": "bin/triggershell.js"
|
||||||
@@ -19,6 +18,7 @@
|
|||||||
"src",
|
"src",
|
||||||
"templates",
|
"templates",
|
||||||
"drizzle",
|
"drizzle",
|
||||||
|
"docs",
|
||||||
".next",
|
".next",
|
||||||
"server.ts",
|
"server.ts",
|
||||||
"next.config.ts",
|
"next.config.ts",
|
||||||
Generated
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -24,6 +24,10 @@ reconcileOrphanedRuns();
|
|||||||
// `dir` must be this file's own directory, not `process.cwd()` - when launched by the installed
|
// `dir` must be this file's own directory, not `process.cwd()` - when launched by the installed
|
||||||
// `triggershell` CLI, the working directory is wherever the user's config lives, not the package.
|
// `triggershell` CLI, the working directory is wherever the user's config lives, not the package.
|
||||||
const dir = path.dirname(fileURLToPath(import.meta.url));
|
const dir = path.dirname(fileURLToPath(import.meta.url));
|
||||||
|
// Exposed via `process.env` (not just the local `dir` const) so Route Handlers/Server Components -
|
||||||
|
// compiled through Next's own module graph, separate from this file's - can find it too. See
|
||||||
|
// `docs.ts`'s use of this and the `globalThis` comment in `runner/events.ts` for the same reasoning.
|
||||||
|
process.env.TRIGGERSHELL_APP_ROOT = dir;
|
||||||
const app = next({ dev, dir, hostname, port });
|
const app = next({ dev, dir, hostname, port });
|
||||||
const handle = app.getRequestHandler();
|
const handle = app.getRequestHandler();
|
||||||
|
|
||||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
|
Before Width: | Height: | Size: 386 B After Width: | Height: | Size: 386 B |
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Loaded 100 of 123 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user