nuxt-studio 1.0.0-alpha.0 → 1.0.0-alpha.2

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 (50) hide show
  1. package/README.md +11 -9
  2. package/dist/app/en-CeGQDKH5.js +7 -0
  3. package/dist/app/en-D0jd_r21.js +7 -0
  4. package/dist/app/en-XbfkDcMn.js +7 -0
  5. package/dist/app/fr-CbcFrmHX.js +7 -0
  6. package/dist/app/fr-Ct4HO5e1.js +7 -0
  7. package/dist/app/fr-ILHmVnG9.js +7 -0
  8. package/dist/app/main.d.ts +83 -33
  9. package/dist/app/main.js +34187 -30512
  10. package/dist/app/service-worker.js +29 -5
  11. package/dist/app/shared-B6H2zqDG.js +8 -0
  12. package/dist/app/{shared-D04791PA.js → shared-DLETHbvn.js} +2311 -2307
  13. package/dist/app/{shared-DI6F-ifc.js → shared-Dvm_mWyG.js} +3120 -3132
  14. package/dist/app/shared.d.ts +1 -20
  15. package/dist/app/shared.js +2 -4
  16. package/dist/module/module.d.mts +70 -27
  17. package/dist/module/module.json +1 -1
  18. package/dist/module/module.mjs +101 -58
  19. package/dist/module/runtime/host.dev.js +19 -12
  20. package/dist/module/runtime/host.js +124 -61
  21. package/dist/module/runtime/plugins/studio.client.js +1 -1
  22. package/dist/module/runtime/server/routes/admin.js +11 -2
  23. package/dist/module/runtime/server/routes/auth/github.get.d.ts +4 -4
  24. package/dist/module/runtime/server/routes/auth/github.get.js +17 -9
  25. package/dist/module/runtime/server/routes/auth/gitlab.get.d.ts +55 -0
  26. package/dist/module/runtime/server/routes/auth/gitlab.get.js +157 -0
  27. package/dist/module/runtime/server/routes/auth/session.delete.js +2 -1
  28. package/dist/module/runtime/server/routes/auth/session.get.js +4 -1
  29. package/dist/module/runtime/server/routes/dev/content/[...path].js +0 -11
  30. package/dist/module/runtime/server/routes/dev/public/[...path].d.ts +1 -0
  31. package/dist/module/runtime/server/routes/dev/public/[...path].js +2 -0
  32. package/dist/module/runtime/types/content.d.ts +6 -0
  33. package/dist/module/runtime/types/content.js +7 -0
  34. package/dist/module/runtime/utils/activation.js +16 -5
  35. package/dist/module/runtime/utils/collection.d.ts +10 -17
  36. package/dist/module/runtime/utils/collection.js +32 -92
  37. package/dist/module/runtime/utils/document.d.ts +15 -0
  38. package/dist/module/runtime/utils/document.js +288 -0
  39. package/dist/module/runtime/utils/media.d.ts +1 -0
  40. package/dist/module/runtime/utils/media.js +5 -0
  41. package/dist/module/runtime/utils/object.d.ts +4 -0
  42. package/dist/module/runtime/utils/object.js +27 -0
  43. package/dist/module/runtime/utils/source.d.ts +11 -0
  44. package/dist/module/runtime/utils/source.js +36 -0
  45. package/license.md +9 -0
  46. package/package.json +7 -6
  47. package/dist/app/shared-R5zYJ3Dl.js +0 -25803
  48. package/dist/app/utils-DI6F-ifc.js +0 -25774
  49. package/dist/app/utils.d.ts +0 -22
  50. package/dist/app/utils.js +0 -6
@@ -1,22 +1,3 @@
1
- import { CollectionItemBase } from '@nuxt/content';
2
-
3
- declare interface BaseItem {
4
- id: string;
5
- extension: string;
6
- stem: string;
7
- path?: string;
8
- }
9
-
10
- declare interface DatabaseItem extends CollectionItemBase, BaseItem {
11
- [key: string]: unknown;
12
- }
13
-
14
- export declare function generateContentFromDocument(document: DatabaseItem): Promise<string | null>;
15
-
16
- export declare function generateDocumentFromContent(id: string, content: string): Promise<DatabaseItem | null>;
17
-
18
- export declare function removeReservedKeysFromDocument(document: DatabaseItem): {
19
- [k: string]: unknown;
20
- };
1
+ export declare const VirtualMediaCollectionName: "public-assets";
21
2
 
