@functional-systems/lambdadb 0.3.2 → 0.3.4-dev.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 (156) hide show
  1. package/README.md +44 -2
  2. package/dist/commonjs/client.d.ts +6 -6
  3. package/dist/commonjs/client.d.ts.map +1 -1
  4. package/dist/commonjs/client.js +33 -9
  5. package/dist/commonjs/client.js.map +1 -1
  6. package/dist/commonjs/funcs/collectionsDocsBulkUpsert.d.ts +1 -1
  7. package/dist/commonjs/funcs/collectionsDocsBulkUpsert.js +1 -1
  8. package/dist/commonjs/funcs/collectionsDocsGetBulkUpsert.d.ts +2 -2
  9. package/dist/commonjs/funcs/collectionsDocsGetBulkUpsert.d.ts.map +1 -1
  10. package/dist/commonjs/funcs/collectionsDocsGetBulkUpsert.js +3 -3
  11. package/dist/commonjs/funcs/collectionsDocsGetBulkUpsert.js.map +1 -1
  12. package/dist/commonjs/lib/matchers.d.ts.map +1 -1
  13. package/dist/commonjs/lib/matchers.js +17 -1
  14. package/dist/commonjs/lib/matchers.js.map +1 -1
  15. package/dist/commonjs/lib/schemas.d.ts +6 -0
  16. package/dist/commonjs/lib/schemas.d.ts.map +1 -1
  17. package/dist/commonjs/lib/schemas.js +9 -0
  18. package/dist/commonjs/lib/schemas.js.map +1 -1
  19. package/dist/commonjs/models/collectionresponse.js +4 -4
  20. package/dist/commonjs/models/collectionresponse.js.map +1 -1
  21. package/dist/commonjs/models/errors/badrequesterror.d.ts.map +1 -1
  22. package/dist/commonjs/models/errors/badrequesterror.js +2 -1
  23. package/dist/commonjs/models/errors/badrequesterror.js.map +1 -1
  24. package/dist/commonjs/models/errors/internalservererror.d.ts.map +1 -1
  25. package/dist/commonjs/models/errors/internalservererror.js +2 -1
  26. package/dist/commonjs/models/errors/internalservererror.js.map +1 -1
  27. package/dist/commonjs/models/errors/resourcealreadyexistserror.d.ts.map +1 -1
  28. package/dist/commonjs/models/errors/resourcealreadyexistserror.js +2 -1
  29. package/dist/commonjs/models/errors/resourcealreadyexistserror.js.map +1 -1
  30. package/dist/commonjs/models/errors/resourcenotfounderror.d.ts.map +1 -1
  31. package/dist/commonjs/models/errors/resourcenotfounderror.js +2 -1
  32. package/dist/commonjs/models/errors/resourcenotfounderror.js.map +1 -1
  33. package/dist/commonjs/models/errors/toomanyrequestserror.d.ts.map +1 -1
  34. package/dist/commonjs/models/errors/toomanyrequestserror.js +2 -1
  35. package/dist/commonjs/models/errors/toomanyrequestserror.js.map +1 -1
  36. package/dist/commonjs/models/errors/unauthenticatederror.d.ts.map +1 -1
  37. package/dist/commonjs/models/errors/unauthenticatederror.js +2 -1
  38. package/dist/commonjs/models/errors/unauthenticatederror.js.map +1 -1
  39. package/dist/commonjs/models/indexconfigsunion.d.ts +76 -4
  40. package/dist/commonjs/models/indexconfigsunion.d.ts.map +1 -1
  41. package/dist/commonjs/models/indexconfigsunion.js +58 -3
  42. package/dist/commonjs/models/indexconfigsunion.js.map +1 -1
  43. package/dist/commonjs/models/operations/fetchdocs.js +1 -1
  44. package/dist/commonjs/models/operations/fetchdocs.js.map +1 -1
  45. package/dist/commonjs/models/operations/getbulkupsertdocs.js +3 -3
  46. package/dist/commonjs/models/operations/getbulkupsertdocs.js.map +1 -1
  47. package/dist/commonjs/models/operations/listcollections.js +1 -1
  48. package/dist/commonjs/models/operations/listcollections.js.map +1 -1
  49. package/dist/commonjs/models/operations/listdocs.js +2 -2
  50. package/dist/commonjs/models/operations/listdocs.js.map +1 -1
  51. package/dist/commonjs/models/operations/querycollection.d.ts +1 -1
  52. package/dist/commonjs/models/operations/querycollection.js +3 -3
  53. package/dist/commonjs/models/operations/querycollection.js.map +1 -1
  54. package/dist/commonjs/models/operations/updatedocs.d.ts +1 -1
  55. package/dist/commonjs/models/operations/upsertdocs.d.ts +1 -1
  56. package/dist/commonjs/models/partitionconfig.js +3 -3
  57. package/dist/commonjs/models/partitionconfig.js.map +1 -1
  58. package/dist/commonjs/sdk/docs.d.ts +2 -2
  59. package/dist/commonjs/sdk/docs.js +2 -2
  60. package/dist/commonjs/types/errors.d.ts +1 -1
  61. package/dist/commonjs/types/errors.d.ts.map +1 -1
  62. package/dist/commonjs/types/public.d.ts +1 -1
  63. package/dist/commonjs/types/public.d.ts.map +1 -1
  64. package/dist/commonjs/types/public.js.map +1 -1
  65. package/dist/esm/client.d.ts +6 -6
  66. package/dist/esm/client.d.ts.map +1 -1
  67. package/dist/esm/client.js +33 -9
  68. package/dist/esm/client.js.map +1 -1
  69. package/dist/esm/funcs/collectionsDocsBulkUpsert.d.ts +1 -1
  70. package/dist/esm/funcs/collectionsDocsBulkUpsert.js +1 -1
  71. package/dist/esm/funcs/collectionsDocsGetBulkUpsert.d.ts +2 -2
  72. package/dist/esm/funcs/collectionsDocsGetBulkUpsert.d.ts.map +1 -1
  73. package/dist/esm/funcs/collectionsDocsGetBulkUpsert.js +3 -3
  74. package/dist/esm/funcs/collectionsDocsGetBulkUpsert.js.map +1 -1
  75. package/dist/esm/lib/matchers.d.ts.map +1 -1
  76. package/dist/esm/lib/matchers.js +17 -1
  77. package/dist/esm/lib/matchers.js.map +1 -1
  78. package/dist/esm/lib/schemas.d.ts +6 -0
  79. package/dist/esm/lib/schemas.d.ts.map +1 -1
  80. package/dist/esm/lib/schemas.js +9 -1
  81. package/dist/esm/lib/schemas.js.map +1 -1
  82. package/dist/esm/models/collectionresponse.js +5 -5
  83. package/dist/esm/models/collectionresponse.js.map +1 -1
  84. package/dist/esm/models/errors/badrequesterror.d.ts.map +1 -1
  85. package/dist/esm/models/errors/badrequesterror.js +2 -1
  86. package/dist/esm/models/errors/badrequesterror.js.map +1 -1
  87. package/dist/esm/models/errors/internalservererror.d.ts.map +1 -1
  88. package/dist/esm/models/errors/internalservererror.js +2 -1
  89. package/dist/esm/models/errors/internalservererror.js.map +1 -1
  90. package/dist/esm/models/errors/resourcealreadyexistserror.d.ts.map +1 -1
  91. package/dist/esm/models/errors/resourcealreadyexistserror.js +2 -1
  92. package/dist/esm/models/errors/resourcealreadyexistserror.js.map +1 -1
  93. package/dist/esm/models/errors/resourcenotfounderror.d.ts.map +1 -1
  94. package/dist/esm/models/errors/resourcenotfounderror.js +2 -1
  95. package/dist/esm/models/errors/resourcenotfounderror.js.map +1 -1
  96. package/dist/esm/models/errors/toomanyrequestserror.d.ts.map +1 -1
  97. package/dist/esm/models/errors/toomanyrequestserror.js +2 -1
  98. package/dist/esm/models/errors/toomanyrequestserror.js.map +1 -1
  99. package/dist/esm/models/errors/unauthenticatederror.d.ts.map +1 -1
  100. package/dist/esm/models/errors/unauthenticatederror.js +2 -1
  101. package/dist/esm/models/errors/unauthenticatederror.js.map +1 -1
  102. package/dist/esm/models/indexconfigsunion.d.ts +76 -4
  103. package/dist/esm/models/indexconfigsunion.d.ts.map +1 -1
  104. package/dist/esm/models/indexconfigsunion.js +54 -3
  105. package/dist/esm/models/indexconfigsunion.js.map +1 -1
  106. package/dist/esm/models/operations/fetchdocs.js +2 -2
  107. package/dist/esm/models/operations/fetchdocs.js.map +1 -1
  108. package/dist/esm/models/operations/getbulkupsertdocs.js +4 -4
  109. package/dist/esm/models/operations/getbulkupsertdocs.js.map +1 -1
  110. package/dist/esm/models/operations/listcollections.js +2 -2
  111. package/dist/esm/models/operations/listcollections.js.map +1 -1
  112. package/dist/esm/models/operations/listdocs.js +3 -3
  113. package/dist/esm/models/operations/listdocs.js.map +1 -1
  114. package/dist/esm/models/operations/querycollection.d.ts +1 -1
  115. package/dist/esm/models/operations/querycollection.js +4 -4
  116. package/dist/esm/models/operations/querycollection.js.map +1 -1
  117. package/dist/esm/models/operations/updatedocs.d.ts +1 -1
  118. package/dist/esm/models/operations/upsertdocs.d.ts +1 -1
  119. package/dist/esm/models/partitionconfig.js +4 -4
  120. package/dist/esm/models/partitionconfig.js.map +1 -1
  121. package/dist/esm/sdk/docs.d.ts +2 -2
  122. package/dist/esm/sdk/docs.js +2 -2
  123. package/dist/esm/types/errors.d.ts +1 -1
  124. package/dist/esm/types/errors.d.ts.map +1 -1
  125. package/dist/esm/types/public.d.ts +1 -1
  126. package/dist/esm/types/public.d.ts.map +1 -1
  127. package/dist/esm/types/public.js.map +1 -1
  128. package/package.json +2 -2
  129. package/src/client.ts +38 -9
  130. package/src/funcs/collectionsDocsBulkUpsert.ts +1 -1
  131. package/src/funcs/collectionsDocsGetBulkUpsert.ts +6 -2
  132. package/src/lib/matchers.ts +18 -1
  133. package/src/lib/schemas.ts +12 -0
  134. package/src/models/collectionresponse.ts +5 -5
  135. package/src/models/errors/badrequesterror.ts +2 -1
  136. package/src/models/errors/internalservererror.ts +2 -1
  137. package/src/models/errors/resourcealreadyexistserror.ts +2 -1
  138. package/src/models/errors/resourcenotfounderror.ts +2 -1
  139. package/src/models/errors/toomanyrequestserror.ts +2 -1
  140. package/src/models/errors/unauthenticatederror.ts +2 -1
  141. package/src/models/indexconfigsunion.ts +162 -5
  142. package/src/models/operations/fetchdocs.ts +2 -2
  143. package/src/models/operations/getbulkupsertdocs.ts +4 -4
  144. package/src/models/operations/listcollections.ts +2 -2
  145. package/src/models/operations/listdocs.ts +3 -3
  146. package/src/models/operations/querycollection.ts +5 -5
  147. package/src/models/operations/updatedocs.ts +1 -1
  148. package/src/models/operations/upsertdocs.ts +1 -1
  149. package/src/models/partitionconfig.ts +4 -4
  150. package/src/sdk/docs.ts +2 -2
  151. package/src/types/errors.ts +3 -1
  152. package/src/types/public.ts +3 -0
  153. package/test/null-response.test.mjs +73 -0
  154. package/test/public-api.test.mjs +348 -0
  155. package/tsconfig.json +1 -2
  156. package/.devcontainer/devcontainer.json +0 -45
