katanakit-js 2.2.1 → 2.12.9

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 (148) hide show
  1. package/README.md +72 -437
  2. package/dist/adapters/astro/astro.service.d.ts +103 -15
  3. package/dist/adapters/astro/astro.service.d.ts.map +1 -1
  4. package/dist/adapters/astro/astro.service.js +145 -75
  5. package/dist/adapters/astro/astro.service.js.map +1 -1
  6. package/dist/adapters/astro/index.d.ts +1 -1
  7. package/dist/adapters/astro/index.d.ts.map +1 -1
  8. package/dist/adapters/astro/index.js +1 -1
  9. package/dist/adapters/astro/index.js.map +1 -1
  10. package/dist/adapters/astro/rss.service.d.ts +85 -105
  11. package/dist/adapters/astro/rss.service.d.ts.map +1 -1
  12. package/dist/adapters/astro/rss.service.js +172 -168
  13. package/dist/adapters/astro/rss.service.js.map +1 -1
  14. package/dist/adapters/astro/seo.service.d.ts +10 -0
  15. package/dist/adapters/astro/seo.service.d.ts.map +1 -0
  16. package/dist/adapters/astro/seo.service.js +3 -0
  17. package/dist/adapters/astro/seo.service.js.map +1 -0
  18. package/dist/adapters/express/app.d.ts +30 -1
  19. package/dist/adapters/express/app.d.ts.map +1 -1
  20. package/dist/adapters/express/app.js +31 -3
  21. package/dist/adapters/express/app.js.map +1 -1
  22. package/dist/adapters/express/index.d.ts +2 -2
  23. package/dist/adapters/express/index.d.ts.map +1 -1
  24. package/dist/adapters/express/index.js +2 -2
  25. package/dist/adapters/express/index.js.map +1 -1
  26. package/dist/adapters/express/main.js +2 -2
  27. package/dist/adapters/express/main.js.map +1 -1
  28. package/dist/adapters/express/products.controller.d.ts +67 -8
  29. package/dist/adapters/express/products.controller.d.ts.map +1 -1
  30. package/dist/adapters/express/products.controller.js +105 -49
  31. package/dist/adapters/express/products.controller.js.map +1 -1
  32. package/dist/adapters/express/server.d.ts +37 -13
  33. package/dist/adapters/express/server.d.ts.map +1 -1
  34. package/dist/adapters/express/server.js +118 -53
  35. package/dist/adapters/express/server.js.map +1 -1
  36. package/dist/adapters/nuxt/nuxt.service.d.ts +8 -6
  37. package/dist/adapters/nuxt/nuxt.service.d.ts.map +1 -1
  38. package/dist/adapters/nuxt/nuxt.service.js +34 -10
  39. package/dist/adapters/nuxt/nuxt.service.js.map +1 -1
  40. package/dist/adapters/vue/vue.service.d.ts +5 -2
  41. package/dist/adapters/vue/vue.service.d.ts.map +1 -1
  42. package/dist/adapters/vue/vue.service.js +41 -7
  43. package/dist/adapters/vue/vue.service.js.map +1 -1
  44. package/dist/config/index.d.ts +2 -1
  45. package/dist/config/index.d.ts.map +1 -1
  46. package/dist/config/index.js +1 -1
  47. package/dist/config/index.js.map +1 -1
  48. package/dist/config/seo-meta.types.d.ts +177 -0
  49. package/dist/config/seo-meta.types.d.ts.map +1 -0
  50. package/dist/config/seo-meta.types.js +11 -0
  51. package/dist/config/seo-meta.types.js.map +1 -0
  52. package/dist/config/seo.service.d.ts +41 -58
  53. package/dist/config/seo.service.d.ts.map +1 -1
  54. package/dist/config/seo.service.js +468 -136
  55. package/dist/config/seo.service.js.map +1 -1
  56. package/dist/config/site.config.d.ts +10 -50
  57. package/dist/config/site.config.d.ts.map +1 -1
  58. package/dist/config/site.config.js +8 -36
  59. package/dist/config/site.config.js.map +1 -1
  60. package/dist/core/index.d.ts +1 -3
  61. package/dist/core/index.d.ts.map +1 -1
  62. package/dist/core/index.js +1 -3
  63. package/dist/core/index.js.map +1 -1
  64. package/dist/core/services/dates.service.d.ts +149 -22
  65. package/dist/core/services/dates.service.d.ts.map +1 -1
  66. package/dist/core/services/dates.service.js +201 -54
  67. package/dist/core/services/dates.service.js.map +1 -1
  68. package/dist/core/services/error.service.d.ts +32 -20
  69. package/dist/core/services/error.service.d.ts.map +1 -1
  70. package/dist/core/services/error.service.js +44 -32
  71. package/dist/core/services/error.service.js.map +1 -1
  72. package/dist/core/services/formatter.service.d.ts +245 -35
  73. package/dist/core/services/formatter.service.d.ts.map +1 -1
  74. package/dist/core/services/formatter.service.js +281 -57
  75. package/dist/core/services/formatter.service.js.map +1 -1
  76. package/dist/core/services/generator.service.d.ts +115 -26
  77. package/dist/core/services/generator.service.d.ts.map +1 -1
  78. package/dist/core/services/generator.service.js +191 -56
  79. package/dist/core/services/generator.service.js.map +1 -1
  80. package/dist/core/services/geometry.service.d.ts +369 -39
  81. package/dist/core/services/geometry.service.d.ts.map +1 -1
  82. package/dist/core/services/geometry.service.js +424 -66
  83. package/dist/core/services/geometry.service.js.map +1 -1
  84. package/dist/core/services/http.service.d.ts +244 -21
  85. package/dist/core/services/http.service.d.ts.map +1 -1
  86. package/dist/core/services/http.service.js +419 -98
  87. package/dist/core/services/http.service.js.map +1 -1
  88. package/dist/core/services/logger.service.d.ts +95 -29
  89. package/dist/core/services/logger.service.d.ts.map +1 -1
  90. package/dist/core/services/logger.service.js +167 -41
  91. package/dist/core/services/logger.service.js.map +1 -1
  92. package/dist/core/services/reactive.service.d.ts +146 -19
  93. package/dist/core/services/reactive.service.d.ts.map +1 -1
  94. package/dist/core/services/reactive.service.js +278 -137
  95. package/dist/core/services/reactive.service.js.map +1 -1
  96. package/dist/core/services/timing.service.d.ts +142 -20
  97. package/dist/core/services/timing.service.d.ts.map +1 -1
  98. package/dist/core/services/timing.service.js +324 -185
  99. package/dist/core/services/timing.service.js.map +1 -1
  100. package/dist/core/services/utils.service.d.ts +228 -43
  101. package/dist/core/services/utils.service.d.ts.map +1 -1
  102. package/dist/core/services/utils.service.js +305 -125
  103. package/dist/core/services/utils.service.js.map +1 -1
  104. package/dist/infrastructure/dom/dom.service.d.ts +307 -44
  105. package/dist/infrastructure/dom/dom.service.d.ts.map +1 -1
  106. package/dist/infrastructure/dom/dom.service.js +408 -129
  107. package/dist/infrastructure/dom/dom.service.js.map +1 -1
  108. package/dist/infrastructure/index.d.ts +0 -3
  109. package/dist/infrastructure/index.d.ts.map +1 -1
  110. package/dist/infrastructure/index.js +0 -3
  111. package/dist/infrastructure/index.js.map +1 -1
  112. package/dist/infrastructure/observer/observer.service.d.ts +124 -31
  113. package/dist/infrastructure/observer/observer.service.d.ts.map +1 -1
  114. package/dist/infrastructure/observer/observer.service.js +227 -131
  115. package/dist/infrastructure/observer/observer.service.js.map +1 -1
  116. package/dist/infrastructure/sensors/sensors.service.d.ts +154 -22
  117. package/dist/infrastructure/sensors/sensors.service.d.ts.map +1 -1
  118. package/dist/infrastructure/sensors/sensors.service.js +264 -112
  119. package/dist/infrastructure/sensors/sensors.service.js.map +1 -1
  120. package/dist/infrastructure/storage/storage.service.d.ts +123 -45
  121. package/dist/infrastructure/storage/storage.service.d.ts.map +1 -1
  122. package/dist/infrastructure/storage/storage.service.js +236 -66
  123. package/dist/infrastructure/storage/storage.service.js.map +1 -1
  124. package/dist/infrastructure/theme/theme.service.d.ts +93 -29
  125. package/dist/infrastructure/theme/theme.service.d.ts.map +1 -1
  126. package/dist/infrastructure/theme/theme.service.js +198 -96
  127. package/dist/infrastructure/theme/theme.service.js.map +1 -1
  128. package/dist/infrastructure/viewport/viewport.service.d.ts +233 -35
  129. package/dist/infrastructure/viewport/viewport.service.d.ts.map +1 -1
  130. package/dist/infrastructure/viewport/viewport.service.js +358 -139
  131. package/dist/infrastructure/viewport/viewport.service.js.map +1 -1
  132. package/dist/infrastructure/worker/worker.service.d.ts +84 -38
  133. package/dist/infrastructure/worker/worker.service.d.ts.map +1 -1
  134. package/dist/infrastructure/worker/worker.service.js +234 -133
  135. package/dist/infrastructure/worker/worker.service.js.map +1 -1
  136. package/dist/prisma/index.d.ts +2 -0
  137. package/dist/prisma/index.d.ts.map +1 -0
  138. package/dist/prisma/index.js +2 -0
  139. package/dist/prisma/index.js.map +1 -0
  140. package/dist/prisma/schema.json +11 -33
  141. package/dist/prisma/use-prisma.d.ts +68 -0
  142. package/dist/prisma/use-prisma.d.ts.map +1 -0
  143. package/dist/prisma/use-prisma.js +82 -0
  144. package/dist/prisma/use-prisma.js.map +1 -0
  145. package/dist/types/index.d.ts +20 -12
  146. package/dist/types/index.d.ts.map +1 -1
  147. package/package.json +124 -125
  148. package/CHANGELOG.md +0 -101