22
3
  export { }
@@ -1,6 +1,4 @@
1
- import { e as t, f as n, F as r } from "./shared-D04791PA.js";
1
+ import { V as o } from "./shared-B6H2zqDG.js";
2
2
  export {
3
- t as generateContentFromDocument,
4
- n as generateDocumentFromContent,
5
- r as removeReservedKeysFromDocument
3
+ o as VirtualMediaCollectionName
6
4
  };
@@ -1,5 +1,38 @@
1
1
  import * as _nuxt_schema from '@nuxt/schema';
2
2
 
3
+ interface BaseRepository {
4
+ /**
5
+ * The owner of the git repository.
6
+ */
7
+ owner: string;
8
+ /**
9
+ * The repository name.
10
+ */
11
+ repo: string;
12
+ /**
13
+ * The branch to use for the git repository.
14
+ * @default 'main'
15
+ */
16
+ branch?: string;
17
+ /**
18
+ * The root directory to use for the git repository.
19
+ * @default ''
20
+ */
21
+ rootDir?: string;
22
+ /**
23
+ * Whether the repository is private or public.
24
+ * If set to false, the 'public_repo' scope will be used instead of the 'repo' scope.
25
+ * @default true
26
+ */
27
+ private?: boolean;
28
+ }
29
+ interface GitHubRepository extends BaseRepository {
30
+ provider: 'github';
31
+ }
32
+ interface GitLabRepository extends BaseRepository {
33
+ provider: 'gitlab';
34
+ instanceUrl?: string;
35
+ }
3
36
  interface ModuleOptions {
4
37
  /**
5
38
  * The route to access the studio login page.
@@ -25,43 +58,53 @@ interface ModuleOptions {
25
58
  */
26
59
  clientSecret?: string;
27
60
  };
61
+ /**
62
+ * The GitLab OAuth credentials.
63
+ */
64
+ gitlab?: {
65
+ /**
66
+ * The GitLab OAuth application ID.
67
+ * @default process.env.STUDIO_GITLAB_APPLICATION_ID
68
+ */
69
+ applicationId?: string;
70
+ /**
71
+ * The GitLab OAuth application secret.
72
+ * @default process.env.STUDIO_GITLAB_APPLICATION_SECRET
73
+ */
74
+ applicationSecret?: string;
75
+ /**
76
+ * The GitLab instance URL (for self-hosted instances).
77
+ * @default 'https://gitlab.com'
78
+ */
79
+ instanceUrl?: string;
80
+ };
28
81
  };
29
82
  /**
30
83
  * The git repository information to connect to.
31
84
  */
32
- repository?: {
33
- /**
34
- * The provider to use for the git repository.
35
- * @default 'github'
36
- */
37
- provider?: 'github';
38
- /**
39
- * The owner of the git repository.
40
- */
41
- owner: string;
42
- /**
43
- * The repository name.
44
- */
45
- repo: string;
46
- /**
47
- * The branch to use for the git repository.
48
- * @default 'main'
49
- */
50
- branch?: string;
51
- /**
52
- * The root directory to use for the git repository.
53
- * @default ''
54
- */
55
- rootDir?: string;
56
- };
85
+ repository?: GitHubRepository | GitLabRepository;
86
+ /**
87
+ * Enable Nuxt Studio to edit content and media files on your filesystem.
88
+ */
89
+ dev: boolean;
57
90
  /**
58
91
  * Enable Nuxt Studio to edit content and media files on your filesystem.
59
- * Currently experimental.
60
- * @experimental
92
+ *
93
+ * @deprecated Use the 'dev' option instead.
61
94
  */
62
95
  development?: {
63
96
  sync?: boolean;
64
97
  };
