jamdesk 1.1.41 → 1.1.43

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 (48) hide show
  1. package/README.md +22 -0
  2. package/dist/__tests__/unit/dev-validate-cache.test.d.ts +2 -0
  3. package/dist/__tests__/unit/dev-validate-cache.test.d.ts.map +1 -0
  4. package/dist/__tests__/unit/dev-validate-cache.test.js +116 -0
  5. package/dist/__tests__/unit/dev-validate-cache.test.js.map +1 -0
  6. package/dist/__tests__/unit/dev-workspace-symlinks.test.d.ts +2 -0
  7. package/dist/__tests__/unit/dev-workspace-symlinks.test.d.ts.map +1 -0
  8. package/dist/__tests__/unit/dev-workspace-symlinks.test.js +105 -0
  9. package/dist/__tests__/unit/dev-workspace-symlinks.test.js.map +1 -0
  10. package/dist/__tests__/unit/language-filter.test.d.ts +2 -0
  11. package/dist/__tests__/unit/language-filter.test.d.ts.map +1 -0
  12. package/dist/__tests__/unit/language-filter.test.js +95 -0
  13. package/dist/__tests__/unit/language-filter.test.js.map +1 -0
  14. package/dist/__tests__/unit/vendored-sync.test.js +4 -0
  15. package/dist/__tests__/unit/vendored-sync.test.js.map +1 -1
  16. package/dist/commands/dev.d.ts +48 -3
  17. package/dist/commands/dev.d.ts.map +1 -1
  18. package/dist/commands/dev.js +134 -41
  19. package/dist/commands/dev.js.map +1 -1
  20. package/dist/index.js +15 -2
  21. package/dist/index.js.map +1 -1
  22. package/dist/lib/language-filter.d.ts +32 -0
  23. package/dist/lib/language-filter.d.ts.map +1 -0
  24. package/dist/lib/language-filter.js +28 -0
  25. package/dist/lib/language-filter.js.map +1 -0
  26. package/package.json +1 -1
  27. package/vendored/app/[[...slug]]/page.tsx +41 -28
  28. package/vendored/app/api/isr-health/route.ts +6 -4
  29. package/vendored/components/mdx/StepSlugContext.tsx +57 -0
  30. package/vendored/components/mdx/Steps.tsx +2 -2
  31. package/vendored/components/navigation/TableOfContents.tsx +77 -5
  32. package/vendored/lib/cache-tags.ts +25 -0
  33. package/vendored/lib/cache-utils.ts +19 -0
  34. package/vendored/lib/heading-extractor.ts +25 -6
  35. package/vendored/lib/indexnow.ts +1 -1
  36. package/vendored/lib/middleware-helpers.ts +103 -15
  37. package/vendored/lib/navigation-resolver.ts +1 -1
  38. package/vendored/lib/openapi-isr.ts +13 -8
  39. package/vendored/lib/r2-cleanup.ts +70 -0
  40. package/vendored/lib/r2-content.ts +0 -24
  41. package/vendored/lib/r2-manifest.ts +13 -3
  42. package/vendored/lib/revalidation-helpers.ts +41 -11
  43. package/vendored/lib/revalidation-trigger.ts +104 -28
  44. package/vendored/lib/scanner-blocklist.ts +265 -0
  45. package/vendored/lib/snippet-compiler-isr.ts +5 -2
  46. package/vendored/scripts/validate-links.cjs +17 -6
  47. package/vendored/workspace-package-lock.json +12 -12
  48. package/vendored/lib/cache-keys.ts +0 -117
@@ -77,9 +77,12 @@ export async function compileSnippetIsr(
77
77
  }
78
78
 
79
79
  /**
80
- * Clear snippet cache.
80
+ * Clear the in-memory compiled-snippet Map for a project (or all projects).
81
81
  *
82
- * @param projectSlug - Optional project to clear. If not provided, clears all.
82
+ * Does NOT touch the unstable_cache layer that wraps fetchSnippet emitting a
83
+ * project: tag here would discard config/mdx/openapi/static cache entries
84
+ * unrelated to snippets. Callers needing that scope should dispatch the
85
+ * project tag themselves (executeRevalidation does this).
83
86
  */
