nuxt-files-sdk 0.0.1 → 0.0.3

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/config.d.ts CHANGED
@@ -1,28 +1,101 @@
1
1
  import { FilesHooks, FilesPlugin, ProviderSlug } from "files-sdk";
2
- import { LoadFilesOptions } from "files-sdk/loader";
3
2
  //#region src/config.d.ts
4
- export type StorageConfig<Plugins extends readonly FilesPlugin[] = readonly FilesPlugin[]> = Omit<LoadFilesOptions, 'provider'> & {
5
- /** Files SDK provider subpath, for example `r2`, `s3`, or `fs`. */
6
- adapter: ProviderSlug;
7
- /** Native Files SDK plugins, applied in array order. */
3
+ interface ProviderFactories {
4
+ akamai: typeof import('files-sdk/akamai').akamai;
5
+ alibaba: typeof import('files-sdk/alibaba').alibaba;
6
+ appwrite: typeof import('files-sdk/appwrite').appwrite;
7
+ archil: typeof import('files-sdk/archil').archil;
8
+ azure: typeof import('files-sdk/azure').azure;
9
+ 'backblaze-b2': typeof import('files-sdk/backblaze-b2').backblazeB2;
10
+ box: typeof import('files-sdk/box').box;
11
+ 'bun-s3': typeof import('files-sdk/bun-s3').bunS3;
12
+ 'bunny-storage': typeof import('files-sdk/bunny-storage').bunnyStorage;
13
+ cloudinary: typeof import('files-sdk/cloudinary').cloudinaryAdapter;
14
+ convex: typeof import('files-sdk/convex').convex;
15
+ 'digitalocean-spaces': typeof import('files-sdk/digitalocean-spaces').digitaloceanSpaces;
16
+ dropbox: typeof import('files-sdk/dropbox').dropbox;
17
+ exoscale: typeof import('files-sdk/exoscale').exoscale;
18
+ filebase: typeof import('files-sdk/filebase').filebase;
19
+ 'firebase-storage': typeof import('files-sdk/firebase-storage').firebaseStorage;
20
+ fs: typeof import('files-sdk/fs').fs;
21
+ ftp: typeof import('files-sdk/ftp').ftp;
22
+ gcs: typeof import('files-sdk/gcs').gcs;
23
+ 'google-drive': typeof import('files-sdk/google-drive').googleDrive;
24
+ hetzner: typeof import('files-sdk/hetzner').hetzner;
25
+ 'ibm-cos': typeof import('files-sdk/ibm-cos').ibmCos;
26
+ 'idrive-e2': typeof import('files-sdk/idrive-e2').idriveE2;
27
+ memory: typeof import('files-sdk/memory').memory;
28
+ minio: typeof import('files-sdk/minio').minio;
29
+ neon: typeof import('files-sdk/neon').neon;
30
+ 'netlify-blobs': typeof import('files-sdk/netlify-blobs').netlifyBlobs;
31
+ onedrive: typeof import('files-sdk/onedrive').onedrive;
32
+ 'oracle-cloud': typeof import('files-sdk/oracle-cloud').oracleCloud;
33
+ ovhcloud: typeof import('files-sdk/ovhcloud').ovhcloud;
34
+ pocketbase: typeof import('files-sdk/pocketbase').pocketbase;
35
+ r2: typeof import('files-sdk/r2').r2;
36
+ s3: typeof import('files-sdk/s3').s3;
37
+ 's3-fetch': typeof import('files-sdk/s3-fetch').s3Fetch;
38
+ scaleway: typeof import('files-sdk/scaleway').scaleway;
39
+ sftp: typeof import('files-sdk/sftp').sftp;
40
+ sharepoint: typeof import('files-sdk/sharepoint').sharepoint;
41
+ storj: typeof import('files-sdk/storj').storj;
42
+ supabase: typeof import('files-sdk/supabase').supabase;
43
+ tencent: typeof import('files-sdk/tencent').tencent;
44
+ tigris: typeof import('files-sdk/tigris').tigris;
45
+ uploadthing: typeof import('files-sdk/uploadthing').uploadthing;
46
+ 'vercel-blob': typeof import('files-sdk/vercel-blob').vercelBlob;
47
+ vultr: typeof import('files-sdk/vultr').vultr;
48
+ wasabi: typeof import('files-sdk/wasabi').wasabi;
49
+ webdav: typeof import('files-sdk/webdav').webdav;
50
+ yandex: typeof import('files-sdk/yandex').yandex;
51
+ }
52
+ type ProviderOptions<Provider extends ProviderSlug> = Parameters<ProviderFactories[Provider]>[0];
53
+ type ConfigValue<Provider extends ProviderSlug> = Exclude<ProviderOptions<Provider>, undefined>;
54
+ type ConfigInput<Provider extends ProviderSlug> = ConfigValue<Provider> | (() => ConfigValue<Provider>);
55
+ type ProviderConfig<Provider extends ProviderSlug> = {
56
+ /** Native provider factory options, or a synchronous runtime resolver for them. */
57
+ config?: ConfigInput<Provider>;
58
+ } & (undefined extends ProviderOptions<Provider> ? unknown : {
59
+ config: ConfigInput<Provider>;
60
+ });
61
+ /** Configuration for one Files SDK storage. */
62
+ export type StorageConfig<Provider extends ProviderSlug = ProviderSlug, Plugins extends readonly FilesPlugin[] = readonly FilesPlugin[]> = Provider extends ProviderSlug ? {
63
+ /** Files SDK provider slug, for example `r2`, `s3`, or `fs`. */
64
+ adapter: Provider;
65
+ /** Native Files SDK plugins applied in array order. */
8
66
  plugins?: Plugins;
9
- /** Native Files SDK hooks. They run before the integration hook bridge. */
67
+ /** Native Files SDK lifecycle hooks. */
10
68
  hooks?: FilesHooks;
11
- };
12
- export type DevStorageConfig = Omit<StorageConfig, 'plugins' | 'hooks'> & {
13
- /** Plugins belong to the logical storage and cannot be replaced in development. */
14
- plugins?: never;
15
- /** Hooks belong to the logical storage and cannot be replaced in development. */
16
- hooks?: never;
17
- };
18
- export interface FilesConfig<Storage extends Record<string, StorageConfig> = Record<string, StorageConfig>> {
19
- /** Storage used when useServerFiles() is called without a name. */
20
- default?: keyof Storage & string;
21
- /** Explicit development overrides. These never act as failure fallbacks. */
22
- devStorage?: Partial<{ [Name in keyof Storage]: DevStorageConfig; }>;
69
+ /** Scope every operation under this key prefix. */
70
+ prefix?: string;
71
+ /** Retry provider failures up to this many times. */
72
+ retries?: number;
73
+ /** Per-attempt timeout in milliseconds. */
74
+ timeout?: number;
75
+ } & ProviderConfig<Provider> : never;
76
+ /** Development-only provider settings for a storage. */
77
+ export type DevStorageConfig<Provider extends ProviderSlug = ProviderSlug> = Provider extends ProviderSlug ? {
78
+ adapter: Provider;
79
+ } & ProviderConfig<Provider> : never;
80
+ /** One unnamed storage, available through `useServerFiles()`. */
81
+ export interface SingleFilesConfig<Storage extends StorageConfig = StorageConfig> {
82
+ /** Files SDK storage configuration. */
23
83
  storage: Storage;
84
+ /** Development-only provider settings. */
85
+ devStorage?: DevStorageConfig;
86
+ }
87
+ /** Named storages, each requiring its name when accessed. */
88
+ export interface NamedFilesConfig<Storages extends Record<string, StorageConfig> = Record<string, StorageConfig>> {
89
+ /** Files SDK storage configuration. */
90
+ storage: Storages;
91
+ /** Development-only provider settings keyed by storage name. */
92
+ devStorage?: Partial<{ [Name in keyof Storages]: DevStorageConfig; }>;
24
93
  }
25
- /** Preserve storage names and plugin tuples for generated/project types. */
26
- export declare const defineFilesConfig: <const Config extends FilesConfig>(config: Config) => Config;
94
+ /** Files SDK configuration used by the Nuxt/Nitro integration. */
95
+ export type FilesConfig = SingleFilesConfig | NamedFilesConfig;
96
+ /** Define one unnamed Files SDK storage while preserving its provider and plugin types. */
97
+ export declare function defineFilesConfig<const Storage extends StorageConfig>(config: SingleFilesConfig<Storage>): SingleFilesConfig<Storage>;
98
+ /** Define named Files SDK storages while preserving their names, providers, and plugin types. */
99
+ export declare function defineFilesConfig<const Storages extends Record<string, StorageConfig>>(config: NamedFilesConfig<Storages>): NamedFilesConfig<Storages>;
27
100
  //#endregion
28
101
  //# sourceMappingURL=config.d.ts.map
package/dist/config.js CHANGED
@@ -1,6 +1,7 @@
1
1
  //#region src/config.ts
2
- /** Preserve storage names and plugin tuples for generated/project types. */
3
- const defineFilesConfig = (config) => config;
2
+ function defineFilesConfig(config) {
3
+ return config;
4
+ }
4
5
  //#endregion
5
6
  export { defineFilesConfig };
6
7
 
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","names":[],"sources":["../src/config.ts"],"sourcesContent":["import type { FilesHooks, FilesPlugin, ProviderSlug } from 'files-sdk'\nimport type { LoadFilesOptions } from 'files-sdk/loader'\n\nexport type StorageConfig<Plugins extends readonly FilesPlugin[] = readonly FilesPlugin[]> = Omit<\n LoadFilesOptions,\n 'provider'\n> & {\n /** Files SDK provider subpath, for example `r2`, `s3`, or `fs`. */\n adapter: ProviderSlug\n /** Native Files SDK plugins, applied in array order. */\n plugins?: Plugins\n /** Native Files SDK hooks. They run before the integration hook bridge. */\n hooks?: FilesHooks\n}\n\nexport type DevStorageConfig = Omit<StorageConfig, 'plugins' | 'hooks'> & {\n /** Plugins belong to the logical storage and cannot be replaced in development. */\n plugins?: never\n /** Hooks belong to the logical storage and cannot be replaced in development. */\n hooks?: never\n}\n\nexport interface FilesConfig<Storage extends Record<string, StorageConfig> = Record<string, StorageConfig>> {\n /** Storage used when useServerFiles() is called without a name. */\n default?: keyof Storage & string\n /** Explicit development overrides. These never act as failure fallbacks. */\n devStorage?: Partial<{ [Name in keyof Storage]: DevStorageConfig }>\n storage: Storage\n}\n\n/** Preserve storage names and plugin tuples for generated/project types. */\nexport const defineFilesConfig = <const Config extends FilesConfig>(config: Config): Config => config\n"],"mappings":";;AA+BA,MAAa,qBAAuD,WAA2B"}
1
+ {"version":3,"file":"config.js","names":[],"sources":["../src/config.ts"],"sourcesContent":["import type { FilesHooks, FilesPlugin, ProviderSlug } from 'files-sdk'\n\ninterface ProviderFactories {\n akamai: typeof import('files-sdk/akamai').akamai\n alibaba: typeof import('files-sdk/alibaba').alibaba\n appwrite: typeof import('files-sdk/appwrite').appwrite\n archil: typeof import('files-sdk/archil').archil\n azure: typeof import('files-sdk/azure').azure\n 'backblaze-b2': typeof import('files-sdk/backblaze-b2').backblazeB2\n box: typeof import('files-sdk/box').box\n 'bun-s3': typeof import('files-sdk/bun-s3').bunS3\n 'bunny-storage': typeof import('files-sdk/bunny-storage').bunnyStorage\n cloudinary: typeof import('files-sdk/cloudinary').cloudinaryAdapter\n convex: typeof import('files-sdk/convex').convex\n 'digitalocean-spaces': typeof import('files-sdk/digitalocean-spaces').digitaloceanSpaces\n dropbox: typeof import('files-sdk/dropbox').dropbox\n exoscale: typeof import('files-sdk/exoscale').exoscale\n filebase: typeof import('files-sdk/filebase').filebase\n 'firebase-storage': typeof import('files-sdk/firebase-storage').firebaseStorage\n fs: typeof import('files-sdk/fs').fs\n ftp: typeof import('files-sdk/ftp').ftp\n gcs: typeof import('files-sdk/gcs').gcs\n 'google-drive': typeof import('files-sdk/google-drive').googleDrive\n hetzner: typeof import('files-sdk/hetzner').hetzner\n 'ibm-cos': typeof import('files-sdk/ibm-cos').ibmCos\n 'idrive-e2': typeof import('files-sdk/idrive-e2').idriveE2\n memory: typeof import('files-sdk/memory').memory\n minio: typeof import('files-sdk/minio').minio\n neon: typeof import('files-sdk/neon').neon\n 'netlify-blobs': typeof import('files-sdk/netlify-blobs').netlifyBlobs\n onedrive: typeof import('files-sdk/onedrive').onedrive\n 'oracle-cloud': typeof import('files-sdk/oracle-cloud').oracleCloud\n ovhcloud: typeof import('files-sdk/ovhcloud').ovhcloud\n pocketbase: typeof import('files-sdk/pocketbase').pocketbase\n r2: typeof import('files-sdk/r2').r2\n s3: typeof import('files-sdk/s3').s3\n 's3-fetch': typeof import('files-sdk/s3-fetch').s3Fetch\n scaleway: typeof import('files-sdk/scaleway').scaleway\n sftp: typeof import('files-sdk/sftp').sftp\n sharepoint: typeof import('files-sdk/sharepoint').sharepoint\n storj: typeof import('files-sdk/storj').storj\n supabase: typeof import('files-sdk/supabase').supabase\n tencent: typeof import('files-sdk/tencent').tencent\n tigris: typeof import('files-sdk/tigris').tigris\n uploadthing: typeof import('files-sdk/uploadthing').uploadthing\n 'vercel-blob': typeof import('files-sdk/vercel-blob').vercelBlob\n vultr: typeof import('files-sdk/vultr').vultr\n wasabi: typeof import('files-sdk/wasabi').wasabi\n webdav: typeof import('files-sdk/webdav').webdav\n yandex: typeof import('files-sdk/yandex').yandex\n}\n\ntype ProviderOptions<Provider extends ProviderSlug> = Parameters<ProviderFactories[Provider]>[0]\ntype ConfigValue<Provider extends ProviderSlug> = Exclude<ProviderOptions<Provider>, undefined>\ntype ConfigInput<Provider extends ProviderSlug> = ConfigValue<Provider> | (() => ConfigValue<Provider>)\ntype ProviderConfig<Provider extends ProviderSlug> = {\n /** Native provider factory options, or a synchronous runtime resolver for them. */\n config?: ConfigInput<Provider>\n} & (undefined extends ProviderOptions<Provider> ? unknown : { config: ConfigInput<Provider> })\n\n/** Configuration for one Files SDK storage. */\nexport type StorageConfig<\n Provider extends ProviderSlug = ProviderSlug,\n Plugins extends readonly FilesPlugin[] = readonly FilesPlugin[],\n> = Provider extends ProviderSlug\n ? {\n /** Files SDK provider slug, for example `r2`, `s3`, or `fs`. */\n adapter: Provider\n /** Native Files SDK plugins applied in array order. */\n plugins?: Plugins\n /** Native Files SDK lifecycle hooks. */\n hooks?: FilesHooks\n /** Scope every operation under this key prefix. */\n prefix?: string\n /** Retry provider failures up to this many times. */\n retries?: number\n /** Per-attempt timeout in milliseconds. */\n timeout?: number\n } & ProviderConfig<Provider>\n : never\n\n/** Development-only provider settings for a storage. */\nexport type DevStorageConfig<Provider extends ProviderSlug = ProviderSlug> = Provider extends ProviderSlug\n ? { adapter: Provider } & ProviderConfig<Provider>\n : never\n\n/** One unnamed storage, available through `useServerFiles()`. */\nexport interface SingleFilesConfig<Storage extends StorageConfig = StorageConfig> {\n /** Files SDK storage configuration. */\n storage: Storage\n /** Development-only provider settings. */\n devStorage?: DevStorageConfig\n}\n\n/** Named storages, each requiring its name when accessed. */\nexport interface NamedFilesConfig<Storages extends Record<string, StorageConfig> = Record<string, StorageConfig>> {\n /** Files SDK storage configuration. */\n storage: Storages\n /** Development-only provider settings keyed by storage name. */\n devStorage?: Partial<{ [Name in keyof Storages]: DevStorageConfig }>\n}\n\n/** Files SDK configuration used by the Nuxt/Nitro integration. */\nexport type FilesConfig = SingleFilesConfig | NamedFilesConfig\n\n/** Define one unnamed Files SDK storage while preserving its provider and plugin types. */\nexport function defineFilesConfig<const Storage extends StorageConfig>(\n config: SingleFilesConfig<Storage>,\n): SingleFilesConfig<Storage>\n/** Define named Files SDK storages while preserving their names, providers, and plugin types. */\nexport function defineFilesConfig<const Storages extends Record<string, StorageConfig>>(\n config: NamedFilesConfig<Storages>,\n): NamedFilesConfig<Storages>\nexport function defineFilesConfig(config: FilesConfig): FilesConfig {\n return config\n}\n"],"mappings":";AAiHA,SAAgB,kBAAkB,QAAkC;CAChE,OAAO;AACX"}
@@ -84,7 +84,7 @@
84
84
  ...snapshot.storages.map((storage) => {
85
85
  const row = document.createElement('tr')
86
86
  for (const value of [
87
- storage.name,
87
+ storage.name ?? 'Single storage',
88
88
  storage.adapter,
89
89
  storage.plugins.join(', ') || '—',
90
90
  storage.source,
@@ -1,7 +1,7 @@
1
1
  //#region src/devtools/snapshot.d.ts
2
2
  export interface FilesDevtoolsSnapshot {
3
3
  storages: Array<{
4
- name: string;
4
+ name?: string;
5
5
  adapter: string;
6
6
  plugins: string[];
7
7
  source: 'storage' | 'devStorage';
@@ -1 +1 @@
1
- {"version":3,"file":"snapshot.js","names":[],"sources":["../../src/devtools/snapshot.ts"],"sourcesContent":["import { inspectFiles } from '../runtime'\n\nexport interface FilesDevtoolsSnapshot {\n storages: Array<{\n name: string\n adapter: string\n plugins: string[]\n source: 'storage' | 'devStorage'\n initialized: boolean\n }>\n diagnostics: Array<{\n code: string\n level: 'info' | 'warning' | 'error'\n message: string\n }>\n}\n\nexport const FILES_DEVTOOLS_PATH = '/__nuxt-files-sdk/'\nexport const FILES_SNAPSHOT_PATH = `${FILES_DEVTOOLS_PATH}snapshot`\n\nexport default () => inspectFiles()\n"],"mappings":";;AAiBA,MAAa,sBAAsB;AACnC,MAAa,sBAAsB,GAAG,oBAAoB;AAE1D,IAAA,yBAAqB,aAAa"}
1
+ {"version":3,"file":"snapshot.js","names":[],"sources":["../../src/devtools/snapshot.ts"],"sourcesContent":["import { inspectFiles } from '../runtime'\n\nexport interface FilesDevtoolsSnapshot {\n storages: Array<{\n name?: string\n adapter: string\n plugins: string[]\n source: 'storage' | 'devStorage'\n initialized: boolean\n }>\n diagnostics: Array<{\n code: string\n level: 'info' | 'warning' | 'error'\n message: string\n }>\n}\n\nexport const FILES_DEVTOOLS_PATH = '/__nuxt-files-sdk/'\nexport const FILES_SNAPSHOT_PATH = `${FILES_DEVTOOLS_PATH}snapshot`\n\nexport default () => inspectFiles()\n"],"mappings":";;AAiBA,MAAa,sBAAsB;AACnC,MAAa,sBAAsB,GAAG,oBAAoB;AAE1D,IAAA,yBAAqB,aAAa"}
@@ -1,3 +1,5 @@
1
+ import "../config.js";
2
+ import { ProviderSlug } from "files-sdk";
1
3
  //#region src/integration/nitro.d.ts
2
4
  export interface NitroIntegration {
3
5
  meta?: {
@@ -8,10 +10,19 @@ export interface NitroIntegration {
8
10
  buildDir: string;
9
11
  dev?: boolean;
10
12
  plugins: string[];
13
+ alias?: Record<string, string>;
11
14
  externals?: {
12
15
  inline?: unknown[];
13
16
  };
14
17
  };
18
+ unimport?: {
19
+ getInternalContext(): {
20
+ addons: {
21
+ name?: string;
22
+ declaration?: (declarations: string) => string;
23
+ }[];
24
+ };
25
+ };
15
26
  hooks: {
16
27
  hook(name: 'types:extend', callback: (types: {
17
28
  tsConfig?: {
@@ -1,27 +1,67 @@
1
1
  import { resolve } from "node:path";
2
2
  import { mkdir, writeFile } from "node:fs/promises";
3
+ import { getProvider } from "files-sdk/providers";
4
+ import { createJiti } from "jiti";
3
5
  //#region src/integration/nitro.ts
6
+ const isStorageConfig = (value) => Boolean(value && typeof value === "object" && "adapter" in value && typeof value.adapter === "string");
7
+ const isStorageRecord = (value) => Boolean(value && typeof value === "object" && Object.values(value).every(isStorageConfig));
8
+ const selectedAdapters = (config, development) => {
9
+ const storage = config.storage;
10
+ const devStorage = config.devStorage;
11
+ if (!storage || !isStorageConfig(storage) && (!isStorageRecord(storage) || Object.keys(storage).length === 0)) throw new Error("[nuxt-files-sdk:invalid-config] At least one storage is required.");
12
+ const selected = [];
13
+ const single = isStorageConfig(storage);
14
+ if (single) {
15
+ if (devStorage && !isStorageConfig(devStorage)) throw new Error("[nuxt-files-sdk:invalid-config] A single storage requires a single devStorage override.");
16
+ selected.push(development && isStorageConfig(devStorage) ? devStorage : storage);
17
+ } else {
18
+ if (devStorage && !isStorageRecord(devStorage)) throw new Error("[nuxt-files-sdk:invalid-config] Named storage requires named devStorage overrides.");
19
+ for (const name of Object.keys(devStorage ?? {})) if (!Object.hasOwn(storage, name)) throw new Error(`[nuxt-files-sdk:unknown-storage] Unknown storage "${name}".`);
20
+ for (const [name, namedStorage] of Object.entries(storage)) selected.push(development ? devStorage?.[name] ?? namedStorage : namedStorage);
21
+ }
22
+ const adapters = [...new Set(selected.map(({ adapter }) => adapter))].toSorted();
23
+ for (const adapter of adapters) if (!getProvider(adapter)) throw new Error(`[nuxt-files-sdk:unknown-adapter] Unknown adapter "${adapter}".`);
24
+ return {
25
+ adapters,
26
+ single
27
+ };
28
+ };
29
+ const factoryName = (adapter) => adapter === "cloudinary" ? "cloudinaryAdapter" : adapter.replaceAll(/-([a-z0-9])/gu, (_, character) => character.toUpperCase());
30
+ const providerCode = (adapters) => ({
31
+ imports: adapters.map((adapter, index) => `import { ${factoryName(adapter)} as provider${index} } from ${JSON.stringify(`files-sdk/${adapter}`)}`).join("\n"),
32
+ factories: adapters.map((adapter, index) => `${JSON.stringify(adapter)}: provider${index}`).join(", ")
33
+ });
4
34
  const hookTypes = (moduleName) => `
5
35
  declare module ${JSON.stringify(moduleName)} {
6
36
  interface NitroRuntimeHooks {
7
- 'files:action': (payload: { event: import('files-sdk').FilesActionEvent; storage: string }) => void | Promise<void>
8
- 'files:error': (payload: { event: import('files-sdk').FilesErrorEvent; storage: string }) => void | Promise<void>
9
- 'files:retry': (payload: { event: import('files-sdk').FilesRetryEvent; storage: string }) => void | Promise<void>
37
+ 'files:action': (payload: { event: import('files-sdk').FilesActionEvent; storage?: string }) => void | Promise<void>
38
+ 'files:error': (payload: { event: import('files-sdk').FilesErrorEvent; storage?: string }) => void | Promise<void>
39
+ 'files:retry': (payload: { event: import('files-sdk').FilesRetryEvent; storage?: string }) => void | Promise<void>
10
40
  }
11
41
  }
12
42
  `;
13
- const storageTypes = (configPath, nitroMajor) => `import type config from ${JSON.stringify(configPath)}
14
- import type { DefaultStorage, StorageRegistry } from 'nuxt-files-sdk/runtime'
43
+ const storageTypes = (configPath, nitroMajor, single) => `import type config from ${JSON.stringify(configPath)}
44
+ import type { SingleStorage, StorageRegistry } from 'nuxt-files-sdk/runtime'
15
45
 
16
46
  declare module 'nuxt-files-sdk/runtime' {
17
- interface NuxtFilesStorageRegistry extends StorageRegistry<typeof config> {}
18
- interface NuxtFilesDefaultStorage { value: DefaultStorage<typeof config> }
47
+ ${single ? "interface NuxtFilesSingleStorage { value: SingleStorage<typeof config> }" : "interface NuxtFilesStorageRegistry extends StorageRegistry<typeof config> {}"}
19
48
  }
20
49
  ${hookTypes(nitroMajor >= 3 ? "nitro/types" : "nitropack/types")}
21
50
  export {}
22
51
  `;
23
52
  const setupNitroFilesIntegration = async (nitro, options) => {
24
53
  const configPath = options.configPath.replaceAll("\\", "/");
54
+ const config = await createJiti(import.meta.url, {
55
+ ...nitro.options.alias ? { alias: nitro.options.alias } : {},
56
+ interopDefault: true,
57
+ moduleCache: false
58
+ }).import(configPath, { default: true });
59
+ const { adapters, single } = selectedAdapters(config, options.development);
60
+ const providers = providerCode(adapters);
61
+ nitro.unimport?.getInternalContext().addons.push({
62
+ name: "nuxt-files-sdk-jsdoc",
63
+ declaration: (declarations) => declarations.replace(/^(\s*)(const useServerFiles: typeof .*\.useServerFiles)$/mu, "$1/** Return the project's Files client, including its configured plugin extensions. */\n$1const useServerFiles: typeof import('nuxt-files-sdk/runtime').useServerFiles")
64
+ });
25
65
  const externals = nitro.options.externals ??= {};
26
66
  (externals.inline ??= []).push("nuxt-files-sdk");
27
67
  if (!nitro.options.dev) externals.inline.push("files-sdk");
@@ -33,21 +73,23 @@ const setupNitroFilesIntegration = async (nitro, options) => {
33
73
  nitro.hooks.hook("types:extend", async (types) => {
34
74
  await mkdir(directory, { recursive: true });
35
75
  await Promise.all([writeFile(pluginPath, `import config from ${JSON.stringify(configPath)}
76
+ ${providers.imports}
36
77
  import { configureFiles } from 'nuxt-files-sdk/runtime'
37
78
 
38
79
  export default (nitroApp) => configureFiles(config, {
39
80
  development: ${JSON.stringify(options.development)},
81
+ factories: { ${providers.factories} },
40
82
  hooks: {
41
83
  onAction: (event, storage) => nitroApp.hooks.callHook('files:action', { event, storage }),
42
84
  onError: (event, storage) => nitroApp.hooks.callHook('files:error', { event, storage }),
43
85
  onRetry: (event, storage) => nitroApp.hooks.callHook('files:retry', { event, storage }),
44
86
  },
45
87
  })
46
- `), writeFile(typesPath, storageTypes(configPath, nitro.meta?.majorVersion ?? ("routing" in nitro ? 3 : 2)))]);
88
+ `), writeFile(typesPath, storageTypes(configPath, nitro.meta?.majorVersion ?? ("routing" in nitro ? 3 : 2), single))]);
47
89
  types.tsConfig?.include?.push(typesPath);
48
90
  });
49
91
  };
50
92
  //#endregion
51
- export { setupNitroFilesIntegration, storageTypes };
93
+ export { providerCode, selectedAdapters, setupNitroFilesIntegration, storageTypes };
52
94
 
53
95
  //# sourceMappingURL=nitro.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"nitro.js","names":[],"sources":["../../src/integration/nitro.ts"],"sourcesContent":["import { mkdir, writeFile } from 'node:fs/promises'\nimport { resolve } from 'node:path'\n\nexport interface NitroIntegration {\n meta?: { majorVersion?: number }\n options: { rootDir: string; buildDir: string; dev?: boolean; plugins: string[]; externals?: { inline?: unknown[] } }\n hooks: {\n hook(\n name: 'types:extend',\n callback: (types: { tsConfig?: { include?: string[] } }) => void | Promise<void>,\n ): void\n }\n}\n\nexport interface NitroFilesIntegrationOptions {\n configPath: string\n development: boolean\n}\n\nconst hookTypes = (moduleName: 'nitropack/types' | 'nitro/types'): string => `\ndeclare module ${JSON.stringify(moduleName)} {\n interface NitroRuntimeHooks {\n 'files:action': (payload: { event: import('files-sdk').FilesActionEvent; storage: string }) => void | Promise<void>\n 'files:error': (payload: { event: import('files-sdk').FilesErrorEvent; storage: string }) => void | Promise<void>\n 'files:retry': (payload: { event: import('files-sdk').FilesRetryEvent; storage: string }) => void | Promise<void>\n }\n}\n`\n\nexport const storageTypes = (\n configPath: string,\n nitroMajor: number,\n): string => `import type config from ${JSON.stringify(configPath)}\nimport type { DefaultStorage, StorageRegistry } from 'nuxt-files-sdk/runtime'\n\ndeclare module 'nuxt-files-sdk/runtime' {\n interface NuxtFilesStorageRegistry extends StorageRegistry<typeof config> {}\n interface NuxtFilesDefaultStorage { value: DefaultStorage<typeof config> }\n}\n${hookTypes(nitroMajor >= 3 ? 'nitro/types' : 'nitropack/types')}\nexport {}\n`\n\nexport const setupNitroFilesIntegration = async (\n nitro: NitroIntegration,\n options: NitroFilesIntegrationOptions,\n): Promise<void> => {\n const configPath = options.configPath.replaceAll('\\\\', '/')\n // Inline both packages so installed consumers also tree-shake the plugin barrel.\n const externals = (nitro.options.externals ??= {})\n ;(externals.inline ??= []).push('nuxt-files-sdk')\n // Nitro's single-file dev build would eagerly import every native provider SDK.\n if (!nitro.options.dev) externals.inline.push('files-sdk')\n const directory = resolve(nitro.options.buildDir, 'nuxt-files-sdk')\n const pluginPath = resolve(directory, 'plugin.mjs')\n const typesPath = resolve(directory, 'storage-registry.d.ts')\n // Development also externalizes local .mjs files unless explicitly inlined.\n externals.inline.push(pluginPath.replaceAll('\\\\', '/'), configPath)\n nitro.options.plugins.push(pluginPath.replaceAll('\\\\', '/'))\n nitro.hooks.hook('types:extend', async (types) => {\n await mkdir(directory, { recursive: true })\n await Promise.all([\n writeFile(\n pluginPath,\n `import config from ${JSON.stringify(configPath)}\nimport { configureFiles } from 'nuxt-files-sdk/runtime'\n\nexport default (nitroApp) => configureFiles(config, {\n development: ${JSON.stringify(options.development)},\n hooks: {\n onAction: (event, storage) => nitroApp.hooks.callHook('files:action', { event, storage }),\n onError: (event, storage) => nitroApp.hooks.callHook('files:error', { event, storage }),\n onRetry: (event, storage) => nitroApp.hooks.callHook('files:retry', { event, storage }),\n },\n})\n`,\n ),\n // Older v2 and current v3 omit meta; only v3 exposes the routing API.\n writeFile(typesPath, storageTypes(configPath, nitro.meta?.majorVersion ?? ('routing' in nitro ? 3 : 2))),\n ])\n types.tsConfig?.include?.push(typesPath)\n })\n}\n"],"mappings":";;;AAmBA,MAAM,aAAa,eAA0D;iBAC5D,KAAK,UAAU,UAAU,EAAE;;;;;;;;AAS5C,MAAa,gBACT,YACA,eACS,2BAA2B,KAAK,UAAU,UAAU,EAAE;;;;;;;EAOjE,UAAU,cAAc,IAAI,gBAAgB,iBAAiB,EAAE;;;AAIjE,MAAa,6BAA6B,OACtC,OACA,YACgB;CAChB,MAAM,aAAa,QAAQ,WAAW,WAAW,MAAM,GAAG;CAE1D,MAAM,YAAa,MAAM,QAAQ,cAAc,CAAC;CAC/C,CAAC,UAAU,WAAW,CAAC,EAAA,CAAG,KAAK,gBAAgB;CAEhD,IAAI,CAAC,MAAM,QAAQ,KAAK,UAAU,OAAO,KAAK,WAAW;CACzD,MAAM,YAAY,QAAQ,MAAM,QAAQ,UAAU,gBAAgB;CAClE,MAAM,aAAa,QAAQ,WAAW,YAAY;CAClD,MAAM,YAAY,QAAQ,WAAW,uBAAuB;CAE5D,UAAU,OAAO,KAAK,WAAW,WAAW,MAAM,GAAG,GAAG,UAAU;CAClE,MAAM,QAAQ,QAAQ,KAAK,WAAW,WAAW,MAAM,GAAG,CAAC;CAC3D,MAAM,MAAM,KAAK,gBAAgB,OAAO,UAAU;EAC9C,MAAM,MAAM,WAAW,EAAE,WAAW,KAAK,CAAC;EAC1C,MAAM,QAAQ,IAAI,CACd,UACI,YACA,sBAAsB,KAAK,UAAU,UAAU,EAAE;;;;iBAIhD,KAAK,UAAU,QAAQ,WAAW,EAAE;;;;;;;CAQzC,GAEA,UAAU,WAAW,aAAa,YAAY,MAAM,MAAM,iBAAiB,aAAa,QAAQ,IAAI,EAAE,CAAC,CAC3G,CAAC;EACD,MAAM,UAAU,SAAS,KAAK,SAAS;CAC3C,CAAC;AACL"}
1
+ {"version":3,"file":"nitro.js","names":[],"sources":["../../src/integration/nitro.ts"],"sourcesContent":["import { mkdir, writeFile } from 'node:fs/promises'\nimport { resolve } from 'node:path'\n\nimport type { ProviderSlug } from 'files-sdk'\nimport { getProvider } from 'files-sdk/providers'\nimport { createJiti } from 'jiti'\n\nimport type { FilesConfig, StorageConfig } from '../config'\n\nexport interface NitroIntegration {\n meta?: { majorVersion?: number }\n options: {\n rootDir: string\n buildDir: string\n dev?: boolean\n plugins: string[]\n alias?: Record<string, string>\n externals?: { inline?: unknown[] }\n }\n unimport?: {\n getInternalContext(): {\n addons: {\n name?: string\n declaration?: (declarations: string) => string\n }[]\n }\n }\n hooks: {\n hook(\n name: 'types:extend',\n callback: (types: { tsConfig?: { include?: string[] } }) => void | Promise<void>,\n ): void\n }\n}\n\nexport interface NitroFilesIntegrationOptions {\n configPath: string\n development: boolean\n}\n\nconst isStorageConfig = (value: unknown): value is StorageConfig =>\n Boolean(value && typeof value === 'object' && 'adapter' in value && typeof value.adapter === 'string')\nconst isStorageRecord = (value: unknown): value is Record<string, StorageConfig> =>\n Boolean(value && typeof value === 'object' && Object.values(value).every(isStorageConfig))\n\nexport const selectedAdapters = (\n config: FilesConfig,\n development: boolean,\n): { adapters: ProviderSlug[]; single: boolean } => {\n const storage = config.storage\n const devStorage = config.devStorage\n if (!storage || (!isStorageConfig(storage) && (!isStorageRecord(storage) || Object.keys(storage).length === 0))) {\n throw new Error('[nuxt-files-sdk:invalid-config] At least one storage is required.')\n }\n const selected: StorageConfig[] = []\n const single = isStorageConfig(storage)\n if (single) {\n if (devStorage && !isStorageConfig(devStorage)) {\n throw new Error('[nuxt-files-sdk:invalid-config] A single storage requires a single devStorage override.')\n }\n selected.push(development && isStorageConfig(devStorage) ? devStorage : storage)\n } else {\n if (devStorage && !isStorageRecord(devStorage)) {\n throw new Error('[nuxt-files-sdk:invalid-config] Named storage requires named devStorage overrides.')\n }\n for (const name of Object.keys(devStorage ?? {})) {\n if (!Object.hasOwn(storage, name)) {\n throw new Error(`[nuxt-files-sdk:unknown-storage] Unknown storage \"${name}\".`)\n }\n }\n for (const [name, namedStorage] of Object.entries(storage)) {\n selected.push(development ? (devStorage?.[name] ?? namedStorage) : namedStorage)\n }\n }\n const adapters = [...new Set(selected.map(({ adapter }) => adapter))].toSorted()\n for (const adapter of adapters) {\n if (!getProvider(adapter)) {\n throw new Error(`[nuxt-files-sdk:unknown-adapter] Unknown adapter \"${adapter}\".`)\n }\n }\n return { adapters, single }\n}\n\nconst factoryName = (adapter: ProviderSlug): string =>\n adapter === 'cloudinary'\n ? 'cloudinaryAdapter'\n : adapter.replaceAll(/-([a-z0-9])/gu, (_, character: string) => character.toUpperCase())\n\nexport const providerCode = (adapters: ProviderSlug[]): { imports: string; factories: string } => ({\n imports: adapters\n .map(\n (adapter, index) =>\n `import { ${factoryName(adapter)} as provider${index} } from ${JSON.stringify(`files-sdk/${adapter}`)}`,\n )\n .join('\\n'),\n factories: adapters.map((adapter, index) => `${JSON.stringify(adapter)}: provider${index}`).join(', '),\n})\n\nconst hookTypes = (moduleName: 'nitropack/types' | 'nitro/types'): string => `\ndeclare module ${JSON.stringify(moduleName)} {\n interface NitroRuntimeHooks {\n 'files:action': (payload: { event: import('files-sdk').FilesActionEvent; storage?: string }) => void | Promise<void>\n 'files:error': (payload: { event: import('files-sdk').FilesErrorEvent; storage?: string }) => void | Promise<void>\n 'files:retry': (payload: { event: import('files-sdk').FilesRetryEvent; storage?: string }) => void | Promise<void>\n }\n}\n`\n\nexport const storageTypes = (\n configPath: string,\n nitroMajor: number,\n single: boolean,\n): string => `import type config from ${JSON.stringify(configPath)}\nimport type { SingleStorage, StorageRegistry } from 'nuxt-files-sdk/runtime'\n\ndeclare module 'nuxt-files-sdk/runtime' {\n ${single ? 'interface NuxtFilesSingleStorage { value: SingleStorage<typeof config> }' : 'interface NuxtFilesStorageRegistry extends StorageRegistry<typeof config> {}'}\n}\n${hookTypes(nitroMajor >= 3 ? 'nitro/types' : 'nitropack/types')}\nexport {}\n`\n\nexport const setupNitroFilesIntegration = async (\n nitro: NitroIntegration,\n options: NitroFilesIntegrationOptions,\n): Promise<void> => {\n const configPath = options.configPath.replaceAll('\\\\', '/')\n const config = await createJiti(import.meta.url, {\n ...(nitro.options.alias ? { alias: nitro.options.alias } : {}),\n interopDefault: true,\n moduleCache: false,\n }).import<FilesConfig>(configPath, { default: true })\n const { adapters, single } = selectedAdapters(config, options.development)\n const providers = providerCode(adapters)\n nitro.unimport?.getInternalContext().addons.push({\n name: 'nuxt-files-sdk-jsdoc',\n declaration: (declarations) =>\n declarations.replace(\n /^(\\s*)(const useServerFiles: typeof .*\\.useServerFiles)$/mu,\n \"$1/** Return the project's Files client, including its configured plugin extensions. */\\n$1const useServerFiles: typeof import('nuxt-files-sdk/runtime').useServerFiles\",\n ),\n })\n // Inline both packages so installed consumers also tree-shake the plugin barrel.\n const externals = (nitro.options.externals ??= {})\n ;(externals.inline ??= []).push('nuxt-files-sdk')\n // Nitro's single-file dev build would eagerly import every native provider SDK.\n if (!nitro.options.dev) externals.inline.push('files-sdk')\n const directory = resolve(nitro.options.buildDir, 'nuxt-files-sdk')\n const pluginPath = resolve(directory, 'plugin.mjs')\n const typesPath = resolve(directory, 'storage-registry.d.ts')\n // Development also externalizes local .mjs files unless explicitly inlined.\n externals.inline.push(pluginPath.replaceAll('\\\\', '/'), configPath)\n nitro.options.plugins.push(pluginPath.replaceAll('\\\\', '/'))\n nitro.hooks.hook('types:extend', async (types) => {\n await mkdir(directory, { recursive: true })\n await Promise.all([\n writeFile(\n pluginPath,\n `import config from ${JSON.stringify(configPath)}\n${providers.imports}\nimport { configureFiles } from 'nuxt-files-sdk/runtime'\n\nexport default (nitroApp) => configureFiles(config, {\n development: ${JSON.stringify(options.development)},\n factories: { ${providers.factories} },\n hooks: {\n onAction: (event, storage) => nitroApp.hooks.callHook('files:action', { event, storage }),\n onError: (event, storage) => nitroApp.hooks.callHook('files:error', { event, storage }),\n onRetry: (event, storage) => nitroApp.hooks.callHook('files:retry', { event, storage }),\n },\n})\n`,\n ),\n // Older v2 and current v3 omit meta; only v3 exposes the routing API.\n writeFile(\n typesPath,\n storageTypes(configPath, nitro.meta?.majorVersion ?? ('routing' in nitro ? 3 : 2), single),\n ),\n ])\n types.tsConfig?.include?.push(typesPath)\n })\n}\n"],"mappings":"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"}
package/dist/module.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { NitroIntegration } from "./integration/nitro.js";
2
- import { DefaultStorage, DefaultStorageName, FilesForStorage, FilesRegistry, FilesRuntimeHooks, StorageRegistry } from "./runtime/registry.js";
3
- import { NuxtFilesDefaultStorage, NuxtFilesStorageRegistry, configureFiles, inspectFiles, useServerFiles } from "./runtime.js";
2
+ import { FilesForStorage, FilesProviderFactories, FilesProviderFactory, FilesRegistry, FilesRuntimeHooks, SingleStorage, StorageRegistry } from "./runtime/registry.js";
3
+ import { NuxtFilesSingleStorage, NuxtFilesStorageRegistry, configureFiles, inspectFiles, useServerFiles } from "./runtime.js";
4
4
  export * from "files-sdk";
5
5
  //#region src/module.d.ts
6
6
  declare module '@nuxt/schema' {
@@ -8,13 +8,15 @@ declare module '@nuxt/schema' {
8
8
  'nitro:init': (nitro: NitroIntegration) => void | Promise<void>;
9
9
  }
10
10
  }
11
+ /** Options for the Nuxt Files SDK module. */
11
12
  export interface ModuleOptions {
12
- /** Files configuration path, relative to the Nuxt root. */
13
+ /** Path to the Files configuration module, relative to the Nuxt root directory. */
13
14
  config: string;
14
- /** Enable development diagnostics integrations. */
15
+ /** Enable Files SDK development diagnostics when Nuxt DevTools is available. */
15
16
  devtools: boolean;
16
17
  }
18
+ /** Install Files SDK storage configuration, server utilities, Vue composables, and development diagnostics in Nuxt. */
17
19
  declare const _default: import("@nuxt/schema").NuxtModule<ModuleOptions, ModuleOptions, false>;
18
20
  //#endregion
19
- export { type DefaultStorage, type DefaultStorageName, type FilesForStorage, FilesRegistry, type FilesRuntimeHooks, NuxtFilesDefaultStorage, NuxtFilesStorageRegistry, type StorageRegistry, configureFiles, _default as default, inspectFiles, useServerFiles };
21
+ export { type FilesForStorage, type FilesProviderFactories, type FilesProviderFactory, FilesRegistry, type FilesRuntimeHooks, NuxtFilesSingleStorage, NuxtFilesStorageRegistry, type SingleStorage, type StorageRegistry, configureFiles, _default as default, inspectFiles, useServerFiles };
20
22
  //# sourceMappingURL=module.d.ts.map
package/dist/module.js CHANGED
@@ -6,6 +6,7 @@ import { resolve } from "node:path";
6
6
  import { addImports, addServerImports, defineNuxtModule, getNuxtModuleVersion } from "@nuxt/kit";
7
7
  export * from "files-sdk";
8
8
  //#region src/module.ts
9
+ /** Install Files SDK storage configuration, server utilities, Vue composables, and development diagnostics in Nuxt. */
9
10
  var module_default = defineNuxtModule({
10
11
  meta: {
11
12
  name: "nuxt-files-sdk",
@@ -1 +1 @@
1
- {"version":3,"file":"module.js","names":[],"sources":["../src/module.ts"],"sourcesContent":["import { resolve } from 'node:path'\n\nimport { addImports, addServerImports, defineNuxtModule, getNuxtModuleVersion } from '@nuxt/kit'\nimport type { Nuxt } from '@nuxt/schema'\n\nimport { shouldEnableFilesDevtools } from './devtools/enabled'\nimport { setupNitroFilesIntegration, type NitroIntegration } from './integration/nitro'\n\ndeclare module '@nuxt/schema' {\n interface NuxtHooks {\n 'nitro:init': (nitro: NitroIntegration) => void | Promise<void>\n }\n}\n\nexport interface ModuleOptions {\n /** Files configuration path, relative to the Nuxt root. */\n config: string\n /** Enable development diagnostics integrations. */\n devtools: boolean\n}\n\nexport default defineNuxtModule<ModuleOptions>({\n meta: {\n name: 'nuxt-files-sdk',\n configKey: 'files',\n compatibility: { nuxt: '^4.0.0 || ^5.0.0' },\n },\n defaults: {\n config: 'files.config.ts',\n devtools: true,\n },\n async setup(options, nuxt: Nuxt) {\n const configPath = resolve(nuxt.options.rootDir, options.config)\n nuxt.hook('nitro:init', (nitro) =>\n setupNitroFilesIntegration(nitro, {\n configPath,\n development: nuxt.options.dev,\n }),\n )\n nuxt.hook('prepare:types', ({ references }) => {\n references.push({ path: resolve(nuxt.options.buildDir, 'nuxt-files-sdk/storage-registry.d.ts') })\n })\n\n addServerImports({ name: 'useServerFiles', from: 'nuxt-files-sdk/runtime' })\n for (const name of ['useFiles', 'useFile', 'useList', 'useSearch']) {\n addImports({ name, from: 'files-sdk/vue' })\n }\n\n if (shouldEnableFilesDevtools(nuxt.options.dev, options.devtools, nuxt.options.devtools)) {\n const version = await getNuxtModuleVersion('@nuxt/devtools', nuxt)\n const { setupFilesDevtools } = await import('./devtools')\n setupFilesDevtools(nuxt, version || '3')\n }\n },\n})\n\nexport * from 'files-sdk'\nexport * from './runtime'\n"],"mappings":";;;;;;;;AAqBA,IAAA,iBAAe,iBAAgC;CAC3C,MAAM;EACF,MAAM;EACN,WAAW;EACX,eAAe,EAAE,MAAM,mBAAmB;CAC9C;CACA,UAAU;EACN,QAAQ;EACR,UAAU;CACd;CACA,MAAM,MAAM,SAAS,MAAY;EAC7B,MAAM,aAAa,QAAQ,KAAK,QAAQ,SAAS,QAAQ,MAAM;EAC/D,KAAK,KAAK,eAAe,UACrB,2BAA2B,OAAO;GAC9B;GACA,aAAa,KAAK,QAAQ;EAC9B,CAAC,CACL;EACA,KAAK,KAAK,kBAAkB,EAAE,iBAAiB;GAC3C,WAAW,KAAK,EAAE,MAAM,QAAQ,KAAK,QAAQ,UAAU,sCAAsC,EAAE,CAAC;EACpG,CAAC;EAED,iBAAiB;GAAE,MAAM;GAAkB,MAAM;EAAyB,CAAC;EAC3E,KAAK,MAAM,QAAQ;GAAC;GAAY;GAAW;GAAW;EAAW,GAC7D,WAAW;GAAE;GAAM,MAAM;EAAgB,CAAC;EAG9C,IAAI,0BAA0B,KAAK,QAAQ,KAAK,QAAQ,UAAU,KAAK,QAAQ,QAAQ,GAAG;GACtF,MAAM,UAAU,MAAM,qBAAqB,kBAAkB,IAAI;GACjE,MAAM,EAAE,uBAAuB,MAAM,OAAO;GAC5C,mBAAmB,MAAM,WAAW,GAAG;EAC3C;CACJ;AACJ,CAAC"}
1
+ {"version":3,"file":"module.js","names":[],"sources":["../src/module.ts"],"sourcesContent":["import { resolve } from 'node:path'\n\nimport { addImports, addServerImports, defineNuxtModule, getNuxtModuleVersion } from '@nuxt/kit'\nimport type { Nuxt } from '@nuxt/schema'\n\nimport { shouldEnableFilesDevtools } from './devtools/enabled'\nimport { setupNitroFilesIntegration, type NitroIntegration } from './integration/nitro'\n\ndeclare module '@nuxt/schema' {\n interface NuxtHooks {\n 'nitro:init': (nitro: NitroIntegration) => void | Promise<void>\n }\n}\n\n/** Options for the Nuxt Files SDK module. */\nexport interface ModuleOptions {\n /** Path to the Files configuration module, relative to the Nuxt root directory. */\n config: string\n /** Enable Files SDK development diagnostics when Nuxt DevTools is available. */\n devtools: boolean\n}\n\n/** Install Files SDK storage configuration, server utilities, Vue composables, and development diagnostics in Nuxt. */\nexport default defineNuxtModule<ModuleOptions>({\n meta: {\n name: 'nuxt-files-sdk',\n configKey: 'files',\n compatibility: { nuxt: '^4.0.0 || ^5.0.0' },\n },\n defaults: {\n config: 'files.config.ts',\n devtools: true,\n },\n async setup(options, nuxt: Nuxt) {\n const configPath = resolve(nuxt.options.rootDir, options.config)\n nuxt.hook('nitro:init', (nitro) =>\n setupNitroFilesIntegration(nitro, {\n configPath,\n development: nuxt.options.dev,\n }),\n )\n nuxt.hook('prepare:types', ({ references }) => {\n references.push({ path: resolve(nuxt.options.buildDir, 'nuxt-files-sdk/storage-registry.d.ts') })\n })\n\n addServerImports({ name: 'useServerFiles', from: 'nuxt-files-sdk/runtime' })\n for (const name of ['useFiles', 'useFile', 'useList', 'useSearch']) {\n addImports({ name, from: 'files-sdk/vue' })\n }\n\n if (shouldEnableFilesDevtools(nuxt.options.dev, options.devtools, nuxt.options.devtools)) {\n const version = await getNuxtModuleVersion('@nuxt/devtools', nuxt)\n const { setupFilesDevtools } = await import('./devtools')\n setupFilesDevtools(nuxt, version || '3')\n }\n },\n})\n\nexport * from 'files-sdk'\nexport * from './runtime'\n"],"mappings":";;;;;;;;;AAuBA,IAAA,iBAAe,iBAAgC;CAC3C,MAAM;EACF,MAAM;EACN,WAAW;EACX,eAAe,EAAE,MAAM,mBAAmB;CAC9C;CACA,UAAU;EACN,QAAQ;EACR,UAAU;CACd;CACA,MAAM,MAAM,SAAS,MAAY;EAC7B,MAAM,aAAa,QAAQ,KAAK,QAAQ,SAAS,QAAQ,MAAM;EAC/D,KAAK,KAAK,eAAe,UACrB,2BAA2B,OAAO;GAC9B;GACA,aAAa,KAAK,QAAQ;EAC9B,CAAC,CACL;EACA,KAAK,KAAK,kBAAkB,EAAE,iBAAiB;GAC3C,WAAW,KAAK,EAAE,MAAM,QAAQ,KAAK,QAAQ,UAAU,sCAAsC,EAAE,CAAC;EACpG,CAAC;EAED,iBAAiB;GAAE,MAAM;GAAkB,MAAM;EAAyB,CAAC;EAC3E,KAAK,MAAM,QAAQ;GAAC;GAAY;GAAW;GAAW;EAAW,GAC7D,WAAW;GAAE;GAAM,MAAM;EAAgB,CAAC;EAG9C,IAAI,0BAA0B,KAAK,QAAQ,KAAK,QAAQ,UAAU,KAAK,QAAQ,QAAQ,GAAG;GACtF,MAAM,UAAU,MAAM,qBAAqB,kBAAkB,IAAI;GACjE,MAAM,EAAE,uBAAuB,MAAM,OAAO;GAC5C,mBAAmB,MAAM,WAAW,GAAG;EAC3C;CACJ;AACJ,CAAC"}
package/dist/nitro.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { NitroIntegration } from "./integration/nitro.js";
2
- import { DefaultStorage, DefaultStorageName, FilesForStorage, FilesRegistry, FilesRuntimeHooks, StorageRegistry } from "./runtime/registry.js";
3
- import { NuxtFilesDefaultStorage, NuxtFilesStorageRegistry, configureFiles, inspectFiles, useServerFiles } from "./runtime.js";
2
+ import { FilesForStorage, FilesProviderFactories, FilesProviderFactory, FilesRegistry, FilesRuntimeHooks, SingleStorage, StorageRegistry } from "./runtime/registry.js";
3
+ import { NuxtFilesSingleStorage, NuxtFilesStorageRegistry, configureFiles, inspectFiles, useServerFiles } from "./runtime.js";
4
4
  //#region src/nitro.d.ts
5
5
  /**
6
6
  * A structurally compatible Nitro v2/v3 module. Nitro loads this export
@@ -11,5 +11,5 @@ declare const _default: {
11
11
  setup: (nitro: NitroIntegration) => Promise<void>;
12
12
  };
13
13
  //#endregion
14
- export { type DefaultStorage, type DefaultStorageName, type FilesForStorage, FilesRegistry, type FilesRuntimeHooks, NuxtFilesDefaultStorage, NuxtFilesStorageRegistry, type StorageRegistry, configureFiles, _default as default, inspectFiles, useServerFiles };
14
+ export { type FilesForStorage, type FilesProviderFactories, type FilesProviderFactory, FilesRegistry, type FilesRuntimeHooks, NuxtFilesSingleStorage, NuxtFilesStorageRegistry, type SingleStorage, type StorageRegistry, configureFiles, _default as default, inspectFiles, useServerFiles };
15
15
  //# sourceMappingURL=nitro.d.ts.map
package/dist/package.js CHANGED
@@ -1,5 +1,5 @@
1
1
  //#region package.json
2
- var version = "0.0.1";
2
+ var version = "0.0.3";
3
3
  //#endregion
4
4
  export { version };
5
5
 
@@ -0,0 +1,3 @@
1
+ import { versioning } from "files-sdk/versioning";
2
+ export type * from "files-sdk/versioning";
3
+ export { versioning };
@@ -0,0 +1,2 @@
1
+ import { versioning } from "files-sdk/versioning";
2
+ export { versioning };
@@ -1,26 +1,40 @@
1
- import { FilesConfig, StorageConfig } from "../config.js";
1
+ import { FilesConfig, NamedFilesConfig, SingleFilesConfig, StorageConfig } from "../config.js";
2
2
  import { FilesDevtoolsSnapshot } from "../devtools/snapshot.js";
3
- import { ExtensionsOf, Files, FilesActionEvent, FilesErrorEvent, FilesRetryEvent, ProviderSlug } from "files-sdk";
3
+ import { Adapter, ExtensionsOf, Files, FilesActionEvent, FilesErrorEvent, FilesRetryEvent, ProviderSlug } from "files-sdk";
4
4
  //#region src/runtime/registry.d.ts
5
+ /** Native Files client plus the methods contributed by a storage's plugins. */
5
6
  export type FilesForStorage<T extends StorageConfig> = Files & ExtensionsOf<NonNullable<T['plugins']>>;
6
- export type StorageRegistry<C extends FilesConfig> = { [Name in keyof C['storage']]: FilesForStorage<C['storage'][Name]>; };
7
- type IsUnion<T, C = T> = T extends C ? ([C] extends [T] ? false : true) : never;
8
- export type DefaultStorageName<C extends FilesConfig> = C extends {
9
- default: infer Name extends Extract<keyof C['storage'], string>;
10
- } ? Name : 'default' extends keyof C['storage'] ? 'default' : IsUnion<Extract<keyof C['storage'], string>> extends false ? Extract<keyof C['storage'], string> : never;
11
- export type DefaultStorage<C extends FilesConfig> = StorageRegistry<C>[DefaultStorageName<C>];
7
+ /** Map each configured storage name to its native Files client and plugin extensions. */
8
+ export type StorageRegistry<C extends FilesConfig> = C extends NamedFilesConfig<infer Storages> ? { [Name in keyof Storages]: FilesForStorage<Storages[Name]>; } : Record<never, never>;
9
+ /** Files client returned by an unnamed single-storage configuration. */
10
+ export type SingleStorage<C extends FilesConfig> = C extends SingleFilesConfig<infer Storage> ? FilesForStorage<Storage> : never;
11
+ /** Hooks emitted by the Nuxt/Nitro bridge after the storage's native hooks. */
12
12
  export interface FilesRuntimeHooks {
13
- onError?: (event: FilesErrorEvent, storage: string) => void | Promise<void>;
14
- onAction?: (event: FilesActionEvent, storage: string) => void | Promise<void>;
15
- onRetry?: (event: FilesRetryEvent, storage: string) => void | Promise<void>;
13
+ /** Observe a failed native Files operation. */
14
+ onError?: (event: FilesErrorEvent, storage?: string) => void | Promise<void>;
15
+ /** Observe a completed native Files operation. */
16
+ onAction?: (event: FilesActionEvent, storage?: string) => void | Promise<void>;
17
+ /** Observe a native Files retry. */
18
+ onRetry?: (event: FilesRetryEvent, storage?: string) => void | Promise<void>;
16
19
  }
20
+ /** One provider factory statically supplied by the generated Nitro plugin. */
21
+ export type FilesProviderFactory = (config: never) => Adapter;
22
+ /** Provider factories available in the current build. */
23
+ export type FilesProviderFactories = Partial<Record<ProviderSlug, FilesProviderFactory>>;
24
+ /** Lazily construct and memoize native Files clients for a validated project configuration. */
17
25
  export declare class FilesRegistry<const C extends FilesConfig = FilesConfig> {
18
26
  #private;
19
- constructor(config: C, options?: {
27
+ /** Create a registry without constructing a provider. */
28
+ constructor(config: C, options: {
20
29
  development?: boolean;
30
+ factories: FilesProviderFactories;
21
31
  hooks?: FilesRuntimeHooks;
22
32
  });
23
- get<Name extends keyof C['storage'] & string>(name?: Name): Promise<StorageRegistry<C>[Name]>;
33
+ /** Return the client from an unnamed single-storage configuration. */
34
+ get(...args: C extends SingleFilesConfig ? [] : [name: never]): SingleStorage<C>;
35
+ /** Return one named storage client. */
36
+ get<Name extends Extract<keyof StorageRegistry<C>, string>>(name: Name): StorageRegistry<C>[Name];
37
+ /** Return secret-free storage metadata and initialization state for development diagnostics. */
24
38
  inspect(): FilesDevtoolsSnapshot;
25
39
  }
26
40
  //#endregion
@@ -1,96 +1,115 @@
1
- import { createFiles } from "files-sdk";
2
- import { loadFiles } from "files-sdk/loader";
3
1
  import { getProvider, listEnvVars } from "files-sdk/providers";
2
+ import { createFiles } from "files-sdk";
4
3
  //#region src/runtime/registry.ts
5
4
  const runHooks = async (...hooks) => {
6
5
  for (const hook of hooks) try {
7
6
  await hook();
8
7
  } catch {}
9
8
  };
9
+ const isStorageConfig = (value) => Boolean(value && typeof value === "object" && "adapter" in value && typeof value.adapter === "string");
10
+ const isStorageRecord = (value) => Boolean(value && typeof value === "object" && Object.values(value).every(isStorageConfig));
11
+ /** Lazily construct and memoize native Files clients for a validated project configuration. */
10
12
  var FilesRegistry = class {
11
13
  #config;
12
14
  #development;
15
+ #factories;
13
16
  #hooks;
14
17
  #instances = /* @__PURE__ */ new Map();
15
- constructor(config, options = {}) {
16
- if (!config.storage || Object.keys(config.storage).length === 0) throw new Error("[nuxt-files-sdk:invalid-config] At least one storage is required.");
18
+ #initializing = /* @__PURE__ */ new Set();
19
+ /** Create a registry without constructing a provider. */
20
+ constructor(config, options) {
21
+ if ("default" in config) throw new Error("[nuxt-files-sdk:invalid-config] The default option has been removed.");
22
+ if (!config.storage || !isStorageConfig(config.storage) && (!isStorageRecord(config.storage) || Object.keys(config.storage).length === 0)) throw new Error("[nuxt-files-sdk:invalid-config] At least one storage is required.");
23
+ if (!isStorageConfig(config.storage)) {
24
+ if (config.devStorage && !isStorageRecord(config.devStorage)) throw new Error("[nuxt-files-sdk:invalid-config] Named storage requires named devStorage overrides.");
25
+ for (const name of Object.keys(config.devStorage ?? {})) if (!Object.hasOwn(config.storage, name)) throw new Error(`[nuxt-files-sdk:unknown-storage] Unknown storage "${name}".`);
26
+ }
17
27
  this.#config = config;
18
28
  this.#development = options.development ?? false;
29
+ this.#factories = options.factories;
19
30
  this.#hooks = options.hooks ?? {};
20
31
  }
21
32
  get(name) {
22
- const resolvedName = name ?? this.#defaultName();
23
- if (!Object.hasOwn(this.#config.storage, resolvedName)) throw new Error(`[nuxt-files-sdk:unknown-storage] Unknown storage "${resolvedName}".`);
24
- let instance = this.#instances.get(resolvedName);
25
- if (!instance) {
26
- instance = this.#create(resolvedName);
27
- this.#instances.set(resolvedName, instance);
28
- instance.catch(() => this.#instances.delete(resolvedName));
33
+ const entry = this.#entry(name);
34
+ const key = entry.name ?? "";
35
+ const cached = this.#instances.get(key);
36
+ if (cached) return cached;
37
+ if (this.#initializing.has(key)) throw new Error("[nuxt-files-sdk:circular-initialization] Storage configuration cannot access itself.");
38
+ this.#initializing.add(key);
39
+ try {
40
+ const files = this.#create(entry);
41
+ this.#instances.set(key, files);
42
+ return files;
43
+ } finally {
44
+ this.#initializing.delete(key);
29
45
  }
30
- return instance;
31
46
  }
47
+ /** Return secret-free storage metadata and initialization state for development diagnostics. */
32
48
  inspect() {
33
49
  return {
34
- storages: Object.entries(this.#config.storage).map(([name, storage]) => {
35
- const override = this.#development ? this.#config.devStorage?.[name] : void 0;
36
- return {
37
- name,
38
- adapter: override?.adapter ?? storage.adapter,
39
- plugins: storage.plugins?.map((plugin) => plugin.name) ?? [],
40
- source: override ? "devStorage" : "storage",
41
- initialized: this.#instances.has(name)
42
- };
43
- }),
50
+ storages: this.#entries().map(({ name, storage, override }) => ({
51
+ ...name === void 0 ? {} : { name },
52
+ adapter: override?.adapter ?? storage.adapter,
53
+ plugins: storage.plugins?.map((plugin) => plugin.name) ?? [],
54
+ source: override ? "devStorage" : "storage",
55
+ initialized: this.#instances.has(name ?? "")
56
+ })),
44
57
  diagnostics: []
45
58
  };
46
59
  }
47
- #defaultName() {
48
- if (this.#config.default) return this.#config.default;
49
- const names = Object.keys(this.#config.storage);
50
- if (names.length === 1 && names[0]) return names[0];
51
- if (Object.hasOwn(this.#config.storage, "default")) return "default";
52
- throw new Error("[nuxt-files-sdk:storage-name-required] A storage name is required.");
53
- }
54
- async #create(name) {
55
- const base = this.#config.storage[name];
56
- const override = this.#development ? this.#config.devStorage?.[name] : void 0;
57
- const selected = override ? {
58
- ...base,
59
- ...override,
60
- plugins: base?.plugins,
61
- hooks: base?.hooks
62
- } : base;
63
- if (!selected) throw new Error(`[nuxt-files-sdk:unknown-storage] Unknown storage "${name}".`);
64
- const { adapter, plugins, hooks: userHooks, ...options } = selected;
65
- const loaded = await withNuxtEnvironment(adapter, () => loadFiles({
66
- ...options,
67
- provider: adapter
60
+ #entries() {
61
+ const storage = this.#config.storage;
62
+ const devStorage = this.#config.devStorage;
63
+ if (isStorageConfig(storage)) return [{
64
+ name: void 0,
65
+ storage,
66
+ override: this.#development && isStorageConfig(devStorage) ? devStorage : void 0
67
+ }];
68
+ const overrides = this.#development && isStorageRecord(devStorage) ? devStorage : void 0;
69
+ return Object.entries(storage).map(([name, namedStorage]) => ({
70
+ name,
71
+ storage: namedStorage,
72
+ override: overrides?.[name]
68
73
  }));
69
- if (!plugins && !userHooks && !Object.values(this.#hooks).some(Boolean)) return loaded.files;
74
+ }
75
+ #entry(name) {
76
+ if (isStorageConfig(this.#config.storage)) {
77
+ if (name !== void 0) throw new Error(`[nuxt-files-sdk:unknown-storage] Unknown storage "${name}".`);
78
+ return this.#entries()[0];
79
+ }
80
+ if (name === void 0) throw new Error("[nuxt-files-sdk:storage-name-required] A storage name is required.");
81
+ const entry = this.#entries().find((candidate) => candidate.name === name);
82
+ if (!entry) throw new Error(`[nuxt-files-sdk:unknown-storage] Unknown storage "${name}".`);
83
+ return entry;
84
+ }
85
+ #create({ name, storage, override }) {
86
+ const selected = override ?? storage;
87
+ const factory = this.#factories[selected.adapter];
88
+ if (!factory) throw new Error(`[nuxt-files-sdk:adapter-not-generated] Adapter "${selected.adapter}" is not available in this build.`);
89
+ const adapter = withNuxtEnvironment(selected.adapter, () => {
90
+ const input = typeof selected.config === "function" ? selected.config() : selected.config;
91
+ if (input && typeof input === "object" && "then" in input) throw new Error("[nuxt-files-sdk:async-config] Storage config functions must be synchronous.");
92
+ return factory(input);
93
+ });
70
94
  return createFiles({
71
- adapter: loaded.files.adapter,
95
+ adapter,
72
96
  hooks: {
73
- onAction: (event) => runHooks(() => userHooks?.onAction?.(event), () => this.#hooks.onAction?.(event, name)),
74
- onError: (event) => runHooks(() => userHooks?.onError?.(event), () => this.#hooks.onError?.(event, name)),
75
- onRetry: (event) => runHooks(() => userHooks?.onRetry?.(event), () => this.#hooks.onRetry?.(event, name))
97
+ onAction: (event) => runHooks(() => storage.hooks?.onAction?.(event), () => this.#hooks.onAction?.(event, name)),
98
+ onError: (event) => runHooks(() => storage.hooks?.onError?.(event), () => this.#hooks.onError?.(event, name)),
99
+ onRetry: (event) => runHooks(() => storage.hooks?.onRetry?.(event), () => this.#hooks.onRetry?.(event, name))
76
100
  },
77
- ...plugins ? { plugins } : {},
78
- ...options.prefix === void 0 ? {} : { prefix: options.prefix },
79
- ...options.retries === void 0 ? {} : { retries: options.retries },
80
- ...options.timeout === void 0 ? {} : { timeout: options.timeout }
101
+ ...storage.plugins ? { plugins: storage.plugins } : {},
102
+ ...storage.prefix === void 0 ? {} : { prefix: storage.prefix },
103
+ ...storage.retries === void 0 ? {} : { retries: storage.retries },
104
+ ...storage.timeout === void 0 ? {} : { timeout: storage.timeout }
81
105
  });
82
106
  }
83
107
  };
84
- let environmentLock = Promise.resolve();
85
- /** Bridge only NUXT_ aliases declared by the configured native provider. */
86
- const withNuxtEnvironment = async (provider, load) => {
108
+ /** Bridge only NUXT_ aliases declared by the configured native provider during synchronous construction. */
109
+ const withNuxtEnvironment = (provider, load) => {
87
110
  if (!getProvider(provider)) return load();
88
111
  const variables = listEnvVars(provider);
89
112
  if (variables.length === 0) return load();
90
- const previous = environmentLock;
91
- let release;
92
- environmentLock = new Promise((resolveLock) => release = resolveLock);
93
- await previous;
94
113
  const injected = [];
95
114
  for (const variable of variables) {
96
115
  const keys = [variable.key, ...variable.aliases ?? []];
@@ -104,10 +123,9 @@ const withNuxtEnvironment = async (provider, load) => {
104
123
  }
105
124
  }
106
125
  try {
107
- return await load();
126
+ return load();
108
127
  } finally {
109
128
  for (const key of injected) delete process.env[key];
110
- release();
111
129
  }
112
130
  };
113
131
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"registry.js","names":[],"sources":["../../src/runtime/registry.ts"],"sourcesContent":["import {\n createFiles,\n type ExtensionsOf,\n type Files,\n type FilesActionEvent,\n type FilesErrorEvent,\n type FilesRetryEvent,\n type ProviderSlug,\n} from 'files-sdk'\nimport { loadFiles } from 'files-sdk/loader'\nimport { getProvider, listEnvVars } from 'files-sdk/providers'\n\nimport type { FilesConfig, StorageConfig } from '../config'\nimport type { FilesDevtoolsSnapshot } from '../devtools/snapshot'\n\nexport type FilesForStorage<T extends StorageConfig> = Files & ExtensionsOf<NonNullable<T['plugins']>>\n\nexport type StorageRegistry<C extends FilesConfig> = {\n [Name in keyof C['storage']]: FilesForStorage<C['storage'][Name]>\n}\n\ntype IsUnion<T, C = T> = T extends C ? ([C] extends [T] ? false : true) : never\n\nexport type DefaultStorageName<C extends FilesConfig> = C extends {\n default: infer Name extends Extract<keyof C['storage'], string>\n}\n ? Name\n : 'default' extends keyof C['storage']\n ? 'default'\n : IsUnion<Extract<keyof C['storage'], string>> extends false\n ? Extract<keyof C['storage'], string>\n : never\n\nexport type DefaultStorage<C extends FilesConfig> = StorageRegistry<C>[DefaultStorageName<C>]\n\nexport interface FilesRuntimeHooks {\n onError?: (event: FilesErrorEvent, storage: string) => void | Promise<void>\n onAction?: (event: FilesActionEvent, storage: string) => void | Promise<void>\n onRetry?: (event: FilesRetryEvent, storage: string) => void | Promise<void>\n}\n\nconst runHooks = async (...hooks: (() => void | Promise<void> | undefined)[]): Promise<void> => {\n for (const hook of hooks) {\n try {\n // Preserve user-before-bridge ordering without exposing hook failures to native operations.\n // oxlint-disable-next-line no-await-in-loop\n await hook()\n } catch {}\n }\n}\n\nexport class FilesRegistry<const C extends FilesConfig = FilesConfig> {\n readonly #config: C\n readonly #development: boolean\n readonly #hooks: FilesRuntimeHooks\n readonly #instances = new Map<string, Promise<Files>>()\n\n constructor(config: C, options: { development?: boolean; hooks?: FilesRuntimeHooks } = {}) {\n if (!config.storage || Object.keys(config.storage).length === 0) {\n throw new Error('[nuxt-files-sdk:invalid-config] At least one storage is required.')\n }\n this.#config = config\n this.#development = options.development ?? false\n this.#hooks = options.hooks ?? {}\n }\n\n get<Name extends keyof C['storage'] & string>(name?: Name): Promise<StorageRegistry<C>[Name]> {\n const resolvedName = name ?? this.#defaultName()\n if (!Object.hasOwn(this.#config.storage, resolvedName)) {\n throw new Error(`[nuxt-files-sdk:unknown-storage] Unknown storage \"${resolvedName}\".`)\n }\n let instance = this.#instances.get(resolvedName)\n if (!instance) {\n instance = this.#create(resolvedName)\n this.#instances.set(resolvedName, instance)\n void instance.catch(() => this.#instances.delete(resolvedName))\n }\n // The instance is created from the same named config; the loader cannot express that link.\n // oxlint-disable-next-line typescript/no-unsafe-type-assertion\n return instance as Promise<StorageRegistry<C>[Name]>\n }\n\n inspect(): FilesDevtoolsSnapshot {\n return {\n storages: Object.entries(this.#config.storage).map(([name, storage]) => {\n const override = this.#development ? this.#config.devStorage?.[name] : undefined\n return {\n name,\n adapter: override?.adapter ?? storage.adapter,\n plugins: storage.plugins?.map((plugin) => plugin.name) ?? [],\n source: override ? 'devStorage' : 'storage',\n initialized: this.#instances.has(name),\n }\n }),\n diagnostics: [],\n }\n }\n\n #defaultName(): string {\n if (this.#config.default) return this.#config.default\n const names = Object.keys(this.#config.storage)\n if (names.length === 1 && names[0]) return names[0]\n if (Object.hasOwn(this.#config.storage, 'default')) return 'default'\n throw new Error('[nuxt-files-sdk:storage-name-required] A storage name is required.')\n }\n\n async #create(name: string): Promise<Files> {\n const base = this.#config.storage[name]\n const override = this.#development ? this.#config.devStorage?.[name] : undefined\n const selected = override ? { ...base, ...override, plugins: base?.plugins, hooks: base?.hooks } : base\n if (!selected) throw new Error(`[nuxt-files-sdk:unknown-storage] Unknown storage \"${name}\".`)\n const { adapter, plugins, hooks: userHooks, ...options } = selected\n const loaded = await withNuxtEnvironment(adapter, () => loadFiles({ ...options, provider: adapter }))\n // The upstream loader has no hooks/plugins input. Avoid rebuilding the\n // native instance unless those native capabilities are actually used.\n if (!plugins && !userHooks && !Object.values(this.#hooks).some(Boolean)) return loaded.files\n return createFiles({\n adapter: loaded.files.adapter,\n hooks: {\n onAction: (event) =>\n runHooks(\n () => userHooks?.onAction?.(event),\n () => this.#hooks.onAction?.(event, name),\n ),\n onError: (event) =>\n runHooks(\n () => userHooks?.onError?.(event),\n () => this.#hooks.onError?.(event, name),\n ),\n onRetry: (event) =>\n runHooks(\n () => userHooks?.onRetry?.(event),\n () => this.#hooks.onRetry?.(event, name),\n ),\n },\n ...(plugins ? { plugins } : {}),\n ...(options.prefix === undefined ? {} : { prefix: options.prefix }),\n ...(options.retries === undefined ? {} : { retries: options.retries }),\n ...(options.timeout === undefined ? {} : { timeout: options.timeout }),\n })\n }\n}\n\nlet environmentLock = Promise.resolve()\n\n/** Bridge only NUXT_ aliases declared by the configured native provider. */\nexport const withNuxtEnvironment = async <T>(provider: ProviderSlug, load: () => Promise<T>): Promise<T> => {\n const metadata = getProvider(provider)\n if (!metadata) return load()\n const variables = listEnvVars(provider)\n if (variables.length === 0) return load()\n // ponytail: module-local env lock; use native env keys to avoid temporary aliases.\n const previous = environmentLock\n let release!: () => void\n environmentLock = new Promise<void>((resolveLock) => (release = resolveLock))\n await previous\n const injected: string[] = []\n for (const variable of variables) {\n const keys = [variable.key, ...(variable.aliases ?? [])]\n if (keys.some((key) => process.env[key] !== undefined)) continue\n for (const key of keys) {\n const value = process.env[`NUXT_${key}`]\n if (value !== undefined && process.env[key] === undefined) {\n process.env[key] = value\n injected.push(key)\n }\n }\n }\n try {\n return await load()\n } finally {\n for (const key of injected) delete process.env[key]\n release()\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"registry.js","names":[],"sources":["../../src/runtime/registry.ts"],"sourcesContent":["import {\n createFiles,\n type Adapter,\n type ExtensionsOf,\n type Files,\n type FilesActionEvent,\n type FilesErrorEvent,\n type FilesRetryEvent,\n type ProviderSlug,\n} from 'files-sdk'\nimport { getProvider, listEnvVars } from 'files-sdk/providers'\n\nimport type { FilesConfig, NamedFilesConfig, SingleFilesConfig, StorageConfig } from '../config'\nimport type { FilesDevtoolsSnapshot } from '../devtools/snapshot'\n\n/** Native Files client plus the methods contributed by a storage's plugins. */\nexport type FilesForStorage<T extends StorageConfig> = Files & ExtensionsOf<NonNullable<T['plugins']>>\n\n/** Map each configured storage name to its native Files client and plugin extensions. */\nexport type StorageRegistry<C extends FilesConfig> =\n C extends NamedFilesConfig<infer Storages>\n ? { [Name in keyof Storages]: FilesForStorage<Storages[Name]> }\n : Record<never, never>\n\n/** Files client returned by an unnamed single-storage configuration. */\nexport type SingleStorage<C extends FilesConfig> =\n C extends SingleFilesConfig<infer Storage> ? FilesForStorage<Storage> : never\n\n/** Hooks emitted by the Nuxt/Nitro bridge after the storage's native hooks. */\nexport interface FilesRuntimeHooks {\n /** Observe a failed native Files operation. */\n onError?: (event: FilesErrorEvent, storage?: string) => void | Promise<void>\n /** Observe a completed native Files operation. */\n onAction?: (event: FilesActionEvent, storage?: string) => void | Promise<void>\n /** Observe a native Files retry. */\n onRetry?: (event: FilesRetryEvent, storage?: string) => void | Promise<void>\n}\n\n/** One provider factory statically supplied by the generated Nitro plugin. */\nexport type FilesProviderFactory = (config: never) => Adapter\n/** Provider factories available in the current build. */\nexport type FilesProviderFactories = Partial<Record<ProviderSlug, FilesProviderFactory>>\n\nconst runHooks = async (...hooks: (() => void | Promise<void> | undefined)[]): Promise<void> => {\n for (const hook of hooks) {\n try {\n // Preserve user-before-bridge ordering without exposing hook failures to native operations.\n // oxlint-disable-next-line no-await-in-loop\n await hook()\n } catch {}\n }\n}\n\nconst isStorageConfig = (value: unknown): value is StorageConfig =>\n Boolean(value && typeof value === 'object' && 'adapter' in value && typeof value.adapter === 'string')\nconst isStorageRecord = (value: unknown): value is Record<string, StorageConfig> =>\n Boolean(value && typeof value === 'object' && Object.values(value).every(isStorageConfig))\n\ntype StorageEntry = { name: string | undefined; storage: StorageConfig; override: StorageConfig | undefined }\n\n/** Lazily construct and memoize native Files clients for a validated project configuration. */\nexport class FilesRegistry<const C extends FilesConfig = FilesConfig> {\n readonly #config: C\n readonly #development: boolean\n readonly #factories: FilesProviderFactories\n readonly #hooks: FilesRuntimeHooks\n readonly #instances = new Map<string, Files>()\n readonly #initializing = new Set<string>()\n\n /** Create a registry without constructing a provider. */\n constructor(\n config: C,\n options: {\n development?: boolean\n factories: FilesProviderFactories\n hooks?: FilesRuntimeHooks\n },\n ) {\n if ('default' in config) {\n throw new Error('[nuxt-files-sdk:invalid-config] The default option has been removed.')\n }\n if (\n !config.storage ||\n (!isStorageConfig(config.storage) &&\n (!isStorageRecord(config.storage) || Object.keys(config.storage).length === 0))\n ) {\n throw new Error('[nuxt-files-sdk:invalid-config] At least one storage is required.')\n }\n if (!isStorageConfig(config.storage)) {\n if (config.devStorage && !isStorageRecord(config.devStorage)) {\n throw new Error('[nuxt-files-sdk:invalid-config] Named storage requires named devStorage overrides.')\n }\n for (const name of Object.keys(config.devStorage ?? {})) {\n if (!Object.hasOwn(config.storage, name)) {\n throw new Error(`[nuxt-files-sdk:unknown-storage] Unknown storage \"${name}\".`)\n }\n }\n }\n this.#config = config\n this.#development = options.development ?? false\n this.#factories = options.factories\n this.#hooks = options.hooks ?? {}\n }\n\n /** Return the client from an unnamed single-storage configuration. */\n get(...args: C extends SingleFilesConfig ? [] : [name: never]): SingleStorage<C>\n /** Return one named storage client. */\n get<Name extends Extract<keyof StorageRegistry<C>, string>>(name: Name): StorageRegistry<C>[Name]\n get(name?: string): Files {\n const entry = this.#entry(name)\n const key = entry.name ?? ''\n const cached = this.#instances.get(key)\n if (cached) return cached\n if (this.#initializing.has(key)) {\n throw new Error('[nuxt-files-sdk:circular-initialization] Storage configuration cannot access itself.')\n }\n this.#initializing.add(key)\n try {\n const files = this.#create(entry)\n this.#instances.set(key, files)\n return files\n } finally {\n this.#initializing.delete(key)\n }\n }\n\n /** Return secret-free storage metadata and initialization state for development diagnostics. */\n inspect(): FilesDevtoolsSnapshot {\n return {\n storages: this.#entries().map(({ name, storage, override }) => ({\n ...(name === undefined ? {} : { name }),\n adapter: override?.adapter ?? storage.adapter,\n plugins: storage.plugins?.map((plugin) => plugin.name) ?? [],\n source: override ? 'devStorage' : 'storage',\n initialized: this.#instances.has(name ?? ''),\n })),\n diagnostics: [],\n }\n }\n\n #entries(): StorageEntry[] {\n const storage = this.#config.storage\n const devStorage = this.#config.devStorage\n if (isStorageConfig(storage)) {\n const override = this.#development && isStorageConfig(devStorage) ? devStorage : undefined\n return [{ name: undefined, storage, override }]\n }\n const overrides = this.#development && isStorageRecord(devStorage) ? devStorage : undefined\n return Object.entries(storage).map(([name, namedStorage]) => ({\n name,\n storage: namedStorage,\n override: overrides?.[name],\n }))\n }\n\n #entry(name?: string): StorageEntry {\n if (isStorageConfig(this.#config.storage)) {\n if (name !== undefined) {\n throw new Error(`[nuxt-files-sdk:unknown-storage] Unknown storage \"${name}\".`)\n }\n return this.#entries()[0]!\n }\n if (name === undefined) {\n throw new Error('[nuxt-files-sdk:storage-name-required] A storage name is required.')\n }\n const entry = this.#entries().find((candidate) => candidate.name === name)\n if (!entry) throw new Error(`[nuxt-files-sdk:unknown-storage] Unknown storage \"${name}\".`)\n return entry\n }\n\n #create({ name, storage, override }: StorageEntry): Files {\n const selected = override ?? storage\n const factory = this.#factories[selected.adapter]\n if (!factory) {\n throw new Error(\n `[nuxt-files-sdk:adapter-not-generated] Adapter \"${selected.adapter}\" is not available in this build.`,\n )\n }\n const adapter = withNuxtEnvironment(selected.adapter, () => {\n const input = typeof selected.config === 'function' ? selected.config() : selected.config\n if (input && typeof input === 'object' && 'then' in input) {\n throw new Error('[nuxt-files-sdk:async-config] Storage config functions must be synchronous.')\n }\n // Generated factories and configs share an adapter key; the broad registry type erases that correlation.\n // oxlint-disable-next-line typescript/no-unsafe-type-assertion\n return factory(input as never)\n })\n return createFiles({\n adapter,\n hooks: {\n onAction: (event) =>\n runHooks(\n () => storage.hooks?.onAction?.(event),\n () => this.#hooks.onAction?.(event, name),\n ),\n onError: (event) =>\n runHooks(\n () => storage.hooks?.onError?.(event),\n () => this.#hooks.onError?.(event, name),\n ),\n onRetry: (event) =>\n runHooks(\n () => storage.hooks?.onRetry?.(event),\n () => this.#hooks.onRetry?.(event, name),\n ),\n },\n ...(storage.plugins ? { plugins: storage.plugins } : {}),\n ...(storage.prefix === undefined ? {} : { prefix: storage.prefix }),\n ...(storage.retries === undefined ? {} : { retries: storage.retries }),\n ...(storage.timeout === undefined ? {} : { timeout: storage.timeout }),\n })\n }\n}\n\n/** Bridge only NUXT_ aliases declared by the configured native provider during synchronous construction. */\nexport const withNuxtEnvironment = <T>(provider: ProviderSlug, load: () => T): T => {\n const metadata = getProvider(provider)\n if (!metadata) return load()\n const variables = listEnvVars(provider)\n if (variables.length === 0) return load()\n const injected: string[] = []\n for (const variable of variables) {\n const keys = [variable.key, ...(variable.aliases ?? [])]\n if (keys.some((key) => process.env[key] !== undefined)) continue\n for (const key of keys) {\n const value = process.env[`NUXT_${key}`]\n if (value !== undefined && process.env[key] === undefined) {\n process.env[key] = value\n injected.push(key)\n }\n }\n }\n try {\n return load()\n } finally {\n for (const key of injected) delete process.env[key]\n }\n}\n"],"mappings":"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"}
package/dist/runtime.d.ts CHANGED
@@ -1,18 +1,22 @@
1
1
  import { FilesConfig } from "./config.js";
2
2
  import { FilesDevtoolsSnapshot } from "./devtools/snapshot.js";
3
- import { DefaultStorage, DefaultStorageName, FilesForStorage, FilesRegistry, FilesRuntimeHooks, StorageRegistry } from "./runtime/registry.js";
3
+ import { FilesForStorage, FilesProviderFactories, FilesProviderFactory, FilesRegistry, FilesRuntimeHooks, SingleStorage, StorageRegistry } from "./runtime/registry.js";
4
4
  import { Files } from "files-sdk";
5
5
  //#region src/runtime.d.ts
6
- /** Project storage names are merged into this interface by the generated declaration. */
6
+ /** Project storage names and plugin-extended Files clients supplied by generated declarations. */
7
7
  export interface NuxtFilesStorageRegistry {}
8
- /** Generated from the project's default-storage selection. */
9
- export interface NuxtFilesDefaultStorage {}
10
- export declare const configureFiles: <const C extends FilesConfig>(config: C, options?: ConstructorParameters<typeof FilesRegistry<C>>[1]) => FilesRegistry<C>;
8
+ /** Project single Files client supplied by generated declarations. */
9
+ export interface NuxtFilesSingleStorage {}
10
+ /** Configure the process-local Files registry used by {@link useServerFiles}. */
11
+ export declare const configureFiles: <const C extends FilesConfig>(config: C, options: ConstructorParameters<typeof FilesRegistry<C>>[1]) => FilesRegistry<C>;
12
+ /** Return secret-free diagnostics for the configured process-local Files registry. */
11
13
  export declare const inspectFiles: () => FilesDevtoolsSnapshot;
12
- export declare function useServerFiles(): Promise<NuxtFilesDefaultStorage extends {
13
- value: infer Default;
14
- } ? Default : Files>;
15
- export declare function useServerFiles<Name extends Extract<keyof NuxtFilesStorageRegistry, string>>(name: Name): Promise<NuxtFilesStorageRegistry[Name]>;
14
+ /** Return the project's unnamed Files client, including its configured plugin extensions. */
15
+ export declare function useServerFiles(...args: keyof NuxtFilesStorageRegistry extends never ? [] : [name: never]): NuxtFilesSingleStorage extends {
16
+ value: infer Single;
17
+ } ? Single : Files;
18
+ /** Return a named project Files client, including that storage's configured plugin extensions. */
19
+ export declare function useServerFiles<Name extends Extract<keyof NuxtFilesStorageRegistry, string>>(name: Name): NuxtFilesStorageRegistry[Name];
16
20
  //#endregion
17
- export { type DefaultStorage, type DefaultStorageName, type FilesForStorage, FilesRegistry, type FilesRuntimeHooks, type StorageRegistry };
21
+ export { type FilesForStorage, type FilesProviderFactories, type FilesProviderFactory, FilesRegistry, type FilesRuntimeHooks, type SingleStorage, type StorageRegistry };
18
22
  //# sourceMappingURL=runtime.d.ts.map
package/dist/runtime.js CHANGED
@@ -1,11 +1,13 @@
1
1
  import { FilesRegistry } from "./runtime/registry.js";
2
2
  //#region src/runtime.ts
3
3
  let registry;
4
+ /** Configure the process-local Files registry used by {@link useServerFiles}. */
4
5
  const configureFiles = (config, options) => {
5
6
  const value = new FilesRegistry(config, options);
6
7
  registry = value;
7
8
  return value;
8
9
  };
10
+ /** Return secret-free diagnostics for the configured process-local Files registry. */
9
11
  const inspectFiles = () => registry?.inspect() ?? {
10
12
  storages: [],
11
13
  diagnostics: [{
@@ -16,7 +18,7 @@ const inspectFiles = () => registry?.inspect() ?? {
16
18
  };
17
19
  function useServerFiles(name) {
18
20
  if (!registry) throw new Error("[nuxt-files-sdk:not-configured] The Files registry has not been configured.");
19
- return registry.get(name);
21
+ return name === void 0 ? registry.get() : registry.get(name);
20
22
  }
21
23
  //#endregion
22
24
  export { FilesRegistry, configureFiles, inspectFiles, useServerFiles };
@@ -1 +1 @@
1
- {"version":3,"file":"runtime.js","names":[],"sources":["../src/runtime.ts"],"sourcesContent":["import type { Files } from 'files-sdk'\n\nimport type { FilesConfig } from './config'\nimport type { FilesDevtoolsSnapshot } from './devtools/snapshot'\nimport { FilesRegistry } from './runtime/registry'\n\nexport { FilesRegistry } from './runtime/registry'\nexport type {\n DefaultStorage,\n DefaultStorageName,\n FilesForStorage,\n FilesRuntimeHooks,\n StorageRegistry,\n} from './runtime/registry'\n\n/** Project storage names are merged into this interface by the generated declaration. */\nexport interface NuxtFilesStorageRegistry {}\n/** Generated from the project's default-storage selection. */\nexport interface NuxtFilesDefaultStorage {}\n\nlet registry: FilesRegistry | undefined\n\nexport const configureFiles = <const C extends FilesConfig>(\n config: C,\n options?: ConstructorParameters<typeof FilesRegistry<C>>[1],\n): FilesRegistry<C> => {\n const value = new FilesRegistry(config, options)\n registry = value\n return value\n}\n\nexport const inspectFiles = (): FilesDevtoolsSnapshot =>\n registry?.inspect() ?? {\n storages: [],\n diagnostics: [\n {\n code: 'NUXT_FILES_NOT_CONFIGURED',\n level: 'warning',\n message: 'The Files registry has not been configured.',\n },\n ],\n }\n\nexport function useServerFiles(): Promise<NuxtFilesDefaultStorage extends { value: infer Default } ? Default : Files>\nexport function useServerFiles<Name extends Extract<keyof NuxtFilesStorageRegistry, string>>(\n name: Name,\n): Promise<NuxtFilesStorageRegistry[Name]>\nexport function useServerFiles(name?: string): Promise<Files> {\n if (!registry) {\n throw new Error('[nuxt-files-sdk:not-configured] The Files registry has not been configured.')\n }\n return registry.get(name)\n}\n"],"mappings":";;AAoBA,IAAI;AAEJ,MAAa,kBACT,QACA,YACmB;CACnB,MAAM,QAAQ,IAAI,cAAc,QAAQ,OAAO;CAC/C,WAAW;CACX,OAAO;AACX;AAEA,MAAa,qBACT,UAAU,QAAQ,KAAK;CACnB,UAAU,CAAC;CACX,aAAa,CACT;EACI,MAAM;EACN,OAAO;EACP,SAAS;CACb,CACJ;AACJ;AAMJ,SAAgB,eAAe,MAA+B;CAC1D,IAAI,CAAC,UACD,MAAM,IAAI,MAAM,6EAA6E;CAEjG,OAAO,SAAS,IAAI,IAAI;AAC5B"}
1
+ {"version":3,"file":"runtime.js","names":[],"sources":["../src/runtime.ts"],"sourcesContent":["import type { Files } from 'files-sdk'\n\nimport type { FilesConfig } from './config'\nimport type { FilesDevtoolsSnapshot } from './devtools/snapshot'\nimport { FilesRegistry } from './runtime/registry'\n\nexport { FilesRegistry } from './runtime/registry'\nexport type {\n FilesForStorage,\n FilesProviderFactories,\n FilesProviderFactory,\n FilesRuntimeHooks,\n SingleStorage,\n StorageRegistry,\n} from './runtime/registry'\n\n/** Project storage names and plugin-extended Files clients supplied by generated declarations. */\nexport interface NuxtFilesStorageRegistry {}\n/** Project single Files client supplied by generated declarations. */\nexport interface NuxtFilesSingleStorage {}\n\nlet registry: FilesRegistry | undefined\n\n/** Configure the process-local Files registry used by {@link useServerFiles}. */\nexport const configureFiles = <const C extends FilesConfig>(\n config: C,\n options: ConstructorParameters<typeof FilesRegistry<C>>[1],\n): FilesRegistry<C> => {\n const value = new FilesRegistry(config, options)\n registry = value\n return value\n}\n\n/** Return secret-free diagnostics for the configured process-local Files registry. */\nexport const inspectFiles = (): FilesDevtoolsSnapshot =>\n registry?.inspect() ?? {\n storages: [],\n diagnostics: [\n {\n code: 'NUXT_FILES_NOT_CONFIGURED',\n level: 'warning',\n message: 'The Files registry has not been configured.',\n },\n ],\n }\n\n/** Return the project's unnamed Files client, including its configured plugin extensions. */\nexport function useServerFiles(\n ...args: keyof NuxtFilesStorageRegistry extends never ? [] : [name: never]\n): NuxtFilesSingleStorage extends { value: infer Single } ? Single : Files\n/** Return a named project Files client, including that storage's configured plugin extensions. */\nexport function useServerFiles<Name extends Extract<keyof NuxtFilesStorageRegistry, string>>(\n name: Name,\n): NuxtFilesStorageRegistry[Name]\nexport function useServerFiles(name?: string): Files {\n if (!registry) {\n throw new Error('[nuxt-files-sdk:not-configured] The Files registry has not been configured.')\n }\n return name === undefined ? registry.get() : (registry.get as (storage: string) => Files)(name)\n}\n"],"mappings":";;AAqBA,IAAI;;AAGJ,MAAa,kBACT,QACA,YACmB;CACnB,MAAM,QAAQ,IAAI,cAAc,QAAQ,OAAO;CAC/C,WAAW;CACX,OAAO;AACX;;AAGA,MAAa,qBACT,UAAU,QAAQ,KAAK;CACnB,UAAU,CAAC;CACX,aAAa,CACT;EACI,MAAM;EACN,OAAO;EACP,SAAS;CACb,CACJ;AACJ;AAUJ,SAAgB,eAAe,MAAsB;CACjD,IAAI,CAAC,UACD,MAAM,IAAI,MAAM,6EAA6E;CAEjG,OAAO,SAAS,KAAA,IAAY,SAAS,IAAI,IAAK,SAAS,IAAmC,IAAI;AAClG"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nuxt-files-sdk",
3
- "version": "0.0.1",
3
+ "version": "0.0.3",
4
4
  "description": "Native-first Files SDK integration for Nuxt and Nitro",
5
5
  "homepage": "https://github.com/liria24/nuxt-files-sdk#readme",
6
6
  "license": "MIT",
@@ -32,6 +32,10 @@
32
32
  "types": "./dist/plugins.d.ts",
33
33
  "import": "./dist/plugins.js"
34
34
  },
35
+ "./plugins/versioning": {
36
+ "types": "./dist/plugins/versioning.d.ts",
37
+ "import": "./dist/plugins/versioning.js"
38
+ },
35
39
  "./runtime": {
36
40
  "types": "./dist/runtime.d.ts",
37
41
  "import": "./dist/runtime.js"
@@ -51,12 +55,13 @@
51
55
  "dependencies": {
52
56
  "@nuxt/kit": "^4.5.2",
53
57
  "devframe": "^0.9.12",
54
- "files-sdk": "^2.3.1"
58
+ "files-sdk": "^2.4.0",
59
+ "jiti": "^2.7.0"
55
60
  },
56
61
  "devDependencies": {
57
62
  "@arethetypeswrong/cli": "^0.18.5",
58
63
  "@nuxt/schema": "^4.5.2",
59
- "@types/node": "^26.4.1",
64
+ "@types/node": "^26.5.0",
60
65
  "publint": "^0.3.24",
61
66
  "tsdown": "^0.23.0",
62
67
  "typescript": "^7.0.2",