@scalar/nuxt 0.4.34 → 0.4.35

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/dist/module.json CHANGED
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "name": "@scalar/nuxt",
3
3
  "configKey": "scalar",
4
- "version": "0.4.34",
4
+ "version": "0.4.35",
5
5
  "builder": {
6
- "@nuxt/module-builder": "0.8.1",
6
+ "@nuxt/module-builder": "1.0.1",
7
7
  "unbuild": "unknown"
8
8
  }
9
9
  }
package/dist/module.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { defineNuxtModule, createResolver, addComponent, extendPages, addPlugin } from '@nuxt/kit';
1
+ import { defineNuxtModule, createResolver, addComponent, extendPages } from '@nuxt/kit';
2
2
 
3
3
  const module = defineNuxtModule({
4
4
  meta: {
@@ -26,17 +26,20 @@ const module = defineNuxtModule({
26
26
  _nuxt.options.imports.transform ||= {};
27
27
  _nuxt.options.imports.transform.exclude ||= [];
28
28
  _nuxt.options.imports.transform.exclude.push(/scalar/);
29
- _nuxt.options.vite.optimizeDeps ||= {};
30
- _nuxt.options.vite.optimizeDeps.include ||= [];
31
- _nuxt.options.vite.optimizeDeps.include.push(
32
- "@scalar/nuxt > @scalar/api-reference",
33
- "@scalar/nuxt > jsonpointer",
34
- "@scalar/nuxt > ajv-draft-04",
35
- "@scalar/nuxt > ajv-formats",
36
- "@scalar/nuxt > ajv",
37
- "@scalar/nuxt > asjv-draft-04 > ajv",
38
- "@scalar/nuxt > asjv-formats > ajv"
39
- );
29
+ _nuxt.options.vite ||= {};
30
+ _nuxt.options.vite.ssr ||= {};
31
+ if (Array.isArray(_nuxt.options.vite.ssr.noExternal)) {
32
+ _nuxt.options.vite.ssr.noExternal.push("ajv-draft-04", "ajv-formats", "ajv", "jsonpointer", "whatwg-mimetype");
33
+ } else {
34
+ _nuxt.options.vite.ssr.noExternal = [
35
+ ...Array.isArray(_nuxt.options.vite.ssr.noExternal) ? _nuxt.options.vite.ssr.noExternal : [],
36
+ "ajv-draft-04",
37
+ "ajv-formats",
38
+ "ajv",
39
+ "jsonpointer",
40
+ "whatwg-mimetype"
41
+ ];
42
+ }
40
43
  _nuxt.hook("nitro:config", (config) => {
41
44
  if (config.experimental?.openAPI) {
42
45
  isOpenApiEnabled = true;
@@ -92,7 +95,6 @@ const module = defineNuxtModule({
92
95
  });
93
96
  });
94
97
  }
95
- addPlugin(resolver.resolve("./runtime/plugins/hydrateClient"));
96
98
  }
97
99
  });
98
100
 
@@ -1,104 +1,124 @@
1
- <script lang="ts" setup>
2
- import { ApiReferenceLayout, parse } from '@scalar/api-reference'
3
- import type { ApiReferenceConfiguration } from '@scalar/types/api-reference'
4
- import { useColorMode } from '@scalar/use-hooks/useColorMode'
5
- import { useFetch, useHead, useRequestURL, useSeoMeta } from '#imports'
6
- import type { Configuration } from '~/src/types'
7
- import { onMounted, reactive, ref, toRaw, watch } from 'vue'
8
-
9
- const props = defineProps<{
10
- configuration: Configuration
11
- }>()
12
-
13
- const isDark = ref(props.configuration.darkMode)
14
- const forcedMode = props.configuration.forceDarkModeState
15
-
1
+ <script setup>
2
+ import { ApiReferenceWorkspace } from "@scalar/api-reference";
3
+ import { useColorMode } from "@scalar/use-hooks/useColorMode";
4
+ import { createWorkspaceStore } from "@scalar/workspace-store/client";
5
+ import {
6
+ useAsyncData,
7
+ useFetch,
8
+ useHead,
9
+ useRequestURL,
10
+ useRoute,
11
+ useSeoMeta,
12
+ useState
13
+ } from "#imports";
14
+ import { onMounted, ref, toRaw, watch } from "vue";
15
+ const props = defineProps({
16
+ configuration: { type: Object, required: true }
17
+ });
18
+ const isDark = ref(props.configuration.darkMode);
19
+ const forcedMode = props.configuration.forceDarkModeState;
16
20
  const { colorMode, toggleColorMode } = useColorMode({
17
- initialColorMode: props.configuration.darkMode ? 'dark' : 'light',
18
- overrideColorMode: props.configuration.forceDarkModeState,
19
- })
20
-
21
- // @ts-expect-error support the old syntax for a bit
22
- const content = props.configuration.spec?.content ?? props.configuration.content
23
- // @ts-expect-error support the old syntax for a bit
24
- const url = props.configuration.spec?.url ?? props.configuration.url
25
-
26
- // Grab spec if we can
27
- const document =
28
- typeof content === 'function'
29
- ? toRaw(content())
30
- : content
31
- ? toRaw(content)
32
- : url
33
- ? (await useFetch<string>(url, { responseType: 'text' })).data.value
34
- : (await useFetch<string>('/_openapi.json', { responseType: 'text' }))
35
- .data.value
36
-
37
- // Set the fetched spec to the config content to prevent ApiReferenceLayout from fetching it again on the client side
38
- props.configuration.content = document
39
-
40
- // Check for empty spec
21
+ initialColorMode: props.configuration.darkMode ? "dark" : "light",
22
+ overrideColorMode: props.configuration.forceDarkModeState
23
+ });
24
+ const content = props.configuration.spec?.content ?? props.configuration.content;
25
+ const url = props.configuration.spec?.url ?? props.configuration.url;
26
+ const currentRoute = useRoute();
27
+ const meta = currentRoute.meta;
28
+ const document = useState("document", () => null);
29
+ if (!document.value) {
30
+ if (typeof content === "function") {
31
+ document.value = content();
32
+ } else if (content) {
33
+ document.value = content;
34
+ } else if (url) {
35
+ try {
36
+ const response = await useFetch(url, { responseType: "text" });
37
+ document.value = response.data.value || null;
38
+ } catch (error) {
39
+ console.error("Failed to fetch spec from URL:", error);
40
+ }
41
+ } else if (meta.isOpenApiEnabled) {
42
+ try {
43
+ const { data } = await useAsyncData("openapi-spec", async () => {
44
+ const response = await $fetch("/_openapi.json", {
45
+ responseType: "text"
46
+ });
47
+ return response;
48
+ });
49
+ document.value = data.value || null;
50
+ } catch (error) {
51
+ console.error("Failed to fetch OpenAPI spec from /_openapi.json:", error);
52
+ }
53
+ }
54
+ }
55
+ props.configuration.content = document.value;
41
56
  if (!document) {
42
- throw new Error('You must provide a document for Scalar API References')
57
+ throw new Error(
58
+ "You must provide a document for Scalar API References. Either provide a spec URL/content, or enable experimental openAPI in the Nitro config."
59
+ );
43
60
  }