@@ -0,0 +1,348 @@
1
+ import assert from "node:assert/strict";
2
+ import test from "node:test";
3
+
4
+ import {
5
+ BadRequestError,
6
+ HTTPClient,
7
+ LambdaDBClient,
8
+ } from "../dist/esm/index.js";
9
+
10
+ const BASE_URL = "https://api.test";
11
+ const PROJECT_NAME = "project-one";
12
+
13
+ function jsonResponse(body, init = {}) {
14
+ return new Response(JSON.stringify(body), {
15
+ status: 200,
16
+ headers: { "content-type": "application/json" },
17
+ ...init,
18
+ });
19
+ }
20
+
21
+ function collectionFixture(collectionName, overrides = {}) {
22
+ return {
23
+ projectName: PROJECT_NAME,
24
+ collectionName,
25
+ indexConfigs: {},
26
+ numPartitions: 1,
27
+ numDocs: 2,
28
+ sourceProjectName: null,
29
+ sourceCollectionName: null,
30
+ sourceCollectionVersionId: null,
31
+ collectionStatus: "ACTIVE",
32
+ createdAt: 1700000000,
33
+ updatedAt: 1700000100,
34
+ dataUpdatedAt: 1700000200,
35
+ ...overrides,
36
+ };
37
+ }
38
+
39
+ function createClient(handler) {
40
+ const calls = [];
41
+ const httpClient = new HTTPClient({
42
+ fetcher: async (request) => {
43
+ const body = await request.clone().text();
44
+ const call = {
45
+ body,
46
+ headers: Object.fromEntries(request.headers.entries()),
47
+ method: request.method,
48
+ url: new URL(request.url),
49
+ };
50
+ calls.push(call);
51
+ return handler(call, calls.length - 1);
52
+ },
53
+ });
54
+
55
+ const client = new LambdaDBClient({
56
+ baseUrl: BASE_URL,
57
+ httpClient,
58
+ projectApiKey: "test-key",
59
+ projectName: PROJECT_NAME,
60
+ });
61
+
62
+ return { calls, client };
63
+ }
64
+
65
+ test("public client lists collections with project URL, auth header, and Date conversion", async () => {
66
+ const { calls, client } = createClient(() =>
67
+ jsonResponse({
68
+ collections: [collectionFixture("alpha")],
69
+ nextPageToken: null,
70
+ })
71
+ );
72
+
73
+ const result = await client.listCollections({ size: 5 });
74
+
75
+ assert.equal(calls.length, 1);
76
+ assert.equal(calls[0].method, "GET");
77
+ assert.equal(calls[0].url.pathname, "/projects/project-one/collections");
78
+ assert.equal(calls[0].url.searchParams.get("size"), "5");
79
+ assert.equal(calls[0].headers["x-api-key"], "test-key");
80
+ assert.equal(result.nextPageToken, undefined);
81
+ assert.equal(result.collections[0].collectionName, "alpha");
82
+ assert.ok(result.collections[0].createdAt instanceof Date);
83
+ assert.equal(result.collections[0].createdAt.toISOString(), "2023-11-14T22:13:20.000Z");
84
+ });
85
+
86
+ test("public client supports managed embedding vector index configs", async () => {
87
+ const managedIndexConfigs = {
88
+ body: {
89
+ type: "text",
90
+ analyzers: ["english"],
91
+ },
92
+ bodyEmbedding: {
93
+ type: "vector",
94
+ managedEmbedding: true,
95
+ embedding: {
96
+ provider: "openai",
97
+ model: "text-embedding-3-small",
98
+ sourceField: "body",
99
+ },
100
+ },
101
+ };
102
+
103
+ const { calls, client } = createClient((call) => {
104
+ assert.equal(call.method, "POST");
105
+ assert.equal(call.url.pathname, "/projects/project-one/collections");
106
+ assert.deepEqual(JSON.parse(call.body), {
107
+ collectionName: "semantic-items",
108
+ indexConfigs: {
109
+ body: {
110
+ type: "text",
111
+ analyzers: ["english"],
112
+ },
113
+ bodyEmbedding: {
114
+ type: "vector",
115
+ managedEmbedding: true,
116
+ embedding: {
117
+ provider: "openai",
118
+ model: "text-embedding-3-small",
119
+ sourceField: "body",
120
+ },
121
+ },
122
+ },
123
+ });
124
+
125
+ return jsonResponse(
126
+ {
127
+ collection: collectionFixture("semantic-items", {
128
+ indexConfigs: {
129
+ ...managedIndexConfigs,
130
+ bodyEmbedding: {
131
+ ...managedIndexConfigs.bodyEmbedding,
132
+ embedding: {
133
+ ...managedIndexConfigs.bodyEmbedding.embedding,
134
+ dimensions: 1536,
135
+ similarity: "cosine",
136
+ },
137
+ },
138
+ },
139
+ }),
140
+ },
141
+ { status: 202 },
142
+ );
143
+ });
144
+
145
+ const result = await client.createCollection({
146
+ collectionName: "semantic-items",
147
+ indexConfigs: managedIndexConfigs,
148
+ });
149
+
150
+ assert.equal(calls.length, 1);
151
+ assert.equal(
152
+ result.collection.indexConfigs.bodyEmbedding.embedding.dimensions,
153
+ 1536,
154
+ );
155
+ assert.equal(
156
+ result.collection.indexConfigs.bodyEmbedding.embedding.similarity,
157
+ "cosine",
158
+ );
159
+ });
160
+
161
+ test("collection query supports managed embedding queryText KNN payloads", async () => {
162
+ const { calls, client } = createClient((call) => {
163
+ assert.equal(call.method, "POST");
164
+ assert.equal(call.url.pathname, "/projects/project-one/collections/items/query");
165
+ assert.deepEqual(JSON.parse(call.body), {
166
+ size: 10,
167
+ query: {
168
+ knn: {
169
+ field: "bodyEmbedding",
170
+ queryText: "refund policy",
171
+ k: 10,
172
+ },
173
+ },
174
+ consistentRead: false,
175
+ includeVectors: false,
176
+ });
177
+
178
+ return jsonResponse({
179
+ took: 3,
180
+ maxScore: 0.98,
181
+ total: 1,
182
+ docs: [{ collection: "items", score: 0.98, doc: { id: "a" } }],
183
+ isDocsInline: true,
184
+ docsUrl: null,
185
+ });
186
+ });
187
+
188
+ const result = await client.collection("items").query({
189
+ size: 10,
190
+ query: {
191
+ knn: {
192
+ field: "bodyEmbedding",
193
+ queryText: "refund policy",
194
+ k: 10,
195
+ },
196
+ },
197
+ });
198
+
199
+ assert.equal(calls.length, 1);
200
+ assert.equal(result.total, 1);
201
+ });
202
+
203
+ test("getBulkUpsertSafe exposes managed embedding unsupported bad requests", async () => {
204
+ const { client } = createClient((call) => {
205
+ assert.equal(call.method, "GET");
206
+ assert.equal(call.url.pathname, "/projects/project-one/collections/items/docs/bulk-upsert");
207
+
208
+ return jsonResponse(
209
+ { message: "Bulk upsert is not supported for collections with managed embedding fields" },
210
+ { status: 400 },
211
+ );
212
+ });
213
+
214
+ const result = await client.collection("items").docs.getBulkUpsertSafe();
215
+
216
+ assert.equal(result.ok, false);
217
+ assert.ok(result.error instanceof BadRequestError);
218
+ assert.equal(
219
+ result.error.data$.message,
220
+ "Bulk upsert is not supported for collections with managed embedding fields",
221
+ );
222
+ });
223
+
224
+ test("public pagination helpers collect all collection pages", async () => {
225
+ const { calls, client } = createClient((call, index) => {
226
+ if (index === 0) {
227
+ return jsonResponse({
228
+ collections: [collectionFixture("alpha")],
229
+ nextPageToken: "next-page",
230
+ });
231
+ }
232
+
233
+ assert.equal(call.url.searchParams.get("pageToken"), "next-page");
234
+ return jsonResponse({
235
+ collections: [collectionFixture("beta")],
236
+ nextPageToken: null,
237
+ });
238
+ });
239
+
240
+ const result = await client.listAllCollections({ size: 1 });
241
+
242
+ assert.equal(calls.length, 2);
243
+ assert.deepEqual(
244
+ result.collections.map((collection) => collection.collectionName),
245
+ ["alpha", "beta"],
246
+ );
247
+ });
248
+
249
+ test("collection docs helpers paginate through the user-facing scoped API", async () => {
250
+ const { calls, client } = createClient((call, index) => {
251
+ assert.equal(call.method, "GET");
252
+ assert.equal(call.url.pathname, "/projects/project-one/collections/items/docs");
253
+
254
+ if (index === 0) {
255
+ return jsonResponse({
256
+ total: 2,
257
+ docs: [{ collection: "items", doc: { id: "a" } }],
258
+ nextPageToken: "docs-page-2",
259
+ isDocsInline: true,
260
+ docsUrl: null,
261
+ });
262
+ }
263
+
264
+ assert.equal(call.url.searchParams.get("pageToken"), "docs-page-2");
265
+ return jsonResponse({
266
+ total: 2,
267
+ docs: [{ collection: "items", doc: { id: "b" } }],
268
+ nextPageToken: null,
269
+ isDocsInline: true,
270
+ docsUrl: null,
271
+ });
272
+ });
273
+
274
+ const result = await client.collection("items").docs.listAll({ size: 1 });
275
+
276
+ assert.equal(calls.length, 2);
277
+ assert.equal(result.total, 2);
278
+ assert.deepEqual(result.docs, [
279
+ { collection: "items", doc: { id: "a" } },
280
+ { collection: "items", doc: { id: "b" } },
281
+ ]);
282
+ });
283
+
284
+ test("collection query fetches docsUrl and returns inline docs through the public API", async () => {
285
+ const originalFetch = globalThis.fetch;
286
+ const docsUrlCalls = [];
287
+ globalThis.fetch = async (input) => {
288
+ docsUrlCalls.push(String(input));
289
+ return jsonResponse({
290
+ docs: [{ collection: "items", score: 0.9, doc: { id: "a" } }],
291
+ });
292
+ };
293
+
294
+ try {
295
+ const { calls, client } = createClient((call) => {
296
+ assert.equal(call.method, "POST");
297
+ assert.equal(call.url.pathname, "/projects/project-one/collections/items/query");
298
+ assert.deepEqual(JSON.parse(call.body), {
299
+ query: { text: "hello" },
300
+ consistentRead: false,
301
+ includeVectors: false,
302
+ });
303
+
304
+ return jsonResponse({
305
+ took: 7,
306
+ maxScore: null,
307
+ total: 1,
308
+ docs: [],
309
+ isDocsInline: false,
310
+ docsUrl: "https://download.test/query-docs.json",
311
+ });
312
+ });
313
+
314
+ const result = await client.collection("items").querySafe({
315
+ query: { text: "hello" },
316
+ });
317
+
318
+ assert.equal(calls.length, 1);
319
+ assert.deepEqual(docsUrlCalls, ["https://download.test/query-docs.json"]);
320
+ assert.equal(result.ok, true);
321
+ assert.equal(result.value.isDocsInline, true);
322
+ assert.deepEqual(result.value.docs, [
323
+ { collection: "items", score: 0.9, doc: { id: "a" } },
324
+ ]);
325
+ } finally {
326
+ globalThis.fetch = originalFetch;
327
+ }
328
+ });
329
+
330
+ test("public safe methods expose typed API errors", async () => {
331
+ const { client } = createClient((call) => {
332
+ assert.equal(call.method, "POST");
333
+ assert.equal(call.url.pathname, "/projects/project-one/collections");
334
+
335
+ return jsonResponse(
336
+ { message: null },
337
+ { status: 400 },
338
+ );
339
+ });
340
+
341
+ const result = await client.createCollectionSafe({ collectionName: "items" });
342
+
343
+ assert.equal(result.ok, false);
344
+ assert.ok(result.error instanceof BadRequestError);
345
+ assert.equal(result.error.statusCode, 400);
346
+ assert.equal(result.error.body, "{\"message\":null}");
347
+ assert.equal(result.error.data$.message, undefined);
348
+ });
package/tsconfig.json CHANGED
@@ -14,9 +14,8 @@
14
14
  "declarationMap": true,
