webhanger 1.0.0 → 1.0.4

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/README.md ADDED
@@ -0,0 +1,594 @@
1
+ # WebHanger
2
+
3
+ > **Component-as-a-Service (CaaS)** — Bundle once. Encrypt with AES-256. Deliver via edge CDN. Load anywhere with zero code.
4
+
5
+ WebHanger is a secure, edge-delivered component distribution platform. Think of it as npm for UI components — but instead of installing packages, you deploy encrypted components to a CDN and load them into any website with a single HTML tag.
6
+
7
+ ---
8
+
9
+ ## Packages
10
+
11
+ | Package | Install | Description |
12
+ |---|---|---|
13
+ | `webhanger` | `npm install -g webhanger` | CLI + Node.js library |
14
+ | `webhanger-front` | `npm install webhanger-front` | Browser SDK |
15
+
16
+ ---
17
+
18
+ ## Quick Start
19
+
20
+ ```bash
21
+ # 1. Install CLI
22
+ npm install -g webhanger
23
+
24
+ # 2. Setup your project (provisions S3 + CloudFront automatically)
25
+ wh init
26
+
27
+ # 3. Deploy all components, build site, zip for upload — one command
28
+ wh ship ./components ./docs 1.0.0 ./dist
29
+ ```
30
+
31
+ Load in any website — zero JS required:
32
+
33
+ ```html
34
+ <script src="https://unpkg.com/webhanger-front@latest/browser.min.js"></script>
35
+ <script>WebHangerFront.initialize("./wh-manifest.json");</script>
36
+
37
+ <wh-component name="navbar"></wh-component>
38
+ <wh-component name="hero"></wh-component>
39
+ <wh-component name="footer"></wh-component>
40
+ ```
41
+
42
+ ---
43
+
44
+ ## CLI Reference
45
+
46
+ ### `wh init`
47
+
48
+ Interactive project setup. Provisions infrastructure automatically.
49
+
50
+ ```bash
51
+ wh init
52
+ ```
53
+
54
+ Prompts:
55
+ - Project name
56
+ - Storage provider: `s3` | `r2` | `minio` | `local`
57
+ - Database provider: `firebase` | `supabase` | `mongodb`
58
+ - Credentials
59
+
60
+ For **S3**: automatically creates the bucket, configures CORS + versioning, spins up a CloudFront distribution. No AWS Console needed.
61
+
62
+ Optional: setup Cloudflare Edge Worker for token validation + geo routing at the edge.
63
+
64
+ Generates `webhanger.config.json`.
65
+
66
+ ---
67
+
68
+ ### `wh ship` ⭐ The main command
69
+
70
+ Deploy + build + zip in one shot.
71
+
72
+ ```bash
73
+ wh ship <components-dir> <site-dir> [version] [out-dir]
74
+ ```
75
+
76
+ ```bash
77
+ wh ship ./components ./docs 1.0.0 ./dist
78
+ ```
79
+
80
+ What it does:
81
+ 1. Deploys all components (bundle → AES encrypt → upload → sign → register)
82
+ 2. Resolves dependency graph
83
+ 3. Writes `wh-manifest.json` (no sensitive data in HTML)
84
+ 4. Production builds the site (minify HTML, inline CSS/JS)
85
+ 5. Zips output for direct upload
86
+
87
+ ```
88
+ 🚀 [1/4] Deploying components...
89
+ navbar@1.0.0... ✅
90
+ hero@1.0.0... ✅
91
+
92
+ 🔍 [2/4] Resolving dependency graph...
93
+
94
+ 🏗️ [3/4] Building ./docs → ./dist...
95
+ index.html 4.2 kB
96
+
97
+ 📦 [4/4] Zipping ./dist...
98
+
99
+ ✅ Ship complete!
100
+ Deploy zip: ./deploy.zip (12.4 kB)
101
+ ```
102
+
103
+ Upload `deploy.zip` to Netlify, S3, cPanel, or any static host.
104
+
105
+ ---
106
+
107
+ ### `wh deploy`
108
+
109
+ Deploy a single component.
110
+
111
+ ```bash
112
+ wh deploy <component-dir> <name> <version>
113
+ wh deploy ./components/navbar navbar 1.0.0
114
+ ```
115
+
116
+ Prompts for token (auto-generate or custom) and expiry (never or seconds).
117
+
118
+ ---
119
+
120
+ ### `wh graph-deploy`
121
+
122
+ Deploy all components in a directory and resolve the dependency graph.
123
+
124
+ ```bash
125
+ wh graph-deploy <components-dir> [version] [out-dir]
126
+ wh graph-deploy ./components 1.0.0 ./output
127
+ ```
128
+
129
+ ---
130
+
131
+ ### `wh build`
132
+
133
+ Production build — minifies HTML, inlines local CSS/JS.
134
+
135
+ ```bash
136
+ wh build <src-dir> [out-dir]
137
+ wh build ./docs ./dist
138
+ ```
139
+
140
+ ---
141
+
142
+ ### `wh zip`
143
+
144
+ Zip a directory for deployment.
145
+
146
+ ```bash
147
+ wh zip <src-dir> [out-file]
148
+ wh zip ./dist ./deploy.zip
149
+ ```
150
+
151
+ ---
152
+
153
+ ### `wh analyze`
154
+
155
+ Detect framework, styling approach, and CDN dependencies automatically.
156
+
157
+ ```bash
158
+ wh analyze ./components/navbar
159
+ ```
160
+
161
+ ```
162
+ 🔍 Component Analysis
163
+
164
+ Framework : vanilla
165
+ Styling : tailwind
166
+ Imports : gsap, axios
167
+ CDN Assets:
168
+ [script] https://cdn.tailwindcss.com
169
+ [script] https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.2/gsap.min.js
170
+ ```
171
+
172
+ ---
173
+
174
+ ### `wh convert`
175
+
176
+ Convert a vanilla HTML/CSS/JS component to any framework.
177
+
178
+ ```bash
179
+ wh convert <dir> <name> <target> [out-dir]
180
+ wh convert ./components/navbar navbar react ./output
181
+ ```
182
+
183
+ Supported targets: `react` `vue` `svelte` `next` `angular` `astro`
184
+
185
+ ---
186
+
187
+ ### `wh access`
188
+
189
+ Role-based access control for teams.
190
+
191
+ ```bash
192
+ wh access grant # generate API key with role
193
+ wh access revoke <key> # revoke a key
194
+ wh access list # list all keys
195
+ ```
196
+
197
+ Roles:
198
+
199
+ | Role | deploy | read | delete | manage_access |
200
+ |---|---|---|---|---|
201
+ | owner | ✅ | ✅ | ✅ | ✅ |
202
+ | admin | ✅ | ✅ | ✅ | ✅ |
203
+ | deployer | ✅ | ✅ | ❌ | ❌ |
204
+ | viewer | ❌ | ✅ | ❌ | ❌ |
205
+
206
+ ---
207
+
208
+ ### `wh edge-init`
209
+
210
+ Setup Cloudflare Edge Worker for production-grade delivery.
211
+
212
+ ```bash
213
+ wh edge-init
214
+ # then:
215
+ cd edge && wrangler deploy
216
+ ```
217
+
218
+ ---
219
+
220
+ ## Component Structure
221
+
222
+ ```
223
+ components/
224
+ navbar/
225
+ index.html ← markup
226
+ style.css ← styles
227
+ script.js ← behaviour
228
+ webhanger.component.json ← assets + dependencies
229
+ ```
230
+
231
+ ### `webhanger.component.json`
232
+
233
+ ```json
234
+ {
235
+ "assets": [
236
+ { "type": "script", "url": "https://cdn.tailwindcss.com" },
237
+ { "type": "script", "url": "https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.2/gsap.min.js" }
238
+ ],
239
+ "dependencies": ["navbar@1.0.0", "chart@2.0.0"]
240
+ }
241
+ ```
242
+
243
+ CDN assets are auto-detected by `wh analyze` and merged automatically on deploy.
244
+
245
+ ---
246
+
247
+ ## Dependency Graph
248
+
249
+ npm-like dependency resolution for UI components.
250
+
251
+ ```
252
+ dashboard@1.0.0
253
+ ├── navbar@1.0.0
254
+ └── statsbar@1.0.0
255
+ └── chart@1.0.0
256
+ ```
257
+
258
+ - Depth-first resolution
259
+ - Circular dependency detection with full chain error
260
+ - Deps load before parent component
261
+ - Stored in Firestore per project
262
+
263
+ ```bash
264
+ wh graph-deploy ./components 1.0.0 ./output
265
+ ```
266
+
267
+ Programmatic:
268
+
269
+ ```js
270
+ import { resolveGraph } from "webhanger";
271
+ const graph = await resolveGraph(config.db, projectId, "dashboard", "1.0.0");
272
+ // Returns: [chart, navbar, statsbar, dashboard] — deps first
273
+ ```
274
+
275
+ ---
276
+
277
+ ## Security
278
+
279
+ ### AES-256-GCM Encryption
280
+
281
+ Every component chunk (HTML/CSS/JS) is encrypted before upload.
282
+
283
+ ```
284
+ Key = SHA-256(projectId + salt)
285
+ Payload = iv:tag:ciphertext (base64)
286
+ Salts = "::html" | "::css" | "::js"
287
+ ```
288
+
289
+ ### HMAC-SHA256 Signed URLs
290
+
291
+ ```
292
+ token = HMAC-SHA256(projectId:componentPath:expires, secretKey)
293
+ ```
294
+
295
+ ### Integrity Check
296
+
297
+ SHA-256 hash of raw content stored in payload. Verified after decryption — detects tampering.
298
+
299
+ ### Domain Restriction
300
+
301
+ ```js
302
+ WebHangerFront.load(url, pid, token, 0, "[data-wh]", null, [], {
303
+ allowedDomains: ["mysite.com", "app.io"]
304
+ });
305
+ ```
306
+
307
+ ### Token Expiry
308
+
309
+ ```js
310
+ // Never expires
311
+ wh.deploy("./navbar", "navbar", "1.0.0");
312
+
313
+ // Expires in 24 hours
314
+ wh.deploy("./navbar", "navbar", "1.0.0", { expiresInSeconds: 86400 });
315
+ ```
316
+
317
+ ### Manifest-based Delivery
318
+
319
+ Tokens, projectId, and CDN URLs never appear in HTML. Fetched at runtime from `wh-manifest.json`.
320
+
321
+ ---
322
+
323
+ ## Edge Worker (Cloudflare Workers)
324
+
325
+ Runs at the edge before S3:
326
+
327
+ - HMAC token validation
328
+ - Version resolution (`latest` → `1.2.0` from KV)
329
+ - Geo-based routing (India → ap-south-1, Europe → eu-west-1)
330
+ - Rate limiting (100 req/min per IP)
331
+
332
+ ```bash
333
+ wh init # answer yes to edge worker setup
334
+ cd edge && wrangler deploy
335
+ ```
336
+
337
+ Update `cdn.url` in `webhanger.config.json` to your worker URL — all requests now go through the edge.
338
+
339
+ ---
340
+
341
+ ## Multi-CDN Failover
342
+
343
+ ```json
344
+ {
345
+ "cdn": {
346
+ "url": "https://primary.cloudfront.net",
347
+ "fallbacks": [
348
+ "https://fallback.r2.dev",
349
+ "https://backup.b-cdn.net"
350
+ ]
351
+ }
352
+ }
353
+ ```
354
+
355
+ SDK tries each URL in order. If primary fails, automatically falls back — zero code changes needed.
356
+
357
+ ---
358
+
359
+ ## Browser SDK
360
+
361
+ ### Zero-code (recommended)
362
+
363
+ ```html
364
+ <script src="https://unpkg.com/webhanger-front@latest/browser.min.js"></script>
365
+ <script>WebHangerFront.initialize("./wh-manifest.json");</script>
366
+
367
+ <wh-component name="navbar"></wh-component>
368
+ <wh-component name="hero"></wh-component>
369
+ <wh-component name="footer" sandbox></wh-component>
370
+ ```
371
+
372
+ ### Manual load
373
+
374
+ ```js
375
+ WebHangerFront.load(
376
+ cdnUrl, // string or array (multi-CDN)
377
+ projectId, // decrypt key
378
+ token, // HMAC token
379
+ expires, // unix timestamp, 0 = never
380
+ selector, // CSS selector, default "[data-wh]"
381
+ onSignal, // optional signal callback
382
+ deps, // optional pre-resolved deps array
383
+ options // optional options object
384
+ );
385
+ ```
386
+
387
+ ### Lifecycle hooks
388
+
389
+ ```js
390
+ WebHangerFront.load(url, pid, token, 0, "[data-wh]", null, [], {
391
+ beforeMount: ({ html }) => showSpinner(),
392
+ afterMount: ({ target }) => hideSpinner(),
393
+ onError: (err) => showFallback(err),
394
+ sandbox: true, // Shadow DOM isolation
395
+ allowedDomains: ["mysite.com"] // domain restriction
396
+ });
397
+ ```
398
+
399
+ ### Signal callback
400
+
401
+ ```js
402
+ WebHangerFront.load(url, pid, token, 0, "[data-wh]", ({ stage, ...detail }) => {
403
+ // stages: start → fetching → assets → deps → injecting → done | error
404
+ console.log(stage, detail.time, detail.source);
405
+ });
406
+ ```
407
+
408
+ ### Plugin system
409
+
410
+ ```js
411
+ WebHangerFront.use({
412
+ install({ on, emit }) {
413
+ on("load", ({ time, source }) => analytics.track("load", { time, source }));
414
+ on("error", ({ message }) => errorTracker.capture(message));
415
+ on("metric", ({ name, value }) => dashboard.update(name, value));
416
+ }
417
+ });
418
+ ```
419
+
420
+ ### Observability
421
+
422
+ ```js
423
+ WebHangerFront.on("load", ({ time, source }) => console.log(time, source));
424
+ WebHangerFront.on("metric", ({ name, value }) => console.log(name, value));
425
+
426
+ console.log(WebHangerFront.metrics);
427
+ // { loads: 5, cacheHits: 3, errors: 0, totalTime: 420 }
428
+ ```
429
+
430
+ ### Hard flush
431
+
432
+ ```js
433
+ await WebHangerFront.clearCache();
434
+ // Clears: localStorage, IndexedDB, SW caches, sessionStorage, unregisters SW
435
+ ```
436
+
437
+ ---
438
+
439
+ ## Caching
440
+
441
+ | Layer | Used for |
442
+ |---|---|
443
+ | `localStorage` | Components < 50KB |
444
+ | `IndexedDB` | Components ≥ 50KB |
445
+ | Service Worker | Offline fallback |
446
+
447
+ **Stale-while-revalidate** — returns cached version instantly, refreshes in background.
448
+
449
+ ---
450
+
451
+ ## Node.js API
452
+
453
+ ```js
454
+ import { WebHanger } from "webhanger";
455
+ const wh = new WebHanger();
456
+
457
+ // Deploy
458
+ const result = await wh.deploy("./components/navbar", "navbar", "1.0.0", {
459
+ expiresInSeconds: 86400, // optional
460
+ token: "custom-token", // optional
461
+ dependencies: ["chart@1.0.0"]
462
+ });
463
+ // { cdnUrl, cdnUrls, token, expires, dependencies }
464
+
465
+ // Resolve
466
+ const comp = await wh.resolve("navbar", "1.0.0");
467
+
468
+ // Rotate token without redeploying
469
+ await wh.resign("navbar", "1.0.0", { expiresInSeconds: 3600 });
470
+
471
+ // Delete from storage
472
+ await wh.remove("navbar", "1.0.0");
473
+
474
+ // Get config
475
+ const config = wh.getConfig();
476
+ ```
477
+
478
+ ### Named exports
479
+
480
+ ```js
481
+ import {
482
+ bundle, encrypt, decrypt, integrityHash,
483
+ signUrl, verifyToken, generateSecretKey,
484
+ upload, remove,
485
+ registerComponent, getComponent,
486
+ deploy, resolveGraph,
487
+ convert, analyzeComponent,
488
+ build,
489
+ grantAccess, revokeAccess, checkPermission, listAccess, generateApiKey,
490
+ provisionBucket, provisionCloudFront,
491
+ loadConfig
492
+ } from "webhanger";
493
+ ```
494
+
495
+ ---
496
+
497
+ ## Storage Providers
498
+
499
+ | Provider | Notes |
500
+ |---|---|
501
+ | `s3` | AWS S3 — auto-provisions bucket + CloudFront |
502
+ | `r2` | Cloudflare R2 — zero egress fees |
503
+ | `minio` | Self-hosted MinIO — S3-compatible |
504
+ | `local` | Local disk — dev/testing only |
505
+
506
+ ## Database Providers
507
+
508
+ | Provider | Notes |
509
+ |---|---|
510
+ | `firebase` | Firebase Firestore — free tier, real-time |
511
+ | `supabase` | Supabase Postgres — open source |
512
+ | `mongodb` | MongoDB Atlas — flexible documents |
513
+
514
+ ---
515
+
516
+ ## `webhanger.config.json`
517
+
518
+ ```json
519
+ {
520
+ "project": "my-app",
521
+ "projectId": "wh_1234567890",
522
+ "secretKey": "64-char-hex-secret",
523
+ "webHangerVersion": "1.0.0",
524
+ "storage": {
525
+ "provider": "s3",
526
+ "accessKey": "...",
527
+ "secretKey": "...",
528
+ "bucket": "my-bucket",
529
+ "region": "ap-south-1",
530
+ "distributionId": "EXXXXX"
531
+ },
532
+ "cdn": {
533
+ "url": "https://primary.cloudfront.net",
534
+ "fallbacks": ["https://fallback.r2.dev"]
535
+ },
536
+ "db": {
537
+ "provider": "firebase",
538
+ "serviceAccountPath": "./firebase-service-account.json"
539
+ }
540
+ }
541
+ ```
542
+
543
+ > Keep this file private. Never commit it. Add to `.gitignore`.
544
+
545
+ ---
546
+
547
+ ## Architecture
548
+
549
+ ```
550
+ Developer
551
+ └── wh ship ./components ./docs
552
+ ├── wh analyze → detect Tailwind, GSAP, deps
553
+ ├── wh bundle → html + css + js → single payload
554
+ ├── AES-256-GCM → encrypt each chunk (SHA-256 key)
555
+ ├── SHA-256 hash → integrity fingerprint
556
+ ├── S3 upload → store encrypted payload
557
+ ├── HMAC sign → project-scoped signed URL
558
+ ├── Firestore → register metadata + dep graph
559
+ ├── wh build → minify HTML, inline assets
560
+ └── wh zip → deploy.zip ready for upload
561
+
562
+ Browser
563
+ └── <wh-component name="navbar">
564
+ ├── fetch wh-manifest.json
565
+ ├── check token expiry
566
+ ├── stale-while-revalidate cache
567
+ ├── fetch from CloudFront (or Edge Worker)
568
+ │ └── Edge: validate token + geo route + rate limit
569
+ ├── multi-CDN failover if primary fails
570
+ ├── load CDN assets (Tailwind, GSAP, etc.)
571
+ ├── resolve + load dependency graph
572
+ ├── AES-256-GCM decrypt in memory
573
+ ├── SHA-256 integrity verify
574
+ ├── domain restriction check
575
+ ├── inject CSS → HTML → JS (or Shadow DOM)
576
+ ├── fire lifecycle hooks
577
+ └── emit metrics + plugin events
578
+ ```
579
+
580
+ ---
581
+
582
+ ## Real-World Use Cases
583
+
584
+ - **Enterprise micro-frontends** — shared UI across 50+ apps, update once
585
+ - **Education platforms** — push UI updates to all school sites instantly
586
+ - **Low-bandwidth regions** — cache once, serve offline via Service Worker
587
+ - **Security platforms** — inject warnings/banners dynamically across sites
588
+ - **White-label SaaS** — per-tenant component customization
589
+
590
+ ---
591
+
592
+ ## License
593
+
594
+ ISC