Skip to content

Commit 704c2a8

Browse files
author
Amine
committed
tests(WIP:) initial node setup and few bug fixes
1 parent ce33bab commit 704c2a8

File tree

9 files changed

+1227
-680
lines changed

9 files changed

+1227
-680
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,5 @@ dist
99
# Useful if running repository in VSCode dev container
1010
.pnpm-store
1111
__screenshots__
12+
**/tests/temp/**/*
13+
**/tests/temp/**/.*

packages/attachments/package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,10 @@
5050
"devDependencies": {
5151
"@powersync/common": "workspace:*",
5252
"@powersync/web": "workspace:*",
53+
"@powersync/node": "workspace:*",
54+
"@powersync/better-sqlite3": "^0.2.0",
5355
"@types/node": "^20.17.6",
56+
"memfs": "^4.50.0",
5457
"vite": "^6.1.0",
5558
"vite-plugin-top-level-await": "^1.4.4",
5659
"vite-plugin-wasm": "^3.3.0"

packages/attachments/src/AttachmentContext.ts

Lines changed: 48 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -118,36 +118,52 @@ export class AttachmentContext {
118118
* @param context - Active database transaction context
119119
*/
120120
upsertAttachment(attachment: AttachmentRecord, context: Transaction): void {
121-
context.execute(
122-
/* sql */
123-
`
124-
INSERT
125-
OR REPLACE INTO ${this.tableName} (
126-
id,
127-
filename,
128-
local_uri,
129-
size,
130-
media_type,
131-
timestamp,
132-
state,
133-
has_synced,
134-
meta_data
135-
)
136-
VALUES
137-
(?, ?, ?, ?, ?, ?, ?, ?, ?)
138-
`,
139-
[
140-
attachment.id,
141-
attachment.filename,
142-
attachment.localUri || null,
143-
attachment.size || null,
144-
attachment.mediaType || null,
145-
attachment.timestamp,
146-
attachment.state,
147-
attachment.hasSynced ? 1 : 0,
148-
attachment.metaData || null
149-
]
150-
);
121+
console.debug('[ATTACHMENT CONTEXT] Upserting attachment:', [
122+
attachment.id,
123+
attachment.filename,
124+
attachment.localUri || null,
125+
attachment.size || null,
126+
attachment.mediaType || null,
127+
attachment.timestamp,
128+
attachment.state,
129+
attachment.hasSynced ? 1 : 0,
130+
attachment.metaData || null
131+
]);
132+
try {
133+
context.execute(
134+
/* sql */
135+
`
136+
INSERT
137+
OR REPLACE INTO ${this.tableName} (
138+
id,
139+
filename,
140+
local_uri,
141+
size,
142+
media_type,
143+
timestamp,
144+
state,
145+
has_synced,
146+
meta_data
147+
)
148+
VALUES
149+
(?, ?, ?, ?, ?, ?, ?, ?, ?)
150+
`,
151+
[
152+
attachment.id,
153+
attachment.filename,
154+
attachment.localUri || 'dummy',
155+
attachment.size || 1,
156+
attachment.mediaType || 'dummy',
157+
attachment.timestamp || Date.now(),
158+
attachment.state,
159+
attachment.hasSynced ? 1 : 0,
160+
attachment.metaData || 'dummy'
161+
]
162+
);
163+
} catch (error) {
164+
console.error('[ATTACHMENT CONTEXT] Error upserting attachment:', attachment.id?.substring(0,8), attachment.state, error);
165+
throw error;
166+
}
151167
}
152168

153169
/**
@@ -182,7 +198,9 @@ export class AttachmentContext {
182198
* @param attachments - Array of attachment records to save
183199
*/
184200
async saveAttachments(attachments: AttachmentRecord[]): Promise<void> {
201+
console.debug('[ATTACHMENT CONTEXT] Saving attachments:', attachments.map(a => ({ id: a.id?.substring(0,8), state: a.state })));
185202
if (attachments.length === 0) {
203+
console.debug('[ATTACHMENT CONTEXT] No attachments to save');
186204
return;
187205
}
188206
await this.db.writeTransaction(async (tx) => {

packages/attachments/src/AttachmentQueue.ts

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import { SyncingService } from './SyncingService.js';
77
import { WatchedAttachmentItem } from './WatchedAttachmentItem.js';
88
import { AttachmentService } from './AttachmentService.js';
99

10+
export type AttachmentData = ArrayBuffer | Blob | string;
11+
1012
/**
1113
* AttachmentQueue manages the lifecycle and synchronization of attachments
1214
* between local and remote storage.
@@ -94,6 +96,7 @@ export class AttachmentQueue {
9496
downloadAttachments?: boolean;
9597
archivedCacheLimit?: number;
9698
}) {
99+
console.debug('AttachmentQueue constructor')
97100
this.context = new AttachmentContext(db, tableName, logger ?? db.logger);
98101
this.remoteStorage = remoteStorage;
99102
this.localStorage = localStorage;
@@ -133,7 +136,12 @@ export class AttachmentQueue {
133136
* - Handles state transitions for archived and new attachments
134137
*/
135138
async startSync(): Promise<void> {
136-
await this.stopSync();
139+
console.debug('[QUEUE] AttachmentQueue startSync')
140+
if (this.attachmentService.watchActiveAttachments) {
141+
await this.stopSync();
142+
// re-create the watch after it was stopped
143+
this.watchActiveAttachments = this.attachmentService.watchActiveAttachments();
144+
}
137145

138146
// Sync storage periodically
139147
this.periodicSyncTimer = setInterval(async () => {
@@ -143,12 +151,14 @@ export class AttachmentQueue {
143151
// Sync storage when there is a change in active attachments
144152
this.watchActiveAttachments.registerListener({
145153
onDiff: async () => {
154+
console.debug('[QUEUE] watchActiveAttachments: diff detected, syncing storage');
146155
await this.syncStorage();
147156
}
148157
});
149158

150159
// Process attachments when there is a change in watched attachments
151160
this.watchAttachments(async (watchedAttachments) => {
161+
console.debug('[QUEUE] watchAttachments callback:', watchedAttachments.length, 'items');
152162
// Need to get all the attachments which are tracked in the DB.
153163
// We might need to restore an archived attachment.
154164
const currentAttachments = await this.context.getAttachments();
@@ -224,6 +234,7 @@ export class AttachmentQueue {
224234
}
225235

226236
if (attachmentUpdates.length > 0) {
237+
console.debug('[QUEUE] Saving attachments:', attachmentUpdates);
227238
await this.context.saveAttachments(attachmentUpdates);
228239
}
229240
});
@@ -237,6 +248,7 @@ export class AttachmentQueue {
237248
*/
238249
async syncStorage(): Promise<void> {
239250
const activeAttachments = await this.context.getActiveAttachments();
251+
console.debug('[QUEUE] syncStorage: processing', activeAttachments.length, 'active attachments');
240252
await this.localStorage.initialize();
241253
await this.syncingService.processAttachments(activeAttachments);
242254
await this.syncingService.deleteArchivedAttachments();
@@ -275,7 +287,7 @@ export class AttachmentQueue {
275287
updateHook
276288
}: {
277289
// TODO: create a dedicated type for data
278-
data: ArrayBuffer | Blob | string;
290+
data: AttachmentData;
279291
fileExtension: string;
280292
mediaType?: string;
281293
metaData?: string;

packages/attachments/src/SyncingService.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,9 +107,10 @@ export class SyncingService {
107107
* @returns Updated attachment record with local URI and new state
108108
*/
109109
async downloadAttachment(attachment: AttachmentRecord): Promise<AttachmentRecord> {
110+
console.debug('[SYNC] Downloading:', attachment.id);
110111
try {
111112
const file = await this.remoteStorage.downloadFile(attachment);
112-
113+
console.debug('[SYNC] Downloaded, converting to base64');
113114
const base64Data = await new Promise<string>((resolve, reject) => {
114115
const reader = new FileReader();
115116
reader.onloadend = () => {

0 commit comments

Comments
 (0)