longcelot-sheet-db 0.1.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.
Files changed (97) hide show
  1. package/API.md +608 -0
  2. package/CHANGELOG.md +0 -0
  3. package/LICENSE +21 -0
  4. package/README.md +369 -0
  5. package/dist/adapter/crud.d.ts +20 -0
  6. package/dist/adapter/crud.d.ts.map +1 -0
  7. package/dist/adapter/crud.js +219 -0
  8. package/dist/adapter/crud.js.map +1 -0
  9. package/dist/adapter/sheetAdapter.d.ts +31 -0
  10. package/dist/adapter/sheetAdapter.d.ts.map +1 -0
  11. package/dist/adapter/sheetAdapter.js +110 -0
  12. package/dist/adapter/sheetAdapter.js.map +1 -0
  13. package/dist/adapter/sheetClient.d.ts +20 -0
  14. package/dist/adapter/sheetClient.d.ts.map +1 -0
  15. package/dist/adapter/sheetClient.js +112 -0
  16. package/dist/adapter/sheetClient.js.map +1 -0
  17. package/dist/auth/oauth.d.ts +15 -0
  18. package/dist/auth/oauth.d.ts.map +1 -0
  19. package/dist/auth/oauth.js +37 -0
  20. package/dist/auth/oauth.js.map +1 -0
  21. package/dist/auth/password.d.ts +7 -0
  22. package/dist/auth/password.d.ts.map +1 -0
  23. package/dist/auth/password.js +36 -0
  24. package/dist/auth/password.js.map +1 -0
  25. package/dist/cli/commands/doctor.d.ts +2 -0
  26. package/dist/cli/commands/doctor.d.ts.map +1 -0
  27. package/dist/cli/commands/doctor.js +91 -0
  28. package/dist/cli/commands/doctor.js.map +1 -0
  29. package/dist/cli/commands/generate.d.ts +2 -0
  30. package/dist/cli/commands/generate.d.ts.map +1 -0
  31. package/dist/cli/commands/generate.js +121 -0
  32. package/dist/cli/commands/generate.js.map +1 -0
  33. package/dist/cli/commands/init.d.ts +2 -0
  34. package/dist/cli/commands/init.d.ts.map +1 -0
  35. package/dist/cli/commands/init.js +122 -0
  36. package/dist/cli/commands/init.js.map +1 -0
  37. package/dist/cli/commands/seed.d.ts +2 -0
  38. package/dist/cli/commands/seed.d.ts.map +1 -0
  39. package/dist/cli/commands/seed.js +119 -0
  40. package/dist/cli/commands/seed.js.map +1 -0
  41. package/dist/cli/commands/status.d.ts +2 -0
  42. package/dist/cli/commands/status.d.ts.map +1 -0
  43. package/dist/cli/commands/status.js +106 -0
  44. package/dist/cli/commands/status.js.map +1 -0
  45. package/dist/cli/commands/sync.d.ts +2 -0
  46. package/dist/cli/commands/sync.d.ts.map +1 -0
  47. package/dist/cli/commands/sync.js +152 -0
  48. package/dist/cli/commands/sync.js.map +1 -0
  49. package/dist/cli/commands/validate.d.ts +2 -0
  50. package/dist/cli/commands/validate.d.ts.map +1 -0
  51. package/dist/cli/commands/validate.js +91 -0
  52. package/dist/cli/commands/validate.js.map +1 -0
  53. package/dist/cli/index.d.ts +3 -0
  54. package/dist/cli/index.d.ts.map +1 -0
  55. package/dist/cli/index.js +46 -0
  56. package/dist/cli/index.js.map +1 -0
  57. package/dist/errors/PermissionError.d.ts +5 -0
  58. package/dist/errors/PermissionError.d.ts.map +1 -0
  59. package/dist/errors/PermissionError.js +13 -0
  60. package/dist/errors/PermissionError.js.map +1 -0
  61. package/dist/errors/SchemaError.d.ts +5 -0
  62. package/dist/errors/SchemaError.d.ts.map +1 -0
  63. package/dist/errors/SchemaError.js +13 -0
  64. package/dist/errors/SchemaError.js.map +1 -0
  65. package/dist/errors/ValidationError.d.ts +5 -0
  66. package/dist/errors/ValidationError.d.ts.map +1 -0
  67. package/dist/errors/ValidationError.js +13 -0
  68. package/dist/errors/ValidationError.js.map +1 -0
  69. package/dist/errors/index.d.ts +4 -0
  70. package/dist/errors/index.d.ts.map +1 -0
  71. package/dist/errors/index.js +10 -0
  72. package/dist/errors/index.js.map +1 -0
  73. package/dist/index.d.ts +12 -0
  74. package/dist/index.d.ts.map +1 -0
  75. package/dist/index.js +29 -0
  76. package/dist/index.js.map +1 -0
  77. package/dist/schema/columnBuilder.d.ts +23 -0
  78. package/dist/schema/columnBuilder.d.ts.map +1 -0
  79. package/dist/schema/columnBuilder.js +78 -0
  80. package/dist/schema/columnBuilder.js.map +1 -0
  81. package/dist/schema/defineTable.d.ts +12 -0
  82. package/dist/schema/defineTable.d.ts.map +1 -0
  83. package/dist/schema/defineTable.js +31 -0
  84. package/dist/schema/defineTable.js.map +1 -0
  85. package/dist/schema/types.d.ts +50 -0
  86. package/dist/schema/types.d.ts.map +1 -0
  87. package/dist/schema/types.js +3 -0
  88. package/dist/schema/types.js.map +1 -0
  89. package/dist/utils/env.d.ts +6 -0
  90. package/dist/utils/env.d.ts.map +1 -0
  91. package/dist/utils/env.js +14 -0
  92. package/dist/utils/env.js.map +1 -0
  93. package/dist/utils/logger.d.ts +7 -0
  94. package/dist/utils/logger.d.ts.map +1 -0
  95. package/dist/utils/logger.js +15 -0
  96. package/dist/utils/logger.js.map +1 -0
  97. package/package.json +73 -0
