@progressive-development/pd-provider-mock 0.9.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,47 @@
1
+ import { IAuthProvider, AuthUser, UserToken, AuthStateCallback, Unsubscribe } from '@progressive-development/pd-provider-interfaces';
2
+ import { MockUserFixture, MockProviderConfig } from './fixtures.js';
3
+ /**
4
+ * Mock implementation of IAuthProvider
5
+ *
6
+ * Features:
7
+ * - JSON fixture-based user configuration
8
+ * - Optional localStorage persistence
9
+ * - Configurable delays for realistic testing
10
+ * - Multiple user support
11
+ */
12
+ export declare class MockAuthProvider implements IAuthProvider {
13
+ private users;
14
+ private currentUser;
15
+ private currentClaims;
16
+ private listeners;
17
+ private config;
18
+ constructor(users?: MockUserFixture[], config?: MockProviderConfig);
19
+ login(email: string, password: string): Promise<AuthUser>;
20
+ logout(): Promise<void>;
21
+ getCurrentUser(): AuthUser | null;
22
+ isAuthenticated(): boolean;
23
+ getIdToken(forceRefresh?: boolean): Promise<string | null>;
24
+ getIdTokenResult(forceRefresh?: boolean): Promise<UserToken | null>;
25
+ onAuthStateChanged(callback: AuthStateCallback): Unsubscribe;
26
+ sendPasswordResetEmail(email: string): Promise<void>;
27
+ /**
28
+ * Add a user fixture at runtime
29
+ */
30
+ addUser(userFixture: MockUserFixture): void;
31
+ /**
32
+ * Set the current user directly (for testing)
33
+ */
34
+ setCurrentUser(user: AuthUser | null, claims?: Record<string, unknown>): void;
35
+ /**
36
+ * Get all configured users
37
+ */
38
+ getConfiguredUsers(): MockUserFixture[];
39
+ private notifyListeners;
40
+ private delay;
41
+ private log;
42
+ private get storageKey();
43
+ private persistToStorage;
44
+ private restoreFromStorage;
45
+ private clearStorage;
46
+ }
47
+ //# sourceMappingURL=MockAuthProvider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MockAuthProvider.d.ts","sourceRoot":"","sources":["../src/MockAuthProvider.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,aAAa,EACb,QAAQ,EACR,SAAS,EACT,iBAAiB,EACjB,WAAW,EACZ,MAAM,iDAAiD,CAAC;AAEzD,OAAO,KAAK,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAIzE;;;;;;;;GAQG;AACH,qBAAa,gBAAiB,YAAW,aAAa;IACpD,OAAO,CAAC,KAAK,CAAoB;IACjC,OAAO,CAAC,WAAW,CAAyB;IAC5C,OAAO,CAAC,aAAa,CAA+B;IACpD,OAAO,CAAC,SAAS,CAAqC;IACtD,OAAO,CAAC,MAAM,CAAqB;gBAEvB,KAAK,GAAE,eAAe,EAAO,EAAE,MAAM,GAAE,kBAAuB;IAUpE,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC;IAiCzD,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAiB7B,cAAc,IAAI,QAAQ,GAAG,IAAI;IAIjC,eAAe,IAAI,OAAO;IAIpB,UAAU,CAAC,YAAY,UAAQ,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAaxD,gBAAgB,CAAC,YAAY,UAAQ,GAAG,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC;IAoBvE,kBAAkB,CAAC,QAAQ,EAAE,iBAAiB,GAAG,WAAW;IAWtD,sBAAsB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAS1D;;OAEG;IACH,OAAO,CAAC,WAAW,EAAE,eAAe,GAAG,IAAI;IAI3C;;OAEG;IACH,cAAc,CAAC,IAAI,EAAE,QAAQ,GAAG,IAAI,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAM7E;;OAEG;IACH,kBAAkB,IAAI,eAAe,EAAE;IAQvC,OAAO,CAAC,eAAe;YAIT,KAAK;IAOnB,OAAO,CAAC,GAAG;IAMX,OAAO,KAAK,UAAU,GAErB;IAED,OAAO,CAAC,gBAAgB;IAYxB,OAAO,CAAC,kBAAkB;IAc1B,OAAO,CAAC,YAAY;CAOrB"}
@@ -0,0 +1,161 @@
1
+ const DEFAULT_PERSIST_KEY = "pd-mock-auth";
2
+ class MockAuthProvider {
3
+ constructor(users = [], config = {}) {
4
+ this.currentUser = null;
5
+ this.currentClaims = {};
6
+ this.listeners = /* @__PURE__ */ new Set();
7
+ this.users = users;
8
+ this.config = config;
9
+ if (config.persistAuth) {
10
+ this.restoreFromStorage();
11
+ }
12
+ }
13
+ async login(email, password) {
14
+ this.log(`Login attempt for: ${email}`);
15
+ await this.delay();
16
+ const userFixture = this.users.find(
17
+ (u) => u.email === email && u.password === password
18
+ );
19
+ if (!userFixture) {
20
+ const error = new Error("Invalid credentials");
21
+ error.code = "auth/wrong-password";
22
+ throw error;
23
+ }
24
+ this.currentUser = userFixture.user;
25
+ this.currentClaims = userFixture.claims || {};
26
+ if (this.config.persistAuth) {
27
+ this.persistToStorage();
28
+ }
29
+ this.notifyListeners();
30
+ this.log(`Login successful for: ${email}`);
31
+ return this.currentUser;
32
+ }
33
+ async logout() {
34
+ this.log("Logout");
35
+ await this.delay();
36
+ this.currentUser = null;
37
+ this.currentClaims = {};
38
+ if (this.config.persistAuth) {
39
+ this.clearStorage();
40
+ }
41
+ this.notifyListeners();
42
+ }
43
+ getCurrentUser() {
44
+ return this.currentUser;
45
+ }
46
+ isAuthenticated() {
47
+ return this.currentUser !== null;
48
+ }
49
+ async getIdToken(forceRefresh = false) {
50
+ if (!this.currentUser) {
51
+ return null;
52
+ }
53
+ if (forceRefresh) {
54
+ await this.delay(100);
55
+ }
56
+ return `mock-token-${this.currentUser.uid}-${Date.now()}`;
57
+ }
58
+ async getIdTokenResult(forceRefresh = false) {
59
+ if (!this.currentUser) {
60
+ return null;
61
+ }
62
+ if (forceRefresh) {
63
+ await this.delay(100);
64
+ }
65
+ const token = await this.getIdToken();
66
+ const expirationDate = /* @__PURE__ */ new Date();
67
+ expirationDate.setHours(expirationDate.getHours() + 1);
68
+ return {
69
+ token,
70
+ claims: this.currentClaims,
71
+ expirationTime: expirationDate.toISOString()
72
+ };
73
+ }
74
+ onAuthStateChanged(callback) {
75
+ this.listeners.add(callback);
76
+ callback(this.currentUser);
77
+ return () => {
78
+ this.listeners.delete(callback);
79
+ };
80
+ }
81
+ async sendPasswordResetEmail(email) {
82
+ this.log(`Password reset email "sent" to: ${email}`);
83
+ await this.delay();
84
+ }
85
+ // -------------------------------------------------------------------------
86
+ // Mock-specific Methods
87
+ // -------------------------------------------------------------------------
88
+ /**
89
+ * Add a user fixture at runtime
90
+ */
91
+ addUser(userFixture) {
92
+ this.users.push(userFixture);
93
+ }
94
+ /**
95
+ * Set the current user directly (for testing)
96
+ */
97
+ setCurrentUser(user, claims) {
98
+ this.currentUser = user;
99
+ this.currentClaims = claims || {};
100
+ this.notifyListeners();
101
+ }
102
+ /**
103
+ * Get all configured users
104
+ */
105
+ getConfiguredUsers() {
106
+ return [...this.users];
107
+ }
108
+ // -------------------------------------------------------------------------
109
+ // Private Helpers
110
+ // -------------------------------------------------------------------------
111
+ notifyListeners() {
112
+ this.listeners.forEach((callback) => callback(this.currentUser));
113
+ }
114
+ async delay(ms) {
115
+ const delayMs = ms ?? this.config.defaultDelay ?? 500;
116
+ if (delayMs > 0) {
117
+ await new Promise((resolve) => setTimeout(resolve, delayMs));
118
+ }
119
+ }
120
+ log(message) {
121
+ if (this.config.logging) {
122
+ console.log(`[MockAuth] ${message}`);
123
+ }
124
+ }
125
+ get storageKey() {
126
+ return this.config.persistAuthKey || DEFAULT_PERSIST_KEY;
127
+ }
128
+ persistToStorage() {
129
+ try {
130
+ const data = {
131
+ user: this.currentUser,
132
+ claims: this.currentClaims
133
+ };
134
+ localStorage.setItem(this.storageKey, JSON.stringify(data));
135
+ } catch (e) {
136
+ this.log(`Failed to persist auth: ${e}`);
137
+ }
138
+ }
139
+ restoreFromStorage() {
140
+ try {
141
+ const stored = localStorage.getItem(this.storageKey);
142
+ if (stored) {
143
+ const data = JSON.parse(stored);
144
+ this.currentUser = data.user;
145
+ this.currentClaims = data.claims || {};
146
+ this.log(`Restored auth from storage: ${this.currentUser?.email}`);
147
+ }
148
+ } catch (e) {
149
+ this.log(`Failed to restore auth: ${e}`);
150
+ }
151
+ }
152
+ clearStorage() {
153
+ try {
154
+ localStorage.removeItem(this.storageKey);
155
+ } catch (e) {
156
+ this.log(`Failed to clear auth storage: ${e}`);
157
+ }
158
+ }
159
+ }
160
+
161
+ export { MockAuthProvider };
@@ -0,0 +1,44 @@
1
+ import { IDatabaseProvider, QueryConstraint, DocumentSnapshot, CollectionCallback, Unsubscribe } from '@progressive-development/pd-provider-interfaces';
2
+ import { MockDatabaseCollection, MockDatabaseDocument, MockProviderConfig } from './fixtures.js';
3
+ /**
4
+ * Mock implementation of IDatabaseProvider
5
+ *
6
+ * Features:
7
+ * - JSON fixture-based collection data
8
+ * - In-memory document operations
9
+ * - Collection listeners with real-time updates
10
+ * - Query constraint filtering
11
+ */
12
+ export declare class MockDatabaseProvider implements IDatabaseProvider {
13
+ private collections;
14
+ private subscriptions;
15
+ private config;
16
+ constructor(fixtures?: MockDatabaseCollection[], config?: MockProviderConfig);
17
+ onCollection<T = unknown>(collectionPath: string, callback: CollectionCallback<T>, constraints?: QueryConstraint[]): Unsubscribe;
18
+ getDocument<T = unknown>(collectionPath: string, documentId: string): Promise<DocumentSnapshot<T>>;
19
+ setDocument<T = unknown>(collectionPath: string, documentId: string, data: T): Promise<void>;
20
+ updateDocument(collectionPath: string, documentId: string, data: Record<string, unknown>): Promise<void>;
21
+ deleteDocument(collectionPath: string, documentId: string): Promise<void>;
22
+ /**
23
+ * Add a collection fixture at runtime
24
+ */
25
+ addCollection(path: string, documents: MockDatabaseDocument[]): void;
26
+ /**
27
+ * Clear a collection
28
+ */
29
+ clearCollection(path: string): void;
30
+ /**
31
+ * Clear all collections
32
+ */
33
+ clearAllCollections(): void;
34
+ /**
35
+ * Get all documents in a collection (without filtering)
36
+ */
37
+ getAllDocuments<T>(collectionPath: string): MockDatabaseDocument<T>[];
38
+ private getFilteredDocuments;
39
+ private matchesConstraints;
40
+ private notifySubscribers;
41
+ private delay;
42
+ private log;
43
+ }
44
+ //# sourceMappingURL=MockDatabaseProvider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MockDatabaseProvider.d.ts","sourceRoot":"","sources":["../src/MockDatabaseProvider.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,iBAAiB,EACjB,eAAe,EACf,gBAAgB,EAChB,kBAAkB,EAClB,WAAW,EACZ,MAAM,iDAAiD,CAAC;AAEzD,OAAO,KAAK,EACV,sBAAsB,EACtB,oBAAoB,EACpB,kBAAkB,EACnB,MAAM,eAAe,CAAC;AAWvB;;;;;;;;GAQG;AACH,qBAAa,oBAAqB,YAAW,iBAAiB;IAC5D,OAAO,CAAC,WAAW,CAAkD;IACrE,OAAO,CAAC,aAAa,CAAmD;IACxE,OAAO,CAAC,MAAM,CAAqB;gBAGjC,QAAQ,GAAE,sBAAsB,EAAO,EACvC,MAAM,GAAE,kBAAuB;IAUjC,YAAY,CAAC,CAAC,GAAG,OAAO,EACtB,cAAc,EAAE,MAAM,EACtB,QAAQ,EAAE,kBAAkB,CAAC,CAAC,CAAC,EAC/B,WAAW,CAAC,EAAE,eAAe,EAAE,GAC9B,WAAW;IAqBR,WAAW,CAAC,CAAC,GAAG,OAAO,EAC3B,cAAc,EAAE,MAAM,EACtB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC;IAezB,WAAW,CAAC,CAAC,GAAG,OAAO,EAC3B,cAAc,EAAE,MAAM,EACtB,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,CAAC,GACN,OAAO,CAAC,IAAI,CAAC;IAuBV,cAAc,CAClB,cAAc,EAAE,MAAM,EACtB,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5B,OAAO,CAAC,IAAI,CAAC;IAsBV,cAAc,CAAC,cAAc,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAuB/E;;OAEG;IACH,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,oBAAoB,EAAE,GAAG,IAAI;IAKpE;;OAEG;IACH,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAKnC;;OAEG;IACH,mBAAmB,IAAI,IAAI;IAM3B;;OAEG;IACH,eAAe,CAAC,CAAC,EAAE,cAAc,EAAE,MAAM,GAAG,oBAAoB,CAAC,CAAC,CAAC,EAAE;IAQrE,OAAO,CAAC,oBAAoB;IAoB5B,OAAO,CAAC,kBAAkB;IAyD1B,OAAO,CAAC,iBAAiB;YAYX,KAAK;IAOnB,OAAO,CAAC,GAAG;CAKZ"}
@@ -0,0 +1,196 @@
1
+ class MockDatabaseProvider {
2
+ constructor(fixtures = [], config = {}) {
3
+ this.collections = /* @__PURE__ */ new Map();
4
+ this.subscriptions = /* @__PURE__ */ new Set();
5
+ this.config = config;
6
+ for (const fixture of fixtures) {
7
+ this.collections.set(fixture.path, [...fixture.documents]);
8
+ }
9
+ }
10
+ onCollection(collectionPath, callback, constraints) {
11
+ this.log(`Subscribing to collection: ${collectionPath}`);
12
+ const subscription = {
13
+ path: collectionPath,
14
+ callback,
15
+ constraints
16
+ };
17
+ this.subscriptions.add(subscription);
18
+ const documents = this.getFilteredDocuments(collectionPath, constraints);
19
+ callback(documents);
20
+ return () => {
21
+ this.subscriptions.delete(subscription);
22
+ this.log(`Unsubscribed from collection: ${collectionPath}`);
23
+ };
24
+ }
25
+ async getDocument(collectionPath, documentId) {
26
+ this.log(`Getting document: ${collectionPath}/${documentId}`);
27
+ await this.delay();
28
+ const collection = this.collections.get(collectionPath) || [];
29
+ const doc = collection.find((d) => d.id === documentId);
30
+ return {
31
+ id: documentId,
32
+ data: doc?.data ?? {},
33
+ exists: !!doc
34
+ };
35
+ }
36
+ async setDocument(collectionPath, documentId, data) {
37
+ this.log(`Setting document: ${collectionPath}/${documentId}`);
38
+ await this.delay();
39
+ let collection = this.collections.get(collectionPath);
40
+ if (!collection) {
41
+ collection = [];
42
+ this.collections.set(collectionPath, collection);
43
+ }
44
+ const existingIndex = collection.findIndex((d) => d.id === documentId);
45
+ if (existingIndex >= 0) {
46
+ collection[existingIndex] = { id: documentId, data };
47
+ } else {
48
+ collection.push({ id: documentId, data });
49
+ }
50
+ this.notifySubscribers(collectionPath);
51
+ }
52
+ async updateDocument(collectionPath, documentId, data) {
53
+ this.log(`Updating document: ${collectionPath}/${documentId}`);
54
+ await this.delay();
55
+ const collection = this.collections.get(collectionPath);
56
+ if (!collection) {
57
+ throw new Error(`Collection not found: ${collectionPath}`);
58
+ }
59
+ const doc = collection.find((d) => d.id === documentId);
60
+ if (!doc) {
61
+ throw new Error(`Document not found: ${collectionPath}/${documentId}`);
62
+ }
63
+ doc.data = { ...doc.data, ...data };
64
+ this.notifySubscribers(collectionPath);
65
+ }
66
+ async deleteDocument(collectionPath, documentId) {
67
+ this.log(`Deleting document: ${collectionPath}/${documentId}`);
68
+ await this.delay();
69
+ const collection = this.collections.get(collectionPath);
70
+ if (!collection) {
71
+ return;
72
+ }
73
+ const index = collection.findIndex((d) => d.id === documentId);
74
+ if (index >= 0) {
75
+ collection.splice(index, 1);
76
+ }
77
+ this.notifySubscribers(collectionPath);
78
+ }
79
+ // -------------------------------------------------------------------------
80
+ // Mock-specific Methods
81
+ // -------------------------------------------------------------------------
82
+ /**
83
+ * Add a collection fixture at runtime
84
+ */
85
+ addCollection(path, documents) {
86
+ this.collections.set(path, [...documents]);
87
+ this.notifySubscribers(path);
88
+ }
89
+ /**
90
+ * Clear a collection
91
+ */
92
+ clearCollection(path) {
93
+ this.collections.delete(path);
94
+ this.notifySubscribers(path);
95
+ }
96
+ /**
97
+ * Clear all collections
98
+ */
99
+ clearAllCollections() {
100
+ const paths = [...this.collections.keys()];
101
+ this.collections.clear();
102
+ paths.forEach((path) => this.notifySubscribers(path));
103
+ }
104
+ /**
105
+ * Get all documents in a collection (without filtering)
106
+ */
107
+ getAllDocuments(collectionPath) {
108
+ return this.collections.get(collectionPath) || [];
109
+ }
110
+ // -------------------------------------------------------------------------
111
+ // Private Helpers
112
+ // -------------------------------------------------------------------------
113
+ getFilteredDocuments(collectionPath, constraints) {
114
+ let documents = this.collections.get(collectionPath) || [];
115
+ if (constraints && constraints.length > 0) {
116
+ documents = documents.filter(
117
+ (doc) => this.matchesConstraints(doc.data, constraints)
118
+ );
119
+ }
120
+ return documents.map((doc) => ({
121
+ id: doc.id,
122
+ data: doc.data,
123
+ exists: true
124
+ }));
125
+ }
126
+ matchesConstraints(data, constraints) {
127
+ for (const constraint of constraints) {
128
+ if (constraint.type !== "where") {
129
+ continue;
130
+ }
131
+ const fieldValue = data[constraint.field];
132
+ const targetValue = constraint.value;
133
+ let matches = false;
134
+ switch (constraint.operator) {
135
+ case "==":
136
+ matches = fieldValue === targetValue;
137
+ break;
138
+ case "!=":
139
+ matches = fieldValue !== targetValue;
140
+ break;
141
+ case "<":
142
+ matches = fieldValue < targetValue;
143
+ break;
144
+ case "<=":
145
+ matches = fieldValue <= targetValue;
146
+ break;
147
+ case ">":
148
+ matches = fieldValue > targetValue;
149
+ break;
150
+ case ">=":
151
+ matches = fieldValue >= targetValue;
152
+ break;
153
+ case "array-contains":
154
+ matches = Array.isArray(fieldValue) && fieldValue.includes(targetValue);
155
+ break;
156
+ case "array-contains-any":
157
+ matches = Array.isArray(fieldValue) && Array.isArray(targetValue) && targetValue.some((v) => fieldValue.includes(v));
158
+ break;
159
+ case "in":
160
+ matches = Array.isArray(targetValue) && targetValue.includes(fieldValue);
161
+ break;
162
+ case "not-in":
163
+ matches = Array.isArray(targetValue) && !targetValue.includes(fieldValue);
164
+ break;
165
+ }
166
+ if (!matches) {
167
+ return false;
168
+ }
169
+ }
170
+ return true;
171
+ }
172
+ notifySubscribers(collectionPath) {
173
+ for (const subscription of this.subscriptions) {
174
+ if (subscription.path === collectionPath) {
175
+ const documents = this.getFilteredDocuments(
176
+ collectionPath,
177
+ subscription.constraints
178
+ );
179
+ subscription.callback(documents);
180
+ }
181
+ }
182
+ }
183
+ async delay() {
184
+ const delayMs = this.config.defaultDelay ?? 100;
185
+ if (delayMs > 0) {
186
+ await new Promise((resolve) => setTimeout(resolve, delayMs));
187
+ }
188
+ }
189
+ log(message) {
190
+ if (this.config.logging) {
191
+ console.log(`[MockDatabase] ${message}`);
192
+ }
193
+ }
194
+ }
195
+
196
+ export { MockDatabaseProvider };
@@ -0,0 +1,43 @@
1
+ import { IFunctionProvider, FunctionResult } from '@progressive-development/pd-provider-interfaces';
2
+ import { MockFunctionFixture, MockProviderConfig } from './fixtures.js';
3
+ /**
4
+ * Mock implementation of IFunctionProvider
5
+ *
6
+ * Features:
7
+ * - JSON fixture-based function responses
8
+ * - Input matching for conditional responses
9
+ * - Configurable delays
10
+ * - Error simulation
11
+ */
12
+ export declare class MockFunctionProvider implements IFunctionProvider {
13
+ private fixtures;
14
+ private config;
15
+ private region;
16
+ constructor(fixtures?: MockFunctionFixture[], config?: MockProviderConfig);
17
+ callFunction(functionName: string, data: unknown): Promise<FunctionResult>;
18
+ setRegion(region: string): void;
19
+ /**
20
+ * Add a function fixture at runtime
21
+ */
22
+ addFixture(fixture: MockFunctionFixture): void;
23
+ /**
24
+ * Remove all fixtures for a function
25
+ */
26
+ removeFixtures(functionName: string): void;
27
+ /**
28
+ * Clear all fixtures
29
+ */
30
+ clearFixtures(): void;
31
+ /**
32
+ * Set fixtures (replace all)
33
+ */
34
+ setFixtures(fixtures: MockFunctionFixture[]): void;
35
+ /**
36
+ * Get configured region
37
+ */
38
+ getRegion(): string;
39
+ private findMatchingFixture;
40
+ private matchesInput;
41
+ private log;
42
+ }
43
+ //# sourceMappingURL=MockFunctionProvider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MockFunctionProvider.d.ts","sourceRoot":"","sources":["../src/MockFunctionProvider.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,iBAAiB,EACjB,cAAc,EACf,MAAM,iDAAiD,CAAC;AAEzD,OAAO,KAAK,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAE7E;;;;;;;;GAQG;AACH,qBAAa,oBAAqB,YAAW,iBAAiB;IAC5D,OAAO,CAAC,QAAQ,CAAwB;IACxC,OAAO,CAAC,MAAM,CAAqB;IACnC,OAAO,CAAC,MAAM,CAAiB;gBAEnB,QAAQ,GAAE,mBAAmB,EAAO,EAAE,MAAM,GAAE,kBAAuB;IAK3E,YAAY,CAAC,YAAY,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,cAAc,CAAC;IA8BhF,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAS/B;;OAEG;IACH,UAAU,CAAC,OAAO,EAAE,mBAAmB,GAAG,IAAI;IAI9C;;OAEG;IACH,cAAc,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI;IAI1C;;OAEG;IACH,aAAa,IAAI,IAAI;IAIrB;;OAEG;IACH,WAAW,CAAC,QAAQ,EAAE,mBAAmB,EAAE,GAAG,IAAI;IAIlD;;OAEG;IACH,SAAS,IAAI,MAAM;IAQnB,OAAO,CAAC,mBAAmB;IA6B3B,OAAO,CAAC,YAAY;IAoBpB,OAAO,CAAC,GAAG;CASZ"}
@@ -0,0 +1,108 @@
1
+ class MockFunctionProvider {
2
+ constructor(fixtures = [], config = {}) {
3
+ this.region = "mock-region";
4
+ this.fixtures = fixtures;
5
+ this.config = config;
6
+ }
7
+ async callFunction(functionName, data) {
8
+ this.log(`Calling function: ${functionName}`, data);
9
+ const fixture = this.findMatchingFixture(functionName, data);
10
+ if (!fixture) {
11
+ this.log(`No fixture found for: ${functionName}`);
12
+ throw new Error(`Mock: No fixture configured for function "${functionName}"`);
13
+ }
14
+ const delay = fixture.response.delay ?? this.config.defaultDelay ?? 500;
15
+ if (delay > 0) {
16
+ await new Promise((resolve) => setTimeout(resolve, delay));
17
+ }
18
+ if (fixture.response.error) {
19
+ const error = new Error(fixture.response.error.message);
20
+ if (fixture.response.error.code) {
21
+ error.code = fixture.response.error.code;
22
+ }
23
+ throw error;
24
+ }
25
+ this.log(`Returning result for: ${functionName}`, fixture.response.result);
26
+ return fixture.response.result;
27
+ }
28
+ setRegion(region) {
29
+ this.region = region;
30
+ this.log(`Region set to: ${region}`);
31
+ }
32
+ // -------------------------------------------------------------------------
33
+ // Mock-specific Methods
34
+ // -------------------------------------------------------------------------
35
+ /**
36
+ * Add a function fixture at runtime
37
+ */
38
+ addFixture(fixture) {
39
+ this.fixtures.push(fixture);
40
+ }
41
+ /**
42
+ * Remove all fixtures for a function
43
+ */
44
+ removeFixtures(functionName) {
45
+ this.fixtures = this.fixtures.filter((f) => f.name !== functionName);
46
+ }
47
+ /**
48
+ * Clear all fixtures
49
+ */
50
+ clearFixtures() {
51
+ this.fixtures = [];
52
+ }
53
+ /**
54
+ * Set fixtures (replace all)
55
+ */
56
+ setFixtures(fixtures) {
57
+ this.fixtures = fixtures;
58
+ }
59
+ /**
60
+ * Get configured region
61
+ */
62
+ getRegion() {
63
+ return this.region;
64
+ }
65
+ // -------------------------------------------------------------------------
66
+ // Private Helpers
67
+ // -------------------------------------------------------------------------
68
+ findMatchingFixture(functionName, data) {
69
+ const matchingByName = this.fixtures.filter((f) => f.name === functionName);
70
+ if (matchingByName.length === 0) {
71
+ return void 0;
72
+ }
73
+ if (matchingByName.length === 1 && !matchingByName[0].inputMatcher) {
74
+ return matchingByName[0];
75
+ }
76
+ const withMatcher = matchingByName.filter((f) => f.inputMatcher);
77
+ for (const fixture of withMatcher) {
78
+ if (this.matchesInput(fixture.inputMatcher, data)) {
79
+ return fixture;
80
+ }
81
+ }
82
+ const withoutMatcher = matchingByName.find((f) => !f.inputMatcher);
83
+ return withoutMatcher;
84
+ }
85
+ matchesInput(matcher, data) {
86
+ if (!data || typeof data !== "object") {
87
+ return false;
88
+ }
89
+ const dataObj = data;
90
+ for (const [key, value] of Object.entries(matcher)) {
91
+ if (dataObj[key] !== value) {
92
+ return false;
93
+ }
94
+ }
95
+ return true;
96
+ }
97
+ log(message, data) {
98
+ if (this.config.logging) {
99
+ if (data !== void 0) {
100
+ console.log(`[MockFunction] ${message}`, data);
101
+ } else {
102
+ console.log(`[MockFunction] ${message}`);
103
+ }
104
+ }
105
+ }
106
+ }
107
+
108
+ export { MockFunctionProvider };
@@ -0,0 +1,43 @@
1
+ import { IStorageProvider, UploadFileRequest, UploadResult, StorageDocument, ListFilesOptions, GetFileOptions } from '@progressive-development/pd-provider-interfaces';
2
+ import { MockStorageFixture, MockStorageFile, MockProviderConfig } from './fixtures.js';
3
+ /**
4
+ * Mock implementation of IStorageProvider
5
+ *
6
+ * Features:
7
+ * - JSON fixture-based file configuration
8
+ * - In-memory upload storage
9
+ * - Configurable delays
10
+ */
11
+ export declare class MockStorageProvider implements IStorageProvider {
12
+ private fixtures;
13
+ private config;
14
+ /** In-memory storage for uploaded files */
15
+ private uploadedFiles;
16
+ constructor(fixtures?: MockStorageFixture[], config?: MockProviderConfig);
17
+ uploadFile(request: UploadFileRequest): Promise<UploadResult>;
18
+ downloadFile(options: GetFileOptions): Promise<string>;
19
+ deleteFile(options: GetFileOptions): Promise<void>;
20
+ listFiles(options: ListFilesOptions): Promise<StorageDocument[]>;
21
+ getFile(options: GetFileOptions): Promise<StorageDocument | null>;
22
+ /**
23
+ * Add a storage fixture at runtime
24
+ */
25
+ addFixture(fixture: MockStorageFixture): void;
26
+ /**
27
+ * Clear all uploaded files (in-memory)
28
+ */
29
+ clearUploads(): void;
30
+ /**
31
+ * Get all uploaded files
32
+ */
33
+ getUploadedFiles(): Map<string, MockStorageFile>;
34
+ /**
35
+ * Set fixtures (replace all)
36
+ */
37
+ setFixtures(fixtures: MockStorageFixture[]): void;
38
+ private buildFilePath;
39
+ private findFileInFixtures;
40
+ private delay;
41
+ private log;
42
+ }
43
+ //# sourceMappingURL=MockStorageProvider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MockStorageProvider.d.ts","sourceRoot":"","sources":["../src/MockStorageProvider.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,gBAAgB,EAChB,iBAAiB,EACjB,YAAY,EACZ,eAAe,EACf,gBAAgB,EAChB,cAAc,EACf,MAAM,iDAAiD,CAAC;AAEzD,OAAO,KAAK,EAAE,kBAAkB,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAE7F;;;;;;;GAOG;AACH,qBAAa,mBAAoB,YAAW,gBAAgB;IAC1D,OAAO,CAAC,QAAQ,CAAuB;IACvC,OAAO,CAAC,MAAM,CAAqB;IACnC,2CAA2C;IAC3C,OAAO,CAAC,aAAa,CAA2C;gBAEpD,QAAQ,GAAE,kBAAkB,EAAO,EAAE,MAAM,GAAE,kBAAuB;IAK1E,UAAU,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,YAAY,CAAC;IAwC7D,YAAY,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC;IA4BtD,UAAU,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAkBlD,SAAS,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC;IA8ChE,OAAO,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC;IA2BvE;;OAEG;IACH,UAAU,CAAC,OAAO,EAAE,kBAAkB,GAAG,IAAI;IAI7C;;OAEG;IACH,YAAY,IAAI,IAAI;IAIpB;;OAEG;IACH,gBAAgB,IAAI,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC;IAIhD;;OAEG;IACH,WAAW,CAAC,QAAQ,EAAE,kBAAkB,EAAE,GAAG,IAAI;IAQjD,OAAO,CAAC,aAAa;IAcrB,OAAO,CAAC,kBAAkB;YAmBZ,KAAK;IAOnB,OAAO,CAAC,GAAG;CAKZ"}