nuxt-studio 1.3.3 → 1.4.0

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 (82) hide show
  1. package/dist/app/asciidoc-AY8u9WWM.js +1 -0
  2. package/dist/app/ayu-dark-DYE7WIF3.js +1 -0
  3. package/dist/app/ayu-light-BA47KaF1.js +1 -0
  4. package/dist/app/ayu-mirage-32ctXXKs.js +1 -0
  5. package/dist/app/bird2-DECYBE5b.js +1 -0
  6. package/dist/app/c3-BBJ779-z.js +1 -0
  7. package/dist/app/en-wvzTRdZ2.js +1 -0
  8. package/dist/app/{erb-BkKzIHzi.js → erb-BPZEWadm.js} +1 -1
  9. package/dist/app/horizon-bright-Cn-bp-IR.js +1 -0
  10. package/dist/app/{index-BemYRVDN.js → index-BzjOWvSV.js} +1 -1
  11. package/dist/app/index-DN_Tmc8V.js +1 -0
  12. package/dist/app/{index-BJwWKj3q.js → index-DnbSsQeV.js} +1 -1
  13. package/dist/app/just-BrBcRIfs.js +1 -0
  14. package/dist/app/latex-DFFaUVSZ.js +1 -0
  15. package/dist/app/{llvm-BMwXnwe8.js → llvm-w4szIS5k.js} +1 -1
  16. package/dist/app/main-BaiiAKHN.js +42 -0
  17. package/dist/app/main.d.ts +29 -23
  18. package/dist/app/main.js +1 -1
  19. package/dist/app/marko-CVUQDN1F.js +1 -0
  20. package/dist/app/{mdc-CKHPIY6R.js → mdc-E5Yo7yrS.js} +1 -1
  21. package/dist/app/mojo-C2cxD0aZ.js +1 -0
  22. package/dist/app/moonbit-B4gpyPjt.js +1 -0
  23. package/dist/app/nextflow-NhKJRLNF.js +1 -0
  24. package/dist/app/nextflow-groovy-CqvLf608.js +1 -0
  25. package/dist/app/nushell-Mk45ZIMx.js +1 -0
  26. package/dist/app/{rehype-B5jXSQHB.js → rehype-B0pzK8Ph.js} +1 -1
  27. package/dist/app/ron-DIZViclS.js +1 -0
  28. package/dist/app/{rst-Db6JICNt.js → rst-RpuXd47r.js} +1 -1
  29. package/dist/app/ruby-Bz6Ou-59.js +1 -0
  30. package/dist/app/service-worker.d.ts +23 -23
  31. package/dist/app/shared--ESjFm2d.js +1 -0
  32. package/dist/app/shared.d.ts +23 -25
  33. package/dist/app/shared.js +1 -1
  34. package/dist/app/{shiki-B5XDhU_3.js → shiki-DIDkQbrM.js} +1 -1
  35. package/dist/app/svelte-BuOg6tJl.js +1 -0
  36. package/dist/app/{swift-dg2QTUdp.js → swift-0qv2hBXI.js} +1 -1
  37. package/dist/app/tex-ByCZWQmN.js +1 -0
  38. package/dist/app/{twig-DL5s0dWc.js → twig-R-aCXzIu.js} +1 -1
  39. package/dist/module/module.d.mts +55 -0
  40. package/dist/module/module.json +1 -1
  41. package/dist/module/module.mjs +154 -99
  42. package/dist/module/runtime/host.js +30 -19
  43. package/dist/module/runtime/server/routes/ai/analyze.post.js +3 -17
  44. package/dist/module/runtime/server/routes/ai/generate.post.js +3 -17
  45. package/dist/module/runtime/server/routes/auth/github.get.d.ts +10 -3
  46. package/dist/module/runtime/server/routes/auth/github.get.js +7 -4
  47. package/dist/module/runtime/server/routes/auth/gitlab.get.js +2 -2
  48. package/dist/module/runtime/server/routes/dev/public/[...path].js +3 -2
  49. package/dist/module/runtime/server/routes/medias/[...path].d.ts +2 -0
  50. package/dist/module/runtime/server/routes/medias/[...path].js +71 -0
  51. package/dist/module/runtime/server/routes/meta.js +4 -19
  52. package/dist/module/runtime/server/utils/auth.d.ts +1 -0
  53. package/dist/module/runtime/server/utils/auth.js +20 -2
  54. package/dist/module/runtime/utils/collection.js +5 -7
  55. package/dist/module/runtime/utils/constants.d.ts +1 -0
  56. package/dist/module/runtime/utils/constants.js +1 -0
  57. package/dist/module/runtime/utils/media.js +2 -2
  58. package/package.json +23 -21
  59. package/dist/app/asciidoc-XTVL4-GN.js +0 -1
  60. package/dist/app/ayu-dark-CMjwMIkn.js +0 -1
  61. package/dist/app/ayu-light-C47S-Tmv.js +0 -1
  62. package/dist/app/ayu-mirage-CjoLj4QM.js +0 -1
  63. package/dist/app/c3-B5xr2KH_.js +0 -1
  64. package/dist/app/en-BLcCUEmi.js +0 -1
  65. package/dist/app/index-BNGZo_v7.js +0 -1
  66. package/dist/app/index-D-57dgKD.js +0 -1
  67. package/dist/app/index-DHS_I0O0.js +0 -2
  68. package/dist/app/latex-DHfEut71.js +0 -1
  69. package/dist/app/main-DIc-1QZK.js +0 -44
  70. package/dist/app/main-PbQDqQ97.js +0 -44
  71. package/dist/app/marko-2xMnbWEh.js +0 -1
  72. package/dist/app/mojo-CxwnvobC.js +0 -1
  73. package/dist/app/moonbit-Cu4LvJk1.js +0 -1
  74. package/dist/app/nextflow-D-awTbLA.js +0 -1
  75. package/dist/app/nushell-Cdolw_6l.js +0 -1
  76. package/dist/app/rehype-C7dZfu6l.js +0 -1
  77. package/dist/app/ron-1l4eGd0-.js +0 -1
  78. package/dist/app/ruby-DQYiaCa_.js +0 -1
  79. package/dist/app/shared-DSAAKzND.js +0 -1
  80. package/dist/app/shiki-BLgMZ_FB.js +0 -1
  81. package/dist/app/svelte-ChRP14-8.js +0 -1
  82. package/dist/app/tex-C-BO_DSa.js +0 -1
