tantan-typeorm-gs 1.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/LICENSE +21 -0
- package/README.md +31 -0
- package/bun.lock +300 -0
- package/docs/authentication.md +118 -0
- package/docs/configuration.md +680 -0
- package/docs/contributing.md +177 -0
- package/docs/crud.md +351 -0
- package/docs/custom-client.md +165 -0
- package/docs/development.md +243 -0
- package/docs/entities.md +502 -0
- package/docs/find-options.md +296 -0
- package/docs/google-cloud.md +101 -0
- package/docs/installation.md +51 -0
- package/docs/integration-testing.md +178 -0
- package/docs/limitations.md +223 -0
- package/docs/pagination.md +384 -0
- package/docs/performance.md +171 -0
- package/docs/security.md +153 -0
- package/docs/sorting.md +0 -0
- package/docs/supported-features.md +310 -0
- package/docs/synchronization.md +203 -0
- package/package.json +43 -0
- package/src/client/index.ts +589 -0
- package/src/core/data-source.ts +47 -0
- package/src/core/driver.ts +290 -0
- package/src/core/error.ts +144 -0
- package/src/core/memory.ts +152 -0
- package/src/core/query/interpreter.ts +949 -0
- package/src/core/query/runner.ts +1297 -0
- package/src/core/query/types.ts +155 -0
- package/src/core/schema-builder.ts +64 -0
- package/src/core/types.ts +113 -0
- package/src/core/utils.ts +13 -0
- package/src/index.ts +3 -0
- package/tantan-typeorm-gs.code-workspace +8 -0
- package/test/base/0001-data-source.test.ts +252 -0
- package/test/base/0002-operator.test.ts +616 -0
- package/test/base/0003-select.test.ts +281 -0
- package/test/base/0004-aggregate.test.ts +213 -0
- package/test/base/0005-transcation.test.ts +1566 -0
- package/test/base/0006-relation.test.ts +1611 -0
- package/test/base/0007-logging.test.ts +182 -0
- package/test/base/0008-soft-delete.test.ts +649 -0
- package/test/google-sheets/0001-client.test.ts +1705 -0
- package/test/google-sheets/0002-worksheet-management.test.ts +408 -0
- package/test/google-sheets/0003-data-source.test.ts +1935 -0
- package/test/google-sheets/0004-transactions.test.ts +952 -0
- package/test/google-sheets/0005-operator.test.ts +1124 -0
- package/test/google-sheets/0006-object-criteria.test.ts +283 -0
- package/test/google-sheets/0007-performance.test.ts +532 -0
- package/test/public-api.test.ts +34 -0
- package/tsconfig.build.json +21 -0
- package/tsconfig.json +34 -0
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
## Performance Considerations
|
|
2
|
+
|
|
3
|
+
Google Sheets is an API-based spreadsheet service rather than a database engine.
|
|
4
|
+
|
|
5
|
+
The performance of the driver therefore depends on several factors, including worksheet size, number of API requests, operation type, and network latency.
|
|
6
|
+
|
|
7
|
+
### Avoid Treating Google Sheets as a Large Database
|
|
8
|
+
|
|
9
|
+
The driver is intended for workloads where Google Sheets is an appropriate data store.
|
|
10
|
+
|
|
11
|
+
For large datasets or high-frequency database workloads, a relational database is generally more appropriate.
|
|
12
|
+
|
|
13
|
+
Operations such as:
|
|
14
|
+
|
|
15
|
+
```ts id="8m2q5v"
|
|
16
|
+
const users = await repository.find();
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
may require processing a significant number of worksheet rows.
|
|
20
|
+
|
|
21
|
+
Applications should avoid loading an entire large worksheet when only a small subset of data is required.
|
|
22
|
+
|
|
23
|
+
### Use Filtering
|
|
24
|
+
|
|
25
|
+
When only specific records are required, use `where` conditions:
|
|
26
|
+
|
|
27
|
+
```ts id="4x7n1c"
|
|
28
|
+
const users = await repository.find({
|
|
29
|
+
where: {
|
|
30
|
+
status: "active"
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
This avoids unnecessarily returning unrelated records to the application.
|
|
36
|
+
|
|
37
|
+
### Use Pagination
|
|
38
|
+
|
|
39
|
+
For user-facing lists, combine filtering, sorting, and pagination:
|
|
40
|
+
|
|
41
|
+
```ts id="9p3k6w"
|
|
42
|
+
const page = 1;
|
|
43
|
+
const pageSize = 20;
|
|
44
|
+
|
|
45
|
+
const users = await repository.find({
|
|
46
|
+
where: {
|
|
47
|
+
status: "active"
|
|
48
|
+
},
|
|
49
|
+
|
|
50
|
+
order: {
|
|
51
|
+
id: "ASC"
|
|
52
|
+
},
|
|
53
|
+
|
|
54
|
+
skip: (page - 1) * pageSize,
|
|
55
|
+
|
|
56
|
+
take: pageSize
|
|
57
|
+
});
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Pagination limits the number of records returned to the application at once.
|
|
61
|
+
|
|
62
|
+
However, `skip` and `take` should not be considered equivalent to indexed database pagination.
|
|
63
|
+
|
|
64
|
+
### Prefer Batch Operations
|
|
65
|
+
|
|
66
|
+
When multiple records need to be modified, use repository operations that allow the driver to process multiple rows together.
|
|
67
|
+
|
|
68
|
+
For example:
|
|
69
|
+
|
|
70
|
+
```ts id="6v4m8q"
|
|
71
|
+
await repository.insert([
|
|
72
|
+
{
|
|
73
|
+
name: "Budi"
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
name: "Andi"
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
name: "Citra"
|
|
80
|
+
}
|
|
81
|
+
]);
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
The Google Sheets API client supports batching compatible operations to reduce unnecessary API requests.
|
|
85
|
+
|
|
86
|
+
### Minimize API Requests
|
|
87
|
+
|
|
88
|
+
The default `GoogleSheetsApiClient` communicates with Google Sheets through the Google Sheets API.
|
|
89
|
+
|
|
90
|
+
Network requests generally have significantly higher overhead than in-memory operations.
|
|
91
|
+
|
|
92
|
+
Applications should therefore avoid unnecessarily repeating operations such as:
|
|
93
|
+
|
|
94
|
+
```ts id="1c5x7m"
|
|
95
|
+
await repository.find();
|
|
96
|
+
await repository.find();
|
|
97
|
+
await repository.find();
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
when the same result can safely be reused by the application.
|
|
101
|
+
|
|
102
|
+
### Custom Client for Specialized Workloads
|
|
103
|
+
|
|
104
|
+
Applications with specialized performance requirements can provide a custom `GoogleSheetsClient`.
|
|
105
|
+
|
|
106
|
+
A custom client can implement application-specific strategies such as:
|
|
107
|
+
|
|
108
|
+
- caching
|
|
109
|
+
- request batching
|
|
110
|
+
- retry handling
|
|
111
|
+
- request deduplication
|
|
112
|
+
- custom transport behavior
|
|
113
|
+
|
|
114
|
+
The driver remains independent of those implementation details.
|
|
115
|
+
|
|
116
|
+
### Performance Baseline
|
|
117
|
+
|
|
118
|
+
The project's automated performance tests include a basic baseline using `Memory`.
|
|
119
|
+
|
|
120
|
+
The current baseline tested:
|
|
121
|
+
|
|
122
|
+
| Operation | Dataset | Result |
|
|
123
|
+
| --------- | ---------: | --------: |
|
|
124
|
+
| Insert | 1,000 rows | ~25.64 ms |
|
|
125
|
+
| Read | 1,000 rows | ~10.96 ms |
|
|
126
|
+
|
|
127
|
+
These measurements are useful as regression indicators for the driver implementation.
|
|
128
|
+
|
|
129
|
+
They **must not** be interpreted as Google Sheets API production performance benchmarks.
|
|
130
|
+
|
|
131
|
+
The test uses an in-memory fake client and therefore does not include network latency, Google API processing time, authentication, quotas, or real spreadsheet behavior.
|
|
132
|
+
|
|
133
|
+
### Performance Testing
|
|
134
|
+
|
|
135
|
+
Performance tests can be run independently from the normal test suite:
|
|
136
|
+
|
|
137
|
+
```bash id="2q8n4x"
|
|
138
|
+
bun test test/google-sheets/0007-performance.test.ts
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
The tests currently use a relatively loose regression threshold rather than guaranteeing a specific execution time.
|
|
142
|
+
|
|
143
|
+
This is intentional because execution time can vary between development machines and CI environments.
|
|
144
|
+
|
|
145
|
+
### When to Consider a Database
|
|
146
|
+
|
|
147
|
+
Consider using a relational database instead when the workload requires:
|
|
148
|
+
|
|
149
|
+
- large datasets
|
|
150
|
+
- high-frequency reads and writes
|
|
151
|
+
- complex queries
|
|
152
|
+
- low-latency database operations
|
|
153
|
+
- transactions
|
|
154
|
+
- concurrent write-heavy workloads
|
|
155
|
+
- database indexes and query planning
|
|
156
|
+
|
|
157
|
+
Google Sheets is better suited when human spreadsheet access, simplicity, and integration with Google Workspace are important requirements.
|
|
158
|
+
|
|
159
|
+
### Summary
|
|
160
|
+
|
|
161
|
+
For better performance:
|
|
162
|
+
|
|
163
|
+
1. Query only the data that is needed.
|
|
164
|
+
2. Use filtering with `where`.
|
|
165
|
+
3. Use deterministic sorting with pagination.
|
|
166
|
+
4. Prefer batch operations for multiple records.
|
|
167
|
+
5. Minimize unnecessary API requests.
|
|
168
|
+
6. Use a custom client when application-specific caching or transport behavior is required.
|
|
169
|
+
7. Use a relational database when the workload exceeds the practical characteristics of a spreadsheet.
|
|
170
|
+
|
|
171
|
+
Performance should be evaluated using the application's actual workload rather than relying solely on the driver's local baseline tests.
|
package/docs/security.md
ADDED
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
## Security
|
|
2
|
+
|
|
3
|
+
The Google Sheets driver requires access to a Google Cloud service account and a target spreadsheet.
|
|
4
|
+
|
|
5
|
+
Security therefore depends on protecting both the authentication credentials and the spreadsheet itself.
|
|
6
|
+
|
|
7
|
+
### Protect Service Account Credentials
|
|
8
|
+
|
|
9
|
+
The default Google Sheets client requires:
|
|
10
|
+
|
|
11
|
+
```ts
|
|
12
|
+
credentials: {
|
|
13
|
+
clientEmail: '...',
|
|
14
|
+
privateKey: '...',
|
|
15
|
+
}
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
The `privateKey` is sensitive and must be protected.
|
|
19
|
+
|
|
20
|
+
Do not:
|
|
21
|
+
|
|
22
|
+
- commit service account credentials to source control
|
|
23
|
+
- expose the private key in client-side code
|
|
24
|
+
- include credentials in public repositories
|
|
25
|
+
- log the private key
|
|
26
|
+
- send credentials to untrusted services
|
|
27
|
+
|
|
28
|
+
Environment variables are recommended for local and server deployments:
|
|
29
|
+
|
|
30
|
+
```env id="7k2p4m"
|
|
31
|
+
GOOGLE_SHEETS_CLIENT_EMAIL=...
|
|
32
|
+
GOOGLE_SHEETS_PRIVATE_KEY="-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n"
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
The application can then load these values when creating the data source.
|
|
36
|
+
|
|
37
|
+
### Spreadsheet Access
|
|
38
|
+
|
|
39
|
+
The service account must have access to the target spreadsheet.
|
|
40
|
+
|
|
41
|
+
Access should follow the principle of least privilege:
|
|
42
|
+
|
|
43
|
+
- grant access only to the spreadsheets required by the application
|
|
44
|
+
- avoid sharing unrelated spreadsheets
|
|
45
|
+
- remove access when the service account is no longer needed
|
|
46
|
+
- review spreadsheet sharing permissions periodically
|
|
47
|
+
|
|
48
|
+
The driver does not bypass Google Sheets permissions. Access is ultimately controlled by Google.
|
|
49
|
+
|
|
50
|
+
### Spreadsheet ID
|
|
51
|
+
|
|
52
|
+
The spreadsheet ID identifies the target spreadsheet:
|
|
53
|
+
|
|
54
|
+
```ts id="3q8v1n"
|
|
55
|
+
const dataSource = createGoogleSheetsDataSource({
|
|
56
|
+
type: "google-sheets",
|
|
57
|
+
|
|
58
|
+
spreadsheetId: process.env.GOOGLE_SHEETS_SPREADSHEET_ID!
|
|
59
|
+
|
|
60
|
+
// ...
|
|
61
|
+
});
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
The spreadsheet ID is generally not considered a secret by itself.
|
|
65
|
+
|
|
66
|
+
However, it should still be treated as application configuration because it identifies the resource the application intends to access.
|
|
67
|
+
|
|
68
|
+
### Private Key Formatting
|
|
69
|
+
|
|
70
|
+
When the private key is stored in an environment variable, escaped newline characters may need to be converted to actual newline characters:
|
|
71
|
+
|
|
72
|
+
```ts id="6m4x9p"
|
|
73
|
+
const privateKey = process.env.GOOGLE_SHEETS_PRIVATE_KEY!.replace(/\\n/g, "\n");
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
This should be done before passing the key to the Google authentication client when the deployment environment stores the key with escaped newlines.
|
|
77
|
+
|
|
78
|
+
### Do Not Log Credentials
|
|
79
|
+
|
|
80
|
+
Application logging should never include:
|
|
81
|
+
|
|
82
|
+
```text id="1v7c5q"
|
|
83
|
+
clientEmail
|
|
84
|
+
privateKey
|
|
85
|
+
access tokens
|
|
86
|
+
authorization headers
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
If query or API logging is enabled for debugging, ensure that sensitive authentication information is not included in the logged output.
|
|
90
|
+
|
|
91
|
+
### Custom Client Security
|
|
92
|
+
|
|
93
|
+
A custom `GoogleSheetsClient` becomes part of the application's security boundary.
|
|
94
|
+
|
|
95
|
+
For example, a custom client may implement:
|
|
96
|
+
|
|
97
|
+
- authentication
|
|
98
|
+
- caching
|
|
99
|
+
- request logging
|
|
100
|
+
- retry handling
|
|
101
|
+
- alternative transports
|
|
102
|
+
|
|
103
|
+
These implementations must follow the same security requirements as the default client.
|
|
104
|
+
|
|
105
|
+
In particular, custom logging should not expose credentials or authorization data.
|
|
106
|
+
|
|
107
|
+
### Production Credentials
|
|
108
|
+
|
|
109
|
+
For production deployments:
|
|
110
|
+
|
|
111
|
+
- store credentials in a secure secret-management system when available
|
|
112
|
+
- restrict service-account permissions
|
|
113
|
+
- rotate credentials according to the organization's security policy
|
|
114
|
+
- avoid storing private keys directly in source code
|
|
115
|
+
- restrict access to deployment configuration
|
|
116
|
+
|
|
117
|
+
The exact secret-management mechanism depends on the deployment environment.
|
|
118
|
+
|
|
119
|
+
### Synchronization Security
|
|
120
|
+
|
|
121
|
+
`Synchronize` and `dropSchema` can modify worksheet structure.
|
|
122
|
+
|
|
123
|
+
They should therefore be treated as privileged configuration in production.
|
|
124
|
+
|
|
125
|
+
Do not enable destructive schema operations in production unless the application intentionally requires them and the consequences are understood.
|
|
126
|
+
|
|
127
|
+
### Data Sensitivity
|
|
128
|
+
|
|
129
|
+
The driver does not encrypt spreadsheet data at the application layer.
|
|
130
|
+
|
|
131
|
+
If sensitive information is stored in Google Sheets, the application should consider:
|
|
132
|
+
|
|
133
|
+
- who can access the spreadsheet
|
|
134
|
+
- which service accounts have access
|
|
135
|
+
- whether the data should be stored in a spreadsheet at all
|
|
136
|
+
- whether additional application-level encryption is required
|
|
137
|
+
|
|
138
|
+
Google Sheets should not automatically be considered an appropriate storage location for highly sensitive data.
|
|
139
|
+
|
|
140
|
+
### Security Summary
|
|
141
|
+
|
|
142
|
+
The main security responsibilities are:
|
|
143
|
+
|
|
144
|
+
1. Protect the service account private key.
|
|
145
|
+
2. Keep credentials out of source control.
|
|
146
|
+
3. Restrict spreadsheet permissions.
|
|
147
|
+
4. Avoid logging authentication information.
|
|
148
|
+
5. Treat custom clients as part of the security boundary.
|
|
149
|
+
6. Use secure secret storage in production.
|
|
150
|
+
7. Be careful with `synchronize` and `dropSchema`.
|
|
151
|
+
8. Evaluate whether sensitive data belongs in Google Sheets.
|
|
152
|
+
|
|
153
|
+
The driver provides the integration layer, while authentication, authorization, credential management, and data classification remain application and infrastructure responsibilities.
|
package/docs/sorting.md
ADDED
|
File without changes
|
|
@@ -0,0 +1,310 @@
|
|
|
1
|
+
## Supported Features
|
|
2
|
+
|
|
3
|
+
The Google Sheets driver supports a subset of TypeORM features that are applicable to Google Sheets.
|
|
4
|
+
|
|
5
|
+
The following table summarizes the currently supported functionality.
|
|
6
|
+
|
|
7
|
+
### Data Source
|
|
8
|
+
|
|
9
|
+
| Feature | Status |
|
|
10
|
+
| --------------------------- | --------- |
|
|
11
|
+
| Google Sheets data source | Supported |
|
|
12
|
+
| Custom Google Sheets client | Supported |
|
|
13
|
+
| Multiple entities | Supported |
|
|
14
|
+
| Entity subscribers | Supported |
|
|
15
|
+
| Entity lifecycle hooks | Supported |
|
|
16
|
+
| Synchronization | Supported |
|
|
17
|
+
| Logging configuration | Supported |
|
|
18
|
+
|
|
19
|
+
### CRUD
|
|
20
|
+
|
|
21
|
+
| Operation | Status |
|
|
22
|
+
| ------------------- | --------- |
|
|
23
|
+
| `insert()` | Supported |
|
|
24
|
+
| `save()` | Supported |
|
|
25
|
+
| `find()` | Supported |
|
|
26
|
+
| `findOne()` | Supported |
|
|
27
|
+
| `update()` | Supported |
|
|
28
|
+
| `delete()` | Supported |
|
|
29
|
+
| `remove()` | Supported |
|
|
30
|
+
| `softDelete()` | Supported |
|
|
31
|
+
| `restore()` | Supported |
|
|
32
|
+
| `softRemove()` | Supported |
|
|
33
|
+
| Multiple-row insert | Supported |
|
|
34
|
+
| Multiple-row update | Supported |
|
|
35
|
+
| Multiple-row delete | Supported |
|
|
36
|
+
|
|
37
|
+
`save()` supports normal entity persistence and column-based foreign-key values.
|
|
38
|
+
|
|
39
|
+
Nested relation persistence and cascade persistence are not fully supported. See [Limitations](#limitations) for details.
|
|
40
|
+
|
|
41
|
+
### Find Options
|
|
42
|
+
|
|
43
|
+
| Feature | Status |
|
|
44
|
+
| ------------------------------- | --------- |
|
|
45
|
+
| `where` | Supported |
|
|
46
|
+
| OR conditions using `where: []` | Supported |
|
|
47
|
+
| `order` | Supported |
|
|
48
|
+
| Multiple-field ordering | Supported |
|
|
49
|
+
| `skip` | Supported |
|
|
50
|
+
| `take` | Supported |
|
|
51
|
+
| `findAndCount()` | Supported |
|
|
52
|
+
| `count()` | Supported |
|
|
53
|
+
| `findOne()` with `where` | Supported |
|
|
54
|
+
| `findOne()` with `order` | Supported |
|
|
55
|
+
| `withDeleted` | Supported |
|
|
56
|
+
|
|
57
|
+
### Primary Keys
|
|
58
|
+
|
|
59
|
+
| Feature | Status |
|
|
60
|
+
| ------------------------------- | ------------- |
|
|
61
|
+
| `@PrimaryColumn()` | Supported |
|
|
62
|
+
| `@PrimaryGeneratedColumn()` | Supported |
|
|
63
|
+
| Increment generated IDs | Supported |
|
|
64
|
+
| UUID generated IDs | Supported |
|
|
65
|
+
| Explicit generated primary key | Supported |
|
|
66
|
+
| Duplicate primary key detection | Supported |
|
|
67
|
+
| Missing primary key detection | Supported |
|
|
68
|
+
| `identity` generation strategy | Not supported |
|
|
69
|
+
| `rowid` generation strategy | Not supported |
|
|
70
|
+
|
|
71
|
+
When an explicit generated primary key is supplied, the driver preserves the supplied value and checks for duplicates.
|
|
72
|
+
|
|
73
|
+
### Data Types
|
|
74
|
+
|
|
75
|
+
The driver uses TypeORM entity metadata to interpret worksheet values and hydrate them into the expected entity types.
|
|
76
|
+
|
|
77
|
+
| Type | Status |
|
|
78
|
+
| --------- | --------- |
|
|
79
|
+
| `string` | Supported |
|
|
80
|
+
| `number` | Supported |
|
|
81
|
+
| `boolean` | Supported |
|
|
82
|
+
| `Date` | Supported |
|
|
83
|
+
| `uuid` | Supported |
|
|
84
|
+
| `int` | Supported |
|
|
85
|
+
| `null` | Supported |
|
|
86
|
+
|
|
87
|
+
Google Sheets commonly returns cell values as strings. The driver performs type conversion based on the corresponding TypeORM column metadata.
|
|
88
|
+
|
|
89
|
+
For example:
|
|
90
|
+
|
|
91
|
+
```ts
|
|
92
|
+
id: 1
|
|
93
|
+
age: 30
|
|
94
|
+
active: true
|
|
95
|
+
createdAt: new Date(...)
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
are hydrated as their corresponding TypeScript runtime values rather than being returned as raw worksheet strings.
|
|
99
|
+
|
|
100
|
+
### Entity Metadata
|
|
101
|
+
|
|
102
|
+
| Feature | Status |
|
|
103
|
+
| -------------------------- | -------------------------------------------- |
|
|
104
|
+
| Entity metadata resolution | Supported |
|
|
105
|
+
| Custom worksheet names | Supported |
|
|
106
|
+
| Custom column names | Supported |
|
|
107
|
+
| Naming strategies | Supported through TypeORM-generated metadata |
|
|
108
|
+
| Create date columns | Supported |
|
|
109
|
+
| Update date columns | Supported |
|
|
110
|
+
| Delete date columns | Supported |
|
|
111
|
+
| Relation metadata | Supported |
|
|
112
|
+
| Relation loading | Supported |
|
|
113
|
+
|
|
114
|
+
### Relations
|
|
115
|
+
|
|
116
|
+
Basic relation metadata, relation loading, and supported JOIN operations are supported.
|
|
117
|
+
|
|
118
|
+
For example:
|
|
119
|
+
|
|
120
|
+
```ts
|
|
121
|
+
id: 1
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
```ts
|
|
125
|
+
const post = await repository.findOne({
|
|
126
|
+
where: {
|
|
127
|
+
id: 1
|
|
128
|
+
},
|
|
129
|
+
|
|
130
|
+
relations: {
|
|
131
|
+
author: true
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
Relations can also be represented through explicit foreign-key columns:
|
|
137
|
+
|
|
138
|
+
```ts
|
|
139
|
+
post.userId = user.id;
|
|
140
|
+
|
|
141
|
+
await postRepository.save(post);
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
However, Google Sheets does not provide database-level relational features such as foreign-key constraints or referential integrity.
|
|
145
|
+
|
|
146
|
+
Nested relation persistence and cascade operations are not fully supported.
|
|
147
|
+
|
|
148
|
+
### Soft Delete
|
|
149
|
+
|
|
150
|
+
Soft-delete operations using TypeORM delete-date metadata are supported.
|
|
151
|
+
|
|
152
|
+
For example:
|
|
153
|
+
|
|
154
|
+
```ts
|
|
155
|
+
@DeleteDateColumn({
|
|
156
|
+
nullable: true,
|
|
157
|
+
})
|
|
158
|
+
deletedAt!: Date | null;
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
The driver supports:
|
|
162
|
+
|
|
163
|
+
* `softDelete()`
|
|
164
|
+
* `softRemove()`
|
|
165
|
+
* `restore()`
|
|
166
|
+
* filtering soft-deleted rows from normal queries
|
|
167
|
+
* `withDeleted`
|
|
168
|
+
* soft-delete filtering when loading supported relations
|
|
169
|
+
|
|
170
|
+
Soft deletion remains an application-level operation because Google Sheets does not provide database-level soft-delete semantics.
|
|
171
|
+
|
|
172
|
+
### Lifecycle Hooks
|
|
173
|
+
|
|
174
|
+
The driver supports relevant TypeORM entity lifecycle hooks, including:
|
|
175
|
+
|
|
176
|
+
```text
|
|
177
|
+
@BeforeInsert
|
|
178
|
+
@AfterInsert
|
|
179
|
+
|
|
180
|
+
@BeforeUpdate
|
|
181
|
+
@AfterUpdate
|
|
182
|
+
|
|
183
|
+
@BeforeRemove
|
|
184
|
+
@AfterRemove
|
|
185
|
+
|
|
186
|
+
@AfterLoad
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
Entity subscribers are also supported.
|
|
190
|
+
|
|
191
|
+
### Query Runner
|
|
192
|
+
|
|
193
|
+
The driver provides a `QueryRunner` implementation for supported Google Sheets operations.
|
|
194
|
+
|
|
195
|
+
Supported query operations include the operations implemented by the Google Sheets query interpreter and query runner.
|
|
196
|
+
|
|
197
|
+
Unsupported operations are rejected by the driver rather than silently executed with potentially incorrect semantics.
|
|
198
|
+
|
|
199
|
+
### Batch Operations
|
|
200
|
+
|
|
201
|
+
The Google Sheets API client supports batching compatible operations to reduce the number of API requests.
|
|
202
|
+
|
|
203
|
+
This includes:
|
|
204
|
+
|
|
205
|
+
* multiple-row reads
|
|
206
|
+
* multiple-row inserts
|
|
207
|
+
* multiple-row updates
|
|
208
|
+
* multiple-row deletes
|
|
209
|
+
|
|
210
|
+
Non-contiguous updates may require separate API requests when the underlying ranges cannot be combined safely.
|
|
211
|
+
|
|
212
|
+
### Transactions
|
|
213
|
+
|
|
214
|
+
Database transactions are **not supported**.
|
|
215
|
+
|
|
216
|
+
Google Sheets does not provide transactional semantics equivalent to a relational database.
|
|
217
|
+
|
|
218
|
+
Applications should not rely on:
|
|
219
|
+
|
|
220
|
+
```ts
|
|
221
|
+
dataSource.transaction(...)
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
for atomic multi-operation behavior.
|
|
225
|
+
|
|
226
|
+
See [Limitations](#limitations) for details.
|
|
227
|
+
|
|
228
|
+
### Migrations
|
|
229
|
+
|
|
230
|
+
Migration-related configuration is exposed through the data source options, but traditional relational database migrations are not supported as a full database migration mechanism.
|
|
231
|
+
|
|
232
|
+
Schema changes should instead be handled through worksheet synchronization and the schema-management capabilities provided by the driver.
|
|
233
|
+
|
|
234
|
+
### Synchronization
|
|
235
|
+
|
|
236
|
+
Schema synchronization is supported for worksheet structures.
|
|
237
|
+
|
|
238
|
+
The driver can:
|
|
239
|
+
|
|
240
|
+
* create missing worksheets
|
|
241
|
+
* create worksheet headers
|
|
242
|
+
* add missing columns to existing worksheets
|
|
243
|
+
|
|
244
|
+
Synchronization operates on worksheet structure rather than relational database schema objects.
|
|
245
|
+
|
|
246
|
+
### Logging
|
|
247
|
+
|
|
248
|
+
TypeORM logging configuration is supported.
|
|
249
|
+
|
|
250
|
+
For example:
|
|
251
|
+
|
|
252
|
+
```ts
|
|
253
|
+
const dataSource = new DataSource({
|
|
254
|
+
type: 'google-sheets',
|
|
255
|
+
|
|
256
|
+
logging: [
|
|
257
|
+
'query',
|
|
258
|
+
'error',
|
|
259
|
+
'schema',
|
|
260
|
+
],
|
|
261
|
+
});
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
The driver integrates with TypeORM's logger for supported query, error, and schema operations.
|
|
265
|
+
|
|
266
|
+
### Custom Client
|
|
267
|
+
|
|
268
|
+
Applications can provide a custom `GoogleSheetsClient` implementation instead of using the default Google Sheets API client.
|
|
269
|
+
|
|
270
|
+
This can be useful for:
|
|
271
|
+
|
|
272
|
+
* testing
|
|
273
|
+
* custom transport implementations
|
|
274
|
+
* alternative data sources
|
|
275
|
+
* controlling API behavior
|
|
276
|
+
|
|
277
|
+
### Feature Compatibility Principle
|
|
278
|
+
|
|
279
|
+
TypeORM exposes a large API surface because it supports many relational database systems.
|
|
280
|
+
|
|
281
|
+
The presence of a TypeORM option does not automatically mean that the Google Sheets driver supports that option.
|
|
282
|
+
|
|
283
|
+
Applications should rely on the capabilities documented by this driver and its tests rather than assuming full relational-database compatibility.
|
|
284
|
+
|
|
285
|
+
### Summary
|
|
286
|
+
|
|
287
|
+
The driver currently provides:
|
|
288
|
+
|
|
289
|
+
```text
|
|
290
|
+
TypeORM Repository
|
|
291
|
+
│
|
|
292
|
+
├── CRUD
|
|
293
|
+
├── Find Options
|
|
294
|
+
├── Sorting
|
|
295
|
+
├── Pagination
|
|
296
|
+
├── Type Conversion
|
|
297
|
+
├── Generated IDs
|
|
298
|
+
├── Soft Delete
|
|
299
|
+
├── Lifecycle Hooks
|
|
300
|
+
├── Subscribers
|
|
301
|
+
├── Relations / Relation Loading
|
|
302
|
+
├── Synchronization
|
|
303
|
+
├── Logging
|
|
304
|
+
└── Custom Client
|
|
305
|
+
│
|
|
306
|
+
▼
|
|
307
|
+
Google Sheets
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
Features that depend on relational-database guarantees, such as transactions, foreign-key enforcement, database-level cascades, and full relational persistence semantics, are outside the capabilities of Google Sheets.
|