lsh-framework 3.2.5 → 3.5.1

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.
Files changed (54) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +72 -34
  3. package/dist/commands/ipfs.js +7 -12
  4. package/dist/commands/self.js +22 -16
  5. package/dist/commands/sync.js +49 -38
  6. package/dist/constants/config.js +3 -0
  7. package/dist/lib/floating-point-arithmetic.js +2 -2
  8. package/dist/lib/ipfs-client-manager.js +51 -13
  9. package/dist/lib/ipfs-secrets-storage.js +21 -16
  10. package/dist/lib/ipfs-sync.js +88 -14
  11. package/dist/lib/secrets-manager.js +117 -47
  12. package/dist/lib/sync-key-store.js +87 -0
  13. package/dist/services/secrets/secrets.js +77 -39
  14. package/package.json +16 -16
  15. package/dist/__tests__/fixtures/job-fixtures.js +0 -204
  16. package/dist/__tests__/fixtures/supabase-mocks.js +0 -252
  17. package/dist/daemon/job-registry.js +0 -556
  18. package/dist/daemon/lshd.js +0 -968
  19. package/dist/daemon/saas-api-routes.js +0 -599
  20. package/dist/daemon/saas-api-server.js +0 -231
  21. package/dist/examples/supabase-integration.js +0 -106
  22. package/dist/lib/api-response.js +0 -226
  23. package/dist/lib/base-command-registrar.js +0 -287
  24. package/dist/lib/base-job-manager.js +0 -295
  25. package/dist/lib/cloud-config-manager.js +0 -348
  26. package/dist/lib/cron-job-manager.js +0 -368
  27. package/dist/lib/daemon-client-helper.js +0 -145
  28. package/dist/lib/daemon-client.js +0 -513
  29. package/dist/lib/database-persistence.js +0 -727
  30. package/dist/lib/database-schema.js +0 -259
  31. package/dist/lib/database-types.js +0 -90
  32. package/dist/lib/enhanced-history-system.js +0 -247
  33. package/dist/lib/history-system.js +0 -246
  34. package/dist/lib/job-manager.js +0 -436
  35. package/dist/lib/job-storage-database.js +0 -164
  36. package/dist/lib/job-storage-memory.js +0 -73
  37. package/dist/lib/local-storage-adapter.js +0 -507
  38. package/dist/lib/optimized-job-scheduler.js +0 -356
  39. package/dist/lib/saas-audit.js +0 -215
  40. package/dist/lib/saas-auth.js +0 -465
  41. package/dist/lib/saas-billing.js +0 -503
  42. package/dist/lib/saas-email.js +0 -403
  43. package/dist/lib/saas-encryption.js +0 -221
  44. package/dist/lib/saas-organizations.js +0 -662
  45. package/dist/lib/saas-secrets.js +0 -408
  46. package/dist/lib/saas-types.js +0 -165
  47. package/dist/lib/supabase-client.js +0 -125
  48. package/dist/lib/supabase-utils.js +0 -396
  49. package/dist/services/cron/cron-registrar.js +0 -240
  50. package/dist/services/cron/cron.js +0 -9
  51. package/dist/services/daemon/daemon-registrar.js +0 -585
  52. package/dist/services/daemon/daemon.js +0 -9
  53. package/dist/services/supabase/supabase-registrar.js +0 -375
  54. package/dist/services/supabase/supabase.js +0 -9
