@onroad/core 4.0.0-alpha.29 → 4.0.0-alpha.30

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/README.md CHANGED
@@ -1012,6 +1012,138 @@ Fix: disable `emitDecoratorMetadata`. @onroad/core uses only custom metadata key
1012
1012
 
1013
1013
  ---
1014
1014
 
1015
+ ### Custom route service methods must extract params from `req` — not expect primitive arguments
1016
+
1017
+ **`AbstractController` always calls custom service methods with the raw `(req, res)` objects.** It only extracts params for the five default CRUD methods (`create`, `read`, `readAll`, `update`, `delete`). Every method registered under `routes:` in the controller config receives `(req, res)` forwarded directly.
1018
+
1019
+ If your service method signature expects primitive parameters (`id: number`, `dataInicio: string`, etc.), it will receive the `req` object instead — causing silent failures (empty queries, NaN ids, wrong SQL filters) because the framework does **not** throw, it just passes the wrong value.
1020
+
1021
+ ```ts
1022
+ // ❌ Wrong — service expects primitives; controller passes (req, res)
1023
+ // Controller calls: this.service.findByBetweenDates(req, res)
1024
+ async findByBetweenDates(dataInicio: string, dataFim: string) {
1025
+ // dataInicio === req object → Sequelize WHERE clause receives an object → returns []
1026
+ return this.repository.findAll({ where: { dataDeAbertura: { [Op.gte]: dataInicio } } })
1027
+ }
1028
+ ```
1029
+
1030
+ ```ts
1031
+ // ✅ Correct — service extracts its own params from req
1032
+ async findByBetweenDates(req: any, res?: any) {
1033
+ const dataInicio: string = req.params.dataInicio
1034
+ const dataFim: string = req.params.dataFim
1035
+ return this.repository.findAll({ where: { dataDeAbertura: { [Op.gte]: dataInicio, [Op.lte]: dataFim } } })
1036
+ }
1037
+ ```
1038
+
1039
+ **Affected params by HTTP position:**
1040
+
1041
+ | Source | How to extract |
1042
+ |------------------|-----------------------------|
1043
+ | Route param (`:id`) | `req.params.id` |
1044
+ | Query string | `req.query.field` |
1045
+ | Request body | `req.body.field` |
1046
+ | Auth / identity | `req.decoded.userId` |
1047
+
1048
+ > **Rule of thumb:** In a TypeRoad service, if the method is registered as a custom route, **the first argument is always `req`**. Never write `async myMethod(id: number)` for a method that is called through a route config key — always write `async myMethod(req: any, res?: any)` and extract from `req` internally.
1049
+
1050
+ **Scope of impact in `teraprox-api-manutencao` (audit — 2025-04-05):**
1051
+
1052
+ The following service methods were found with the wrong signature (primitive params instead of `req`). All calls through their controller routes were silently broken:
1053
+
1054
+ | Service | Method | Broken params |
1055
+ |---------|--------|---------------|
1056
+ | `OrdemDeServicoService` | `findByBetweenDates` | `dataInicio`, `dataFim` — **fixed** |
1057
+ | `OrdemDeServicoService` | `findByRecursoBetweenDates` | `recursoId`, `dataInicio`, `dataFim` |
1058
+ | `OrdemDeServicoService` | `findByBranchIdBetweenDates` | `branchId`, `dataInicio`, `dataFim` |
1059
+ | `OrdemDeServicoService` | `findByRecursoId` | `recursoId` |
1060
+ | `OrdemDeServicoService` | `findMonitoramentoByCriticidade` | `criticidade` |
1061
+ | `OrdemDeServicoService` | `findByModoDeFalhaId` | `modoDeFalhaId` |
1062
+ | `OrdemDeServicoService` | `encerraOS` | `id`, `form` |
1063
+ | `OrdemDeServicoService` | `setStatusOs` | `id`, `form` |
1064
+ | `OrdemDeServicoService` | `setStatusOsBulk` | `osIds`, `status`, `extraData` |
1065
+ | `OrdemDeServicoService` | `iniciarOsBulk` | `osIds`, `status` |
1066
+ | `OrdemDeServicoService` | `addTarefaToOrdem` | `osId`, `tarefa` |
1067
+ | `OrdemDeServicoService` | `updateDescricaoOs` | `osId`, `descricao` |
1068
+ | `OrdemDeServicoService` | `shiftRecursoOs` | `osId`, `recId` |
1069
+ | `OrdemDeServicoService` | `findInspecoesBetweenDates` | `recursoId`, `dataInicio`, `dataFim` |
1070
+ | `OrdemDeServicoService` | `putAnexos` | `id`, `anexos` |
1071
+ | `OrdemDeServicoService` | `findOrdensInBatch` | `ids` |
1072
+ | `OrdemDeServicoService` | `loadOsForOcpMigration` | `osIds` |
1073
+ | `RecursoService` | `findRecursoFatherByRecursoId` | `recursoId` |
1074
+ | `RecursoService` | `findByTagDescription` | `tag` |
1075
+ | `RecursoService` | `findRecursoByTagId` | `tagId` |
1076
+ | `RecursoService` | `findParadasByRecursoId` | `recursoId` |
1077
+ | `RecursoService` | `findSemParadasByRecursoId` | `recursoId` |
1078
+ | `TarefaService` | `encerrarTarefa` | `id` |
1079
+ | `TarefaService` | `addUnidadeMaterialTarefa` | `tarefaId`, `form` |
1080
+ | `TarefaService` | `addObservacaoTarefa` | `tarefaId`, `form` |
1081
+ | `TarefaService` | `deleteObservacaoTarefa` | `justificativaId` |
1082
+ | `TarefaService` | `loadMultipleIds` | `tarefaIds` |
1083
+ | `TarefaService` | `removeAnexo` | `id`, `anexoKey` |
1084
+ | `SolicitacaoDeServicoService` | `shiftRecursoSs` | `ssId`, `recId` |
1085
+ | `SolicitacaoDeServicoService` | `aprovaSolicitacao` | `id`, `form` |
1086
+ | `SolicitacaoDeServicoService` | `reprovaSolicitacao` | `id`, `form` |
1087
+ | `SolicitacaoDeServicoService` | `updateDescricaoSs` | `ssId`, `descricao` |
1088
+ | `SolicitacaoDeServicoService` | `findByRecursoId` | `recursoId` |
1089
+ | `SolicitacaoDeServicoService` | `findBetweenDates` | `start`, `end` |
1090
+ | `SolicitacaoDeServicoService` | `putAnexos` | `id`, `anexos` |
1091
+
1092
+ ---
1093
+
1094
+ ### Custom route key name must exactly match the service method name
1095
+
1096
+ When you register a custom route in the controller config, the key name is used **verbatim** as the service method name to call. If the service was later renamed (e.g. during a refactor), the controller silently returns `null` because the `typeof service[methodName] === 'function'` guard evaluates to `false`.
1097
+
1098
+ ```ts
1099
+ // ❌ Wrong — controller key "addModoDeFalhaOS" but service method is "addModoDeFalha"
1100
+ routes: { addModoDeFalhaOS: { method: "post", path: "/..." } }
1101
+ // → service.addModoDeFalhaOS is undefined → always returns null (no error thrown)
1102
+ ```
1103
+
1104
+ **Known mismatches in `teraprox-api-manutencao` (audit — 2025-04-05):**
1105
+
1106
+ | Controller route key | Expected service method (by key) | Actual service method |
1107
+ |----------------------|-----------------------------------|-----------------------|
1108
+ | `addModoDeFalhaOS` | `addModoDeFalhaOS` | `addModoDeFalha` |
1109
+ | `updateTipoDeOrdem` | `updateTipoDeOrdem` | `setTipoOrdem` |
1110
+ | `updateTipoDeOrdemBulk` | `updateTipoDeOrdemBulk` | `setTipoOrdemBulk` |
1111
+ | `removeAnexo` | `removeAnexo` | `removeAnexoOs` |
1112
+ | `readConcluidasCount` | `readConcluidasCount` | `countTarefasConcluidas` |
1113
+ | `findPlanned` | `findPlanned` | `findPlannedOrdensBetweenDatesV2` |
1114
+ | `findPlannedV3` | `findPlannedV3` | `findPlannedOrdensBetweenDatesV3` |
1115
+ | `findPlannedAgregador` | `findPlannedAgregador` | `findPlannedOrdensWithAgregadores` |
1116
+ | `findRecorrenciaPlanned` | `findRecorrenciaPlanned` | `findPlannedOrdensFromRecorrenciaBetweenDates` |
1117
+ | `findAgregadorPlanned` | `findAgregadorPlanned` | `findPlannedOrdensFromAgregadorBetweenDates` |
1118
+ | `createInBulk` | `createInBulk` | `createInBulkOs` |
1119
+ | `findDashByOs` | `findDashByOs` | `findWithDashboardAssociation` |
1120
+
1121
+ > Fix: either rename the service method to match the route key, or rename the route key to match the service method. Both sides must be in sync.
1122
+
1123
+ ---
1124
+
1125
+ ### `BelongsToMany` association returns `null` (not `[]`) when no records exist
1126
+
1127
+ Sequelize's `BelongsToMany` association populates the association property with `null` (not an empty array) when no join-table records exist for a given entity. Any code that iterates over that property with `for...of` or `.forEach()` without a guard will throw `TypeError: x is not iterable`.
1128
+
1129
+ ```ts
1130
+ // ❌ Wrong — crashes with "TypeError: o.tarefas is not iterable" when OS has no tarefas
1131
+ for (const tarefa of o.tarefas) { ... }
1132
+ o.tarefas.forEach(...)
1133
+ o.tarefas.flatMap(...)
1134
+ ```
1135
+
1136
+ ```ts
1137
+ // ✅ Correct — guard with nullish coalescing
1138
+ for (const tarefa of (o.tarefas ?? [])) { ... }
1139
+ ;(o.tarefas ?? []).forEach(...)
1140
+ ordens.flatMap((o) => (o.tarefas ?? []).map(...))
1141
+ ```
1142
+
1143
+ > This was the direct cause of `TypeError: o.tarefas is not iterable` at `OrdemDeServicoService.buildTarefa` (line 235) and `findByBetweenDates`. Apply the same `?? []` guard to **all** `BelongsToMany` associations before iterating.
1144
+
1145
+ ---
1146
+
1015
1147
  ## Migration Guide — Lessons Learned (v3 → v4)