@@ -1,7 +1,24 @@
1
+ import { createRequire } from "node:module";
2
+ let cachedCreateError;
3
+ function tryLoadH3CreateError() {
4
+ if (cachedCreateError !== undefined)
5
+ return cachedCreateError;
6
+ try {
7
+ const require = createRequire(import.meta.url);
8
+ const h3 = require("h3");
9
+ cachedCreateError = typeof h3.createError === "function" ? h3.createError : null;
10
+ }
11
+ catch {
12
+ cachedCreateError = null;
13
+ }
14
+ return cachedCreateError;
15
+ }
1
16
  /**
2
17
  * Unwraps a KatanaKit Safe Result, throwing an H3-compatible error on failure.
3
18
  * Returns the data directly on success.
4
19
  *
20
+ * Prefers `h3.createError` when available so Nuxt/H3 status codes work correctly.
21
+ *
5
22
  * @param result - The Safe Result from `useFetch`, `useGet`, `usePost`, etc.
6
23
  * @param context - Optional context prefix for the error message.
7
24
  * @returns The data from the result.
@@ -10,12 +27,12 @@
10
27
  * @example
11
28
  * ```ts
12
29
  * // server/api/pokemon/[id].ts
13
- * import { useGet } from "katanakit-js";
30
+ * import { useGetApi } from "katanakit-js";
14
31
  * import { useUnwrap } from "katanakit-js/adapters/nuxt";
15
32
  *
16
33
  * export default defineEventHandler(async (event) => {
17
34
  * const id = getRouterParam(event, "id");
18
- * const result = await useGet("pokeapi", "pokemonById", { params: { id } });
35
+ * const result = await useGetApi("pokeapi", "pokemonById", { params: { id } });
19
36
  * return useUnwrap(result, `Pokemon ${id}`);
20
37
  * });
21
38
  * ```
@@ -26,8 +43,6 @@ export function useUnwrap(result, context) {
26
43
  }
27
44
  const message = context ? `${context}: ${result.error.message}` : result.error.message;
28
45
  const statusCode = result.error.status || 500;
29
- // Dynamic import to avoid hard dependency on h3.
30
- // Consumers must have h3 installed (it comes with Nuxt).
31
46
  throw createH3Error(statusCode, message);
32
47
  }
33
48
  /**
@@ -41,11 +56,11 @@ export function useUnwrap(result, context) {
41
56
  * @example
42
57
  * ```ts
43
58
  * // server/api/users.ts
44
- * import { useGet } from "katanakit-js";
59
+ * import { useGetApi } from "katanakit-js";
45
60
  * import { useSafeResponse } from "katanakit-js/adapters/nuxt";
46
61
  *
47
62
  * export default defineEventHandler(async () => {
48
- * const result = await useGet("api", "users");
63
+ * const result = await useGetApi("api", "users");
49
64
  * return useSafeResponse(result);
50
65
  * });
51
66
  * ```
@@ -74,11 +89,11 @@ export function useSafeResponse(result) {
74
89
  * @example
75
90
  * ```ts
76
91
  * // server/api/products.ts
77
- * import { useFetch } from "katanakit-js";
92
+ * import { useFetchApi } from "katanakit-js";
78
93
  * import { useEventResponse } from "katanakit-js/adapters/nuxt";
79
94
  *
80
95
  * export default defineEventHandler(async (event) => {
81
- * const result = await useFetch("shop", "products");
96
+ * const result = await useFetchApi("shop", "products");
82
97
  * return useEventResponse(event, result);
83
98
  * });
84
99
  * ```
@@ -94,11 +109,20 @@ export function useEventResponse(event, result) {
94
109
  status: result.error.status,
95
110
  };
96
111
  }
97
- // Internal helper: creates an error that looks like an H3 error.
98
- // We don't import h3 directly to avoid a hard peer dependency.
112
+ /**
113
+ * Creates an error that H3/Nuxt recognize (statusCode / statusMessage).
114
+ * Uses `h3.createError` when the peer is installed; otherwise brands a plain Error.
115
+ */
99
116
  function createH3Error(statusCode, message) {
117
+ const createError = tryLoadH3CreateError();
118
+ if (createError) {
119
+ return createError({ statusCode, statusMessage: message, message });
120
+ }
100
121
  const error = new Error(message);
101
122
  error.statusCode = statusCode;
123
+ error.status = statusCode;
124
+ error.statusMessage = message;
125
+ error.name = "H3Error";
102
126
  return error;
103
127
  }
