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.
@@ -0,0 +1,14 @@
1
+ import { AmplifyDataService, SingletonAmplifyService } from "./types";
2
+ /**
3
+ * Function to create an extension service for singleton models
4
+ * @param baseService Base service
5
+ * @param getModelId Function to get the unique ID of the model
6
+ * @returns Extended service supporting singleton pattern
7
+ */
8
+ export declare function createSingletonService<T>(baseService: AmplifyDataService<T>, getModelId: () => Promise<string>): SingletonAmplifyService<T>;
9
+ /**
10
+ * Define functions to get model IDs by model
11
+ */
12
+ export declare const getModelIds: {
13
+ User: () => Promise<string>;
14
+ };
@@ -0,0 +1,144 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.getModelIds = void 0;
13
+ exports.createSingletonService = createSingletonService;
14
+ const client_1 = require("./client");
15
+ const auth_1 = require("aws-amplify/auth");
16
+ /**
17
+ * Function to create an extension service for singleton models
18
+ * @param baseService Base service
19
+ * @param getModelId Function to get the unique ID of the model
20
+ * @returns Extended service supporting singleton pattern
21
+ */
22
+ function createSingletonService(baseService, getModelId) {
23
+ // Extract modelName from baseService
24
+ const { modelName } = baseService;
25
+ // Create singleton service object
26
+ const singletonService = Object.assign(Object.assign({}, baseService), {
27
+ // Add singleton instance management methods
28
+ getCurrent: (options) => __awaiter(this, void 0, void 0, function* () {
29
+ var _a, _b, _c;
30
+ try {
31
+ const modelId = yield getModelId();
32
+ return baseService.get(modelId, options);
33
+ }
34
+ catch (error) {
35
+ console.error(`${modelName} singleton instance lookup error:`, error);
36
+ // Safely call getStore
37
+ try {
38
+ (_c = (_b = (_a = baseService
39
+ .getStore) === null || _a === void 0 ? void 0 : _a.call(baseService)) === null || _b === void 0 ? void 0 : _b.setError) === null || _c === void 0 ? void 0 : _c.call(_b, error instanceof Error ? error : new Error(String(error)));
40
+ }
41
+ catch (storeError) {
42
+ // Ignore if getStore doesn't exist or call fails
43
+ }
44
+ return null;
45
+ }
46
+ }), updateCurrent: (data) => __awaiter(this, void 0, void 0, function* () {
47
+ var _a, _b, _c;
48
+ try {
49
+ const modelId = yield getModelId();
50
+ return baseService.update(Object.assign(Object.assign({}, data), { id: modelId }));
51
+ }
52
+ catch (error) {
53
+ console.error(`${modelName} singleton instance update error:`, error);
54
+ // Safely call getStore
55
+ try {
56
+ (_c = (_b = (_a = baseService
57
+ .getStore) === null || _a === void 0 ? void 0 : _a.call(baseService)) === null || _b === void 0 ? void 0 : _b.setError) === null || _c === void 0 ? void 0 : _c.call(_b, error instanceof Error ? error : new Error(String(error)));
58
+ }
59
+ catch (storeError) {
60
+ // Ignore if getStore doesn't exist or call fails
61
+ }
62
+ return null;
63
+ }
64
+ }), upsertCurrent: (data) => __awaiter(this, void 0, void 0, function* () {
65
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q;
66
+ try {
67
+ const modelId = yield getModelId();
68
+ // Check the latest status by forced refresh
69
+ const existingItem = yield baseService.get(modelId, {
70
+ forceRefresh: true,
71
+ });
72
+ if (existingItem) {
73
+ // Update
74
+ return baseService.update(Object.assign(Object.assign({}, data), { id: modelId }));
75
+ }
76
+ else {
77
+ // Create (Direct call to Amplify Client - prevents random ID generation of generic create)
78
+ const modelData = Object.assign(Object.assign({}, data), { id: modelId });
79
+ // Safely call getStore
80
+ try {
81
+ (_c = (_b = (_a = baseService.getStore) === null || _a === void 0 ? void 0 : _a.call(baseService)) === null || _b === void 0 ? void 0 : _b.setLoading) === null || _c === void 0 ? void 0 : _c.call(_b, true);
82
+ }
83
+ catch (storeError) {
84
+ // Ignore if getStore doesn't exist or call fails
85
+ }
86
+ try {
87
+ // Call appropriate model from Amplify Models
88
+ const { data: createdItem } = yield (0, client_1.getClient)().models[modelName].create(modelData);
89
+ if (createdItem) {
90
+ try {
91
+ (_f = (_e = (_d = baseService.getStore) === null || _d === void 0 ? void 0 : _d.call(baseService)) === null || _e === void 0 ? void 0 : _e.setItem) === null || _f === void 0 ? void 0 : _f.call(_e, createdItem);
92
+ }
93
+ catch (storeError) {
94
+ // Ignore if getStore doesn't exist or call fails
95
+ }
96
+ }
97
+ try {
98
+ (_j = (_h = (_g = baseService.getStore) === null || _g === void 0 ? void 0 : _g.call(baseService)) === null || _h === void 0 ? void 0 : _h.setLoading) === null || _j === void 0 ? void 0 : _j.call(_h, false);
99
+ }
100
+ catch (storeError) {
101
+ // Ignore if getStore doesn't exist or call fails
102
+ }
103
+ return createdItem !== null && createdItem !== void 0 ? createdItem : null;
104
+ }
105
+ catch (apiError) {
106
+ try {
107
+ (_m = (_l = (_k = baseService.getStore) === null || _k === void 0 ? void 0 : _k.call(baseService)) === null || _l === void 0 ? void 0 : _l.setLoading) === null || _m === void 0 ? void 0 : _m.call(_l, false);
108
+ (_q = (_p = (_o = baseService
109
+ .getStore) === null || _o === void 0 ? void 0 : _o.call(baseService)) === null || _p === void 0 ? void 0 : _p.setError) === null || _q === void 0 ? void 0 : _q.call(_p, apiError instanceof Error
110
+ ? apiError
111
+ : new Error(String(apiError)));
112
+ }
113
+ catch (storeError) {
114
+ // Ignore if getStore doesn't exist or call fails
115
+ }
116
+ console.error(`${modelName} singleton instance Upsert error:`, apiError);
117
+ throw apiError; // Propagate error upwards
118
+ }
119
+ }
120
+ }
121
+ catch (error) {
122
+ console.error(`${modelName} singleton instance final Upsert error:`, error);
123
+ return null;
124
+ }
125
+ }) });
126
+ return singletonService;
127
+ }
128
+ /**
129
+ * Define functions to get model IDs by model
130
+ */
131
+ exports.getModelIds = {
132
+ // Get user ID
133
+ User: () => __awaiter(void 0, void 0, void 0, function* () {
134
+ try {
135
+ const { userId } = yield (0, auth_1.getCurrentUser)();
136
+ return userId;
137
+ }
138
+ catch (e) {
139
+ console.error("Failed to get user ID:", e);
140
+ throw new Error("Unable to retrieve user authentication information.");
141
+ }
142
+ }),
143
+ // Users can add their own functions to get singleton model IDs here as needed.
144
+ };
@@ -0,0 +1,5 @@
1
+ import { BaseModel, StoreState } from "./types";
2
+ /**
3
+ * Create cache store for each model
4
+ */
5
+ export declare function createModelStore<T extends BaseModel>(modelName: string): import("zustand").UseBoundStore<import("zustand").StoreApi<StoreState<T>>>;
package/dist/store.js ADDED
@@ -0,0 +1,67 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createModelStore = createModelStore;
4
+ const zustand_1 = require("zustand");
5
+ /**
6
+ * Create cache store for each model
7
+ */
8
+ function createModelStore(modelName) {
9
+ return (0, zustand_1.create)((set, get) => ({
10
+ items: [],
11
+ itemsMap: new Map(),
12
+ lastFetched: null,
13
+ isLoading: false,
14
+ error: null,
15
+ setItems: (items) => {
16
+ const itemsMap = new Map();
17
+ items.forEach((item) => itemsMap.set(item.id, item));
18
+ set({
19
+ items,
20
+ itemsMap,
21
+ lastFetched: Date.now(),
22
+ error: null,
23
+ });
24
+ },
25
+ setItem: (item) => {
26
+ const items = [...get().items];
27
+ const itemsMap = new Map(get().itemsMap);
28
+ // Search for existing item
29
+ const index = items.findIndex((i) => i.id === item.id);
30
+ if (index >= 0) {
31
+ // Update existing item
32
+ items[index] = item;
33
+ }
34
+ else {
35
+ // Add new item
36
+ items.push(item);
37
+ }
38
+ // Update map
39
+ itemsMap.set(item.id, item);
40
+ set({
41
+ items,
42
+ itemsMap,
43
+ lastFetched: Date.now(),
44
+ error: null,
45
+ });
46
+ },
47
+ removeItem: (id) => {
48
+ const items = get().items.filter((item) => item.id !== id);
49
+ const itemsMap = new Map(get().itemsMap);
50
+ itemsMap.delete(id);
51
+ set({
52
+ items,
53
+ itemsMap,
54
+ error: null,
55
+ });
56
+ },
57
+ setLoading: (isLoading) => set({ isLoading }),
58
+ setError: (error) => set({ error }),
59
+ resetState: () => set({
60
+ items: [],
61
+ itemsMap: new Map(),
62
+ lastFetched: null,
63
+ isLoading: false,
64
+ error: null,
65
+ }),
66
+ }));
67
+ }
@@ -0,0 +1,138 @@
1
+ /**
2
+ * Store state type
3
+ */
4
+ export type StoreState<T> = {
5
+ items: T[];
6
+ itemsMap: Map<string, T>;
7
+ lastFetched: number | null;
8
+ isLoading: boolean;
9
+ error: Error | null;
10
+ setItems: (items: T[]) => void;
11
+ setItem: (item: T) => void;
12
+ removeItem: (id: string) => void;
13
+ setLoading: (isLoading: boolean) => void;
14
+ setError: (error: Error | null) => void;
15
+ resetState: () => void;
16
+ };
17
+ /**
18
+ * Hook interface type
19
+ */
20
+ export type ModelHook<T> = {
21
+ items: T[];
22
+ isLoading: boolean;
23
+ error: Error | null;
24
+ getItem: (id: string) => T | null | undefined;
25
+ refresh: (options?: {
26
+ filter?: Record<string, any>;
27
+ }) => Promise<T[]>;
28
+ create: (data: Partial<T>) => Promise<T | null>;
29
+ update: (data: Partial<T> & {
30
+ id: string;
31
+ }) => Promise<T | null>;
32
+ delete: (id: string) => Promise<boolean>;
33
+ customList: (queryName: string, args: Record<string, any>, options?: {
34
+ forceRefresh?: boolean;
35
+ }) => Promise<T[]>;
36
+ };
37
+ /**
38
+ * Single item Hook interface type
39
+ */
40
+ export type ItemHook<T> = {
41
+ item: T | null;
42
+ isLoading: boolean;
43
+ error: Error | null;
44
+ refresh: () => Promise<T | null>;
45
+ update: (data: Partial<T>) => Promise<T | null>;
46
+ delete: () => Promise<boolean>;
47
+ };
48
+ export type AuthMode = "apiKey" | "iam" | "identityPool" | "oidc" | "userPool" | "lambda" | "none";
49
+ export interface AuthOptions {
50
+ authMode?: AuthMode;
51
+ }
52
+ /**
53
+ * Amplify Data service type
54
+ */
55
+ export interface AmplifyDataService<T> {
56
+ create: (data: Partial<T>, options?: AuthOptions) => Promise<T | null>;
57
+ createList: (dataList: Partial<T>[], options?: AuthOptions) => Promise<(T | null)[]>;
58
+ get: (id: string, options?: {
59
+ forceRefresh?: boolean;
60
+ authMode?: AuthMode;
61
+ }) => Promise<T | null>;
62
+ list: (options?: {
63
+ filter?: Record<string, any>;
64
+ forceRefresh?: boolean;
65
+ authMode?: AuthMode;
66
+ }) => Promise<T[]>;
67
+ customList: (queryName: string, args: Record<string, any>, options?: {
68
+ forceRefresh?: boolean;
69
+ authMode?: AuthMode;
70
+ }) => Promise<T[]>;
71
+ update: (data: Partial<T> & {
72
+ id: string;
73
+ }, options?: AuthOptions) => Promise<T | null>;
74
+ delete: (id: string, options?: AuthOptions) => Promise<boolean>;
75
+ deleteList: (ids: string[], options?: AuthOptions) => Promise<{
76
+ success: string[];
77
+ failed: string[];
78
+ }>;
79
+ upsert: (data: Partial<T> & {
80
+ id: string;
81
+ }, options?: AuthOptions) => Promise<T | null>;
82
+ getStore?: () => StoreState<T>;
83
+ loadFromCache: () => T[];
84
+ resetCache: () => void;
85
+ useHook: (options?: {
86
+ initialFetchOptions?: {
87
+ fetch?: boolean;
88
+ filter?: Record<string, any>;
89
+ };
90
+ customList?: {
91
+ queryName: string;
92
+ args: Record<string, any>;
93
+ forceRefresh?: boolean;
94
+ };
95
+ }) => ModelHook<T>;
96
+ useItemHook: (id: string) => ItemHook<T>;
97
+ modelName: string;
98
+ withExtensions: <E>(extensions: E) => AmplifyDataService<T> & E;
99
+ setAuthMode: (authMode: AuthMode) => void;
100
+ getAuthMode: () => AuthMode;
101
+ withAuthMode: (authMode: AuthMode) => AmplifyDataService<T>;
102
+ }
103
+ export interface SingletonAmplifyService<T> extends AmplifyDataService<T> {
104
+ getCurrent: (options?: {
105
+ forceRefresh?: boolean;
106
+ }) => Promise<T | null>;
107
+ updateCurrent: (data: Partial<T>) => Promise<T | null>;
108
+ upsertCurrent: (data: Partial<T>) => Promise<T | null>;
109
+ }
110
+ export interface BaseModel {
111
+ id: string;
112
+ createdAt: string;
113
+ updatedAt: string;
114
+ }
115
+ /**
116
+ * GraphQL client interface
117
+ * Compatible with clients generated by AWS Amplify's generateClient() function.
118
+ */
119
+ export interface GraphQLClient {
120
+ models: Record<string, any>;
121
+ queries: Record<string, any>;
122
+ mutations: Record<string, any>;
123
+ }
124
+ import { QueryClientConfig } from "@tanstack/react-query";
125
+ /**
126
+ * Library configuration options
127
+ */
128
+ export interface AmplifyQueryConfig {
129
+ client: GraphQLClient;
130
+ defaultAuthMode?: AuthMode;
131
+ isCachingEnabled?: boolean;
132
+ queryClientConfig?: QueryClientConfig;
133
+ storage?: {
134
+ mmkvId?: string;
135
+ cacheKey?: string;
136
+ maxAge?: number;
137
+ };
138
+ }
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,130 @@
1
+ import { AmplifyDataService, ModelHook, BaseModel } from "./types";
2
+ /**
3
+ * Set the base URL for the app
4
+ * @param url Base URL for the app
5
+ */
6
+ export declare function setAppUrl(url: string): void;
7
+ /**
8
+ * Get the base URL for the app
9
+ * @returns Configured app URL or empty string
10
+ */
11
+ export declare function getAppUrl(): string;
12
+ /**
13
+ * Utility functions
14
+ */
15
+ export declare const Utils: {
16
+ /**
17
+ * Get the ID of the currently logged-in user.
18
+ */
19
+ getUserId: () => Promise<string>;
20
+ /**
21
+ * Timestamp formatting function
22
+ */
23
+ formatTimestamp: (date?: Date) => string;
24
+ /**
25
+ * Extract YYYY-MM-DD format from date string
26
+ */
27
+ getDateString: (dateStr: string | undefined) => string;
28
+ /**
29
+ * Utility function to remove the owner field and print a warning
30
+ * @param data Data object to process
31
+ * @param operation Operation being performed (create or update)
32
+ * @returns Data object with owner field removed
33
+ */
34
+ removeOwnerField: <T extends Record<string, any>>(data: T, operation: "create" | "update" | "upsert") => Omit<T, "owner">;
35
+ };
36
+ /**
37
+ * Storage related utilities
38
+ */
39
+ export declare const StorageService: {
40
+ _types: {
41
+ Item: {
42
+ url: string;
43
+ expiresAt: number;
44
+ };
45
+ CacheData: {
46
+ [key: string]: {
47
+ url: string;
48
+ expiresAt: number;
49
+ };
50
+ };
51
+ };
52
+ _urlCache: Map<string, {
53
+ url: string;
54
+ expiresAt: number;
55
+ }>;
56
+ _CACHE_KEY: string;
57
+ _initialized: boolean;
58
+ /**
59
+ * Initialize the memory cache.
60
+ * Loads URL cache from MMKV storage.
61
+ */
62
+ _initCache: () => void;
63
+ /**
64
+ * Save cache to MMKV storage.
65
+ */
66
+ _saveCache: () => void;
67
+ /**
68
+ * Upload an image file to Storage.
69
+ * @param file File to upload (Blob or File object)
70
+ * @param key Path and filename to save as (auto-generated if not specified)
71
+ * @returns Key of the uploaded file
72
+ */
73
+ uploadImage: (file: Blob | File, key?: string) => Promise<string>;
74
+ /**
75
+ * Get the URL of a stored file. (Auto-caching)
76
+ * @param key File key
77
+ * @param options Caching options (forceRefresh: ignore cache and fetch new URL)
78
+ * @returns File URL
79
+ */
80
+ getFileUrl: (key: string, options?: {
81
+ forceRefresh?: boolean;
82
+ }) => Promise<string>;
83
+ /**
84
+ * Delete a stored file.
85
+ * @param key Key of the file to delete
86
+ */
87
+ deleteFile: (key: string) => Promise<void>;
88
+ /**
89
+ * Clear the URL cache.
90
+ */
91
+ clearUrlCache: () => void;
92
+ /**
93
+ * Remove a specific key's URL cache.
94
+ * @param key Key of the URL to remove
95
+ */
96
+ clearUrlCacheForKey: (key: string) => void;
97
+ /**
98
+ * Remove only expired URL caches.
99
+ */
100
+ clearExpiredUrlCache: () => void;
101
+ /**
102
+ * Download an audio file.
103
+ * @param audioKey Key of the audio file to download
104
+ * @returns Local file system path of the downloaded file
105
+ */
106
+ downloadAudioFile: (audioKey: string) => Promise<string>;
107
+ };
108
+ /**
109
+ * Authentication related utilities
110
+ */
111
+ export declare const AuthService: {
112
+ /**
113
+ * Get information about the currently logged-in user.
114
+ */
115
+ getCurrentUserInfo: () => Promise<{
116
+ userId: string;
117
+ username: string;
118
+ }>;
119
+ };
120
+ /**
121
+ * Utility to create a relational query hook.
122
+ * Creates a hook to query related items based on a specific foreign key.
123
+ *
124
+ * @param service Base service object
125
+ * @param relationName Name of the relation (e.g., Daily, User)
126
+ * @param queryName API query name (e.g., listMissionsByDaily)
127
+ * @param idParamName ID parameter name (e.g., dailyId, userId)
128
+ * @returns Relational query hook function
129
+ */
130
+ export declare function createRelationalHook<T extends BaseModel, R extends BaseModel = any>(service: AmplifyDataService<T>, relationName: string, queryName: string, idParamName?: string): (id: string) => ModelHook<T>;