@flightdev/cms 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,123 @@
1
+ import { Ref } from 'vue';
2
+ import { Instance as CMSInstance, FindOneOptions, FindManyOptions, Result as CMSResult } from '../index.js';
3
+
4
+ /**
5
+ * Vue composables for @flightdev/cms
6
+ *
7
+ * @example
8
+ * ```typescript
9
+ * import { provideCMS, useCMS, useCMSQuery } from '@flightdev/cms/vue';
10
+ * import { createCMS } from '@flightdev/cms';
11
+ * import { strapi } from '@flightdev/cms/strapi';
12
+ *
13
+ * // In App.vue setup
14
+ * const cms = createCMS(strapi({ url: '...', token: '...' }));
15
+ * provideCMS(cms);
16
+ *
17
+ * // In component
18
+ * const { data, loading, error } = useCMSQuery('posts', { limit: 10 });
19
+ * ```
20
+ */
21
+
22
+ /**
23
+ * Provide CMS instance to child components.
24
+ * Call this in your root component's setup.
25
+ */
26
+ declare function provideCMS(cms: CMSInstance): void;
27
+ /**
28
+ * Get CMS instance from context.
29
+ * Must be used within a component tree where provideCMS was called.
30
+ */
31
+ declare function useCMS(): CMSInstance;
32
+ interface QueryResult<T> {
33
+ data: Ref<T | null>;
34
+ loading: Ref<boolean>;
35
+ error: Ref<Error | null>;
36
+ refetch: () => Promise<void>;
37
+ }
38
+ interface ListQueryResult<T> {
39
+ data: Ref<T[]>;
40
+ meta: Ref<CMSResult<T>['meta'] | null>;
41
+ loading: Ref<boolean>;
42
+ error: Ref<Error | null>;
43
+ refetch: () => Promise<void>;
44
+ }
45
+ /**
46
+ * Query a single entity from the CMS.
47
+ *
48
+ * @example
49
+ * ```vue
50
+ * <script setup>
51
+ * const { slug } = useRoute().params;
52
+ * const { data: post, loading, error } = useCMSOne('posts', () => ({
53
+ * where: { slug },
54
+ * populate: ['author'],
55
+ * }));
56
+ * </script>
57
+ *
58
+ * <template>
59
+ * <Loading v-if="loading" />
60
+ * <Error v-else-if="error" :error="error" />
61
+ * <Post v-else-if="post" :post="post" />
62
+ * </template>
63
+ * ```
64
+ */
65
+ declare function useCMSOne<T = unknown>(collection: string | Ref<string>, options?: FindOneOptions | Ref<FindOneOptions> | (() => FindOneOptions)): QueryResult<T>;
66
+ /**
67
+ * Query multiple entities from the CMS with pagination.
68
+ *
69
+ * @example
70
+ * ```vue
71
+ * <script setup>
72
+ * const { data: posts, meta, loading, refetch } = useCMSQuery('posts', {
73
+ * limit: 10,
74
+ * sort: { publishedAt: 'desc' },
75
+ * });
76
+ * </script>
77
+ *
78
+ * <template>
79
+ * <PostGrid :posts="posts" />
80
+ * <Pagination v-if="meta" :total="meta.total" :page="meta.page" />
81
+ * <button @click="refetch">Refresh</button>
82
+ * </template>
83
+ * ```
84
+ */
85
+ declare function useCMSQuery<T = unknown>(collection: string | Ref<string>, options?: FindManyOptions | Ref<FindManyOptions> | (() => FindManyOptions)): ListQueryResult<T>;
86
+ /**
87
+ * Query an entity by ID.
88
+ *
89
+ * @example
90
+ * ```vue
91
+ * <script setup>
92
+ * const { id } = useRoute().params;
93
+ * const { data: post, loading } = useCMSById('posts', () => id, {
94
+ * populate: ['author', 'comments'],
95
+ * });
96
+ * </script>
97
+ * ```
98
+ */
99
+ declare function useCMSById<T = unknown>(collection: string | Ref<string>, id: string | number | Ref<string | number> | (() => string | number), options?: Omit<FindOneOptions, 'where'> | Ref<Omit<FindOneOptions, 'where'>>): QueryResult<T>;
100
+ interface MutationResult<TData, TInput> {
101
+ data: Ref<TData | null>;
102
+ loading: Ref<boolean>;
103
+ error: Ref<Error | null>;
104
+ mutate: (input: TInput) => Promise<TData>;
105
+ reset: () => void;
106
+ }
107
+ /**
108
+ * Create a new entity in the CMS.
109
+ */
110
+ declare function useCMSCreate<T = unknown, TInput = Partial<T>>(collection: string | Ref<string>): MutationResult<T, TInput>;
111
+ /**
112
+ * Update an entity in the CMS.
113
+ */
114
+ declare function useCMSUpdate<T = unknown, TInput = Partial<T>>(collection: string | Ref<string>): MutationResult<T, {
115
+ id: string | number;
116
+ data: TInput;
117
+ }>;
118
+ /**
119
+ * Delete an entity from the CMS.
120
+ */
121
+ declare function useCMSDelete(collection: string | Ref<string>): MutationResult<void, string | number>;
122
+
123
+ export { provideCMS, useCMS, useCMSById, useCMSCreate, useCMSDelete, useCMSOne, useCMSQuery, useCMSUpdate };
@@ -0,0 +1,201 @@
1
+ import { provide, inject, ref, computed, watch } from 'vue';
2
+
3
+ // src/vue/index.ts
4
+ var CMS_KEY = /* @__PURE__ */ Symbol("flight-cms");
5
+ function provideCMS(cms) {
6
+ provide(CMS_KEY, cms);
7
+ }
8
+ function useCMS() {
9
+ const cms = inject(CMS_KEY);
10
+ if (!cms) {
11
+ throw new Error("useCMS: CMS not provided. Call provideCMS in a parent component.");
12
+ }
13
+ return cms;
14
+ }
15
+ function useCMSOne(collection, options) {
16
+ const cms = useCMS();
17
+ const data = ref(null);
18
+ const loading = ref(true);
19
+ const error = ref(null);
20
+ const collectionValue = computed(
21
+ () => typeof collection === "string" ? collection : collection.value
22
+ );
23
+ const optionsValue = computed(() => {
24
+ if (typeof options === "function") return options();
25
+ if (options && "value" in options) return options.value;
26
+ return options;
27
+ });
28
+ const fetch = async () => {
29
+ loading.value = true;
30
+ error.value = null;
31
+ try {
32
+ data.value = await cms.findOne(collectionValue.value, optionsValue.value);
33
+ } catch (e) {
34
+ error.value = e;
35
+ data.value = null;
36
+ } finally {
37
+ loading.value = false;
38
+ }
39
+ };
40
+ watch([collectionValue, optionsValue], fetch, { immediate: true, deep: true });
41
+ return { data, loading, error, refetch: fetch };
42
+ }
43
+ function useCMSQuery(collection, options) {
44
+ const cms = useCMS();
45
+ const data = ref([]);
46
+ const meta = ref(null);
47
+ const loading = ref(true);
48
+ const error = ref(null);
49
+ const collectionValue = computed(
50
+ () => typeof collection === "string" ? collection : collection.value
51
+ );
52
+ const optionsValue = computed(() => {
53
+ if (typeof options === "function") return options();
54
+ if (options && "value" in options) return options.value;
55
+ return options;
56
+ });
57
+ const fetch = async () => {
58
+ loading.value = true;
59
+ error.value = null;
60
+ try {
61
+ const result = await cms.findMany(collectionValue.value, optionsValue.value);
62
+ data.value = result.data;
63
+ meta.value = result.meta;
64
+ } catch (e) {
65
+ error.value = e;
66
+ } finally {
67
+ loading.value = false;
68
+ }
69
+ };
70
+ watch([collectionValue, optionsValue], fetch, { immediate: true, deep: true });
71
+ return { data, meta, loading, error, refetch: fetch };
72
+ }
73
+ function useCMSById(collection, id, options) {
74
+ const cms = useCMS();
75
+ const data = ref(null);
76
+ const loading = ref(true);
77
+ const error = ref(null);
78
+ const collectionValue = computed(
79
+ () => typeof collection === "string" ? collection : collection.value
80
+ );
81
+ const idValue = computed(() => {
82
+ if (typeof id === "function") return id();
83
+ if (typeof id === "object" && "value" in id) return id.value;
84
+ return id;
85
+ });
86
+ const optionsValue = computed(() => {
87
+ if (options && "value" in options) return options.value;
88
+ return options;
89
+ });
90
+ const fetch = async () => {
91
+ loading.value = true;
92
+ error.value = null;
93
+ try {
94
+ data.value = await cms.findById(collectionValue.value, idValue.value, optionsValue.value);
95
+ } catch (e) {
96
+ error.value = e;
97
+ data.value = null;
98
+ } finally {
99
+ loading.value = false;
100
+ }
101
+ };
102
+ watch([collectionValue, idValue, optionsValue], fetch, { immediate: true, deep: true });
103
+ return { data, loading, error, refetch: fetch };
104
+ }
105
+ function useCMSCreate(collection) {
106
+ const cms = useCMS();
107
+ const data = ref(null);
108
+ const loading = ref(false);
109
+ const error = ref(null);
110
+ const collectionValue = computed(
111
+ () => typeof collection === "string" ? collection : collection.value
112
+ );
113
+ const mutate = async (input) => {
114
+ if (!cms.create) {
115
+ throw new Error("CMS adapter does not support create operations");
116
+ }
117
+ loading.value = true;
118
+ error.value = null;
119
+ try {
120
+ const result = await cms.create(collectionValue.value, input);
121
+ data.value = result;
122
+ return result;
123
+ } catch (e) {
124
+ error.value = e;
125
+ throw e;
126
+ } finally {
127
+ loading.value = false;
128
+ }
129
+ };
130
+ const reset = () => {
131
+ data.value = null;
132
+ loading.value = false;
133
+ error.value = null;
134
+ };
135
+ return { data, loading, error, mutate, reset };
136
+ }
137
+ function useCMSUpdate(collection) {
138
+ const cms = useCMS();
139
+ const data = ref(null);
140
+ const loading = ref(false);
141
+ const error = ref(null);
142
+ const collectionValue = computed(
143
+ () => typeof collection === "string" ? collection : collection.value
144
+ );
145
+ const mutate = async ({ id, data: inputData }) => {
146
+ if (!cms.update) {
147
+ throw new Error("CMS adapter does not support update operations");
148
+ }
149
+ loading.value = true;
150
+ error.value = null;
151
+ try {
152
+ const result = await cms.update(collectionValue.value, id, inputData);
153
+ data.value = result;
154
+ return result;
155
+ } catch (e) {
156
+ error.value = e;
157
+ throw e;
158
+ } finally {
159
+ loading.value = false;
160
+ }
161
+ };
162
+ const reset = () => {
163
+ data.value = null;
164
+ loading.value = false;
165
+ error.value = null;
166
+ };
167
+ return { data, loading, error, mutate, reset };
168
+ }
169
+ function useCMSDelete(collection) {
170
+ const cms = useCMS();
171
+ const data = ref(void 0);
172
+ const loading = ref(false);
173
+ const error = ref(null);
174
+ const collectionValue = computed(
175
+ () => typeof collection === "string" ? collection : collection.value
176
+ );
177
+ const mutate = async (id) => {
178
+ if (!cms.delete) {
179
+ throw new Error("CMS adapter does not support delete operations");
180
+ }
181
+ loading.value = true;
182
+ error.value = null;
183
+ try {
184
+ await cms.delete(collectionValue.value, id);
185
+ } catch (e) {
186
+ error.value = e;
187
+ throw e;
188
+ } finally {
189
+ loading.value = false;
190
+ }
191
+ };
192
+ const reset = () => {
193
+ loading.value = false;
194
+ error.value = null;
195
+ };
196
+ return { data, loading, error, mutate, reset };
197
+ }
198
+
199
+ export { provideCMS, useCMS, useCMSById, useCMSCreate, useCMSDelete, useCMSOne, useCMSQuery, useCMSUpdate };
200
+ //# sourceMappingURL=index.js.map
201
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/vue/index.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/**\r\n * Vue composables for @flightdev/cms\r\n * \r\n * @example\r\n * ```typescript\r\n * import { provideCMS, useCMS, useCMSQuery } from '@flightdev/cms/vue';\r\n * import { createCMS } from '@flightdev/cms';\r\n * import { strapi } from '@flightdev/cms/strapi';\r\n * \r\n * // In App.vue setup\r\n * const cms = createCMS(strapi({ url: '...', token: '...' }));\r\n * provideCMS(cms);\r\n * \r\n * // In component\r\n * const { data, loading, error } = useCMSQuery('posts', { limit: 10 });\r\n * ```\r\n */\r\n\r\nimport { inject, provide, ref, watch, computed, type Ref, type InjectionKey } from 'vue';\r\nimport type { CMSInstance, CMSResult, FindManyOptions, FindOneOptions } from '../index';\r\n\r\n// =============================================================================\r\n// Context\r\n// =============================================================================\r\n\r\nconst CMS_KEY = Symbol('flight-cms') as InjectionKey<CMSInstance>;\r\n\r\n/**\r\n * Provide CMS instance to child components.\r\n * Call this in your root component's setup.\r\n */\r\nexport function provideCMS(cms: CMSInstance): void {\r\n provide(CMS_KEY, cms);\r\n}\r\n\r\n/**\r\n * Get CMS instance from context.\r\n * Must be used within a component tree where provideCMS was called.\r\n */\r\nexport function useCMS(): CMSInstance {\r\n const cms = inject(CMS_KEY);\r\n\r\n if (!cms) {\r\n throw new Error('useCMS: CMS not provided. Call provideCMS in a parent component.');\r\n }\r\n\r\n return cms;\r\n}\r\n\r\n// =============================================================================\r\n// Query Composables\r\n// =============================================================================\r\n\r\ninterface QueryResult<T> {\r\n data: Ref<T | null>;\r\n loading: Ref<boolean>;\r\n error: Ref<Error | null>;\r\n refetch: () => Promise<void>;\r\n}\r\n\r\ninterface ListQueryResult<T> {\r\n data: Ref<T[]>;\r\n meta: Ref<CMSResult<T>['meta'] | null>;\r\n loading: Ref<boolean>;\r\n error: Ref<Error | null>;\r\n refetch: () => Promise<void>;\r\n}\r\n\r\n/**\r\n * Query a single entity from the CMS.\r\n * \r\n * @example\r\n * ```vue\r\n * <script setup>\r\n * const { slug } = useRoute().params;\r\n * const { data: post, loading, error } = useCMSOne('posts', () => ({\r\n * where: { slug },\r\n * populate: ['author'],\r\n * }));\r\n * </script>\r\n * \r\n * <template>\r\n * <Loading v-if=\"loading\" />\r\n * <Error v-else-if=\"error\" :error=\"error\" />\r\n * <Post v-else-if=\"post\" :post=\"post\" />\r\n * </template>\r\n * ```\r\n */\r\nexport function useCMSOne<T = unknown>(\r\n collection: string | Ref<string>,\r\n options?: FindOneOptions | Ref<FindOneOptions> | (() => FindOneOptions)\r\n): QueryResult<T> {\r\n const cms = useCMS();\r\n\r\n const data = ref<T | null>(null) as Ref<T | null>;\r\n const loading = ref(true);\r\n const error = ref<Error | null>(null);\r\n\r\n const collectionValue = computed(() =>\r\n typeof collection === 'string' ? collection : collection.value\r\n );\r\n\r\n const optionsValue = computed(() => {\r\n if (typeof options === 'function') return options();\r\n if (options && 'value' in options) return options.value;\r\n return options;\r\n });\r\n\r\n const fetch = async () => {\r\n loading.value = true;\r\n error.value = null;\r\n\r\n try {\r\n data.value = await cms.findOne<T>(collectionValue.value, optionsValue.value);\r\n } catch (e) {\r\n error.value = e as Error;\r\n data.value = null;\r\n } finally {\r\n loading.value = false;\r\n }\r\n };\r\n\r\n // Watch for changes and refetch\r\n watch([collectionValue, optionsValue], fetch, { immediate: true, deep: true });\r\n\r\n return { data, loading, error, refetch: fetch };\r\n}\r\n\r\n/**\r\n * Query multiple entities from the CMS with pagination.\r\n * \r\n * @example\r\n * ```vue\r\n * <script setup>\r\n * const { data: posts, meta, loading, refetch } = useCMSQuery('posts', {\r\n * limit: 10,\r\n * sort: { publishedAt: 'desc' },\r\n * });\r\n * </script>\r\n * \r\n * <template>\r\n * <PostGrid :posts=\"posts\" />\r\n * <Pagination v-if=\"meta\" :total=\"meta.total\" :page=\"meta.page\" />\r\n * <button @click=\"refetch\">Refresh</button>\r\n * </template>\r\n * ```\r\n */\r\nexport function useCMSQuery<T = unknown>(\r\n collection: string | Ref<string>,\r\n options?: FindManyOptions | Ref<FindManyOptions> | (() => FindManyOptions)\r\n): ListQueryResult<T> {\r\n const cms = useCMS();\r\n\r\n const data = ref<T[]>([]) as Ref<T[]>;\r\n const meta = ref<CMSResult<T>['meta'] | null>(null) as Ref<CMSResult<T>['meta'] | null>;\r\n const loading = ref(true);\r\n const error = ref<Error | null>(null);\r\n\r\n const collectionValue = computed(() =>\r\n typeof collection === 'string' ? collection : collection.value\r\n );\r\n\r\n const optionsValue = computed(() => {\r\n if (typeof options === 'function') return options();\r\n if (options && 'value' in options) return options.value;\r\n return options;\r\n });\r\n\r\n const fetch = async () => {\r\n loading.value = true;\r\n error.value = null;\r\n\r\n try {\r\n const result = await cms.findMany<T>(collectionValue.value, optionsValue.value);\r\n data.value = result.data;\r\n meta.value = result.meta;\r\n } catch (e) {\r\n error.value = e as Error;\r\n } finally {\r\n loading.value = false;\r\n }\r\n };\r\n\r\n watch([collectionValue, optionsValue], fetch, { immediate: true, deep: true });\r\n\r\n return { data, meta, loading, error, refetch: fetch };\r\n}\r\n\r\n/**\r\n * Query an entity by ID.\r\n * \r\n * @example\r\n * ```vue\r\n * <script setup>\r\n * const { id } = useRoute().params;\r\n * const { data: post, loading } = useCMSById('posts', () => id, {\r\n * populate: ['author', 'comments'],\r\n * });\r\n * </script>\r\n * ```\r\n */\r\nexport function useCMSById<T = unknown>(\r\n collection: string | Ref<string>,\r\n id: string | number | Ref<string | number> | (() => string | number),\r\n options?: Omit<FindOneOptions, 'where'> | Ref<Omit<FindOneOptions, 'where'>>\r\n): QueryResult<T> {\r\n const cms = useCMS();\r\n\r\n const data = ref<T | null>(null) as Ref<T | null>;\r\n const loading = ref(true);\r\n const error = ref<Error | null>(null);\r\n\r\n const collectionValue = computed(() =>\r\n typeof collection === 'string' ? collection : collection.value\r\n );\r\n\r\n const idValue = computed(() => {\r\n if (typeof id === 'function') return id();\r\n if (typeof id === 'object' && 'value' in id) return id.value;\r\n return id;\r\n });\r\n\r\n const optionsValue = computed(() => {\r\n if (options && 'value' in options) return options.value;\r\n return options;\r\n });\r\n\r\n const fetch = async () => {\r\n loading.value = true;\r\n error.value = null;\r\n\r\n try {\r\n data.value = await cms.findById<T>(collectionValue.value, idValue.value, optionsValue.value);\r\n } catch (e) {\r\n error.value = e as Error;\r\n data.value = null;\r\n } finally {\r\n loading.value = false;\r\n }\r\n };\r\n\r\n watch([collectionValue, idValue, optionsValue], fetch, { immediate: true, deep: true });\r\n\r\n return { data, loading, error, refetch: fetch };\r\n}\r\n\r\n// =============================================================================\r\n// Mutation Composables\r\n// =============================================================================\r\n\r\ninterface MutationResult<TData, TInput> {\r\n data: Ref<TData | null>;\r\n loading: Ref<boolean>;\r\n error: Ref<Error | null>;\r\n mutate: (input: TInput) => Promise<TData>;\r\n reset: () => void;\r\n}\r\n\r\n/**\r\n * Create a new entity in the CMS.\r\n */\r\nexport function useCMSCreate<T = unknown, TInput = Partial<T>>(\r\n collection: string | Ref<string>\r\n): MutationResult<T, TInput> {\r\n const cms = useCMS();\r\n\r\n const data = ref<T | null>(null) as Ref<T | null>;\r\n const loading = ref(false);\r\n const error = ref<Error | null>(null);\r\n\r\n const collectionValue = computed(() =>\r\n typeof collection === 'string' ? collection : collection.value\r\n );\r\n\r\n const mutate = async (input: TInput): Promise<T> => {\r\n if (!cms.create) {\r\n throw new Error('CMS adapter does not support create operations');\r\n }\r\n\r\n loading.value = true;\r\n error.value = null;\r\n\r\n try {\r\n const result = await cms.create<T>(collectionValue.value, input as Partial<T>);\r\n data.value = result;\r\n return result;\r\n } catch (e) {\r\n error.value = e as Error;\r\n throw e;\r\n } finally {\r\n loading.value = false;\r\n }\r\n };\r\n\r\n const reset = () => {\r\n data.value = null;\r\n loading.value = false;\r\n error.value = null;\r\n };\r\n\r\n return { data, loading, error, mutate, reset };\r\n}\r\n\r\n/**\r\n * Update an entity in the CMS.\r\n */\r\nexport function useCMSUpdate<T = unknown, TInput = Partial<T>>(\r\n collection: string | Ref<string>\r\n): MutationResult<T, { id: string | number; data: TInput }> {\r\n const cms = useCMS();\r\n\r\n const data = ref<T | null>(null) as Ref<T | null>;\r\n const loading = ref(false);\r\n const error = ref<Error | null>(null);\r\n\r\n const collectionValue = computed(() =>\r\n typeof collection === 'string' ? collection : collection.value\r\n );\r\n\r\n const mutate = async ({ id, data: inputData }: { id: string | number; data: TInput }): Promise<T> => {\r\n if (!cms.update) {\r\n throw new Error('CMS adapter does not support update operations');\r\n }\r\n\r\n loading.value = true;\r\n error.value = null;\r\n\r\n try {\r\n const result = await cms.update<T>(collectionValue.value, id, inputData as Partial<T>);\r\n data.value = result;\r\n return result;\r\n } catch (e) {\r\n error.value = e as Error;\r\n throw e;\r\n } finally {\r\n loading.value = false;\r\n }\r\n };\r\n\r\n const reset = () => {\r\n data.value = null;\r\n loading.value = false;\r\n error.value = null;\r\n };\r\n\r\n return { data, loading, error, mutate, reset };\r\n}\r\n\r\n/**\r\n * Delete an entity from the CMS.\r\n */\r\nexport function useCMSDelete(\r\n collection: string | Ref<string>\r\n): MutationResult<void, string | number> {\r\n const cms = useCMS();\r\n\r\n const data = ref<void>(undefined);\r\n const loading = ref(false);\r\n const error = ref<Error | null>(null);\r\n\r\n const collectionValue = computed(() =>\r\n typeof collection === 'string' ? collection : collection.value\r\n );\r\n\r\n const mutate = async (id: string | number): Promise<void> => {\r\n if (!cms.delete) {\r\n throw new Error('CMS adapter does not support delete operations');\r\n }\r\n\r\n loading.value = true;\r\n error.value = null;\r\n\r\n try {\r\n await cms.delete(collectionValue.value, id);\r\n } catch (e) {\r\n error.value = e as Error;\r\n throw e;\r\n } finally {\r\n loading.value = false;\r\n }\r\n };\r\n\r\n const reset = () => {\r\n loading.value = false;\r\n error.value = null;\r\n };\r\n\r\n return { data, loading, error, mutate, reset };\r\n}\r\n"]}
package/package.json ADDED
@@ -0,0 +1,78 @@
1
+ {
2
+ "name": "@flightdev/cms",
3
+ "version": "0.2.0",
4
+ "description": "Unified CMS adapters for Flight Framework - use any headless CMS",
5
+ "keywords": [
6
+ "flight",
7
+ "cms",
8
+ "strapi",
9
+ "contentful",
10
+ "sanity",
11
+ "headless"
12
+ ],
13
+ "license": "MIT",
14
+ "author": "Flight Contributors",
15
+ "type": "module",
16
+ "exports": {
17
+ ".": {
18
+ "types": "./dist/index.d.ts",
19
+ "import": "./dist/index.js"
20
+ },
21
+ "./strapi": {
22
+ "types": "./dist/adapters/strapi.d.ts",
23
+ "import": "./dist/adapters/strapi.js"
24
+ },
25
+ "./contentful": {
26
+ "types": "./dist/adapters/contentful.d.ts",
27
+ "import": "./dist/adapters/contentful.js"
28
+ },
29
+ "./sanity": {
30
+ "types": "./dist/adapters/sanity.d.ts",
31
+ "import": "./dist/adapters/sanity.js"
32
+ },
33
+ "./react": {
34
+ "types": "./dist/react/index.d.ts",
35
+ "import": "./dist/react/index.js"
36
+ },
37
+ "./vue": {
38
+ "types": "./dist/vue/index.d.ts",
39
+ "import": "./dist/vue/index.js"
40
+ }
41
+ },
42
+ "main": "./dist/index.js",
43
+ "types": "./dist/index.d.ts",
44
+ "files": [
45
+ "dist"
46
+ ],
47
+ "devDependencies": {
48
+ "@types/node": "^22.0.0",
49
+ "@types/react": "^19.0.0",
50
+ "react": "^19.0.0",
51
+ "rimraf": "^6.0.0",
52
+ "tsup": "^8.0.0",
53
+ "typescript": "^5.7.0",
54
+ "vitest": "^2.0.0",
55
+ "vue": "^3.5.0"
56
+ },
57
+ "peerDependencies": {
58
+ "react": "^18.0.0 || ^19.0.0",
59
+ "vue": "^3.0.0"
60
+ },
61
+ "peerDependenciesMeta": {
62
+ "react": {
63
+ "optional": true
64
+ },
65
+ "vue": {
66
+ "optional": true
67
+ }
68
+ },
69
+ "scripts": {
70
+ "build": "tsup",
71
+ "dev": "tsup --watch",
72
+ "test": "vitest run",
73
+ "test:watch": "vitest",
74
+ "lint": "eslint src/",
75
+ "clean": "rimraf dist",
76
+ "typecheck": "tsc --noEmit"
77
+ }
78
+ }