104
128
  //# sourceMappingURL=nuxt.service.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"nuxt.service.js","sourceRoot":"","sources":["../../../src/adapters/nuxt/nuxt.service.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,UAAU,SAAS,CAAI,MAAsB,EAAE,OAAgB;IACpE,IAAI,MAAM,CAAC,EAAE,EAAE,CAAC;QACf,OAAO,MAAM,CAAC,IAAI,CAAC;IACpB,CAAC;IAED,MAAM,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,KAAK,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC;IAEvF,MAAM,UAAU,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,IAAI,GAAG,CAAC;IAE9C,iDAAiD;IACjD,yDAAyD;IACzD,MAAM,aAAa,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;AAC1C,CAAC;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,UAAU,eAAe,CAAI,MAAsB;IAKxD,IAAI,MAAM,CAAC,EAAE,EAAE,CAAC;QACf,OAAO,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;IACrD,CAAC;IAED,OAAO;QACN,IAAI,EAAE,IAAI;QACV,KAAK,EAAE;YACN,OAAO,EAAE,MAAM,CAAC,KAAK,CAAC,OAAO;YAC7B,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,MAAM;SAC3B;QACD,EAAE,EAAE,KAAK;KACT,CAAC;AACH,CAAC;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,UAAU,gBAAgB,CAC/B,KAAgD,EAChD,MAAsB;IAEtB,IAAI,MAAM,CAAC,EAAE,EAAE,CAAC;QACf,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,UAAU,GAAG,GAAG,CAAC;QAChC,OAAO,MAAM,CAAC,IAAI,CAAC;IACpB,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,UAAU,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,IAAI,GAAG,CAAC;IACvD,OAAO;QACN,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,OAAO;QAC3B,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,MAAM;KAC3B,CAAC;AACH,CAAC;AAED,iEAAiE;AACjE,+DAA+D;AAC/D,SAAS,aAAa,CAAC,UAAkB,EAAE,OAAe;IACzD,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC,OAAO,CAAmC,CAAC;IACnE,KAAK,CAAC,UAAU,GAAG,UAAU,CAAC;IAC9B,OAAO,KAAK,CAAC;AACd,CAAC"}
1
+ {"version":3,"file":"nuxt.service.js","sourceRoot":"","sources":["../../../src/adapters/nuxt/nuxt.service.ts"],"names":[],"mappings":"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"}
@@ -14,14 +14,17 @@ export interface KatanaFetchState<T> {
14
14
  refetch: () => Promise<void>;
15
15
  }
