11// TODO: Make this a pre-publish hook and just bundle everything
2+ import { createHash } from 'node:crypto' ;
23import * as OS from 'node:os' ;
34import * as fs from 'node:fs/promises' ;
45import * as path from 'node:path' ;
56import { Readable } from 'node:stream' ;
67import { finished } from 'node:stream/promises' ;
78import { exit } from 'node:process' ;
89
10+ // When changing this version, run node download_core.js update_hashes
911const version = '0.3.14' ;
12+ const versionHashes = {
13+ 'powersync_x64.dll' : 'ba0fda2496878d195ea5530562509cc585fa4702fd308594d0eef6f37060dafe' ,
14+ 'libpowersync_x64.so' : '4cee8675b78af786f26f1e1666367de3d228f584084cca257e879060302c1371' ,
15+ 'libpowersync_aarch64.so' : 'ed4ec55cb29ac4b295dc076de71e4247b08d46db562a53e2875cc47420a97a55' ,
16+ 'libpowersync_x64.dylib' : 'cec6fb04732dd8c9a8ec6c6028b1b996965a0a359b0461d7dd6aa885d6eccddf' ,
17+ 'libpowersync_aarch64.dylib' : '55b60e156c3ddc9e7d6fae273943b94b83481c861676c9bcd1e2cfcea02b0a18'
18+ } ;
1019
1120const platform = OS . platform ( ) ;
1221let destination ;
@@ -23,24 +32,68 @@ if (platform === 'win32') {
2332 destination = 'libpowersync.dylib' ;
2433}
2534
35+ const expectedHash = versionHashes [ asset ] ;
2636const destinationPath = path . resolve ( 'lib' , destination ) ;
27- try {
28- await fs . access ( destinationPath ) ;
29- exit ( 0 ) ;
30- } catch { }
31-
32- const url = `https://github.com/powersync-ja/powersync-sqlite-core/releases/download/v${ version } /${ asset } ` ;
33- const response = await fetch ( url ) ;
34- if ( response . status != 200 ) {
35- throw `Could not download ${ url } ` ;
36- }
3737
38- try {
39- await fs . access ( 'lib' ) ;
40- } catch {
41- await fs . mkdir ( 'lib' ) ;
42- }
38+ const hashStream = async ( input ) => {
39+ for await ( const chunk of input . pipe ( createHash ( 'sha256' ) ) . setEncoding ( 'hex' ) ) {
40+ return chunk ;
41+ }
42+ } ;
43+
44+ const hashLocal = async ( ) => {
45+ try {
46+ const handle = await fs . open ( destinationPath , 'r' ) ;
47+ const input = handle . createReadStream ( ) ;
48+
49+ const result = await hashStream ( input ) ;
50+ await handle . close ( ) ;
51+ return result ;
52+ } catch {
53+ return null ;
54+ }
55+ } ;
56+
57+ const download = async ( ) => {
58+ if ( ( await hashLocal ( ) ) == expectedHash ) {
59+ console . debug ( 'Local copy is up-to-date, skipping download' ) ;
60+ exit ( 0 ) ;
61+ }
62+
63+ const url = `https://github.com/powersync-ja/powersync-sqlite-core/releases/download/v${ version } /${ asset } ` ;
64+ const response = await fetch ( url ) ;
65+ if ( response . status != 200 ) {
66+ throw `Could not download ${ url } ` ;
67+ }
4368
44- const file = await fs . open ( destinationPath , 'w' ) ;
45- await finished ( Readable . fromWeb ( response . body ) . pipe ( file . createWriteStream ( ) ) ) ;
46- await file . close ( ) ;
69+ try {
70+ await fs . access ( 'lib' ) ;
71+ } catch {
72+ await fs . mkdir ( 'lib' ) ;
73+ }
74+
75+ const file = await fs . open ( destinationPath , 'w' ) ;
76+ await finished ( Readable . fromWeb ( response . body ) . pipe ( file . createWriteStream ( ) ) ) ;
77+ await file . close ( ) ;
78+
79+ const hashAfterDownloading = await hashLocal ( ) ;
80+ if ( hashAfterDownloading != expectedHash ) {
81+ throw `Unexpected hash after downloading (got ${ hashAfterDownloading } , expected ${ expectedHash } )` ;
82+ }
83+ } ;
84+
85+ const updateReferenceHashes = async ( ) => {
86+ for ( const asset of Object . keys ( versionHashes ) ) {
87+ const url = `https://github.com/powersync-ja/powersync-sqlite-core/releases/download/v${ version } /${ asset } ` ;
88+ const response = await fetch ( url ) ;
89+ const hash = await hashStream ( Readable . fromWeb ( response . body ) ) ;
90+
91+ console . log ( ` '${ asset } ': '${ hash } ',` ) ;
92+ }
93+ } ;
94+
95+ if ( process . argv [ process . argv . length - 1 ] == 'update_hashes' ) {
96+ await updateReferenceHashes ( ) ;
97+ } else {
98+ await download ( ) ;
99+ }
0 commit comments