@@ -5,7 +5,7 @@ import { applyCollectionSchema, isDocumentMatchingContent, generateDocumentFromC
5
5
  import { getHostStyles, getSidebarWidth, adjustFixedElements } from "./utils/sidebar.js";
6
6
  import { clearError, getAppManifest, queryCollection, queryCollectionItemSurroundings, queryCollectionNavigation, queryCollectionSearchSections, useRuntimeConfig } from "#imports";
7
7
  import { collections } from "#content/preview";
8
- import { publicAssetsStorage } from "#build/studio-public-assets";
8
+ import { publicAssetsStorage, externalAssetsStorage } from "#build/studio-assets";
9
9
  import { useHostMeta } from "./composables/useMeta.js";
10
10
  import { generateIdFromFsPath as generateMediaIdFromFsPath } from "./utils/media.js";
11
11
  import { getCollectionSourceById } from "./utils/source.js";
@@ -52,11 +52,13 @@ export function useStudioHost(user, repository) {
52
52
  function useContentCollectionQuery(collection) {
53
53
  return useContent().queryCollection(collection);
54
54
  }
55
- const runtimeConfig = useRuntimeConfig();
56
- const aiConfig = runtimeConfig.public.studio.ai;
55
+ const studioConfig = useRuntimeConfig().public.studio;
56
+ const aiConfig = studioConfig.ai;
57
+ const mediaConfig = studioConfig.media;
57
58
  const host = {
58
59
  meta: {
59
60
  dev: false,
61
+ media: mediaConfig,
60
62
  ai: {
61
63
  enabled: aiConfig?.enabled ?? false,
62
64
  experimental: {
@@ -68,7 +70,7 @@ export function useStudioHost(user, repository) {
68
70
  }
69
71
  },
70
72
  getComponents: () => meta.components.value,
71
- defaultLocale: runtimeConfig.public.studio.i18n?.defaultLocale || "en",
73
+ defaultLocale: studioConfig.i18n?.defaultLocale || "en",
72
74
  getHighlightTheme: () => meta.highlightTheme.value
73
75
  },
74
76
  on: {
@@ -235,21 +237,30 @@ export function useStudioHost(user, repository) {
235
237
  contentFromDocument: async (document2) => generateContentFromDocument(document2)
236
238
  }
237
239
  },
238
- media: {
239
- get: async (fsPath) => {
240
- return await publicAssetsStorage.getItem(generateMediaIdFromFsPath(fsPath));
241
- },
242
- list: async () => {
243
- return await Promise.all(await publicAssetsStorage.getKeys().then((keys) => keys.map((key) => publicAssetsStorage.getItem(key))));
244
- },
245
- upsert: async (fsPath, media) => {
246
- const id = generateMediaIdFromFsPath(fsPath);
247
- await publicAssetsStorage.setItem(generateMediaIdFromFsPath(fsPath), { ...media, id });
248
- },
249
- delete: async (fsPath) => {
250
- await publicAssetsStorage.removeItem(generateMediaIdFromFsPath(fsPath));
251
- }
252
- },
240
+ media: /* @__PURE__ */ (() => {
241
+ const getStorage = () => host.meta.media?.external ? externalAssetsStorage : publicAssetsStorage;
242
+ return {
243
+ get: async (fsPath) => {
244
+ return await getStorage().getItem(generateMediaIdFromFsPath(fsPath));
245
+ },
246
+ list: async () => {
247
+ const storage = getStorage();
248
+ return await Promise.all(
249
+ await storage.getKeys().then(
250
+ (keys) => keys.map((key) => storage.getItem(key))
251
+ )
252
+ );
253
+ },
254
+ upsert: async (fsPath, media) => {
255
+ const id = generateMediaIdFromFsPath(fsPath);
256
+ await getStorage().setItem(id, { ...media, id });
257
+ },
258
+ delete: async (fsPath) => {
259
+ const id = generateMediaIdFromFsPath(fsPath);
260
+ await getStorage().removeItem(id);
261
+ }
262
+ };
263
+ })(),
253
264
  app: {
254
265
  getManifestId: async () => {
255
266
  const manifest = await getAppManifest();
@@ -1,8 +1,9 @@
1
1
  import { streamText } from "ai";
2
2
  import { createGateway } from "@ai-sdk/gateway";
3
- import { eventHandler, createError, useSession, getRequestProtocol, readBody } from "h3";
3
+ import { eventHandler, createError, readBody } from "h3";
4
4
  import { consola } from "consola";
5
5
  import { useRuntimeConfig } from "#imports";
6
+ import { requireStudioAuth } from "../../utils/auth.js";
6
7
  import { queryCollection } from "@nuxt/content/server";
7
8
  import {
8
9
  detectContentType,
@@ -14,6 +15,7 @@ import {
14
15
  import { ContentType } from "../../types/ai.js";
15
16
  const logger = consola.withTag("Nuxt Studio");
16
17
  export default eventHandler(async (event) => {
18
+ await requireStudioAuth(event);
17
19
  const config = useRuntimeConfig(event);
18
20
  const body = await readBody(event).catch(() => ({}));
19
21
  const collection = body.collection;
@@ -29,22 +31,6 @@ export default eventHandler(async (event) => {
29
31
  statusMessage: "Invalid collection: name and type are required"
30
32
  });
31
33
  }
32
- if (!config.public.studio.dev) {
33
- const session = await useSession(event, {
34
- name: "studio-session",
35
- password: config.studio?.auth?.sessionSecret,
36
- cookie: {
37
- secure: getRequestProtocol(event) === "https",
38
- path: "/"
39
- }
40
- });
41
- if (!session.data || Object.keys(session.data).length === 0) {
42
- throw createError({
43
- statusCode: 401,
44
- statusMessage: "Unauthorized. Please log in to use AI features."
45
- });
46
- }
47
- }
48
34
  const aiConfig = config.studio?.ai;
49
35
  const apiKey = aiConfig?.apiKey;
50
36
  if (!apiKey) {
@@ -1,30 +1,16 @@
1
1
  import { streamText } from "ai";
2
2
  import { createGateway } from "@ai-sdk/gateway";
3
- import { eventHandler, readBody, createError, useSession, getRequestProtocol } from "h3";
3
+ import { eventHandler, readBody, createError } from "h3";
4
4
  import { useRuntimeConfig } from "#imports";
5
5
  import {
6
6
  buildAIContext,
7
7
  calculateMaxTokens,
8
8
  getSystem
9
9
  } from "../../utils/ai/generate.js";
10
+ import { requireStudioAuth } from "../../utils/auth.js";
10
11
  export default eventHandler(async (event) => {
12
+ await requireStudioAuth(event);
11
13
  const config = useRuntimeConfig(event);
12
- if (!config.public.studio.dev) {
13
- const session = await useSession(event, {
14
- name: "studio-session",
15
- password: config.studio?.auth?.sessionSecret,
16
- cookie: {
17
- secure: getRequestProtocol(event) === "https",
18
- path: "/"
19
- }
20
- });
21
- if (!session.data || Object.keys(session.data).length === 0) {
22
- throw createError({
23
- statusCode: 401,
24
- statusMessage: "Unauthorized. Please log in to use AI features."
25
- });
26
- }
27
- }
28
14
  const aiConfig = config.studio?.ai;
29
15
  const apiKey = aiConfig?.apiKey;
30
16
  if (!apiKey) {
@@ -21,19 +21,26 @@ export interface OAuthGitHubConfig {
21
21
  * @default false
22
22
  */
23
23
  emailRequired?: boolean;
24
+ /**
25
+ * GitHub instance base web URL (for GitHub Enterprise Server).
26
+ * Must be the web origin without a trailing slash and without `/api/v3`,
27
+ * for example: `https://github.com` or `https://ghe.example.com`.
28
+ * @default 'https://github.com'
29
+ */
30
+ instanceUrl?: string;
24
31
  /**
25
32
  * GitHub OAuth Authorization URL
26
- * @default 'https://github.com/login/oauth/authorize'
33
+ * @default '{instanceUrl}/login/oauth/authorize'
27
34
  */
28
35
  authorizationURL?: string;
29
36
  /**
30
37
  * GitHub OAuth Token URL
31
- * @default 'https://github.com/login/oauth/access_token'
38
+ * @default '{instanceUrl}/login/oauth/access_token'
32
39
  */
33
40
  tokenURL?: string;
34
41
  /**
35
42
  * GitHub API URL
36
- * @default 'https://api.github.com'
43
+ * @default 'https://api.github.com' (or '{instanceUrl}/api/v3' for GitHub Enterprise Server)
37
44
  */
38
45
  apiURL?: string;
39
46
  /**
@@ -1,18 +1,21 @@
1
1
  import { useRuntimeConfig } from "#imports";
2
2
  import { createError, deleteCookie, eventHandler, getCookie, getQuery, getRequestURL, sendRedirect } from "h3";
3
- import { withQuery } from "ufo";
3
+ import { withQuery, withoutTrailingSlash } from "ufo";
4
4
  import { generateOAuthState, requestAccessToken, validateOAuthState } from "../../utils/auth.js";
5
5
  import { setInternalStudioUserSession } from "../../utils/session.js";
6
6
  import { mergeConfig } from "../../utils/object.js";
7
7
  export default eventHandler(async (event) => {
8
8
  const studioConfig = useRuntimeConfig(event).studio;
9
+ const instanceUrl = withoutTrailingSlash(studioConfig?.auth?.github?.instanceUrl || studioConfig?.repository?.instanceUrl || "https://github.com");
10
+ const isEnterprise = new URL(instanceUrl).hostname !== "github.com";
9
11
  const config = mergeConfig(studioConfig?.auth?.github, {
10
12
  clientId: process.env.STUDIO_GITHUB_CLIENT_ID,
11
13
  clientSecret: process.env.STUDIO_GITHUB_CLIENT_SECRET,
12
14
  redirectURL: process.env.STUDIO_GITHUB_REDIRECT_URL,
13
- authorizationURL: "https://github.com/login/oauth/authorize",
14
- tokenURL: "https://github.com/login/oauth/access_token",
15
- apiURL: "https://api.github.com",
15
+ instanceUrl,
16
+ authorizationURL: `${instanceUrl}/login/oauth/authorize`,
17
+ tokenURL: `${instanceUrl}/login/oauth/access_token`,
18
+ apiURL: isEnterprise ? `${instanceUrl}/api/v3` : "https://api.github.com",
16
19
  authorizationParams: {},
17
20
  emailRequired: true
18
21
  });
@@ -1,13 +1,13 @@
1
1
  import { useRuntimeConfig } from "#imports";
2
2
  import { createError, deleteCookie, eventHandler, getCookie, getQuery, getRequestURL, sendRedirect } from "h3";
3
3
  import { FetchError } from "ofetch";
4
- import { withQuery } from "ufo";
4
+ import { withQuery, withoutTrailingSlash } from "ufo";
5
5
  import { generateOAuthState, validateOAuthState } from "../../utils/auth.js";
6
6
  import { setInternalStudioUserSession } from "../../utils/session.js";
7
7
  import { mergeConfig } from "../../utils/object.js";
8
8
  export default eventHandler(async (event) => {
9
9
  const studioConfig = useRuntimeConfig(event).studio;
10
- const instanceUrl = studioConfig?.auth?.gitlab?.instanceUrl || "https://gitlab.com";
10
+ const instanceUrl = withoutTrailingSlash(studioConfig?.auth?.gitlab?.instanceUrl || studioConfig?.repository?.instanceUrl || "https://gitlab.com");
11
11
  const config = mergeConfig(studioConfig?.auth?.gitlab, {
12
12
  applicationId: process.env.STUDIO_GITLAB_APPLICATION_ID,
13
13
  applicationSecret: process.env.STUDIO_GITLAB_APPLICATION_SECRET,
@@ -1,9 +1,10 @@
1
1
  import { createError, eventHandler, getRequestHeader, readRawBody, setResponseHeader } from "h3";
2
2
  import { withLeadingSlash } from "ufo";
3
3
  import { useStorage } from "#imports";
4
+ import { VIRTUAL_MEDIA_COLLECTION_NAME } from "../../../../utils/constants.js";
4
5
  export default eventHandler(async (event) => {
5
6
  const path = event.path.replace("/__nuxt_studio/dev/public/", "");
6
- const key = path.replace(/\//g, ":").replace(/^public-assets:/, "");
7
+ const key = path.replace(/\//g, ":").replace(new RegExp(`^${VIRTUAL_MEDIA_COLLECTION_NAME}:`), "");
7
8
  const storage = useStorage("nuxt_studio_public_assets");
8
9
  if (event.method === "GET") {
9
10
  const lastChar = key[key.length - 1];
@@ -20,7 +21,7 @@ export default eventHandler(async (event) => {
20
21
  });
21
22
  }
22
23
  return {
23
- id: `public-assets/${key.replace(/:/g, "/")}`,
24
+ id: `${VIRTUAL_MEDIA_COLLECTION_NAME}/${key.replace(/:/g, "/")}`,
24
25
  extension: key.split(".").pop(),
25
26
  stem: key.split(".").join("."),
26
27
  path: "/" + key.replace(/:/g, "/"),
@@ -0,0 +1,2 @@
1
+ declare const _default: import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<any>>;
2
+ export default _default;
@@ -0,0 +1,71 @@
1
+ import { joinURL, withLeadingSlash } from "ufo";
2
+ import { createError, eventHandler, readBody } from "h3";
3
+ import { useRuntimeConfig } from "#imports";
4
+ import { VIRTUAL_MEDIA_COLLECTION_NAME } from "../../../utils/constants.js";
5
+ import { requireStudioAuth } from "../../utils/auth.js";
6
+ import { blob } from "hub:blob";
7
+ export default eventHandler(async (event) => {
8
+ await requireStudioAuth(event);
9
+ const { prefix, publicUrl, maxFileSize, allowedTypes } = useRuntimeConfig(event).public.studio.media;
10
+ const path = event.path.replace("/__nuxt_studio/medias/", "");
11
+ const key = path.replace(/\//g, ":").replace(new RegExp(`^${VIRTUAL_MEDIA_COLLECTION_NAME}:`), "");
12
+ if (event.method === "GET") {
13
+ const isBaseKey = key.endsWith("/") || key.endsWith(":");
14
+ if (isBaseKey) {
15
+ const subPath = key.slice(0, -1).replace(/:/g, "/");
16
+ const effectivePrefix = prefix ? subPath ? `${prefix}/${subPath}` : prefix : subPath;
17
+ const { blobs } = await blob.list(effectivePrefix ? { prefix: `${effectivePrefix}/` } : {});
18
+ return blobs.map((b) => {
19
+ return prefix ? b.pathname.slice(`${prefix}/`.length) : b.pathname;
20
+ });
21
+ }
22
+ const blobPath = key.replace(/:/g, "/");
23
+ const pathname = prefix ? `${prefix}/${blobPath}` : blobPath;
24
+ const meta = await blob.head(pathname);
25
+ if (!meta) {
26
+ throw createError({ statusCode: 404, message: "Item not found" });
27
+ }
28
+ const fsPath = withLeadingSlash(blobPath);
29
+ const resolvedPath = meta.url ?? joinURL(publicUrl, prefix, fsPath);
30
+ return {
31
+ id: path,
32
+ fsPath,
33
+ extension: fsPath.split(".").pop(),
34
+ stem: fsPath.split(".").slice(0, -1).join("."),
35
+ path: resolvedPath
36
+ };
37
+ }
38
+ if (event.method === "PUT") {
39
+ const body = await readBody(event);
40
+ const blobPath = key.replace(/:/g, "/");
41
+ const pathname = prefix ? `${prefix}/${blobPath}` : blobPath;
42
+ if (!body.raw) {
43
+ await blob.put(pathname, JSON.stringify(body), { contentType: "application/json" });
44
+ } else {
45
+ const raw = body.raw;
46
+ const [meta, data] = raw.split(";base64,");
47
+ const mimeType = meta.replace("data:", "");
48
+ const approximateSize = data.length * 3 / 4;
49
+ if (approximateSize > maxFileSize) {
50
+ throw createError({ statusCode: 413, message: `File size exceeds maximum of ${maxFileSize / 1024 / 1024}MB` });
51
+ }
52
+ if (!allowedTypes.some((t) => mimeType.startsWith(t.replace("*", "")))) {
53
+ throw createError({ statusCode: 415, message: `File type "${mimeType}" is not allowed` });
54
+ }
55
+ const binaryString = atob(data);
56
+ const bytes = new Uint8Array(binaryString.length);
57
+ for (let i = 0; i < binaryString.length; i++) {
58
+ bytes[i] = binaryString.charCodeAt(i);
59
+ }
60
+ await blob.put(pathname, bytes, { contentType: mimeType });
61
+ }
62
+ return "OK";
63
+ }
64
+ if (event.method === "DELETE") {
65
+ const blobPath = key.replace(/:/g, "/");
66
+ const pathname = prefix ? `${prefix}/${blobPath}` : blobPath;
67
+ await blob.del(pathname);
68
+ return "OK";
69
+ }
70
+ throw createError({ statusCode: 405, message: "Method not allowed" });
71
+ });
@@ -1,27 +1,12 @@
1
- import { eventHandler, useSession, getRequestProtocol } from "h3";
2
- import { useRuntimeConfig, createError } from "#imports";
1
+ import { eventHandler } from "h3";
2
+ import { useRuntimeConfig } from "#imports";
3
3
  import components from "#nuxt-component-meta/nitro";
4
4
  import { highlight } from "#mdc-imports";
5
5
  import { filterComponents } from "../utils/meta.js";
6
+ import { requireStudioAuth } from "../utils/auth.js";
6
7
  export default eventHandler(async (event) => {
8
+ await requireStudioAuth(event);
7
9
  const config = useRuntimeConfig();
8
- if (!import.meta.dev) {
9
- const session = await useSession(event, {
10
- name: "studio-session",
11
- password: config.studio?.auth?.sessionSecret,
12
- cookie: {
13
- // Use secure cookies over HTTPS, required for locally testing purposes
14
- secure: getRequestProtocol(event) === "https",
15
- path: "/"
16
- }
17
- });
18
- if (!session?.data?.user) {
19
- throw createError({
20
- statusCode: 404,
21
- message: "Not found"
22
- });
23
- }
24
- }
25
10
  const mappedComponents = Object.values(components).map(({ pascalName, filePath, meta }) => {
26
11
  return {
27
12
  name: pascalName,
@@ -1,4 +1,5 @@
1
1
  import { type H3Event } from 'h3';
2
+ export declare function requireStudioAuth(event: H3Event): Promise<void>;
2
3
  export interface RequestAccessTokenResponse {
3
4
  access_token?: string;
4
5
  scope?: string;
@@ -1,6 +1,24 @@
1
- import { createError, deleteCookie, getCookie, getRequestProtocol, setCookie } from "h3";
2
- import { FetchError } from "ofetch";
3
1
  import { getRandomValues } from "uncrypto";
2
+ import { getCookie, deleteCookie, setCookie, useSession, getRequestProtocol, createError } from "h3";
3
+ import { FetchError } from "ofetch";
4
+ import { useRuntimeConfig } from "#imports";
5
+ export async function requireStudioAuth(event) {
6
+ if (import.meta.dev) {
7
+ return;
8
+ }
9
+ const config = useRuntimeConfig(event);
10
+ const session = await useSession(event, {
11
+ name: "studio-session",
12
+ password: config.studio?.auth?.sessionSecret,
13
+ cookie: {
14
+ secure: getRequestProtocol(event) === "https",
15
+ path: "/"
16
+ }
17
+ });
18
+ if (!session?.data?.user) {
19
+ throw createError({ statusCode: 404, message: "Not found" });
20
+ }
21
+ }
4
22
  export async function requestAccessToken(url, options) {
5
23
  const headers = {
6
24
  "Content-Type": "application/x-www-form-urlencoded",
@@ -74,16 +74,14 @@ function computeValuesBasedOnCollectionSchema(collection, data) {
74
74
  const defaultValue = value?.default !== void 0 ? value.default : "NULL";
75
75
  const valueToInsert = typeof data[key] !== "undefined" ? data[key] : defaultValue;
76
76
  fields.push(key);
77
- if (type === "json") {
77
+ if (valueToInsert === null || valueToInsert === "NULL" || valueToInsert === "") {
78
+ values.push("NULL");
79
+ } else if (type === "json") {
78
80
  values.push(`'${JSON.stringify(valueToInsert).replace(/'/g, "''")}'`);
79
81
  } else if (type === "string" || ["string", "enum"].includes(value.type)) {
80
- if (["data", "datetime"].includes(value.format)) {
81
- values.push(valueToInsert !== "NULL" ? `'${new Date(valueToInsert).toISOString()}'` : defaultValue);
82
- } else {
83
- values.push(`'${String(valueToInsert).replace(/\n/g, "\\n").replace(/'/g, "''")}'`);
84
- }
82
+ values.push(`'${String(valueToInsert).replace(/\n/g, "\\n").replace(/'/g, "''")}'`);
85
83
  } else if (type === "boolean") {
86
- values.push(valueToInsert !== "NULL" ? !!valueToInsert : valueToInsert);
84
+ values.push(!!valueToInsert);
87
85
  } else {
88
86
  values.push(valueToInsert);
89
87
  }
@@ -0,0 +1 @@
1
+ export declare const VIRTUAL_MEDIA_COLLECTION_NAME: "public-assets";
@@ -0,0 +1 @@
1
+ export const VIRTUAL_MEDIA_COLLECTION_NAME = "public-assets";
@@ -1,5 +1,5 @@
1
1
  import { join } from "pathe";
2
- import { VirtualMediaCollectionName } from "nuxt-studio/app/utils";
2
+ import { VIRTUAL_MEDIA_COLLECTION_NAME } from "./constants.js";
3
3
  export function generateIdFromFsPath(fsPath) {
4
- return join(VirtualMediaCollectionName, fsPath);
4
+ return join(VIRTUAL_MEDIA_COLLECTION_NAME, fsPath);
5
5
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nuxt-studio",
3
- "version": "1.3.3",
3
+ "version": "1.4.0",
4
4
  "description": "Nuxt Studio for Nuxt Content",
5
5
  "private": false,
6
6
  "repository": {
@@ -48,59 +48,61 @@
48
48
  "clean": "rm -rf dist .nuxt .output node_modules docs/node_modules docs/.output docs/.data docs/.nuxt playground/docus/node_modules playground/docus/.output playground/docus/.data playground/docus/.nuxt playground/minimal/node_modules playground/minimal/.output playground/minimal/.data playground/minimal/.nuxt pnpm-lock.yaml"
49
49
  },
50
50
  "dependencies": {
51
- "@ai-sdk/gateway": "^3.0.42",
52
- "@ai-sdk/vue": "^3.0.82",
53
- "@iconify-json/lucide": "^1.2.90",
51
+ "@ai-sdk/gateway": "^3.0.55",
52
+ "@ai-sdk/vue": "^3.0.101",
53
+ "@iconify-json/lucide": "^1.2.94",
54
54
  "@nuxtjs/mdc": "^0.20.1",
55
55
  "@vueuse/core": "^14.2.1",
56
- "ai": "^6.0.82",
56
+ "ai": "^6.0.101",
57
57
  "defu": "^6.1.4",
58
58
  "destr": "^2.0.5",
59
59
  "js-yaml": "^4.1.1",
60
- "minimatch": "^10.1.2",
60
+ "minimatch": "^10.2.4",
61
61
  "nuxt-component-meta": "^0.17.2",
62
62
  "remark-mdc": "^3.10.0",
63
- "shiki": "^3.22.0",
63
+ "shiki": "^3.23.0",
64
64
  "unstorage": "1.17.4",
65
65
  "zod": "^4.3.6",
66
66
  "zod-to-json-schema": "^3.25.1"
67
67
  },
68
68
  "devDependencies": {
69
69
  "@gitbeaker/core": "^43.8.0",
70
- "@iconify-json/simple-icons": "^1.2.70",
71
- "@nuxt/content": "^3.11.2",
72
- "@nuxt/eslint-config": "^1.15.1",
70
+ "@iconify-json/simple-icons": "^1.2.71",
71
+ "@nuxt/content": "^3.12.0",
72
+ "@nuxt/eslint-config": "^1.15.2",
73
73
  "@nuxt/kit": "^4.3.1",
74
74
  "@nuxt/module-builder": "^1.0.2",
75
- "@nuxt/ui": "^4.4.0",
75
+ "@nuxt/ui": "^4.5.0",
76
76
  "@octokit/types": "^16.0.0",
77
77
  "@release-it/conventional-changelog": "^10.0.5",
78
78
  "@tailwindcss/typography": "^0.5.19",
79
- "@tiptap/extension-emoji": "^3.19.0",
79
+ "@tiptap/extension-emoji": "^3.20.0",
80
80
  "@types/js-yaml": "^4.0.9",
81
- "@unhead/vue": "^2.1.4",
81
+ "@unhead/vue": "^2.1.9",
82
82
  "@unpic/vue": "^1.0.0",
83
83
  "@vitejs/plugin-vue": "^6.0.4",
84
- "eslint": "^10.0.0",
84
+ "eslint": "^10.0.2",
85
85
  "idb-keyval": "^6.2.2",
86
86
  "minimark": "^0.2.0",
87
- "modern-monaco": "^0.3.7",
87
+ "modern-monaco": "^0.3.8",
88
88
  "nuxt-studio": "workspace:*",
89
89
  "ofetch": "^1.5.1",
90
90
  "release-it": "^19.2.4",
91
- "tailwindcss": "^4.1.18",
91
+ "tailwindcss": "^4.2.1",
92
92
  "vite": "^7.3.1",
93
93
  "vite-plugin-dts": "^4.5.4",
94
94
  "vite-plugin-libcss": "^1.1.2",
95
95
  "vitest": "^4.0.18",
96
- "vue": "^3.5.28",
97
- "vue-router": "^5.0.2",
98
- "vue-tsc": "^3.2.4"
96
+ "vue": "^3.5.29",
97
+ "vue-router": "^5.0.3",
98
+ "vue-tsc": "^3.2.5"
99
99
  },
100
100
  "resolutions": {
101
- "minimark": "^0.2.0"
101
+ "minimark": "^0.2.0",
102
+ "@nuxt/content": "^3.12.0",
103
+ "unimport": "5.6.0"
102
104
  },
103
- "packageManager": "pnpm@10.29.3",
105
+ "packageManager": "pnpm@10.30.3",
104
106
  "keywords": [
105
107
  "nuxt",
106
108
  "content",