@contedra/core 0.1.5 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,43 @@
1
+ import type { App } from "firebase-admin/app";
2
+ /**
3
+ * Parse an asset:// URI and return the asset path.
4
+ * Returns null if the URI is not a valid asset:// URI or contains unsafe paths.
5
+ */
6
+ export declare function parseAssetUri(uri: string): string | null;
7
+ /**
8
+ * Build a Firebase Storage public URL for a given asset path.
9
+ * Format: https://firebasestorage.googleapis.com/v0/b/{bucket}/o/{encodedPath}?alt=media
10
+ */
11
+ export declare function buildStorageUrl(assetPath: string, storageBucket: string): string;
12
+ /**
13
+ * Convert an asset:// URI to a Firebase Storage public URL.
14
+ * Returns the original URI if it cannot be parsed.
15
+ */
16
+ export declare function resolveAssetUriToUrl(uri: string, storageBucket: string): string;
17
+ /**
18
+ * Replace all asset:// URIs in a string using the provided replacer function.
19
+ */
20
+ export declare function replaceAssetUris(text: string, replacer: (uri: string) => string): string;
21
+ /**
22
+ * Walk all string values in a record and replace asset:// URIs.
23
+ * Returns a new record with replaced values.
24
+ */
25
+ export declare function replaceAssetUrisInRecord(data: Record<string, unknown>, replacer: (uri: string) => string): Record<string, unknown>;
26
+ /**
27
+ * Download a file from Firebase Storage to the local filesystem.
28
+ * Returns true if the file was downloaded, false if it already existed in cache.
29
+ */
30
+ export declare function downloadAsset(app: App, assetPath: string, cacheDir: string): Promise<boolean>;
31
+ /**
32
+ * Copy a cached asset to the output directory.
33
+ */
34
+ export declare function copyAssetToOutput(assetPath: string, cacheDir: string, outputDir: string): void;
35
+ /**
36
+ * Collect all unique asset:// URIs from a string.
37
+ */
38
+ export declare function collectAssetUris(text: string): string[];
39
+ /**
40
+ * Collect all unique asset:// URIs from a record's string values.
41
+ */
42
+ export declare function collectAssetUrisFromRecord(data: Record<string, unknown>): string[];
43
+ //# sourceMappingURL=assets.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assets.d.ts","sourceRoot":"","sources":["../src/assets.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,oBAAoB,CAAC;AA2C9C;;;GAGG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAcxD;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAC7B,SAAS,EAAE,MAAM,EACjB,aAAa,EAAE,MAAM,GACpB,MAAM,CAOR;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAClC,GAAG,EAAE,MAAM,EACX,aAAa,EAAE,MAAM,GACpB,MAAM,CAIR;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,GAChC,MAAM,CAER;AAED;;;GAGG;AACH,wBAAgB,wBAAwB,CACtC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,QAAQ,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,GAChC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAMzB;AAsBD;;;GAGG;AACH,wBAAsB,aAAa,CACjC,GAAG,EAAE,GAAG,EACR,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,OAAO,CAAC,CAwBlB;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,GAChB,IAAI,CAcN;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAGvD;AAED;;GAEG;AACH,wBAAgB,0BAA0B,CACxC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5B,MAAM,EAAE,CAMV"}
package/dist/assets.js ADDED
@@ -0,0 +1,193 @@
1
+ import { existsSync, mkdirSync, copyFileSync } from "node:fs";
2
+ import { writeFile } from "node:fs/promises";
3
+ import path from "node:path";
4
+ import { getStorage } from "firebase-admin/storage";
5
+ function isPlainObject(value) {
6
+ if (typeof value !== "object" || value === null)
7
+ return false;
8
+ const proto = Object.getPrototypeOf(value);
9
+ return proto === Object.prototype || proto === null;
10
+ }
11
+ // Match until common URI terminators while allowing encoded/object-name characters.
12
+ const ASSET_URI_PATTERN = /asset:\/\/[^\s"'<>()[\]{}]+/g;
13
+ /**
14
+ * Validate that an asset path is safe for filesystem use.
15
+ * Rejects traversal sequences, absolute paths, and null bytes.
16
+ * Returns the normalized path, or null if unsafe.
17
+ */
18
+ function sanitizeAssetPath(assetPath) {
19
+ if (!assetPath)
20
+ return null;
21
+ // Reject null bytes
22
+ if (assetPath.includes("\0"))
23
+ return null;
24
+ // Reject absolute paths (Unix and Windows)
25
+ if (assetPath.startsWith("/") || assetPath.startsWith("\\"))
26
+ return null;
27
+ if (/^[A-Za-z]:/.test(assetPath))
28
+ return null;
29
+ // Reject any path containing ".." segments (before and after normalization)
30
+ if (assetPath.split("/").includes(".."))
31
+ return null;
32
+ const normalized = path.posix.normalize(assetPath).replace(/^(\.\/)+/, "");
33
+ if (normalized === "" ||
34
+ normalized === ".." ||
35
+ normalized.startsWith("../") ||
36
+ normalized.includes("/../")) {
37
+ return null;
38
+ }
39
+ return normalized;
40
+ }
41
+ /**
42
+ * Parse an asset:// URI and return the asset path.
43
+ * Returns null if the URI is not a valid asset:// URI or contains unsafe paths.
44
+ */
45
+ export function parseAssetUri(uri) {
46
+ if (!uri.startsWith("asset://"))
47
+ return null;
48
+ const rawPath = uri.slice("asset://".length);
49
+ // Decode percent-encoded characters to get canonical filesystem path
50
+ let assetPath;
51
+ try {
52
+ assetPath = rawPath
53
+ .split("/")
54
+ .map((segment) => decodeURIComponent(segment))
55
+ .join("/");
56
+ }
57
+ catch {
58
+ return null;
59
+ }
60
+ return sanitizeAssetPath(assetPath);
61
+ }
62
+ /**
63
+ * Build a Firebase Storage public URL for a given asset path.
64
+ * Format: https://firebasestorage.googleapis.com/v0/b/{bucket}/o/{encodedPath}?alt=media
65
+ */
66
+ export function buildStorageUrl(assetPath, storageBucket) {
67
+ const storagePath = `assets/${assetPath}`;
68
+ const encodedPath = storagePath
69
+ .split("/")
70
+ .map((segment) => encodeURIComponent(segment))
71
+ .join("%2F");
72
+ return `https://firebasestorage.googleapis.com/v0/b/${storageBucket}/o/${encodedPath}?alt=media`;
73
+ }
74
+ /**
75
+ * Convert an asset:// URI to a Firebase Storage public URL.
76
+ * Returns the original URI if it cannot be parsed.
77
+ */
78
+ export function resolveAssetUriToUrl(uri, storageBucket) {
79
+ const assetPath = parseAssetUri(uri);
80
+ if (!assetPath)
81
+ return uri;
82
+ return buildStorageUrl(assetPath, storageBucket);
83
+ }
84
+ /**
85
+ * Replace all asset:// URIs in a string using the provided replacer function.
86
+ */
87
+ export function replaceAssetUris(text, replacer) {
88
+ return text.replace(ASSET_URI_PATTERN, (match) => replacer(match));
89
+ }
90
+ /**
91
+ * Walk all string values in a record and replace asset:// URIs.
92
+ * Returns a new record with replaced values.
93
+ */
94
+ export function replaceAssetUrisInRecord(data, replacer) {
95
+ const result = {};
96
+ for (const [key, value] of Object.entries(data)) {
97
+ result[key] = replaceValue(value, replacer);
98
+ }
99
+ return result;
100
+ }
101
+ function replaceValue(value, replacer) {
102
+ if (typeof value === "string") {
103
+ return replaceAssetUris(value, replacer);
104
+ }
105
+ if (Array.isArray(value)) {
106
+ return value.map((v) => replaceValue(v, replacer));
107
+ }
108
+ if (isPlainObject(value)) {
109
+ const result = {};
110
+ for (const [k, v] of Object.entries(value)) {
111
+ result[k] = replaceValue(v, replacer);
112
+ }
113
+ return result;
114
+ }
115
+ return value;
116
+ }
117
+ /**
118
+ * Download a file from Firebase Storage to the local filesystem.
119
+ * Returns true if the file was downloaded, false if it already existed in cache.
120
+ */
121
+ export async function downloadAsset(app, assetPath, cacheDir) {
122
+ const safePath = sanitizeAssetPath(assetPath);
123
+ if (!safePath)
124
+ throw new Error(`Invalid asset path: ${assetPath}`);
125
+ const resolvedCache = path.resolve(cacheDir);
126
+ const cachePath = path.resolve(cacheDir, safePath);
127
+ if (!cachePath.startsWith(resolvedCache + path.sep)) {
128
+ throw new Error(`Asset path escapes cache directory: ${assetPath}`);
129
+ }
130
+ if (existsSync(cachePath)) {
131
+ return false;
132
+ }
133
+ const dir = path.dirname(cachePath);
134
+ mkdirSync(dir, { recursive: true });
135
+ const storagePath = `assets/${safePath}`;
136
+ const bucket = getStorage(app).bucket();
137
+ const file = bucket.file(storagePath);
138
+ const [contents] = await file.download();
139
+ await writeFile(cachePath, contents);
140
+ return true;
141
+ }
142
+ /**
143
+ * Copy a cached asset to the output directory.
144
+ */
145
+ export function copyAssetToOutput(assetPath, cacheDir, outputDir) {
146
+ const safePath = sanitizeAssetPath(assetPath);
147
+ if (!safePath)
148
+ throw new Error(`Invalid asset path: ${assetPath}`);
149
+ const resolvedOutput = path.resolve(outputDir);
150
+ const dest = path.resolve(outputDir, safePath);
151
+ if (!dest.startsWith(resolvedOutput + path.sep)) {
152
+ throw new Error(`Asset path escapes output directory: ${assetPath}`);
153
+ }
154
+ const src = path.resolve(cacheDir, safePath);
155
+ const dir = path.dirname(dest);
156
+ mkdirSync(dir, { recursive: true });
157
+ copyFileSync(src, dest);
158
+ }
159
+ /**
160
+ * Collect all unique asset:// URIs from a string.
161
+ */
162
+ export function collectAssetUris(text) {
163
+ const matches = text.match(ASSET_URI_PATTERN);
164
+ return matches ? [...new Set(matches)] : [];
165
+ }
166
+ /**
167
+ * Collect all unique asset:// URIs from a record's string values.
168
+ */
169
+ export function collectAssetUrisFromRecord(data) {
170
+ const uris = new Set();
171
+ for (const value of Object.values(data)) {
172
+ collectFromValue(value, uris);
173
+ }
174
+ return [...uris];
175
+ }
176
+ function collectFromValue(value, uris) {
177
+ if (typeof value === "string") {
178
+ for (const uri of collectAssetUris(value)) {
179
+ uris.add(uri);
180
+ }
181
+ }
182
+ else if (Array.isArray(value)) {
183
+ for (const v of value) {
184
+ collectFromValue(v, uris);
185
+ }
186
+ }
187
+ else if (isPlainObject(value)) {
188
+ for (const v of Object.values(value)) {
189
+ collectFromValue(v, uris);
190
+ }
191
+ }
192
+ }
193
+ //# sourceMappingURL=assets.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assets.js","sourceRoot":"","sources":["../src/assets.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,6 @@
1
+ import { type App } from "firebase-admin/app";
1
2
  import type { FirebaseConfig, ModelDefinition } from "./types.js";
3
+ export declare function initFirebase(config: FirebaseConfig): App;
2
4
  export declare function initFirestore(config: FirebaseConfig): FirebaseFirestore.Firestore;
3
5
  export declare function fetchDocuments(firestore: FirebaseFirestore.Firestore, collectionName: string): Promise<Array<{
4
6
  id: string;
@@ -1 +1 @@
1
- {"version":3,"file":"firestore.d.ts","sourceRoot":"","sources":["../src/firestore.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElE,wBAAgB,aAAa,CAAC,MAAM,EAAE,cAAc,+BAkBnD;AAED,wBAAsB,cAAc,CAClC,SAAS,EAAE,iBAAiB,CAAC,SAAS,EACtC,cAAc,EAAE,MAAM,GACrB,OAAO,CAAC,KAAK,CAAC;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,CAAC,CAAC,CAM/D;AAED,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,KAAK,EAAE,eAAe,EACtB,SAAS,CAAC,EAAE,MAAM,GACjB;IAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,CAgBlD"}
1
+ {"version":3,"file":"firestore.d.ts","sourceRoot":"","sources":["../src/firestore.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgC,KAAK,GAAG,EAAE,MAAM,oBAAoB,CAAC;AAE5E,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElE,wBAAgB,YAAY,CAAC,MAAM,EAAE,cAAc,GAAG,GAAG,CAiBxD;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,cAAc,+BAGnD;AAED,wBAAsB,cAAc,CAClC,SAAS,EAAE,iBAAiB,CAAC,SAAS,EACtC,cAAc,EAAE,MAAM,GACrB,OAAO,CAAC,KAAK,CAAC;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,CAAC,CAAC,CAM/D;AAED,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,KAAK,EAAE,eAAe,EACtB,SAAS,CAAC,EAAE,MAAM,GACjB;IAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,CAgBlD"}
package/dist/firestore.js CHANGED
@@ -1,16 +1,19 @@
1
1
  import { cert, getApps, initializeApp } from "firebase-admin/app";
2
2
  import { getFirestore, Timestamp } from "firebase-admin/firestore";
3
- export function initFirestore(config) {
3
+ export function initFirebase(config) {
4
4
  const appName = `contedra-${config.projectId}`;
5
5
  const existingApp = getApps().find((app) => app.name === appName);
6
- const app = existingApp ??
6
+ return (existingApp ??
7
7
  initializeApp({
8
8
  projectId: config.projectId,
9
9
  ...(config.credential ? { credential: cert(config.credential) } : {}),
10
10
  ...(config.storageBucket
11
11
  ? { storageBucket: config.storageBucket }
12
12
  : {}),
13
- }, appName);
13
+ }, appName));
14
+ }
15
+ export function initFirestore(config) {
16
+ const app = initFirebase(config);
14
17
  return getFirestore(app);
15
18
  }
16
19
  export async function fetchDocuments(firestore, collectionName) {
@@ -1 +1 @@
1
- {"version":3,"file":"firestore.js","sourceRoot":"","sources":["../src/firestore.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"firestore.js","sourceRoot":"","sources":["../src/firestore.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  export { loadModel, detectBodyField } from "./model.js";
2
2
  export { buildSchema, dataTypeToZod } from "./schema.js";
3
- export { initFirestore, fetchDocuments, transformDocumentData } from "./firestore.js";
3
+ export { initFirebase, initFirestore, fetchDocuments, transformDocumentData } from "./firestore.js";
4
+ export { parseAssetUri, buildStorageUrl, resolveAssetUriToUrl, replaceAssetUris, replaceAssetUrisInRecord, downloadAsset, copyAssetToOutput, collectAssetUris, collectAssetUrisFromRecord, } from "./assets.js";
4
5
  export type { ModelDefinition, ModelProperty, FirebaseConfig } from "./types.js";
5
6
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AACxD,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACzD,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AACtF,YAAY,EAAE,eAAe,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AACxD,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACzD,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,cAAc,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AACpG,OAAO,EACL,aAAa,EACb,eAAe,EACf,oBAAoB,EACpB,gBAAgB,EAChB,wBAAwB,EACxB,aAAa,EACb,iBAAiB,EACjB,gBAAgB,EAChB,0BAA0B,GAC3B,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,eAAe,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC"}
package/dist/index.js CHANGED
@@ -1,4 +1,5 @@
1
1
  export { loadModel, detectBodyField } from "./model.js";
2
2
  export { buildSchema, dataTypeToZod } from "./schema.js";
3
- export { initFirestore, fetchDocuments, transformDocumentData } from "./firestore.js";
3
+ export { initFirebase, initFirestore, fetchDocuments, transformDocumentData } from "./firestore.js";
4
+ export { parseAssetUri, buildStorageUrl, resolveAssetUriToUrl, replaceAssetUris, replaceAssetUrisInRecord, downloadAsset, copyAssetToOutput, collectAssetUris, collectAssetUrisFromRecord, } from "./assets.js";
4
5
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AACxD,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACzD,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AACxD,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACzD,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,cAAc,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AACpG,OAAO,EACL,aAAa,EACb,eAAe,EACf,oBAAoB,EACpB,gBAAgB,EAChB,wBAAwB,EACxB,aAAa,EACb,iBAAiB,EACjB,gBAAgB,EAChB,0BAA0B,GAC3B,MAAM,aAAa,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contedra/core",
3
- "version": "0.1.5",
3
+ "version": "0.2.1",
4
4
  "description": "Core library for Contedra toolkit — Firebase connection, model parsing, and schema generation",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -37,7 +37,7 @@
37
37
  },
38
38
  "scripts": {
39
39
  "build": "tsc",
40
- "test": "vitest run",
40
+ "test": "firebase emulators:exec --only storage --project test \"vitest run\"",
41
41
  "lint": "oxlint src"
42
42
  }
43
43
  }