lsh-framework 3.2.4 → 3.5.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/LICENSE +21 -0
- package/README.md +72 -34
- package/dist/commands/ipfs.js +7 -12
- package/dist/commands/sync.js +51 -39
- package/dist/constants/config.js +3 -0
- package/dist/lib/floating-point-arithmetic.js +2 -2
- package/dist/lib/ipfs-client-manager.js +51 -13
- package/dist/lib/ipfs-secrets-storage.js +21 -16
- package/dist/lib/ipfs-sync.js +88 -14
- package/dist/lib/secrets-manager.js +117 -47
- package/dist/lib/sync-key-store.js +87 -0
- package/dist/services/secrets/secrets.js +77 -39
- package/package.json +16 -16
- package/dist/__tests__/fixtures/job-fixtures.js +0 -204
- package/dist/__tests__/fixtures/supabase-mocks.js +0 -252
- package/dist/daemon/job-registry.js +0 -556
- package/dist/daemon/lshd.js +0 -968
- package/dist/daemon/saas-api-routes.js +0 -599
- package/dist/daemon/saas-api-server.js +0 -231
- package/dist/examples/supabase-integration.js +0 -106
- package/dist/lib/api-response.js +0 -226
- package/dist/lib/base-command-registrar.js +0 -287
- package/dist/lib/base-job-manager.js +0 -295
- package/dist/lib/cloud-config-manager.js +0 -348
- package/dist/lib/cron-job-manager.js +0 -368
- package/dist/lib/daemon-client-helper.js +0 -145
- package/dist/lib/daemon-client.js +0 -513
- package/dist/lib/database-persistence.js +0 -727
- package/dist/lib/database-schema.js +0 -259
- package/dist/lib/database-types.js +0 -90
- package/dist/lib/enhanced-history-system.js +0 -247
- package/dist/lib/history-system.js +0 -246
- package/dist/lib/job-manager.js +0 -436
- package/dist/lib/job-storage-database.js +0 -164
- package/dist/lib/job-storage-memory.js +0 -73
- package/dist/lib/local-storage-adapter.js +0 -507
- package/dist/lib/optimized-job-scheduler.js +0 -356
- package/dist/lib/saas-audit.js +0 -215
- package/dist/lib/saas-auth.js +0 -465
- package/dist/lib/saas-billing.js +0 -503
- package/dist/lib/saas-email.js +0 -403
- package/dist/lib/saas-encryption.js +0 -221
- package/dist/lib/saas-organizations.js +0 -662
- package/dist/lib/saas-secrets.js +0 -408
- package/dist/lib/saas-types.js +0 -165
- package/dist/lib/supabase-client.js +0 -125
- package/dist/lib/supabase-utils.js +0 -396
- package/dist/services/cron/cron-registrar.js +0 -240
- package/dist/services/cron/cron.js +0 -9
- package/dist/services/daemon/daemon-registrar.js +0 -585
- package/dist/services/daemon/daemon.js +0 -9
- package/dist/services/supabase/supabase-registrar.js +0 -375
- package/dist/services/supabase/supabase.js +0 -9
|
@@ -1,375 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Supabase Command Registrar
|
|
3
|
-
* Registers all Supabase-related CLI commands using BaseCommandRegistrar
|
|
4
|
-
*/
|
|
5
|
-
import { BaseCommandRegistrar } from '../../lib/base-command-registrar.js';
|
|
6
|
-
import { supabaseClient } from '../../lib/supabase-client.js';
|
|
7
|
-
import DatabasePersistence from '../../lib/database-persistence.js';
|
|
8
|
-
import CloudConfigManager from '../../lib/cloud-config-manager.js';
|
|
9
|
-
import { CREATE_TABLES_SQL } from '../../lib/database-schema.js';
|
|
10
|
-
import { TABLES } from '../../constants/index.js';
|
|
11
|
-
export class SupabaseCommandRegistrar extends BaseCommandRegistrar {
|
|
12
|
-
constructor() {
|
|
13
|
-
super('SupabaseService');
|
|
14
|
-
}
|
|
15
|
-
async register(program) {
|
|
16
|
-
const supabaseCmd = this.createCommand(program, 'supabase', 'Supabase database management commands');
|
|
17
|
-
this.registerConnectionCommands(supabaseCmd);
|
|
18
|
-
this.registerDataCommands(supabaseCmd);
|
|
19
|
-
this.registerMLCommands(supabaseCmd);
|
|
20
|
-
}
|
|
21
|
-
registerConnectionCommands(supabaseCmd) {
|
|
22
|
-
// Test connection
|
|
23
|
-
this.addSubcommand(supabaseCmd, {
|
|
24
|
-
name: 'test',
|
|
25
|
-
description: 'Test Supabase database connection',
|
|
26
|
-
action: async () => {
|
|
27
|
-
this.logInfo('Testing Supabase connection...');
|
|
28
|
-
const isConnected = await supabaseClient.testConnection();
|
|
29
|
-
if (isConnected) {
|
|
30
|
-
this.logSuccess('Supabase connection successful');
|
|
31
|
-
const info = supabaseClient.getConnectionInfo();
|
|
32
|
-
this.logInfo(`Connection info: ${JSON.stringify(info)}`);
|
|
33
|
-
}
|
|
34
|
-
else {
|
|
35
|
-
throw new Error('Supabase connection failed');
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
});
|
|
39
|
-
// Initialize schema
|
|
40
|
-
this.addSubcommand(supabaseCmd, {
|
|
41
|
-
name: 'init',
|
|
42
|
-
description: 'Initialize database schema',
|
|
43
|
-
action: async () => {
|
|
44
|
-
this.logInfo('Initializing database schema...');
|
|
45
|
-
const persistence = new DatabasePersistence();
|
|
46
|
-
const success = await persistence.initializeSchema();
|
|
47
|
-
if (success) {
|
|
48
|
-
this.logSuccess('Database schema initialized');
|
|
49
|
-
this.logInfo('Note: Run the following SQL in your Supabase dashboard:');
|
|
50
|
-
this.logInfo(CREATE_TABLES_SQL);
|
|
51
|
-
}
|
|
52
|
-
else {
|
|
53
|
-
throw new Error('Failed to initialize schema');
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
});
|
|
57
|
-
// Sync management
|
|
58
|
-
this.addSubcommand(supabaseCmd, {
|
|
59
|
-
name: 'sync',
|
|
60
|
-
description: 'Synchronize data with Supabase',
|
|
61
|
-
options: [
|
|
62
|
-
{ flags: '-f, --force', description: 'Force full synchronization', defaultValue: false }
|
|
63
|
-
],
|
|
64
|
-
action: async (_options) => {
|
|
65
|
-
this.logInfo('Synchronizing data with Supabase...');
|
|
66
|
-
const persistence = new DatabasePersistence();
|
|
67
|
-
// Test connection first
|
|
68
|
-
const isConnected = await persistence.testConnection();
|
|
69
|
-
if (!isConnected) {
|
|
70
|
-
throw new Error('Cannot sync - database not available');
|
|
71
|
-
}
|
|
72
|
-
// Sync configuration
|
|
73
|
-
this.logInfo('Syncing configuration...');
|
|
74
|
-
// Configuration sync is handled automatically by CloudConfigManager
|
|
75
|
-
// Sync history (this would be done automatically by the enhanced history system)
|
|
76
|
-
this.logInfo('Syncing history...');
|
|
77
|
-
// History sync is handled by EnhancedHistorySystem
|
|
78
|
-
this.logSuccess('Synchronization completed');
|
|
79
|
-
}
|
|
80
|
-
});
|
|
81
|
-
}
|
|
82
|
-
registerDataCommands(supabaseCmd) {
|
|
83
|
-
// History management
|
|
84
|
-
this.addSubcommand(supabaseCmd, {
|
|
85
|
-
name: 'history',
|
|
86
|
-
description: 'Manage shell history',
|
|
87
|
-
options: [
|
|
88
|
-
{ flags: '-l, --list', description: 'List recent history entries', defaultValue: false },
|
|
89
|
-
{ flags: '-c, --count <number>', description: 'Number of entries to show', defaultValue: '10' },
|
|
90
|
-
{ flags: '-s, --search <query>', description: 'Search history entries' }
|
|
91
|
-
],
|
|
92
|
-
action: async (options) => {
|
|
93
|
-
const opts = options;
|
|
94
|
-
const persistence = new DatabasePersistence();
|
|
95
|
-
if (opts.list) {
|
|
96
|
-
const count = parseInt(opts.count);
|
|
97
|
-
const entries = await persistence.getHistoryEntries(count);
|
|
98
|
-
this.logInfo(`Recent ${entries.length} history entries:`);
|
|
99
|
-
entries.forEach((entry, index) => {
|
|
100
|
-
const timestamp = new Date(entry.timestamp).toLocaleString();
|
|
101
|
-
const exitCode = entry.exit_code ? ` (exit: ${entry.exit_code})` : '';
|
|
102
|
-
this.logInfo(`${index + 1}. [${timestamp}] ${entry.command}${exitCode}`);
|
|
103
|
-
});
|
|
104
|
-
}
|
|
105
|
-
else if (opts.search) {
|
|
106
|
-
const entries = await persistence.getHistoryEntries(100);
|
|
107
|
-
const filtered = entries.filter(entry => entry.command.toLowerCase().includes(opts.search.toLowerCase()));
|
|
108
|
-
this.logInfo(`Found ${filtered.length} matching entries:`);
|
|
109
|
-
filtered.forEach((entry, index) => {
|
|
110
|
-
const timestamp = new Date(entry.timestamp).toLocaleString();
|
|
111
|
-
this.logInfo(`${index + 1}. [${timestamp}] ${entry.command}`);
|
|
112
|
-
});
|
|
113
|
-
}
|
|
114
|
-
else {
|
|
115
|
-
this.logInfo('Use --list or --search to manage history');
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
});
|
|
119
|
-
// Configuration management
|
|
120
|
-
this.addSubcommand(supabaseCmd, {
|
|
121
|
-
name: 'config',
|
|
122
|
-
description: 'Manage shell configuration',
|
|
123
|
-
options: [
|
|
124
|
-
{ flags: '-l, --list', description: 'List all configuration', defaultValue: false },
|
|
125
|
-
{ flags: '-g, --get <key>', description: 'Get configuration value' },
|
|
126
|
-
{ flags: '-s, --set <key> <value>', description: 'Set configuration value' },
|
|
127
|
-
{ flags: '-d, --delete <key>', description: 'Delete configuration key' },
|
|
128
|
-
{ flags: '-e, --export', description: 'Export configuration to JSON', defaultValue: false }
|
|
129
|
-
],
|
|
130
|
-
action: async (options) => {
|
|
131
|
-
const opts = options;
|
|
132
|
-
const configManager = new CloudConfigManager();
|
|
133
|
-
if (opts.list) {
|
|
134
|
-
const config = configManager.getAll();
|
|
135
|
-
this.logInfo('Current configuration:');
|
|
136
|
-
config.forEach(item => {
|
|
137
|
-
this.logInfo(` ${item.key}: ${JSON.stringify(item.value)}`);
|
|
138
|
-
});
|
|
139
|
-
}
|
|
140
|
-
else if (opts.get) {
|
|
141
|
-
const value = configManager.get(opts.get);
|
|
142
|
-
if (value !== undefined) {
|
|
143
|
-
this.logInfo(`${opts.get}: ${JSON.stringify(value)}`);
|
|
144
|
-
}
|
|
145
|
-
else {
|
|
146
|
-
this.logWarning(`Configuration key '${opts.get}' not found`);
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
else if (opts.set) {
|
|
150
|
-
const [key, value] = opts.set;
|
|
151
|
-
configManager.set(key, value);
|
|
152
|
-
this.logSuccess(`Configuration '${key}' set to: ${value}`);
|
|
153
|
-
}
|
|
154
|
-
else if (opts.delete) {
|
|
155
|
-
configManager.delete(opts.delete);
|
|
156
|
-
this.logSuccess(`Configuration '${opts.delete}' deleted`);
|
|
157
|
-
}
|
|
158
|
-
else if (opts.export) {
|
|
159
|
-
const exported = configManager.export();
|
|
160
|
-
this.logInfo(exported);
|
|
161
|
-
}
|
|
162
|
-
else {
|
|
163
|
-
this.logInfo('Use --list, --get, --set, --delete, or --export to manage configuration');
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
});
|
|
167
|
-
// Jobs management
|
|
168
|
-
this.addSubcommand(supabaseCmd, {
|
|
169
|
-
name: 'jobs',
|
|
170
|
-
description: 'Manage shell jobs',
|
|
171
|
-
options: [
|
|
172
|
-
{ flags: '-l, --list', description: 'List active jobs', defaultValue: false },
|
|
173
|
-
{ flags: '-h, --history', description: 'List job history', defaultValue: false }
|
|
174
|
-
],
|
|
175
|
-
action: async (options) => {
|
|
176
|
-
const opts = options;
|
|
177
|
-
const persistence = new DatabasePersistence();
|
|
178
|
-
if (opts.list) {
|
|
179
|
-
const jobs = await persistence.getActiveJobs();
|
|
180
|
-
this.logInfo(`Active jobs (${jobs.length}):`);
|
|
181
|
-
jobs.forEach(job => {
|
|
182
|
-
const started = new Date(job.started_at).toLocaleString();
|
|
183
|
-
this.logInfo(`${job.job_id}: ${job.command} (${job.status}) - Started: ${started}`);
|
|
184
|
-
});
|
|
185
|
-
}
|
|
186
|
-
else if (opts.history) {
|
|
187
|
-
this.logInfo('Job history feature not yet implemented');
|
|
188
|
-
}
|
|
189
|
-
else {
|
|
190
|
-
this.logInfo('Use --list or --history to manage jobs');
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
});
|
|
194
|
-
// Database rows management
|
|
195
|
-
this.addSubcommand(supabaseCmd, {
|
|
196
|
-
name: 'rows',
|
|
197
|
-
description: 'Show latest database entries',
|
|
198
|
-
options: [
|
|
199
|
-
{ flags: '-l, --limit <number>', description: 'Number of rows to show per table', defaultValue: '5' },
|
|
200
|
-
{ flags: '-t, --table <name>', description: 'Show rows from specific table only' }
|
|
201
|
-
],
|
|
202
|
-
action: async (options) => {
|
|
203
|
-
const opts = options;
|
|
204
|
-
const persistence = new DatabasePersistence();
|
|
205
|
-
const limit = parseInt(opts.limit);
|
|
206
|
-
// Test connection first
|
|
207
|
-
const isConnected = await persistence.testConnection();
|
|
208
|
-
if (!isConnected) {
|
|
209
|
-
throw new Error('Cannot fetch rows - database not available');
|
|
210
|
-
}
|
|
211
|
-
if (opts.table) {
|
|
212
|
-
// Show rows from specific table
|
|
213
|
-
this.logInfo(`Latest ${limit} entries from table '${opts.table}':`);
|
|
214
|
-
const rows = await persistence.getLatestRowsFromTable(opts.table, limit);
|
|
215
|
-
if (rows.length === 0) {
|
|
216
|
-
this.logInfo('No entries found.');
|
|
217
|
-
}
|
|
218
|
-
else {
|
|
219
|
-
rows.forEach((row, index) => {
|
|
220
|
-
const timestamp = row.created_at ? new Date(row.created_at).toLocaleString() : 'N/A';
|
|
221
|
-
this.logInfo(`\n${index + 1}. [${timestamp}]`);
|
|
222
|
-
this.logInfo(JSON.stringify(row, null, 2));
|
|
223
|
-
});
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
else {
|
|
227
|
-
// Show rows from all tables
|
|
228
|
-
this.logInfo(`Latest ${limit} entries from each table:`);
|
|
229
|
-
const allRows = await persistence.getLatestRows(limit);
|
|
230
|
-
for (const [tableName, rows] of Object.entries(allRows)) {
|
|
231
|
-
this.logInfo(`\n=== ${tableName.toUpperCase()} ===`);
|
|
232
|
-
if (rows.length === 0) {
|
|
233
|
-
this.logInfo('No entries found.');
|
|
234
|
-
}
|
|
235
|
-
else {
|
|
236
|
-
rows.forEach((row, index) => {
|
|
237
|
-
const timestamp = row.created_at ? new Date(row.created_at).toLocaleString() : 'N/A';
|
|
238
|
-
this.logInfo(`\n${index + 1}. [${timestamp}]`);
|
|
239
|
-
this.logInfo(JSON.stringify(row, null, 2));
|
|
240
|
-
});
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
|
-
});
|
|
246
|
-
}
|
|
247
|
-
registerMLCommands(supabaseCmd) {
|
|
248
|
-
// ML Training Jobs
|
|
249
|
-
this.addSubcommand(supabaseCmd, {
|
|
250
|
-
name: 'ml-train',
|
|
251
|
-
description: 'Manage ML training jobs',
|
|
252
|
-
options: [
|
|
253
|
-
{ flags: '-l, --list', description: 'List training jobs', defaultValue: false },
|
|
254
|
-
{ flags: '-s, --status <status>', description: 'Filter by status (pending, running, completed, failed)' },
|
|
255
|
-
{ flags: '-c, --create <name>', description: 'Create new training job' },
|
|
256
|
-
{ flags: '--model-type <type>', description: 'Model type for new job' },
|
|
257
|
-
{ flags: '--dataset <name>', description: 'Dataset name for new job' }
|
|
258
|
-
],
|
|
259
|
-
action: async (options) => {
|
|
260
|
-
const opts = options;
|
|
261
|
-
if (opts.list) {
|
|
262
|
-
let query = supabaseClient.getClient()
|
|
263
|
-
.from(TABLES.ML_TRAINING_JOBS)
|
|
264
|
-
.select('*')
|
|
265
|
-
.order('created_at', { ascending: false });
|
|
266
|
-
if (opts.status) {
|
|
267
|
-
query = query.eq('status', opts.status);
|
|
268
|
-
}
|
|
269
|
-
const { data: jobs, error } = await query.limit(20);
|
|
270
|
-
if (error) {
|
|
271
|
-
throw new Error(`Failed to fetch training jobs: ${error.message}`);
|
|
272
|
-
}
|
|
273
|
-
this.logInfo(`Training Jobs (${jobs?.length || 0}):`);
|
|
274
|
-
jobs?.forEach(job => {
|
|
275
|
-
const created = new Date(job.created_at).toLocaleString();
|
|
276
|
-
this.logInfo(`\n${job.job_name} (${job.model_type})`);
|
|
277
|
-
this.logInfo(` Status: ${job.status}`);
|
|
278
|
-
this.logInfo(` Created: ${created}`);
|
|
279
|
-
this.logInfo(` Dataset: ${job.dataset_name}`);
|
|
280
|
-
});
|
|
281
|
-
}
|
|
282
|
-
else if (opts.create) {
|
|
283
|
-
if (!opts.modelType || !opts.dataset) {
|
|
284
|
-
throw new Error('Both --model-type and --dataset are required to create a job');
|
|
285
|
-
}
|
|
286
|
-
const { data, error } = await supabaseClient.getClient()
|
|
287
|
-
.from('ml_training_jobs')
|
|
288
|
-
.insert({
|
|
289
|
-
job_name: opts.create,
|
|
290
|
-
model_type: opts.modelType,
|
|
291
|
-
dataset_name: opts.dataset,
|
|
292
|
-
status: 'pending',
|
|
293
|
-
created_at: new Date().toISOString()
|
|
294
|
-
})
|
|
295
|
-
.select();
|
|
296
|
-
if (error) {
|
|
297
|
-
throw new Error(`Failed to create training job: ${error.message}`);
|
|
298
|
-
}
|
|
299
|
-
this.logSuccess(`Created training job: ${opts.create}`);
|
|
300
|
-
this.logInfo(JSON.stringify(data, null, 2));
|
|
301
|
-
}
|
|
302
|
-
else {
|
|
303
|
-
this.logInfo('Use --list or --create to manage training jobs');
|
|
304
|
-
}
|
|
305
|
-
}
|
|
306
|
-
});
|
|
307
|
-
// ML Models
|
|
308
|
-
this.addSubcommand(supabaseCmd, {
|
|
309
|
-
name: 'ml-models',
|
|
310
|
-
description: 'Manage ML models',
|
|
311
|
-
options: [
|
|
312
|
-
{ flags: '-l, --list', description: 'List ML models', defaultValue: false },
|
|
313
|
-
{ flags: '--deployed', description: 'Filter by deployed models only', defaultValue: false }
|
|
314
|
-
],
|
|
315
|
-
action: async (options) => {
|
|
316
|
-
const opts = options;
|
|
317
|
-
if (opts.list) {
|
|
318
|
-
let query = supabaseClient.getClient()
|
|
319
|
-
.from(TABLES.ML_MODELS)
|
|
320
|
-
.select('*')
|
|
321
|
-
.order('created_at', { ascending: false });
|
|
322
|
-
if (opts.deployed) {
|
|
323
|
-
query = query.eq('deployed', true);
|
|
324
|
-
}
|
|
325
|
-
const { data: models, error } = await query.limit(20);
|
|
326
|
-
if (error) {
|
|
327
|
-
throw new Error(`Failed to fetch models: ${error.message}`);
|
|
328
|
-
}
|
|
329
|
-
this.logInfo(`ML Models (${models?.length || 0}):`);
|
|
330
|
-
models?.forEach(model => {
|
|
331
|
-
const created = new Date(model.created_at).toLocaleString();
|
|
332
|
-
this.logInfo(`\n${model.model_name} (v${model.version})`);
|
|
333
|
-
this.logInfo(` Type: ${model.model_type}`);
|
|
334
|
-
this.logInfo(` Accuracy: ${model.accuracy}`);
|
|
335
|
-
this.logInfo(` Deployed: ${model.deployed ? 'Yes' : 'No'}`);
|
|
336
|
-
this.logInfo(` Created: ${created}`);
|
|
337
|
-
});
|
|
338
|
-
}
|
|
339
|
-
else {
|
|
340
|
-
this.logInfo('Use --list to manage ML models');
|
|
341
|
-
}
|
|
342
|
-
}
|
|
343
|
-
});
|
|
344
|
-
// ML Features
|
|
345
|
-
this.addSubcommand(supabaseCmd, {
|
|
346
|
-
name: 'ml-features',
|
|
347
|
-
description: 'Manage ML feature definitions',
|
|
348
|
-
options: [
|
|
349
|
-
{ flags: '-l, --list', description: 'List feature definitions', defaultValue: false }
|
|
350
|
-
],
|
|
351
|
-
action: async (options) => {
|
|
352
|
-
const opts = options;
|
|
353
|
-
if (opts.list) {
|
|
354
|
-
const { data: features, error } = await supabaseClient.getClient()
|
|
355
|
-
.from(TABLES.ML_FEATURES)
|
|
356
|
-
.select('*')
|
|
357
|
-
.order('created_at', { ascending: false })
|
|
358
|
-
.limit(20);
|
|
359
|
-
if (error) {
|
|
360
|
-
throw new Error(`Failed to fetch features: ${error.message}`);
|
|
361
|
-
}
|
|
362
|
-
this.logInfo(`ML Features (${features?.length || 0}):`);
|
|
363
|
-
features?.forEach(feature => {
|
|
364
|
-
this.logInfo(`\n${feature.feature_name}`);
|
|
365
|
-
this.logInfo(` Type: ${feature.feature_type}`);
|
|
366
|
-
this.logInfo(` Importance: ${feature.importance_score}`);
|
|
367
|
-
});
|
|
368
|
-
}
|
|
369
|
-
else {
|
|
370
|
-
this.logInfo('Use --list to manage ML features');
|
|
371
|
-
}
|
|
372
|
-
}
|
|
373
|
-
});
|
|
374
|
-
}
|
|
375
|
-
}
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Supabase Service - CLI command registration
|
|
3
|
-
* Uses SupabaseCommandRegistrar for clean, maintainable command setup
|
|
4
|
-
*/
|
|
5
|
-
import { SupabaseCommandRegistrar } from './supabase-registrar.js';
|
|
6
|
-
export async function init_supabase(program) {
|
|
7
|
-
const registrar = new SupabaseCommandRegistrar();
|
|
8
|
-
await registrar.register(program);
|
|
9
|
-
}
|