@syncular/cli 0.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.
- package/dist/args.d.ts +6 -0
- package/dist/args.d.ts.map +1 -0
- package/dist/args.js +92 -0
- package/dist/args.js.map +1 -0
- package/dist/commands/create.d.ts +8 -0
- package/dist/commands/create.d.ts.map +1 -0
- package/dist/commands/create.js +423 -0
- package/dist/commands/create.js.map +1 -0
- package/dist/commands/init.d.ts +3 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +15 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/migrate.d.ts +4 -0
- package/dist/commands/migrate.d.ts.map +1 -0
- package/dist/commands/migrate.js +114 -0
- package/dist/commands/migrate.js.map +1 -0
- package/dist/config.d.ts +10 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +118 -0
- package/dist/config.js.map +1 -0
- package/dist/constants.d.ts +18 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +108 -0
- package/dist/constants.js.map +1 -0
- package/dist/create-libraries-wizard.d.ts +8 -0
- package/dist/create-libraries-wizard.d.ts.map +1 -0
- package/dist/create-libraries-wizard.js +428 -0
- package/dist/create-libraries-wizard.js.map +1 -0
- package/dist/doctor.d.ts +3 -0
- package/dist/doctor.d.ts.map +1 -0
- package/dist/doctor.js +53 -0
- package/dist/doctor.js.map +1 -0
- package/dist/help.d.ts +2 -0
- package/dist/help.d.ts.map +1 -0
- package/dist/help.js +52 -0
- package/dist/help.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/dist/interactive.d.ts +5 -0
- package/dist/interactive.d.ts.map +1 -0
- package/dist/interactive.js +180 -0
- package/dist/interactive.js.map +1 -0
- package/dist/main.d.ts +2 -0
- package/dist/main.d.ts.map +1 -0
- package/dist/main.js +118 -0
- package/dist/main.js.map +1 -0
- package/dist/output.d.ts +3 -0
- package/dist/output.d.ts.map +1 -0
- package/dist/output.js +8 -0
- package/dist/output.js.map +1 -0
- package/dist/template.d.ts +8 -0
- package/dist/template.d.ts.map +1 -0
- package/dist/template.js +26 -0
- package/dist/template.js.map +1 -0
- package/dist/types.d.ts +101 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +1 -0
- package/dist/types.js.map +1 -0
- package/package.json +52 -0
- package/templates/demo/index.html.tpl +12 -0
- package/templates/demo/package.json.tpl +40 -0
- package/templates/demo/src/client/App.tsx.tpl +137 -0
- package/templates/demo/src/client/main.tsx.tpl +15 -0
- package/templates/demo/src/client/styles.css.tpl +93 -0
- package/templates/demo/src/client/syncular.ts.tpl +109 -0
- package/templates/demo/src/server/index.ts.tpl +58 -0
- package/templates/demo/src/shared/db.ts.tpl +40 -0
- package/templates/demo/syncular-migrate.ts.tpl +79 -0
- package/templates/demo/syncular-typegen.ts.tpl +23 -0
- package/templates/demo/syncular.config.json.tpl +7 -0
- package/templates/demo/tsconfig.json.tpl +12 -0
- package/templates/demo/vite.config.ts.tpl +15 -0
- package/templates/libraries/syncular-electron.ts.tpl +36 -0
- package/templates/libraries/syncular-expo.ts.tpl +32 -0
- package/templates/libraries/syncular-migrate.ts.tpl +81 -0
- package/templates/libraries/syncular-proxy-api.ts.tpl +32 -0
- package/templates/libraries/syncular-react-native.ts.tpl +32 -0
- package/templates/libraries/syncular-react.ts.tpl +27 -0
- package/templates/libraries/syncular-server.postgres.ts.tpl +40 -0
- package/templates/libraries/syncular-server.sqlite.ts.tpl +34 -0
- package/templates/libraries/syncular-typegen.ts.tpl +29 -0
- package/templates/libraries/syncular-vanilla.ts.tpl +38 -0
- package/templates/libraries/syncular.config.json.tpl +9 -0
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Syncular CLI migration adapter.
|
|
3
|
+
*
|
|
4
|
+
* Generated by `syncular create`.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { getSchemaVersion, runMigrations, type DefinedMigrations } from '@syncular/migrations';
|
|
8
|
+
import type { Kysely } from 'kysely';
|
|
9
|
+
|
|
10
|
+
// Replace with your app DB type and concrete implementation.
|
|
11
|
+
type Db = Record<string, never>;
|
|
12
|
+
|
|
13
|
+
async function createDb(): Promise<Kysely<Db>> {
|
|
14
|
+
throw new Error('TODO: implement createDb() in scripts/syncular-migrate.ts');
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
async function loadMigrations(): Promise<DefinedMigrations<Db>> {
|
|
18
|
+
throw new Error('TODO: return your defineMigrations(...) export in scripts/syncular-migrate.ts');
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export const <%= it.ADAPTER_EXPORT %> = {
|
|
22
|
+
async status() {
|
|
23
|
+
const db = await createDb();
|
|
24
|
+
try {
|
|
25
|
+
const migrations = await loadMigrations();
|
|
26
|
+
const currentVersion = await getSchemaVersion(db);
|
|
27
|
+
const targetVersion = migrations.currentVersion;
|
|
28
|
+
const pendingVersions = migrations.migrations
|
|
29
|
+
.map((migration) => migration.version)
|
|
30
|
+
.filter((version) => version > currentVersion);
|
|
31
|
+
|
|
32
|
+
return {
|
|
33
|
+
currentVersion,
|
|
34
|
+
targetVersion,
|
|
35
|
+
pendingVersions,
|
|
36
|
+
trackingTable: 'sync_migration_state',
|
|
37
|
+
};
|
|
38
|
+
} finally {
|
|
39
|
+
await db.destroy();
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
|
|
43
|
+
async up(options: {
|
|
44
|
+
onChecksumMismatch: 'error' | 'reset';
|
|
45
|
+
dryRun: boolean;
|
|
46
|
+
}) {
|
|
47
|
+
const db = await createDb();
|
|
48
|
+
try {
|
|
49
|
+
const migrations = await loadMigrations();
|
|
50
|
+
const currentVersion = await getSchemaVersion(db);
|
|
51
|
+
|
|
52
|
+
if (options.dryRun) {
|
|
53
|
+
const pendingVersions = migrations.migrations
|
|
54
|
+
.map((migration) => migration.version)
|
|
55
|
+
.filter((version) => version > currentVersion);
|
|
56
|
+
|
|
57
|
+
return {
|
|
58
|
+
appliedVersions: pendingVersions,
|
|
59
|
+
currentVersion,
|
|
60
|
+
wasReset: false,
|
|
61
|
+
dryRun: true,
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const result = await runMigrations({
|
|
66
|
+
db,
|
|
67
|
+
migrations,
|
|
68
|
+
onChecksumMismatch: options.onChecksumMismatch,
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
return {
|
|
72
|
+
appliedVersions: result.applied,
|
|
73
|
+
currentVersion: result.currentVersion,
|
|
74
|
+
wasReset: result.wasReset,
|
|
75
|
+
dryRun: false,
|
|
76
|
+
};
|
|
77
|
+
} finally {
|
|
78
|
+
await db.destroy();
|
|
79
|
+
}
|
|
80
|
+
},
|
|
81
|
+
};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Syncular proxy API scaffold.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { createProxyRoutes } from '@syncular/server-hono';
|
|
6
|
+
import { ProxyTableRegistry } from '@syncular/server';
|
|
7
|
+
|
|
8
|
+
type ProxyRouteOptions = Parameters<typeof createProxyRoutes>[0];
|
|
9
|
+
|
|
10
|
+
export function createSyncularProxyRoutes(args: {
|
|
11
|
+
db: ProxyRouteOptions['db'];
|
|
12
|
+
dialect: ProxyRouteOptions['dialect'];
|
|
13
|
+
upgradeWebSocket: ProxyRouteOptions['upgradeWebSocket'];
|
|
14
|
+
validateToken: (token: string | undefined) => string | null;
|
|
15
|
+
}) {
|
|
16
|
+
const handlers = new ProxyTableRegistry().register({
|
|
17
|
+
table: 'tasks',
|
|
18
|
+
computeScopes: (row) => ({ user_id: String(row.user_id ?? '') }),
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
return createProxyRoutes({
|
|
22
|
+
db: args.db,
|
|
23
|
+
dialect: args.dialect,
|
|
24
|
+
handlers,
|
|
25
|
+
upgradeWebSocket: args.upgradeWebSocket,
|
|
26
|
+
authenticate: async (c) => {
|
|
27
|
+
const token = c.req.query('token') ?? c.req.header('x-api-key');
|
|
28
|
+
const actorId = args.validateToken(token);
|
|
29
|
+
return actorId ? { actorId } : null;
|
|
30
|
+
},
|
|
31
|
+
});
|
|
32
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Syncular React Native module scaffold (Nitro SQLite).
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { createClient } from '@syncular/client';
|
|
6
|
+
import type { SyncClientDb } from '@syncular/client';
|
|
7
|
+
import { createNitroSqliteDb } from '@syncular/dialect-react-native-nitro-sqlite';
|
|
8
|
+
import { createHttpTransport } from '@syncular/transport-http';
|
|
9
|
+
|
|
10
|
+
export function createClientDb<DB extends SyncClientDb>() {
|
|
11
|
+
return createNitroSqliteDb<DB>({ name: 'app.sqlite' });
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export async function createSyncularReactNativeClient<DB extends SyncClientDb>(args: {
|
|
15
|
+
actorId: string;
|
|
16
|
+
token: string;
|
|
17
|
+
baseUrl: string;
|
|
18
|
+
tables: string[];
|
|
19
|
+
scopes: string[];
|
|
20
|
+
}) {
|
|
21
|
+
const db = createClientDb<DB>();
|
|
22
|
+
return createClient({
|
|
23
|
+
db,
|
|
24
|
+
actorId: args.actorId,
|
|
25
|
+
transport: createHttpTransport({
|
|
26
|
+
baseUrl: args.baseUrl,
|
|
27
|
+
getHeaders: () => ({ Authorization: `Bearer ${args.token}` }),
|
|
28
|
+
}),
|
|
29
|
+
tables: args.tables,
|
|
30
|
+
scopes: args.scopes,
|
|
31
|
+
});
|
|
32
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Syncular React module scaffold.
|
|
3
|
+
*
|
|
4
|
+
* Dialect: <%= it.CLIENT_DIALECT_LABEL %>
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
<%= it.CLIENT_DIALECT_IMPORT %>
|
|
8
|
+
import type { SyncClientDb } from '@syncular/client';
|
|
9
|
+
import { createSyncularReact } from '@syncular/client-react';
|
|
10
|
+
import { createHttpTransport } from '@syncular/transport-http';
|
|
11
|
+
|
|
12
|
+
export const clientDialect = '<%= it.CLIENT_DIALECT %>';
|
|
13
|
+
|
|
14
|
+
export function createClientDb<DB>() {
|
|
15
|
+
<%= it.CLIENT_DB_FACTORY_LINE %>
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function createSyncTransport(args: { baseUrl: string; token: string }) {
|
|
19
|
+
return createHttpTransport({
|
|
20
|
+
baseUrl: args.baseUrl,
|
|
21
|
+
getHeaders: () => ({ Authorization: `Bearer ${args.token}` }),
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function createReactBindings<DB extends SyncClientDb>() {
|
|
26
|
+
return createSyncularReact<DB>();
|
|
27
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Syncular server module scaffold (Postgres).
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { createServerHandler, ensureSyncSchema, type SyncCoreDb } from '@syncular/server';
|
|
6
|
+
import { createPostgresServerDialect } from '@syncular/server-dialect-postgres';
|
|
7
|
+
import { createSyncServer } from '@syncular/server-hono';
|
|
8
|
+
import { Kysely, PostgresDialect } from 'kysely';
|
|
9
|
+
import { Pool } from 'pg';
|
|
10
|
+
|
|
11
|
+
export interface AppServerDb extends SyncCoreDb {}
|
|
12
|
+
|
|
13
|
+
export async function createSyncularServer() {
|
|
14
|
+
const db = new Kysely<AppServerDb>({
|
|
15
|
+
dialect: new PostgresDialect({
|
|
16
|
+
pool: new Pool({ connectionString: process.env.DATABASE_URL }),
|
|
17
|
+
}),
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
const dialect = createPostgresServerDialect();
|
|
21
|
+
await ensureSyncSchema(db, dialect);
|
|
22
|
+
|
|
23
|
+
const tasksHandler = createServerHandler({
|
|
24
|
+
table: 'tasks',
|
|
25
|
+
scopes: ['user:{user_id}'],
|
|
26
|
+
resolveScopes: async (ctx) => ({ user_id: [ctx.actorId] }),
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
const server = createSyncServer({
|
|
30
|
+
db,
|
|
31
|
+
dialect,
|
|
32
|
+
handlers: [tasksHandler],
|
|
33
|
+
authenticate: async (c) => {
|
|
34
|
+
const actorId = c.req.header('x-user-id');
|
|
35
|
+
return actorId ? { actorId } : null;
|
|
36
|
+
},
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
return { ...server, db, dialect };
|
|
40
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Syncular server module scaffold (SQLite).
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { createBunSqliteDb } from '@syncular/dialect-bun-sqlite';
|
|
6
|
+
import { createServerHandler, ensureSyncSchema, type SyncCoreDb } from '@syncular/server';
|
|
7
|
+
import { createSqliteServerDialect } from '@syncular/server-dialect-sqlite';
|
|
8
|
+
import { createSyncServer } from '@syncular/server-hono';
|
|
9
|
+
|
|
10
|
+
export interface AppServerDb extends SyncCoreDb {}
|
|
11
|
+
|
|
12
|
+
export async function createSyncularServer() {
|
|
13
|
+
const db = createBunSqliteDb<AppServerDb>({ path: './data/server.sqlite' });
|
|
14
|
+
const dialect = createSqliteServerDialect();
|
|
15
|
+
await ensureSyncSchema(db, dialect);
|
|
16
|
+
|
|
17
|
+
const tasksHandler = createServerHandler({
|
|
18
|
+
table: 'tasks',
|
|
19
|
+
scopes: ['user:{user_id}'],
|
|
20
|
+
resolveScopes: async (ctx) => ({ user_id: [ctx.actorId] }),
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
const server = createSyncServer({
|
|
24
|
+
db,
|
|
25
|
+
dialect,
|
|
26
|
+
handlers: [tasksHandler],
|
|
27
|
+
authenticate: async (c) => {
|
|
28
|
+
const actorId = c.req.header('x-user-id');
|
|
29
|
+
return actorId ? { actorId } : null;
|
|
30
|
+
},
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
return { ...server, db, dialect };
|
|
34
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Syncular type generation scaffold.
|
|
3
|
+
*
|
|
4
|
+
* Wire your migrations export and run via `bun run db:typegen`.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { generateTypes } from '@syncular/typegen';
|
|
8
|
+
|
|
9
|
+
async function main() {
|
|
10
|
+
throw new Error('TODO: import your migrations and call generateTypes(...)');
|
|
11
|
+
|
|
12
|
+
// Example:
|
|
13
|
+
// const result = await generateTypes({
|
|
14
|
+
// migrations,
|
|
15
|
+
// output: './src/syncular/types.generated.ts',
|
|
16
|
+
// extendsSyncClientDb: true,
|
|
17
|
+
// });
|
|
18
|
+
// console.log(`Generated ${result.outputPath}`);
|
|
19
|
+
// await generateTypes({
|
|
20
|
+
// migrations,
|
|
21
|
+
// output: './src/syncular/types.generated.ts',
|
|
22
|
+
// extendsSyncClientDb: true,
|
|
23
|
+
// });
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
main().catch((error) => {
|
|
27
|
+
console.error('Typegen failed:', error);
|
|
28
|
+
process.exit(1);
|
|
29
|
+
});
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Syncular vanilla module scaffold.
|
|
3
|
+
*
|
|
4
|
+
* Dialect: <%= it.CLIENT_DIALECT_LABEL %>
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { createClient } from '@syncular/client';
|
|
8
|
+
import type { SyncClientDb } from '@syncular/client';
|
|
9
|
+
<%= it.CLIENT_DIALECT_IMPORT %>
|
|
10
|
+
import { createHttpTransport } from '@syncular/transport-http';
|
|
11
|
+
|
|
12
|
+
export const clientDialect = '<%= it.CLIENT_DIALECT %>';
|
|
13
|
+
|
|
14
|
+
export function createClientDb<DB extends SyncClientDb>() {
|
|
15
|
+
<%= it.CLIENT_DB_FACTORY_LINE %>
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export async function createSyncularClient<DB extends SyncClientDb>(args: {
|
|
19
|
+
actorId: string;
|
|
20
|
+
token: string;
|
|
21
|
+
baseUrl: string;
|
|
22
|
+
tables: string[];
|
|
23
|
+
scopes: string[];
|
|
24
|
+
}) {
|
|
25
|
+
const db = createClientDb<DB>();
|
|
26
|
+
const transport = createHttpTransport({
|
|
27
|
+
baseUrl: args.baseUrl,
|
|
28
|
+
getHeaders: () => ({ Authorization: `Bearer ${args.token}` }),
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
return createClient({
|
|
32
|
+
db,
|
|
33
|
+
actorId: args.actorId,
|
|
34
|
+
transport,
|
|
35
|
+
tables: args.tables,
|
|
36
|
+
scopes: args.scopes,
|
|
37
|
+
});
|
|
38
|
+
}
|