15
15
  "sourceMap": true,
16
16
  "outDir": ".",
17
-
17
+ "rootDir": "src",
18
18
 
19
- // https://github.com/tsconfig/bases/blob/a1bf7c0fa2e094b068ca3e1448ca2ece4157977e/bases/strictest.json
20
19
  "strict": true,
21
20
  "allowUnusedLabels": false,
22
21
  "allowUnreachableCode": false,
@@ -1,45 +0,0 @@
1
- // For format details, see https://aka.ms/devcontainer.json. For config options, see the
2
- // README at: https://github.com/devcontainers/images/tree/main/src/typescript-node
3
- {
4
- "name": "TypeScript",
5
- "image": "mcr.microsoft.com/devcontainers/typescript-node:1-20-bullseye",
6
- // Features to add to the dev container. More info: https://containers.dev/features.
7
- // "features": {},
8
- // Use 'forwardPorts' to make a list of ports inside the container available locally.
9
- // "forwardPorts": [],
10
- // Use 'postCreateCommand' to run commands after the container is created.
11
- "postCreateCommand": "sudo chmod +x ./.devcontainer/setup.sh && ./.devcontainer/setup.sh",
12
- "customizations": {
13
- "vscode": {
14
- "extensions": [
15
- "ms-vscode.vscode-typescript-tslint-plugin",
16
- "esbenp.prettier-vscode",
17
- "github.vscode-pull-request-github"
18
- ],
19
- "settings": {
20
- "files.eol": "\n",
21
- "editor.formatOnSave": true,
22
- "typescript.tsc.autoDetect": "on",
23
- "typescript.updateImportsOnFileMove.enabled": "always",
24
- "typescript.preferences.importModuleSpecifier": "relative",
25
- "[typescript]": {
26
- "editor.codeActionsOnSave": {
27
- "source.organizeImports": true
28
- }
29
- },
30
- "[typescriptreact]": {
31
- "editor.codeActionsOnSave": {
32
- "source.organizeImports": true
33
- }
34
- }
35
- }
36
- },
37
- "codespaces": {
38
- "openFiles": [
39
- ".devcontainer/README.md"
40
- ]
41
- }
42
- }
43
- // Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root.
44
- // "remoteUser": "root"
45
- }