44
-
45
- const parsedSpec = reactive(await parse(document))
46
- const rawSpec = JSON.stringify(document)
47
-
48
- // Load up the metadata
49
61
  if (props.configuration?.metaData) {
50
- useSeoMeta(props.configuration.metaData)
62
+ useSeoMeta(props.configuration.metaData);
51
63
  }
52
-
53
64
  useHead({
54
65
  script: [
55
66
  {
56
67
  // Inject dark / light detection that runs before loading Nuxt to avoid flicker
57
68
  // This is a bit of a hack inspired by @nuxtjs/color-mode, but it works
58
- id: 'scalar-color-mode-script',
59
- tagPosition: 'bodyClose',
69
+ id: "scalar-color-mode-script",
70
+ tagPosition: "bodyClose",
60
71
  innerHTML: `((isDark, forced) => {
61
72
  try {
62
73
  const stored = window.localStorage.getItem('colorMode');
63
74
  const useDark = forced === 'dark' || !forced && (stored === 'dark' || !stored && isDark);
64
75
  window.document.body.classList.add(useDark ? 'dark-mode' : 'light-mode');
65
76
  } catch {}
66
- })(${isDark.value}, ${JSON.stringify(forcedMode)});`
67
- .replace(/[\n\r]/g, '')
68
- .replace(/ +/g, ' '),
69
- },
70
- ],
71
- })
72
-
77
+ })(${isDark.value}, ${JSON.stringify(forcedMode)});`.replace(/[\n\r]/g, "").replace(/ +/g, " ")
78
+ }
79
+ ]
80
+ });
73
81
  watch(colorMode, () => {
74
- isDark.value = colorMode.value === 'dark'
75
- })
76
-
82
+ isDark.value = colorMode.value === "dark";
83
+ });
77
84
  onMounted(() => {
78
- // Adjust the color mode toggle switch
79
- isDark.value = window.document.body.classList.contains('dark-mode')
80
- // Remove scalar-color-mode-script
81
- window.document.getElementById('scalar-color-mode-script')?.remove()
82
- })
83
-
84
- // Add baseServerURL and _integration
85
- const { origin } = useRequestURL()
86
-
87
- const config: Partial<ApiReferenceConfiguration> = {
85
+ isDark.value = window.document.body.classList.contains("dark-mode");
86
+ window.document.getElementById("scalar-color-mode-script")?.remove();
87
+ });
88
+ const { origin } = useRequestURL();
89
+ const config = {
88
90
  baseServerURL: origin,
89
- _integration: 'nuxt',
90
- layout: 'modern',
91
- ...props.configuration,
91
+ _integration: "nuxt",
92
+ layout: "modern",
93
+ ...props.configuration
94
+ };
95
+ const route = useRoute();
96
+ const store = createWorkspaceStore();
97
+ let parsedDocument;
98
+ if (typeof document.value === "string") {
99
+ try {
100
+ parsedDocument = JSON.parse(document.value);
101
+ } catch (error) {
102
+ console.error("Failed to parse OpenAPI document:", error);
103
+ throw new Error("Invalid OpenAPI document format");
104
+ }
105
+ } else {
106
+ if (document.value && typeof document.value === "object") {
107
+ parsedDocument = document.value;
108
+ } else {
109
+ throw new Error("Document must be a valid OpenAPI object");
110
+ }
92
111
  }
112
+ store.addDocumentSync({
113
+ name: route.name,
114
+ document: parsedDocument
115
+ });
93
116
  </script>
94
117
 
95
118
  <template>
96
- <ApiReferenceLayout
97
- :configuration="config"
98
- :isDark="!!isDark"
99
- :parsedSpec="parsedSpec"
100
- :rawSpec="rawSpec"
101
- @toggleDarkMode="() => toggleColorMode()" />
119
+ <ApiReferenceWorkspace
120
+ :store
121
+ :configuration="config" />
102
122
  </template>
103
123
 
104
124
  <style>
@@ -0,0 +1,15 @@
1
+ import type { Configuration } from '../../types.js';
2
+ type __VLS_Props = {
3
+ configuration: Configuration;
4
+ };
5
+ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropTypes<__VLS_TypePropsToOption<__VLS_Props>>, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<__VLS_TypePropsToOption<__VLS_Props>>> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
6
+ export default _default;
7
+ type __VLS_NonUndefinedable<T> = T extends undefined ? never : T;
8
+ type __VLS_TypePropsToOption<T> = {
9
+ [K in keyof T]-?: {} extends Pick<T, K> ? {
10
+ type: import('vue').PropType<__VLS_NonUndefinedable<T[K]>>;
11
+ } : {
12
+ type: import('vue').PropType<T[K]>;
13
+ required: true;
14
+ };
15
+ };
@@ -1,23 +1,13 @@
1
- <script lang="ts" setup>
2
- import { useRoute } from '#imports'
3
- import type { Meta } from '~/src/types'
4
-
5
- const route = useRoute()
6
- const meta = route.meta as Meta
7
-
8
- // Ensure we have a spec
9
- if (
10
- !meta.isOpenApiEnabled &&
11
- !meta.configuration?.url &&
12
- !meta.configuration?.content &&
13
- // @ts-expect-error support the old syntax for a bit
14
- !meta.configuration?.spec?.url &&
15
- // @ts-expect-error support the old syntax for a bit
16
- !meta.configuration?.spec?.content
17
- ) {
1
+ <script setup>
2
+ import { useRoute } from "#imports";
3
+ const route = useRoute();
4
+ const meta = route.meta;
5
+ if (!meta.isOpenApiEnabled && !meta.configuration?.url && !meta.configuration?.content && // @ts-expect-error support the old syntax for a bit
6
+ !meta.configuration?.spec?.url && // @ts-expect-error support the old syntax for a bit
7
+ !meta.configuration?.spec?.content) {
18
8
  throw new Error(
19
- 'You must either provide a spec to scalar, or enable experimental openApi in the Nitro config.',
20
- )
9
+ "You must either provide a spec to scalar, or enable experimental openApi in the Nitro config."
10
+ );
21
11
  }
22
12
  </script>
23
13
 
@@ -0,0 +1,2 @@
1
+ declare const _default: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
2
+ export default _default;
package/dist/types.d.mts CHANGED
@@ -1 +1 @@
1
- export { type ModuleOptions, default } from './module.js'
1
+ export { type ModuleOptions, default } from './module.mjs'
package/package.json CHANGED
@@ -20,42 +20,42 @@
20
20
  "testing",
21
21
  "vue"
22
22
  ],
23
- "version": "0.4.34",
23
+ "version": "0.4.35",
24
24
  "engines": {
25
25
  "node": ">=20"
26
26
  },
27
27
  "type": "module",
28
- "main": "./dist/module.cjs",
29
- "types": "./dist/types.d.ts",
28
+ "main": "./dist/module.mjs",
29
+ "types": "./dist/types.d.mts",
30
30
  "exports": {
31
31
  ".": {
32
- "types": "./dist/types.d.ts",
33
- "import": "./dist/module.mjs",
34
- "require": "./dist/module.cjs"
32
+ "types": "./dist/types.d.mts",
33
+ "import": "./dist/module.mjs"
35
34
  }
36
35
  },
37
36
  "files": [
38
37
  "dist"
39
38
  ],
40
39
  "dependencies": {
41
- "@nuxt/kit": "^3.12.3",
42
- "@scalar/api-reference": "1.32.10",
43
- "@scalar/api-client": "2.5.19",
40
+ "@nuxt/kit": "^4.0.0",
41
+ "vue": "^3.5.17",
42
+ "@scalar/types": "0.2.11",
43
+ "@scalar/api-client": "2.5.20",
44
+ "@scalar/api-reference": "1.33.0",
44
45
  "@scalar/use-hooks": "0.2.4",
45
- "@scalar/types": "0.2.10"
46
+ "@scalar/workspace-store": "0.11.0"
46
47
  },
47
48
  "devDependencies": {
48
- "@nuxt/devtools": "^1.3.9",
49
+ "@nuxt/devtools": "^2.6.2",
49
50
  "@nuxt/eslint-config": "^0.7.3",
50
- "@nuxt/module-builder": "^0.8.1",
51
- "@nuxt/schema": "^3.12.3",
52
- "@nuxt/test-utils": "^3.13.1",
51
+ "@nuxt/module-builder": "^1.0.1",
52
+ "@nuxt/schema": "^4.0.0",
53
+ "@nuxt/test-utils": "^3.19.2",
53
54
  "@types/node": "^22.9.0",
54
- "changelogen": "^0.5.5",
55
55
  "cross-env": "^7.0.3",
56
- "nuxt": "^3.12.4",
57
- "vite": "5.4.19",
58
- "vitest": "^1.6.1"
56
+ "nuxt": "^4.0.0",
57
+ "vite": "6.1.6",
58
+ "vitest": "^3.2.4"
59
59
  },
60
60
  "scripts": {
61
61
  "build": "cross-env NUXT_TELEMETRY_DISABLED=false pnpm dev:prepare && nuxt-module-build build",
@@ -67,6 +67,6 @@
67
67
  "lint:check": "scalar-lint-check",
68
68
  "lint:fix": "scalar-lint-fix",
69
69
  "test:watch": "vitest watch",
70
- "types:check": "nuxi typecheck"
70
+ "types:check": "NUXT_TELEMETRY_DISABLED=true nuxi typecheck"
71
71
  }
72
72
  }
package/dist/module.cjs DELETED
@@ -1,5 +0,0 @@
1
- module.exports = function(...args) {
2
- return import('./module.mjs').then(m => m.default.call(this, ...args))
3
- }
4
- const _meta = module.exports.meta = require('./module.json')
5
- module.exports.getMeta = () => Promise.resolve(_meta)
package/dist/module.d.ts DELETED
@@ -1,29 +0,0 @@
1
- import * as _nuxt_schema from '@nuxt/schema';
2
- import { ApiReferenceConfiguration } from '@scalar/types/api-reference';
3
-
4
- type Configuration = Omit<Partial<ApiReferenceConfiguration>, 'layout' | 'isEditable' | 'onSpecUpdate' | 'theme'> & {
5
- /**
6
- * Whether to show scalar in Nuxt DevTools
7
- *
8
- * @default true
9
- */
10
- devtools: boolean;
11
- /**
12
- * The theme to use for the reference
13
- *
14
- * @default undefined (nuxt theme)
15
- */
16
- theme?: ApiReferenceConfiguration['theme'];
17
- };
18
-
19
- type ModuleOptions = {
20
- /**
21
- * For multiple references, pass an array of config objects into
22
- * configurations. These configurations will extend over the base config
23
- */
24
- configurations: Omit<Configuration, 'devtools'>[];
25
- layout: string | false;
26
- } & Configuration;
27
- declare const _default: _nuxt_schema.NuxtModule<ModuleOptions, ModuleOptions, false>;
28
-
29
- export { type ModuleOptions, _default as default };
@@ -1,2 +0,0 @@
1
- declare const _default: import("#app").Plugin<Record<string, unknown>> & import("#app").ObjectPlugin<Record<string, unknown>>;
2
- export default _default;
@@ -1,13 +0,0 @@
1
- import { defineNuxtPlugin } from "#app";
2
- import { useHead } from "#imports";
3
- export default defineNuxtPlugin((_nuxtApp) => {
4
- _nuxtApp.hook("app:rendered", ({ ssrContext }) => {
5
- useHead({
6
- script: [
7
- {
8
- children: `window.__SCALAR__ = ${JSON.stringify(ssrContext?.payload?.data ?? {})}`
9
- }
10
- ]
11
- });
12
- });
13
- });
package/dist/types.d.ts DELETED
@@ -1 +0,0 @@
1
- export { type ModuleOptions, default } from './module'