amplifyquery 1.0.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.
package/README.md ADDED
@@ -0,0 +1,203 @@
1
+ # AmplifyQuery
2
+
3
+ A library that combines AWS Amplify and React Query, making it easier to manage Amplify backend data in React applications.
4
+
5
+ ## Key Features
6
+
7
+ - 💡 **Simple Type-Based API**: Written in TypeScript for complete type safety and autocompletion support.
8
+ - 🔄 **React Query Integration**: Leverage all React Query features like caching, retries, background updates, etc.
9
+ - 📱 **Offline Support**: Persistent query caching via MMKV for fast data loading even offline.
10
+ - 🪝 **Convenient Hooks API**: Abstract complex data synchronization into simple Hooks.
11
+ - 🛡 **Auth Mode Support**: Supports various AWS Amplify authentication modes (API Key, IAM, Cognito, etc.).
12
+ - ⚡ **Performance Optimized**: Maximize performance with request batching and intelligent caching.
13
+
14
+ ## Installation
15
+
16
+ ```bash
17
+ npm install amplifyquery
18
+ # or
19
+ yarn add amplifyquery
20
+ ```
21
+
22
+ ## Basic Usage
23
+
24
+ ### 1. Initialization
25
+
26
+ ```typescript
27
+ import { AmplifyQuery } from "amplifyquery";
28
+ import { generateClient } from "aws-amplify/api";
29
+
30
+ // Create Amplify client and initialize AmplifyQuery
31
+ const client = generateClient();
32
+ AmplifyQuery.configure({
33
+ client,
34
+ // Caching options (optional)
35
+ isCachingEnabled: true,
36
+ // Customize Query Client configuration (optional)
37
+ queryClientConfig: {
38
+ defaultOptions: {
39
+ queries: {
40
+ staleTime: 60000, // 1 minute
41
+ },
42
+ },
43
+ },
44
+ // Storage configuration (optional)
45
+ storage: {
46
+ mmkvId: "my-app.cache", // MMKV store ID
47
+ cacheKey: "MY_QUERY_CACHE", // Cache key name
48
+ maxAge: 1000 * 60 * 60 * 24 * 3, // 3 days (in milliseconds)
49
+ },
50
+ });
51
+ ```
52
+
53
+ ### 2. Service Creation
54
+
55
+ ```typescript
56
+ import { AmplifyQuery } from "amplifyquery";
57
+
58
+ // Define Todo model type (adjust to your backend schema)
59
+ interface TodoModel {
60
+ id: string;
61
+ name: string;
62
+ description?: string;
63
+ completed: boolean;
64
+ createdAt: string;
65
+ updatedAt: string;
66
+ }
67
+
68
+ // Create Todo service
69
+ const TodoService = AmplifyQuery.createAmplifyService<TodoModel>("Todo");
70
+
71
+ // Create Singleton service (for single-instance models)
72
+ const UserSettingsService =
73
+ AmplifyQuery.createSingletonService<UserSettingsModel>("UserSettings");
74
+ ```
75
+
76
+ ### 3. Data Fetching and Saving
77
+
78
+ ```typescript
79
+ // Fetch all items
80
+ const todos = await TodoService.list();
81
+
82
+ // Filtering
83
+ const completedTodos = await TodoService.list({
84
+ filter: { completed: { eq: true } },
85
+ });
86
+
87
+ // Fetch a single item
88
+ const todo = await TodoService.get("some-id");
89
+
90
+ // Create
91
+ const newTodo = await TodoService.create({
92
+ name: "Buy milk",
93
+ description: "Low-fat milk",
94
+ completed: false,
95
+ });
96
+
97
+ // Update
98
+ await TodoService.update({
99
+ id: "some-id",
100
+ completed: true,
101
+ });
102
+
103
+ // Delete
104
+ await TodoService.delete("some-id");
105
+ ```
106
+
107
+ ### 4. Using React Hooks
108
+
109
+ ```tsx
110
+ import React from "react";
111
+ import { View, Text, Button } from "react-native";
112
+
113
+ function TodoScreen() {
114
+ // Hook for managing a list of items
115
+ const {
116
+ items: todos,
117
+ isLoading,
118
+ error,
119
+ refresh,
120
+ create,
121
+ update,
122
+ delete: deleteTodo,
123
+ } = TodoService.useHook();
124
+
125
+ // Hook for managing a single item
126
+ const { item: settings, update: updateSettings } =
127
+ UserSettingsService.useItemHook(); // Assuming UserSettingsService is defined
128
+
129
+ if (isLoading) return <Text>Loading...</Text>;
130
+ if (error) return <Text>Error: {error.message}</Text>;
131
+
132
+ return (
133
+ <View>
134
+ {todos.map((todo) => (
135
+ <View key={todo.id}>
136
+ <Text>{todo.name}</Text>
137
+ <Button
138
+ title={todo.completed ? "Done" : "Mark as Done"}
139
+ onPress={() => update({ id: todo.id, completed: !todo.completed })}
140
+ />
141
+ <Button title="Delete" onPress={() => deleteTodo(todo.id)} />
142
+ </View>
143
+ ))}
144
+ <Button
145
+ title="New Todo"
146
+ onPress={() => create({ name: "New Todo", completed: false })}
147
+ />
148
+ <Button title="Refresh" onPress={() => refresh()} />
149
+ </View>
150
+ );
151
+ }
152
+ ```
153
+
154
+ ## Advanced Features
155
+
156
+ ### Caching
157
+
158
+ AmplifyQuery uses MMKV to persistently cache query results. This allows the app to display previous data immediately upon restart.
159
+
160
+ ```typescript
161
+ // Enable/disable caching (enabled by default)
162
+ AmplifyQuery.configure({
163
+ client,
164
+ isCachingEnabled: true, // or false
165
+ storage: {
166
+ maxAge: 1000 * 60 * 60 * 24 * 7, // 7 days (in milliseconds)
167
+ },
168
+ });
169
+
170
+ // Reset cache for a specific model
171
+ TodoService.resetCache();
172
+
173
+ // Force refresh a specific query
174
+ const todos = await TodoService.list({ forceRefresh: true });
175
+ ```
176
+
177
+ ### Authentication Modes
178
+
179
+ Access data with various authentication methods.
180
+
181
+ ```typescript
182
+ // Set global default authentication mode
183
+ AmplifyQuery.configure({ client, defaultAuthMode: "userPool" });
184
+
185
+ // Set authentication mode for a service
186
+ TodoService.setAuthMode("apiKey");
187
+
188
+ // Apply authentication mode to a specific request
189
+ await TodoService.list({ authMode: "iam" });
190
+
191
+ // Get a new service instance with a specific auth mode applied
192
+ const adminTodoService = TodoService.withAuthMode("iam");
193
+ ```
194
+
195
+ ## Important Notes
196
+
197
+ - This library is designed to be used with AWS Amplify v6 or higher.
198
+ - Requires React Query v5 or higher.
199
+ - Test thoroughly before using in a production project.
200
+
201
+ ## License
202
+
203
+ MIT
@@ -0,0 +1,11 @@
1
+ import { GraphQLClient } from "./types";
2
+ /**
3
+ * Function to set the client.
4
+ * @param client GraphQL client to inject.
5
+ */
6
+ export declare function setClient(client: GraphQLClient): void;
7
+ /**
8
+ * Returns the currently configured client.
9
+ * Throws an error if the client has not been set.
10
+ */
11
+ export declare function getClient(): GraphQLClient;
package/dist/client.js ADDED
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.setClient = setClient;
4
+ exports.getClient = getClient;
5
+ /**
6
+ * API client to be used throughout the application.
7
+ * This is injected by the library user.
8
+ */
9
+ let _client = null;
10
+ /**
11
+ * Function to set the client.
12
+ * @param client GraphQL client to inject.
13
+ */
14
+ function setClient(client) {
15
+ _client = client;
16
+ }
17
+ /**
18
+ * Returns the currently configured client.
19
+ * Throws an error if the client has not been set.
20
+ */
21
+ function getClient() {
22
+ if (!_client) {
23
+ throw new Error("API client has not been configured. Please call AmplifyQuery.configure() first.");
24
+ }
25
+ return _client;
26
+ }
@@ -0,0 +1,133 @@
1
+ import { getClient } from "./client";
2
+ import { queryClient, createQueryKeys, invalidateModel, invalidateModelItem, invalidateModelByField, invalidateAll, ensureMutationsFlushed } from "./query";
3
+ import { createAmplifyService } from "./service";
4
+ import { createSingletonService } from "./singleton";
5
+ import { AmplifyQueryConfig } from "./types";
6
+ import { createRelationalHook, setAppUrl, getAppUrl } from "./utils";
7
+ /**
8
+ * Initialization function for the AmplifyQuery library.
9
+ *
10
+ * This function must be called before using the library.
11
+ *
12
+ * @example
13
+ * ```typescript
14
+ * import { generateClient } from 'aws-amplify/api';
15
+ * import { AmplifyQuery } from 'amplifyquery';
16
+ *
17
+ * // Create Amplify client and initialize AmplifyQuery
18
+ * const client = generateClient();
19
+ * AmplifyQuery.configure({
20
+ * client,
21
+ * // Additional caching options, etc.
22
+ * isCachingEnabled: true,
23
+ * storage: {
24
+ * mmkvId: "custom.cache",
25
+ * maxAge: 1000 * 60 * 60 * 24 // 1 day
26
+ * }
27
+ * });
28
+ * ```
29
+ */
30
+ export declare function configure(config: AmplifyQueryConfig): void;
31
+ export * from "./types";
32
+ export { queryClient, invalidateModel, invalidateModelItem, invalidateModelByField, invalidateAll, ensureMutationsFlushed, createQueryKeys, };
33
+ export { getClient };
34
+ export declare const Utils: {
35
+ getUserId: () => Promise<string>;
36
+ formatTimestamp: (date?: Date) => string;
37
+ getDateString: (dateStr: string | undefined) => string;
38
+ removeOwnerField: <T extends Record<string, any>>(data: T, operation: "create" | "update" | "upsert") => Omit<T, "owner">;
39
+ };
40
+ export declare const Storage: {
41
+ _types: {
42
+ Item: {
43
+ url: string;
44
+ expiresAt: number;
45
+ };
46
+ CacheData: {
47
+ [key: string]: {
48
+ url: string;
49
+ expiresAt: number;
50
+ };
51
+ };
52
+ };
53
+ _urlCache: Map<string, {
54
+ url: string;
55
+ expiresAt: number;
56
+ }>;
57
+ _CACHE_KEY: string;
58
+ _initialized: boolean;
59
+ _initCache: () => void;
60
+ _saveCache: () => void;
61
+ uploadImage: (file: Blob | File, key?: string) => Promise<string>;
62
+ getFileUrl: (key: string, options?: {
63
+ forceRefresh?: boolean;
64
+ }) => Promise<string>;
65
+ deleteFile: (key: string) => Promise<void>;
66
+ clearUrlCache: () => void;
67
+ clearUrlCacheForKey: (key: string) => void;
68
+ clearExpiredUrlCache: () => void;
69
+ downloadAudioFile: (audioKey: string) => Promise<string>;
70
+ };
71
+ export declare const Auth: {
72
+ getCurrentUserInfo: () => Promise<{
73
+ userId: string;
74
+ username: string;
75
+ }>;
76
+ };
77
+ export { setAppUrl, getAppUrl };
78
+ /**
79
+ * Main object for the AmplifyQuery library.
80
+ */
81
+ export declare const AmplifyQuery: {
82
+ configure: typeof configure;
83
+ createQueryKeys: typeof createQueryKeys;
84
+ createAmplifyService: typeof createAmplifyService;
85
+ createSingletonService: typeof createSingletonService;
86
+ createRelationalHook: typeof createRelationalHook;
87
+ Utils: {
88
+ getUserId: () => Promise<string>;
89
+ formatTimestamp: (date?: Date) => string;
90
+ getDateString: (dateStr: string | undefined) => string;
91
+ removeOwnerField: <T extends Record<string, any>>(data: T, operation: "create" | "update" | "upsert") => Omit<T, "owner">;
92
+ };
93
+ Storage: {
94
+ _types: {
95
+ Item: {
96
+ url: string;
97
+ expiresAt: number;
98
+ };
99
+ CacheData: {
100
+ [key: string]: {
101
+ url: string;
102
+ expiresAt: number;
103
+ };
104
+ };
105
+ };
106
+ _urlCache: Map<string, {
107
+ url: string;
108
+ expiresAt: number;
109
+ }>;
110
+ _CACHE_KEY: string;
111
+ _initialized: boolean;
112
+ _initCache: () => void;
113
+ _saveCache: () => void;
114
+ uploadImage: (file: Blob | File, key?: string) => Promise<string>;
115
+ getFileUrl: (key: string, options?: {
116
+ forceRefresh?: boolean;
117
+ }) => Promise<string>;
118
+ deleteFile: (key: string) => Promise<void>;
119
+ clearUrlCache: () => void;
120
+ clearUrlCacheForKey: (key: string) => void;
121
+ clearExpiredUrlCache: () => void;
122
+ downloadAudioFile: (audioKey: string) => Promise<string>;
123
+ };
124
+ Auth: {
125
+ getCurrentUserInfo: () => Promise<{
126
+ userId: string;
127
+ username: string;
128
+ }>;
129
+ };
130
+ getModelIds: {
131
+ User: () => Promise<string>;
132
+ };
133
+ };
package/dist/index.js ADDED
@@ -0,0 +1,89 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.AmplifyQuery = exports.getAppUrl = exports.setAppUrl = exports.Auth = exports.Storage = exports.Utils = exports.getClient = exports.createQueryKeys = exports.ensureMutationsFlushed = exports.invalidateAll = exports.invalidateModelByField = exports.invalidateModelItem = exports.invalidateModel = exports.queryClient = void 0;
18
+ exports.configure = configure;
19
+ const client_1 = require("./client");
20
+ Object.defineProperty(exports, "getClient", { enumerable: true, get: function () { return client_1.getClient; } });
21
+ const query_1 = require("./query");
22
+ Object.defineProperty(exports, "queryClient", { enumerable: true, get: function () { return query_1.queryClient; } });
23
+ Object.defineProperty(exports, "createQueryKeys", { enumerable: true, get: function () { return query_1.createQueryKeys; } });
24
+ Object.defineProperty(exports, "invalidateModel", { enumerable: true, get: function () { return query_1.invalidateModel; } });
25
+ Object.defineProperty(exports, "invalidateModelItem", { enumerable: true, get: function () { return query_1.invalidateModelItem; } });
26
+ Object.defineProperty(exports, "invalidateModelByField", { enumerable: true, get: function () { return query_1.invalidateModelByField; } });
27
+ Object.defineProperty(exports, "invalidateAll", { enumerable: true, get: function () { return query_1.invalidateAll; } });
28
+ Object.defineProperty(exports, "ensureMutationsFlushed", { enumerable: true, get: function () { return query_1.ensureMutationsFlushed; } });
29
+ const service_1 = require("./service");
30
+ const singleton_1 = require("./singleton");
31
+ const utils_1 = require("./utils");
32
+ Object.defineProperty(exports, "setAppUrl", { enumerable: true, get: function () { return utils_1.setAppUrl; } });
33
+ Object.defineProperty(exports, "getAppUrl", { enumerable: true, get: function () { return utils_1.getAppUrl; } });
34
+ /**
35
+ * Initialization function for the AmplifyQuery library.
36
+ *
37
+ * This function must be called before using the library.
38
+ *
39
+ * @example
40
+ * ```typescript
41
+ * import { generateClient } from 'aws-amplify/api';
42
+ * import { AmplifyQuery } from 'amplifyquery';
43
+ *
44
+ * // Create Amplify client and initialize AmplifyQuery
45
+ * const client = generateClient();
46
+ * AmplifyQuery.configure({
47
+ * client,
48
+ * // Additional caching options, etc.
49
+ * isCachingEnabled: true,
50
+ * storage: {
51
+ * mmkvId: "custom.cache",
52
+ * maxAge: 1000 * 60 * 60 * 24 // 1 day
53
+ * }
54
+ * });
55
+ * ```
56
+ */
57
+ function configure(config) {
58
+ // Configure Amplify client
59
+ if (config.client) {
60
+ (0, client_1.setClient)(config.client);
61
+ }
62
+ // Apply React Query settings
63
+ (0, query_1.configure)({
64
+ isCachingEnabled: config.isCachingEnabled,
65
+ queryClientConfig: config.queryClientConfig,
66
+ storage: config.storage,
67
+ });
68
+ console.log("🔌 AmplifyQuery initialized successfully.");
69
+ }
70
+ // Re-export types
71
+ __exportStar(require("./types"), exports);
72
+ // Re-export utility services
73
+ exports.Utils = utils_1.Utils;
74
+ exports.Storage = utils_1.StorageService;
75
+ exports.Auth = utils_1.AuthService;
76
+ /**
77
+ * Main object for the AmplifyQuery library.
78
+ */
79
+ exports.AmplifyQuery = {
80
+ configure,
81
+ createQueryKeys: query_1.createQueryKeys,
82
+ createAmplifyService: service_1.createAmplifyService,
83
+ createSingletonService: singleton_1.createSingletonService,
84
+ createRelationalHook: utils_1.createRelationalHook,
85
+ Utils: utils_1.Utils,
86
+ Storage: utils_1.StorageService,
87
+ Auth: utils_1.AuthService,
88
+ getModelIds: singleton_1.getModelIds,
89
+ };
@@ -0,0 +1,52 @@
1
+ import { QueryClient, QueryClientConfig } from "@tanstack/react-query";
2
+ type ConfigOptions = {
3
+ isCachingEnabled?: boolean;
4
+ queryClientConfig?: QueryClientConfig;
5
+ storage?: {
6
+ mmkvId?: string;
7
+ cacheKey?: string;
8
+ maxAge?: number;
9
+ };
10
+ };
11
+ /**
12
+ * TanStack Query client
13
+ */
14
+ export declare let queryClient: QueryClient;
15
+ /**
16
+ * AmplifyQuery configuration
17
+ * @param options Configuration options
18
+ */
19
+ export declare function configure(options?: ConfigOptions): void;
20
+ /**
21
+ * Create query keys from model names
22
+ * @param modelNames Array of model names
23
+ * @returns Object of query keys per model
24
+ */
25
+ export declare function createQueryKeys(modelNames: string[]): Record<string, string[]>;
26
+ /**
27
+ * Invalidate all queries for a model
28
+ * @param modelName Model name
29
+ */
30
+ export declare function invalidateModel(modelName: string): void;
31
+ /**
32
+ * Invalidate a model item with a specific ID
33
+ * @param modelName Model name
34
+ * @param id Item ID
35
+ */
36
+ export declare function invalidateModelItem(modelName: string, id: string): void;
37
+ /**
38
+ * Invalidate model items with a specific field value
39
+ * @param modelName Model name
40
+ * @param field Field name
41
+ * @param value Field value
42
+ */
43
+ export declare function invalidateModelByField(modelName: string, field: string, value: any): void;
44
+ /**
45
+ * Invalidate all query caches (full app reset)
46
+ */
47
+ export declare function invalidateAll(): void;
48
+ /**
49
+ * Ensure important changes are synced to server before app closes
50
+ */
51
+ export declare function ensureMutationsFlushed(): Promise<unknown>;
52
+ export {};