1016
1148
 
1017
1149
  This section documents the key issues found while migrating `teraprox-api-user` from onRoad v3 to TypeRoad v4. Use this as a checklist when migrating other APIs (`api-manutencao`, `api-processo`, etc.).
@@ -0,0 +1,15 @@
1
+ import { StorageProvider, UploadOptions, SignedUrlOptions, ObjectMetadata } from "./StorageProvider.js";
2
+ export declare class GCSStorageProvider extends StorageProvider {
3
+ private storage;
4
+ private bucketName;
5
+ constructor(bucketName: string);
6
+ buildObjectKey(opts: UploadOptions): string;
7
+ generateSignedUrl(key: string, opts: SignedUrlOptions): Promise<string>;
8
+ getObjectMetadata(key: string): Promise<ObjectMetadata | null>;
9
+ deleteObject(key: string): Promise<void>;
10
+ upload(_bucketName: string, _filePath: string, _data: Buffer, _contentType?: string): Promise<string>;
11
+ download(_bucketName: string, _filePath: string): Promise<Buffer>;
12
+ delete(_bucketName: string, filePath: string): Promise<void>;
13
+ getSignedUrl(_bucketName: string, filePath: string, expiresMs: number): Promise<string>;
14
+ }
15
+ //# sourceMappingURL=GCSStorageProvider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GCSStorageProvider.d.ts","sourceRoot":"","sources":["../../src/storage/GCSStorageProvider.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AAEvG,qBAAa,kBAAmB,SAAQ,eAAe;IACrD,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,UAAU,CAAQ;gBAEd,UAAU,EAAE,MAAM;IAM9B,cAAc,CAAC,IAAI,EAAE,aAAa,GAAG,MAAM;IAMrC,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAAC,MAAM,CAAC;IAcvE,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC;IAY9D,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAKxC,MAAM,CAAC,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAGrG,QAAQ,CAAC,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAGjE,MAAM,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAG5D,YAAY,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;CAG9F"}
@@ -0,0 +1,58 @@
1
+ import { Storage } from "@google-cloud/storage";
2
+ import { randomUUID } from "node:crypto";
3
+ import { StorageProvider } from "./StorageProvider.js";
4
+ export class GCSStorageProvider extends StorageProvider {
5
+ storage;
6
+ bucketName;
7
+ constructor(bucketName) {
8
+ super();
9
+ this.storage = new Storage(); // ADC - Assumes Cloud Run SA context
10
+ this.bucketName = bucketName;
11
+ }
12
+ buildObjectKey(opts) {
13
+ const uuid = randomUUID();
14
+ const safeName = opts.originalName.replace(/[^a-zA-Z0-9._-]/g, "_");
15
+ return `${opts.tenant}/${opts.dataContext}/${uuid}/${safeName}`;
16
+ }
17
+ async generateSignedUrl(key, opts) {
18
+ const file = this.storage.bucket(this.bucketName).file(key);
19
+ const defaultExpiry = opts.action === "write" ? 15 * 60_000 : 60 * 60_000;
20
+ const expires = opts.expiresMs ?? defaultExpiry;
21
+ const [url] = await file.getSignedUrl({
22
+ version: "v4",
23
+ action: opts.action,
24
+ expires: Date.now() + expires,
25
+ ...(opts.contentType && { contentType: opts.contentType }),
26
+ });
27
+ return url;
28
+ }
29
+ async getObjectMetadata(key) {
30
+ try {
31
+ const [metadata] = await this.storage.bucket(this.bucketName).file(key).getMetadata();
32
+ return {
33
+ size: Number(metadata.size),
34
+ contentType: metadata.contentType ?? ""
35
+ };
36
+ }
37
+ catch {
38
+ return null;
39
+ }
40
+ }
41
+ async deleteObject(key) {
42
+ await this.storage.bucket(this.bucketName).file(key).delete({ ignoreNotFound: true });
43
+ }
44
+ // Deprecated stubs to satisfy abstract class until full migration
45
+ async upload(_bucketName, _filePath, _data, _contentType) {
46
+ throw new Error("GCSStorageProvider.upload is deprecated. Use client-side direct upload via generateSignedUrl.");
47
+ }
48
+ async download(_bucketName, _filePath) {
49
+ throw new Error("GCSStorageProvider.download is deprecated. Use client-side fetch via generateSignedUrl.");
50
+ }
51
+ async delete(_bucketName, filePath) {
52
+ return this.deleteObject(filePath);
53
+ }
54
+ async getSignedUrl(_bucketName, filePath, expiresMs) {
55
+ return this.generateSignedUrl(filePath, { action: "read", expiresMs });
56
+ }
57
+ }
58
+ //# sourceMappingURL=GCSStorageProvider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GCSStorageProvider.js","sourceRoot":"","sources":["../../src/storage/GCSStorageProvider.ts"],"names":[],"mappings":"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"}
@@ -1,7 +1,35 @@
1
+ export interface UploadOptions {
2
+ tenant: string;
3
+ dataContext: string;
4
+ originalName: string;
5
+ contentType: string;
6
+ author: string;
7
+ }
8
+ export interface SignedUrlOptions {
9
+ action: "read" | "write";
10
+ contentType?: string;
11
+ expiresMs?: number;
12
+ }
13
+ export interface ObjectMetadata {
14
+ size: number;
15
+ contentType: string;
16
+ }
1
17
  export declare abstract class StorageProvider {
18
+ /** Generates a signed URL for reading or writing. */
19
+ abstract generateSignedUrl(key: string, opts: SignedUrlOptions): Promise<string>;
20
+ /** Retrieves object metadata (size, content-type) from storage. */
21
+ abstract getObjectMetadata(key: string): Promise<ObjectMetadata | null>;
22
+ /** Deletes an object from storage. */
23
+ abstract deleteObject(key: string): Promise<void>;
24
+ /** Builds a standardized object key: {tenant}/{dataContext}/{uuid}/{fileName} */
25
+ abstract buildObjectKey(opts: UploadOptions): string;
26
+ /** @deprecated Use generateSignedUrl for read or direct client-side upload */
2
27
  abstract upload(bucketName: string, filePath: string, data: Buffer, contentType?: string): Promise<string>;
28
+ /** @deprecated Use generateSignedUrl and fetch client-side */
3
29
  abstract download(bucketName: string, filePath: string): Promise<Buffer>;
30
+ /** @deprecated Use deleteObject */
4
31
  abstract delete(bucketName: string, filePath: string): Promise<void>;
32
+ /** @deprecated Use generateSignedUrl */
5
33
  abstract getSignedUrl(bucketName: string, filePath: string, expiresMs: number): Promise<string>;
6
34
  }
