jg-sw 0.0.0-stage → 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.
Files changed (105) hide show
  1. package/CHANGELOG.md +36 -0
  2. package/LICENSE +21 -0
  3. package/README.md +197 -2
  4. package/dist/build/config/config.d.ts +34 -0
  5. package/dist/build/config/config.js +75 -0
  6. package/dist/build/config/config.js.map +1 -0
  7. package/dist/build/config/firebase.d.ts +18 -0
  8. package/dist/build/config/firebase.js +58 -0
  9. package/dist/build/config/firebase.js.map +1 -0
  10. package/dist/build/config/index.d.ts +3 -0
  11. package/dist/build/config/index.js +7 -0
  12. package/dist/build/config/index.js.map +1 -0
  13. package/dist/build/config/schema.d.ts +52 -0
  14. package/dist/build/config/schema.js +65 -0
  15. package/dist/build/config/schema.js.map +1 -0
  16. package/dist/build/index.d.ts +5 -0
  17. package/dist/build/index.js +9 -0
  18. package/dist/build/index.js.map +1 -0
  19. package/dist/build/plugin/index.d.ts +1 -0
  20. package/dist/build/plugin/index.js +3 -0
  21. package/dist/build/plugin/index.js.map +1 -0
  22. package/dist/build/plugin/plugin.d.ts +25 -0
  23. package/dist/build/plugin/plugin.js +76 -0
  24. package/dist/build/plugin/plugin.js.map +1 -0
  25. package/dist/build/precache/index.d.ts +1 -0
  26. package/dist/build/precache/index.js +3 -0
  27. package/dist/build/precache/index.js.map +1 -0
  28. package/dist/build/precache/precache.d.ts +12 -0
  29. package/dist/build/precache/precache.js +66 -0
  30. package/dist/build/precache/precache.js.map +1 -0
  31. package/dist/build/service-worker/index.d.ts +1 -0
  32. package/dist/build/service-worker/index.js +3 -0
  33. package/dist/build/service-worker/index.js.map +1 -0
  34. package/dist/build/service-worker/service-worker.d.ts +58 -0
  35. package/dist/build/service-worker/service-worker.js +102 -0
  36. package/dist/build/service-worker/service-worker.js.map +1 -0
  37. package/dist/build/shared/constants.d.ts +11 -0
  38. package/dist/build/shared/constants.js +18 -0
  39. package/dist/build/shared/constants.js.map +1 -0
  40. package/dist/build/shared/errors.d.ts +10 -0
  41. package/dist/build/shared/errors.js +12 -0
  42. package/dist/build/shared/errors.js.map +1 -0
  43. package/dist/build/shared/index.d.ts +3 -0
  44. package/dist/build/shared/index.js +5 -0
  45. package/dist/build/shared/index.js.map +1 -0
  46. package/dist/build/shared/types.d.ts +6 -0
  47. package/dist/build/shared/types.js +2 -0
  48. package/dist/build/shared/types.js.map +1 -0
  49. package/dist/build/templates/base.sw.js +237 -0
  50. package/dist/build/templates/firebase-fcm.sw.js +169 -0
  51. package/dist/build/worker/index.d.ts +1 -0
  52. package/dist/build/worker/index.js +3 -0
  53. package/dist/build/worker/index.js.map +1 -0
  54. package/dist/build/worker/worker.d.ts +20 -0
  55. package/dist/build/worker/worker.js +51 -0
  56. package/dist/build/worker/worker.js.map +1 -0
  57. package/dist/cli/cli.d.ts +2 -0
  58. package/dist/cli/cli.js +65 -0
  59. package/dist/cli/cli.js.map +1 -0
  60. package/dist/runtime/index.d.ts +8 -0
  61. package/dist/runtime/index.js +14 -0
  62. package/dist/runtime/index.js.map +1 -0
  63. package/dist/runtime/installation/index.d.ts +1 -0
  64. package/dist/runtime/installation/index.js +3 -0
  65. package/dist/runtime/installation/index.js.map +1 -0
  66. package/dist/runtime/installation/installation.d.ts +29 -0
  67. package/dist/runtime/installation/installation.js +78 -0
  68. package/dist/runtime/installation/installation.js.map +1 -0
  69. package/dist/runtime/registration/index.d.ts +1 -0
  70. package/dist/runtime/registration/index.js +3 -0
  71. package/dist/runtime/registration/index.js.map +1 -0
  72. package/dist/runtime/registration/registration.d.ts +15 -0
  73. package/dist/runtime/registration/registration.js +99 -0
  74. package/dist/runtime/registration/registration.js.map +1 -0
  75. package/dist/runtime/shared/constants.d.ts +2 -0
  76. package/dist/runtime/shared/constants.js +5 -0
  77. package/dist/runtime/shared/constants.js.map +1 -0
  78. package/dist/runtime/shared/errors.d.ts +6 -0
  79. package/dist/runtime/shared/errors.js +8 -0
  80. package/dist/runtime/shared/errors.js.map +1 -0
  81. package/dist/runtime/shared/index.d.ts +3 -0
  82. package/dist/runtime/shared/index.js +5 -0
  83. package/dist/runtime/shared/index.js.map +1 -0
  84. package/dist/runtime/shared/types.d.ts +33 -0
  85. package/dist/runtime/shared/types.js +2 -0
  86. package/dist/runtime/shared/types.js.map +1 -0
  87. package/dist/runtime/state/index.d.ts +1 -0
  88. package/dist/runtime/state/index.js +3 -0
  89. package/dist/runtime/state/index.js.map +1 -0
  90. package/dist/runtime/state/state.d.ts +48 -0
  91. package/dist/runtime/state/state.js +94 -0
  92. package/dist/runtime/state/state.js.map +1 -0
  93. package/dist/runtime/update/index.d.ts +1 -0
  94. package/dist/runtime/update/index.js +3 -0
  95. package/dist/runtime/update/index.js.map +1 -0
  96. package/dist/runtime/update/update.d.ts +14 -0
  97. package/dist/runtime/update/update.js +107 -0
  98. package/dist/runtime/update/update.js.map +1 -0
  99. package/dist/shared/constants.d.ts +4 -0
  100. package/dist/shared/constants.js +9 -0
  101. package/dist/shared/constants.js.map +1 -0
  102. package/dist/shared/index.d.ts +1 -0
  103. package/dist/shared/index.js +3 -0
  104. package/dist/shared/index.js.map +1 -0
  105. package/package.json +82 -3