@@ -0,0 +1,110 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SheetAdapter = void 0;
4
+ exports.createSheetAdapter = createSheetAdapter;
5
+ const sheetClient_1 = require("./sheetClient");
6
+ const crud_1 = require("./crud");
7
+ const PermissionError_1 = require("../errors/PermissionError");
8
+ const SchemaError_1 = require("../errors/SchemaError");
9
+ class SheetAdapter {
10
+ constructor(config) {
11
+ this.schemas = new Map();
12
+ this.client = new sheetClient_1.SheetClient(config.credentials, config.tokens);
13
+ this.adminSheetId = config.adminSheetId;
14
+ }
15
+ registerSchema(schema) {
16
+ this.schemas.set(schema.name, schema);
17
+ }
18
+ registerSchemas(schemas) {
19
+ schemas.forEach((schema) => this.registerSchema(schema));
20
+ }
21
+ withContext(context) {
22
+ const newAdapter = Object.create(this);
23
+ newAdapter.context = context;
24
+ return newAdapter;
25
+ }
26
+ table(tableName) {
27
+ const schema = this.schemas.get(tableName);
28
+ if (!schema) {
29
+ throw new SchemaError_1.SchemaError(`Table ${tableName} is not registered`, tableName);
30
+ }
31
+ const spreadsheetId = this.resolveSpreadsheetId(schema);
32
+ if (!this.hasPermission(schema)) {
33
+ throw new PermissionError_1.PermissionError(`User does not have permission to access ${tableName}`, this.context?.role);
34
+ }
35
+ return new crud_1.CRUDOperations(this.client, spreadsheetId, schema);
36
+ }
37
+ async createUserSheet(userId, role, email) {
38
+ const sheetId = await this.client.createSpreadsheet(`${role}-${userId}`);
39
+ await this.client.shareWithUser(sheetId, process.env.SUPER_ADMIN_EMAIL, 'writer');
40
+ await this.client.shareWithUser(sheetId, email, 'writer');
41
+ const userTables = Array.from(this.schemas.values()).filter((s) => s.actor === role);
42
+ for (const table of userTables) {
43
+ await this.client.addSheet(sheetId, table.name);
44
+ const headers = Object.keys(table.columns);
45
+ await this.client.writeHeader(sheetId, table.name, headers);
46
+ }
47
+ const adminTable = this.table('users');
48
+ await adminTable.create({
49
+ user_id: userId,
50
+ role,
51
+ email,
52
+ actor_sheet_id: sheetId,
53
+ created_at: new Date().toISOString(),
54
+ });
55
+ return sheetId;
56
+ }
57
+ async syncSchema(schema) {
58
+ const sheetExists = await this.sheetExists(schema);
59
+ if (!sheetExists) {
60
+ const spreadsheetId = this.resolveSpreadsheetId(schema);
61
+ await this.client.addSheet(spreadsheetId, schema.name);
62
+ }
63
+ const headers = Object.keys(schema.columns);
64
+ const spreadsheetId = this.resolveSpreadsheetId(schema);
65
+ const existingSheets = await this.client.getSheetNames(spreadsheetId);
66
+ if (existingSheets.includes(schema.name)) {
67
+ const rows = await this.client.getAllRows(spreadsheetId, schema.name);
68
+ if (rows.length === 0) {
69
+ await this.client.writeHeader(spreadsheetId, schema.name, headers);
70
+ }
71
+ }
72
+ }
73
+ resolveSpreadsheetId(schema) {
74
+ if (schema.actor === 'admin') {
75
+ return this.adminSheetId;
76
+ }
77
+ if (this.context?.actorSheetId) {
78
+ return this.context.actorSheetId;
79
+ }
80
+ throw new PermissionError_1.PermissionError('Actor sheet ID not provided in context', this.context?.role);
81
+ }
82
+ hasPermission(schema) {
83
+ if (!this.context) {
84
+ return false;
85
+ }
86
+ if (this.context.role === 'admin') {
87
+ return true;
88
+ }
89
+ if (schema.actor === this.context.role) {
90
+ return true;
91
+ }
92
+ if (schema.actor === 'admin') {
93
+ return false;
94
+ }
95
+ return false;
96
+ }
97
+ async sheetExists(schema) {
98
+ const spreadsheetId = this.resolveSpreadsheetId(schema);
99
+ const sheetNames = await this.client.getSheetNames(spreadsheetId);
100
+ return sheetNames.includes(schema.name);
101
+ }
102
+ getClient() {
103
+ return this.client;
104
+ }
105
+ }
106
+ exports.SheetAdapter = SheetAdapter;
107
+ function createSheetAdapter(config) {
108
+ return new SheetAdapter(config);
109
+ }
110
+ //# sourceMappingURL=sheetAdapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sheetAdapter.js","sourceRoot":"","sources":["../../src/adapter/sheetAdapter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ export declare class SheetClient {
2
+ private sheets;
3
+ private auth;
4
+ constructor(credentials: {
5
+ clientId: string;
6
+ clientSecret: string;
7
+ redirectUri: string;
8
+ }, tokens: any);
9
+ createSpreadsheet(title: string): Promise<string>;
10
+ addSheet(spreadsheetId: string, sheetName: string): Promise<void>;
11
+ getSheetNames(spreadsheetId: string): Promise<string[]>;
12
+ writeHeader(spreadsheetId: string, sheetName: string, headers: string[]): Promise<void>;
13
+ appendRow(spreadsheetId: string, sheetName: string, values: any[]): Promise<void>;
14
+ getAllRows(spreadsheetId: string, sheetName: string): Promise<any[][]>;
15
+ updateRow(spreadsheetId: string, sheetName: string, rowIndex: number, values: any[]): Promise<void>;
16
+ deleteRow(spreadsheetId: string, sheetName: string, rowIndex: number): Promise<void>;
17
+ shareWithUser(spreadsheetId: string, email: string, role?: 'reader' | 'writer'): Promise<void>;
18
+ private getSheetId;
19
+ }
20
+ //# sourceMappingURL=sheetClient.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sheetClient.d.ts","sourceRoot":"","sources":["../../src/adapter/sheetClient.ts"],"names":[],"mappings":"AAGA,qBAAa,WAAW;IACtB,OAAO,CAAC,MAAM,CAAmB;IACjC,OAAO,CAAC,IAAI,CAAe;gBAEf,WAAW,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,EAAE,MAAM,EAAE,GAAG;IAU/F,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IASjD,QAAQ,CAAC,aAAa,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAejE,aAAa,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAKvD,WAAW,CAAC,aAAa,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAWvF,SAAS,CAAC,aAAa,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAWjF,UAAU,CAAC,aAAa,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC;IAQtE,SAAS,CAAC,aAAa,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAWnG,SAAS,CAAC,aAAa,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAqBpF,aAAa,CAAC,aAAa,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,GAAE,QAAQ,GAAG,QAAmB,GAAG,OAAO,CAAC,IAAI,CAAC;YAYhG,UAAU;CAKzB"}
@@ -0,0 +1,112 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SheetClient = void 0;
4
+ const googleapis_1 = require("googleapis");
5
+ class SheetClient {
6
+ constructor(credentials, tokens) {
7
+ this.auth = new googleapis_1.google.auth.OAuth2(credentials.clientId, credentials.clientSecret, credentials.redirectUri);
8
+ this.auth.setCredentials(tokens);
9
+ this.sheets = googleapis_1.google.sheets({ version: 'v4', auth: this.auth });
10
+ }
11
+ async createSpreadsheet(title) {
12
+ const response = await this.sheets.spreadsheets.create({
13
+ requestBody: {
14
+ properties: { title },
15
+ },
16
+ });
17
+ return response.data.spreadsheetId;
18
+ }
19
+ async addSheet(spreadsheetId, sheetName) {
20
+ await this.sheets.spreadsheets.batchUpdate({
21
+ spreadsheetId,
22
+ requestBody: {
23
+ requests: [
24
+ {
25
+ addSheet: {
26
+ properties: { title: sheetName },
27
+ },
28
+ },
29
+ ],
30
+ },
31
+ });
32
+ }
33
+ async getSheetNames(spreadsheetId) {
34
+ const response = await this.sheets.spreadsheets.get({ spreadsheetId });
35
+ return response.data.sheets?.map((sheet) => sheet.properties?.title || '') || [];
36
+ }
37
+ async writeHeader(spreadsheetId, sheetName, headers) {
38
+ await this.sheets.spreadsheets.values.update({
39
+ spreadsheetId,
40
+ range: `${sheetName}!A1`,
41
+ valueInputOption: 'RAW',
42
+ requestBody: {
43
+ values: [headers],
44
+ },
45
+ });
46
+ }
47
+ async appendRow(spreadsheetId, sheetName, values) {
48
+ await this.sheets.spreadsheets.values.append({
49
+ spreadsheetId,
50
+ range: `${sheetName}!A:A`,
51
+ valueInputOption: 'RAW',
52
+ requestBody: {
53
+ values: [values],
54
+ },
55
+ });
56
+ }
57
+ async getAllRows(spreadsheetId, sheetName) {
58
+ const response = await this.sheets.spreadsheets.values.get({
59
+ spreadsheetId,
60
+ range: `${sheetName}!A:ZZ`,
61
+ });
62
+ return response.data.values || [];
63
+ }
64
+ async updateRow(spreadsheetId, sheetName, rowIndex, values) {
65
+ await this.sheets.spreadsheets.values.update({
66
+ spreadsheetId,
67
+ range: `${sheetName}!A${rowIndex}`,
68
+ valueInputOption: 'RAW',
69
+ requestBody: {
70
+ values: [values],
71
+ },
72
+ });
73
+ }
74
+ async deleteRow(spreadsheetId, sheetName, rowIndex) {
75
+ const sheetId = await this.getSheetId(spreadsheetId, sheetName);
76
+ await this.sheets.spreadsheets.batchUpdate({
77
+ spreadsheetId,
78
+ requestBody: {
79
+ requests: [
80
+ {
81
+ deleteDimension: {
82
+ range: {
83
+ sheetId,
84
+ dimension: 'ROWS',
85
+ startIndex: rowIndex - 1,
86
+ endIndex: rowIndex,
87
+ },
88
+ },
89
+ },
90
+ ],
91
+ },
92
+ });
93
+ }
94
+ async shareWithUser(spreadsheetId, email, role = 'writer') {
95
+ const drive = googleapis_1.google.drive({ version: 'v3', auth: this.auth });
96
+ await drive.permissions.create({
97
+ fileId: spreadsheetId,
98
+ requestBody: {
99
+ type: 'user',
100
+ role,
101
+ emailAddress: email,
102
+ },
103
+ });
104
+ }
105
+ async getSheetId(spreadsheetId, sheetName) {
106
+ const response = await this.sheets.spreadsheets.get({ spreadsheetId });
107
+ const sheet = response.data.sheets?.find((s) => s.properties?.title === sheetName);
108
+ return sheet?.properties?.sheetId || 0;
109
+ }
110
+ }
111
+ exports.SheetClient = SheetClient;
112
+ //# sourceMappingURL=sheetClient.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sheetClient.js","sourceRoot":"","sources":["../../src/adapter/sheetClient.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ export interface OAuthConfig {
2
+ clientId: string;
3
+ clientSecret: string;
4
+ redirectUri: string;
5
+ }
6
+ export declare class OAuthManager {
7
+ private client;
8
+ constructor(config: OAuthConfig);
9
+ getAuthUrl(scopes?: string[]): string;
10
+ getTokens(code: string): Promise<any>;
11
+ refreshTokens(refreshToken: string): Promise<any>;
12
+ verifyToken(token: string): Promise<any>;
13
+ }
14
+ export declare function createOAuthManager(config: OAuthConfig): OAuthManager;
15
+ //# sourceMappingURL=oauth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oauth.d.ts","sourceRoot":"","sources":["../../src/auth/oauth.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,qBAAa,YAAY;IACvB,OAAO,CAAC,MAAM,CAAe;gBAEjB,MAAM,EAAE,WAAW;IAI/B,UAAU,CAAC,MAAM,GAAE,MAAM,EAAmG,GAAG,MAAM;IAO/H,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC;IAKrC,aAAa,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC;IAMjD,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC;CAO/C;AAED,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,WAAW,GAAG,YAAY,CAEpE"}
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.OAuthManager = void 0;
4
+ exports.createOAuthManager = createOAuthManager;
5
+ const google_auth_library_1 = require("google-auth-library");
6
+ class OAuthManager {
7
+ constructor(config) {
8
+ this.client = new google_auth_library_1.OAuth2Client(config.clientId, config.clientSecret, config.redirectUri);
9
+ }
10
+ getAuthUrl(scopes = ['https://www.googleapis.com/auth/spreadsheets', 'https://www.googleapis.com/auth/drive.file']) {
11
+ return this.client.generateAuthUrl({
12
+ access_type: 'offline',
13
+ scope: scopes,
14
+ });
15
+ }
16
+ async getTokens(code) {
17
+ const { tokens } = await this.client.getToken(code);
18
+ return tokens;
19
+ }
20
+ async refreshTokens(refreshToken) {
21
+ this.client.setCredentials({ refresh_token: refreshToken });
22
+ const { credentials } = await this.client.refreshAccessToken();
23
+ return credentials;
24
+ }
25
+ async verifyToken(token) {
26
+ const ticket = await this.client.verifyIdToken({
27
+ idToken: token,
28
+ audience: this.client._clientId,
29
+ });
30
+ return ticket.getPayload();
31
+ }
32
+ }
33
+ exports.OAuthManager = OAuthManager;
34
+ function createOAuthManager(config) {
35
+ return new OAuthManager(config);
36
+ }
37
+ //# sourceMappingURL=oauth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oauth.js","sourceRoot":"","sources":["../../src/auth/oauth.ts"],"names":[],"mappings":";;;AA0CA,gDAEC;AA5CD,6DAAmD;AAQnD,MAAa,YAAY;IAGvB,YAAY,MAAmB;QAC7B,IAAI,CAAC,MAAM,GAAG,IAAI,kCAAY,CAAC,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,YAAY,EAAE,MAAM,CAAC,WAAW,CAAC,CAAC;IAC3F,CAAC;IAED,UAAU,CAAC,SAAmB,CAAC,8CAA8C,EAAE,4CAA4C,CAAC;QAC1H,OAAO,IAAI,CAAC,MAAM,CAAC,eAAe,CAAC;YACjC,WAAW,EAAE,SAAS;YACtB,KAAK,EAAE,MAAM;SACd,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,SAAS,CAAC,IAAY;QAC1B,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QACpD,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,YAAoB;QACtC,IAAI,CAAC,MAAM,CAAC,cAAc,CAAC,EAAE,aAAa,EAAE,YAAY,EAAE,CAAC,CAAC;QAC5D,MAAM,EAAE,WAAW,EAAE,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,kBAAkB,EAAE,CAAC;QAC/D,OAAO,WAAW,CAAC;IACrB,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,KAAa;QAC7B,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC;YAC7C,OAAO,EAAE,KAAK;YACd,QAAQ,EAAE,IAAI,CAAC,MAAM,CAAC,SAAS;SAChC,CAAC,CAAC;QACH,OAAO,MAAM,CAAC,UAAU,EAAE,CAAC;IAC7B,CAAC;CACF;AAhCD,oCAgCC;AAED,SAAgB,kBAAkB,CAAC,MAAmB;IACpD,OAAO,IAAI,YAAY,CAAC,MAAM,CAAC,CAAC;AAClC,CAAC"}
@@ -0,0 +1,7 @@
1
+ export declare function hashPassword(password: string): Promise<string>;
2
+ export declare function comparePassword(password: string, hash: string): Promise<boolean>;
3
+ export declare function validatePasswordStrength(password: string): {
4
+ valid: boolean;
5
+ errors: string[];
6
+ };
7
+ //# sourceMappingURL=password.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"password.d.ts","sourceRoot":"","sources":["../../src/auth/password.ts"],"names":[],"mappings":"AAIA,wBAAsB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAEpE;AAED,wBAAsB,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAEtF;AAED,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,MAAM,GAAG;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAA;CAAE,CAuB/F"}
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.hashPassword = hashPassword;
7
+ exports.comparePassword = comparePassword;
8
+ exports.validatePasswordStrength = validatePasswordStrength;
9
+ const bcryptjs_1 = __importDefault(require("bcryptjs"));
10
+ const SALT_ROUNDS = 10;
11
+ async function hashPassword(password) {
12
+ return bcryptjs_1.default.hash(password, SALT_ROUNDS);
13
+ }
14
+ async function comparePassword(password, hash) {
15
+ return bcryptjs_1.default.compare(password, hash);
16
+ }
17
+ function validatePasswordStrength(password) {
18
+ const errors = [];
19
+ if (password.length < 8) {
20
+ errors.push('Password must be at least 8 characters long');
21
+ }
22
+ if (!/[A-Z]/.test(password)) {
23
+ errors.push('Password must contain at least one uppercase letter');
24
+ }
25
+ if (!/[a-z]/.test(password)) {
26
+ errors.push('Password must contain at least one lowercase letter');
27
+ }
28
+ if (!/[0-9]/.test(password)) {
29
+ errors.push('Password must contain at least one number');
30
+ }
31
+ return {
32
+ valid: errors.length === 0,
33
+ errors,
34
+ };
35
+ }
36
+ //# sourceMappingURL=password.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"password.js","sourceRoot":"","sources":["../../src/auth/password.ts"],"names":[],"mappings":";;;;;AAIA,oCAEC;AAED,0CAEC;AAED,4DAuBC;AAnCD,wDAA8B;AAE9B,MAAM,WAAW,GAAG,EAAE,CAAC;AAEhB,KAAK,UAAU,YAAY,CAAC,QAAgB;IACjD,OAAO,kBAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAC;AAC5C,CAAC;AAEM,KAAK,UAAU,eAAe,CAAC,QAAgB,EAAE,IAAY;IAClE,OAAO,kBAAM,CAAC,OAAO,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;AACxC,CAAC;AAED,SAAgB,wBAAwB,CAAC,QAAgB;IACvD,MAAM,MAAM,GAAa,EAAE,CAAC;IAE5B,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxB,MAAM,CAAC,IAAI,CAAC,6CAA6C,CAAC,CAAC;IAC7D,CAAC;IAED,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC5B,MAAM,CAAC,IAAI,CAAC,qDAAqD,CAAC,CAAC;IACrE,CAAC;IAED,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC5B,MAAM,CAAC,IAAI,CAAC,qDAAqD,CAAC,CAAC;IACrE,CAAC;IAED,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC5B,MAAM,CAAC,IAAI,CAAC,2CAA2C,CAAC,CAAC;IAC3D,CAAC;IAED,OAAO;QACL,KAAK,EAAE,MAAM,CAAC,MAAM,KAAK,CAAC;QAC1B,MAAM;KACP,CAAC;AACJ,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function doctorCommand(): Promise<void>;
2
+ //# sourceMappingURL=doctor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/doctor.ts"],"names":[],"mappings":"AAcA,wBAAsB,aAAa,kBA8GlC"}
@@ -0,0 +1,91 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.doctorCommand = doctorCommand;
7
+ const fs_1 = __importDefault(require("fs"));
8
+ const path_1 = __importDefault(require("path"));
9
+ const chalk_1 = __importDefault(require("chalk"));
10
+ function check(label, ok, message) {
11
+ return { label, ok, message };
12
+ }
13
+ async function doctorCommand() {
14
+ console.log(chalk_1.default.blue.bold('🩺 Running diagnostics...\n'));
15
+ require('dotenv').config();
16
+ const results = [];
17
+ // 1. Config file
18
+ const configPath = path_1.default.join(process.cwd(), 'sheet-db.config.ts');
19
+ results.push(check('Config file (sheet-db.config.ts)', fs_1.default.existsSync(configPath)));
20
+ // 2. .env file
21
+ const envPath = path_1.default.join(process.cwd(), '.env');
22
+ results.push(check('.env file', fs_1.default.existsSync(envPath), 'Create a .env file with required variables'));
23
+ // 3. Required env vars
24
+ const requiredEnvVars = [
25
+ 'GOOGLE_CLIENT_ID',
26
+ 'GOOGLE_CLIENT_SECRET',
27
+ 'GOOGLE_REDIRECT_URI',
28
+ 'ADMIN_SHEET_ID',
29
+ ];
30
+ for (const envVar of requiredEnvVars) {
31
+ results.push(check(`Env var: ${envVar}`, !!process.env[envVar], `Set ${envVar} in your .env file`));
32
+ }
33
+ // 4. Schemas directory
34
+ const schemasDir = path_1.default.join(process.cwd(), 'schemas');
35
+ results.push(check('schemas/ directory', fs_1.default.existsSync(schemasDir), 'Run: sheet-db init'));
36
+ // 5. Schema files
37
+ let schemaCount = 0;
38
+ if (fs_1.default.existsSync(schemasDir)) {
39
+ const actorDirs = fs_1.default.readdirSync(schemasDir, { withFileTypes: true })
40
+ .filter((d) => d.isDirectory())
41
+ .map((d) => d.name);
42
+ for (const actor of actorDirs) {
43
+ const actorDir = path_1.default.join(schemasDir, actor);
44
+ const files = fs_1.default.readdirSync(actorDir).filter((f) => f.endsWith('.ts'));
45
+ schemaCount += files.length;
46
+ }
47
+ }
48
+ results.push(check(`Schema files (${schemaCount} found)`, schemaCount > 0, 'Run: sheet-db generate <table-name> to create schemas'));
49
+ // 6. OAuth tokens
50
+ const tokensPath = path_1.default.join(process.cwd(), '.sheet-db-tokens.json');
51
+ results.push(check('OAuth tokens (.sheet-db-tokens.json)', fs_1.default.existsSync(tokensPath), 'Run: sheet-db sync to authorize and create tokens'));
52
+ // 7. OAuth token validity (basic check)
53
+ if (fs_1.default.existsSync(tokensPath)) {
54
+ try {
55
+ const tokens = JSON.parse(fs_1.default.readFileSync(tokensPath, 'utf-8'));
56
+ const hasRefreshToken = !!tokens.refresh_token;
57
+ const expiryDate = tokens.expiry_date;
58
+ const expired = expiryDate ? Date.now() > expiryDate : false;
59
+ results.push(check('OAuth refresh token present', hasRefreshToken, 'Re-run: sheet-db sync to get a refresh token'));
60
+ if (expiryDate) {
61
+ results.push(check(`Access token ${expired ? '(expired — will auto-refresh)' : '(valid)'}`, true));
62
+ }
63
+ }
64
+ catch {
65
+ results.push(check('OAuth token file parseable', false, 'Delete .sheet-db-tokens.json and run: sheet-db sync'));
66
+ }
67
+ }
68
+ // Print results
69
+ let passed = 0;
70
+ let failed = 0;
71
+ for (const result of results) {
72
+ if (result.ok) {
73
+ console.log(` ${chalk_1.default.green('āœ“')} ${result.label}`);
74
+ passed++;
75
+ }
76
+ else {
77
+ console.log(` ${chalk_1.default.red('āœ–')} ${result.label}${result.message ? chalk_1.default.gray(` — ${result.message}`) : ''}`);
78
+ failed++;
79
+ }
80
+ }
81
+ console.log();
82
+ if (failed === 0) {
83
+ console.log(chalk_1.default.green.bold(`āœ… All ${passed} checks passed. You're good to go!`));
84
+ }
85
+ else {
86
+ console.log(chalk_1.default.yellow.bold(`āš ļø ${failed} check(s) failed, ${passed} passed.`));
87
+ console.log(chalk_1.default.gray('Fix the issues above before running sheet-db sync.'));
88
+ process.exit(1);
89
+ }
90
+ }
91
+ //# sourceMappingURL=doctor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../../src/cli/commands/doctor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare function generateCommand(tableName: string): Promise<void>;
2
+ //# sourceMappingURL=generate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/generate.ts"],"names":[],"mappings":"AAKA,wBAAsB,eAAe,CAAC,SAAS,EAAE,MAAM,iBAwHtD"}
@@ -0,0 +1,121 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.generateCommand = generateCommand;
7
+ const fs_1 = __importDefault(require("fs"));
8
+ const path_1 = __importDefault(require("path"));
9
+ const inquirer_1 = __importDefault(require("inquirer"));
10
+ const chalk_1 = __importDefault(require("chalk"));
11
+ async function generateCommand(tableName) {
12
+ console.log(chalk_1.default.blue.bold(`šŸ“ Generating table schema: ${tableName}\n`));
13
+ let config;
14
+ try {
15
+ config = require(path_1.default.join(process.cwd(), 'sheet-db.config.ts')).default;
16
+ }
17
+ catch {
18
+ console.error(chalk_1.default.red('āŒ sheet-db.config.ts not found. Run: sheet-db init'));
19
+ process.exit(1);
20
+ }
21
+ const answers = await inquirer_1.default.prompt([
22
+ {
23
+ type: 'list',
24
+ name: 'actor',
25
+ message: 'Which actor owns this table?',
26
+ choices: config.actors,
27
+ },
28
+ {
29
+ type: 'confirm',
30
+ name: 'timestamps',
31
+ message: 'Add timestamps (_created_at, _updated_at)?',
32
+ default: true,
33
+ },
34
+ {
35
+ type: 'confirm',
36
+ name: 'softDelete',
37
+ message: 'Enable soft delete (_deleted_at)?',
38
+ default: false,
39
+ },
40
+ ]);
41
+ const columns = [];
42
+ let addMore = true;
43
+ while (addMore) {
44
+ const column = await inquirer_1.default.prompt([
45
+ {
46
+ type: 'input',
47
+ name: 'name',
48
+ message: 'Column name (or press Enter to finish):',
49
+ },
50
+ ]);
51
+ if (!column.name) {
52
+ addMore = false;
53
+ continue;
54
+ }
55
+ const columnDetails = await inquirer_1.default.prompt([
56
+ {
57
+ type: 'list',
58
+ name: 'type',
59
+ message: `Type for ${column.name}:`,
60
+ choices: ['string', 'number', 'boolean', 'date', 'json'],
61
+ },
62
+ {
63
+ type: 'confirm',
64
+ name: 'required',
65
+ message: 'Required?',
66
+ default: false,
67
+ },
68
+ {
69
+ type: 'confirm',
70
+ name: 'unique',
71
+ message: 'Unique?',
72
+ default: false,
73
+ },
74
+ {
75
+ type: 'input',
76
+ name: 'defaultValue',
77
+ message: 'Default value (leave empty for none):',
78
+ },
79
+ ]);
80
+ columns.push({
81
+ name: column.name,
82
+ ...columnDetails,
83
+ });
84
+ }
85
+ const columnsCode = columns
86
+ .map((col) => {
87
+ let line = ` ${col.name}: ${col.type}()`;
88
+ if (col.required)
89
+ line += '.required()';
90
+ if (col.unique)
91
+ line += '.unique()';
92
+ if (col.defaultValue) {
93
+ const value = col.type === 'string' ? `"${col.defaultValue}"` : col.defaultValue;
94
+ line += `.default(${value})`;
95
+ }
96
+ line += ',';
97
+ return line;
98
+ })
99
+ .join('\n');
100
+ const schemaContent = `import { defineTable, string, number, boolean, date, json } from 'longcelot-sheet-db';
101
+
102
+ export default defineTable({
103
+ name: '${tableName}',
104
+ actor: '${answers.actor}',
105
+ timestamps: ${answers.timestamps},
106
+ softDelete: ${answers.softDelete},
107
+ columns: {
108
+ ${columnsCode}
109
+ },
110
+ });
111
+ `;
112
+ const actorDir = path_1.default.join(process.cwd(), 'schemas', answers.actor);
113
+ if (!fs_1.default.existsSync(actorDir)) {
114
+ fs_1.default.mkdirSync(actorDir, { recursive: true });
115
+ }
116
+ const filePath = path_1.default.join(actorDir, `${tableName}.ts`);
117
+ fs_1.default.writeFileSync(filePath, schemaContent);
118
+ console.log(chalk_1.default.green(`\nāœ… Schema created: ${filePath}`));
119
+ console.log(chalk_1.default.cyan('\nNext: Run "sheet-db sync" to create the sheet\n'));
120
+ }
121
+ //# sourceMappingURL=generate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate.js","sourceRoot":"","sources":["../../../src/cli/commands/generate.ts"],"names":[],"mappings":";;;;;AAKA,0CAwHC;AA7HD,4CAAoB;AACpB,gDAAwB;AACxB,wDAAgC;AAChC,kDAA0B;AAEnB,KAAK,UAAU,eAAe,CAAC,SAAiB;IACrD,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,IAAI,CAAC,IAAI,CAAC,+BAA+B,SAAS,IAAI,CAAC,CAAC,CAAC;IAE3E,IAAI,MAAM,CAAC;IACX,IAAI,CAAC;QACH,MAAM,GAAG,OAAO,CAAC,cAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,oBAAoB,CAAC,CAAC,CAAC,OAAO,CAAC;IAC3E,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,CAAC,KAAK,CAAC,eAAK,CAAC,GAAG,CAAC,oDAAoD,CAAC,CAAC,CAAC;QAC/E,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,OAAO,GAAG,MAAM,kBAAQ,CAAC,MAAM,CAAC;QACpC;YACE,IAAI,EAAE,MAAM;YACZ,IAAI,EAAE,OAAO;YACb,OAAO,EAAE,8BAA8B;YACvC,OAAO,EAAE,MAAM,CAAC,MAAM;SACvB;QACD;YACE,IAAI,EAAE,SAAS;YACf,IAAI,EAAE,YAAY;YAClB,OAAO,EAAE,4CAA4C;YACrD,OAAO,EAAE,IAAI;SACd;QACD;YACE,IAAI,EAAE,SAAS;YACf,IAAI,EAAE,YAAY;YAClB,OAAO,EAAE,mCAAmC;YAC5C,OAAO,EAAE,KAAK;SACf;KACF,CAAC,CAAC;IAEH,MAAM,OAAO,GAAU,EAAE,CAAC;IAC1B,IAAI,OAAO,GAAG,IAAI,CAAC;IAEnB,OAAO,OAAO,EAAE,CAAC;QACf,MAAM,MAAM,GAAG,MAAM,kBAAQ,CAAC,MAAM,CAAC;YACnC;gBACE,IAAI,EAAE,OAAO;gBACb,IAAI,EAAE,MAAM;gBACZ,OAAO,EAAE,yCAAyC;aACnD;SACF,CAAC,CAAC;QAEH,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;YACjB,OAAO,GAAG,KAAK,CAAC;YAChB,SAAS;QACX,CAAC;QAED,MAAM,aAAa,GAAG,MAAM,kBAAQ,CAAC,MAAM,CAAC;YAC1C;gBACE,IAAI,EAAE,MAAM;gBACZ,IAAI,EAAE,MAAM;gBACZ,OAAO,EAAE,YAAY,MAAM,CAAC,IAAI,GAAG;gBACnC,OAAO,EAAE,CAAC,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,CAAC;aACzD;YACD;gBACE,IAAI,EAAE,SAAS;gBACf,IAAI,EAAE,UAAU;gBAChB,OAAO,EAAE,WAAW;gBACpB,OAAO,EAAE,KAAK;aACf;YACD;gBACE,IAAI,EAAE,SAAS;gBACf,IAAI,EAAE,QAAQ;gBACd,OAAO,EAAE,SAAS;gBAClB,OAAO,EAAE,KAAK;aACf;YACD;gBACE,IAAI,EAAE,OAAO;gBACb,IAAI,EAAE,cAAc;gBACpB,OAAO,EAAE,uCAAuC;aACjD;SACF,CAAC,CAAC;QAEH,OAAO,CAAC,IAAI,CAAC;YACX,IAAI,EAAE,MAAM,CAAC,IAAI;YACjB,GAAG,aAAa;SACjB,CAAC,CAAC;IACL,CAAC;IAED,MAAM,WAAW,GAAG,OAAO;SACxB,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE;QACX,IAAI,IAAI,GAAG,OAAO,GAAG,CAAC,IAAI,KAAK,GAAG,CAAC,IAAI,IAAI,CAAC;QAE5C,IAAI,GAAG,CAAC,QAAQ;YAAE,IAAI,IAAI,aAAa,CAAC;QACxC,IAAI,GAAG,CAAC,MAAM;YAAE,IAAI,IAAI,WAAW,CAAC;QACpC,IAAI,GAAG,CAAC,YAAY,EAAE,CAAC;YACrB,MAAM,KAAK,GAAG,GAAG,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,YAAY,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,YAAY,CAAC;YACjF,IAAI,IAAI,YAAY,KAAK,GAAG,CAAC;QAC/B,CAAC;QAED,IAAI,IAAI,GAAG,CAAC;QACZ,OAAO,IAAI,CAAC;IACd,CAAC,CAAC;SACD,IAAI,CAAC,IAAI,CAAC,CAAC;IAEd,MAAM,aAAa,GAAG;;;WAGb,SAAS;YACR,OAAO,CAAC,KAAK;gBACT,OAAO,CAAC,UAAU;gBAClB,OAAO,CAAC,UAAU;;EAEhC,WAAW;;;CAGZ,CAAC;IAEA,MAAM,QAAQ,GAAG,cAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC;IACpE,IAAI,CAAC,YAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC7B,YAAE,CAAC,SAAS,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC9C,CAAC;IAED,MAAM,QAAQ,GAAG,cAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,SAAS,KAAK,CAAC,CAAC;IACxD,YAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC;IAE1C,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,KAAK,CAAC,uBAAuB,QAAQ,EAAE,CAAC,CAAC,CAAC;IAC5D,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,IAAI,CAAC,mDAAmD,CAAC,CAAC,CAAC;AAC/E,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function initCommand(): Promise<void>;
2
+ //# sourceMappingURL=init.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/init.ts"],"names":[],"mappings":"AAKA,wBAAsB,WAAW,kBAuHhC"}