98
+ /**
99
+ * i18n settings for the Studio.
100
+ */
101
+ i18n?: {
102
+ /**
103
+ * The default locale to use.
104
+ * @default 'en'
105
+ */
106
+ defaultLocale?: string;
107
+ };
65
108
  }
66
109
  declare const _default: _nuxt_schema.NuxtModule<ModuleOptions, ModuleOptions, false>;
67
110
 
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "nuxt-studio",
3
3
  "configKey": "studio",
4
- "version": "1.0.0-alpha.0",
4
+ "version": "1.0.0-alpha.2",
5
5
  "docs": "https://content.nuxt.com/studio",
6
6
  "builder": {
7
7
  "@nuxt/module-builder": "1.0.2",
@@ -1,9 +1,10 @@
1
- import { useLogger, defineNuxtModule, createResolver, addPlugin, extendViteConfig, addServerHandler, addVitePlugin, addTemplate } from '@nuxt/kit';
1
+ import { addServerHandler, addVitePlugin, useLogger, defineNuxtModule, createResolver, extendViteConfig, addPlugin, addTemplate } from '@nuxt/kit';
2
2
  import { createHash } from 'node:crypto';
3
3
  import { defu } from 'defu';
4
4
  import { resolve } from 'node:path';
5
5
  import fsDriver from 'unstorage/drivers/fs';
6
6
  import { createStorage } from 'unstorage';
7
+ import { withLeadingSlash } from 'ufo';
7
8
 
8
9
  async function getAssetsStorageDevTemplate(_assetsStorage, _nuxt) {
9
10
  return [
@@ -21,11 +22,13 @@ async function getAssetsStorageTemplate(assetsStorage, _nuxt) {
21
22
  "const storage = createStorage({})",
22
23
  "",
23
24
  ...keys.map((key) => {
25
+ const path = withLeadingSlash(key.replace(/:/g, "/"));
24
26
  const value = {
25
27
  id: `public-assets/${key.replace(/:/g, "/")}`,
26
28
  extension: key.split(".").pop(),
27
29
  stem: key.split(".").join("."),
28
- path: "/" + key.replace(/:/g, "/")
30
+ path,
31
+ fsPath: path
29
32
  };
30
33
  return `storage.setItem('${value.id}', ${JSON.stringify(value)})`;
31
34
  }),
@@ -34,10 +37,47 @@ async function getAssetsStorageTemplate(assetsStorage, _nuxt) {
34
37
  ].join("\n");
35
38
  }
36
39
 
37
- const version = "1.0.0-alpha.0";
40
+ const version = "1.0.0-alpha.2";
41
+
42
+ function setupDevMode(nuxt, runtime, assetsStorage) {
43
+ nuxt.options.nitro.storage = {
44
+ ...nuxt.options.nitro.storage,
45
+ nuxt_studio_content: {
46
+ driver: "fs",
47
+ base: resolve(nuxt.options.rootDir, "content")
48
+ },
49
+ nuxt_studio_public_assets: {
50
+ driver: "fs",
51
+ base: resolve(nuxt.options.rootDir, "public")
52
+ }
53
+ };
54
+ addServerHandler({
55
+ route: "/__nuxt_studio/dev/content/**",
56
+ handler: runtime("./server/routes/dev/content/[...path]")
57
+ });
58
+ addServerHandler({
59
+ route: "/__nuxt_studio/dev/public/**",
60
+ handler: runtime("./server/routes/dev/public/[...path]")
61
+ });
62
+ addVitePlugin({
63
+ name: "nuxt-studio",
64
+ configureServer: (server) => {
65
+ assetsStorage.watch((type, file) => {
66
+ server.ws.send({
67
+ type: "custom",
68
+ event: "nuxt-studio:media:update",
69
+ data: { type, id: `public-assets/${file}` }
70
+ });
71
+ });
72
+ },
73
+ closeWatcher: () => {
74
+ assetsStorage.unwatch();
75
+ }
76
+ });
77
+ }
38
78
 
39
79
  const logger = useLogger("nuxt-studio");
40
- const module = defineNuxtModule({
80
+ const module$1 = defineNuxtModule({
41
81
  meta: {
42
82
  name: "nuxt-studio",
43
83
  configKey: "studio",
@@ -45,60 +85,82 @@ const module = defineNuxtModule({
45
85
  docs: "https://content.nuxt.com/studio"
46
86
  },
47
87
  defaults: {
88
+ dev: true,
48
89
  route: "/_studio",
49
90
  repository: {
50
91
  provider: "github",
51
92
  owner: "",
52
93
  repo: "",
53
94
  branch: "main",
54
- rootDir: ""
95
+ rootDir: "",
96
+ private: true
55
97
  },
56
98
  auth: {
57
99
  github: {
58
100
  clientId: process.env.STUDIO_GITHUB_CLIENT_ID,
59
101
  clientSecret: process.env.STUDIO_GITHUB_CLIENT_SECRET
102
+ },
103
+ gitlab: {
104
+ applicationId: process.env.STUDIO_GITLAB_APPLICATION_ID,
105
+ applicationSecret: process.env.STUDIO_GITLAB_APPLICATION_SECRET,
106
+ instanceUrl: process.env.STUDIO_GITLAB_INSTANCE_URL || process.env.CI_SERVER_URL || "https://gitlab.com"
60
107
  }
61
108
  },
62
- development: {
63
- sync: false
109
+ i18n: {
110
+ defaultLocale: "en"
64
111
  }
65
112
  },
66
113
  async setup(options, nuxt) {
67
114
  const resolver = createResolver(import.meta.url);
68
115
  const runtime = (...args) => resolver.resolve("./runtime", ...args);
69
- if (!nuxt.options.dev) {
70
- options.development.sync = false;
116
+ if (nuxt.options.dev === false || options.development?.sync === false) {
117
+ options.dev = false;
71
118
  }
72
119
  if (!nuxt.options.dev && !nuxt.options._prepare) {
73
- if (!options.auth?.github?.clientId && !options.auth?.github?.clientSecret) {
120
+ const provider = options.repository?.provider || "github";
121
+ const hasGitHubAuth = options.auth?.github?.clientId && options.auth?.github?.clientSecret;
122
+ const hasGitLabAuth = options.auth?.gitlab?.applicationId && options.auth?.gitlab?.applicationSecret;
123
+ if (provider === "github" && !hasGitHubAuth) {
74
124
  logger.warn([
75
- "Nuxt Content Studio relies on GitHub OAuth to authenticate users.",
125
+ "Nuxt Content Studio requires GitHub OAuth to authenticate users.",
76
126
  "Please set the `STUDIO_GITHUB_CLIENT_ID` and `STUDIO_GITHUB_CLIENT_SECRET` environment variables."
77
127
  ].join(" "));
128
+ } else if (provider === "gitlab" && !hasGitLabAuth) {
129
+ logger.warn([
130
+ "Nuxt Content Studio requires GitLab OAuth to authenticate users.",
131
+ "Please set the `STUDIO_GITLAB_APPLICATION_ID` and `STUDIO_GITLAB_APPLICATION_SECRET` environment variables."
132
+ ].join(" "));
78
133
  }
79
134
  }
80
135
  nuxt.options.experimental = nuxt.options.experimental || {};
81
136
  nuxt.options.experimental.checkOutdatedBuildInterval = 1e3 * 30;
82
137
  nuxt.options.runtimeConfig.public.studio = {
83
138
  route: options.route,
139
+ dev: Boolean(options.dev),
84
140
  development: {
85
- sync: Boolean(options.development.sync),
86
141
  server: process.env.STUDIO_DEV_SERVER
87
142
  },
88
143
  // @ts-expect-error Autogenerated type does not match with options
89
- repository: options.repository
144
+ repository: options.repository,
145
+ // @ts-expect-error Autogenerated type does not match with options
146
+ i18n: options.i18n
90
147
  };
91
148
  nuxt.options.runtimeConfig.studio = {
92
149
  auth: {
93
150
  sessionSecret: createHash("md5").update([
94
151
  options.auth?.github?.clientId,
95
- options.auth?.github?.clientSecret
152
+ options.auth?.github?.clientSecret,
153
+ options.auth?.gitlab?.applicationId,
154
+ options.auth?.gitlab?.applicationSecret
96
155
  ].join("")).digest("hex"),
97
156
  // @ts-expect-error todo fix github type issue
98
- github: options.auth?.github
99
- }
157
+ github: options.auth?.github,
158
+ // @ts-expect-error autogenerated type doesn't match with project options
159
+ gitlab: options.auth?.gitlab
160
+ },
161
+ // @ts-expect-error Autogenerated type does not match with options
162
+ repository: options.repository
100
163
  };
101
- addPlugin(process.env.STUDIO_DEV_SERVER ? runtime("./plugins/studio.client.dev") : runtime("./plugins/studio.client"));
102
164
  nuxt.options.vite = defu(nuxt.options.vite, {
103
165
  vue: {
104
166
  template: {
@@ -118,42 +180,7 @@ const module = defineNuxtModule({
118
180
  "extend"
119
181
  ];
120
182
  });
121
- if (options.development.sync) {
122
- nuxt.options.nitro.storage = {
123
- ...nuxt.options.nitro.storage,
124
- nuxt_studio_content: {
125
- driver: "fs",
126
- base: resolve(nuxt.options.rootDir, "content")
127
- },
128
- nuxt_studio_public_assets: {
129
- driver: "fs",
130
- base: resolve(nuxt.options.srcDir, "public")
131
- }
132
- };
133
- addServerHandler({
134
- route: "/__nuxt_studio/dev/content/**",
135
- handler: runtime("./server/routes/dev/content/[...path]")
136
- });
137
- addServerHandler({
138
- route: "/__nuxt_studio/dev/public/**",
139
- handler: runtime("./server/routes/dev/public/[...path]")
140
- });
141
- addVitePlugin({
142
- name: "nuxt-studio",
143
- configureServer: (server) => {
144
- assetsStorage.watch((type, file) => {
145
- server.ws.send({
146
- type: "custom",
147
- event: "nuxt-studio:media:update",
148
- data: { type, id: `public-assets/${file}` }
149
- });
150
- });
151
- },
152
- closeWatcher: () => {
153
- assetsStorage.unwatch();
154
- }
155
- });
156
- }
183
+ addPlugin(process.env.STUDIO_DEV_SERVER ? runtime("./plugins/studio.client.dev") : runtime("./plugins/studio.client"));
157
184
  const assetsStorage = createStorage({
158
185
  driver: fsDriver({
159
186
  base: resolve(nuxt.options.rootDir, "public")
@@ -161,12 +188,19 @@ const module = defineNuxtModule({
161
188
  });
162
189
  addTemplate({
163
190
  filename: "studio-public-assets.mjs",
164
- getContents: () => options.development.sync ? getAssetsStorageDevTemplate() : getAssetsStorageTemplate(assetsStorage)
191
+ getContents: () => options.dev ? getAssetsStorageDevTemplate() : getAssetsStorageTemplate(assetsStorage)
165
192
  });
193
+ if (options.dev) {
194
+ setupDevMode(nuxt, runtime, assetsStorage);
195
+ }
166
196
  addServerHandler({
167
197
  route: "/__nuxt_studio/auth/github",
168
198
  handler: runtime("./server/routes/auth/github.get")
169
199
  });
200
+ addServerHandler({
201
+ route: "/__nuxt_studio/auth/gitlab",
202
+ handler: runtime("./server/routes/auth/gitlab.get")
203
+ });
170
204
  addServerHandler({
171
205
  route: "/__nuxt_studio/auth/session",
172
206
  handler: runtime("./server/routes/auth/session.get")
@@ -176,10 +210,19 @@ const module = defineNuxtModule({
176
210
  route: "/__nuxt_studio/auth/session",
177
211
  handler: runtime("./server/routes/auth/session.delete")
178
212
  });
179
- addServerHandler({ route: options.route, handler: runtime("./server/routes/admin") });
180
- addServerHandler({ route: "/__nuxt_studio/meta", handler: runtime("./server/routes/meta") });
181
- addServerHandler({ route: "/sw.js", handler: runtime("./server/routes/sw") });
213
+ addServerHandler({
214
+ route: options.route,
215
+ handler: runtime("./server/routes/admin")
216
+ });
217
+ addServerHandler({
218
+ route: "/__nuxt_studio/meta",
219
+ handler: runtime("./server/routes/meta")
220
+ });
221
+ addServerHandler({
222
+ route: "/sw.js",
223
+ handler: runtime("./server/routes/sw")
224
+ });
182
225
  }
183
226
  });
184
227
 
185
- export { module as default };
228
+ export { module$1 as default };
@@ -1,14 +1,15 @@
1
1
  import { useStudioHost as useStudioHostBase } from "./host.js";
2
- import { generateContentFromDocument } from "nuxt-studio/app/utils";
3
- import { createCollectionDocument, getCollectionInfo } from "./utils/collection.js";
2
+ import { getCollectionByFilePath, generateIdFromFsPath, generateFsPathFromId, getCollectionById } from "./utils/collection.js";
3
+ import { normalizeDocument } from "./utils/document.js";
4
4
  import { createStorage } from "unstorage";
5
5
  import httpDriver from "unstorage/drivers/http";
6
6
  import { useRuntimeConfig } from "#imports";
7
7
  import { collections } from "#content/preview";
8
8
  import { debounce } from "perfect-debounce";
9
+ import { getCollectionSourceById } from "./utils/source.js";
9
10
  export function useStudioHost(user, repository) {
10
11
  const host = useStudioHostBase(user, repository);
11
- if (!useRuntimeConfig().public.studio.development.sync) {
12
+ if (!useRuntimeConfig().public.studio.dev) {
12
13
  return host;
13
14
  }
14
15
  host.meta.dev = true;
@@ -17,24 +18,30 @@ export function useStudioHost(user, repository) {
17
18
  });
18
19
  host.app.requestRerender = () => {
19
20
  };
20
- host.document.upsert = debounce(async (id, upsertedDocument) => {
21
- id = id.replace(/:/g, "/");
22
- const collection = getCollectionInfo(id, collections).collection;
23
- const doc = createCollectionDocument(collection, id, upsertedDocument);
24
- const content = await generateContentFromDocument(doc);
25
- await devStorage.setItem(host.document.getFileSystemPath(id), content, {
21
+ host.document.db.upsert = debounce(async (fsPath, upsertedDocument) => {
22
+ const collectionInfo = getCollectionByFilePath(fsPath, collections);
23
+ if (!collectionInfo) {
24
+ throw new Error(`Collection not found for fsPath: ${fsPath}`);
25
+ }
26
+ const id = generateIdFromFsPath(fsPath, collectionInfo);
27
+ const document = normalizeDocument(id, collectionInfo, upsertedDocument);
28
+ const content = await host.document.generate.contentFromDocument(document);
29
+ await devStorage.setItem(fsPath, content, {
26
30
  headers: {
27
31
  "content-type": "text/plain"
28
32
  }
29
33
  });
30
34
  }, 100);
31
- host.document.delete = async (id) => {
32
- await devStorage.removeItem(host.document.getFileSystemPath(id.replace(/:/g, "/")));
35
+ host.document.db.delete = async (fsPath) => {
36
+ await devStorage.removeItem(fsPath);
33
37
  };
34
38
  host.on.documentUpdate = (fn) => {
35
39
  import.meta.hot.on("nuxt-content:update", (data) => {
40
+ const collection = getCollectionById(data.key, collections);
41
+ const source = getCollectionSourceById(data.key, collection.source);
42
+ const fsPath = generateFsPathFromId(data.key, source);
36
43
  const isRemoved = data.queries.length === 0;
37
- fn(data.key, isRemoved ? "remove" : "update");
44
+ fn(fsPath, isRemoved ? "remove" : "update");
38
45
  });
39
46
  };
40
47
  host.on.mediaUpdate = (fn) => {