84
87
  export function clearSnippetCache(projectSlug?: string): void {
85
88
  if (projectSlug) {
@@ -217,6 +217,16 @@ function generateSlug(text) {
217
217
  .replace(/^-+|-+$/g, '');
218
218
  }
219
219
 
220
+ /**
221
+ * Mirrors uniquifySlug in lib/heading-extractor.ts. First occurrence keeps the
222
+ * bare slug; later collisions get -2, -3, ... suffixes in source order.
223
+ */
224
+ function uniquifySlug(seen, base) {
225
+ const count = seen.get(base) || 0;
226
+ seen.set(base, count + 1);
227
+ return count === 0 ? base : `${base}-${count + 1}`;
228
+ }
229
+
220
230
  /**
221
231
  * Extract heading slugs from MDX content.
222
232
  * Includes markdown headings, <Update label="..."> anchors, and
@@ -229,6 +239,7 @@ function generateSlug(text) {
229
239
  */
230
240
  function extractHeadingSlugs(content) {
231
241
  const slugs = new Set();
242
+ const seen = new Map();
232
243
  const lines = content.split('\n');
233
244
  let inCodeBlock = false;
234
245
  let fencePattern = '';
@@ -264,20 +275,20 @@ function extractHeadingSlugs(content) {
264
275
 
265
276
  const headingMatch = line.match(/^#{1,6}\s+(.+)$/);
266
277
  if (headingMatch) {
267
- const slug = generateSlug(headingMatch[1].trim());
268
- if (slug) slugs.add(slug);
278
+ const base = generateSlug(headingMatch[1].trim());
279
+ if (base) slugs.add(uniquifySlug(seen, base));
269
280
  }
270
281
 
271
282
  const updateMatch = line.match(/<Update\s+label=["']([^"']+)["']/);
272
283
  if (updateMatch) {
273
- const slug = generateSlug(updateMatch[1]);
274
- if (slug) slugs.add(slug);
284
+ const base = generateSlug(updateMatch[1]);
285
+ if (base) slugs.add(uniquifySlug(seen, base));
275
286
  }
276
287
 
277
288
  if (inStepsBlock) {
278
289
  for (const match of line.matchAll(STEP_TITLE_REGEX)) {
279
- const slug = generateSlug(match[1] ?? match[2]);
280
- if (slug) slugs.add(slug);
290
+ const base = generateSlug(match[1] ?? match[2]);
291
+ if (base) slugs.add(uniquifySlug(seen, base));
281
292
  }
282
293
  }
283
294
 
@@ -2152,9 +2152,9 @@
2152
2152
  }
2153
2153
  },
2154
2154
  "node_modules/baseline-browser-mapping": {
2155
- "version": "2.10.23",
2156
- "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.23.tgz",
2157
- "integrity": "sha512-xwVXGqevyKPsiuQdLj+dZMVjidjJV508TBqexND5HrF89cGdCYCJFB3qhcxRHSeMctdCfbR1jrxBajhDy7o29g==",
2155
+ "version": "2.10.24",
2156
+ "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.24.tgz",
2157
+ "integrity": "sha512-I2NkZOOrj2XuguvWCK6OVh9GavsNjZjK908Rq3mIBK25+GD8vPX5w2WdxVqnQ7xx3SrZJiCiZFu+/Oz50oSYSA==",
2158
2158
  "license": "Apache-2.0",
2159
2159
  "bin": {
2160
2160
  "baseline-browser-mapping": "dist/cli.cjs"
@@ -6295,9 +6295,9 @@
6295
6295
  "license": "ISC"
6296
6296
  },
6297
6297
  "node_modules/tinyexec": {
6298
- "version": "1.1.1",
6299
- "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.1.1.tgz",
6300
- "integrity": "sha512-VKS/ZaQhhkKFMANmAOhhXVoIfBXblQxGX1myCQ2faQrfmobMftXeJPcZGp0gS07ocvGJWDLZGyOZDadDBqYIJg==",
6298
+ "version": "1.1.2",
6299
+ "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.1.2.tgz",
6300
+ "integrity": "sha512-dAqSqE/RabpBKI8+h26GfLq6Vb3JVXs30XYQjdMjaj/c2tS8IYYMbIzP599KtRj7c57/wYApb3QjgRgXmrCukA==",
6301
6301
  "license": "MIT",
6302
6302
  "engines": {
6303
6303
  "node": ">=18"
@@ -6352,9 +6352,9 @@
6352
6352
  }
6353
6353
  },
6354
6354
  "node_modules/ufo": {
6355
- "version": "1.6.3",
6356
- "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.6.3.tgz",
6357
- "integrity": "sha512-yDJTmhydvl5lJzBmy/hyOAA0d+aqCBuwl818haVdYCRrWV84o7YyeVm4QlVHStqNrrJSTb6jKuFAVqAFsr+K3Q==",
6355
+ "version": "1.6.4",
6356
+ "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.6.4.tgz",
6357
+ "integrity": "sha512-JFNbkD1Svwe0KvGi8GOeLcP4kAWQ609twvCdcHxq1oSL8svv39ZuSvajcD8B+5D0eL4+s1Is2D/O6KN3qcTeRA==",
6358
6358
  "license": "MIT"
6359
6359
  },
6360
6360
  "node_modules/undici-types": {
@@ -6579,9 +6579,9 @@
6579
6579
  "license": "MIT"
6580
6580
  },
6581
6581
  "node_modules/uuid": {
6582
- "version": "11.1.0",
6583
- "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.0.tgz",
6584
- "integrity": "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==",
6582
+ "version": "11.1.1",
6583
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.1.tgz",
6584
+ "integrity": "sha512-vIYxrBCC/N/K+Js3qSN88go7kIfNPssr/hHCesKCQNAjmgvYS2oqr69kIufEG+O4+PfezOH4EbIeHCfFov8ZgQ==",
6585
6585
  "funding": [
6586
6586
  "https://github.com/sponsors/broofa",
6587
6587
  "https://github.com/sponsors/ctavan"
@@ -1,117 +0,0 @@
1
- /**
2
- * Cache Key Generation for Multi-Tenant ISR
3
- *
4
- * Ensures cache keys are properly namespaced by project to prevent
5
- * cache bleed between tenants. All caches should use these functions
6
- * for key generation.
7
- */
8
-
9
- /**
10
- * Generate a cache key for project-scoped resources.
11
- *
12
- * @param projectSlug - Project identifier
13
- * @param resourcePath - Resource path within project
14
- * @returns Namespaced cache key
15
- */
16
- export function getCacheKey(projectSlug: string, resourcePath: string): string {
17
- // Normalize path (remove leading/trailing slashes)
18
- const normalizedPath = resourcePath.replace(/^\/+|\/+$/g, '');
19
- return `${projectSlug}:${normalizedPath}`;
20
- }
21
-
22
- /**
23
- * Generate a cache key for config resources.
24
- *
25
- * @param projectSlug - Project identifier
26
- * @returns Namespaced cache key for docs.json
27
- */
28
- export function getConfigCacheKey(projectSlug: string): string {
29
- return `${projectSlug}:config`;
30
- }
31
-
32
- /**
33
- * Generate a cache key for snippet resources.
34
- *
35
- * @param projectSlug - Project identifier
36
- * @param snippetPath - Path to snippet file
37
- * @returns Namespaced cache key
38
- */
39
- export function getSnippetCacheKey(projectSlug: string, snippetPath: string): string {
40
- return `${projectSlug}:snippet:${snippetPath}`;
41
- }
42
-
43
- /**
44
- * Generate a cache key for OpenAPI specs.
45
- *
46
- * @param projectSlug - Project identifier
47
- * @param specPath - Path or URL to OpenAPI spec
48
- * @returns Namespaced cache key
49
- */
50
- export function getOpenApiCacheKey(projectSlug: string, specPath: string): string {
51
- // For URLs, include the full URL in the key
52
- if (specPath.startsWith('http://') || specPath.startsWith('https://')) {
53
- return `${projectSlug}:openapi:url:${specPath}`;
54
- }
55
- return `${projectSlug}:openapi:${specPath}`;
56
- }
57
-
58
- /**
59
- * Generate a cache key for page content.
60
- *
61
- * @param projectSlug - Project identifier
62
- * @param pagePath - Page path
63
- * @returns Namespaced cache key
64
- */
65
- export function getPageCacheKey(projectSlug: string, pagePath: string): string {
66
- return `${projectSlug}:page:${pagePath}`;
67
- }
68
-
69
- /**
70
- * Generate a Next.js revalidation tag for a project.
71
- *
72
- * @param projectSlug - Project identifier
73
- * @returns Tag for use with revalidateTag()
74
- */
75
- export function getProjectTag(projectSlug: string): string {
76
- return `project:${projectSlug}`;
77
- }
78
-
79
- /**
80
- * Generate a Next.js revalidation tag for a specific page.
81
- *
82
- * @param projectSlug - Project identifier
83
- * @param pagePath - Page path
84
- * @returns Tag for use with revalidateTag()
85
- */
86
- export function getPageTag(projectSlug: string, pagePath: string): string {
87
- return `page:${projectSlug}:${pagePath}`;
88
- }
89
-
90
- /**
91
- * Parse a cache key back to its components.
92
- *
93
- * @param cacheKey - Cache key to parse
94
- * @returns Project slug and resource path
95
- */
96
- export function parseCacheKey(cacheKey: string): { projectSlug: string; resourcePath: string } {
97
- const colonIndex = cacheKey.indexOf(':');
98
- if (colonIndex === -1) {
99
- throw new Error(`Invalid cache key format: ${cacheKey}`);
100
- }
101
-
102
- return {
103
- projectSlug: cacheKey.slice(0, colonIndex),
104
- resourcePath: cacheKey.slice(colonIndex + 1),
105
- };
106
- }
107
-
108
- /**
109
- * Check if a cache key belongs to a specific project.
110
- *
111
- * @param cacheKey - Cache key to check
112
- * @param projectSlug - Project to check against
113
- * @returns true if key belongs to project
114
- */
115
- export function isProjectKey(cacheKey: string, projectSlug: string): boolean {
116
- return cacheKey.startsWith(`${projectSlug}:`);
117
- }