@nearform/fling 0.0.0-stage → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Nearform
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,219 @@
1
- # Temporary Holding Version
1
+ # @nearform/fling
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Fling a folder of static files at [fling.labs.nearform.com](https://fling.labs.nearform.com) and
4
+ get a stable link back:
5
+
6
+ ```
7
+ https://<name>.fling.labs.nearform.com
8
+ ```
9
+
10
+ Site names are one global namespace, first come first served. Sites are private to signed-in Nearformers by default. Share links make them viewable by anyone
11
+ who has the link.
12
+
13
+ ## Install
14
+
15
+ Node 22 or later.
16
+
17
+ ```sh
18
+ npm install -g @nearform/fling # then: fling …
19
+ # or run without installing:
20
+ npx @nearform/fling …
21
+ ```
22
+
23
+ ## Log in
24
+
25
+ ```sh
26
+ fling login
27
+ ```
28
+
29
+ This opens your browser for Nearform Google sign-in and stores an API key in
30
+ `~/.fling/config.json` (mode 0600). `fling whoami` shows who you are, and `fling logout` removes the
31
+ key. For CI, set `FLING_API_KEY` instead.
32
+
33
+ ## Deploy
34
+
35
+ ```sh
36
+ npm run build
37
+ fling ./dist # name generated from the project, e.g. rocketpod-docs; you confirm it
38
+ fling ./dist --name my-app # → https://my-app.fling.labs.nearform.com
39
+ fling ./dist --name my-app --spa # client-side routing: unknown paths serve index.html
40
+ fling ./dist --public # no sign-in needed to view
41
+ fling ./dist --yes # never prompt (CI): use the generated name as is
42
+ fling # deploys the current folder
43
+ fling "Pitch Deck.html" # a single page, served as index.html → pitch-deck
44
+ fling site.zip # a zip of a site: extracted, a single top folder unwrapped
45
+ fling diagram.svg # any other file, next to a generated page that shows it
46
+ ```
47
+
48
+ What you can fling:
49
+
50
+ - **A folder**, as is.
51
+ - **A single `.html`/`.htm` file**, served as the site's `index.html`.
52
+ - **A `.zip`**: extracted (paths that would escape the folder are refused), `__MACOSX/` and dotfiles
53
+ skipped, and a single top-level folder unwrapped.
54
+ - **Any other file** (`.pdf`, `.svg`, `.png`, `.md`…), served next to a small generated `index.html`
55
+ that shows it (images, PDF, video, audio) or links to it.
56
+
57
+ A file's default site name comes from its name, without the extension or a browser's ` (1)`
58
+ duplicate suffix: `Pitch Deck (1).html` → `pitch-deck`. Folders use the naming rules below.
59
+
60
+ **Files by name.** If the path doesn't exist where you are, Fling looks for it by name, newest
61
+ first, in Downloads (`FLING_DOWNLOADS_DIR` if set; on Linux your XDG download folder), Desktop,
62
+ `~/Documents/Claude`, `~/Claude` and Claude Desktop's output folders, and says where it found it:
63
+
64
+ ```
65
+ $ fling Pitch-Deck.html
66
+ fling Found in Downloads: /Users/me/Downloads/Pitch-Deck.html
67
+ ```
68
+
69
+ - Re-fling to update. Identical content is a no-op, and content you deployed before is restored
70
+ instantly without uploading.
71
+ - Dotfiles, `node_modules` and anything listed in a `.flingignore` (gitignore syntax) are skipped.
72
+ Symlinks pointing outside the folder are never followed.
73
+ - Limits are 25 MB per file, 100 MB per deploy and 5,000 files.
74
+ - Absolute asset paths (`/assets/x.js`) work because each site has its own subdomain.
75
+
76
+ ### Site names
77
+
78
+ Names use lowercase letters, digits and single hyphens, up to 50 characters, and are first come,
79
+ first served across everyone. A few (`api`, `www`, `fling`…) are reserved. If a name belongs to
80
+ someone else, Fling suggests free ones with your initials appended (`my-app-cc`, `my-app-cc2`…).
81
+
82
+ Without `--name`, the name is generated from the folder, never from your user name:
83
+
84
+ 1. Find the project root: the nearest folder (this one or above) containing `.git`, otherwise
85
+ `package.json`, `pyproject.toml`, `Cargo.toml` or `go.mod`. The search stops at your home folder.
86
+ 2. Use the root's folder name plus the folders from the root down, skipping build output
87
+ (`dist`, `build`, `out`, `output`, `public`, `www`, `_site`, `site`, `html`, `static`, `export`,
88
+ `target`), monorepo containers (`apps`, `packages`, `src`, `sites`, `libs`, `projects`,
89
+ `services`), dot-folders (`.vitepress`, `.next`…) and repeats. A `-static`/`-dist`/`-build`/`-out`
90
+ suffix is trimmed (`storybook-static` → `storybook`).
91
+ 3. With no project root, use the deepest folder that isn't build output.
92
+ 4. Too long? Middle parts are dropped, then it is truncated.
93
+
94
+ | Folder | Name |
95
+ |---|---|
96
+ | `~/work/rocketpod/docs` | `rocketpod-docs` |
97
+ | `~/work/myapp/dist` | `myapp` |
98
+ | `~/work/mono/apps/web/dist` | `mono-web` |
99
+ | `~/work/mono/packages/ui/storybook-static` | `mono-ui-storybook` |
100
+ | `~/Downloads/report/dist` (no project) | `report` |
101
+
102
+ ### Prompts
103
+
104
+ In a terminal, Fling checks the generated name and asks before deploying:
105
+
106
+ ```
107
+ fling Site name: rocketpod-docs → https://rocketpod-docs.fling.labs.nearform.com/ (new)
108
+ Use "rocketpod-docs"? [Y/n or type another name]
109
+ ```
110
+
111
+ The note says `(new)` or `(updates your existing site)`. If the name is taken it lists suggestions
112
+ and offers the first one. Press Enter to accept, type another name to check that one, or `n` to
113
+ abort.
114
+
115
+ If there is no `index.html` at the top it asks:
116
+
117
+ ```
118
+ No index.html at the root. [L]ist the HTML pages on a generated index page / [f]ling anyway (the root will 404) / [a]bort
119
+ ```
120
+
121
+ **L** (the default, offered when there are `.html` pages) adds a generated `index.html` that links
122
+ every HTML page, titled from each page's `<title>`. It is built in memory and uploaded with the
123
+ site; your folder is never written to. Without HTML pages the choices are fling anyway or abort
124
+ (the default). `--list-html` and `--no-list-html` decide up front.
125
+
126
+ With `--name` there is no name prompt. With `--yes`, or without a terminal (CI, agents), Fling never
127
+ asks: with no `index.html` it generates the listing when there are HTML pages (otherwise it warns),
128
+ and a taken name fails (exit 1) with suggestions rather than picking another name — pass `--name`.
129
+
130
+ ## Manage sites
131
+
132
+ | Command | |
133
+ |---|---|
134
+ | `fling ls [--archived]` | your sites |
135
+ | `fling info <name>` / `fling versions <name>` | details and version history |
136
+ | `fling files <name> [versionId]` | the files in the live version (or an earlier one) |
137
+ | `fling rollback <name> <versionId>` | serve an earlier version |
138
+ | `fling share <name> [--refresh] [--revoke]` | public share link: print or create it, rotate it, or remove it |
139
+ | `fling visibility <name> private\|public` | require sign-in, or not |
140
+ | `fling archive <name>` / `fling unarchive <name>` | take offline and keep the files, or bring back |
141
+ | `fling rm <name> [--yes]` | delete permanently |
142
+
143
+ Global options: `--json` prints machine-readable output, and `--server <url>` points at another
144
+ server. Exit codes are `0` ok, `1` error, `2` not logged in and `3` forbidden.
145
+
146
+ Environment: `FLING_API_KEY`, `FLING_URL`, `FLING_CONFIG_DIR`, `FLING_DEBUG`, `FLING_DOWNLOADS_DIR`
147
+ (where files given by name are looked for first), `FLING_NO_WAIT=1` (after a deploy or a new share
148
+ link, don't wait the few seconds it takes to reach every edge).
149
+
150
+ ## Claude Code plugin and MCP
151
+
152
+ The Fling plugin gives Claude a `fling` skill plus an MCP server (`fling mcp`), so you can say
153
+ "fling the dist folder and give me a share link":
154
+
155
+ ```
156
+ /plugin marketplace add nearform/fling
157
+ /plugin install fling@fling
158
+ ```
159
+
160
+ Log in once with `fling login` (or `npx @nearform/fling login` if it is not installed). The MCP server reuses that login.
161
+
162
+ The MCP tools:
163
+
164
+ - `fling_deploy`: a folder, `.html`, `.zip` or other file on this computer, by path or just its
165
+ name (looked up like the CLI does).
166
+ - `fling_publish`: files passed inline, for content Claude wrote in the conversation. It has the same
167
+ definition as the remote connector's tool.
168
+ - `fling_find_files`: recent `.html`/`.zip` files and folders with an `index.html` in those folders,
169
+ newest first (last 14 days by default).
170
+ - `fling_login`: opens the browser sign-in. If you haven't finished after about 30 seconds it returns
171
+ and keeps waiting in the background for up to 5 minutes.
172
+ - `fling_check_name`, `fling_list`, `fling_info`, `fling_share`, `fling_set_visibility`,
173
+ `fling_archive`, `fling_rollback`, `fling_delete` (needs `confirm: true`) and `fling_whoami`.
174
+
175
+ The MCP server never prompts:
176
+
177
+ - **Names.** Without a `name`, `fling_deploy` uses the generated name and fails with suggestions if
178
+ it is taken. `fling_check_name` (with a `name`, or a `path` to see its generated name) lets the
179
+ agent confirm a name with you first.
180
+ - **No `index.html`.** If there are HTML pages but no `index.html`, `fling_deploy` and
181
+ `fling_publish` don't deploy. They ask the agent to check with you, then retry with
182
+ `listHtml: true` (generate the listing) or `listHtml: false` (deploy anyway).
183
+
184
+ ## Claude Desktop extension
185
+
186
+ For Claude Desktop (including Cowork), install the one-click extension. It runs the same MCP server
187
+ on your computer, so Claude can fling files you downloaded or that Claude Desktop saved, by name,
188
+ without uploading anything from Claude's sandbox.
189
+
190
+ 1. Download [fling.mcpb](https://fling.labs.nearform.com/downloads/fling.mcpb).
191
+ 2. Double-click it, or drag it into Claude Desktop, or go to **Settings → Extensions → Advanced
192
+ settings → Install Extension…** and pick the file.
193
+ 3. Optional settings: **Fling server** (default `https://fling.labs.nearform.com`) and **Downloads
194
+ folder** (default `~/Downloads`).
195
+ 4. Ask Claude to "fling Pitch Deck.html from my Downloads". If you're not signed in, Claude calls
196
+ `fling_login` and your browser opens. The extension and the CLI share the login in
197
+ `~/.fling/config.json`.
198
+
199
+ It needs Node.js 20 or later, which Claude Desktop provides, on macOS or Windows.
200
+
201
+ Build it with `pnpm --filter @nearform/fling build:mcpb`. That bundles `src/mcp-entry.ts` and every
202
+ dependency into one file, then validates and packs `mcpb/manifest.json` into `dist/fling.mcpb`.
203
+ CI publishes it at `/downloads/fling.mcpb`.
204
+
205
+ To use the MCP server in another client, run it over stdio:
206
+
207
+ ```json
208
+ { "command": "npx", "args": ["-y", "@nearform/fling@latest", "mcp"] }
209
+ ```
210
+
211
+ ## Development
212
+
213
+ From the repo root:
214
+
215
+ ```sh
216
+ pnpm cli --server http://localhost:3001 login # against `pnpm dev`
217
+ pnpm --filter @nearform/fling test
218
+ pnpm --filter @nearform/fling build # → dist/cli.js
219
+ ```