16
16
  /**
17
- * Vue 3 composable that wraps KatanaKit's `useGet` with the reactivity system.
17
+ * Vue 3 composable that wraps KatanaKit's HTTP GET with the reactivity system.
18
18
  * It bridges the Safe Result pattern to idiomatic Vue state (`data`, `error`,
19
19
  * `loading`) and never throws on HTTP errors.
20
20
  *
21
+ * Stale responses are ignored via a request version counter and AbortController.
22
+ * In-flight requests are aborted on unmount when `onUnmounted` is available.
23
+ *
21
24
  * When `options` is a Vue `Ref`, the request re-runs automatically whenever the
22
25
  * ref changes (deep watch), so URL params or query params can drive refetching.
23
26
  *
24
- * @param apiName - Name of the registered API (see `useInit`).
27
+ * @param apiName - Name of the registered API (see `useInitApis`).
25
28
  * @param endpointName - Name of the endpoint inside that API.
26
29
  * @param options - Optional `UrlOptions` (path/query params), plain or reactive.
27
30
  * @returns Reactive `{ data, error, loading, refetch }`.
@@ -1 +1 @@
1
- {"version":3,"file":"vue.service.d.ts","sourceRoot":"","sources":["../../../src/adapters/vue/vue.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,KAAK,QAAQ,EAAE,KAAK,GAAG,EAAiC,MAAM,KAAK,CAAC;AAGpF,OAAO,KAAK,EAAE,QAAQ,EAAe,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAE9E;;GAEG;AACH,MAAM,WAAW,gBAAgB,CAAC,CAAC;IAClC,sDAAsD;IACtD,IAAI,EAAE,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IACpB,0DAA0D;IAC1D,KAAK,EAAE,GAAG,CAAC,QAAQ,GAAG,IAAI,CAAC,CAAC;IAC5B,sCAAsC;IACtC,OAAO,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;IACtB,oCAAoC;IACpC,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC7B;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAC/B,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,MAAM,EACpB,OAAO,CAAC,EAAE,QAAQ,CAAC,UAAU,CAAC,GAC5B,gBAAgB,CAAC,CAAC,CAAC,CA6BrB"}
1
+ {"version":3,"file":"vue.service.d.ts","sourceRoot":"","sources":["../../../src/adapters/vue/vue.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,KAAK,QAAQ,EAAe,KAAK,GAAG,EAAiC,MAAM,KAAK,CAAC;AAGjG,OAAO,KAAK,EAAE,QAAQ,EAAe,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAE9E;;GAEG;AACH,MAAM,WAAW,gBAAgB,CAAC,CAAC;IAClC,sDAAsD;IACtD,IAAI,EAAE,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IACpB,0DAA0D;IAC1D,KAAK,EAAE,GAAG,CAAC,QAAQ,GAAG,IAAI,CAAC,CAAC;IAC5B,sCAAsC;IACtC,OAAO,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;IACtB,oCAAoC;IACpC,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC7B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAC/B,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,MAAM,EACpB,OAAO,CAAC,EAAE,QAAQ,CAAC,UAAU,CAAC,GAC5B,gBAAgB,CAAC,CAAC,CAAC,CAmErB"}
@@ -1,14 +1,17 @@
1
- import { isRef, ref, shallowRef, unref, watch } from "vue";
2
- import { useGet } from "../../core/services/http.service.js";
1
+ import { isRef, onUnmounted, ref, shallowRef, unref, watch } from "vue";
2
+ import { useFetch } from "../../core/services/http.service.js";
3
3
  /**
4
- * Vue 3 composable that wraps KatanaKit's `useGet` with the reactivity system.
4
+ * Vue 3 composable that wraps KatanaKit's HTTP GET with the reactivity system.
5
5
  * It bridges the Safe Result pattern to idiomatic Vue state (`data`, `error`,
6
6
  * `loading`) and never throws on HTTP errors.
7
7
  *
8
+ * Stale responses are ignored via a request version counter and AbortController.
9
+ * In-flight requests are aborted on unmount when `onUnmounted` is available.
10
+ *
8
11
  * When `options` is a Vue `Ref`, the request re-runs automatically whenever the
9
12
  * ref changes (deep watch), so URL params or query params can drive refetching.
10
13
  *
11
- * @param apiName - Name of the registered API (see `useInit`).
14
+ * @param apiName - Name of the registered API (see `useInitApis`).
12
15
  * @param endpointName - Name of the endpoint inside that API.
13
16
  * @param options - Optional `UrlOptions` (path/query params), plain or reactive.
14
17
  * @returns Reactive `{ data, error, loading, refetch }`.
@@ -28,21 +31,52 @@ export function useKatanaFetch(apiName, endpointName, options) {
28
31
  const data = shallowRef(null);
29
32
  const error = ref(null);
30
33
  const loading = ref(true);
34
+ let requestVersion = 0;
35
+ let activeController = null;
36
+ let disposed = false;
31
37
  const refetch = async () => {
38
+ const version = ++requestVersion;
39
+ activeController?.abort();
40
+ const controller = new AbortController();
41
+ activeController = controller;
32
42
  loading.value = true;
33
43
  error.value = null;
34
- const result = await useGet(apiName, endpointName, unref(options));
44
+ const result = await useFetch(apiName, endpointName, {
45
+ method: "GET",
46
+ urlOptions: unref(options),
47
+ signal: controller.signal,
48
+ });
49
+ if (disposed || version !== requestVersion) {
50
+ return;
51
+ }
35
52
  if (result.ok) {
36
53
  data.value = result.data;
54
+ error.value = null;
37
55
  }
38
56
  else {
39
- error.value = result.error;
57
+ // Ignore abort errors from superseded / unmounted requests.
58
+ const aborted = controller.signal.aborted || /abort/i.test(result.error.message);
59
+ if (!aborted) {
60
+ error.value = result.error;
61
+ }
40
62
  }
41
63
  loading.value = false;
42
64
  };
43
65
  // Refetch automatically when a reactive options ref changes.
44
66
  if (isRef(options)) {
45
- watch(options, refetch, { deep: true });
67
+ watch(options, () => {
68
+ void refetch();
69
+ }, { deep: true });
70
+ }
71
+ // Dispose on unmount when running inside a component setup.
72
+ try {
73
+ onUnmounted(() => {
74
+ disposed = true;
75
+ activeController?.abort();
76
+ });
77
+ }
78
+ catch {
79
+ // Outside of a component setup context — skip lifecycle hook.
46
80
  }
47
81
  // Initial fetch on setup.
48
82
  void refetch();
@@ -1 +1 @@
1
- {"version":3,"file":"vue.service.js","sourceRoot":"","sources":["../../../src/adapters/vue/vue.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAA2B,GAAG,EAAE,UAAU,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,KAAK,CAAC;AAEpF,OAAO,EAAE,MAAM,EAAE,MAAM,qCAAqC,CAAC;AAiB7D;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,UAAU,cAAc,CAC7B,OAAe,EACf,YAAoB,EACpB,OAA8B;IAE9B,MAAM,IAAI,GAAG,UAAU,CAAW,IAAI,CAAC,CAAC;IACxC,MAAM,KAAK,GAAG,GAAG,CAAkB,IAAI,CAAC,CAAC;IACzC,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC;IAE1B,MAAM,OAAO,GAAG,KAAK,IAAmB,EAAE;QACzC,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC;QACrB,KAAK,CAAC,KAAK,GAAG,IAAI,CAAC;QAEnB,MAAM,MAAM,GAAmB,MAAM,MAAM,CAAI,OAAO,EAAE,YAAY,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;QAEtF,IAAI,MAAM,CAAC,EAAE,EAAE,CAAC;YACf,IAAI,CAAC,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC;QAC1B,CAAC;aAAM,CAAC;YACP,KAAK,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC;QAC5B,CAAC;QAED,OAAO,CAAC,KAAK,GAAG,KAAK,CAAC;IACvB,CAAC,CAAC;IAEF,6DAA6D;IAC7D,IAAI,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;QACpB,KAAK,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;IACzC,CAAC;IAED,0BAA0B;IAC1B,KAAK,OAAO,EAAE,CAAC;IAEf,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC;AAC1C,CAAC"}
1
+ {"version":3,"file":"vue.service.js","sourceRoot":"","sources":["../../../src/adapters/vue/vue.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAiB,WAAW,EAAY,GAAG,EAAE,UAAU,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,KAAK,CAAC;AAEjG,OAAO,EAAE,QAAQ,EAAE,MAAM,qCAAqC,CAAC;AAiB/D;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,MAAM,UAAU,cAAc,CAC7B,OAAe,EACf,YAAoB,EACpB,OAA8B;IAE9B,MAAM,IAAI,GAAG,UAAU,CAAW,IAAI,CAAC,CAAC;IACxC,MAAM,KAAK,GAAG,GAAG,CAAkB,IAAI,CAAC,CAAC;IACzC,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC;IAE1B,IAAI,cAAc,GAAG,CAAC,CAAC;IACvB,IAAI,gBAAgB,GAA2B,IAAI,CAAC;IACpD,IAAI,QAAQ,GAAG,KAAK,CAAC;IAErB,MAAM,OAAO,GAAG,KAAK,IAAmB,EAAE;QACzC,MAAM,OAAO,GAAG,EAAE,cAAc,CAAC;QACjC,gBAAgB,EAAE,KAAK,EAAE,CAAC;QAC1B,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;QACzC,gBAAgB,GAAG,UAAU,CAAC;QAE9B,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC;QACrB,KAAK,CAAC,KAAK,GAAG,IAAI,CAAC;QAEnB,MAAM,MAAM,GAAmB,MAAM,QAAQ,CAAI,OAAO,EAAE,YAAY,EAAE;YACvE,MAAM,EAAE,KAAK;YACb,UAAU,EAAE,KAAK,CAAC,OAAO,CAAC;YAC1B,MAAM,EAAE,UAAU,CAAC,MAAM;SACzB,CAAC,CAAC;QAEH,IAAI,QAAQ,IAAI,OAAO,KAAK,cAAc,EAAE,CAAC;YAC5C,OAAO;QACR,CAAC;QAED,IAAI,MAAM,CAAC,EAAE,EAAE,CAAC;YACf,IAAI,CAAC,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC;YACzB,KAAK,CAAC,KAAK,GAAG,IAAI,CAAC;QACpB,CAAC;aAAM,CAAC;YACP,4DAA4D;YAC5D,MAAM,OAAO,GAAG,UAAU,CAAC,MAAM,CAAC,OAAO,IAAI,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YACjF,IAAI,CAAC,OAAO,EAAE,CAAC;gBACd,KAAK,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC;YAC5B,CAAC;QACF,CAAC;QAED,OAAO,CAAC,KAAK,GAAG,KAAK,CAAC;IACvB,CAAC,CAAC;IAEF,6DAA6D;IAC7D,IAAI,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;QACpB,KAAK,CACJ,OAAO,EACP,GAAG,EAAE;YACJ,KAAK,OAAO,EAAE,CAAC;QAChB,CAAC,EACD,EAAE,IAAI,EAAE,IAAI,EAAE,CACd,CAAC;IACH,CAAC;IAED,4DAA4D;IAC5D,IAAI,CAAC;QACJ,WAAW,CAAC,GAAG,EAAE;YAChB,QAAQ,GAAG,IAAI,CAAC;YAChB,gBAAgB,EAAE,KAAK,EAAE,CAAC;QAC3B,CAAC,CAAC,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACR,8DAA8D;IAC/D,CAAC;IAED,0BAA0B;IAC1B,KAAK,OAAO,EAAE,CAAC;IAEf,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC;AAC1C,CAAC"}
@@ -1,3 +1,4 @@
1
- export { type SeoMeta, useGenerateMetaTags, useHeadTags, useRssHeadLink, useTitle, } from "./seo.service.js";
1
+ export type { SeoArrayable, SeoBooleanable, SeoMeta, SeoMetaArticle, SeoMetaFlat, SeoMetaInput, SeoOgImageObject, SeoRobotsObject, SeoTagNode, SeoTagResult, SeoTagsResult, UseSeoMetaBase, UseSeoMetaOptions, } from "./seo.service.js";
2
+ export { useApplySeoTag, useGenerateMetaTags, useHeadTags, useRssHeadLink, useSeoMeta, useSeoTag, useSeoTags, useTitle, } from "./seo.service.js";
2
3
  export { type SiteConfig, siteConfig } from "./site.config.js";
3
4
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/config/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,KAAK,OAAO,EACZ,mBAAmB,EACnB,WAAW,EACX,cAAc,EACd,QAAQ,GACR,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,KAAK,UAAU,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/config/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACX,YAAY,EACZ,cAAc,EACd,OAAO,EACP,cAAc,EACd,WAAW,EACX,YAAY,EACZ,gBAAgB,EAChB,eAAe,EACf,UAAU,EACV,YAAY,EACZ,aAAa,EACb,cAAc,EACd,iBAAiB,GACjB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACN,cAAc,EACd,mBAAmB,EACnB,WAAW,EACX,cAAc,EACd,UAAU,EACV,SAAS,EACT,UAAU,EACV,QAAQ,GACR,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,KAAK,UAAU,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC"}
@@ -1,3 +1,3 @@
1
- export { useGenerateMetaTags, useHeadTags, useRssHeadLink, useTitle, } from "./seo.service.js";
1
+ export { useApplySeoTag, useGenerateMetaTags, useHeadTags, useRssHeadLink, useSeoMeta, useSeoTag, useSeoTags, useTitle, } from "./seo.service.js";
2
2
  export { siteConfig } from "./site.config.js";
3
3
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/config/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAEN,mBAAmB,EACnB,WAAW,EACX,cAAc,EACd,QAAQ,GACR,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAmB,UAAU,EAAE,MAAM,kBAAkB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/config/index.ts"],"names":[],"mappings":"AAeA,OAAO,EACN,cAAc,EACd,mBAAmB,EACnB,WAAW,EACX,cAAc,EACd,UAAU,EACV,SAAS,EACT,UAAU,EACV,QAAQ,GACR,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAmB,UAAU,EAAE,MAAM,kBAAkB,CAAC"}
@@ -0,0 +1,177 @@
1
+ /**
2
+ * Slim SEO types: typical HTML meta + Open Graph (Facebook) only.
3
+ * CamelCase keys map to `<title>` / `<meta>` / `<link rel="canonical">`.
4
+ *
5
+ * Naming cheat-sheet for {@link UseSeoMetaOptions}:
6
+ * - `site` = base URL (`https://example.com`)
7
+ * - `siteTitle` = brand / site name (`"My Site"`)
8
+ * - `title` = **page** document title (`"Blog Post"` → often `"Blog Post | My Site"`)
9
+ */
10
+ export type SeoBooleanable = boolean | "true" | "false" | "" | 0 | 1;
11
+ export type SeoArrayable<T> = T | readonly T[];
12
+ /** Open Graph image (string URL or object). */
13
+ export interface SeoOgImageObject {
14
+ url?: string;
15
+ secureUrl?: string;
16
+ type?: "image/jpeg" | "image/gif" | "image/png" | "image/webp" | "image/avif" | string;
17
+ width?: string | number;
18
+ height?: string | number;
19
+ alt?: string;
20
+ }
21
+ /** Robots as string or simple object. */
22
+ export interface SeoRobotsObject {
23
+ index?: SeoBooleanable;
24
+ follow?: SeoBooleanable;
25
+ noindex?: SeoBooleanable;
26
+ nofollow?: SeoBooleanable;
27
+ none?: SeoBooleanable;
28
+ noarchive?: SeoBooleanable;
29
+ nosnippet?: SeoBooleanable;
30
+ }
31
+ /** Article Open Graph extensions (`og:type=article`). */
32
+ export interface SeoMetaArticle {
33
+ articleAuthor?: readonly string[];
34
+ articleModifiedTime?: string;
35
+ articlePublishedTime?: string;
36
+ articleSection?: string;
37
+ articleTag?: readonly string[];
38
+ }
39
+ /**
40
+ * Flat meta: HTML head essentials + Facebook Open Graph.
41
+ */
42
+ export interface SeoMetaFlat extends SeoMetaArticle {
43
+ /**
44
+ * Page document title → `<title>`.
45
+ * Not the site brand (`siteTitle`). When both differ, the helper usually
46
+ * renders `"Page | Brand"`.
47
+ */
48
+ title?: string;
49
+ /**
50
+ * Page summary → `<meta name="description">`.
51
+ * Prefer this for the page; use `ogDescription` only to override the share preview.
52
+ */
53
+ description?: string;
54
+ /** Meta keywords (legacy; optional). */
55
+ keywords?: string;
56
+ /** Meta author. */
57
+ author?: string;
58
+ /**
59
+ * Explicit canonical URL → `<link rel="canonical">`.
60
+ * Prefer this over `url` when you know the preferred address.
61
+ */
62
+ canonical?: string;
63
+ /**
64
+ * Absolute page URL. Fallback for canonical / `og:url` when those are omitted
65
+ * (resolution order: `ogUrl` → `canonical` → `url` → `site`).
66
+ */
67
+ url?: string;
68
+ charset?: "utf-8" | string;
69
+ viewport?: string | Record<string, string | number | undefined>;
70
+ robots?: "noindex, nofollow" | "index, follow" | string | SeoRobotsObject;
71
+ /**
72
+ * Open Graph page URL (`og:url`).
73
+ * Falls back to `canonical` → `url` → `site`.
74
+ */
75
+ ogUrl?: string;
76
+ /**
77
+ * Open Graph title (`og:title`). Defaults to the resolved page `title` when omitted.
78
+ */
79
+ ogTitle?: string;
80
+ /**
81
+ * Open Graph description (`og:description`). Defaults to `description` when omitted.
82
+ */
83
+ ogDescription?: string;
84
+ ogType?: "website" | "article" | "profile" | string;
85
+ ogLocale?: string;
86
+ /**
87
+ * Open Graph site name (`og:site_name`). Defaults to `siteTitle` when omitted.
88
+ */
89
+ ogSiteName?: string;
90
+ ogImage?: string | SeoArrayable<SeoOgImageObject>;
91
+ ogImageUrl?: string;
92
+ ogImageSecureUrl?: string;
93
+ ogImageType?: string;
94
+ ogImageWidth?: string | number;
95
+ ogImageHeight?: string | number;
96
+ ogImageAlt?: string;
97
+ }
98
+ /** Flat meta input (all keys optional / nullable). */
99
+ export type SeoMetaInput = {
100
+ [K in keyof SeoMetaFlat]?: SeoMetaFlat[K] | null;
101
+ };
102
+ /** Site + HTML + OG fields in one object (before Omit). */
103
+ export type UseSeoMetaBase = SeoMetaInput & {
104
+ /**
105
+ * Site origin / base URL (no trailing slash), e.g. `"https://example.com"`.
106
+ * Not a title — used for canonical, OG, RSS, and JSON-LD defaults.
107
+ */
108
+ site?: string;
109
+ /**
110
+ * Site brand / product name (e.g. `"KatanaKit"`).
111
+ * Distinct from page {@link SeoMetaFlat.title}.
112
+ * Used as `<title>` suffix (`"Page | Brand"`), `og:site_name`, and RSS feed name.
113
+ */
114
+ siteTitle?: string;
115
+ /** Language code (e.g. `"en"`, `"es-ES"`). */
116
+ lang?: string;
117
+ rss?: Partial<{
118
+ enabled: boolean;
119
+ path: string;
120
+ title?: string;
121
+ description?: string;
122
+ limit: number;
123
+ }>;
124
+ seo?: Partial<{
125
+ noindex: boolean;
126
+ canonical: boolean;
127
+ openGraph: boolean;
128
+ jsonLd: boolean;
129
+ }>;
130
+ nav?: Array<{
131
+ label: string;
132
+ href: string;
133
+ external?: boolean;
134
+ }>;
135
+ };
136
+ /**
137
+ * Public options for {@link useSeoMeta}.
138
+ * Only HTML + Open Graph (+ site fields). Omit keys you do not want in the type.
139
+ *
140
+ * @example
141
+ * ```ts
142
+ * // site = URL, siteTitle = brand, title = this page
143
+ * useSeoMeta({
144
+ * site: "https://katanakit.dev",
145
+ * siteTitle: "KatanaKit",
146
+ * title: "Getting started", // → <title>Getting started | KatanaKit</title>
147
+ * description: "…",
148
+ * ogImage: "/og.png",
149
+ * } satisfies UseSeoMetaOptions);
150
+ *
151
+ * useSeoMeta({ title: "Home" } as UseSeoMetaOptions<"rss" | "nav">);
152
+ * ```
153
+ */
154
+ export type UseSeoMetaOptions<OmitKeys extends keyof UseSeoMetaBase = never> = Omit<UseSeoMetaBase, OmitKeys>;
155
+ /**
156
+ * Legacy page meta. Prefer {@link UseSeoMetaOptions}.
157
+ * @deprecated
158
+ */
159
+ export interface SeoMeta {
160
+ title: string;
161
+ description?: string;
162
+ canonical?: string;
163
+ url?: string;
164
+ ogImage?: string;
165
+ ogType?: "website" | "article" | "profile";
166
+ publishedTime?: string;
167
+ modifiedTime?: string;
168
+ author?: string;
169
+ tags?: string[];
170
+ noindex?: boolean;
171
+ }
172
+ export interface SeoTagNode {
173
+ tag: "title" | "meta" | "link" | "script";
174
+ attrs?: Record<string, string>;
175
+ text?: string;
176
+ }
177
+ //# sourceMappingURL=seo-meta.types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"seo-meta.types.d.ts","sourceRoot":"","sources":["../../src/config/seo-meta.types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Slim SEO types: typical HTML meta + Open Graph (Facebook) only.
3
+ * CamelCase keys map to `<title>` / `<meta>` / `<link rel="canonical">`.
4
+ *
5
+ * Naming cheat-sheet for {@link UseSeoMetaOptions}:
6
+ * - `site` = base URL (`https://example.com`)
7
+ * - `siteTitle` = brand / site name (`"My Site"`)
8
+ * - `title` = **page** document title (`"Blog Post"` → often `"Blog Post | My Site"`)
9
+ */
10
+ export {};
11
+ //# sourceMappingURL=seo-meta.types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"seo-meta.types.js","sourceRoot":"","sources":["../../src/config/seo-meta.types.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG"}
@@ -1,72 +1,55 @@
1
- import type { SiteConfig } from "./site.config.js";
1
+ import type { SeoMeta, SeoMetaInput, SeoTagNode, UseSeoMetaBase, UseSeoMetaOptions } from "./seo-meta.types.js";
2
+ import { type SiteConfig } from "./site.config.js";
3
+ export type { SeoArrayable, SeoBooleanable, SeoMeta, SeoMetaArticle, SeoMetaFlat, SeoMetaInput, SeoOgImageObject, SeoRobotsObject, SeoTagNode, UseSeoMetaBase, UseSeoMetaOptions, } from "./seo-meta.types.js";
2
4
  /**
3
- * SEO meta tag configuration for a single page.
5
+ * Result of {@link useSeoMeta}: `html` / `tags` for the head, plus **one**
6
+ * flat object of resolved fields (site + HTML + OG). No duplicate
7
+ * `title` / `meta.title` / `config.title`.
8
+ *
9
+ * - `title` = document title (page)
10
+ * - `siteTitle` = brand / site name
11
+ * - `html` / `tags` = what you inject into `<head>`
4
12
  */