@@ -1,204 +0,0 @@
1
- /**
2
- * Job Fixtures for Testing
3
- *
4
- * Provides factory functions and sample data for testing job-related functionality.
5
- *
6
- * @example
7
- * ```typescript
8
- * import { createTestJob, SAMPLE_JOBS } from '../fixtures/job-fixtures';
9
- *
10
- * const job = createTestJob({ name: 'my-test-job', command: 'echo test' });
11
- * ```
12
- */
13
- // ============================================================================
14
- // FACTORY FUNCTIONS
15
- // ============================================================================
16
- /**
17
- * Create a test job specification with sensible defaults.
18
- */
19
- export function createTestJob(overrides = {}) {
20
- const id = `job_${Math.random().toString(36).substr(2, 9)}`;
21
- return {
22
- id,
23
- name: 'test-job',
24
- command: 'echo "test"',
25
- args: [],
26
- status: 'created',
27
- createdAt: new Date(),
28
- tags: [],
29
- priority: 5,
30
- maxRetries: 3,
31
- retryCount: 0,
32
- databaseSync: false, // Disable DB sync in tests by default
33
- ...overrides,
34
- };
35
- }
36
- /**
37
- * Create a test job execution record.
38
- */
39
- export function createTestExecution(overrides = {}) {
40
- const executionId = `exec_${Math.random().toString(36).substr(2, 9)}`;
41
- return {
42
- executionId,
43
- jobId: `job_${Math.random().toString(36).substr(2, 9)}`,
44
- jobName: 'test-job',
45
- command: 'echo "test"',
46
- startTime: new Date(),
47
- status: 'completed',
48
- exitCode: 0,
49
- ...overrides,
50
- };
51
- }
52
- /**
53
- * Create a scheduled job with cron expression.
54
- */
55
- export function createScheduledJob(cronExpression, overrides = {}) {
56
- return createTestJob({
57
- name: 'scheduled-job',
58
- command: './scripts/scheduled.sh',
59
- schedule: {
60
- cron: cronExpression,
61
- },
62
- ...overrides,
63
- });
64
- }
65
- /**
66
- * Create a job with interval scheduling.
67
- */
68
- export function createIntervalJob(intervalMs, overrides = {}) {
69
- return createTestJob({
70
- name: 'interval-job',
71
- command: './scripts/interval.sh',
72
- schedule: {
73
- interval: intervalMs,
74
- },
75
- ...overrides,
76
- });
77
- }
78
- // ============================================================================
79
- // SAMPLE DATA
80
- // ============================================================================
81
- /**
82
- * Collection of sample jobs for different test scenarios.
83
- */
84
- export const SAMPLE_JOBS = {
85
- /** Simple echo job */
86
- simple: createTestJob({
87
- id: 'job_simple',
88
- name: 'simple-job',
89
- command: 'echo "hello"',
90
- }),
91
- /** Job with environment variables */
92
- withEnv: createTestJob({
93
- id: 'job_with_env',
94
- name: 'env-job',
95
- command: 'printenv',
96
- env: {
97
- MY_VAR: 'test_value',
98
- ANOTHER_VAR: '123',
99
- },
100
- }),
101
- /** Job with arguments */
102
- withArgs: createTestJob({
103
- id: 'job_with_args',
104
- name: 'args-job',
105
- command: 'ls',
106
- args: ['-la', '/tmp'],
107
- }),
108
- /** Scheduled job (daily at midnight) */
109
- scheduled: createScheduledJob('0 0 * * *', {
110
- id: 'job_scheduled',
111
- name: 'daily-job',
112
- }),
113
- /** Interval job (every 5 minutes) */
114
- interval: createIntervalJob(5 * 60 * 1000, {
115
- id: 'job_interval',
116
- name: 'frequent-job',
117
- }),
118
- /** Long-running job with timeout */
119
- longRunning: createTestJob({
120
- id: 'job_long',
121
- name: 'long-running-job',
122
- command: 'sleep 300',
123
- timeout: 60000, // 1 minute timeout
124
- }),
125
- /** Job that will fail */
126
- failing: createTestJob({
127
- id: 'job_failing',
128
- name: 'failing-job',
129
- command: 'exit 1',
130
- maxRetries: 2,
131
- }),
132
- /** Completed job */
133
- completed: createTestJob({
134
- id: 'job_completed',
135
- name: 'completed-job',
136
- command: 'echo "done"',
137
- status: 'completed',
138
- startedAt: new Date(Date.now() - 1000),
139
- completedAt: new Date(),
140
- exitCode: 0,
141
- stdout: 'done\n',
142
- }),
143
- /** Failed job */
144
- failed: createTestJob({
145
- id: 'job_failed',
146
- name: 'failed-job',
147
- command: 'false',
148
- status: 'failed',
149
- startedAt: new Date(Date.now() - 1000),
150
- completedAt: new Date(),
151
- exitCode: 1,
152
- stderr: 'Command failed\n',
153
- retryCount: 3,
154
- }),
155
- /** Secrets rotation job (realistic example) */
156
- secretsRotation: createScheduledJob('0 2 1 * *', {
157
- id: 'job_secrets_rotation',
158
- name: 'rotate-api-keys',
159
- command: './examples/secrets-rotation/rotate-api-keys.sh',
160
- description: 'Monthly API key rotation',
161
- tags: ['secrets', 'maintenance', 'security'],
162
- env: {
163
- LSH_ENVIRONMENT: 'production',
164
- LOG_LEVEL: 'info',
165
- },
166
- timeout: 300000, // 5 minutes
167
- }),
168
- };
169
- /**
170
- * Sample execution records for testing history/statistics.
171
- */
172
- export const SAMPLE_EXECUTIONS = {
173
- success: createTestExecution({
174
- executionId: 'exec_success',
175
- jobId: 'job_simple',
176
- status: 'completed',
177
- exitCode: 0,
178
- duration: 150,
179
- stdout: 'hello\n',
180
- }),
181
- failure: createTestExecution({
182
- executionId: 'exec_failure',
183
- jobId: 'job_failing',
184
- status: 'failed',
185
- exitCode: 1,
186
- duration: 50,
187
- stderr: 'Error: Command failed\n',
188
- errorMessage: 'Process exited with code 1',
189
- }),
190
- timeout: createTestExecution({
191
- executionId: 'exec_timeout',
192
- jobId: 'job_long',
193
- status: 'timeout',
194
- duration: 60000,
195
- errorMessage: 'Job exceeded timeout of 60000ms',
196
- }),
197
- killed: createTestExecution({
198
- executionId: 'exec_killed',
199
- jobId: 'job_simple',
200
- status: 'killed',
201
- duration: 5000,
202
- errorMessage: 'Process killed by signal SIGTERM',
203
- }),
204
- };
@@ -1,252 +0,0 @@
1
- /**
2
- * Supabase Mock Utilities for Testing
3
- *
4
- * Provides mock Supabase client and factory functions for creating
5
- * test data that matches the database schema.
6
- *
7
- * @example
8
- * ```typescript
9
- * import { createMockSupabase, mockOrganization } from '../fixtures/supabase-mocks';
10
- *
11
- * const supabase = createMockSupabase({
12
- * organizations: [mockOrganization({ name: 'Test Org' })],
13
- * });
14
- * ```
15
- */
16
- // ============================================================================
17
- // FACTORY FUNCTIONS
18
- // ============================================================================
19
- /**
20
- * Create a mock organization record with sensible defaults.
21
- * Override any field by passing it in the partial.
22
- */
23
- export function mockOrganization(overrides = {}) {
24
- const now = new Date().toISOString();
25
- return {
26
- id: `org_${Math.random().toString(36).substr(2, 9)}`,
27
- name: 'Test Organization',
28
- slug: 'test-org',
29
- stripe_customer_id: null,
30
- subscription_tier: 'free',
31
- subscription_status: 'active',
32
- subscription_expires_at: null,
33
- settings: null,
34
- created_at: now,
35
- updated_at: now,
36
- deleted_at: null,
37
- ...overrides,
38
- };
39
- }
40
- /**
41
- * Create a mock user record with sensible defaults.
42
- */
43
- export function mockUser(overrides = {}) {
44
- const now = new Date().toISOString();
45
- const id = `user_${Math.random().toString(36).substr(2, 9)}`;
46
- return {
47
- id,
48
- email: `${id}@example.com`,
49
- email_verified: true,
50
- email_verification_token: null,
51
- email_verification_expires_at: null,
52
- password_hash: '$2b$12$mockhashmockhashmockhashmockhash', // Not a real hash
53
- oauth_provider: null,
54
- oauth_provider_id: null,
55
- first_name: 'Test',
56
- last_name: 'User',
57
- avatar_url: null,
58
- last_login_at: now,
59
- last_login_ip: '127.0.0.1',
60
- created_at: now,
61
- updated_at: now,
62
- deleted_at: null,
63
- ...overrides,
64
- };
65
- }
66
- /**
67
- * Create a mock team record with sensible defaults.
68
- */
69
- export function mockTeam(overrides = {}) {
70
- const now = new Date().toISOString();
71
- return {
72
- id: `team_${Math.random().toString(36).substr(2, 9)}`,
73
- organization_id: `org_${Math.random().toString(36).substr(2, 9)}`,
74
- name: 'Test Team',
75
- slug: 'test-team',
76
- description: 'A test team',
77
- encryption_key_id: null,
78
- created_at: now,
79
- updated_at: now,
80
- deleted_at: null,
81
- ...overrides,
82
- };
83
- }
84
- /**
85
- * Create a mock secret record with sensible defaults.
86
- */
87
- export function mockSecret(overrides = {}) {
88
- const now = new Date().toISOString();
89
- return {
90
- id: `secret_${Math.random().toString(36).substr(2, 9)}`,
91
- team_id: `team_${Math.random().toString(36).substr(2, 9)}`,
92
- environment: 'development',
93
- key: 'TEST_SECRET',
94
- encrypted_value: 'encrypted_test_value',
95
- encryption_key_id: `key_${Math.random().toString(36).substr(2, 9)}`,
96
- description: 'A test secret',
97
- tags: '[]',
98
- last_rotated_at: null,
99
- rotation_interval_days: null,
100
- created_at: now,
101
- created_by: null,
102
- updated_at: now,
103
- updated_by: null,
104
- deleted_at: null,
105
- deleted_by: null,
106
- ...overrides,
107
- };
108
- }
109
- /**
110
- * Create a mock organization member record.
111
- */
112
- export function mockOrgMember(overrides = {}) {
113
- const now = new Date().toISOString();
114
- return {
115
- id: `member_${Math.random().toString(36).substr(2, 9)}`,
116
- organization_id: `org_${Math.random().toString(36).substr(2, 9)}`,
117
- user_id: `user_${Math.random().toString(36).substr(2, 9)}`,
118
- role: 'member',
119
- invited_by: null,
120
- invited_at: now,
121
- accepted_at: now,
122
- created_at: now,
123
- updated_at: now,
124
- ...overrides,
125
- };
126
- }
127
- /**
128
- * Create a successful Supabase response.
129
- */
130
- export function mockSuccess(data) {
131
- return { data, error: null };
132
- }
133
- /**
134
- * Create an error Supabase response.
135
- */
136
- export function mockError(message, code = 'PGRST000') {
137
- return { data: null, error: { message, code } };
138
- }
139
- /**
140
- * Create a mock Supabase client for testing.
141
- *
142
- * Returns data from the provided config based on query parameters.
143
- * Supports basic filtering via .eq() and .single().
144
- *
145
- * @example
146
- * ```typescript
147
- * const mockClient = createMockSupabase({
148
- * organizations: [mockOrganization({ id: 'org_123' })],
149
- * });
150
- *
151
- * // In test
152
- * jest.mock('../../lib/supabase-client', () => ({
153
- * getSupabaseClient: () => mockClient,
154
- * }));
155
- * ```
156
- */
157
- export function createMockSupabase(config = {}) {
158
- const tables = {
159
- organizations: config.organizations || [],
160
- users: config.users || [],
161
- teams: config.teams || [],
162
- secrets: config.secrets || [],
163
- organization_members: config.members || [],
164
- };
165
- return {
166
- from: (tableName) => {
167
- const tableData = tables[tableName] || [];
168
- let filteredData = [...tableData];
169
- let isSingle = false;
170
- const queryBuilder = {
171
- select: (_columns) => queryBuilder,
172
- insert: (data) => {
173
- if (Array.isArray(data)) {
174
- tableData.push(...data);
175
- }
176
- else {
177
- tableData.push(data);
178
- }
179
- filteredData = Array.isArray(data) ? data : [data];
180
- return queryBuilder;
181
- },
182
- update: (_data) => queryBuilder,
183
- delete: () => queryBuilder,
184
- eq: (column, value) => {
185
- filteredData = filteredData.filter((row) => row[column] === value);
186
- return queryBuilder;
187
- },
188
- neq: (column, value) => {
189
- filteredData = filteredData.filter((row) => row[column] !== value);
190
- return queryBuilder;
191
- },
192
- is: (column, value) => {
193
- filteredData = filteredData.filter((row) => row[column] === value);
194
- return queryBuilder;
195
- },
196
- order: (_column, _options) => queryBuilder,
197
- limit: (count) => {
198
- filteredData = filteredData.slice(0, count);
199
- return queryBuilder;
200
- },
201
- single: () => {
202
- isSingle = true;
203
- return queryBuilder;
204
- },
205
- then: (resolve) => {
206
- if (isSingle) {
207
- if (filteredData.length === 0) {
208
- resolve(mockError('No rows found', 'PGRST116'));
209
- }
210
- else {
211
- resolve(mockSuccess(filteredData[0]));
212
- }
213
- }
214
- else {
215
- resolve(mockSuccess(filteredData));
216
- }
217
- },
218
- };
219
- return queryBuilder;
220
- },
221
- };
222
- }
223
- // ============================================================================
224
- // SAMPLE DATA
225
- // ============================================================================
226
- /**
227
- * Pre-built sample organization for quick testing.
228
- */
229
- export const SAMPLE_ORG = mockOrganization({
230
- id: 'org_sample123',
231
- name: 'Sample Organization',
232
- slug: 'sample-org',
233
- subscription_tier: 'pro',
234
- });
235
- /**
236
- * Pre-built sample user for quick testing.
237
- */
238
- export const SAMPLE_USER = mockUser({
239
- id: 'user_sample123',
240
- email: 'sample@example.com',
241
- first_name: 'Sample',
242
- last_name: 'User',
243
- });
244
- /**
245
- * Pre-built sample team for quick testing.
246
- */
247
- export const SAMPLE_TEAM = mockTeam({
248
- id: 'team_sample123',
249
- organization_id: 'org_sample123',
250
- name: 'Sample Team',
251
- slug: 'sample-team',
252
- });