7
35
  //# sourceMappingURL=StorageProvider.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"StorageProvider.d.ts","sourceRoot":"","sources":["../../src/storage/StorageProvider.ts"],"names":[],"mappings":"AAAA,8BAAsB,eAAe;IACnC,QAAQ,CAAC,MAAM,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAC1G,QAAQ,CAAC,QAAQ,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IACxE,QAAQ,CAAC,MAAM,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IACpE,QAAQ,CAAC,YAAY,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;CAChG"}
1
+ {"version":3,"file":"StorageProvider.d.ts","sourceRoot":"","sources":["../../src/storage/StorageProvider.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAA;IACd,WAAW,EAAE,MAAM,CAAA;IACnB,YAAY,EAAE,MAAM,CAAA;IACpB,WAAW,EAAE,MAAM,CAAA;IACnB,MAAM,EAAE,MAAM,CAAA;CACf;AAED,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,GAAG,OAAO,CAAA;IACxB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,CAAA;CACpB;AAED,8BAAsB,eAAe;IACnC,qDAAqD;IACrD,QAAQ,CAAC,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAAC,MAAM,CAAC;IAEhF,mEAAmE;IACnE,QAAQ,CAAC,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC;IAEvE,sCAAsC;IACtC,QAAQ,CAAC,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAEjD,iFAAiF;IACjF,QAAQ,CAAC,cAAc,CAAC,IAAI,EAAE,aAAa,GAAG,MAAM;IAEpD,8EAA8E;IAC9E,QAAQ,CAAC,MAAM,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAC1G,8DAA8D;IAC9D,QAAQ,CAAC,QAAQ,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IACxE,mCAAmC;IACnC,QAAQ,CAAC,MAAM,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IACpE,wCAAwC;IACxC,QAAQ,CAAC,YAAY,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;CAChG"}
@@ -1 +1 @@
1
- {"version":3,"file":"StorageProvider.js","sourceRoot":"","sources":["../../src/storage/StorageProvider.ts"],"names":[],"mappings":"AAAA,MAAM,OAAgB,eAAe;CAKpC"}
1
+ {"version":3,"file":"StorageProvider.js","sourceRoot":"","sources":["../../src/storage/StorageProvider.ts"],"names":[],"mappings":"AAmBA,MAAM,OAAgB,eAAe;CAqBpC"}
@@ -1,2 +1,3 @@
1
- export { StorageProvider } from "./StorageProvider.js";
1
+ export { StorageProvider, type UploadOptions, type SignedUrlOptions, type ObjectMetadata } from "./StorageProvider.js";
2
+ export { GCSStorageProvider } from "./GCSStorageProvider.js";
2
3
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/storage/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/storage/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,KAAK,aAAa,EAAE,KAAK,gBAAgB,EAAE,KAAK,cAAc,EAAE,MAAM,sBAAsB,CAAA;AACtH,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA"}
@@ -1,2 +1,3 @@
1
1
  export { StorageProvider } from "./StorageProvider.js";
2
+ export { GCSStorageProvider } from "./GCSStorageProvider.js";
2
3
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/storage/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/storage/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAkE,MAAM,sBAAsB,CAAA;AACtH,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@onroad/core",
3
- "version": "4.0.0-alpha.29",
3
+ "version": "4.0.0-alpha.30",
4
4
  "description": "TypeScript backend framework — DI Container, Filter Chain, EventBus, Provider Pattern",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -148,6 +148,7 @@
148
148
  }
149
149
  },
150
150
  "devDependencies": {
151
+ "@google-cloud/storage": "^7.19.0",
151
152
  "@types/amqplib": "^0.10.0",
152
153
  "@types/express": "^5.0.0",
153
154
  "@types/node": "^22.0.0",