package/CHANGELOG.md ADDED
@@ -0,0 +1,36 @@
1
+ # Changelog
2
+
3
+ ## 1.0.0
4
+
5
+ The first release of `jg-sw`, which replaces `sw-service` 1.2.0 and `sw-builder` 1.2.1.
6
+
7
+ ### Added
8
+
9
+ - `registerServiceWorker`, `getServiceWorkerSnapshot`, `subscribeToServiceWorker`, `updateApp`, `canInstallApp`, and `installApp`, which replace the `SWService` object, with `ERRORS` and the `REGISTRATION_DURATION_SECONDS`, `UPDATE_INSTALL_TIMEOUT_SECONDS`, `DEFAULT_SERVICE_WORKER_PATH`, `DEFAULT_SERVICE_WORKER_SCOPE`, and `SKIP_WAITING_MESSAGE_TYPE` constants.
10
+ - A snapshot whose identity changes only with the state, for `useSyncExternalStore`, with `hasWaitingWorker` and the installation state.
11
+ - `jg-sw/build`, with `buildServiceWorker`, `writeServiceWorker`, `readServiceWorkerConfig`, `ServiceWorkerConfigSchema`, and `ERRORS`, the codes of every error it throws.
12
+ - `serviceWorkerPlugin`, a Vite plugin that writes the worker after a build and serves it without caching in development.
13
+ - The `jg-sw` CLI, with `--config`, `--environment`, `--no-caching`, and `--help`.
14
+ - The worker activates when the page posts the skip-waiting message.
15
+ - `caching: false` and `--no-caching`, which generate a worker without precaching, cache cleanup, or a fetch handler.
16
+ - The `INVALID_FIREBASE_SDK_VERSION` code.
17
+
18
+ ### Changed
19
+
20
+ - `updateApp()` activates the waiting worker and reloads once it controls the page. Without one, it waits up to 30 seconds for a new worker to install, and reloads as it is when none installs.
21
+ - `registerServiceWorker()` resolves once the registration settles, never rejects, and returns the first call's promise on later calls.
22
+ - `installApp()` resolves to the prompt's outcome.
23
+ - The install prompt is tracked from the first `registerServiceWorker()` call, before the registration settles.
24
+ - Logs appear only with `debugMode`, and nothing touches `window` or `navigator` when the module loads.
25
+ - The worker never caches responses marked `Cache-Control: no-store` or `private`.
26
+ - The config file is named `jg-sw.config.json`, and the Firebase background hook `self.jgSwFcmBackgroundMessageHandler`.
27
+ - `firebaseSdkVersion` must be a version such as `12.4.0`. An invalid template fails with `INVALID_TEMPLATE_NAME`, and an unsupported environment with `INVALID_ENVIRONMENT`, whatever the template.
28
+ - Environment files load with Node.js's `process.loadEnvFile`.
29
+ - Precached paths are URL paths from `outDir`, with `#`, `?`, and `%` percent-encoded and each directory's files sorted. A path outside `outDir` fails with `NOT_A_PATH_ELEMENT`.
30
+ - Values written into the worker are serialized as JSON.
31
+ - Errors are `Exception`s from `jg-exception`.
32
+
33
+ ### Removed
34
+
35
+ - The `SWService` object and its `ISWService`, `IAppInstallerService`, and `ISWRegistrationOptions` types.
36
+ - Running the CLI on import, and the `dotenv` and `argv-utils` dependencies.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Jesus Graterol
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,198 @@
1
- # Temporary Holding Version
1
+ # jg-sw
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
+ Service workers for web apps: a generated caching worker with a Vite plugin and CLI, plus registration, updates, and installation.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ npm install jg-sw
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ### Register the worker
14
+
15
+ ```ts
16
+ import { registerServiceWorker } from 'jg-sw';
17
+
18
+ const { registration, registrationError } = await registerServiceWorker(); // registers /sw.js
19
+ ```
20
+
21
+ It never rejects: a failure lands in `registrationError`. Later calls return the first call's promise, and nothing runs until the first call, so it's safe to import during server-side rendering.
22
+
23
+ ### Offer updates and installation
24
+
25
+ The snapshot tells you when a new version waits and whether the app can be installed. It keeps its identity until something changes, so React can read it directly:
26
+
27
+ ```tsx
28
+ import { useSyncExternalStore } from 'react';
29
+ import { getServiceWorkerSnapshot, installApp, subscribeToServiceWorker, updateApp } from 'jg-sw';
30
+
31
+ export const AppBanner = () => {
32
+ const { hasWaitingWorker, installation } = useSyncExternalStore(
33
+ subscribeToServiceWorker,
34
+ getServiceWorkerSnapshot,
35
+ getServiceWorkerSnapshot,
36
+ );
37
+ return (
38
+ <>
39
+ {hasWaitingWorker && <button onClick={() => void updateApp()}>Update</button>}
40
+ {installation.canInstall && <button onClick={() => void installApp()}>Install</button>}
41
+ </>
42
+ );
43
+ };
44
+ ```
45
+
46
+ Without React, `subscribeToServiceWorker(listener)` calls the listener on every change and returns a function that stops it.
47
+
48
+ `updateApp()` reloads the page once, never in a loop:
49
+
50
+ - When a new version waits, it asks it to activate and reloads once it controls the page.
51
+ - Otherwise it checks for one, waits up to `UPDATE_INSTALL_TIMEOUT_SECONDS` (30) for it to install, then activates it the same way.
52
+ - When nothing new is found, the installation fails, or the time runs out, it reloads the page as it is.
53
+
54
+ `installApp()` shows the browser's install prompt and resolves to `'accepted'` or `'dismissed'`. Only Chromium-based browsers offer it, so check `canInstallApp()` or `installation.canInstall` first.
55
+
56
+ ### Describe the worker
57
+
58
+ Create `jg-sw.config.json` next to your app's `package.json`:
59
+
60
+ ```json
61
+ {
62
+ "outDir": "dist",
63
+ "template": "base",
64
+ "cacheNamePrefix": "my-app",
65
+ "includeToPrecache": ["/assets"],
66
+ "excludeFilesFromPrecache": ["some-ignorable-file.woff2"],
67
+ "excludeMIMETypesFromCache": ["application/json", "text/plain", "text/html"]
68
+ }
69
+ ```
70
+
71
+ | Field | What it does |
72
+ | --------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
73
+ | `outDir` | The directory the app's build is written to. The worker is written there as `sw.js`. |
74
+ | `template` | `base` caches the app. `firebase-fcm` also shows Firebase Cloud Messaging notifications. |
75
+ | `cacheNamePrefix` | The namespace of the worker's caches, in lowercase words separated by hyphens, such as `my-app`. Each build caches under `<cacheNamePrefix>--<10 characters>`. |
76
+ | `includeToPrecache` | The files and directories, relative to `outDir`, cached when the worker installs. Directories are read recursively, and `/` stands for the app's root page. |
77
+ | `excludeFilesFromPrecache` | File names left out of precaching, wherever they are. |
78
+ | `excludeMIMETypesFromCache` | MIME types whose responses are never cached. |
79
+
80
+ This config precaches the hashed files under `dist/assets`, but not `/` or `index.html`. Nothing is precached unless it's listed: add `/` and `/index.html` to precache the app's shell.
81
+
82
+ ### Generate it with Vite
83
+
84
+ ```ts
85
+ // vite.config.ts
86
+ import { defineConfig } from 'vite';
87
+ import { serviceWorkerPlugin } from 'jg-sw/build';
88
+
89
+ export default defineConfig({
90
+ plugins: [serviceWorkerPlugin({ config: 'jg-sw.config.json' })],
91
+ });
92
+ ```
93
+
94
+ `vite build` writes `dist/sw.js` after the app's files. `vite` serves a worker without caching at `/sw.js`, so you can test registration and updates while every request still reaches the dev server.
95
+
96
+ ### Generate it with the CLI
97
+
98
+ Run `jg-sw` after your build:
99
+
100
+ ```json
101
+ {
102
+ "scripts": {
103
+ "build": "vite build && jg-sw"
104
+ }
105
+ }
106
+ ```
107
+
108
+ ```text
109
+ Usage: jg-sw [options]
110
+
111
+ Options:
112
+ --config <path> The config file. Defaults to jg-sw.config.json.
113
+ --environment <name> development, staging, or production.
114
+ --no-caching Generates a worker without precaching, cache cleanup, or a fetch handler.
115
+ --help Prints this message.
116
+ ```
117
+
118
+ It prints the path it wrote and exits 0, or prints the error and exits 1.
119
+
120
+ ### Generate it from code
121
+
122
+ ```ts
123
+ import { readServiceWorkerConfig, writeServiceWorker } from 'jg-sw/build';
124
+
125
+ const config = await readServiceWorkerConfig('jg-sw.config.json');
126
+ await writeServiceWorker(config, { environment: 'production' }); // '/app/dist/sw.js'
127
+ ```
128
+
129
+ `buildServiceWorker` returns the worker's source without writing it.
130
+
131
+ ### What the worker does
132
+
133
+ - `install` fills only the new version's cache, and doesn't skip waiting, so the previous worker keeps serving its clients.
134
+ - The page activates a waiting worker by posting `{ type: 'JG_SW_SKIP_WAITING' }` to it.
135
+ - `activate` deletes the older caches in its own namespace, keeps every other cache, then claims its clients.
136
+ - It answers same-origin `GET` requests from the current version's cache, then from the network, and caches successful responses unless they're opaque, partial, marked `Vary: *`, marked `Cache-Control: no-store` or `private`, or of an excluded MIME type. A failed cache write never replaces a valid response.
137
+
138
+ ### Firebase Cloud Messaging
139
+
140
+ The `firebase-fcm` template adds two fields:
141
+
142
+ ```json
143
+ {
144
+ "template": "firebase-fcm",
145
+ "firebaseConfigProcessEnvKey": "VITE_FIREBASE_CONFIG",
146
+ "firebaseSdkVersion": "12.4.0"
147
+ }
148
+ ```
149
+
150
+ The environment variable holds the Firebase web app's options as JSON:
151
+
152
+ ```bash
153
+ VITE_FIREBASE_CONFIG='{"options":{"apiKey":"example-api-key","authDomain":"example.firebaseapp.com","projectId":"example-project","storageBucket":"example.firebasestorage.app","messagingSenderId":"123456789012","appId":"1:123456789012:web:example"}}'
154
+ ```
155
+
156
+ Generate the worker with an environment, such as `jg-sw --environment production`. It loads `.env`, `.env.staging`, or `.env.production` when the file exists, and variables already set keep their values.
157
+
158
+ The worker loads Firebase's compat SDK from `gstatic`. When no app window is visible, it shows a notification for each data-only message, using its `title`, `body`, `icon`, `badge`, and `url` fields, and Firebase shows the messages that carry a notification. Clicking a notification focuses or opens its URL, limited to the app's origin. To decide yourself, append code to the generated worker that assigns `self.jgSwFcmBackgroundMessageHandler = async (payload) => { … }`. The worker waits for it, and shows nothing else.
159
+
160
+ ## Coming from `sw-service` and `sw-builder`
161
+
162
+ | `sw-service` and `sw-builder` | `jg-sw` |
163
+ | ------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------- |
164
+ | `SWService.register(options)` | `registerServiceWorker(options)`, now awaitable |
165
+ | `SWService.updateApp()` | `updateApp()`, which now activates the waiting worker |
166
+ | `SWService.registration`, `.worker`, `.registrationError` | `getServiceWorkerSnapshot().registration`, `.worker`, `.registrationError` |
167
+ | polling `SWService` for changes | `subscribeToServiceWorker(listener)` |
168
+ | `SWService.registrationDurationSeconds` | `REGISTRATION_DURATION_SECONDS` |
169
+ | `SWService.installer.canAppBeInstalled()` | `canInstallApp()` |
170
+ | `SWService.installer.installApp()` | `installApp()`, which now resolves to the outcome |
171
+ | `installer.installationPromptOutcome`, `.appInstalled`, `.runningInstalledApp` | `getServiceWorkerSnapshot().installation.promptOutcome`, `.isAppInstalled`, `.isRunningInstalledApp` |
172
+ | `ISWService`, `IAppInstallerService` | `IServiceWorkerSnapshot`, `IAppInstallationState` |
173
+ | `ISWRegistrationOptions` | `IRegisterServiceWorkerOptions` |
174
+ | the codes, not exported | `ERRORS` from `jg-sw`, and from `jg-sw/build` |
175
+ | the `sw-builder` CLI and `sw-builder.config.json` | the `jg-sw` CLI and `jg-sw.config.json`, or `writeServiceWorker()` and `serviceWorkerPlugin()` |
176
+ | `self.swBuilderFcmBackgroundMessageHandler` | `self.jgSwFcmBackgroundMessageHandler` |
177
+
178
+ `IInstallationPromptOutcome`, `IUserChoice`, `IBeforeInstallPromptEvent`, the config fields, and the error codes keep their names.
179
+
180
+ - `updateApp()` used to reload without activating the waiting worker, which then kept waiting. It now activates it and reloads once the new worker controls the page, waiting for a worker that's still installing.
181
+ - The install prompt is tracked from the first `registerServiceWorker()` call, before the registration settles and even when it fails.
182
+ - Nothing logs unless `debugMode` is set, and nothing touches `window` or `navigator` when the module loads.
183
+ - The worker activates when the page posts the skip-waiting message, never caches `Cache-Control: no-store` or `private` responses, and can be generated without caching for development.
184
+ - The Vite plugin serves the worker in development, so you no longer need an empty `public/sw.js`.
185
+ - `firebaseSdkVersion` must be a version such as `12.4.0`, or generation fails with `INVALID_FIREBASE_SDK_VERSION`. A template other than `base` or `firebase-fcm` fails with `INVALID_TEMPLATE_NAME`, and an unsupported `--environment` with `INVALID_ENVIRONMENT`, whatever the template.
186
+ - Environment files load with Node.js's `process.loadEnvFile`, without `dotenv`.
187
+ - Precached paths are URL paths from `outDir`: `app.js` becomes `/app.js`, `#`, `?`, and `%` are percent-encoded, each directory's files are sorted, and a path outside `outDir` fails with `NOT_A_PATH_ELEMENT`.
188
+ - Values written into the worker are serialized as JSON, so paths with quotes stay intact.
189
+ - Importing the package no longer runs the CLI.
190
+ - Errors are `Exception`s from `jg-exception`.
191
+
192
+ ## Documentation
193
+
194
+ The full API reference is at https://jg-packages.jesusgraterol.dev/packages/jg-sw/.
195
+
196
+ ## License
197
+
198
+ [MIT](https://github.com/jesusgraterol/jg-packages/blob/main/packages/jg-sw/LICENSE)
@@ -0,0 +1,34 @@
1
+ import { type IServiceWorkerEnvironment } from '../shared/index.js';
2
+ import { type IServiceWorkerConfig } from './schema.js';
3
+ /**
4
+ * Validates a service worker config.
5
+ * @param value The config to validate.
6
+ * @param source Where the config came from, such as its file path, for the error message.
7
+ * @returns The config.
8
+ * @throws
9
+ * - INVALID_TEMPLATE_NAME: The template must be 'base' or 'firebase-fcm'.
10
+ * - INVALID_FIREBASE_SDK_VERSION: The Firebase SDK version must be a version such as 12.4.0.
11
+ * - FAILED_TO_READ_BASE_CONFIG: The service worker config is invalid.
12
+ */
13
+ export declare const parseServiceWorkerConfig: (value: unknown, source?: string) => IServiceWorkerConfig;
14
+ /**
15
+ * Checks the environment option, which JavaScript callers and the CLI pass unchecked.
16
+ * @param environment The environment, or undefined when none was given.
17
+ * @returns The environment.
18
+ * @throws
19
+ * - INVALID_ENVIRONMENT: The environment must be development, staging, or production.
20
+ */
21
+ export declare const parseEnvironment: (environment: string | undefined) => IServiceWorkerEnvironment | undefined;
22
+ /**
23
+ * Reads and validates a service worker config file, such as `jg-sw.config.json`.
24
+ * @param path The config file's path.
25
+ * @returns A promise that resolves to the config.
26
+ * @example
27
+ * const config = await readServiceWorkerConfig('jg-sw.config.json');
28
+ * config.template; // 'base'
29
+ * @throws
30
+ * - FAILED_TO_READ_BASE_CONFIG: Unable to read the service worker config, or it is invalid.
31
+ * - INVALID_TEMPLATE_NAME: The template must be 'base' or 'firebase-fcm'.
32
+ * - INVALID_FIREBASE_SDK_VERSION: The Firebase SDK version must be a version such as 12.4.0.
33
+ */
34
+ export declare const readServiceWorkerConfig: (path: string) => Promise<IServiceWorkerConfig>;
@@ -0,0 +1,75 @@
1
+ import { Exception, extractMessage } from 'jg-exception';
2
+ import { readJSONFile } from 'jg-fs';
3
+ import { ENV_FILE_NAME_BY_ENVIRONMENT, ERRORS, } from '../shared/index.js';
4
+ import { ServiceWorkerConfigSchema } from './schema.js';
5
+ /**
6
+ * Picks the code for a config that failed validation: a bad template or Firebase SDK version
7
+ * alone gets its own code, and anything else is a bad config.
8
+ * @param issues The validation issues.
9
+ * @returns The error code.
10
+ */
11
+ const getConfigErrorCode = (issues) => {
12
+ if (issues.every(({ code, path }) => code === 'invalid_union' && path[0] === 'template')) {
13
+ return ERRORS.INVALID_TEMPLATE_NAME;
14
+ }
15
+ if (issues.every(({ code, path }) => code === 'invalid_format' && path[0] === 'firebaseSdkVersion')) {
16
+ return ERRORS.INVALID_FIREBASE_SDK_VERSION;
17
+ }
18
+ return ERRORS.FAILED_TO_READ_BASE_CONFIG;
19
+ };
20
+ /**
21
+ * Validates a service worker config.
22
+ * @param value The config to validate.
23
+ * @param source Where the config came from, such as its file path, for the error message.
24
+ * @returns The config.
25
+ * @throws
26
+ * - INVALID_TEMPLATE_NAME: The template must be 'base' or 'firebase-fcm'.
27
+ * - INVALID_FIREBASE_SDK_VERSION: The Firebase SDK version must be a version such as 12.4.0.
28
+ * - FAILED_TO_READ_BASE_CONFIG: The service worker config is invalid.
29
+ */
30
+ export const parseServiceWorkerConfig = (value, source) => {
31
+ const result = ServiceWorkerConfigSchema.safeParse(value);
32
+ if (result.success) {
33
+ return result.data;
34
+ }
35
+ const issues = result.error.issues
36
+ .map(({ path, message }) => `${path.length === 0 ? 'config' : path.join('.')}: ${message}`)
37
+ .join('; ');
38
+ throw new Exception(`The service worker config${source === undefined ? '' : ` '${source}'`} is invalid: ${issues}`, getConfigErrorCode(result.error.issues));
39
+ };
40
+ /**
41
+ * Checks the environment option, which JavaScript callers and the CLI pass unchecked.
42
+ * @param environment The environment, or undefined when none was given.
43
+ * @returns The environment.
44
+ * @throws
45
+ * - INVALID_ENVIRONMENT: The environment must be development, staging, or production.
46
+ */
47
+ export const parseEnvironment = (environment) => {
48
+ if (environment === undefined || Object.hasOwn(ENV_FILE_NAME_BY_ENVIRONMENT, environment)) {
49
+ return environment;
50
+ }
51
+ throw new Exception(`The environment '${environment}' isn't supported. Use development, staging, or production.`, ERRORS.INVALID_ENVIRONMENT);
52
+ };
53
+ /**
54
+ * Reads and validates a service worker config file, such as `jg-sw.config.json`.
55
+ * @param path The config file's path.
56
+ * @returns A promise that resolves to the config.
57
+ * @example
58
+ * const config = await readServiceWorkerConfig('jg-sw.config.json');
59
+ * config.template; // 'base'
60
+ * @throws
61
+ * - FAILED_TO_READ_BASE_CONFIG: Unable to read the service worker config, or it is invalid.
62
+ * - INVALID_TEMPLATE_NAME: The template must be 'base' or 'firebase-fcm'.
63
+ * - INVALID_FIREBASE_SDK_VERSION: The Firebase SDK version must be a version such as 12.4.0.
64
+ */
65
+ export const readServiceWorkerConfig = async (path) => {
66
+ let value;
67
+ try {
68
+ value = await readJSONFile(path);
69
+ }
70
+ catch (error) {
71
+ throw new Exception(`Unable to read the service worker config '${path}': ${extractMessage(error)}`, ERRORS.FAILED_TO_READ_BASE_CONFIG);
72
+ }
73
+ return parseServiceWorkerConfig(value, path);
74
+ };
75
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../../src/build/config/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACzD,OAAO,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAGrC,OAAO,EACL,4BAA4B,EAC5B,MAAM,GAEP,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,yBAAyB,EAA6B,MAAM,aAAa,CAAC;AAEnF;;;;;GAKG;AACH,MAAM,kBAAkB,GAAG,CAAC,MAA0B,EAAU,EAAE;IAChE,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,IAAI,KAAK,eAAe,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,UAAU,CAAC,EAAE,CAAC;QACzF,OAAO,MAAM,CAAC,qBAAqB,CAAC;IACtC,CAAC;IACD,IACE,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,IAAI,KAAK,gBAAgB,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,oBAAoB,CAAC,EAC/F,CAAC;QACD,OAAO,MAAM,CAAC,4BAA4B,CAAC;IAC7C,CAAC;IACD,OAAO,MAAM,CAAC,0BAA0B,CAAC;AAC3C,CAAC,CAAC;AAEF;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,KAAc,EAAE,MAAe,EAAwB,EAAE;IAChG,MAAM,MAAM,GAAG,yBAAyB,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IAC1D,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;QACnB,OAAO,MAAM,CAAC,IAAI,CAAC;IACrB,CAAC;IACD,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM;SAC/B,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,OAAO,EAAE,CAAC;SAC1F,IAAI,CAAC,IAAI,CAAC,CAAC;IACd,MAAM,IAAI,SAAS,CACjB,4BAA4B,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,MAAM,GAAG,gBAAgB,MAAM,EAAE,EAC9F,kBAAkB,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CACxC,CAAC;AACJ,CAAC,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAC9B,WAA+B,EACQ,EAAE;IACzC,IAAI,WAAW,KAAK,SAAS,IAAI,MAAM,CAAC,MAAM,CAAC,4BAA4B,EAAE,WAAW,CAAC,EAAE,CAAC;QAC1F,OAAO,WAAoD,CAAC;IAC9D,CAAC;IACD,MAAM,IAAI,SAAS,CACjB,oBAAoB,WAAW,6DAA6D,EAC5F,MAAM,CAAC,mBAAmB,CAC3B,CAAC;AACJ,CAAC,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,KAAK,EAAE,IAAY,EAAiC,EAAE;IAC3F,IAAI,KAAc,CAAC;IACnB,IAAI,CAAC;QACH,KAAK,GAAG,MAAM,YAAY,CAAU,IAAI,CAAC,CAAC;IAC5C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,SAAS,CACjB,6CAA6C,IAAI,MAAM,cAAc,CAAC,KAAK,CAAC,EAAE,EAC9E,MAAM,CAAC,0BAA0B,CAClC,CAAC;IACJ,CAAC;IACD,OAAO,wBAAwB,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;AAC/C,CAAC,CAAC","sourcesContent":["import { Exception, extractMessage } from 'jg-exception';\nimport { readJSONFile } from 'jg-fs';\nimport type { z } from 'zod';\n\nimport {\n ENV_FILE_NAME_BY_ENVIRONMENT,\n ERRORS,\n type IServiceWorkerEnvironment,\n} from '../shared/index.js';\nimport { ServiceWorkerConfigSchema, type IServiceWorkerConfig } from './schema.js';\n\n/**\n * Picks the code for a config that failed validation: a bad template or Firebase SDK version\n * alone gets its own code, and anything else is a bad config.\n * @param issues The validation issues.\n * @returns The error code.\n */\nconst getConfigErrorCode = (issues: z.core.$ZodIssue[]): string => {\n if (issues.every(({ code, path }) => code === 'invalid_union' && path[0] === 'template')) {\n return ERRORS.INVALID_TEMPLATE_NAME;\n }\n if (\n issues.every(({ code, path }) => code === 'invalid_format' && path[0] === 'firebaseSdkVersion')\n ) {\n return ERRORS.INVALID_FIREBASE_SDK_VERSION;\n }\n return ERRORS.FAILED_TO_READ_BASE_CONFIG;\n};\n\n/**\n * Validates a service worker config.\n * @param value The config to validate.\n * @param source Where the config came from, such as its file path, for the error message.\n * @returns The config.\n * @throws\n * - INVALID_TEMPLATE_NAME: The template must be 'base' or 'firebase-fcm'.\n * - INVALID_FIREBASE_SDK_VERSION: The Firebase SDK version must be a version such as 12.4.0.\n * - FAILED_TO_READ_BASE_CONFIG: The service worker config is invalid.\n */\nexport const parseServiceWorkerConfig = (value: unknown, source?: string): IServiceWorkerConfig => {\n const result = ServiceWorkerConfigSchema.safeParse(value);\n if (result.success) {\n return result.data;\n }\n const issues = result.error.issues\n .map(({ path, message }) => `${path.length === 0 ? 'config' : path.join('.')}: ${message}`)\n .join('; ');\n throw new Exception(\n `The service worker config${source === undefined ? '' : ` '${source}'`} is invalid: ${issues}`,\n getConfigErrorCode(result.error.issues),\n );\n};\n\n/**\n * Checks the environment option, which JavaScript callers and the CLI pass unchecked.\n * @param environment The environment, or undefined when none was given.\n * @returns The environment.\n * @throws\n * - INVALID_ENVIRONMENT: The environment must be development, staging, or production.\n */\nexport const parseEnvironment = (\n environment: string | undefined,\n): IServiceWorkerEnvironment | undefined => {\n if (environment === undefined || Object.hasOwn(ENV_FILE_NAME_BY_ENVIRONMENT, environment)) {\n return environment as IServiceWorkerEnvironment | undefined;\n }\n throw new Exception(\n `The environment '${environment}' isn't supported. Use development, staging, or production.`,\n ERRORS.INVALID_ENVIRONMENT,\n );\n};\n\n/**\n * Reads and validates a service worker config file, such as `jg-sw.config.json`.\n * @param path The config file's path.\n * @returns A promise that resolves to the config.\n * @example\n * const config = await readServiceWorkerConfig('jg-sw.config.json');\n * config.template; // 'base'\n * @throws\n * - FAILED_TO_READ_BASE_CONFIG: Unable to read the service worker config, or it is invalid.\n * - INVALID_TEMPLATE_NAME: The template must be 'base' or 'firebase-fcm'.\n * - INVALID_FIREBASE_SDK_VERSION: The Firebase SDK version must be a version such as 12.4.0.\n */\nexport const readServiceWorkerConfig = async (path: string): Promise<IServiceWorkerConfig> => {\n let value: unknown;\n try {\n value = await readJSONFile<unknown>(path);\n } catch (error) {\n throw new Exception(\n `Unable to read the service worker config '${path}': ${extractMessage(error)}`,\n ERRORS.FAILED_TO_READ_BASE_CONFIG,\n );\n }\n return parseServiceWorkerConfig(value, path);\n};\n"]}
@@ -0,0 +1,18 @@
1
+ import { type IServiceWorkerEnvironment } from '../shared/index.js';
2
+ import { type IFirebaseOptions } from './schema.js';
3
+ /**
4
+ * Reads the Firebase options the firebase-fcm worker is initialized with, from the environment
5
+ * variable the config names, after loading the environment's file.
6
+ * @param envKey The environment variable that holds the Firebase config.
7
+ * @param environment The environment, which selects the environment file.
8
+ * @param cwd The directory the environment file is resolved from.
9
+ * @returns A promise that resolves to the Firebase options.
10
+ * @throws
11
+ * - INVALID_ENVIRONMENT: The firebase-fcm template needs an environment.
12
+ * - FAILED_TO_BUILD_CONFIG: Unable to load the environment file.
13
+ * - INVALID_FIREBASE_CONFIG: The environment variable that holds the Firebase config is missing or
14
+ * empty.
15
+ * - FAILED_TO_READ_FIREBASE_CONFIG: Unable to read the Firebase config from the environment
16
+ * variable.
17
+ */
18
+ export declare const readFirebaseOptions: (envKey: string, environment: IServiceWorkerEnvironment | undefined, cwd: string) => Promise<IFirebaseOptions>;
@@ -0,0 +1,58 @@
1
+ import { resolve } from 'node:path';
2
+ import { Exception, extractMessage } from 'jg-exception';
3
+ import { pathExists } from 'jg-fs';
4
+ import { ENV_FILE_NAME_BY_ENVIRONMENT, ERRORS, } from '../shared/index.js';
5
+ import { FirebaseConfigSchema } from './schema.js';
6
+ /**
7
+ * Loads the environment's file into process.env when it exists. Variables already set keep their
8
+ * values.
9
+ * @param cwd The directory the file is resolved from.
10
+ * @param environment The environment.
11
+ * @returns A promise that resolves once the file is loaded, or found missing.
12
+ * @throws
13
+ * - FAILED_TO_BUILD_CONFIG: Unable to load the environment file.
14
+ */
15
+ const loadEnvironmentFile = async (cwd, environment) => {
16
+ const path = resolve(cwd, ENV_FILE_NAME_BY_ENVIRONMENT[environment]);
17
+ if (!(await pathExists(path))) {
18
+ return;
19
+ }
20
+ try {
21
+ process.loadEnvFile(path);
22
+ }
23
+ catch (error) {
24
+ throw new Exception(`Unable to load the environment file '${path}': ${extractMessage(error)}`, ERRORS.FAILED_TO_BUILD_CONFIG);
25
+ }
26
+ };
27
+ /**
28
+ * Reads the Firebase options the firebase-fcm worker is initialized with, from the environment
29
+ * variable the config names, after loading the environment's file.
30
+ * @param envKey The environment variable that holds the Firebase config.
31
+ * @param environment The environment, which selects the environment file.
32
+ * @param cwd The directory the environment file is resolved from.
33
+ * @returns A promise that resolves to the Firebase options.
34
+ * @throws
35
+ * - INVALID_ENVIRONMENT: The firebase-fcm template needs an environment.
36
+ * - FAILED_TO_BUILD_CONFIG: Unable to load the environment file.
37
+ * - INVALID_FIREBASE_CONFIG: The environment variable that holds the Firebase config is missing or
38
+ * empty.
39
+ * - FAILED_TO_READ_FIREBASE_CONFIG: Unable to read the Firebase config from the environment
40
+ * variable.
41
+ */
42
+ export const readFirebaseOptions = async (envKey, environment, cwd) => {
43
+ if (environment === undefined) {
44
+ throw new Exception('The firebase-fcm template needs an environment, which selects the environment file that holds its Firebase config. Pass --environment, or the environment option.', ERRORS.INVALID_ENVIRONMENT);
45
+ }
46
+ await loadEnvironmentFile(cwd, environment);
47
+ const value = process.env[envKey];
48
+ if (value === undefined || value.trim() === '') {
49
+ throw new Exception(`The environment variable '${envKey}' that holds the Firebase config is missing or empty.`, ERRORS.INVALID_FIREBASE_CONFIG);
50
+ }
51
+ try {
52
+ return FirebaseConfigSchema.parse(JSON.parse(value)).options;
53
+ }
54
+ catch (error) {
55
+ throw new Exception(`Unable to read the Firebase config from the environment variable '${envKey}': ${extractMessage(error)}`, ERRORS.FAILED_TO_READ_FIREBASE_CONFIG);
56
+ }
57
+ };
58
+ //# sourceMappingURL=firebase.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"firebase.js","sourceRoot":"","sources":["../../../src/build/config/firebase.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACzD,OAAO,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AAEnC,OAAO,EACL,4BAA4B,EAC5B,MAAM,GAEP,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,oBAAoB,EAAyB,MAAM,aAAa,CAAC;AAE1E;;;;;;;;GAQG;AACH,MAAM,mBAAmB,GAAG,KAAK,EAC/B,GAAW,EACX,WAAsC,EACvB,EAAE;IACjB,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,EAAE,4BAA4B,CAAC,WAAW,CAAC,CAAC,CAAC;IACrE,IAAI,CAAC,CAAC,MAAM,UAAU,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;QAC9B,OAAO;IACT,CAAC;IACD,IAAI,CAAC;QACH,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;IAC5B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,SAAS,CACjB,wCAAwC,IAAI,MAAM,cAAc,CAAC,KAAK,CAAC,EAAE,EACzE,MAAM,CAAC,sBAAsB,CAC9B,CAAC;IACJ,CAAC;AACH,CAAC,CAAC;AAEF;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,KAAK,EACtC,MAAc,EACd,WAAkD,EAClD,GAAW,EACgB,EAAE;IAC7B,IAAI,WAAW,KAAK,SAAS,EAAE,CAAC;QAC9B,MAAM,IAAI,SAAS,CACjB,mKAAmK,EACnK,MAAM,CAAC,mBAAmB,CAC3B,CAAC;IACJ,CAAC;IACD,MAAM,mBAAmB,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC;IAE5C,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IAClC,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;QAC/C,MAAM,IAAI,SAAS,CACjB,6BAA6B,MAAM,uDAAuD,EAC1F,MAAM,CAAC,uBAAuB,CAC/B,CAAC;IACJ,CAAC;IACD,IAAI,CAAC;QACH,OAAO,oBAAoB,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC;IAC/D,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,SAAS,CACjB,qEAAqE,MAAM,MAAM,cAAc,CAAC,KAAK,CAAC,EAAE,EACxG,MAAM,CAAC,8BAA8B,CACtC,CAAC;IACJ,CAAC;AACH,CAAC,CAAC","sourcesContent":["import { resolve } from 'node:path';\nimport { Exception, extractMessage } from 'jg-exception';\nimport { pathExists } from 'jg-fs';\n\nimport {\n ENV_FILE_NAME_BY_ENVIRONMENT,\n ERRORS,\n type IServiceWorkerEnvironment,\n} from '../shared/index.js';\nimport { FirebaseConfigSchema, type IFirebaseOptions } from './schema.js';\n\n/**\n * Loads the environment's file into process.env when it exists. Variables already set keep their\n * values.\n * @param cwd The directory the file is resolved from.\n * @param environment The environment.\n * @returns A promise that resolves once the file is loaded, or found missing.\n * @throws\n * - FAILED_TO_BUILD_CONFIG: Unable to load the environment file.\n */\nconst loadEnvironmentFile = async (\n cwd: string,\n environment: IServiceWorkerEnvironment,\n): Promise<void> => {\n const path = resolve(cwd, ENV_FILE_NAME_BY_ENVIRONMENT[environment]);\n if (!(await pathExists(path))) {\n return;\n }\n try {\n process.loadEnvFile(path);\n } catch (error) {\n throw new Exception(\n `Unable to load the environment file '${path}': ${extractMessage(error)}`,\n ERRORS.FAILED_TO_BUILD_CONFIG,\n );\n }\n};\n\n/**\n * Reads the Firebase options the firebase-fcm worker is initialized with, from the environment\n * variable the config names, after loading the environment's file.\n * @param envKey The environment variable that holds the Firebase config.\n * @param environment The environment, which selects the environment file.\n * @param cwd The directory the environment file is resolved from.\n * @returns A promise that resolves to the Firebase options.\n * @throws\n * - INVALID_ENVIRONMENT: The firebase-fcm template needs an environment.\n * - FAILED_TO_BUILD_CONFIG: Unable to load the environment file.\n * - INVALID_FIREBASE_CONFIG: The environment variable that holds the Firebase config is missing or\n * empty.\n * - FAILED_TO_READ_FIREBASE_CONFIG: Unable to read the Firebase config from the environment\n * variable.\n */\nexport const readFirebaseOptions = async (\n envKey: string,\n environment: IServiceWorkerEnvironment | undefined,\n cwd: string,\n): Promise<IFirebaseOptions> => {\n if (environment === undefined) {\n throw new Exception(\n 'The firebase-fcm template needs an environment, which selects the environment file that holds its Firebase config. Pass --environment, or the environment option.',\n ERRORS.INVALID_ENVIRONMENT,\n );\n }\n await loadEnvironmentFile(cwd, environment);\n\n const value = process.env[envKey];\n if (value === undefined || value.trim() === '') {\n throw new Exception(\n `The environment variable '${envKey}' that holds the Firebase config is missing or empty.`,\n ERRORS.INVALID_FIREBASE_CONFIG,\n );\n }\n try {\n return FirebaseConfigSchema.parse(JSON.parse(value)).options;\n } catch (error) {\n throw new Exception(\n `Unable to read the Firebase config from the environment variable '${envKey}': ${extractMessage(error)}`,\n ERRORS.FAILED_TO_READ_FIREBASE_CONFIG,\n );\n }\n};\n"]}
@@ -0,0 +1,3 @@
1
+ export { parseEnvironment, parseServiceWorkerConfig, readServiceWorkerConfig } from './config.js';
2
+ export { readFirebaseOptions } from './firebase.js';
3
+ export { FirebaseConfigSchema, FirebaseOptionsSchema, ServiceWorkerConfigSchema, type IFirebaseOptions, type IServiceWorkerConfig, } from './schema.js';
@@ -0,0 +1,7 @@
1
+ // config files
2
+ export { parseEnvironment, parseServiceWorkerConfig, readServiceWorkerConfig } from './config.js';
3
+ // Firebase
4
+ export { readFirebaseOptions } from './firebase.js';
5
+ // schemas and types
6
+ export { FirebaseConfigSchema, FirebaseOptionsSchema, ServiceWorkerConfigSchema, } from './schema.js';
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/build/config/index.ts"],"names":[],"mappings":"AAAA,eAAe;AACf,OAAO,EAAE,gBAAgB,EAAE,wBAAwB,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAC;AAElG,WAAW;AACX,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAEpD,oBAAoB;AACpB,OAAO,EACL,oBAAoB,EACpB,qBAAqB,EACrB,yBAAyB,GAG1B,MAAM,aAAa,CAAC","sourcesContent":["// config files\nexport { parseEnvironment, parseServiceWorkerConfig, readServiceWorkerConfig } from './config.js';\n\n// Firebase\nexport { readFirebaseOptions } from './firebase.js';\n\n// schemas and types\nexport {\n FirebaseConfigSchema,\n FirebaseOptionsSchema,\n ServiceWorkerConfigSchema,\n type IFirebaseOptions,\n type IServiceWorkerConfig,\n} from './schema.js';\n"]}
@@ -0,0 +1,52 @@
1
+ import { z } from 'zod';
2
+ /**
3
+ * The schema of a service worker config: the `jg-sw.config.json` file the CLI reads, or the
4
+ * object passed to `buildServiceWorker`. `template` selects the worker: `base` caches the app,
5
+ * and `firebase-fcm` also shows Firebase Cloud Messaging notifications.
6
+ * @example
7
+ * const config = ServiceWorkerConfigSchema.parse({
8
+ * outDir: 'dist',
9
+ * cacheNamePrefix: 'my-app',
10
+ * template: 'base',
11
+ * includeToPrecache: ['/', '/index.html', '/assets'],
12
+ * excludeFilesFromPrecache: [],
13
+ * excludeMIMETypesFromCache: ['application/json'],
14
+ * });
15
+ */
16
+ export declare const ServiceWorkerConfigSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
17
+ template: z.ZodLiteral<"base">;
18
+ outDir: z.ZodString;
19
+ cacheNamePrefix: z.ZodString;
20
+ includeToPrecache: z.ZodArray<z.ZodString>;
21
+ excludeFilesFromPrecache: z.ZodArray<z.ZodString>;
22
+ excludeMIMETypesFromCache: z.ZodArray<z.ZodString>;
23
+ }, z.core.$strict>, z.ZodObject<{
24
+ template: z.ZodLiteral<"firebase-fcm">;
25
+ firebaseConfigProcessEnvKey: z.ZodString;
26
+ firebaseSdkVersion: z.ZodString;
27
+ outDir: z.ZodString;
28
+ cacheNamePrefix: z.ZodString;
29
+ includeToPrecache: z.ZodArray<z.ZodString>;
30
+ excludeFilesFromPrecache: z.ZodArray<z.ZodString>;
31
+ excludeMIMETypesFromCache: z.ZodArray<z.ZodString>;
32
+ }, z.core.$strict>], "template">;
33
+ export type IServiceWorkerConfig = z.infer<typeof ServiceWorkerConfigSchema>;
34
+ export declare const FirebaseOptionsSchema: z.ZodObject<{
35
+ apiKey: z.ZodString;
36
+ authDomain: z.ZodString;
37
+ projectId: z.ZodString;
38
+ storageBucket: z.ZodString;
39
+ messagingSenderId: z.ZodString;
40
+ appId: z.ZodString;
41
+ }, z.core.$strict>;
42
+ export type IFirebaseOptions = z.infer<typeof FirebaseOptionsSchema>;
43
+ export declare const FirebaseConfigSchema: z.ZodObject<{
44
+ options: z.ZodObject<{
45
+ apiKey: z.ZodString;
46
+ authDomain: z.ZodString;
47
+ projectId: z.ZodString;
48
+ storageBucket: z.ZodString;
49
+ messagingSenderId: z.ZodString;
50
+ appId: z.ZodString;
51
+ }, z.core.$strict>;
52
+ }, z.core.$strip>;
@@ -0,0 +1,65 @@
1
+ import { z } from 'zod';
2
+ import { CACHE_NAME_PREFIX_PATTERN, FIREBASE_SDK_VERSION_PATTERN } from '../shared/index.js';
3
+ // the fields every template shares
4
+ const BaseConfigShape = {
5
+ // the directory the app's build is written to, where the worker is written too
6
+ outDir: z.string().min(1),
7
+ // the application-owned namespace the worker's caches are named in, such as 'my-app'
8
+ cacheNamePrefix: z
9
+ .string()
10
+ .regex(CACHE_NAME_PREFIX_PATTERN, 'The cache name prefix must contain lowercase alphanumeric tokens separated by hyphens.'),
11
+ // the files and directories, relative to outDir, the worker caches when it installs
12
+ includeToPrecache: z.array(z.string()),
13
+ // the file names left out of precaching, wherever they are
14
+ excludeFilesFromPrecache: z.array(z.string()),
15
+ // the MIME types whose responses the worker never caches, such as 'application/json'
16
+ excludeMIMETypesFromCache: z.array(z.string()),
17
+ };
18
+ // the config of a worker that caches the app
19
+ const BaseConfigSchema = z.strictObject({
20
+ ...BaseConfigShape,
21
+ template: z.literal('base'),
22
+ });
23
+ // the config of a worker that caches the app and shows Firebase Cloud Messaging notifications
24
+ const FirebaseFcmConfigSchema = z.strictObject({
25
+ ...BaseConfigShape,
26
+ template: z.literal('firebase-fcm'),
27
+ // the environment variable holding the Firebase config, as JSON: { "options": { … } }
28
+ firebaseConfigProcessEnvKey: z.string().min(1),
29
+ // the Firebase JavaScript SDK version the worker loads, such as '12.4.0'
30
+ firebaseSdkVersion: z
31
+ .string()
32
+ .regex(FIREBASE_SDK_VERSION_PATTERN, 'The Firebase SDK version must be a version such as 12.4.0.'),
33
+ });
34
+ /**
35
+ * The schema of a service worker config: the `jg-sw.config.json` file the CLI reads, or the
36
+ * object passed to `buildServiceWorker`. `template` selects the worker: `base` caches the app,
37
+ * and `firebase-fcm` also shows Firebase Cloud Messaging notifications.
38
+ * @example
39
+ * const config = ServiceWorkerConfigSchema.parse({
40
+ * outDir: 'dist',
41
+ * cacheNamePrefix: 'my-app',
42
+ * template: 'base',
43
+ * includeToPrecache: ['/', '/index.html', '/assets'],
44
+ * excludeFilesFromPrecache: [],
45
+ * excludeMIMETypesFromCache: ['application/json'],
46
+ * });
47
+ */
48
+ export const ServiceWorkerConfigSchema = z.discriminatedUnion('template', [
49
+ BaseConfigSchema,
50
+ FirebaseFcmConfigSchema,
51
+ ]);
52
+ // the options Firebase's initializeApp receives in the worker
53
+ export const FirebaseOptionsSchema = z.strictObject({
54
+ apiKey: z.string().min(1),
55
+ authDomain: z.string().min(1),
56
+ projectId: z.string().min(1),
57
+ storageBucket: z.string().min(1),
58
+ messagingSenderId: z.string().min(1),
59
+ appId: z.string().min(1),
60
+ });
61
+ // the JSON value the environment variable named by firebaseConfigProcessEnvKey holds
62
+ export const FirebaseConfigSchema = z.object({
63
+ options: FirebaseOptionsSchema,
64
+ });
65
+ //# sourceMappingURL=schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../../src/build/config/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,yBAAyB,EAAE,4BAA4B,EAAE,MAAM,oBAAoB,CAAC;AAE7F,mCAAmC;AACnC,MAAM,eAAe,GAAG;IACtB,+EAA+E;IAC/E,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAEzB,qFAAqF;IACrF,eAAe,EAAE,CAAC;SACf,MAAM,EAAE;SACR,KAAK,CACJ,yBAAyB,EACzB,wFAAwF,CACzF;IAEH,oFAAoF;IACpF,iBAAiB,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;IAEtC,2DAA2D;IAC3D,wBAAwB,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;IAE7C,qFAAqF;IACrF,yBAAyB,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;CAC/C,CAAC;AAEF,6CAA6C;AAC7C,MAAM,gBAAgB,GAAG,CAAC,CAAC,YAAY,CAAC;IACtC,GAAG,eAAe;IAClB,QAAQ,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC;CAC5B,CAAC,CAAC;AAEH,8FAA8F;AAC9F,MAAM,uBAAuB,GAAG,CAAC,CAAC,YAAY,CAAC;IAC7C,GAAG,eAAe;IAClB,QAAQ,EAAE,CAAC,CAAC,OAAO,CAAC,cAAc,CAAC;IAEnC,sFAAsF;IACtF,2BAA2B,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAE9C,yEAAyE;IACzE,kBAAkB,EAAE,CAAC;SAClB,MAAM,EAAE;SACR,KAAK,CACJ,4BAA4B,EAC5B,4DAA4D,CAC7D;CACJ,CAAC,CAAC;AAEH;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAG,CAAC,CAAC,kBAAkB,CAAC,UAAU,EAAE;IACxE,gBAAgB;IAChB,uBAAuB;CACxB,CAAC,CAAC;AAKH,8DAA8D;AAC9D,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,CAAC,YAAY,CAAC;IAClD,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACzB,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC7B,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC5B,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAChC,iBAAiB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACpC,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;CACzB,CAAC,CAAC;AAIH,qFAAqF;AACrF,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC3C,OAAO,EAAE,qBAAqB;CAC/B,CAAC,CAAC","sourcesContent":["import { z } from 'zod';\n\nimport { CACHE_NAME_PREFIX_PATTERN, FIREBASE_SDK_VERSION_PATTERN } from '../shared/index.js';\n\n// the fields every template shares\nconst BaseConfigShape = {\n // the directory the app's build is written to, where the worker is written too\n outDir: z.string().min(1),\n\n // the application-owned namespace the worker's caches are named in, such as 'my-app'\n cacheNamePrefix: z\n .string()\n .regex(\n CACHE_NAME_PREFIX_PATTERN,\n 'The cache name prefix must contain lowercase alphanumeric tokens separated by hyphens.',\n ),\n\n // the files and directories, relative to outDir, the worker caches when it installs\n includeToPrecache: z.array(z.string()),\n\n // the file names left out of precaching, wherever they are\n excludeFilesFromPrecache: z.array(z.string()),\n\n // the MIME types whose responses the worker never caches, such as 'application/json'\n excludeMIMETypesFromCache: z.array(z.string()),\n};\n\n// the config of a worker that caches the app\nconst BaseConfigSchema = z.strictObject({\n ...BaseConfigShape,\n template: z.literal('base'),\n});\n\n// the config of a worker that caches the app and shows Firebase Cloud Messaging notifications\nconst FirebaseFcmConfigSchema = z.strictObject({\n ...BaseConfigShape,\n template: z.literal('firebase-fcm'),\n\n // the environment variable holding the Firebase config, as JSON: { \"options\": { … } }\n firebaseConfigProcessEnvKey: z.string().min(1),\n\n // the Firebase JavaScript SDK version the worker loads, such as '12.4.0'\n firebaseSdkVersion: z\n .string()\n .regex(\n FIREBASE_SDK_VERSION_PATTERN,\n 'The Firebase SDK version must be a version such as 12.4.0.',\n ),\n});\n\n/**\n * The schema of a service worker config: the `jg-sw.config.json` file the CLI reads, or the\n * object passed to `buildServiceWorker`. `template` selects the worker: `base` caches the app,\n * and `firebase-fcm` also shows Firebase Cloud Messaging notifications.\n * @example\n * const config = ServiceWorkerConfigSchema.parse({\n * outDir: 'dist',\n * cacheNamePrefix: 'my-app',\n * template: 'base',\n * includeToPrecache: ['/', '/index.html', '/assets'],\n * excludeFilesFromPrecache: [],\n * excludeMIMETypesFromCache: ['application/json'],\n * });\n */\nexport const ServiceWorkerConfigSchema = z.discriminatedUnion('template', [\n BaseConfigSchema,\n FirebaseFcmConfigSchema,\n]);\n\n// a service worker config, validated by ServiceWorkerConfigSchema\nexport type IServiceWorkerConfig = z.infer<typeof ServiceWorkerConfigSchema>;\n\n// the options Firebase's initializeApp receives in the worker\nexport const FirebaseOptionsSchema = z.strictObject({\n apiKey: z.string().min(1),\n authDomain: z.string().min(1),\n projectId: z.string().min(1),\n storageBucket: z.string().min(1),\n messagingSenderId: z.string().min(1),\n appId: z.string().min(1),\n});\n\nexport type IFirebaseOptions = z.infer<typeof FirebaseOptionsSchema>;\n\n// the JSON value the environment variable named by firebaseConfigProcessEnvKey holds\nexport const FirebaseConfigSchema = z.object({\n options: FirebaseOptionsSchema,\n});\n"]}
@@ -0,0 +1,5 @@
1
+ export { ERRORS } from './shared/index.js';
2
+ export type { IBuildServiceWorkerOptions } from './shared/index.js';
3
+ export { ServiceWorkerConfigSchema, readServiceWorkerConfig, type IServiceWorkerConfig, } from './config/index.js';
4
+ export { buildServiceWorker, writeServiceWorker } from './service-worker/index.js';
5
+ export { serviceWorkerPlugin } from './plugin/index.js';