@honuware/ui 0.1.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,325 @@
1
+ import { of, throwError } from 'rxjs';
2
+ import { provideHonuwareAccess } from '@honuware/ui/access';
3
+
4
+ const EMPTY_SCHEMA = {
5
+ root_tables: [],
6
+ nested_tables: [],
7
+ tables: [],
8
+ display_templates: {},
9
+ fk_picker_preload_threshold: 50,
10
+ };
11
+ /**
12
+ * In-memory, schema-driven {@link CrudAccess} for library/consumer tests. Honors
13
+ * a supplied {@link DatabaseSchema} (columns, primary keys, FK display
14
+ * templates) and keeps rows per table. Deterministic and dependency-free — the
15
+ * framework counterpart to the app's ServerAccessMock, but only the 12 generic
16
+ * CRUD methods.
17
+ */
18
+ class MockCrudAccess {
19
+ schema;
20
+ rows = new Map();
21
+ pkCounters = new Map();
22
+ constructor(options = {}) {
23
+ this.schema = options.schema ?? EMPTY_SCHEMA;
24
+ for (const [table, rows] of Object.entries(options.seedRows ?? {})) {
25
+ this.rows.set(table, rows.map((row) => ({ ...row })));
26
+ }
27
+ }
28
+ getDbSchema() {
29
+ return of(this.schema);
30
+ }
31
+ getTableRows(tableName) {
32
+ return of(this.toDataResults(tableName, this.tableRows(tableName)));
33
+ }
34
+ getRowsByColumn(tableName, columnName, ascending, pageSize, pageNumber) {
35
+ const sorted = this.sorted(this.tableRows(tableName), columnName, ascending);
36
+ return of(this.paginate(tableName, sorted, pageSize, pageNumber));
37
+ }
38
+ getFilteredTableRows(tableName, columnName, ascending, pageSize, page, filterPairs) {
39
+ const filtered = this.applyFilters(this.tableRows(tableName), filterPairs);
40
+ return of(this.paginate(tableName, this.sorted(filtered, columnName, ascending), pageSize, page));
41
+ }
42
+ getRow(tableName, columnName, columnValue) {
43
+ const matches = this.tableRows(tableName).filter((row) => row[columnName] === columnValue);
44
+ return of(this.toDataResults(tableName, matches));
45
+ }
46
+ getRowByValues(tableName, filterPairs) {
47
+ return of(this.toDataResults(tableName, this.applyFilters(this.tableRows(tableName), filterPairs)));
48
+ }
49
+ addItem(body) {
50
+ this.insert(body.table_name, body.value);
51
+ return of(void 0);
52
+ }
53
+ addItemFetchPrimaryKey(body) {
54
+ return of(this.insert(body.table_name, body.value));
55
+ }
56
+ updateItem(body) {
57
+ for (const row of this.tableRows(body.table_name)) {
58
+ if (row[body.column_name] === body.column_value) {
59
+ Object.assign(row, body.value);
60
+ }
61
+ }
62
+ return of(void 0);
63
+ }
64
+ deleteItem(tableName, columnName, columnValue) {
65
+ this.rows.set(tableName, this.tableRows(tableName).filter((row) => row[columnName] !== columnValue));
66
+ return of(void 0);
67
+ }
68
+ getFkOptions(tableName, searchText, pageSize) {
69
+ const primaryKey = this.tableSchema(tableName)?.primary_key ?? 'id';
70
+ const template = this.schema.display_templates[tableName];
71
+ const options = this.tableRows(tableName).map((row) => ({
72
+ value: row[primaryKey] ?? '',
73
+ display: this.renderTemplate(template, row) || (row[primaryKey] ?? ''),
74
+ }));
75
+ const search = searchText.toLowerCase();
76
+ const matching = search ? options.filter((o) => o.display.toLowerCase().includes(search)) : options;
77
+ return of({ total_count: matching.length, options: matching.slice(0, pageSize) });
78
+ }
79
+ resolveFkDisplay(parentTableName, values) {
80
+ const primaryKey = this.tableSchema(parentTableName)?.primary_key ?? 'id';
81
+ const template = this.schema.display_templates[parentTableName];
82
+ const resolved = {};
83
+ for (const value of values) {
84
+ const row = this.tableRows(parentTableName).find((r) => r[primaryKey] === value);
85
+ resolved[value] = row ? this.renderTemplate(template, row) || value : value;
86
+ }
87
+ return of({ resolved });
88
+ }
89
+ // --- internals ---
90
+ tableSchema(tableName) {
91
+ return this.schema.tables.find((t) => t.table_name === tableName);
92
+ }
93
+ columnNames(tableName) {
94
+ const table = this.tableSchema(tableName);
95
+ if (table)
96
+ return table.columns.map((c) => c.column_name);
97
+ const rows = this.rows.get(tableName) ?? [];
98
+ return rows.length ? Object.keys(rows[0]) : [];
99
+ }
100
+ tableRows(tableName) {
101
+ let rows = this.rows.get(tableName);
102
+ if (!rows) {
103
+ rows = [];
104
+ this.rows.set(tableName, rows);
105
+ }
106
+ return rows;
107
+ }
108
+ toDataResults(tableName, rows) {
109
+ const columns = this.columnNames(tableName);
110
+ return {
111
+ sortedColumnNames: columns,
112
+ dataTable: rows.map((row) => columns.map((c) => row[c] ?? '')),
113
+ };
114
+ }
115
+ insert(tableName, value) {
116
+ const rows = this.tableRows(tableName);
117
+ const primaryKey = this.tableSchema(tableName)?.primary_key ?? 'id';
118
+ const row = { ...value };
119
+ if (!row[primaryKey])
120
+ row[primaryKey] = this.nextPrimaryKey(tableName, rows, primaryKey);
121
+ rows.push(row);
122
+ return row[primaryKey];
123
+ }
124
+ nextPrimaryKey(tableName, rows, primaryKey) {
125
+ let counter = this.pkCounters.get(tableName);
126
+ if (counter === undefined) {
127
+ counter = rows.reduce((max, row) => Math.max(max, Number(row[primaryKey]) || 0), 0);
128
+ }
129
+ counter += 1;
130
+ this.pkCounters.set(tableName, counter);
131
+ return String(counter);
132
+ }
133
+ applyFilters(rows, filterPairs) {
134
+ if (!filterPairs.length)
135
+ return rows;
136
+ return rows.filter((row) => filterPairs.every((f) => row[f.column_name] === f.column_value));
137
+ }
138
+ sorted(rows, columnName, ascending) {
139
+ if (!columnName)
140
+ return rows;
141
+ const sorted = [...rows].sort((a, b) => (a[columnName] ?? '').localeCompare(b[columnName] ?? ''));
142
+ return ascending ? sorted : sorted.reverse();
143
+ }
144
+ paginate(tableName, rows, pageSize, page) {
145
+ const pageRows = pageSize > 0 ? rows.slice(page * pageSize, page * pageSize + pageSize) : rows;
146
+ return { ...this.toDataResults(tableName, pageRows), totalCount: rows.length };
147
+ }
148
+ renderTemplate(template, row) {
149
+ if (!template)
150
+ return '';
151
+ let result = template;
152
+ for (const [key, value] of Object.entries(row)) {
153
+ result = result.split(`{${key}}`).join(value);
154
+ }
155
+ return result;
156
+ }
157
+ }
158
+
159
+ const unauthorized = () => throwError(() => ({ status: 401, message: 'Unauthorized' }));
160
+ /**
161
+ * In-memory {@link AuthAccess} session simulator for tests. Tracks registered
162
+ * users, a current session, and a "remember me" token. `me()`/`getUserInfo()`
163
+ * reject with a 401-shaped error when no session is active — enough to exercise
164
+ * AuthService's login / silent-reauth (me → remember → me) flows.
165
+ */
166
+ class MockAuthAccess {
167
+ users = new Map();
168
+ currentEmail = null;
169
+ rememberedEmail = null;
170
+ personIdCounter = 0;
171
+ constructor(options = {}) {
172
+ for (const seed of options.users ?? []) {
173
+ this.users.set(seed.user.email, { user: { ...seed.user }, password: seed.password });
174
+ this.personIdCounter = Math.max(this.personIdCounter, seed.user.person_id);
175
+ }
176
+ }
177
+ register(firstName, lastName, email, password) {
178
+ this.users.set(email, {
179
+ user: {
180
+ person_id: ++this.personIdCounter,
181
+ first_name: firstName,
182
+ last_name: lastName,
183
+ email,
184
+ created_at: '0',
185
+ roles: [],
186
+ permissions: [],
187
+ must_change_password: false,
188
+ },
189
+ password,
190
+ });
191
+ return of(void 0);
192
+ }
193
+ verify() {
194
+ // The mock treats every verification link as valid.
195
+ return of(void 0);
196
+ }
197
+ login(loginInfo) {
198
+ const stored = this.users.get(loginInfo.email);
199
+ if (!stored || stored.password !== loginInfo.password)
200
+ return unauthorized();
201
+ this.currentEmail = loginInfo.email;
202
+ this.rememberedEmail = loginInfo.remember ? loginInfo.email : null;
203
+ return of(void 0);
204
+ }
205
+ logout() {
206
+ this.currentEmail = null;
207
+ this.rememberedEmail = null;
208
+ return of(void 0);
209
+ }
210
+ me() {
211
+ return this.currentEmail ? of(void 0) : unauthorized();
212
+ }
213
+ remember() {
214
+ if (!this.rememberedEmail)
215
+ return unauthorized();
216
+ this.currentEmail = this.rememberedEmail;
217
+ return of(void 0);
218
+ }
219
+ getUserInfo() {
220
+ const stored = this.currentEmail ? this.users.get(this.currentEmail) : undefined;
221
+ return stored ? of({ ...stored.user }) : unauthorized();
222
+ }
223
+ setUserInfo(userInfo) {
224
+ const email = this.currentEmail;
225
+ const stored = email ? this.users.get(email) : undefined;
226
+ if (!email || !stored)
227
+ return unauthorized();
228
+ stored.user = { ...stored.user, ...userInfo };
229
+ if (userInfo.email !== email) {
230
+ this.users.delete(email);
231
+ this.users.set(userInfo.email, stored);
232
+ this.currentEmail = userInfo.email;
233
+ }
234
+ return of(void 0);
235
+ }
236
+ updateUserPassword(passwordInfo) {
237
+ const stored = this.currentEmail ? this.users.get(this.currentEmail) : undefined;
238
+ if (!stored || stored.password !== passwordInfo.old_password)
239
+ return unauthorized();
240
+ stored.password = passwordInfo.new_password;
241
+ return of(void 0);
242
+ }
243
+ /**
244
+ * Test helper (not part of AuthAccess): drop the active session but keep the
245
+ * "remember me" token — so a subsequent `me()` rejects and `remember()` can
246
+ * restore the session, exercising the silent-reauth path (me → remember → me).
247
+ */
248
+ expireSession() {
249
+ this.currentEmail = null;
250
+ }
251
+ }
252
+
253
+ const photoInfo = (id, type) => ({
254
+ source_photo_id: id,
255
+ type,
256
+ width: 300,
257
+ height: 300,
258
+ created_at_us: 0,
259
+ });
260
+ /**
261
+ * In-memory {@link PhotoAccess} simulator for tests. Remembers which table rows
262
+ * have a photo so `hasPhoto()` reflects prior `uploadPhoto()`/`deletePhoto()`
263
+ * calls. Ignores the image bytes (mocks the server's re-encode + store).
264
+ */
265
+ class MockPhotoAccess {
266
+ photos = new Set();
267
+ nextId = 1;
268
+ uploadPhoto(tableName, tableItemId, imageData, imageType) {
269
+ this.photos.add(this.key(tableName, tableItemId));
270
+ return of(photoInfo(this.nextId++, imageType));
271
+ }
272
+ uploadUserPhoto(imageData, imageType) {
273
+ return of(photoInfo(this.nextId++, imageType));
274
+ }
275
+ deletePhoto(tableName, tableItemId) {
276
+ this.photos.delete(this.key(tableName, tableItemId));
277
+ return of(void 0);
278
+ }
279
+ hasPhoto(tableName, tableItemId) {
280
+ return of({ has_photo: this.photos.has(this.key(tableName, tableItemId)) });
281
+ }
282
+ key(tableName, tableItemId) {
283
+ return `${tableName}:${tableItemId}`;
284
+ }
285
+ }
286
+
287
+ /**
288
+ * Test wiring: creates the three in-memory framework mocks and provides them for
289
+ * the `HONUWARE_*_ACCESS` tokens (mock mode of `provideHonuwareAccess`). Pass a
290
+ * `capture` callback to grab the mock instances for seeding/assertions.
291
+ *
292
+ * @example
293
+ * let mocks: HonuwareAccessMocks;
294
+ * TestBed.configureTestingModule({
295
+ * providers: [provideHonuwareAccessMock({ crud: { schema } }, (m) => (mocks = m))],
296
+ * });
297
+ */
298
+ function provideHonuwareAccessMock(options = {}, capture) {
299
+ const mocks = {
300
+ crud: new MockCrudAccess(options.crud),
301
+ auth: new MockAuthAccess(options.auth),
302
+ photo: new MockPhotoAccess(),
303
+ };
304
+ capture?.(mocks);
305
+ return provideHonuwareAccess({
306
+ mode: 'mock',
307
+ crud: mocks.crud,
308
+ auth: mocks.auth,
309
+ photo: mocks.photo,
310
+ });
311
+ }
312
+
313
+ /*
314
+ * @honuware/ui/testing — fresh, minimal in-memory framework mocks for
315
+ * library/consumer tests: a schema-driven CrudAccess store, an AuthAccess
316
+ * session simulator, a PhotoAccess simulator, and provideHonuwareAccessMock()
317
+ * wiring for mock mode. Depends on @honuware/ui/access only.
318
+ */
319
+
320
+ /**
321
+ * Generated bundle index. Do not edit.
322
+ */
323
+
324
+ export { MockAuthAccess, MockCrudAccess, MockPhotoAccess, provideHonuwareAccessMock };
325
+ //# sourceMappingURL=honuware-ui-testing.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"honuware-ui-testing.mjs","sources":["../../../projects/honuware-ui/testing/src/mock-crud-access.ts","../../../projects/honuware-ui/testing/src/mock-auth-access.ts","../../../projects/honuware-ui/testing/src/mock-photo-access.ts","../../../projects/honuware-ui/testing/src/provide-honuware-access-mock.ts","../../../projects/honuware-ui/testing/src/public-api.ts","../../../projects/honuware-ui/testing/src/honuware-ui-testing.ts"],"sourcesContent":["import { Observable, of } from 'rxjs';\nimport {\n CrudAccess,\n AddItemBody,\n UpdateItemBody,\n DataResults,\n DataResultsWithCount,\n DatabaseSchema,\n TableSchema,\n FilterPair,\n FkOptionsResponse,\n FkDisplayResponse,\n} from '@honuware/ui/access';\n\n/** A stored row: a column-name → string-value map. */\nexport type MockRow = Record<string, string>;\n\nexport interface MockCrudAccessOptions {\n /** The schema this store honors (columns, primary keys, FK display templates). */\n schema?: DatabaseSchema;\n /** Seed rows keyed by table name. */\n seedRows?: Record<string, MockRow[]>;\n}\n\nconst EMPTY_SCHEMA: DatabaseSchema = {\n root_tables: [],\n nested_tables: [],\n tables: [],\n display_templates: {},\n fk_picker_preload_threshold: 50,\n};\n\n/**\n * In-memory, schema-driven {@link CrudAccess} for library/consumer tests. Honors\n * a supplied {@link DatabaseSchema} (columns, primary keys, FK display\n * templates) and keeps rows per table. Deterministic and dependency-free — the\n * framework counterpart to the app's ServerAccessMock, but only the 12 generic\n * CRUD methods.\n */\nexport class MockCrudAccess implements CrudAccess {\n private readonly schema: DatabaseSchema;\n private readonly rows = new Map<string, MockRow[]>();\n private readonly pkCounters = new Map<string, number>();\n\n constructor(options: MockCrudAccessOptions = {}) {\n this.schema = options.schema ?? EMPTY_SCHEMA;\n for (const [table, rows] of Object.entries(options.seedRows ?? {})) {\n this.rows.set(table, rows.map((row) => ({ ...row })));\n }\n }\n\n getDbSchema(): Observable<DatabaseSchema> {\n return of(this.schema);\n }\n\n getTableRows(tableName: string): Observable<DataResults> {\n return of(this.toDataResults(tableName, this.tableRows(tableName)));\n }\n\n getRowsByColumn(\n tableName: string,\n columnName: string,\n ascending: boolean,\n pageSize: number,\n pageNumber: number,\n ): Observable<DataResultsWithCount> {\n const sorted = this.sorted(this.tableRows(tableName), columnName, ascending);\n return of(this.paginate(tableName, sorted, pageSize, pageNumber));\n }\n\n getFilteredTableRows(\n tableName: string,\n columnName: string,\n ascending: boolean,\n pageSize: number,\n page: number,\n filterPairs: FilterPair[],\n ): Observable<DataResultsWithCount> {\n const filtered = this.applyFilters(this.tableRows(tableName), filterPairs);\n return of(this.paginate(tableName, this.sorted(filtered, columnName, ascending), pageSize, page));\n }\n\n getRow(tableName: string, columnName: string, columnValue: string): Observable<DataResults> {\n const matches = this.tableRows(tableName).filter((row) => row[columnName] === columnValue);\n return of(this.toDataResults(tableName, matches));\n }\n\n getRowByValues(tableName: string, filterPairs: FilterPair[]): Observable<DataResults> {\n return of(this.toDataResults(tableName, this.applyFilters(this.tableRows(tableName), filterPairs)));\n }\n\n addItem(body: AddItemBody): Observable<void> {\n this.insert(body.table_name, body.value as MockRow);\n return of(void 0);\n }\n\n addItemFetchPrimaryKey(body: AddItemBody): Observable<string> {\n return of(this.insert(body.table_name, body.value as MockRow));\n }\n\n updateItem(body: UpdateItemBody): Observable<void> {\n for (const row of this.tableRows(body.table_name)) {\n if (row[body.column_name] === body.column_value) {\n Object.assign(row, body.value as MockRow);\n }\n }\n return of(void 0);\n }\n\n deleteItem(tableName: string, columnName: string, columnValue: string): Observable<void> {\n this.rows.set(\n tableName,\n this.tableRows(tableName).filter((row) => row[columnName] !== columnValue),\n );\n return of(void 0);\n }\n\n getFkOptions(tableName: string, searchText: string, pageSize: number): Observable<FkOptionsResponse> {\n const primaryKey = this.tableSchema(tableName)?.primary_key ?? 'id';\n const template = this.schema.display_templates[tableName];\n const options = this.tableRows(tableName).map((row) => ({\n value: row[primaryKey] ?? '',\n display: this.renderTemplate(template, row) || (row[primaryKey] ?? ''),\n }));\n const search = searchText.toLowerCase();\n const matching = search ? options.filter((o) => o.display.toLowerCase().includes(search)) : options;\n return of({ total_count: matching.length, options: matching.slice(0, pageSize) });\n }\n\n resolveFkDisplay(parentTableName: string, values: string[]): Observable<FkDisplayResponse> {\n const primaryKey = this.tableSchema(parentTableName)?.primary_key ?? 'id';\n const template = this.schema.display_templates[parentTableName];\n const resolved: Record<string, string> = {};\n for (const value of values) {\n const row = this.tableRows(parentTableName).find((r) => r[primaryKey] === value);\n resolved[value] = row ? this.renderTemplate(template, row) || value : value;\n }\n return of({ resolved });\n }\n\n // --- internals ---\n\n private tableSchema(tableName: string): TableSchema | undefined {\n return this.schema.tables.find((t) => t.table_name === tableName);\n }\n\n private columnNames(tableName: string): string[] {\n const table = this.tableSchema(tableName);\n if (table) return table.columns.map((c) => c.column_name);\n const rows = this.rows.get(tableName) ?? [];\n return rows.length ? Object.keys(rows[0]) : [];\n }\n\n private tableRows(tableName: string): MockRow[] {\n let rows = this.rows.get(tableName);\n if (!rows) {\n rows = [];\n this.rows.set(tableName, rows);\n }\n return rows;\n }\n\n private toDataResults(tableName: string, rows: MockRow[]): DataResults {\n const columns = this.columnNames(tableName);\n return {\n sortedColumnNames: columns,\n dataTable: rows.map((row) => columns.map((c) => row[c] ?? '')),\n };\n }\n\n private insert(tableName: string, value: MockRow): string {\n const rows = this.tableRows(tableName);\n const primaryKey = this.tableSchema(tableName)?.primary_key ?? 'id';\n const row: MockRow = { ...value };\n if (!row[primaryKey]) row[primaryKey] = this.nextPrimaryKey(tableName, rows, primaryKey);\n rows.push(row);\n return row[primaryKey];\n }\n\n private nextPrimaryKey(tableName: string, rows: MockRow[], primaryKey: string): string {\n let counter = this.pkCounters.get(tableName);\n if (counter === undefined) {\n counter = rows.reduce((max, row) => Math.max(max, Number(row[primaryKey]) || 0), 0);\n }\n counter += 1;\n this.pkCounters.set(tableName, counter);\n return String(counter);\n }\n\n private applyFilters(rows: MockRow[], filterPairs: FilterPair[]): MockRow[] {\n if (!filterPairs.length) return rows;\n return rows.filter((row) => filterPairs.every((f) => row[f.column_name] === f.column_value));\n }\n\n private sorted(rows: MockRow[], columnName: string, ascending: boolean): MockRow[] {\n if (!columnName) return rows;\n const sorted = [...rows].sort((a, b) => (a[columnName] ?? '').localeCompare(b[columnName] ?? ''));\n return ascending ? sorted : sorted.reverse();\n }\n\n private paginate(tableName: string, rows: MockRow[], pageSize: number, page: number): DataResultsWithCount {\n const pageRows = pageSize > 0 ? rows.slice(page * pageSize, page * pageSize + pageSize) : rows;\n return { ...this.toDataResults(tableName, pageRows), totalCount: rows.length };\n }\n\n private renderTemplate(template: string | undefined, row: MockRow): string {\n if (!template) return '';\n let result = template;\n for (const [key, value] of Object.entries(row)) {\n result = result.split(`{${key}}`).join(value);\n }\n return result;\n }\n}\n","import { Observable, of, throwError } from 'rxjs';\nimport {\n AuthAccess,\n UserInfo,\n LoginInfo,\n SetUserInfo,\n UpdateUserPasswordInfo,\n} from '@honuware/ui/access';\n\nexport interface StoredUser {\n user: UserInfo;\n password: string;\n}\n\nexport interface MockAuthAccessOptions {\n /** Seed users the store knows about (with their login password). */\n users?: StoredUser[];\n}\n\nconst unauthorized = (): Observable<never> =>\n throwError(() => ({ status: 401, message: 'Unauthorized' }));\n\n/**\n * In-memory {@link AuthAccess} session simulator for tests. Tracks registered\n * users, a current session, and a \"remember me\" token. `me()`/`getUserInfo()`\n * reject with a 401-shaped error when no session is active — enough to exercise\n * AuthService's login / silent-reauth (me → remember → me) flows.\n */\nexport class MockAuthAccess implements AuthAccess {\n private readonly users = new Map<string, StoredUser>();\n private currentEmail: string | null = null;\n private rememberedEmail: string | null = null;\n private personIdCounter = 0;\n\n constructor(options: MockAuthAccessOptions = {}) {\n for (const seed of options.users ?? []) {\n this.users.set(seed.user.email, { user: { ...seed.user }, password: seed.password });\n this.personIdCounter = Math.max(this.personIdCounter, seed.user.person_id);\n }\n }\n\n register(firstName: string, lastName: string, email: string, password: string): Observable<void> {\n this.users.set(email, {\n user: {\n person_id: ++this.personIdCounter,\n first_name: firstName,\n last_name: lastName,\n email,\n created_at: '0',\n roles: [],\n permissions: [],\n must_change_password: false,\n },\n password,\n });\n return of(void 0);\n }\n\n verify(): Observable<void> {\n // The mock treats every verification link as valid.\n return of(void 0);\n }\n\n login(loginInfo: LoginInfo): Observable<void> {\n const stored = this.users.get(loginInfo.email);\n if (!stored || stored.password !== loginInfo.password) return unauthorized();\n this.currentEmail = loginInfo.email;\n this.rememberedEmail = loginInfo.remember ? loginInfo.email : null;\n return of(void 0);\n }\n\n logout(): Observable<void> {\n this.currentEmail = null;\n this.rememberedEmail = null;\n return of(void 0);\n }\n\n me(): Observable<void> {\n return this.currentEmail ? of(void 0) : unauthorized();\n }\n\n remember(): Observable<void> {\n if (!this.rememberedEmail) return unauthorized();\n this.currentEmail = this.rememberedEmail;\n return of(void 0);\n }\n\n getUserInfo(): Observable<UserInfo> {\n const stored = this.currentEmail ? this.users.get(this.currentEmail) : undefined;\n return stored ? of({ ...stored.user }) : unauthorized();\n }\n\n setUserInfo(userInfo: SetUserInfo): Observable<void> {\n const email = this.currentEmail;\n const stored = email ? this.users.get(email) : undefined;\n if (!email || !stored) return unauthorized();\n stored.user = { ...stored.user, ...userInfo };\n if (userInfo.email !== email) {\n this.users.delete(email);\n this.users.set(userInfo.email, stored);\n this.currentEmail = userInfo.email;\n }\n return of(void 0);\n }\n\n updateUserPassword(passwordInfo: UpdateUserPasswordInfo): Observable<void> {\n const stored = this.currentEmail ? this.users.get(this.currentEmail) : undefined;\n if (!stored || stored.password !== passwordInfo.old_password) return unauthorized();\n stored.password = passwordInfo.new_password;\n return of(void 0);\n }\n\n /**\n * Test helper (not part of AuthAccess): drop the active session but keep the\n * \"remember me\" token — so a subsequent `me()` rejects and `remember()` can\n * restore the session, exercising the silent-reauth path (me → remember → me).\n */\n expireSession(): void {\n this.currentEmail = null;\n }\n}\n","import { Observable, of } from 'rxjs';\nimport { PhotoAccess, SourcePhotoInfo } from '@honuware/ui/access';\n\nconst photoInfo = (id: number, type: string): SourcePhotoInfo => ({\n source_photo_id: id,\n type,\n width: 300,\n height: 300,\n created_at_us: 0,\n});\n\n/**\n * In-memory {@link PhotoAccess} simulator for tests. Remembers which table rows\n * have a photo so `hasPhoto()` reflects prior `uploadPhoto()`/`deletePhoto()`\n * calls. Ignores the image bytes (mocks the server's re-encode + store).\n */\nexport class MockPhotoAccess implements PhotoAccess {\n private readonly photos = new Set<string>();\n private nextId = 1;\n\n uploadPhoto(\n tableName: string,\n tableItemId: number,\n imageData: ArrayBuffer,\n imageType: string,\n ): Observable<SourcePhotoInfo> {\n this.photos.add(this.key(tableName, tableItemId));\n return of(photoInfo(this.nextId++, imageType));\n }\n\n uploadUserPhoto(imageData: ArrayBuffer, imageType: string): Observable<SourcePhotoInfo> {\n return of(photoInfo(this.nextId++, imageType));\n }\n\n deletePhoto(tableName: string, tableItemId: number): Observable<void> {\n this.photos.delete(this.key(tableName, tableItemId));\n return of(void 0);\n }\n\n hasPhoto(tableName: string, tableItemId: number): Observable<{ has_photo: boolean }> {\n return of({ has_photo: this.photos.has(this.key(tableName, tableItemId)) });\n }\n\n private key(tableName: string, tableItemId: number): string {\n return `${tableName}:${tableItemId}`;\n }\n}\n","import { Provider } from '@angular/core';\nimport { provideHonuwareAccess } from '@honuware/ui/access';\nimport { MockCrudAccess, MockCrudAccessOptions } from './mock-crud-access';\nimport { MockAuthAccess, MockAuthAccessOptions } from './mock-auth-access';\nimport { MockPhotoAccess } from './mock-photo-access';\n\nexport interface HonuwareAccessMocks {\n crud: MockCrudAccess;\n auth: MockAuthAccess;\n photo: MockPhotoAccess;\n}\n\nexport interface ProvideHonuwareAccessMockOptions {\n crud?: MockCrudAccessOptions;\n auth?: MockAuthAccessOptions;\n}\n\n/**\n * Test wiring: creates the three in-memory framework mocks and provides them for\n * the `HONUWARE_*_ACCESS` tokens (mock mode of `provideHonuwareAccess`). Pass a\n * `capture` callback to grab the mock instances for seeding/assertions.\n *\n * @example\n * let mocks: HonuwareAccessMocks;\n * TestBed.configureTestingModule({\n * providers: [provideHonuwareAccessMock({ crud: { schema } }, (m) => (mocks = m))],\n * });\n */\nexport function provideHonuwareAccessMock(\n options: ProvideHonuwareAccessMockOptions = {},\n capture?: (mocks: HonuwareAccessMocks) => void,\n): Provider[] {\n const mocks: HonuwareAccessMocks = {\n crud: new MockCrudAccess(options.crud),\n auth: new MockAuthAccess(options.auth),\n photo: new MockPhotoAccess(),\n };\n capture?.(mocks);\n return provideHonuwareAccess({\n mode: 'mock',\n crud: mocks.crud,\n auth: mocks.auth,\n photo: mocks.photo,\n });\n}\n","/*\n * @honuware/ui/testing — fresh, minimal in-memory framework mocks for\n * library/consumer tests: a schema-driven CrudAccess store, an AuthAccess\n * session simulator, a PhotoAccess simulator, and provideHonuwareAccessMock()\n * wiring for mock mode. Depends on @honuware/ui/access only.\n */\nexport { MockCrudAccess } from './mock-crud-access';\nexport type { MockRow, MockCrudAccessOptions } from './mock-crud-access';\n\nexport { MockAuthAccess } from './mock-auth-access';\nexport type { MockAuthAccessOptions, StoredUser } from './mock-auth-access';\n\nexport { MockPhotoAccess } from './mock-photo-access';\n\nexport { provideHonuwareAccessMock } from './provide-honuware-access-mock';\nexport type { HonuwareAccessMocks, ProvideHonuwareAccessMockOptions } from './provide-honuware-access-mock';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ /*
2
+ * Public API of @honuware/ui (primary entry point).
3
+ *
4
+ * The reusable code lives in the layered SECONDARY entry points —
5
+ * @honuware/ui/foundation, /access, /controls, /photos, /auth, /crud,
6
+ * /square, /testing — so consumers import only what they use and the
7
+ * layering is build-enforced (ng-packagr fails on cycles between entries).
8
+ * This primary entry deliberately stays minimal.
9
+ */
10
+ const HONUWARE_UI_VERSION = '0.1.0';
11
+
12
+ /**
13
+ * Generated bundle index. Do not edit.
14
+ */
15
+
16
+ export { HONUWARE_UI_VERSION };
17
+ //# sourceMappingURL=honuware-ui.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"honuware-ui.mjs","sources":["../../../projects/honuware-ui/src/public-api.ts","../../../projects/honuware-ui/src/honuware-ui.ts"],"sourcesContent":["/*\n * Public API of @honuware/ui (primary entry point).\n *\n * The reusable code lives in the layered SECONDARY entry points —\n * @honuware/ui/foundation, /access, /controls, /photos, /auth, /crud,\n * /square, /testing — so consumers import only what they use and the\n * layering is build-enforced (ng-packagr fails on cycles between entries).\n * This primary entry deliberately stays minimal.\n */\nexport const HONUWARE_UI_VERSION = '0.1.0';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"AAAA;;;;;;;;AAQG;AACI,MAAM,mBAAmB,GAAG;;ACTnC;;AAEG;;;;"}
package/package.json ADDED
@@ -0,0 +1,80 @@
1
+ {
2
+ "name": "@honuware/ui",
3
+ "version": "0.1.0",
4
+ "description": "Reusable, brand-free Angular UI + server-access framework.",
5
+ "license": "Apache-2.0",
6
+ "author": "Mason Bendixen",
7
+ "homepage": "https://github.com/honuware/web_components#readme",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+https://github.com/honuware/web_components.git"
11
+ },
12
+ "bugs": {
13
+ "url": "https://github.com/honuware/web_components/issues"
14
+ },
15
+ "keywords": [
16
+ "angular",
17
+ "ui",
18
+ "components",
19
+ "crud",
20
+ "honuware"
21
+ ],
22
+ "peerDependencies": {
23
+ "@angular/animations": "^21.0.0",
24
+ "@angular/cdk": "^21.0.0",
25
+ "@angular/common": "^21.0.0",
26
+ "@angular/core": "^21.0.0",
27
+ "@angular/forms": "^21.0.0",
28
+ "@angular/material": "^21.0.0",
29
+ "@angular/router": "^21.0.0",
30
+ "rxjs": "^7.8.0"
31
+ },
32
+ "dependencies": {
33
+ "tslib": "^2.3.0"
34
+ },
35
+ "sideEffects": false,
36
+ "module": "fesm2022/honuware-ui.mjs",
37
+ "typings": "types/honuware-ui.d.ts",
38
+ "exports": {
39
+ "./package.json": {
40
+ "default": "./package.json"
41
+ },
42
+ ".": {
43
+ "types": "./types/honuware-ui.d.ts",
44
+ "default": "./fesm2022/honuware-ui.mjs"
45
+ },
46
+ "./access": {
47
+ "types": "./types/honuware-ui-access.d.ts",
48
+ "default": "./fesm2022/honuware-ui-access.mjs"
49
+ },
50
+ "./auth": {
51
+ "types": "./types/honuware-ui-auth.d.ts",
52
+ "default": "./fesm2022/honuware-ui-auth.mjs"
53
+ },
54
+ "./controls": {
55
+ "types": "./types/honuware-ui-controls.d.ts",
56
+ "default": "./fesm2022/honuware-ui-controls.mjs"
57
+ },
58
+ "./crud": {
59
+ "types": "./types/honuware-ui-crud.d.ts",
60
+ "default": "./fesm2022/honuware-ui-crud.mjs"
61
+ },
62
+ "./foundation": {
63
+ "types": "./types/honuware-ui-foundation.d.ts",
64
+ "default": "./fesm2022/honuware-ui-foundation.mjs"
65
+ },
66
+ "./photos": {
67
+ "types": "./types/honuware-ui-photos.d.ts",
68
+ "default": "./fesm2022/honuware-ui-photos.mjs"
69
+ },
70
+ "./square": {
71
+ "types": "./types/honuware-ui-square.d.ts",
72
+ "default": "./fesm2022/honuware-ui-square.mjs"
73
+ },
74
+ "./testing": {
75
+ "types": "./types/honuware-ui-testing.d.ts",
76
+ "default": "./fesm2022/honuware-ui-testing.mjs"
77
+ }
78
+ },
79
+ "type": "module"
80
+ }