5
- export interface SeoMeta {
6
- /** Page title (will be suffixed with site title). */
7
- title: string;
8
- /** Page description (falls back to site description). */
9
- description?: string;
10
- /** Canonical URL (absolute). If omitted, derived from `url`. */
11
- canonical?: string;
12
- /** Page URL (absolute, e.g. "https://example.com/blog/post/"). */
13
- url?: string;
14
- /** OG image URL (absolute). Falls back to site config. */
15
- ogImage?: string;
16
- /** Content type: "website" | "article" | "profile" (default: "website"). */
17
- ogType?: "website" | "article" | "profile";
18
- /** Article published date (ISO string, for og:type=article). */
19
- publishedTime?: string;
20
- /** Article modified date (ISO string, for og:type=article). */
21
- modifiedTime?: string;
22
- /** Article author (for og:type=article). */
23
- author?: string;
24
- /** Article tags (for og:type=article). */
25
- tags?: string[];
26
- /** Whether to add noindex (default: false). */
27
- noindex?: boolean;
28
- }
13
+ export type SeoTagResult = UseSeoMetaOptions & {
14
+ html: string;
15
+ tags: SeoTagNode[];
16
+ jsonLd?: Record<string, unknown>;
17
+ };
18
+ /** @deprecated Use {@link SeoTagResult}. */
19
+ export type SeoTagsResult = SeoTagResult;
29
20
  /**
30
- * Generates all `<head>` meta tags for SEO, Open Graph, Twitter Card,
31
- * canonical URL, and JSON-LD structured data.
32
- *
33
- * @param config - Site-wide configuration.
34
- * @param meta - Page-specific meta.
35
- * @returns HTML string of meta tags to inject in `<head>`.
21
+ * SEO helper: one flat object in → one flat object out (+ html/tags).
36
22
  *
37
23
  * @example
38
- * ```astro
39
- * ---
40
- * import { siteConfig } from "@/config/site.config";
41
- * import { useGenerateMetaTags } from "@/config/seo.service";
42
- *
43
- * const metaTags = useGenerateMetaTags(siteConfig, {
44
- * title: "My Blog Post",
45
- * description: "A great post about TypeScript",
46
- * url: "https://example.com/blog/my-post/",
47
- * ogType: "article",
48
- * publishedTime: "2024-01-15T00:00:00Z",
24
+ * ```ts
25
+ * const seo = useSeoMeta({
26
+ * site: "https://example.com",
27
+ * siteTitle: "My Site",
28
+ * title: "Home",
29
+ * description: "…",
30
+ * ogImage: "https://example.com/image.png",
49
31
  * });
50
- * ---
51
- * <head>
52
- * <Fragment set:html={metaTags} />
53
- * </head>
32
+ * // seo.title, seo.site, seo.ogImage — once each
33
+ * // seo.html / seo.tags — head injection
54
34
  * ```
55
35
  */
