@despia/local 1.0.0

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,748 @@
1
+ # @despia/local
2
+
3
+ Universal build plugin to generate `despia/local.json` manifest for [Despia](https://despia.com) web-native apps. This manifest enables Despia Local Server, which runs your web app from a secure local HTTPS server on-device, providing full offline functionality with seamless updates.
4
+
5
+ **Note**: Despia Local Server is optional. Normally, the Despia runtime can run your web app directly from a URL. Despia Local Server is for developers who need extra performance and full true native offline support.
6
+
7
+ **Store Compliant**: Despia Local Server is fully compliant with Apple App Store and Google Play Store guidelines. It downloads and caches web content (HTML, CSS, JavaScript) for offline display in a WebView—identical to how web browsers work. No native code or executables are downloaded. See [Store Compliance & Security](#store-compliance--security) section for detailed compliance information.
8
+
9
+ ## Features
10
+
11
+ - **Universal Support** - Works with Vite, Webpack, Rollup, Next.js, Nuxt, SvelteKit, Astro, Remix, esbuild, Parcel, and more
12
+ - **Zero Dependencies** - Uses only Node.js built-in modules
13
+ - **Automatic Asset Discovery** - Collects all output files (JS, CSS, images, fonts, HTML, etc.)
14
+ - **Root-Relative Paths** - Formats all paths as root-relative (starting with `/`)
15
+ - **Sorted Output** - Alphabetically sorted paths for consistent builds
16
+ - **Standalone Script** - Can be used with any build system via CLI
17
+
18
+ ## About Despia Local Server
19
+
20
+ **Note**: Despia Local Server is optional. Normally, the Despia runtime can run your web app directly from a URL. Despia Local Server is for developers who need extra performance and full true native offline support.
21
+
22
+ Despia Local Server enables your web app to run entirely from a secure local HTTPS server on-device, providing a native app experience with full offline functionality.
23
+
24
+ ### Architecture
25
+
26
+ The Despia native container consists of:
27
+
28
+ - **Native iOS/Android Container**: The native binary submitted to App Store/Play Store
29
+ - WebView for UI rendering (WKWebView on iOS, WebView on Android)
30
+ - JavaScript bridge for native API access (exposes native capabilities to web content via [`despia-native`](https://www.npmjs.com/package/despia-native))
31
+ - Local HTTPS server infrastructure (runs on-device only)
32
+ - Storage and update management systems
33
+
34
+ - **Web Content Layer** (downloaded and cached):
35
+ - HTML, CSS, JavaScript files
36
+ - Images, fonts, and other static assets
37
+ - Served from `https://localhost` after initial hydration
38
+
39
+ **Key Architecture Principles:**
40
+ - Web content updates (HTML/CSS/JS only)
41
+ - JavaScript bridge provides access to native APIs already in the binary
42
+ - No native code execution or downloads
43
+ - No executable binaries downloaded
44
+ - All native code fixed at App Store/Play Store submission
45
+
46
+ ### How It Works
47
+
48
+ **Initial Installation**
49
+ The App Store/Play Store binary contains the native iOS/Android container (see [Architecture](#architecture) above):
50
+ - Native code (Swift/Kotlin) for platform integration
51
+ - WebView component for UI rendering
52
+ - JavaScript bridge for native API access (exposes native capabilities to web content via [`despia-native`](https://www.npmjs.com/package/despia-native))
53
+ - Local HTTPS server infrastructure (runs on-device only)
54
+ - Storage and update management systems
55
+ - No web app assets (HTML, CSS, JavaScript) are bundled in the binary
56
+
57
+ This approach keeps initial install sizes minimal and allows for rapid iteration of web UI without requiring app store resubmissions. **Important**: All native code, the JavaScript bridge, and app functionality are fixed at submission time and cannot be changed. Only web content (HTML/CSS/JS) can be updated.
58
+
59
+ **First Launch Hydration**
60
+ On first app launch, Despia securely downloads your latest web build (HTML, CSS, JavaScript, images, fonts) from your repository and stores it locally on the device. The local HTTPS server then begins serving your web content from `https://localhost`, providing a stable, secure origin for your web application.
61
+
62
+ **Note on Compliance**: This process downloads and caches web content files only. No native code, executables, or binary files are downloaded. The JavaScript executes within the WebView's sandbox, identical to how Safari or Chrome render web pages.
63
+
64
+ **Offline Operation**
65
+ After the initial hydration, your app operates completely offline:
66
+ - Instant app boot times (no network requests)
67
+ - No network connectivity required
68
+ - Full SPA routing and navigation
69
+ - Deep linking support
70
+ - Stable HTTPS origin (`https://localhost`) for security
71
+
72
+ If the device goes offline permanently, the app continues to function using the last hydrated version, ensuring reliability even without connectivity.
73
+
74
+ **Seamless Updates**
75
+ When connectivity is available, Despia checks for updates in the background and downloads new web builds atomically. Updates are applied on the next app launch, ensuring:
76
+ - No partial or broken states
77
+ - Atomic updates for reliability
78
+ - No app store resubmission required for web UI changes
79
+ - Background updates that don't interrupt user experience
80
+
81
+ **Important**: Updates only change web content (HTML, CSS, JavaScript). Native code, permissions, and app functionality remain unchanged from the original App Store/Play Store submission.
82
+
83
+ ### Store Compliance & Security
84
+
85
+ **Compliance Summary for App Reviewers:**
86
+
87
+ Despia Local Server downloads and caches web content files (HTML, CSS, JavaScript, images) for offline display in a WebView. This is identical to how web browsers (Safari, Chrome) download and render web pages.
88
+
89
+ **Key Compliance Points:**
90
+ - No native code is downloaded or executed
91
+ - No executable binaries (`.so`, `.dylib`, `.dex`) are downloaded
92
+ - All native code and native API capabilities are fixed at App Store/Play Store submission
93
+ - JavaScript executes only within WebView sandbox (same as browsers)
94
+ - All content served from on-device `localhost` server
95
+ - App permissions and which native APIs are available cannot be changed
96
+ - Web UI can be updated to use existing native APIs (already in binary) in new ways
97
+
98
+ This approach is explicitly permitted under both App Store and Play Store policies, as it involves web content rendering, not native code execution.
99
+
100
+ #### Compliance Validation Tools
101
+
102
+ For conditionally rendering UI elements based on the Despia Native SDK runtime version, consider using [`despia-version-guard`](https://www.npmjs.com/package/despia-version-guard), a recommended tool in the Despia ecosystem. This framework-agnostic solution helps ensure store compliance and reliability by:
103
+
104
+ - Conditionally rendering UI based on `window.bundleNumber` (Despia Native SDK runtime version)
105
+ - Version-gating major UI shifts to maintain store compliance
106
+ - Preventing broken UI when Despia adds new runtime features that older users don't have
107
+ - Supporting React, Vue, Angular, Svelte, and Vanilla JS/Web Components
108
+
109
+ `despia-version-guard` complements `@despia/local` by enabling you to build conditional UI for major version shifts while remaining store-compliant. This is particularly useful for:
110
+
111
+ - **Major UI Shifts**: Show new UI only to users with the required minimum version
112
+ - **Deprecation**: Hide legacy features when version exceeds maximum
113
+ - **Upgrade Prompts**: Conditionally show upgrade buttons based on version
114
+ - **Store Compliance**: Ensure app review compatibility by version-gating major changes
115
+ - **Enterprise Reliability**: Prevent broken UI when Despia adds new runtime features
116
+
117
+ **Installation:**
118
+ ```bash
119
+ npm install despia-version-guard
120
+ ```
121
+
122
+ **Example Usage (React):**
123
+ ```jsx
124
+ import { VersionGuard } from 'despia-version-guard';
125
+
126
+ // Only show this feature if version is 21.0.3 or higher
127
+ <VersionGuard min_version="21.0.3">
128
+ <NewFeatureComponent />
129
+ </VersionGuard>
130
+ ```
131
+
132
+ See the [`despia-version-guard` documentation](https://www.npmjs.com/package/despia-version-guard) for framework-specific usage and API details.
133
+
134
+ ---
135
+
136
+ Despia Local Server is fully compliant with both Apple App Store and Google Play Store guidelines. This section explains the compliance in detail.
137
+
138
+ #### Apple App Store Compliance
139
+
140
+ **Guideline 3.3.2 - Code Execution:**
141
+ > "Apps must not download, install, or execute code which introduces or changes features or functionality of the app, including other apps."
142
+
143
+ **Compliance Statement:**
144
+ Despia Local Server complies with this guideline because:
145
+
146
+ 1. **No Native Code Execution**: The app does not download, install, or execute any native code (Swift, Objective-C, C++, etc.). All native code is fixed at App Store submission time and cannot be modified.
147
+
148
+ 2. **Web Content Rendering Only**: Only web content assets (HTML, CSS, JavaScript) are downloaded and rendered. This is identical to how Safari, Chrome, and other web browsers load and display web content. The JavaScript executes within the WebView's sandbox, not as native code.
149
+
150
+ 3. **Fixed Native Functionality**: All native capabilities, permissions, and native API implementations are determined at submission time. The downloaded web content cannot change:
151
+ - App permissions (declared in Info.plist)
152
+ - Which native APIs are available in the binary
153
+ - Native API implementations
154
+ - App Store metadata
155
+ - Binary behavior
156
+ - System integration
157
+
158
+ **However**, the web UI can be updated to use existing native APIs in new ways. For example, if Face ID is already implemented in the native code and exposed through the WebView bridge, the web UI can be updated to call Face ID from new parts of the app. This is compliant because the native capability already exists in the submitted binary—only the web UI's usage of it changes.
159
+
160
+ **Note**: This follows the same pattern as [Expo](https://expo.dev), which has been generally accepted by app stores. However, Apple's interpretation of "feature changes" under Guideline 3.3.2 is subjective, and your app could still face review challenges. It's recommended to be conservative with updates that significantly change app behavior, even when using existing native APIs.
161
+
162
+ 4. **On-Device Execution**: All web content is served from a local HTTPS server running on-device (`localhost`). No remote code execution occurs.
163
+
164
+ **This approach is explicitly permitted** under App Store guidelines, as evidenced by:
165
+ - Safari and other browsers downloading and rendering web content
166
+ - Apps using WKWebView to display web content
167
+ - Enterprise apps using web-based UIs
168
+ - Apps that cache web content for offline use
169
+
170
+ #### Google Play Store Compliance
171
+
172
+ **Play Store Policy - Malicious Behavior:**
173
+ > "Apps must not download executable code (e.g., dex, JAR, .so files) from a source other than Google Play."
174
+
175
+ **Compliance Statement:**
176
+ Despia Local Server complies with this policy because:
177
+
178
+ 1. **No Executable Code Downloads**: The app does not download any executable code (`.dex`, `.jar`, `.so`, `.apk`, or native binaries). Only web content files (HTML, CSS, JavaScript, images, fonts) are downloaded.
179
+
180
+ 2. **Web Content Rendering**: JavaScript files are executed within the WebView's JavaScript engine, not as native executables. This is the same mechanism used by Chrome and other Android browsers.
181
+
182
+ 3. **Fixed Native Binary**: The APK/AAB submitted to Google Play contains all native code. No native code is downloaded or executed after installation.
183
+
184
+ 4. **Sandboxed Execution**: All web content executes within the WebView's security sandbox, with permissions and capabilities fixed at APK submission time.
185
+
186
+ **However**, the web UI can be updated to use existing native APIs in new ways. For example, if biometric authentication is already implemented in the native code and exposed through the WebView bridge, the web UI can be updated to call it from new parts of the app. This is compliant because the native capability already exists in the submitted APK—only the web UI's usage of it changes.
187
+
188
+ **This approach is explicitly permitted** under Play Store policies, as evidenced by:
189
+ - Chrome and other browsers rendering web content
190
+ - Apps using WebView to display web content
191
+ - Progressive Web Apps (PWAs) that cache content
192
+ - Apps that update UI via web technologies
193
+
194
+ #### Technical Implementation Details
195
+
196
+ **What Gets Downloaded:**
197
+ - HTML files (markup)
198
+ - CSS files (styling)
199
+ - JavaScript files (executed in WebView sandbox)
200
+ - Images, fonts, and other static assets
201
+ - Native code (Swift, Kotlin, C++, etc.) - NOT downloaded
202
+ - Executable binaries (`.so`, `.dylib`, `.dex`, etc.) - NOT downloaded
203
+ - Native libraries or frameworks - NOT downloaded
204
+
205
+ **What Cannot Change:**
206
+ - Native app permissions (declared in Info.plist/AndroidManifest.xml)
207
+ - App Store/Play Store metadata
208
+ - Native API implementations and capabilities
209
+ - System integration capabilities
210
+ - App signing and security model
211
+ - Which native APIs are available in the binary
212
+
213
+ **What CAN Change (Compliant Updates):**
214
+ - **Usage of Existing Native APIs**: The web UI can be updated to use native APIs that are already built into the binary and exposed through the WebView bridge. For example:
215
+ - If Face ID/Touch ID is already implemented in the native code, the web UI can be updated to call it from new parts of the app
216
+ - If camera access is already granted, the web UI can be updated to use it in new features
217
+ - If location services are already available, the web UI can be updated to request location in new screens
218
+ - Any native capability that exists in the submitted binary can be exposed to new parts of the web UI via updates
219
+
220
+ **Important Distinction:**
221
+ - **Compliant**: Updating web content to use existing native APIs (e.g., adding Face ID to a new login screen when Face ID is already in the binary)
222
+ - **Not Compliant**: Downloading new native code or adding new native capabilities that weren't in the original submission
223
+
224
+ This is compliant because:
225
+ 1. The native API/capability already exists in the binary submitted to the stores
226
+ 2. The WebView bridge was already configured to expose these APIs at submission time
227
+ 3. Only the web UI is changing to call existing native functions
228
+ 4. No new native code, permissions, or capabilities are being added
229
+
230
+ This follows the same pattern as established frameworks like [Expo](https://expo.dev), which uses JavaScript bridges to expose native APIs to web content and has been generally accepted by app stores.
231
+
232
+ **Important Disclaimer**: While this approach is technically compliant and follows established patterns, Apple's interpretation of Guideline 3.3.2 regarding "feature changes" is subjective. Apps using this pattern have been generally accepted, but your app could still face review challenges, especially if updates significantly change app behavior or functionality. It's recommended to:
233
+ - Be conservative with updates that dramatically change user-facing features
234
+ - Test thoroughly before submitting significant UI/UX changes
235
+ - Be prepared to explain how updates use existing native APIs if questioned during review
236
+ - Consider submitting major feature additions through the normal App Store review process when possible
237
+
238
+ **Security Model:**
239
+ - All web content is served from `https://localhost` (on-device only)
240
+ - WebView sandbox enforces same-origin policy
241
+ - No network access to external servers after initial hydration
242
+ - Content Security Policy (CSP) can be enforced
243
+ - All execution happens within WebView's security boundaries
244
+
245
+ #### Comparison to Similar Technologies
246
+
247
+ This approach is conceptually and technically identical to:
248
+
249
+ 1. **Web Browsers** (Safari, Chrome): Download and render web content from servers
250
+ 2. **Expo**: Uses JavaScript bridge to expose native APIs to React Native web content
251
+ 3. **Electron Apps**: Update web UI content without changing native code
252
+ 5. **Progressive Web Apps**: Cache web content for offline use
253
+ 6. **Enterprise MDM Solutions**: Deploy web-based UIs to managed devices
254
+ 7. **Hybrid Mobile Apps**: Use WebView to display web content
255
+
256
+ The key distinction that ensures compliance: **Web content rendering is not code execution in the App Store/Play Store policy sense**. Native code execution is what the policies restrict, and Despia does not perform any native code execution.
257
+
258
+ **Note**: Expo follows the same pattern of exposing native APIs through JavaScript bridges and has been generally accepted by app stores. However, as with any approach involving web content updates, there's always a possibility of review challenges depending on how Apple interprets "feature changes" in specific cases.
259
+
260
+ #### Practical Example: Using Existing Native APIs
261
+
262
+ To illustrate compliance with using existing native APIs:
263
+
264
+ **Scenario**: An app is submitted with Face ID/Touch ID already implemented in the native code and exposed through the WebView bridge. The initial web UI only uses Face ID on the login screen.
265
+
266
+ **Compliant Update**: The web UI can be updated via OTA to also use Face ID on:
267
+ - A new settings screen
268
+ - A payment confirmation screen
269
+ - Any other new feature
270
+
271
+ **Why This Is Compliant:**
272
+ 1. Face ID native code was already in the binary at App Store submission
273
+ 2. The WebView bridge was already configured to expose Face ID to JavaScript
274
+ 3. Only the web UI JavaScript is changing to call the existing native function
275
+ 4. No new native code, permissions, or capabilities are being added
276
+
277
+ **Not Compliant**: Downloading new native code to add Face ID support that wasn't in the original submission.
278
+
279
+ This is analogous to:
280
+ - A web browser using JavaScript to call `navigator.geolocation` in different parts of a website
281
+ - Expo apps updating React Native code to use existing native modules in new screens
282
+ - An Electron app updating its web UI to use existing Electron APIs in new features
283
+ - A hybrid app using existing Cordova plugins in new screens
284
+
285
+ **Review Considerations**: While this pattern is technically compliant and follows established frameworks like Expo, Apple's interpretation of Guideline 3.3.2 can be subjective. If your update significantly changes app behavior or introduces major new user-facing features, consider whether it might be better to submit through the normal App Store review process to avoid potential challenges.
286
+
287
+ #### Developer Responsibility
288
+
289
+ When submitting apps using Despia Local Server:
290
+
291
+ 1. **App Store Submission**: Clearly state that the app uses a WebView to display web content that may be cached for offline use. This is standard practice and does not require special disclosure.
292
+
293
+ 2. **Play Store Submission**: No special disclosure required. The app uses standard Android WebView components to display web content.
294
+
295
+ 3. **Privacy Policy**: If your app collects data through the web content, ensure your privacy policy covers this, as required by both stores.
296
+
297
+ 4. **Content Guidelines**: Ensure all web content complies with App Store and Play Store content policies, as the web content is part of your app submission.
298
+
299
+ 5. **Update Strategy**: Be mindful that while using existing native APIs in new ways is technically compliant (following the same pattern as Expo), Apple's interpretation of "feature changes" under Guideline 3.3.2 is subjective. Consider:
300
+ - Being conservative with updates that dramatically change app behavior
301
+ - Testing thoroughly before deploying significant UI/UX changes
302
+ - Being prepared to explain how updates use existing native APIs if questioned
303
+ - Submitting major feature additions through normal App Store review when appropriate
304
+
305
+ 6. **Version-Based UI Rendering**: Consider using [`despia-version-guard`](https://www.npmjs.com/package/despia-version-guard) to conditionally render UI elements based on the Despia Native SDK runtime version. This helps maintain store compliance by version-gating major changes and prevents broken UI for users with older runtime versions.
306
+
307
+ ### The `local.json` Manifest
308
+
309
+ The `despia/local.json` manifest generated by this plugin serves as an asset inventory for Despia Local Server. It contains a complete list of all assets that need to be cached locally, enabling:
310
+
311
+ - **Complete Asset Discovery**: Ensures all files (JS, CSS, images, fonts, HTML) are properly cached
312
+ - **Efficient Updates**: Allows Despia to determine which assets have changed between builds
313
+ - **Reliable Offline Operation**: Guarantees all required assets are available offline
314
+ - **Atomic Updates**: Enables safe, complete updates without partial states
315
+
316
+ This manifest is automatically used by Despia during the hydration and update processes to ensure your app has everything it needs to run offline.
317
+
318
+ ## Installation
319
+
320
+ ```bash
321
+ npm install --save-dev @despia/local
322
+ ```
323
+
324
+ ## Quick Start
325
+
326
+ ### Option 1: Framework-Specific Plugin (Recommended)
327
+
328
+ Choose the plugin for your framework below.
329
+
330
+ ### Option 2: Standalone Script (Universal)
331
+
332
+ Add to your `package.json`:
333
+
334
+ ```json
335
+ {
336
+ "scripts": {
337
+ "build": "your-build-command",
338
+ "postbuild": "despia-local"
339
+ }
340
+ }
341
+ ```
342
+
343
+ Or run manually:
344
+
345
+ ```bash
346
+ npx despia-local [outputDir] [entryHtml]
347
+ ```
348
+
349
+ ## Framework Support
350
+
351
+ ### Vite
352
+
353
+ ```javascript
354
+ // vite.config.js
355
+ import { defineConfig } from 'vite';
356
+ import { despiaOfflinePlugin } from '@despia/local/vite';
357
+
358
+ export default defineConfig({
359
+ plugins: [
360
+ // ... your other plugins
361
+ despiaOfflinePlugin({
362
+ outDir: 'dist', // optional, default: 'dist'
363
+ entryHtml: 'index.html' // optional, default: 'index.html'
364
+ })
365
+ ]
366
+ });
367
+ ```
368
+
369
+ **Works with:**
370
+ - Vite + React
371
+ - Vite + Vue
372
+ - Vite + Svelte
373
+ - Vite + Preact
374
+ - Vite + Lit
375
+ - Any Vite-based project
376
+
377
+ ### Webpack
378
+
379
+ ```javascript
380
+ // webpack.config.js
381
+ const DespiaOfflinePlugin = require('@despia/local/webpack');
382
+
383
+ module.exports = {
384
+ // ... your config
385
+ plugins: [
386
+ // ... your other plugins
387
+ new DespiaOfflinePlugin({
388
+ outDir: 'dist', // optional, default: 'dist'
389
+ entryHtml: 'index.html' // optional, default: 'index.html'
390
+ })
391
+ ]
392
+ };
393
+ ```
394
+
395
+ **Works with:**
396
+ - Create React App (eject or CRACO)
397
+ - Vue CLI
398
+ - Angular (custom webpack config)
399
+ - Any webpack-based project
400
+
401
+ ### Rollup
402
+
403
+ ```javascript
404
+ // rollup.config.js
405
+ import { despiaOffline } from '@despia/local/rollup';
406
+
407
+ export default {
408
+ // ... your config
409
+ plugins: [
410
+ // ... your other plugins
411
+ despiaOffline({
412
+ outDir: 'dist',
413
+ entryHtml: 'index.html'
414
+ })
415
+ ]
416
+ };
417
+ ```
418
+
419
+ ### Next.js
420
+
421
+ ```javascript
422
+ // next.config.js
423
+ const withDespiaOffline = require('@despia/local/next');
424
+
425
+ module.exports = withDespiaOffline({
426
+ entryHtml: 'index.html',
427
+ outDir: '.next' // or 'out' for static export
428
+ })({
429
+ // your Next.js config
430
+ });
431
+ ```
432
+
433
+ **For static export:**
434
+
435
+ ```javascript
436
+ // next.config.js
437
+ const withDespiaOffline = require('@despia/local/next');
438
+
439
+ module.exports = withDespiaOffline({
440
+ outDir: 'out', // Next.js static export directory
441
+ entryHtml: 'index.html'
442
+ })({
443
+ output: 'export',
444
+ // ... rest of config
445
+ });
446
+ ```
447
+
448
+ **Alternative: Webpack Plugin Approach**
449
+
450
+ ```javascript
451
+ // next.config.js
452
+ const DespiaOfflinePlugin = require('@despia/local/webpack');
453
+
454
+ module.exports = {
455
+ webpack: (config) => {
456
+ config.plugins.push(
457
+ new DespiaOfflinePlugin({ outDir: '.next' })
458
+ );
459
+ return config;
460
+ }
461
+ };
462
+ ```
463
+
464
+ ### Nuxt
465
+
466
+ ```javascript
467
+ // nuxt.config.js
468
+ export default {
469
+ modules: ['@despia/local/nuxt'],
470
+ despiaOffline: {
471
+ entryHtml: 'index.html'
472
+ }
473
+ }
474
+ ```
475
+
476
+ **Or as a local module:**
477
+
478
+ ```javascript
479
+ // modules/despia-offline.js
480
+ import DespiaOfflineModule from '@despia/local/nuxt';
481
+ export default DespiaOfflineModule;
482
+ ```
483
+
484
+ ### SvelteKit
485
+
486
+ ```javascript
487
+ // vite.config.js
488
+ import { sveltekit } from '@sveltejs/kit/vite';
489
+ import { despiaOfflineSvelteKit } from '@despia/local/sveltekit';
490
+
491
+ export default {
492
+ plugins: [
493
+ sveltekit(),
494
+ despiaOfflineSvelteKit({
495
+ entryHtml: 'index.html'
496
+ })
497
+ ]
498
+ };
499
+ ```
500
+
501
+ ### Astro
502
+
503
+ ```javascript
504
+ // astro.config.mjs
505
+ import { defineConfig } from 'astro/config';
506
+ import despiaOffline from '@despia/local/astro';
507
+
508
+ export default defineConfig({
509
+ integrations: [
510
+ despiaOffline({
511
+ entryHtml: 'index.html',
512
+ outDir: 'dist'
513
+ })
514
+ ]
515
+ });
516
+ ```
517
+
518
+ ### Remix
519
+
520
+ ```javascript
521
+ // vite.config.js (Remix uses Vite)
522
+ import { remix } from '@remix-run/dev';
523
+ import { despiaOfflineRemix } from '@despia/local/remix';
524
+
525
+ export default {
526
+ plugins: [
527
+ remix(),
528
+ despiaOfflineRemix({
529
+ entryHtml: 'index.html',
530
+ outDir: 'build/client'
531
+ })
532
+ ]
533
+ };
534
+ ```
535
+
536
+ ### esbuild
537
+
538
+ ```javascript
539
+ import { build } from 'esbuild';
540
+ import { despiaOfflineEsbuild } from '@despia/local/esbuild';
541
+
542
+ await build({
543
+ entryPoints: ['src/index.js'],
544
+ outdir: 'dist',
545
+ plugins: [
546
+ despiaOfflineEsbuild({
547
+ outDir: 'dist',
548
+ entryHtml: 'index.html'
549
+ })
550
+ ]
551
+ });
552
+ ```
553
+
554
+ ### Parcel
555
+
556
+ ```json
557
+ // .parcelrc
558
+ {
559
+ "extends": "@parcel/config-default",
560
+ "plugins": {
561
+ "@despia/local/parcel": true
562
+ }
563
+ }
564
+ ```
565
+
566
+ **Or in package.json:**
567
+
568
+ ```json
569
+ {
570
+ "parcel": {
571
+ "plugins": {
572
+ "@despia/local/parcel": true
573
+ }
574
+ }
575
+ }
576
+ ```
577
+
578
+ ### Other Build Tools
579
+
580
+ For any build tool not listed above, use the standalone CLI script:
581
+
582
+ ```json
583
+ {
584
+ "scripts": {
585
+ "build": "your-build-command",
586
+ "postbuild": "despia-local dist index.html"
587
+ }
588
+ }
589
+ ```
590
+
591
+ ## Configuration Options
592
+
593
+ All plugins accept the following options:
594
+
595
+ | Option | Type | Default | Description |
596
+ |--------|------|---------|-------------|
597
+ | `outDir` | `string` | `'dist'` | Output directory to scan for assets |
598
+ | `entryHtml` | `string` | `'index.html'` | Entry HTML filename to include in manifest |
599
+
600
+ ## Output Format
601
+
602
+ The generated `despia/local.json` file contains a sorted JSON array of root-relative paths:
603
+
604
+ ```json
605
+ [
606
+ "/assets/app.abc123.css",
607
+ "/assets/app.def456.js",
608
+ "/assets/logo.xyz789.png",
609
+ "/index.html"
610
+ ]
611
+ ```
612
+
613
+ ## Examples
614
+
615
+ ### React + Vite
616
+
617
+ ```javascript
618
+ // vite.config.js
619
+ import { defineConfig } from 'vite';
620
+ import react from '@vitejs/plugin-react';
621
+ import { despiaOfflinePlugin } from '@despia/local/vite';
622
+
623
+ export default defineConfig({
624
+ plugins: [
625
+ react(),
626
+ despiaOfflinePlugin()
627
+ ]
628
+ });
629
+ ```
630
+
631
+ ### Vue + Vite
632
+
633
+ ```javascript
634
+ // vite.config.js
635
+ import { defineConfig } from 'vite';
636
+ import vue from '@vitejs/plugin-vue';
637
+ import { despiaOfflinePlugin } from '@despia/local/vite';
638
+
639
+ export default defineConfig({
640
+ plugins: [
641
+ vue(),
642
+ despiaOfflinePlugin()
643
+ ]
644
+ });
645
+ ```
646
+
647
+ ### Angular
648
+
649
+ ```javascript
650
+ // angular.json - Add to build configuration
651
+ {
652
+ "projects": {
653
+ "your-app": {
654
+ "architect": {
655
+ "build": {
656
+ "builder": "@angular-builders/custom-webpack:browser",
657
+ "options": {
658
+ "customWebpackConfig": {
659
+ "path": "./webpack.config.js"
660
+ }
661
+ }
662
+ }
663
+ }
664
+ }
665
+ }
666
+ }
667
+ ```
668
+
669
+ ```javascript
670
+ // webpack.config.js
671
+ const DespiaOfflinePlugin = require('@despia/local/webpack');
672
+
673
+ module.exports = {
674
+ plugins: [
675
+ new DespiaOfflinePlugin({ outDir: 'dist' })
676
+ ]
677
+ };
678
+ ```
679
+
680
+ ### Svelte + Vite
681
+
682
+ ```javascript
683
+ // vite.config.js
684
+ import { defineConfig } from 'vite';
685
+ import { svelte } from '@sveltejs/vite-plugin-svelte';
686
+ import { despiaOfflinePlugin } from '@despia/local/vite';
687
+
688
+ export default defineConfig({
689
+ plugins: [
690
+ svelte(),
691
+ despiaOfflinePlugin()
692
+ ]
693
+ });
694
+ ```
695
+
696
+ ## How the Plugin Works
697
+
698
+ 1. **Hook into Build Process** - The plugin hooks into your build tool's completion event
699
+ 2. **Scan Output Directory** - Recursively scans the build output directory for all files
700
+ 3. **Collect Asset Paths** - Collects paths from both the build tool's bundle metadata and file system
701
+ 4. **Normalize Paths** - Converts all paths to root-relative format (starting with `/`)
702
+ 5. **Include Entry HTML** - Ensures the entry HTML file is always included
703
+ 6. **Sort & Write** - Sorts paths alphabetically and writes to `despia/local.json`
704
+
705
+ The generated manifest is then used by Despia during app hydration and updates to ensure all assets are properly cached for offline operation.
706
+
707
+ ## Notes
708
+
709
+ - The plugin automatically creates the `despia` subdirectory if it doesn't exist
710
+ - All paths are normalized to use forward slashes (`/`) regardless of OS
711
+ - Paths are sorted alphabetically for consistent output across builds
712
+ - The entry HTML file is always included, even if not found in the output directory
713
+ - The `despia` directory itself is excluded from the manifest to avoid recursion
714
+
715
+ ## Troubleshooting
716
+
717
+ ### Manifest not generated
718
+
719
+ 1. Ensure the build completes successfully
720
+ 2. Check that the output directory exists
721
+ 3. Verify the `outDir` option matches your build configuration
722
+ 4. Check console for error messages
723
+
724
+ ### Missing assets in manifest
725
+
726
+ - The plugin scans the entire output directory
727
+ - Ensure assets are copied to the output directory during build
728
+ - Check that file paths are correctly formatted
729
+
730
+ ### Path format issues
731
+
732
+ - All paths are automatically normalized to root-relative format
733
+ - Paths starting with `/` are preserved as-is
734
+ - Windows backslashes are converted to forward slashes
735
+
736
+ ## Contributing
737
+
738
+ Contributions welcome! Please open an issue or submit a pull request.
739
+
740
+ ## License
741
+
742
+ MIT
743
+
744
+ ## Related
745
+
746
+ - [Despia](https://despia.com) - Web-native app platform
747
+ - [despia-native](https://www.npmjs.com/package/despia-native) - JavaScript SDK for accessing native device features (haptics, biometrics, camera, location, push notifications, in-app purchases, and 25+ more APIs)
748
+ - [despia-version-guard](https://www.npmjs.com/package/despia-version-guard) - Framework-agnostic solution for conditionally rendering UI based on Despia Native SDK runtime version