@swoff/cli 0.3.8 → 0.3.10
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 +47 -33
- package/dist/__tests__/assemble-sw.test.js +14 -53
- package/dist/__tests__/assemble-sw.test.js.map +1 -1
- package/dist/__tests__/cli-integration.test.js +119 -11
- package/dist/__tests__/cli-integration.test.js.map +1 -1
- package/dist/__tests__/config-types.test.js +44 -17
- package/dist/__tests__/config-types.test.js.map +1 -1
- package/dist/__tests__/file-generators.test.js +3 -3
- package/dist/__tests__/file-generators.test.js.map +1 -1
- package/dist/__tests__/glob-matcher.test.js +86 -0
- package/dist/__tests__/glob-matcher.test.js.map +1 -0
- package/dist/__tests__/invalidation-tags.test.js +207 -23
- package/dist/__tests__/invalidation-tags.test.js.map +1 -1
- package/dist/__tests__/loader.test.js +16 -12
- package/dist/__tests__/loader.test.js.map +1 -1
- package/dist/__tests__/validator.test.js +140 -100
- package/dist/__tests__/validator.test.js.map +1 -1
- package/dist/index.js +39 -34
- package/dist/index.js.map +1 -1
- package/dist/lib/cli/help.js +12 -12
- package/dist/lib/cli/help.js.map +1 -1
- package/dist/lib/commands/add.js +84 -36
- package/dist/lib/commands/add.js.map +1 -1
- package/dist/lib/commands/assets.js +37 -0
- package/dist/lib/commands/assets.js.map +1 -0
- package/dist/lib/commands/clean.js +32 -30
- package/dist/lib/commands/clean.js.map +1 -1
- package/dist/lib/commands/generate-assets.js +44 -0
- package/dist/lib/commands/generate-assets.js.map +1 -0
- package/dist/lib/commands/generate-guide.js +22 -29
- package/dist/lib/commands/generate-guide.js.map +1 -1
- package/dist/lib/commands/generate.js +17 -24
- package/dist/lib/commands/generate.js.map +1 -1
- package/dist/lib/commands/info.js +41 -48
- package/dist/lib/commands/info.js.map +1 -1
- package/dist/lib/commands/init.js +27 -13
- package/dist/lib/commands/init.js.map +1 -1
- package/dist/lib/commands/validate.js +4 -4
- package/dist/lib/commands/validate.js.map +1 -1
- package/dist/lib/config/loader.js +25 -23
- package/dist/lib/config/loader.js.map +1 -1
- package/dist/lib/config/validator.js +169 -91
- package/dist/lib/config/validator.js.map +1 -1
- package/dist/lib/generators/asset-generator/dependency-resolver.js +76 -0
- package/dist/lib/generators/asset-generator/dependency-resolver.js.map +1 -0
- package/dist/lib/generators/asset-generator/generate.js +111 -0
- package/dist/lib/generators/asset-generator/generate.js.map +1 -0
- package/dist/lib/generators/asset-generator/guide.js +43 -0
- package/dist/lib/generators/asset-generator/guide.js.map +1 -0
- package/dist/lib/generators/asset-generator/html-patcher.js +65 -0
- package/dist/lib/generators/asset-generator/html-patcher.js.map +1 -0
- package/dist/lib/generators/asset-generator/ico-encoder.js +29 -0
- package/dist/lib/generators/asset-generator/ico-encoder.js.map +1 -0
- package/dist/lib/generators/asset-generator/manifest-patcher.js +23 -0
- package/dist/lib/generators/asset-generator/manifest-patcher.js.map +1 -0
- package/dist/lib/generators/asset-generator/maskable.js +15 -0
- package/dist/lib/generators/asset-generator/maskable.js.map +1 -0
- package/dist/lib/generators/asset-generator/rasterize.js +32 -0
- package/dist/lib/generators/asset-generator/rasterize.js.map +1 -0
- package/dist/lib/generators/asset-generator/sizes.js +25 -0
- package/dist/lib/generators/asset-generator/sizes.js.map +1 -0
- package/dist/lib/generators/file-generators/api-config.js +6 -0
- package/dist/lib/generators/file-generators/api-config.js.map +1 -0
- package/dist/lib/generators/file-generators/auth-state.js +2 -34
- package/dist/lib/generators/file-generators/auth-state.js.map +1 -1
- package/dist/lib/generators/file-generators/auth-store.js +2 -250
- package/dist/lib/generators/file-generators/auth-store.js.map +1 -1
- package/dist/lib/generators/file-generators/auth-user.js +3 -81
- package/dist/lib/generators/file-generators/auth-user.js.map +1 -1
- package/dist/lib/generators/file-generators/background-sync.js +2 -57
- package/dist/lib/generators/file-generators/background-sync.js.map +1 -1
- package/dist/lib/generators/file-generators/cache.js +2 -38
- package/dist/lib/generators/file-generators/cache.js.map +1 -1
- package/dist/lib/generators/file-generators/client-injector.js +2 -91
- package/dist/lib/generators/file-generators/client-injector.js.map +1 -1
- package/dist/lib/generators/file-generators/fetch-state.js +6 -0
- package/dist/lib/generators/file-generators/fetch-state.js.map +1 -0
- package/dist/lib/generators/file-generators/fetch-wrapper.js +3 -267
- package/dist/lib/generators/file-generators/fetch-wrapper.js.map +1 -1
- package/dist/lib/generators/file-generators/generate-framework-adapters.js +56 -0
- package/dist/lib/generators/file-generators/generate-framework-adapters.js.map +1 -0
- package/dist/lib/generators/file-generators/generate-hooks.js +4 -3
- package/dist/lib/generators/file-generators/generate-hooks.js.map +1 -1
- package/dist/lib/generators/file-generators/gql-wrapper.js +3 -145
- package/dist/lib/generators/file-generators/gql-wrapper.js.map +1 -1
- package/dist/lib/generators/file-generators/guide-generator.js +24 -630
- package/dist/lib/generators/file-generators/guide-generator.js.map +1 -1
- package/dist/lib/generators/file-generators/invalidation-tags.js +18 -86
- package/dist/lib/generators/file-generators/invalidation-tags.js.map +1 -1
- package/dist/lib/generators/file-generators/manifest.js +15 -5
- package/dist/lib/generators/file-generators/manifest.js.map +1 -1
- package/dist/lib/generators/file-generators/mutation-queue.js +3 -285
- package/dist/lib/generators/file-generators/mutation-queue.js.map +1 -1
- package/dist/lib/generators/file-generators/mutation-state.js +2 -117
- package/dist/lib/generators/file-generators/mutation-state.js.map +1 -1
- package/dist/lib/generators/file-generators/push.js +6 -139
- package/dist/lib/generators/file-generators/push.js.map +1 -1
- package/dist/lib/generators/file-generators/pwa-install.js +11 -84
- package/dist/lib/generators/file-generators/pwa-install.js.map +1 -1
- package/dist/lib/generators/file-generators/quick-readme.js +8 -125
- package/dist/lib/generators/file-generators/quick-readme.js.map +1 -1
- package/dist/lib/generators/file-generators/reset.js +6 -0
- package/dist/lib/generators/file-generators/reset.js.map +1 -0
- package/dist/lib/generators/file-generators/server-push.js +3 -124
- package/dist/lib/generators/file-generators/server-push.js.map +1 -1
- package/dist/lib/generators/file-generators/sw-generator-build.js +8 -9
- package/dist/lib/generators/file-generators/sw-generator-build.js.map +1 -1
- package/dist/lib/generators/file-generators/sw-injector.js +10 -230
- package/dist/lib/generators/file-generators/sw-injector.js.map +1 -1
- package/dist/lib/generators/file-generators/type-definitions.js +2 -114
- package/dist/lib/generators/file-generators/type-definitions.js.map +1 -1
- package/dist/lib/generators/sw-generator.js +10 -20
- package/dist/lib/generators/sw-generator.js.map +1 -1
- package/dist/lib/generators/sw-sections/activate-handler.js +25 -3
- package/dist/lib/generators/sw-sections/activate-handler.js.map +1 -1
- package/dist/lib/generators/sw-sections/assemble-sw.js +20 -16
- package/dist/lib/generators/sw-sections/assemble-sw.js.map +1 -1
- package/dist/lib/generators/sw-sections/background-sync-handler.js +68 -19
- package/dist/lib/generators/sw-sections/background-sync-handler.js.map +1 -1
- package/dist/lib/generators/sw-sections/config-header.js +2 -2
- package/dist/lib/generators/sw-sections/config-header.js.map +1 -1
- package/dist/lib/generators/sw-sections/fetch-handler.js +506 -144
- package/dist/lib/generators/sw-sections/fetch-handler.js.map +1 -1
- package/dist/lib/generators/sw-sections/glob-matcher-code.js.map +1 -0
- package/dist/lib/generators/sw-sections/message-handler.js +55 -15
- package/dist/lib/generators/sw-sections/message-handler.js.map +1 -1
- package/dist/lib/generators/sw-sections/server-push-handler.js +12 -0
- package/dist/lib/generators/sw-sections/server-push-handler.js.map +1 -1
- package/dist/lib/generators/sw-sections/sw-push.js +67 -0
- package/dist/lib/generators/sw-sections/sw-push.js.map +1 -0
- package/dist/lib/generators/sw-sections/tag-management.js +65 -23
- package/dist/lib/generators/sw-sections/tag-management.js.map +1 -1
- package/dist/lib/generators/swoff-files-generator.js +66 -45
- package/dist/lib/generators/swoff-files-generator.js.map +1 -1
- package/dist/lib/shared/config-types.js +182 -71
- package/dist/lib/shared/config-types.js.map +1 -1
- package/dist/lib/shared/glob-matcher.js +77 -0
- package/dist/lib/shared/glob-matcher.js.map +1 -0
- package/dist/lib/utils/tty-status.js +21 -0
- package/dist/lib/utils/tty-status.js.map +1 -0
- package/dist/runtime/api-config.js +18 -0
- package/dist/runtime/api-config.js.map +1 -0
- package/dist/runtime/auth-state.js +35 -0
- package/dist/runtime/auth-state.js.map +1 -0
- package/dist/runtime/auth-store.js +273 -0
- package/dist/runtime/auth-store.js.map +1 -0
- package/dist/runtime/auth-user.js +168 -0
- package/dist/runtime/auth-user.js.map +1 -0
- package/dist/runtime/background-sync.js +59 -0
- package/dist/runtime/background-sync.js.map +1 -0
- package/dist/runtime/cache.js +30 -0
- package/dist/runtime/cache.js.map +1 -0
- package/dist/runtime/client-injector.js +136 -0
- package/dist/runtime/client-injector.js.map +1 -0
- package/dist/runtime/fetch-state.js +42 -0
- package/dist/runtime/fetch-state.js.map +1 -0
- package/dist/runtime/fetch-wrapper.js +355 -0
- package/dist/runtime/fetch-wrapper.js.map +1 -0
- package/dist/runtime/gql-wrapper.js +135 -0
- package/dist/runtime/gql-wrapper.js.map +1 -0
- package/dist/runtime/invalidation-tags.js +260 -0
- package/dist/runtime/invalidation-tags.js.map +1 -0
- package/dist/runtime/mutation-queue.js +304 -0
- package/dist/runtime/mutation-queue.js.map +1 -0
- package/dist/runtime/mutation-state.js +117 -0
- package/dist/runtime/mutation-state.js.map +1 -0
- package/dist/runtime/push.js +138 -0
- package/dist/runtime/push.js.map +1 -0
- package/dist/runtime/pwa-index.js +11 -0
- package/dist/runtime/pwa-index.js.map +1 -0
- package/dist/runtime/pwa-injector.js +44 -0
- package/dist/runtime/pwa-injector.js.map +1 -0
- package/dist/runtime/pwa-install.js +83 -0
- package/dist/runtime/pwa-install.js.map +1 -0
- package/dist/runtime/pwa-prompt.js +54 -0
- package/dist/runtime/pwa-prompt.js.map +1 -0
- package/dist/runtime/reset.js +148 -0
- package/dist/runtime/reset.js.map +1 -0
- package/dist/runtime/server-push.js +148 -0
- package/dist/runtime/server-push.js.map +1 -0
- package/dist/runtime/sw-injector.js +236 -0
- package/dist/runtime/sw-injector.js.map +1 -0
- package/dist/runtime/type-definitions.js +138 -0
- package/dist/runtime/type-definitions.js.map +1 -0
- package/dist/runtime/utils.js +27 -0
- package/dist/runtime/utils.js.map +1 -0
- package/package.json +3 -1
- package/templates/react/useAuth.jsx +106 -0
- package/templates/react/useAuth.tsx +118 -0
- package/templates/{hooks → react}/useBackgroundSync.jsx +6 -4
- package/templates/{hooks → react}/useBackgroundSync.tsx +6 -4
- package/templates/{hooks → react}/useCacheInvalidation.jsx +2 -2
- package/templates/react/useCacheInvalidation.tsx +52 -0
- package/templates/react/useCachedFetch.jsx +140 -0
- package/templates/react/useCachedFetch.tsx +160 -0
- package/templates/react/useIsFetching.jsx +32 -0
- package/templates/react/useIsFetching.tsx +32 -0
- package/templates/react/useMutation.jsx +141 -0
- package/templates/react/useMutation.tsx +180 -0
- package/templates/react/useMutationQueue.jsx +69 -0
- package/templates/react/useMutationQueue.tsx +83 -0
- package/templates/react/useMutationState.jsx +13 -0
- package/templates/react/useMutationState.tsx +25 -0
- package/templates/react/useNetworkStatus.jsx +61 -0
- package/templates/react/useNetworkStatus.tsx +76 -0
- package/templates/react/usePrefetch.jsx +32 -0
- package/templates/react/usePrefetch.tsx +42 -0
- package/templates/{hooks → react}/usePushSubscription.jsx +7 -7
- package/templates/{hooks → react}/usePushSubscription.tsx +7 -7
- package/templates/{hooks → react}/useSWUpdate.jsx +3 -3
- package/templates/{hooks → react}/useSWUpdate.tsx +4 -4
- package/templates/react/useSwoffReset.jsx +32 -0
- package/templates/react/useSwoffReset.tsx +39 -0
- package/templates/hooks/useAuth.jsx +0 -30
- package/templates/hooks/useAuth.tsx +0 -30
- package/templates/hooks/useCacheInvalidation.tsx +0 -19
- package/templates/hooks/useCachedFetch.jsx +0 -94
- package/templates/hooks/useCachedFetch.tsx +0 -112
- package/templates/hooks/useMutation.jsx +0 -76
- package/templates/hooks/useMutation.tsx +0 -97
- package/templates/hooks/useMutationQueue.jsx +0 -42
- package/templates/hooks/useMutationQueue.tsx +0 -49
- package/templates/hooks/useMutationState.jsx +0 -27
- package/templates/hooks/useMutationState.tsx +0 -41
- package/templates/hooks/useNetworkStatus.jsx +0 -19
- package/templates/hooks/useNetworkStatus.tsx +0 -19
- package/templates/hooks/usePrefetch.jsx +0 -10
- package/templates/hooks/usePrefetch.tsx +0 -25
|
@@ -3,31 +3,16 @@
|
|
|
3
3
|
* Uses direct imports (no subprocess spawning) for a single status line.
|
|
4
4
|
*/
|
|
5
5
|
import { log } from "../cli/logger.js";
|
|
6
|
-
import {
|
|
6
|
+
import { loadConfigAsync } from "../config/loader.js";
|
|
7
7
|
import { detectProjectLanguage } from "../utils/detect-language.js";
|
|
8
|
-
import {
|
|
8
|
+
import { statusLine, clearStatusLine } from "../utils/tty-status.js";
|
|
9
9
|
import { generateSW } from "../generators/sw-generator.js";
|
|
10
10
|
import { generateFiles } from "../generators/swoff-files-generator.js";
|
|
11
11
|
import { join } from "path";
|
|
12
|
-
function statusLine(msg) {
|
|
13
|
-
if (process.stdout.isTTY) {
|
|
14
|
-
const cols = process.stdout.columns || 80;
|
|
15
|
-
process.stdout.write(`\r${" ".repeat(cols - 1)}\r ${msg}`);
|
|
16
|
-
}
|
|
17
|
-
else {
|
|
18
|
-
console.log(` ${msg}`);
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
function clearStatusLine() {
|
|
22
|
-
if (process.stdout.isTTY) {
|
|
23
|
-
const cols = process.stdout.columns || 80;
|
|
24
|
-
process.stdout.write(`\r${" ".repeat(cols - 1)}\r`);
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
12
|
export async function generateCommand(projectRoot, options = {}) {
|
|
28
|
-
const { swOnly = false, filesOnly = false, language } = options;
|
|
29
|
-
log.header("Generating Swoff Files");
|
|
30
|
-
const { config, configPath } =
|
|
13
|
+
const { swOnly = false, filesOnly = false, language, continueOnSwError = false, } = options;
|
|
14
|
+
// log.header("Generating Swoff Files");
|
|
15
|
+
const { config, configPath } = await loadConfigAsync(projectRoot);
|
|
31
16
|
if (!configPath) {
|
|
32
17
|
log.warn('No swoff.config.json found. Run "swoff init" first.');
|
|
33
18
|
return;
|
|
@@ -49,6 +34,10 @@ export async function generateCommand(projectRoot, options = {}) {
|
|
|
49
34
|
catch (err) {
|
|
50
35
|
clearStatusLine();
|
|
51
36
|
log.error(`Service worker failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
37
|
+
if (!continueOnSwError) {
|
|
38
|
+
log.error("Generation aborted. Fix the issue and re-run. Use --continue-on-sw-error to skip SW and continue with files.");
|
|
39
|
+
process.exit(1);
|
|
40
|
+
}
|
|
52
41
|
}
|
|
53
42
|
}
|
|
54
43
|
if (!swOnly) {
|
|
@@ -75,11 +64,15 @@ export async function generateCommand(projectRoot, options = {}) {
|
|
|
75
64
|
}
|
|
76
65
|
}
|
|
77
66
|
log.success("Generation complete!");
|
|
78
|
-
if (
|
|
79
|
-
log.
|
|
67
|
+
if (config.features.pwa.enabled) {
|
|
68
|
+
log.normal("");
|
|
69
|
+
log.help("PWA assets: run 'npx @swoff/cli assets --source <path>' to generate icons and splash screens");
|
|
80
70
|
}
|
|
81
71
|
log.normal("");
|
|
82
|
-
log.help("
|
|
83
|
-
log.
|
|
72
|
+
log.help("1. Read swoff/GUIDE.md for documentation links");
|
|
73
|
+
log.normal("");
|
|
74
|
+
log.help("2. After each build, run the SW generator:");
|
|
75
|
+
log.help(" node swoff/sw/generator.js");
|
|
76
|
+
log.help(" (Add this to your build script if you want it automated)");
|
|
84
77
|
}
|
|
85
78
|
//# sourceMappingURL=generate.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generate.js","sourceRoot":"","sources":["../../../src/lib/commands/generate.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAC;AACvC,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"generate.js","sourceRoot":"","sources":["../../../src/lib/commands/generate.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,14 +1,9 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* info command — minimal summary or per-feature detail.
|
|
3
|
-
*
|
|
4
|
-
* Usage:
|
|
5
|
-
* swoff info List enabled features and generated files
|
|
6
|
-
* swoff info <feature> Detailed explanation of a specific feature
|
|
7
|
-
*/
|
|
8
1
|
import { readFileSync, existsSync, readdirSync } from "fs";
|
|
9
|
-
import { join } from "path";
|
|
2
|
+
import { join, dirname } from "path";
|
|
3
|
+
import { fileURLToPath } from "url";
|
|
10
4
|
import { log } from "../cli/logger.js";
|
|
11
5
|
import { loadConfigAsync } from "../config/loader.js";
|
|
6
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
12
7
|
const FEATURES = {
|
|
13
8
|
"mutation-queue": {
|
|
14
9
|
label: "Mutation Queue",
|
|
@@ -47,7 +42,7 @@ const FEATURES = {
|
|
|
47
42
|
},
|
|
48
43
|
"tag-invalidation": {
|
|
49
44
|
label: "Tag Invalidation",
|
|
50
|
-
description: "Generates cache tags from
|
|
45
|
+
description: "Generates cache tags from URLs and invalidates stale cache entries after mutations. Keeps cached data fresh.",
|
|
51
46
|
files: ["invalidation-tags.ts", "cache.ts"],
|
|
52
47
|
functions: [
|
|
53
48
|
"generateTags(url) — extract tags from URL (e.g. /api/todos/42 → ['todos', 'todo:42'])",
|
|
@@ -77,7 +72,7 @@ const FEATURES = {
|
|
|
77
72
|
description: "Push notification subscription management with IndexedDB persistence, VAPID key support, and service worker push/notificationclick event handlers.",
|
|
78
73
|
files: ["push.ts"],
|
|
79
74
|
functions: [
|
|
80
|
-
"subscribeToPush(
|
|
75
|
+
"subscribeToPush() — request permission and subscribe (uses VAPID key from config)",
|
|
81
76
|
"unsubscribeFromPush() — unsubscribe and clear stored subscription",
|
|
82
77
|
"isSubscribed() — check subscription status",
|
|
83
78
|
"getPushSubscription() — get current PushSubscription object",
|
|
@@ -105,26 +100,53 @@ const FEATURES = {
|
|
|
105
100
|
],
|
|
106
101
|
},
|
|
107
102
|
};
|
|
103
|
+
function countFilesRecursive(dir) {
|
|
104
|
+
let count = 0;
|
|
105
|
+
for (const entry of readdirSync(dir, { withFileTypes: true })) {
|
|
106
|
+
const full = join(dir, entry.name);
|
|
107
|
+
if (entry.isDirectory()) {
|
|
108
|
+
count += countFilesRecursive(full);
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
count++;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
return count;
|
|
115
|
+
}
|
|
116
|
+
function showFeatureDetail(feature) {
|
|
117
|
+
const key = feature.toLowerCase().replace(/[_-]/g, "-").replace(/^-+|-+$/g, "");
|
|
118
|
+
const info = FEATURES[key];
|
|
119
|
+
if (!info) {
|
|
120
|
+
log.error(`Unknown feature: ${feature}`);
|
|
121
|
+
log.info("Available: mutation-queue, background-sync, auth, tag-invalidation, cross-tab, graphql, push-notification, server-push, pwa");
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
log.header(info.label);
|
|
125
|
+
log.normal(info.description);
|
|
126
|
+
log.normal("\nGenerated files:");
|
|
127
|
+
info.files.forEach((f) => log.help(` swoff/${f}`));
|
|
128
|
+
log.normal("\nFunctions:");
|
|
129
|
+
info.functions.forEach((f) => log.help(` ${f}`));
|
|
130
|
+
log.help("\n Read swoff/GUIDE.md for documentation links.");
|
|
131
|
+
}
|
|
108
132
|
export async function infoCommand(projectRoot, feature) {
|
|
109
133
|
if (feature) {
|
|
110
134
|
return showFeatureDetail(feature);
|
|
111
135
|
}
|
|
112
|
-
// Minimal top-level summary
|
|
113
136
|
const { config, configPath } = await loadConfigAsync(projectRoot);
|
|
114
137
|
if (!configPath) {
|
|
115
138
|
log.warn('No swoff.config.json found. Run "swoff init" first.');
|
|
116
139
|
return;
|
|
117
140
|
}
|
|
118
141
|
log.header("Swoff");
|
|
119
|
-
// Show version
|
|
120
142
|
try {
|
|
121
|
-
const
|
|
143
|
+
const pkgDir = join(__dirname, "..", "..", "..");
|
|
144
|
+
const pkg = JSON.parse(readFileSync(join(pkgDir, "package.json"), "utf8"));
|
|
122
145
|
log.normal(`Version: ${pkg.version}`);
|
|
123
146
|
}
|
|
124
147
|
catch {
|
|
125
148
|
// version not available
|
|
126
149
|
}
|
|
127
|
-
// Show enabled features
|
|
128
150
|
const enabled = [];
|
|
129
151
|
if (config.features.mutationQueue.enabled)
|
|
130
152
|
enabled.push("mutation-queue");
|
|
@@ -134,57 +156,28 @@ export async function infoCommand(projectRoot, feature) {
|
|
|
134
156
|
enabled.push("auth");
|
|
135
157
|
if (config.features.crossTabSync)
|
|
136
158
|
enabled.push("cross-tab");
|
|
137
|
-
if (config.features.tagInvalidation)
|
|
138
|
-
enabled.push("tag-invalidation");
|
|
139
159
|
if (config.features.graphql.enabled)
|
|
140
160
|
enabled.push("graphql");
|
|
141
161
|
if (config.features.pushNotifications?.enabled)
|
|
142
162
|
enabled.push("push-notification");
|
|
163
|
+
if (config.features.serverPush.enabled)
|
|
164
|
+
enabled.push("server-push");
|
|
143
165
|
if (config.features.pwa.enabled)
|
|
144
166
|
enabled.push("pwa");
|
|
167
|
+
enabled.push("tag-invalidation");
|
|
145
168
|
if (enabled.length > 0) {
|
|
146
169
|
log.normal(`\nEnabled features: ${enabled.join(", ")}`);
|
|
147
170
|
}
|
|
148
171
|
else {
|
|
149
172
|
log.normal("\nEnabled features: (none)");
|
|
150
173
|
}
|
|
151
|
-
// Count generated files
|
|
152
174
|
const swoffDir = join(projectRoot, "swoff");
|
|
153
175
|
if (existsSync(swoffDir)) {
|
|
154
176
|
const count = countFilesRecursive(swoffDir);
|
|
155
177
|
log.normal(`Generated files: ${count} in swoff/`);
|
|
156
178
|
}
|
|
157
179
|
log.help("\n swoff info <feature> — detailed info for a feature");
|
|
158
|
-
log.help(" Features: mutation-queue, background-sync, auth, tag-invalidation, cross-tab, graphql, push-notification,
|
|
159
|
-
log.help(" Read swoff/GUIDE.md for
|
|
160
|
-
}
|
|
161
|
-
function showFeatureDetail(feature) {
|
|
162
|
-
const key = feature.toLowerCase().replace(/[_-]/g, "-").replace(/^-+|-+$/g, "");
|
|
163
|
-
const info = FEATURES[key];
|
|
164
|
-
if (!info) {
|
|
165
|
-
log.error(`Unknown feature: ${feature}`);
|
|
166
|
-
log.info("Available: mutation-queue, background-sync, auth, tag-invalidation, cross-tab, graphql, push-notification, pwa");
|
|
167
|
-
return;
|
|
168
|
-
}
|
|
169
|
-
log.header(info.label);
|
|
170
|
-
log.normal(info.description);
|
|
171
|
-
log.normal("\nGenerated files:");
|
|
172
|
-
info.files.forEach((f) => log.help(` swoff/${f}`));
|
|
173
|
-
log.normal("\nFunctions:");
|
|
174
|
-
info.functions.forEach((f) => log.help(` ${f}`));
|
|
175
|
-
log.help("\n Read swoff/GUIDE.md for code examples and usage details.");
|
|
176
|
-
}
|
|
177
|
-
function countFilesRecursive(dir) {
|
|
178
|
-
let count = 0;
|
|
179
|
-
for (const entry of readdirSync(dir, { withFileTypes: true })) {
|
|
180
|
-
const full = join(dir, entry.name);
|
|
181
|
-
if (entry.isDirectory()) {
|
|
182
|
-
count += countFilesRecursive(full);
|
|
183
|
-
}
|
|
184
|
-
else {
|
|
185
|
-
count++;
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
return count;
|
|
180
|
+
log.help(" Features: mutation-queue, background-sync, auth, tag-invalidation, cross-tab, graphql, push-notification, server-push, pwa");
|
|
181
|
+
log.help(" Read swoff/GUIDE.md for documentation links");
|
|
189
182
|
}
|
|
190
183
|
//# sourceMappingURL=info.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"info.js","sourceRoot":"","sources":["../../../src/lib/commands/info.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"info.js","sourceRoot":"","sources":["../../../src/lib/commands/info.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,13 +1,23 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* init command - creates swoff.config.json
|
|
2
|
+
* init command - creates swoff.config.json.
|
|
3
3
|
*/
|
|
4
|
-
import { writeFileSync, existsSync
|
|
4
|
+
import { writeFileSync, existsSync } from "fs";
|
|
5
5
|
import { join } from "path";
|
|
6
|
+
import { createInterface } from "readline";
|
|
6
7
|
import { log } from "../cli/logger.js";
|
|
7
|
-
import { defaultInitConfig } from "../shared/config-types.js";
|
|
8
|
+
import { defaultInitConfig, defaultPwaAssets, } from "../shared/config-types.js";
|
|
8
9
|
import { detectFramework } from "../utils/detect-framework.js";
|
|
10
|
+
function ask(question) {
|
|
11
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
12
|
+
return new Promise((resolve) => {
|
|
13
|
+
rl.question(` ${question} `, (answer) => {
|
|
14
|
+
rl.close();
|
|
15
|
+
resolve(answer.trim());
|
|
16
|
+
});
|
|
17
|
+
});
|
|
18
|
+
}
|
|
9
19
|
export async function initCommand(projectRoot, framework) {
|
|
10
|
-
log.header("Initializing Swoff");
|
|
20
|
+
// log.header("Initializing Swoff");
|
|
11
21
|
const configFiles = ["swoff.config.json", "swoff.config.js"];
|
|
12
22
|
const existingConfig = configFiles.find((f) => existsSync(join(projectRoot, f)));
|
|
13
23
|
if (existingConfig) {
|
|
@@ -18,22 +28,26 @@ export async function initCommand(projectRoot, framework) {
|
|
|
18
28
|
const detected = framework || detectFramework(projectRoot);
|
|
19
29
|
const config = {
|
|
20
30
|
$schema: defaultInitConfig.$schema,
|
|
31
|
+
configVersion: defaultInitConfig.configVersion,
|
|
21
32
|
enabled: defaultInitConfig.enabled,
|
|
22
33
|
framework: detected,
|
|
23
34
|
build: defaultInitConfig.build,
|
|
24
|
-
features:
|
|
35
|
+
features: {
|
|
36
|
+
...defaultInitConfig.features,
|
|
37
|
+
pwa: {
|
|
38
|
+
...defaultInitConfig.features.pwa,
|
|
39
|
+
assets: { ...defaultPwaAssets },
|
|
40
|
+
},
|
|
41
|
+
},
|
|
25
42
|
};
|
|
43
|
+
const logoPath = await ask("Path to your app logo (SVG, PNG, JPG) — leave empty for placeholder:");
|
|
44
|
+
if (logoPath) {
|
|
45
|
+
config.features.pwa.assets.source = logoPath;
|
|
46
|
+
log.info("Logo source saved.");
|
|
47
|
+
}
|
|
26
48
|
const configPath = join(projectRoot, "swoff.config.json");
|
|
27
49
|
writeFileSync(configPath, JSON.stringify(config, null, 2));
|
|
28
50
|
log.info("Created swoff.config.json");
|
|
29
|
-
const dirs = ["swoff", "swoff/hooks"];
|
|
30
|
-
for (const dir of dirs) {
|
|
31
|
-
const dirPath = join(projectRoot, dir);
|
|
32
|
-
if (!existsSync(dirPath)) {
|
|
33
|
-
mkdirSync(dirPath, { recursive: true });
|
|
34
|
-
log.info(`Created ${dir}/`);
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
51
|
log.success("Swoff initialized successfully!");
|
|
38
52
|
log.normal("\nNext steps:");
|
|
39
53
|
log.help("1. Review swoff.config.json and customize as needed");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../../src/lib/commands/init.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../../src/lib/commands/init.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AAC/C,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAC3C,OAAO,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAC;AACvC,OAAO,EACL,iBAAiB,EACjB,gBAAgB,GAEjB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAE/D,SAAS,GAAG,CAAC,QAAgB;IAC3B,MAAM,EAAE,GAAG,eAAe,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAC7E,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,EAAE,CAAC,QAAQ,CAAC,KAAK,QAAQ,GAAG,EAAE,CAAC,MAAM,EAAE,EAAE;YACvC,EAAE,CAAC,KAAK,EAAE,CAAC;YACX,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;QACzB,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,WAAmB,EAAE,SAAkB;IACvE,oCAAoC;IAEpC,MAAM,WAAW,GAAG,CAAC,mBAAmB,EAAE,iBAAiB,CAAC,CAAC;IAC7D,MAAM,cAAc,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAC5C,UAAU,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,CACjC,CAAC;IAEF,IAAI,cAAc,EAAE,CAAC;QACnB,GAAG,CAAC,IAAI,CAAC,kBAAkB,cAAc,kBAAkB,CAAC,CAAC;QAC7D,GAAG,CAAC,IAAI,CAAC,gDAAgD,CAAC,CAAC;QAC3D,OAAO;IACT,CAAC;IAED,MAAM,QAAQ,GAAG,SAAS,IAAI,eAAe,CAAC,WAAW,CAAC,CAAC;IAC3D,MAAM,MAAM,GAAG;QACb,OAAO,EAAE,iBAAiB,CAAC,OAAO;QAClC,aAAa,EAAE,iBAAiB,CAAC,aAAa;QAC9C,OAAO,EAAE,iBAAiB,CAAC,OAAO;QAClC,SAAS,EAAE,QAAoC;QAC/C,KAAK,EAAE,iBAAiB,CAAC,KAAK;QAC9B,QAAQ,EAAE;YACR,GAAG,iBAAiB,CAAC,QAAQ;YAC7B,GAAG,EAAE;gBACH,GAAG,iBAAiB,CAAC,QAAQ,CAAC,GAAG;gBACjC,MAAM,EAAE,EAAE,GAAG,gBAAgB,EAAE;aAChC;SACF;KACF,CAAC;IAEF,MAAM,QAAQ,GAAG,MAAM,GAAG,CACxB,sEAAsE,CACvE,CAAC;IACF,IAAI,QAAQ,EAAE,CAAC;QACb,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,GAAG,QAAQ,CAAC;QAC7C,GAAG,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;IACjC,CAAC;IAED,MAAM,UAAU,GAAG,IAAI,CAAC,WAAW,EAAE,mBAAmB,CAAC,CAAC;IAC1D,aAAa,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IAC3D,GAAG,CAAC,IAAI,CAAC,2BAA2B,CAAC,CAAC;IAEtC,GAAG,CAAC,OAAO,CAAC,iCAAiC,CAAC,CAAC;IAC/C,GAAG,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC;IAC5B,GAAG,CAAC,IAAI,CAAC,qDAAqD,CAAC,CAAC;IAChE,GAAG,CAAC,IAAI,CAAC,iCAAiC,CAAC,CAAC;IAC5C,GAAG,CAAC,IAAI,CAAC,kDAAkD,CAAC,CAAC;AAC/D,CAAC"}
|
|
@@ -5,7 +5,7 @@ import { log } from "../cli/logger.js";
|
|
|
5
5
|
import { loadConfigAsync } from "../config/loader.js";
|
|
6
6
|
import { validateConfig } from "../config/validator.js";
|
|
7
7
|
export async function validateCommand(projectRoot) {
|
|
8
|
-
log.header("Validating Swoff Configuration");
|
|
8
|
+
// log.header("Validating Swoff Configuration");
|
|
9
9
|
const { config, configPath, configSource } = await loadConfigAsync(projectRoot);
|
|
10
10
|
if (!configPath) {
|
|
11
11
|
log.warn('No swoff.config.json found. Run "swoff init" first.');
|
|
@@ -20,9 +20,9 @@ export async function validateCommand(projectRoot) {
|
|
|
20
20
|
}
|
|
21
21
|
log.success("Configuration is valid!");
|
|
22
22
|
log.info("\nConfig summary:");
|
|
23
|
-
log.help(`Version
|
|
24
|
-
log.help(`
|
|
25
|
-
log.help(`Default strategy: ${config.features.serviceWorker.
|
|
23
|
+
log.help(`Version: ${config.features.serviceWorker.version}`);
|
|
24
|
+
log.help(`Min supported version: ${config.features.serviceWorker.minSupportedVersion}`);
|
|
25
|
+
log.help(`Default strategy: ${config.features.serviceWorker.strategy.default}`);
|
|
26
26
|
log.help(`Auto update: ${config.features.serviceWorker.autoUpdate}`);
|
|
27
27
|
log.help(`Features enabled: ${Object.entries(config.features)
|
|
28
28
|
.filter(([k, v]) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validate.js","sourceRoot":"","sources":["../../../src/lib/commands/validate.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAC;AACvC,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAExD,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,WAAmB;IACvD,
|
|
1
|
+
{"version":3,"file":"validate.js","sourceRoot":"","sources":["../../../src/lib/commands/validate.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAC;AACvC,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAExD,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,WAAmB;IACvD,gDAAgD;IAEhD,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,YAAY,EAAE,GACxC,MAAM,eAAe,CAAC,WAAW,CAAC,CAAC;IAErC,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,GAAG,CAAC,IAAI,CAAC,qDAAqD,CAAC,CAAC;QAChE,OAAO;IACT,CAAC;IAED,GAAG,CAAC,IAAI,CAAC,cAAc,UAAU,KAAK,CAAC,CAAC;IAExC,MAAM,MAAM,GAAG,cAAc,CAAC,MAA4C,CAAC,CAAC;IAE5E,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACtB,GAAG,CAAC,KAAK,CAAC,0BAA0B,MAAM,CAAC,MAAM,YAAY,CAAC,CAAC;QAC/D,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC;QAC5C,OAAO;IACT,CAAC;IAED,GAAG,CAAC,OAAO,CAAC,yBAAyB,CAAC,CAAC;IACvC,GAAG,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;IAC9B,GAAG,CAAC,IAAI,CAAC,YAAY,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAC,OAAO,EAAE,CAAC,CAAC;IAC9D,GAAG,CAAC,IAAI,CACN,0BAA0B,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAC,mBAAmB,EAAE,CAC9E,CAAC;IACF,GAAG,CAAC,IAAI,CACN,qBAAqB,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC,OAAO,EAAE,CACtE,CAAC;IACF,GAAG,CAAC,IAAI,CAAC,gBAAgB,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAC,UAAU,EAAE,CAAC,CAAC;IACrE,GAAG,CAAC,IAAI,CACN,qBAAqB,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC;SACjD,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE;QACjB,IAAI,CAAC,KAAK,eAAe;YAAE,OAAO,KAAK,CAAC;QACxC,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,IAAI;YACrC,OAAQ,CAA6B,CAAC,OAAO,KAAK,IAAI,CAAC;QACzD,OAAO,CAAC,KAAK,IAAI,CAAC;IACpB,CAAC,CAAC;SACD,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;SACf,IAAI,CAAC,IAAI,CAAC,EAAE,CAChB,CAAC;AACJ,CAAC"}
|
|
@@ -4,7 +4,17 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import { readFileSync, existsSync } from "fs";
|
|
6
6
|
import { join } from "path";
|
|
7
|
-
import { defaultConfig, mergeConfigs } from "../shared/config-types.js";
|
|
7
|
+
import { defaultConfig, mergeConfigs, CONFIG_VERSION } from "../shared/config-types.js";
|
|
8
|
+
function checkConfigVersion(config) {
|
|
9
|
+
if (config.configVersion === undefined) {
|
|
10
|
+
console.warn("[swoff] Config is missing configVersion — the format may have changed since it was created.\n" +
|
|
11
|
+
" Add \"configVersion\": 1 to your swoff.config.json to suppress this warning.");
|
|
12
|
+
}
|
|
13
|
+
else if (config.configVersion > CONFIG_VERSION) {
|
|
14
|
+
console.warn(`[swoff] Config has configVersion ${config.configVersion}, but this CLI version supports up to ${CONFIG_VERSION}.\n` +
|
|
15
|
+
" Some settings may not be recognized. Upgrade @swoff/cli for full compatibility.");
|
|
16
|
+
}
|
|
17
|
+
}
|
|
8
18
|
/**
|
|
9
19
|
* Load config from project root. Tries JSON first, then JS.
|
|
10
20
|
* Falls back to defaults if no config found or parse fails.
|
|
@@ -16,13 +26,12 @@ export function loadConfig(projectRoot, explicitPath) {
|
|
|
16
26
|
if (explicitPath.endsWith(".json")) {
|
|
17
27
|
try {
|
|
18
28
|
const raw = JSON.parse(readFileSync(explicitPath, "utf8"));
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
configSource: "JSON",
|
|
23
|
-
};
|
|
29
|
+
const config = mergeConfigs(defaultConfig, raw);
|
|
30
|
+
checkConfigVersion(config);
|
|
31
|
+
return { config, configPath: explicitPath, configSource: "JSON" };
|
|
24
32
|
}
|
|
25
33
|
catch {
|
|
34
|
+
console.warn(`[swoff] Warning: Failed to parse explicit config "${explicitPath}" — falling back to defaults`);
|
|
26
35
|
return { config: defaultConfig, configPath: null, configSource: "defaults" };
|
|
27
36
|
}
|
|
28
37
|
}
|
|
@@ -35,23 +44,17 @@ export function loadConfig(projectRoot, explicitPath) {
|
|
|
35
44
|
if (file.endsWith(".json")) {
|
|
36
45
|
try {
|
|
37
46
|
const raw = JSON.parse(readFileSync(path, "utf8"));
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
configSource: "JSON",
|
|
42
|
-
};
|
|
47
|
+
const config = mergeConfigs(defaultConfig, raw);
|
|
48
|
+
checkConfigVersion(config);
|
|
49
|
+
return { config, configPath: path, configSource: "JSON" };
|
|
43
50
|
}
|
|
44
51
|
catch {
|
|
45
|
-
|
|
52
|
+
console.warn(`[swoff] Warning: Failed to parse "${path}" — falling back to defaults`);
|
|
46
53
|
}
|
|
47
54
|
}
|
|
48
|
-
//
|
|
55
|
+
// JS configs require the async loader
|
|
49
56
|
if (file.endsWith(".js")) {
|
|
50
|
-
|
|
51
|
-
config: defaultConfig,
|
|
52
|
-
configPath: path,
|
|
53
|
-
configSource: "JavaScript",
|
|
54
|
-
};
|
|
57
|
+
throw new Error(`JavaScript config files require the async loader. Use loadConfigAsync() instead of loadConfig() for "${path}".`);
|
|
55
58
|
}
|
|
56
59
|
}
|
|
57
60
|
return { config: defaultConfig, configPath: null, configSource: "defaults" };
|
|
@@ -65,13 +68,12 @@ export async function loadConfigAsync(projectRoot, explicitPath) {
|
|
|
65
68
|
try {
|
|
66
69
|
const mod = await import(syncResult.configPath);
|
|
67
70
|
const raw = (mod.default || mod);
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
configSource: "JavaScript",
|
|
72
|
-
};
|
|
71
|
+
const config = mergeConfigs(defaultConfig, raw);
|
|
72
|
+
checkConfigVersion(config);
|
|
73
|
+
return { config, configPath: syncResult.configPath, configSource: "JavaScript" };
|
|
73
74
|
}
|
|
74
75
|
catch {
|
|
76
|
+
console.warn(`[swoff] Warning: Failed to load JS config "${syncResult.configPath}" — falling back to defaults`);
|
|
75
77
|
return { config: defaultConfig, configPath: null, configSource: "defaults" };
|
|
76
78
|
}
|
|
77
79
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loader.js","sourceRoot":"","sources":["../../../src/lib/config/loader.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AAC9C,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,aAAa,EAAE,YAAY,EAAoB,MAAM,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"loader.js","sourceRoot":"","sources":["../../../src/lib/config/loader.ts"],"names":[],"mappings":"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"}
|