56
- export declare function useGenerateMetaTags(config: SiteConfig, meta: SeoMeta): string;
36
+ export declare function useSeoMeta<OmitKeys extends keyof UseSeoMetaBase = never>(opts: UseSeoMetaOptions<OmitKeys>, defaults?: SiteConfig): SeoTagResult;
57
37
  /**
58
- * Generates a `<title>` tag string.
38
+ * @deprecated Prefer {@link useSeoMeta} with a unified flat object.
39
+ * Legacy: `useSeoTag(siteConfig, { title, description, ... })`.
59
40
  */
60
- export declare function useTitle(config: SiteConfig, pageTitle?: string): string;
41
+ export declare function useSeoTag(config: SiteConfig, meta: SeoMeta): SeoTagResult;
42
+ /** @deprecated Prefer {@link useSeoMeta}. */
43
+ export declare const useSeoTags: typeof useSeoTag;
61
44
  /**
62
- * Generates the RSS `<link>` tag for the `<head>`.
45
+ * Applies tags from a {@link SeoTagResult} into `document.head` (Vanilla / SPA).
46
+ * No-op when `document` is unavailable (SSR).
63
47
  */
48
+ export declare function useApplySeoTag(seo: SeoTagResult, head?: ParentNode | null): void;
49
+ /** HTML string of meta tags (no RSS). Prefer {@link useSeoMeta}. */
50
+ export declare function useGenerateMetaTags(config: SiteConfig, meta: SeoMeta): string;
51
+ export declare function useTitle(config: SiteConfig, pageTitle?: string): string;
64
52
  export declare function useRssHeadLink(config: SiteConfig): string;
