@swoff/cli 0.3.13 → 0.3.14
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 +28 -32
- package/dist/index.js +2 -13
- package/dist/index.js.map +1 -1
- package/dist/lib/cli/help.js +3 -8
- package/dist/lib/cli/help.js.map +1 -1
- package/dist/lib/commands/add.js +29 -87
- package/dist/lib/commands/add.js.map +1 -1
- package/dist/lib/commands/generate-guide.js +16 -30
- package/dist/lib/commands/generate-guide.js.map +1 -1
- package/dist/lib/commands/generate.js +31 -6
- package/dist/lib/commands/generate.js.map +1 -1
- package/dist/lib/commands/init.js +188 -11
- package/dist/lib/commands/init.js.map +1 -1
- package/dist/lib/commands/validate.js +2 -4
- package/dist/lib/commands/validate.js.map +1 -1
- package/dist/lib/config/loader.js +34 -25
- package/dist/lib/config/loader.js.map +1 -1
- package/dist/lib/config/validator.js +202 -96
- package/dist/lib/config/validator.js.map +1 -1
- package/dist/lib/generators/file-generators/api-config.js +1 -1
- package/dist/lib/generators/file-generators/api-config.js.map +1 -1
- package/dist/lib/generators/file-generators/auth-adapter.js +13 -0
- package/dist/lib/generators/file-generators/auth-adapter.js.map +1 -0
- package/dist/lib/generators/file-generators/auth-check.js +40 -0
- package/dist/lib/generators/file-generators/auth-check.js.map +1 -0
- package/dist/lib/generators/file-generators/auth-store.js +2 -5
- package/dist/lib/generators/file-generators/auth-store.js.map +1 -1
- package/dist/lib/generators/file-generators/background-sync.js +1 -1
- package/dist/lib/generators/file-generators/background-sync.js.map +1 -1
- package/dist/lib/generators/file-generators/cache.js +2 -1
- package/dist/lib/generators/file-generators/cache.js.map +1 -1
- package/dist/lib/generators/file-generators/client-injector-bundle.js +15 -0
- package/dist/lib/generators/file-generators/client-injector-bundle.js.map +1 -0
- package/dist/lib/generators/file-generators/client-injector.js +2 -1
- package/dist/lib/generators/file-generators/client-injector.js.map +1 -1
- package/dist/lib/generators/file-generators/connectivity-manager.js +12 -0
- package/dist/lib/generators/file-generators/connectivity-manager.js.map +1 -0
- package/dist/lib/generators/file-generators/connectivity.js +12 -0
- package/dist/lib/generators/file-generators/connectivity.js.map +1 -0
- package/dist/lib/generators/file-generators/context.js +7 -0
- package/dist/lib/generators/file-generators/context.js.map +1 -1
- package/dist/lib/generators/file-generators/fetch-wrapper.js +1 -1
- package/dist/lib/generators/file-generators/fetch-wrapper.js.map +1 -1
- package/dist/lib/generators/file-generators/generate-framework-adapters.js +29 -20
- package/dist/lib/generators/file-generators/generate-framework-adapters.js.map +1 -1
- package/dist/lib/generators/file-generators/gql-wrapper.js +2 -2
- package/dist/lib/generators/file-generators/gql-wrapper.js.map +1 -1
- package/dist/lib/generators/file-generators/guide-generator.js +51 -1
- package/dist/lib/generators/file-generators/guide-generator.js.map +1 -1
- package/dist/lib/generators/file-generators/invalidation-tags.js +2 -3
- package/dist/lib/generators/file-generators/invalidation-tags.js.map +1 -1
- package/dist/lib/generators/file-generators/mutation-queue.js +2 -2
- package/dist/lib/generators/file-generators/mutation-queue.js.map +1 -1
- package/dist/lib/generators/file-generators/mutation-state.js +1 -1
- package/dist/lib/generators/file-generators/mutation-state.js.map +1 -1
- package/dist/lib/generators/file-generators/notification-generator.js +6 -0
- package/dist/lib/generators/file-generators/notification-generator.js.map +1 -0
- package/dist/lib/generators/file-generators/open-db.js +6 -0
- package/dist/lib/generators/file-generators/open-db.js.map +1 -0
- package/dist/lib/generators/file-generators/push.js +1 -2
- package/dist/lib/generators/file-generators/push.js.map +1 -1
- package/dist/lib/generators/file-generators/pwa-install.js +2 -6
- package/dist/lib/generators/file-generators/pwa-install.js.map +1 -1
- package/dist/lib/generators/file-generators/server-push.js +1 -1
- package/dist/lib/generators/file-generators/server-push.js.map +1 -1
- package/dist/lib/generators/file-generators/storage-generator.js +6 -0
- package/dist/lib/generators/file-generators/storage-generator.js.map +1 -0
- package/dist/lib/generators/file-generators/storage-notify.js +6 -0
- package/dist/lib/generators/file-generators/storage-notify.js.map +1 -0
- package/dist/lib/generators/file-generators/storage.js +6 -0
- package/dist/lib/generators/file-generators/storage.js.map +1 -0
- package/dist/lib/generators/file-generators/sw-generator-build.js +96 -45
- package/dist/lib/generators/file-generators/sw-generator-build.js.map +1 -1
- package/dist/lib/generators/file-generators/sw-injector.js +0 -4
- package/dist/lib/generators/file-generators/sw-injector.js.map +1 -1
- package/dist/lib/generators/file-generators/sw-template.js +8 -9
- package/dist/lib/generators/file-generators/sw-template.js.map +1 -1
- package/dist/lib/generators/file-generators/sw-version-gen.js +32 -0
- package/dist/lib/generators/file-generators/sw-version-gen.js.map +1 -0
- package/dist/lib/generators/file-generators/swoff-api-bundle.js +51 -0
- package/dist/lib/generators/file-generators/swoff-api-bundle.js.map +1 -0
- package/dist/lib/generators/sw-build-utils.js +69 -0
- package/dist/lib/generators/sw-build-utils.js.map +1 -0
- package/dist/lib/generators/sw-generator.js +23 -34
- package/dist/lib/generators/sw-generator.js.map +1 -1
- package/dist/lib/generators/sw-sections/activate-handler.js +74 -23
- package/dist/lib/generators/sw-sections/activate-handler.js.map +1 -1
- package/dist/lib/generators/sw-sections/assemble-sw.js +15 -94
- package/dist/lib/generators/sw-sections/assemble-sw.js.map +1 -1
- package/dist/lib/generators/sw-sections/background-sync-handler.js +74 -72
- package/dist/lib/generators/sw-sections/background-sync-handler.js.map +1 -1
- package/dist/lib/generators/sw-sections/batch-refresh-queue.js +102 -0
- package/dist/lib/generators/sw-sections/batch-refresh-queue.js.map +1 -0
- package/dist/lib/generators/sw-sections/config-header.js +2 -3
- package/dist/lib/generators/sw-sections/config-header.js.map +1 -1
- package/dist/lib/generators/sw-sections/default-template.js +59 -6
- package/dist/lib/generators/sw-sections/default-template.js.map +1 -1
- package/dist/lib/generators/sw-sections/fetch-handler.js +621 -495
- package/dist/lib/generators/sw-sections/fetch-handler.js.map +1 -1
- package/dist/lib/generators/sw-sections/install-handler.js +40 -23
- package/dist/lib/generators/sw-sections/install-handler.js.map +1 -1
- package/dist/lib/generators/sw-sections/message-handler.js +25 -8
- package/dist/lib/generators/sw-sections/message-handler.js.map +1 -1
- package/dist/lib/generators/sw-sections/server-push-handler.js +10 -14
- package/dist/lib/generators/sw-sections/server-push-handler.js.map +1 -1
- package/dist/lib/generators/sw-sections/shared.js +68 -0
- package/dist/lib/generators/sw-sections/shared.js.map +1 -0
- package/dist/lib/generators/sw-sections/sw-push.js +2 -6
- package/dist/lib/generators/sw-sections/sw-push.js.map +1 -1
- package/dist/lib/generators/sw-sections/tag-management.js +55 -86
- package/dist/lib/generators/sw-sections/tag-management.js.map +1 -1
- package/dist/lib/generators/swoff-files-generator.js +183 -59
- package/dist/lib/generators/swoff-files-generator.js.map +1 -1
- package/dist/lib/shared/config-types.js +67 -63
- package/dist/lib/shared/config-types.js.map +1 -1
- package/dist/lib/shared/feature-registry.js +198 -0
- package/dist/lib/shared/feature-registry.js.map +1 -0
- package/dist/lib/utils/detect-framework.js +52 -9
- package/dist/lib/utils/detect-framework.js.map +1 -1
- package/dist/runtime/api-config.js +2 -2
- package/dist/runtime/api-config.js.map +1 -1
- package/dist/runtime/auth-adapter.js +179 -0
- package/dist/runtime/auth-adapter.js.map +1 -0
- package/dist/runtime/auth-state.js +16 -6
- package/dist/runtime/auth-state.js.map +1 -1
- package/dist/runtime/auth-store.js +219 -213
- package/dist/runtime/auth-store.js.map +1 -1
- package/dist/runtime/auth-user.js +5 -19
- package/dist/runtime/auth-user.js.map +1 -1
- package/dist/runtime/background-sync.js +5 -2
- package/dist/runtime/background-sync.js.map +1 -1
- package/dist/runtime/cache.js +91 -3
- package/dist/runtime/cache.js.map +1 -1
- package/dist/runtime/client-injector-bundle.js +314 -0
- package/dist/runtime/client-injector-bundle.js.map +1 -0
- package/dist/runtime/client-injector.js +173 -30
- package/dist/runtime/client-injector.js.map +1 -1
- package/dist/runtime/connectivity-manager.js +83 -0
- package/dist/runtime/connectivity-manager.js.map +1 -0
- package/dist/runtime/connectivity.js +83 -0
- package/dist/runtime/connectivity.js.map +1 -0
- package/dist/runtime/fetch-wrapper.js +26 -59
- package/dist/runtime/fetch-wrapper.js.map +1 -1
- package/dist/runtime/gql-wrapper.js +15 -9
- package/dist/runtime/gql-wrapper.js.map +1 -1
- package/dist/runtime/invalidation-tags.js +12 -89
- package/dist/runtime/invalidation-tags.js.map +1 -1
- package/dist/runtime/mutation-queue.js +83 -31
- package/dist/runtime/mutation-queue.js.map +1 -1
- package/dist/runtime/mutation-state.js +3 -3
- package/dist/runtime/mutation-state.js.map +1 -1
- package/dist/runtime/notification.js +65 -0
- package/dist/runtime/notification.js.map +1 -0
- package/dist/runtime/open-db.js +41 -0
- package/dist/runtime/open-db.js.map +1 -0
- package/dist/runtime/push.js +15 -27
- package/dist/runtime/push.js.map +1 -1
- package/dist/runtime/pwa-injector.js +3 -32
- package/dist/runtime/pwa-injector.js.map +1 -1
- package/dist/runtime/pwa-prompt.js +35 -3
- package/dist/runtime/pwa-prompt.js.map +1 -1
- package/dist/runtime/reset.js +39 -42
- package/dist/runtime/reset.js.map +1 -1
- package/dist/runtime/server-push.js +23 -13
- package/dist/runtime/server-push.js.map +1 -1
- package/dist/runtime/storage.js +32 -0
- package/dist/runtime/storage.js.map +1 -0
- package/dist/runtime/sw-injector.js +19 -178
- package/dist/runtime/sw-injector.js.map +1 -1
- package/dist/runtime/sw-version.js +13 -0
- package/dist/runtime/sw-version.js.map +1 -0
- package/dist/runtime/swoff-api-bundle.js +1491 -0
- package/dist/runtime/swoff-api-bundle.js.map +1 -0
- package/dist/runtime/type-definitions.js +8 -7
- package/dist/runtime/type-definitions.js.map +1 -1
- package/dist/runtime/utils.js +4 -0
- package/dist/runtime/utils.js.map +1 -1
- package/dist/swoff-nkdhhmw8. +18 -0
- package/dist/swoff.js +5 -0
- package/package.json +1 -1
- package/templates/react/useAuth.jsx +7 -4
- package/templates/react/useAuth.tsx +14 -14
- package/templates/react/useBackgroundSync.jsx +5 -4
- package/templates/react/useBackgroundSync.tsx +5 -4
- package/templates/react/useCachedFetch.jsx +8 -0
- package/templates/react/useCachedFetch.tsx +8 -0
- package/templates/react/useMutation.jsx +60 -56
- package/templates/react/useMutation.tsx +65 -64
- package/templates/react/useMutationQueue.jsx +5 -1
- package/templates/react/useMutationQueue.tsx +8 -2
- package/templates/react/useMutationState.jsx +3 -4
- package/templates/react/useMutationState.tsx +4 -8
- package/templates/react/useNetworkStatus.jsx +57 -17
- package/templates/react/useNetworkStatus.tsx +42 -20
- package/templates/react/useOfflineAnalytics.jsx +42 -0
- package/templates/react/useOfflineAnalytics.tsx +50 -0
- package/templates/react/usePwaInstall.jsx +26 -0
- package/templates/react/usePwaInstall.tsx +26 -0
- package/templates/react/useSWUpdate.jsx +7 -52
- package/templates/react/useSWUpdate.tsx +12 -51
- package/templates/react/useStorageEstimate.jsx +56 -0
- package/templates/react/useStorageEstimate.tsx +67 -0
- package/dist/__tests__/assemble-sw.test.js +0 -145
- package/dist/__tests__/assemble-sw.test.js.map +0 -1
- package/dist/__tests__/cli-integration.test.js +0 -231
- package/dist/__tests__/cli-integration.test.js.map +0 -1
- package/dist/__tests__/config-types.test.js +0 -124
- package/dist/__tests__/config-types.test.js.map +0 -1
- package/dist/__tests__/detect-language.test.js +0 -51
- package/dist/__tests__/detect-language.test.js.map +0 -1
- package/dist/__tests__/file-generators.test.js +0 -228
- package/dist/__tests__/file-generators.test.js.map +0 -1
- package/dist/__tests__/glob-matcher.test.js +0 -86
- package/dist/__tests__/glob-matcher.test.js.map +0 -1
- package/dist/__tests__/invalidation-tags.test.js +0 -283
- package/dist/__tests__/invalidation-tags.test.js.map +0 -1
- package/dist/__tests__/loader.test.js +0 -77
- package/dist/__tests__/loader.test.js.map +0 -1
- package/dist/__tests__/validator.test.js +0 -340
- package/dist/__tests__/validator.test.js.map +0 -1
- package/templates/react/useCacheInvalidation.jsx +0 -19
- package/templates/react/useCacheInvalidation.tsx +0 -52
- package/templates/react/useIsFetching.jsx +0 -32
- package/templates/react/useIsFetching.tsx +0 -32
|
@@ -1,228 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, beforeEach, afterEach } from "vitest";
|
|
2
|
-
import { existsSync, rmSync, readFileSync, mkdirSync } from "fs";
|
|
3
|
-
import { join } from "path";
|
|
4
|
-
import { defaultConfig } from "../lib/shared/config-types.js";
|
|
5
|
-
import { generateSwTemplate } from "../lib/generators/file-generators/sw-template.js";
|
|
6
|
-
import { generateSwInjector } from "../lib/generators/file-generators/sw-injector.js";
|
|
7
|
-
import { generateClientInjector } from "../lib/generators/file-generators/client-injector.js";
|
|
8
|
-
import { generateFetchWrapper } from "../lib/generators/file-generators/fetch-wrapper.js";
|
|
9
|
-
import { generateCache } from "../lib/generators/file-generators/cache.js";
|
|
10
|
-
import { generateMutationQueue } from "../lib/generators/file-generators/mutation-queue.js";
|
|
11
|
-
import { generateBackgroundSync } from "../lib/generators/file-generators/background-sync.js";
|
|
12
|
-
import { generateSwGeneratorBuild } from "../lib/generators/file-generators/sw-generator-build.js";
|
|
13
|
-
import { generateTypeDefinitions } from "../lib/generators/file-generators/type-definitions.js";
|
|
14
|
-
const testDir = "/tmp/swoff-test-generators";
|
|
15
|
-
function makeContext(overrides) {
|
|
16
|
-
const config = {
|
|
17
|
-
...defaultConfig,
|
|
18
|
-
...overrides,
|
|
19
|
-
features: {
|
|
20
|
-
...defaultConfig.features,
|
|
21
|
-
...overrides?.features,
|
|
22
|
-
pwa: { ...defaultConfig.features.pwa, ...overrides?.features?.pwa },
|
|
23
|
-
serviceWorker: { ...defaultConfig.features.serviceWorker, ...overrides?.features?.serviceWorker },
|
|
24
|
-
},
|
|
25
|
-
build: { ...defaultConfig.build, ...overrides?.build },
|
|
26
|
-
};
|
|
27
|
-
return {
|
|
28
|
-
config,
|
|
29
|
-
projectRoot: testDir,
|
|
30
|
-
swoffDir: join(testDir, "swoff"),
|
|
31
|
-
ext: "js",
|
|
32
|
-
generatedFiles: [],
|
|
33
|
-
frameworkName: "vanilla",
|
|
34
|
-
};
|
|
35
|
-
}
|
|
36
|
-
beforeEach(() => {
|
|
37
|
-
if (existsSync(testDir))
|
|
38
|
-
rmSync(testDir, { recursive: true });
|
|
39
|
-
mkdirSync(testDir, { recursive: true });
|
|
40
|
-
});
|
|
41
|
-
afterEach(() => {
|
|
42
|
-
if (existsSync(testDir))
|
|
43
|
-
rmSync(testDir, { recursive: true });
|
|
44
|
-
});
|
|
45
|
-
describe("generateSwTemplate", () => {
|
|
46
|
-
it("produces a template with placeholders", () => {
|
|
47
|
-
const ctx = makeContext();
|
|
48
|
-
generateSwTemplate(ctx);
|
|
49
|
-
const content = readFileSync(join(ctx.swoffDir, "sw", "template.js"), "utf8");
|
|
50
|
-
expect(content).toContain("// [[CACHE_NAME]]");
|
|
51
|
-
expect(content).toContain("// [[ASSETS_LIST]]");
|
|
52
|
-
expect(content).toContain("// [[AUTO_SKIP_WAITING]]");
|
|
53
|
-
expect(content).toContain("CACHE_NAME_RUNTIME");
|
|
54
|
-
expect(content).toContain("self.addEventListener");
|
|
55
|
-
expect(content).toContain("fromPrecache");
|
|
56
|
-
});
|
|
57
|
-
it("includes config-driven strategy code", () => {
|
|
58
|
-
const ctx = makeContext({
|
|
59
|
-
features: { ...defaultConfig.features, serviceWorker: { ...defaultConfig.features.serviceWorker, strategy: { ...defaultConfig.features.serviceWorker.strategy, patterns: { "/api/*": "network-first" } } } },
|
|
60
|
-
});
|
|
61
|
-
generateSwTemplate(ctx);
|
|
62
|
-
const content = readFileSync(join(ctx.swoffDir, "sw", "template.js"), "utf8");
|
|
63
|
-
expect(content).toContain("determineCacheStrategy");
|
|
64
|
-
expect(content).toContain("fromPrecache");
|
|
65
|
-
expect(content).toContain("network-first");
|
|
66
|
-
expect(content).toContain("invalidateByTag");
|
|
67
|
-
});
|
|
68
|
-
});
|
|
69
|
-
describe("generateSwInjector", () => {
|
|
70
|
-
it("generates JS registration with correct config values", () => {
|
|
71
|
-
const ctx = makeContext({
|
|
72
|
-
features: { ...defaultConfig.features, serviceWorker: { ...defaultConfig.features.serviceWorker, autoUpdate: true, autoActivate: true } },
|
|
73
|
-
});
|
|
74
|
-
generateSwInjector(ctx);
|
|
75
|
-
const content = readFileSync(join(ctx.swoffDir, "sw", "injector.js"), "utf8");
|
|
76
|
-
expect(content).toContain("AUTO_UPDATE = true");
|
|
77
|
-
expect(content).toContain("AUTO_ACTIVATE = true");
|
|
78
|
-
expect(content).toContain("initServiceWorker");
|
|
79
|
-
expect(content).toContain("checkForUpdate");
|
|
80
|
-
expect(content).toContain("handleUpdateApproved");
|
|
81
|
-
expect(content).toContain("skipWaiting");
|
|
82
|
-
expect(content).toContain("waitForController");
|
|
83
|
-
expect(content).toContain("semverCompare");
|
|
84
|
-
});
|
|
85
|
-
it("generates TS when ext is ts", () => {
|
|
86
|
-
const ctx = makeContext();
|
|
87
|
-
ctx.ext = "ts";
|
|
88
|
-
generateSwInjector(ctx);
|
|
89
|
-
expect(existsSync(join(ctx.swoffDir, "sw", "injector.ts"))).toBe(true);
|
|
90
|
-
});
|
|
91
|
-
it("reflects autoUpdate false", () => {
|
|
92
|
-
const ctx = makeContext({
|
|
93
|
-
features: { ...defaultConfig.features, serviceWorker: { ...defaultConfig.features.serviceWorker, autoUpdate: false } },
|
|
94
|
-
});
|
|
95
|
-
generateSwInjector(ctx);
|
|
96
|
-
const content = readFileSync(join(ctx.swoffDir, "sw", "injector.js"), "utf8");
|
|
97
|
-
expect(content).toContain("AUTO_UPDATE = false");
|
|
98
|
-
});
|
|
99
|
-
it("generates simple injector when version mode is 'hash'", () => {
|
|
100
|
-
const ctx = makeContext({
|
|
101
|
-
features: { ...defaultConfig.features, serviceWorker: { ...defaultConfig.features.serviceWorker, version: "hash" } },
|
|
102
|
-
});
|
|
103
|
-
generateSwInjector(ctx);
|
|
104
|
-
const content = readFileSync(join(ctx.swoffDir, "sw", "injector.js"), "utf8");
|
|
105
|
-
expect(content).toContain("Simple Mode");
|
|
106
|
-
expect(content).toContain("navigator.serviceWorker.register(\"/sw.js\")");
|
|
107
|
-
expect(content).not.toContain("checkForUpdate");
|
|
108
|
-
expect(content).not.toContain("AUTO_UPDATE");
|
|
109
|
-
});
|
|
110
|
-
});
|
|
111
|
-
describe("generateClientInjector", () => {
|
|
112
|
-
it("generates orchestrator with PWA setup and SW message listener when pwa enabled", () => {
|
|
113
|
-
const ctx = makeContext({
|
|
114
|
-
features: { ...defaultConfig.features },
|
|
115
|
-
});
|
|
116
|
-
generateClientInjector(ctx);
|
|
117
|
-
const content = readFileSync(join(ctx.swoffDir, "client-injector.js"), "utf8");
|
|
118
|
-
expect(content).toContain("initServiceWorker");
|
|
119
|
-
expect(content).toContain("setupPwaInstall");
|
|
120
|
-
expect(content).toContain("SW_PROGRESS");
|
|
121
|
-
expect(content).toContain("BACKGROUND_SYNC_COMPLETE");
|
|
122
|
-
});
|
|
123
|
-
it("includes TAG_INVALIDATED handler when crossTabSync is enabled", () => {
|
|
124
|
-
const ctx = makeContext({
|
|
125
|
-
features: { ...defaultConfig.features, crossTabSync: true },
|
|
126
|
-
});
|
|
127
|
-
generateClientInjector(ctx);
|
|
128
|
-
const content = readFileSync(join(ctx.swoffDir, "client-injector.js"), "utf8");
|
|
129
|
-
expect(content).toContain("TAG_INVALIDATED");
|
|
130
|
-
expect(content).toContain('"cache-invalidated"');
|
|
131
|
-
});
|
|
132
|
-
it("includes setupPwaInstall and beforeinstallprompt import when pwa enabled", () => {
|
|
133
|
-
const ctx = makeContext({
|
|
134
|
-
features: { ...defaultConfig.features },
|
|
135
|
-
});
|
|
136
|
-
generateClientInjector(ctx);
|
|
137
|
-
const content = readFileSync(join(ctx.swoffDir, "client-injector.js"), "utf8");
|
|
138
|
-
expect(content).toContain("setupPwaInstall");
|
|
139
|
-
expect(content).toContain("./pwa/install");
|
|
140
|
-
});
|
|
141
|
-
it("always imports sw/injector", () => {
|
|
142
|
-
const ctx = makeContext({
|
|
143
|
-
features: { ...defaultConfig.features, pwa: { ...defaultConfig.features.pwa, enabled: true } },
|
|
144
|
-
});
|
|
145
|
-
generateClientInjector(ctx);
|
|
146
|
-
const content = readFileSync(join(ctx.swoffDir, "client-injector.js"), "utf8");
|
|
147
|
-
expect(content).toContain("swInit");
|
|
148
|
-
expect(content).toContain("./sw/injector");
|
|
149
|
-
expect(content).toContain("setupPwaInstall");
|
|
150
|
-
expect(content).not.toContain("No SW registration configured");
|
|
151
|
-
});
|
|
152
|
-
});
|
|
153
|
-
describe("generateFetchWrapper", () => {
|
|
154
|
-
it("exports fetchWithCache", () => {
|
|
155
|
-
const ctx = makeContext();
|
|
156
|
-
generateFetchWrapper(ctx);
|
|
157
|
-
const content = readFileSync(join(ctx.swoffDir, "fetch-wrapper.js"), "utf8");
|
|
158
|
-
expect(content).toContain("fetchWithCache");
|
|
159
|
-
});
|
|
160
|
-
});
|
|
161
|
-
describe("generateCache", () => {
|
|
162
|
-
it("exports cache invalidation functions", () => {
|
|
163
|
-
const ctx = makeContext();
|
|
164
|
-
generateCache(ctx);
|
|
165
|
-
const content = readFileSync(join(ctx.swoffDir, "cache.js"), "utf8");
|
|
166
|
-
expect(content).toContain("invalidateByTag");
|
|
167
|
-
expect(content).toContain("invalidateByTags");
|
|
168
|
-
expect(content).toContain("INVALIDATE_TAG");
|
|
169
|
-
expect(content).not.toContain("initCrossTabSync");
|
|
170
|
-
expect(content).not.toContain("TAG_INVALIDATED");
|
|
171
|
-
});
|
|
172
|
-
});
|
|
173
|
-
describe("generateMutationQueue", () => {
|
|
174
|
-
it("contains mutation queue functions", () => {
|
|
175
|
-
const ctx = makeContext();
|
|
176
|
-
generateMutationQueue(ctx);
|
|
177
|
-
const content = readFileSync(join(ctx.swoffDir, "mutation-queue.js"), "utf8");
|
|
178
|
-
expect(content).toContain("queueMutation");
|
|
179
|
-
expect(content).toContain("processMutationQueue");
|
|
180
|
-
expect(content).toContain("getPendingCount");
|
|
181
|
-
expect(content).toContain("MAX_RETRIES");
|
|
182
|
-
expect(content).toContain("swoff-queue");
|
|
183
|
-
});
|
|
184
|
-
});
|
|
185
|
-
describe("generateBackgroundSync", () => {
|
|
186
|
-
it("contains background sync utilities", () => {
|
|
187
|
-
const ctx = makeContext();
|
|
188
|
-
generateBackgroundSync(ctx);
|
|
189
|
-
const content = readFileSync(join(ctx.swoffDir, "background-sync.js"), "utf8");
|
|
190
|
-
expect(content).toContain("syncWhenPossible");
|
|
191
|
-
expect(content).toContain("retrySync");
|
|
192
|
-
expect(content).toContain("SYNC_TAG");
|
|
193
|
-
expect(content).toContain("SyncManager");
|
|
194
|
-
expect(content).toContain("sync-mutations");
|
|
195
|
-
});
|
|
196
|
-
});
|
|
197
|
-
describe("generateSwGeneratorBuild", () => {
|
|
198
|
-
it("generates build script with correct imports", () => {
|
|
199
|
-
const ctx = makeContext();
|
|
200
|
-
generateSwGeneratorBuild(ctx);
|
|
201
|
-
const content = readFileSync(join(ctx.swoffDir, "sw", "generator.js"), "utf8");
|
|
202
|
-
expect(content).toContain("#!/usr/bin/env node");
|
|
203
|
-
expect(content).toContain("readFileSync");
|
|
204
|
-
expect(content).toContain("writeFileSync");
|
|
205
|
-
expect(content).toContain("mkdirSync");
|
|
206
|
-
expect(content).toContain("template.js");
|
|
207
|
-
expect(content).toContain("createHash");
|
|
208
|
-
expect(content).not.toContain("import('fs').then");
|
|
209
|
-
});
|
|
210
|
-
});
|
|
211
|
-
describe("generateTypeDefinitions", () => {
|
|
212
|
-
it("generates type declarations when ext is ts", () => {
|
|
213
|
-
const ctx = makeContext();
|
|
214
|
-
ctx.ext = "ts";
|
|
215
|
-
generateTypeDefinitions(ctx);
|
|
216
|
-
const content = readFileSync(join(ctx.swoffDir, "swoff.d.ts"), "utf8");
|
|
217
|
-
expect(content).toContain("BeforeInstallPromptEvent");
|
|
218
|
-
expect(content).toContain("FetchWithCacheOptions");
|
|
219
|
-
expect(content).toContain("MutationQueueItem");
|
|
220
|
-
expect(content).toContain("MutationQueueResult");
|
|
221
|
-
});
|
|
222
|
-
it("skips generation when ext is js", () => {
|
|
223
|
-
const ctx = makeContext();
|
|
224
|
-
generateTypeDefinitions(ctx);
|
|
225
|
-
expect(ctx.generatedFiles).not.toContain("swoff/swoff.d.ts");
|
|
226
|
-
});
|
|
227
|
-
});
|
|
228
|
-
//# sourceMappingURL=file-generators.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"file-generators.test.js","sourceRoot":"","sources":["../../src/__tests__/file-generators.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, beforeEach } from "vitest";
|
|
2
|
-
import { matchGlob, clearGlobCache } from "../lib/shared/glob-matcher";
|
|
3
|
-
beforeEach(() => {
|
|
4
|
-
clearGlobCache();
|
|
5
|
-
});
|
|
6
|
-
describe("matchGlob", () => {
|
|
7
|
-
describe("wildcard (*)", () => {
|
|
8
|
-
it("matches single segment", () => {
|
|
9
|
-
expect(matchGlob("/api/users", "/api/*")).toBe(true);
|
|
10
|
-
});
|
|
11
|
-
it("does not cross segment boundary", () => {
|
|
12
|
-
expect(matchGlob("/api/users/123", "/api/*")).toBe(false);
|
|
13
|
-
});
|
|
14
|
-
it("matches within segment", () => {
|
|
15
|
-
expect(matchGlob("/api/users/123", "/api/users/*")).toBe(true);
|
|
16
|
-
});
|
|
17
|
-
});
|
|
18
|
-
describe("globstar (**)", () => {
|
|
19
|
-
it("matches across segments", () => {
|
|
20
|
-
expect(matchGlob("/api/users/123/posts", "/api/users/**")).toBe(true);
|
|
21
|
-
});
|
|
22
|
-
it("matches deep nesting", () => {
|
|
23
|
-
expect(matchGlob("/api/v1/users/123/posts/456", "/api/**")).toBe(true);
|
|
24
|
-
});
|
|
25
|
-
it("matches zero segments", () => {
|
|
26
|
-
expect(matchGlob("/api", "/api/**")).toBe(true);
|
|
27
|
-
});
|
|
28
|
-
});
|
|
29
|
-
describe("single char (?)", () => {
|
|
30
|
-
it("matches exactly one char", () => {
|
|
31
|
-
expect(matchGlob("/api/users/123", "/api/users/???")).toBe(true);
|
|
32
|
-
});
|
|
33
|
-
it("fails if wrong length", () => {
|
|
34
|
-
expect(matchGlob("/api/users/12", "/api/users/???")).toBe(false);
|
|
35
|
-
});
|
|
36
|
-
it("does not cross segments", () => {
|
|
37
|
-
expect(matchGlob("/api/users/1/2", "/api/users/?")).toBe(false);
|
|
38
|
-
});
|
|
39
|
-
});
|
|
40
|
-
describe("alternation ({a,b})", () => {
|
|
41
|
-
it("matches any alternative", () => {
|
|
42
|
-
expect(matchGlob("/api/users", "/api/{users,posts}")).toBe(true);
|
|
43
|
-
expect(matchGlob("/api/posts", "/api/{users,posts}")).toBe(true);
|
|
44
|
-
});
|
|
45
|
-
it("rejects non-matching", () => {
|
|
46
|
-
expect(matchGlob("/api/comments", "/api/{users,posts}")).toBe(false);
|
|
47
|
-
});
|
|
48
|
-
});
|
|
49
|
-
describe("negation (!)", () => {
|
|
50
|
-
it("inverts match result", () => {
|
|
51
|
-
expect(matchGlob("/api/internal/health", "!/api/internal/**")).toBe(false);
|
|
52
|
-
});
|
|
53
|
-
it("allows non-matching paths", () => {
|
|
54
|
-
expect(matchGlob("/api/users/123", "!/api/internal/**")).toBe(true);
|
|
55
|
-
});
|
|
56
|
-
});
|
|
57
|
-
describe("concrete paths", () => {
|
|
58
|
-
it("matches exact path", () => {
|
|
59
|
-
expect(matchGlob("/api/users", "/api/users")).toBe(true);
|
|
60
|
-
});
|
|
61
|
-
it("rejects different path", () => {
|
|
62
|
-
expect(matchGlob("/api/users/123", "/api/users")).toBe(false);
|
|
63
|
-
});
|
|
64
|
-
});
|
|
65
|
-
describe("complex patterns", () => {
|
|
66
|
-
it("matches nested with wildcards", () => {
|
|
67
|
-
expect(matchGlob("/api/v2/users/123", "/api/**/users/*")).toBe(true);
|
|
68
|
-
});
|
|
69
|
-
it("matches deep nested with globstar", () => {
|
|
70
|
-
expect(matchGlob("/a/b/c/d/e", "/a/**/e")).toBe(true);
|
|
71
|
-
});
|
|
72
|
-
it("matches with multiple wildcards", () => {
|
|
73
|
-
expect(matchGlob("/api/users/123/posts/456", "/api/*/123/*/456")).toBe(true);
|
|
74
|
-
});
|
|
75
|
-
});
|
|
76
|
-
describe("alternation in nested paths", () => {
|
|
77
|
-
it("matches with globstar and alternation", () => {
|
|
78
|
-
expect(matchGlob("/api/v1/users/123", "/api/**/{users,posts}/*")).toBe(true);
|
|
79
|
-
expect(matchGlob("/api/v1/posts/456", "/api/**/{users,posts}/*")).toBe(true);
|
|
80
|
-
});
|
|
81
|
-
it("rejects when alternation does not match", () => {
|
|
82
|
-
expect(matchGlob("/api/v1/comments/789", "/api/**/{users,posts}/*")).toBe(false);
|
|
83
|
-
});
|
|
84
|
-
});
|
|
85
|
-
});
|
|
86
|
-
//# sourceMappingURL=glob-matcher.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"glob-matcher.test.js","sourceRoot":"","sources":["../../src/__tests__/glob-matcher.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,283 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from "vitest";
|
|
2
|
-
// Replicate the segment-based generateTags logic for testing fallback
|
|
3
|
-
const SKIP_PREFIXES = ["api", "v1", "v2", "v3", "rest", "graphql", "gql"];
|
|
4
|
-
const SINGULARIZATION = {};
|
|
5
|
-
function generateTagsFallback(url) {
|
|
6
|
-
const parsed = new URL(url, "http://example.com");
|
|
7
|
-
const segments = parsed.pathname.split("/").filter(Boolean);
|
|
8
|
-
if (segments.length === 0)
|
|
9
|
-
return ["root"];
|
|
10
|
-
let startIdx = 0;
|
|
11
|
-
while (startIdx < segments.length && SKIP_PREFIXES.includes(segments[startIdx])) {
|
|
12
|
-
startIdx++;
|
|
13
|
-
}
|
|
14
|
-
const resourceSegments = segments.slice(startIdx);
|
|
15
|
-
if (resourceSegments.length === 0)
|
|
16
|
-
return ["root"];
|
|
17
|
-
const tags = [];
|
|
18
|
-
tags.push(resourceSegments[0]);
|
|
19
|
-
if (resourceSegments.length >= 2 && !isNaN(Number(resourceSegments[1]))) {
|
|
20
|
-
const collection = resourceSegments[0];
|
|
21
|
-
const id = resourceSegments[1];
|
|
22
|
-
const singular = SINGULARIZATION[collection] !== undefined
|
|
23
|
-
? SINGULARIZATION[collection]
|
|
24
|
-
: collection.replace(/s$/, "");
|
|
25
|
-
tags.push(`${singular}:${id}`);
|
|
26
|
-
}
|
|
27
|
-
for (let i = 2; i < resourceSegments.length; i++) {
|
|
28
|
-
if (isNaN(Number(resourceSegments[i]))) {
|
|
29
|
-
tags.push(resourceSegments[i]);
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
return tags;
|
|
33
|
-
}
|
|
34
|
-
describe("generateTags (segment-based fallback)", () => {
|
|
35
|
-
describe("basic URLs", () => {
|
|
36
|
-
it("returns root tag for root path", () => {
|
|
37
|
-
expect(generateTagsFallback("/")).toEqual(["root"]);
|
|
38
|
-
});
|
|
39
|
-
it("generates collection tag from simple path", () => {
|
|
40
|
-
expect(generateTagsFallback("/todos")).toEqual(["todos"]);
|
|
41
|
-
});
|
|
42
|
-
it("generates collection tag from API path", () => {
|
|
43
|
-
expect(generateTagsFallback("/api/todos")).toEqual(["todos"]);
|
|
44
|
-
});
|
|
45
|
-
it("generates resource tag with ID", () => {
|
|
46
|
-
expect(generateTagsFallback("/api/todos/42")).toEqual(["todos", "todo:42"]);
|
|
47
|
-
});
|
|
48
|
-
it("generates sub-resource tags", () => {
|
|
49
|
-
expect(generateTagsFallback("/api/todos/42/comments")).toEqual(["todos", "todo:42", "comments"]);
|
|
50
|
-
});
|
|
51
|
-
});
|
|
52
|
-
describe("API prefix skipping", () => {
|
|
53
|
-
it("skips /api prefix", () => {
|
|
54
|
-
expect(generateTagsFallback("/api/users/123")).toEqual(["users", "user:123"]);
|
|
55
|
-
});
|
|
56
|
-
it("skips /v1 prefix", () => {
|
|
57
|
-
expect(generateTagsFallback("/v1/users/123")).toEqual(["users", "user:123"]);
|
|
58
|
-
});
|
|
59
|
-
it("skips /v2 prefix", () => {
|
|
60
|
-
expect(generateTagsFallback("/v2/users/123")).toEqual(["users", "user:123"]);
|
|
61
|
-
});
|
|
62
|
-
it("skips multiple prefixes", () => {
|
|
63
|
-
expect(generateTagsFallback("/api/v1/users/123")).toEqual(["users", "user:123"]);
|
|
64
|
-
});
|
|
65
|
-
it("skips /graphql prefix", () => {
|
|
66
|
-
expect(generateTagsFallback("/graphql")).toEqual(["root"]);
|
|
67
|
-
});
|
|
68
|
-
it("skips /rest prefix", () => {
|
|
69
|
-
expect(generateTagsFallback("/rest/items/456")).toEqual(["items", "item:456"]);
|
|
70
|
-
});
|
|
71
|
-
});
|
|
72
|
-
describe("pluralization", () => {
|
|
73
|
-
it("singularizes collection name for resource tag", () => {
|
|
74
|
-
expect(generateTagsFallback("/api/posts/1")).toEqual(["posts", "post:1"]);
|
|
75
|
-
});
|
|
76
|
-
it("handles non-plural collection names", () => {
|
|
77
|
-
expect(generateTagsFallback("/api/data/1")).toEqual(["data", "data:1"]);
|
|
78
|
-
});
|
|
79
|
-
it("handles nested resources", () => {
|
|
80
|
-
expect(generateTagsFallback("/api/users/123/posts/456")).toEqual([
|
|
81
|
-
"users",
|
|
82
|
-
"user:123",
|
|
83
|
-
"posts",
|
|
84
|
-
]);
|
|
85
|
-
});
|
|
86
|
-
});
|
|
87
|
-
describe("edge cases", () => {
|
|
88
|
-
it("handles query parameters", () => {
|
|
89
|
-
expect(generateTagsFallback("/api/todos?status=active")).toEqual(["todos"]);
|
|
90
|
-
});
|
|
91
|
-
it("handles trailing slashes", () => {
|
|
92
|
-
expect(generateTagsFallback("/api/todos/42/")).toEqual(["todos", "todo:42"]);
|
|
93
|
-
});
|
|
94
|
-
it("handles full URLs", () => {
|
|
95
|
-
expect(generateTagsFallback("https://example.com/api/todos/42")).toEqual([
|
|
96
|
-
"todos",
|
|
97
|
-
"todo:42",
|
|
98
|
-
]);
|
|
99
|
-
});
|
|
100
|
-
});
|
|
101
|
-
});
|
|
102
|
-
// Test compilePatternEntry (used by the generator)
|
|
103
|
-
describe("compilePatternEntry", () => {
|
|
104
|
-
// We import and test the actual function from the generator
|
|
105
|
-
// For unit testing purposes, we replicate the logic
|
|
106
|
-
function compileEntry(pattern, templates) {
|
|
107
|
-
const rawParts = pattern.split("/");
|
|
108
|
-
const parts = rawParts.filter((p) => p !== "");
|
|
109
|
-
const paramNames = [];
|
|
110
|
-
const regexParts = [];
|
|
111
|
-
for (let i = 0; i < parts.length; i++) {
|
|
112
|
-
const part = parts[i];
|
|
113
|
-
if (part === "**") {
|
|
114
|
-
regexParts.push("(?:\\/[^/]+)*");
|
|
115
|
-
continue;
|
|
116
|
-
}
|
|
117
|
-
if (regexParts.length > 0) {
|
|
118
|
-
regexParts.push("\\/");
|
|
119
|
-
}
|
|
120
|
-
if (part === "*") {
|
|
121
|
-
regexParts.push("[^/]+");
|
|
122
|
-
}
|
|
123
|
-
else if (part.startsWith(":")) {
|
|
124
|
-
paramNames.push(part.slice(1));
|
|
125
|
-
regexParts.push("([^/]+)");
|
|
126
|
-
}
|
|
127
|
-
else if (part.includes("{")) {
|
|
128
|
-
const close = part.indexOf("}");
|
|
129
|
-
if (close !== -1) {
|
|
130
|
-
const inner = part.slice(part.indexOf("{") + 1, close);
|
|
131
|
-
const alternatives = inner.split(",").map((s) => s.trim().replace(/[.+^${}()|[\]\\]/g, "\\$&"));
|
|
132
|
-
regexParts.push("(?:" + alternatives.join("|") + ")");
|
|
133
|
-
}
|
|
134
|
-
else {
|
|
135
|
-
regexParts.push(part.replace(/[.+^${}()|[\]\\]/g, "\\$&"));
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
else {
|
|
139
|
-
regexParts.push(part.replace(/[.+^${}()|[\]\\]/g, "\\$&"));
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
if (regexParts.length === 0)
|
|
143
|
-
return null;
|
|
144
|
-
const hasLeadingSlash = pattern.startsWith("/");
|
|
145
|
-
const regex = (hasLeadingSlash ? "^\\/" : "^") + regexParts.join("") + "$";
|
|
146
|
-
// Validate template params match captured params
|
|
147
|
-
const templatePlaceholders = new Set();
|
|
148
|
-
for (const tmpl of templates) {
|
|
149
|
-
const matches = tmpl.match(/\{(\w+)\}/g);
|
|
150
|
-
if (matches) {
|
|
151
|
-
for (const m of matches) {
|
|
152
|
-
templatePlaceholders.add(m.slice(1, -1));
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
for (const ph of templatePlaceholders) {
|
|
157
|
-
if (!paramNames.includes(ph))
|
|
158
|
-
return null;
|
|
159
|
-
}
|
|
160
|
-
return { regex, params: paramNames, templates };
|
|
161
|
-
}
|
|
162
|
-
function testMatch(regex, url) {
|
|
163
|
-
const parsed = new URL(url, "http://example.com");
|
|
164
|
-
return parsed.pathname.match(new RegExp(regex));
|
|
165
|
-
}
|
|
166
|
-
function generateTagsWithPatterns(url, patterns) {
|
|
167
|
-
const parsed = new URL(url, "http://example.com");
|
|
168
|
-
for (const entry of patterns) {
|
|
169
|
-
const match = parsed.pathname.match(new RegExp(entry.regex));
|
|
170
|
-
if (match) {
|
|
171
|
-
const params = {};
|
|
172
|
-
for (let i = 0; i < entry.params.length; i++) {
|
|
173
|
-
params[entry.params[i]] = match[i + 1];
|
|
174
|
-
}
|
|
175
|
-
return entry.templates.map((tmpl) => tmpl.replace(/\{(\w+)\}/g, (_, key) => params[key] ?? ""));
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
return generateTagsFallback(url);
|
|
179
|
-
}
|
|
180
|
-
it("compiles :param pattern", () => {
|
|
181
|
-
const entry = compileEntry("/api/users/:id", ["users", "user:{id}"]);
|
|
182
|
-
expect(entry).not.toBeNull();
|
|
183
|
-
expect(entry.params).toEqual(["id"]);
|
|
184
|
-
const match = testMatch(entry.regex, "/api/users/42");
|
|
185
|
-
expect(match).not.toBeNull();
|
|
186
|
-
expect(match[1]).toBe("42");
|
|
187
|
-
});
|
|
188
|
-
it("compiles * glob pattern", () => {
|
|
189
|
-
const entry = compileEntry("/api/users/*", ["users", "user"]);
|
|
190
|
-
expect(entry).not.toBeNull();
|
|
191
|
-
expect(testMatch(entry.regex, "/api/users/42")).not.toBeNull();
|
|
192
|
-
expect(testMatch(entry.regex, "/api/users/abc")).not.toBeNull();
|
|
193
|
-
expect(testMatch(entry.regex, "/api/users/42/posts")).toBeNull();
|
|
194
|
-
});
|
|
195
|
-
it("compiles ** globstar pattern", () => {
|
|
196
|
-
const entry = compileEntry("/api/**", ["api"]);
|
|
197
|
-
expect(entry).not.toBeNull();
|
|
198
|
-
expect(testMatch(entry.regex, "/api/users")).not.toBeNull();
|
|
199
|
-
expect(testMatch(entry.regex, "/api/users/123/posts")).not.toBeNull();
|
|
200
|
-
});
|
|
201
|
-
it("compiles {alternation} pattern", () => {
|
|
202
|
-
const entry = compileEntry("/api/{users,posts}/:id", ["entry", "entry:{id}"]);
|
|
203
|
-
expect(entry).not.toBeNull();
|
|
204
|
-
expect(entry.params).toEqual(["id"]);
|
|
205
|
-
expect(testMatch(entry.regex, "/api/users/42")).not.toBeNull();
|
|
206
|
-
expect(testMatch(entry.regex, "/api/posts/42")).not.toBeNull();
|
|
207
|
-
expect(testMatch(entry.regex, "/api/comments/42")).toBeNull();
|
|
208
|
-
});
|
|
209
|
-
it("generates tags from matched pattern", () => {
|
|
210
|
-
const patterns = [
|
|
211
|
-
compileEntry("/api/users/:id", ["users", "user:{id}"]),
|
|
212
|
-
];
|
|
213
|
-
expect(generateTagsWithPatterns("/api/users/42", patterns)).toEqual(["users", "user:42"]);
|
|
214
|
-
expect(generateTagsWithPatterns("/api/users/abc", patterns)).toEqual(["users", "user:abc"]);
|
|
215
|
-
});
|
|
216
|
-
it("falls back to segment-based when no pattern matches", () => {
|
|
217
|
-
const patterns = [
|
|
218
|
-
compileEntry("/api/users/:id", ["users", "user:{id}"]),
|
|
219
|
-
];
|
|
220
|
-
expect(generateTagsWithPatterns("/api/todos/42", patterns)).toEqual(["todos", "todo:42"]);
|
|
221
|
-
expect(generateTagsWithPatterns("/api/todos", patterns)).toEqual(["todos"]);
|
|
222
|
-
});
|
|
223
|
-
it("handles multiple named params", () => {
|
|
224
|
-
const entry = compileEntry("/api/:resource/:id", ["{resource}", "{resource}:{id}"]);
|
|
225
|
-
expect(entry).not.toBeNull();
|
|
226
|
-
expect(entry.params).toEqual(["resource", "id"]);
|
|
227
|
-
const match = testMatch(entry.regex, "/api/todos/42");
|
|
228
|
-
expect(match).not.toBeNull();
|
|
229
|
-
expect(match[1]).toBe("todos");
|
|
230
|
-
expect(match[2]).toBe("42");
|
|
231
|
-
expect(generateTagsWithPatterns("/api/todos/42", [entry])).toEqual(["todos", "todos:42"]);
|
|
232
|
-
});
|
|
233
|
-
it("handles deeply nested patterns", () => {
|
|
234
|
-
const entry = compileEntry("/api/users/:userId/posts/:postId", ["users", "user:{userId}", "posts", "post:{postId}"]);
|
|
235
|
-
expect(entry).not.toBeNull();
|
|
236
|
-
expect(entry.params).toEqual(["userId", "postId"]);
|
|
237
|
-
const match = testMatch(entry.regex, "/api/users/42/posts/99");
|
|
238
|
-
expect(match).not.toBeNull();
|
|
239
|
-
expect(match[1]).toBe("42");
|
|
240
|
-
expect(match[2]).toBe("99");
|
|
241
|
-
expect(generateTagsWithPatterns("/api/users/42/posts/99", [entry]))
|
|
242
|
-
.toEqual(["users", "user:42", "posts", "post:99"]);
|
|
243
|
-
});
|
|
244
|
-
it("returns null when template uses undeclared param", () => {
|
|
245
|
-
const entry = compileEntry("/api/users/:id", ["users", "user:{id}", "extra:{missing}"]);
|
|
246
|
-
expect(entry).toBeNull();
|
|
247
|
-
});
|
|
248
|
-
});
|
|
249
|
-
// Test the generated output contains expected code
|
|
250
|
-
describe("generated output", () => {
|
|
251
|
-
it("generated file exports expected functions", () => {
|
|
252
|
-
// We test what the generator produces by reading it indirectly
|
|
253
|
-
// through the file-generators test which invokes the generator
|
|
254
|
-
const code = `
|
|
255
|
-
import { invalidateByTags } from "./cache.js";
|
|
256
|
-
const TAG_PATTERNS = [];
|
|
257
|
-
const SKIP_PREFIXES = ["api","v1","v2","v3","rest","graphql","gql"];
|
|
258
|
-
const SINGULARIZATION = null;
|
|
259
|
-
const CASCADING = null;
|
|
260
|
-
export function generateTags(url) {}
|
|
261
|
-
export function generateTagsFromMethod(method, url) {}
|
|
262
|
-
export async function invalidateUrl(url) {}
|
|
263
|
-
export async function invalidateByMethod(method, url) {}
|
|
264
|
-
function expandCascading(tags) {}
|
|
265
|
-
`;
|
|
266
|
-
expect(code).toContain("generateTags");
|
|
267
|
-
expect(code).toContain("invalidateUrl");
|
|
268
|
-
expect(code).toContain("invalidateByMethod");
|
|
269
|
-
expect(code).toContain("CASCADING");
|
|
270
|
-
expect(code).toContain("expandCascading");
|
|
271
|
-
});
|
|
272
|
-
it("generated code with patterns includes compiled entries", () => {
|
|
273
|
-
// Simulate what the generator would produce for a config with patterns
|
|
274
|
-
const patternCode = `[
|
|
275
|
-
{ re: new RegExp("^\\\\/api\\\\/users\\\\([^/]+\\\\)$"), params: ["id"], templates: ["users","user:{id}"] }
|
|
276
|
-
]`;
|
|
277
|
-
const code = `const TAG_PATTERNS = ${patternCode};`;
|
|
278
|
-
expect(code).toContain("TAG_PATTERNS");
|
|
279
|
-
expect(code).toContain("users");
|
|
280
|
-
expect(code).toContain("user:{id}");
|
|
281
|
-
});
|
|
282
|
-
});
|
|
283
|
-
//# sourceMappingURL=invalidation-tags.test.js.map
|