65
- /**
66
- * Generates all default `<head>` meta tags for a page (title, description,
67
- * canonical, OG, Twitter, JSON-LD, RSS link).
68
- *
69
- * Convenience wrapper around `useGenerateMetaTags` + `useRssHeadLink`.
70
- */
71
- export declare function useHeadTags(config: SiteConfig, meta: SeoMeta): string;
53
+ /** Full `<head>` HTML (meta + RSS). Accepts legacy {@link SeoMeta} or flat {@link SeoMetaInput}. */
54
+ export declare function useHeadTags(config: SiteConfig, meta: SeoMeta | SeoMetaInput): string;
72
55
  //# sourceMappingURL=seo.service.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"seo.service.d.ts","sourceRoot":"","sources":["../../src/config/seo.service.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAEnD;;GAEG;AACH,MAAM,WAAW,OAAO;IACvB,qDAAqD;IACrD,KAAK,EAAE,MAAM,CAAC;IACd,yDAAyD;IACzD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,gEAAgE;IAChE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,kEAAkE;IAClE,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,0DAA0D;IAC1D,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,4EAA4E;IAC5E,MAAM,CAAC,EAAE,SAAS,GAAG,SAAS,GAAG,SAAS,CAAC;IAC3C,gEAAgE;IAChE,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,+DAA+D;IAC/D,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,4CAA4C;IAC5C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,0CAA0C;IAC1C,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,+CAA+C;IAC/C,OAAO,CAAC,EAAE,OAAO,CAAC;CAClB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,OAAO,GAAG,MAAM,CAmG7E;AAED;;GAEG;AACH,wBAAgB,QAAQ,CAAC,MAAM,EAAE,UAAU,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAKvE;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,CAKzD;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,OAAO,GAAG,MAAM,CAIrE"}
1
+ {"version":3,"file":"seo.service.d.ts","sourceRoot":"","sources":["../../src/config/seo.service.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACX,OAAO,EACP,YAAY,EAGZ,UAAU,EACV,cAAc,EACd,iBAAiB,EACjB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAmC,KAAK,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAEpF,YAAY,EACX,YAAY,EACZ,cAAc,EACd,OAAO,EACP,cAAc,EACd,WAAW,EACX,YAAY,EACZ,gBAAgB,EAChB,eAAe,EACf,UAAU,EACV,cAAc,EACd,iBAAiB,GACjB,MAAM,qBAAqB,CAAC;AAE7B;;;;;;;;GAQG;AACH,MAAM,MAAM,YAAY,GAAG,iBAAiB,GAAG;IAC9C,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,UAAU,EAAE,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACjC,CAAC;AAEF,4CAA4C;AAC5C,MAAM,MAAM,aAAa,GAAG,YAAY,CAAC;AAEzC;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,UAAU,CAAC,QAAQ,SAAS,MAAM,cAAc,GAAG,KAAK,EACvE,IAAI,EAAE,iBAAiB,CAAC,QAAQ,CAAC,EACjC,QAAQ,GAAE,UAA8B,GACtC,YAAY,CA6Cd;AAED;;;GAGG;AACH,wBAAgB,SAAS,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,OAAO,GAAG,YAAY,CAEzE;AAED,6CAA6C;AAC7C,eAAO,MAAM,UAAU,kBAAY,CAAC;AAgEpC;;;GAGG;AACH,wBAAgB,cAAc,CAC7B,GAAG,EAAE,YAAY,EACjB,IAAI,GAAE,UAAU,GAAG,IAA6D,GAC9E,IAAI,CAoBN;AAED,oEAAoE;AACpE,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,OAAO,GAAG,MAAM,CAM7E;AAED,wBAAgB,QAAQ,CAAC,MAAM,EAAE,UAAU,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAKvE;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,CAGzD;AAED,oGAAoG;AACpG,wBAAgB,WAAW,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,OAAO,GAAG,YAAY,GAAG,MAAM,CAKpF"}