@opensaas/stack-rag 0.1.6 → 0.3.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 (95) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/CHANGELOG.md +141 -0
  3. package/README.md +82 -6
  4. package/dist/config/index.d.ts.map +1 -1
  5. package/dist/config/index.js +9 -0
  6. package/dist/config/index.js.map +1 -1
  7. package/dist/config/plugin.d.ts.map +1 -1
  8. package/dist/config/plugin.js +61 -1
  9. package/dist/config/plugin.js.map +1 -1
  10. package/dist/config/plugin.test.js +70 -14
  11. package/dist/config/plugin.test.js.map +1 -1
  12. package/dist/config/types.d.ts +186 -0
  13. package/dist/config/types.d.ts.map +1 -1
  14. package/dist/fields/index.d.ts +1 -0
  15. package/dist/fields/index.d.ts.map +1 -1
  16. package/dist/fields/index.js +1 -0
  17. package/dist/fields/index.js.map +1 -1
  18. package/dist/fields/searchable.d.ts +42 -0
  19. package/dist/fields/searchable.d.ts.map +1 -0
  20. package/dist/fields/searchable.js +51 -0
  21. package/dist/fields/searchable.js.map +1 -0
  22. package/dist/fields/searchable.test.d.ts +2 -0
  23. package/dist/fields/searchable.test.d.ts.map +1 -0
  24. package/dist/fields/searchable.test.js +112 -0
  25. package/dist/fields/searchable.test.js.map +1 -0
  26. package/dist/index.d.ts +2 -1
  27. package/dist/index.d.ts.map +1 -1
  28. package/dist/providers/openai.d.ts +2 -0
  29. package/dist/providers/openai.d.ts.map +1 -1
  30. package/dist/providers/openai.js +35 -20
  31. package/dist/providers/openai.js.map +1 -1
  32. package/dist/runtime/batch.test.js +1 -1
  33. package/dist/runtime/build-time.d.ts +100 -0
  34. package/dist/runtime/build-time.d.ts.map +1 -0
  35. package/dist/runtime/build-time.js +185 -0
  36. package/dist/runtime/build-time.js.map +1 -0
  37. package/dist/runtime/index.d.ts +3 -0
  38. package/dist/runtime/index.d.ts.map +1 -1
  39. package/dist/runtime/index.js +6 -0
  40. package/dist/runtime/index.js.map +1 -1
  41. package/dist/runtime/markdown.d.ts +33 -0
  42. package/dist/runtime/markdown.d.ts.map +1 -0
  43. package/dist/runtime/markdown.js +94 -0
  44. package/dist/runtime/markdown.js.map +1 -0
  45. package/dist/runtime/provider-helpers.d.ts +56 -0
  46. package/dist/runtime/provider-helpers.d.ts.map +1 -0
  47. package/dist/runtime/provider-helpers.js +95 -0
  48. package/dist/runtime/provider-helpers.js.map +1 -0
  49. package/dist/runtime/types.d.ts +29 -0
  50. package/dist/runtime/types.d.ts.map +1 -0
  51. package/dist/runtime/types.js +6 -0
  52. package/dist/runtime/types.js.map +1 -0
  53. package/dist/storage/access-filter.d.ts +30 -0
  54. package/dist/storage/access-filter.d.ts.map +1 -0
  55. package/dist/storage/access-filter.js +241 -0
  56. package/dist/storage/access-filter.js.map +1 -0
  57. package/dist/storage/index.d.ts +2 -0
  58. package/dist/storage/index.d.ts.map +1 -1
  59. package/dist/storage/index.js +3 -0
  60. package/dist/storage/index.js.map +1 -1
  61. package/dist/storage/json-file.d.ts +53 -0
  62. package/dist/storage/json-file.d.ts.map +1 -0
  63. package/dist/storage/json-file.js +124 -0
  64. package/dist/storage/json-file.js.map +1 -0
  65. package/dist/storage/pgvector.d.ts.map +1 -1
  66. package/dist/storage/pgvector.js +26 -11
  67. package/dist/storage/pgvector.js.map +1 -1
  68. package/dist/storage/storage.test.js +2 -0
  69. package/dist/storage/storage.test.js.map +1 -1
  70. package/dist/storage/types.d.ts +5 -0
  71. package/dist/storage/types.d.ts.map +1 -1
  72. package/dist/storage/types.js.map +1 -1
  73. package/package.json +6 -5
  74. package/src/config/index.ts +9 -0
  75. package/src/config/plugin.test.ts +70 -14
  76. package/src/config/plugin.ts +72 -2
  77. package/src/config/types.ts +217 -0
  78. package/src/fields/index.ts +2 -0
  79. package/src/fields/searchable.test.ts +136 -0
  80. package/src/fields/searchable.ts +57 -0
  81. package/src/index.ts +6 -0
  82. package/src/providers/openai.ts +37 -22
  83. package/src/runtime/batch.test.ts +1 -1
  84. package/src/runtime/build-time.ts +216 -0
  85. package/src/runtime/index.ts +18 -0
  86. package/src/runtime/markdown.ts +119 -0
  87. package/src/runtime/provider-helpers.ts +115 -0
  88. package/src/runtime/types.ts +30 -0
  89. package/src/storage/access-filter.ts +303 -0
  90. package/src/storage/index.ts +4 -0
  91. package/src/storage/json-file.ts +157 -0
  92. package/src/storage/pgvector.ts +31 -11
  93. package/src/storage/storage.test.ts +2 -0
  94. package/src/storage/types.ts +6 -0
  95. package/tsconfig.tsbuildinfo +1 -1
@@ -0,0 +1,95 @@
1
+ /**
2
+ * Helper utilities for working with embedding providers
3
+ * Simplifies provider creation from environment variables
4
+ */
5
+ import { createEmbeddingProvider } from '../providers/index.js';
6
+ import 'dotenv/config';
7
+ /**
8
+ * Create an embedding provider from environment variables
9
+ *
10
+ * Reads configuration from environment variables:
11
+ * - EMBEDDING_PROVIDER: 'openai' or 'ollama' (default: 'openai')
12
+ * - OPENAI_API_KEY: Required if using OpenAI
13
+ * - OLLAMA_BASE_URL: Ollama endpoint (default: 'http://localhost:11434')
14
+ *
15
+ * @param overrides - Optional overrides for environment config
16
+ * @returns Configured embedding provider
17
+ *
18
+ * @example
19
+ * ```typescript
20
+ * import { createProviderFromEnv } from '@opensaas/stack-rag/runtime'
21
+ *
22
+ * // Uses EMBEDDING_PROVIDER and OPENAI_API_KEY from env
23
+ * const provider = createProviderFromEnv()
24
+ *
25
+ * // Override provider type
26
+ * const ollamaProvider = createProviderFromEnv({ provider: 'ollama' })
27
+ * ```
28
+ */
29
+ export function createProviderFromEnv(overrides) {
30
+ const providerType = overrides?.provider || process.env.EMBEDDING_PROVIDER || 'openai';
31
+ let config;
32
+ if (providerType === 'openai') {
33
+ const apiKey = overrides?.openaiApiKey || process.env.OPENAI_API_KEY;
34
+ if (!apiKey) {
35
+ throw new Error('OPENAI_API_KEY environment variable is required when using OpenAI provider');
36
+ }
37
+ config = {
38
+ type: 'openai',
39
+ apiKey,
40
+ model: overrides?.model ||
41
+ 'text-embedding-3-small',
42
+ };
43
+ }
44
+ else if (providerType === 'ollama') {
45
+ config = {
46
+ type: 'ollama',
47
+ baseURL: overrides?.ollamaBaseUrl || process.env.OLLAMA_BASE_URL || 'http://localhost:11434',
48
+ model: overrides?.model || 'nomic-embed-text',
49
+ };
50
+ }
51
+ else {
52
+ throw new Error(`Unknown provider type: ${providerType}. Supported: openai, ollama`);
53
+ }
54
+ return createEmbeddingProvider(config);
55
+ }
56
+ /**
57
+ * Get provider configuration from environment
58
+ *
59
+ * Useful for inspecting what provider would be used without creating it.
60
+ *
61
+ * @returns Provider configuration object
62
+ *
63
+ * @example
64
+ * ```typescript
65
+ * import { getProviderConfigFromEnv } from '@opensaas/stack-rag/runtime'
66
+ *
67
+ * const config = getProviderConfigFromEnv()
68
+ * console.log(`Using ${config.type} provider`)
69
+ * ```
70
+ */
71
+ export function getProviderConfigFromEnv() {
72
+ const providerType = process.env.EMBEDDING_PROVIDER || 'openai';
73
+ if (providerType === 'openai') {
74
+ const apiKey = process.env.OPENAI_API_KEY;
75
+ if (!apiKey) {
76
+ throw new Error('OPENAI_API_KEY environment variable is required');
77
+ }
78
+ return {
79
+ type: 'openai',
80
+ apiKey,
81
+ model: 'text-embedding-3-small',
82
+ };
83
+ }
84
+ else if (providerType === 'ollama') {
85
+ return {
86
+ type: 'ollama',
87
+ baseURL: process.env.OLLAMA_BASE_URL || 'http://localhost:11434',
88
+ model: 'nomic-embed-text',
89
+ };
90
+ }
91
+ else {
92
+ throw new Error(`Unknown provider type: ${providerType}`);
93
+ }
94
+ }
95
+ //# sourceMappingURL=provider-helpers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider-helpers.js","sourceRoot":"","sources":["../../src/runtime/provider-helpers.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAA;AAG/D,OAAO,eAAe,CAAA;AAOtB;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,UAAU,qBAAqB,CAAC,SAKrC;IACC,MAAM,YAAY,GAChB,SAAS,EAAE,QAAQ,IAAK,OAAO,CAAC,GAAG,CAAC,kBAAmC,IAAI,QAAQ,CAAA;IAErF,IAAI,MAA+B,CAAA;IAEnC,IAAI,YAAY,KAAK,QAAQ,EAAE,CAAC;QAC9B,MAAM,MAAM,GAAG,SAAS,EAAE,YAAY,IAAI,OAAO,CAAC,GAAG,CAAC,cAAc,CAAA;QAEpE,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,IAAI,KAAK,CAAC,4EAA4E,CAAC,CAAA;QAC/F,CAAC;QAED,MAAM,GAAG;YACP,IAAI,EAAE,QAAQ;YACd,MAAM;YACN,KAAK,EACF,SAAS,EAAE,KAA6D;gBACzE,wBAAwB;SAC3B,CAAA;IACH,CAAC;SAAM,IAAI,YAAY,KAAK,QAAQ,EAAE,CAAC;QACrC,MAAM,GAAG;YACP,IAAI,EAAE,QAAQ;YACd,OAAO,EAAE,SAAS,EAAE,aAAa,IAAI,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,wBAAwB;YAC5F,KAAK,EAAE,SAAS,EAAE,KAAK,IAAI,kBAAkB;SAC9C,CAAA;IACH,CAAC;SAAM,CAAC;QACN,MAAM,IAAI,KAAK,CAAC,0BAA0B,YAAY,6BAA6B,CAAC,CAAA;IACtF,CAAC;IAED,OAAO,uBAAuB,CAAC,MAAM,CAAC,CAAA;AACxC,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,wBAAwB;IACtC,MAAM,YAAY,GAAI,OAAO,CAAC,GAAG,CAAC,kBAAmC,IAAI,QAAQ,CAAA;IAEjF,IAAI,YAAY,KAAK,QAAQ,EAAE,CAAC;QAC9B,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,CAAA;QAEzC,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAAA;QACpE,CAAC;QAED,OAAO;YACL,IAAI,EAAE,QAAQ;YACd,MAAM;YACN,KAAK,EAAE,wBAAwB;SAChC,CAAA;IACH,CAAC;SAAM,IAAI,YAAY,KAAK,QAAQ,EAAE,CAAC;QACrC,OAAO;YACL,IAAI,EAAE,QAAQ;YACd,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,wBAAwB;YAChE,KAAK,EAAE,kBAAkB;SAC1B,CAAA;IACH,CAAC;SAAM,CAAC;QACN,MAAM,IAAI,KAAK,CAAC,0BAA0B,YAAY,EAAE,CAAC,CAAA;IAC3D,CAAC;AACH,CAAC"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Type definitions for RAG plugin runtime services
3
+ * These types are used for type-safe access to context.plugins.rag
4
+ */
5
+ /**
6
+ * Runtime services provided by the RAG plugin
7
+ * Available via context.plugins.rag
8
+ */
9
+ export interface RAGRuntimeServices {
10
+ /**
11
+ * Generate embedding for a given text
12
+ * Uses the configured embedding provider
13
+ *
14
+ * @param text - The text to generate an embedding for
15
+ * @param providerName - Optional provider name if multiple providers are configured
16
+ * @returns Vector embedding as array of numbers
17
+ */
18
+ generateEmbedding: (text: string, providerName?: string) => Promise<number[]>;
19
+ /**
20
+ * Generate embeddings for multiple texts (batch)
21
+ * More efficient than calling generateEmbedding multiple times
22
+ *
23
+ * @param texts - Array of texts to generate embeddings for
24
+ * @param providerName - Optional provider name if multiple providers are configured
25
+ * @returns Array of vector embeddings
26
+ */
27
+ generateEmbeddings: (texts: string[], providerName?: string) => Promise<number[][]>;
28
+ }
29
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/runtime/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;GAGG;AACH,MAAM,WAAW,kBAAkB;IACjC;;;;;;;OAOG;IACH,iBAAiB,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,EAAE,CAAC,CAAA;IAE7E;;;;;;;OAOG;IACH,kBAAkB,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,YAAY,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAA;CACpF"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Type definitions for RAG plugin runtime services
3
+ * These types are used for type-safe access to context.plugins.rag
4
+ */
5
+ export {};
6
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/runtime/types.ts"],"names":[],"mappings":"AAAA;;;GAGG"}
@@ -0,0 +1,30 @@
1
+ import type { AccessContext, PrismaFilter } from '@opensaas/stack-core';
2
+ import type { OpenSaasConfig } from '@opensaas/stack-core';
3
+ /**
4
+ * Build access control filter for a given list and context
5
+ * Extracts the filter that would be applied by the access control engine
6
+ *
7
+ * @param listKey - The list name (e.g., 'Post', 'Article')
8
+ * @param context - The access context with session
9
+ * @param config - The OpenSaas configuration
10
+ * @returns Prisma filter object or null if access is denied
11
+ */
12
+ export declare function buildAccessControlFilter(listKey: string, context: AccessContext, config: OpenSaasConfig): Promise<PrismaFilter | null>;
13
+ /**
14
+ * Merge access control filter with user-provided where clause
15
+ *
16
+ * @param accessFilter - Filter from access control
17
+ * @param userWhere - User-provided where clause
18
+ * @returns Combined filter or null if access is denied
19
+ */
20
+ export declare function mergeAccessFilter(accessFilter: PrismaFilter | null, userWhere?: Record<string, unknown>): PrismaFilter | null;
21
+ /**
22
+ * Convert a Prisma filter object to SQL WHERE clause
23
+ * Handles common Prisma filter operators
24
+ *
25
+ * @param filter - Prisma filter object
26
+ * @param tableName - Table name for column references
27
+ * @returns SQL WHERE clause string (without "WHERE" keyword)
28
+ */
29
+ export declare function prismaFilterToSQL(filter: PrismaFilter, tableName?: string): string;
30
+ //# sourceMappingURL=access-filter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"access-filter.d.ts","sourceRoot":"","sources":["../../src/storage/access-filter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAiB,MAAM,sBAAsB,CAAA;AACtF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AAoD1D;;;;;;;;GAQG;AACH,wBAAsB,wBAAwB,CAC5C,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,aAAa,EACtB,MAAM,EAAE,cAAc,GACrB,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAiC9B;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC/B,YAAY,EAAE,YAAY,GAAG,IAAI,EACjC,SAAS,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,GACtC,YAAY,GAAG,IAAI,CAMrB;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,YAAY,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAiJlF"}
@@ -0,0 +1,241 @@
1
+ /**
2
+ * Execute an access control function (copied from @opensaas/stack-core/access)
3
+ */
4
+ async function checkAccess(accessControl, args) {
5
+ // No access control means deny by default
6
+ if (!accessControl) {
7
+ return false;
8
+ }
9
+ // Execute the access control function
10
+ const result = await accessControl(args);
11
+ return result;
12
+ }
13
+ /**
14
+ * Merge user filter with access control filter (copied from @opensaas/stack-core/access)
15
+ */
16
+ function mergeFilters(userFilter, accessFilter) {
17
+ // If access is denied, return null
18
+ if (accessFilter === false) {
19
+ return null;
20
+ }
21
+ // If access is fully granted, use user filter
22
+ if (accessFilter === true) {
23
+ return userFilter || {};
24
+ }
25
+ // Merge access filter with user filter
26
+ if (!userFilter) {
27
+ return accessFilter;
28
+ }
29
+ // Combine filters with AND
30
+ return {
31
+ AND: [accessFilter, userFilter],
32
+ };
33
+ }
34
+ /**
35
+ * Build access control filter for a given list and context
36
+ * Extracts the filter that would be applied by the access control engine
37
+ *
38
+ * @param listKey - The list name (e.g., 'Post', 'Article')
39
+ * @param context - The access context with session
40
+ * @param config - The OpenSaas configuration
41
+ * @returns Prisma filter object or null if access is denied
42
+ */
43
+ export async function buildAccessControlFilter(listKey, context, config) {
44
+ const listConfig = config.lists[listKey];
45
+ if (!listConfig) {
46
+ throw new Error(`List '${listKey}' not found in config`);
47
+ }
48
+ // Check query access control
49
+ const queryAccess = listConfig.access?.operation?.query;
50
+ if (!queryAccess) {
51
+ // No access control means deny by default (following OpenSaaS Stack pattern)
52
+ return null;
53
+ }
54
+ // Execute access control function
55
+ const accessResult = await checkAccess(queryAccess, {
56
+ session: context.session,
57
+ context,
58
+ });
59
+ // If access is denied (false), return null
60
+ if (accessResult === false) {
61
+ return null;
62
+ }
63
+ // If access is fully granted (true), return empty filter
64
+ if (accessResult === true) {
65
+ return {};
66
+ }
67
+ // Otherwise, return the filter object
68
+ return accessResult;
69
+ }
70
+ /**
71
+ * Merge access control filter with user-provided where clause
72
+ *
73
+ * @param accessFilter - Filter from access control
74
+ * @param userWhere - User-provided where clause
75
+ * @returns Combined filter or null if access is denied
76
+ */
77
+ export function mergeAccessFilter(accessFilter, userWhere = {}) {
78
+ if (accessFilter === null) {
79
+ return null;
80
+ }
81
+ return mergeFilters(userWhere, accessFilter);
82
+ }
83
+ /**
84
+ * Convert a Prisma filter object to SQL WHERE clause
85
+ * Handles common Prisma filter operators
86
+ *
87
+ * @param filter - Prisma filter object
88
+ * @param tableName - Table name for column references
89
+ * @returns SQL WHERE clause string (without "WHERE" keyword)
90
+ */
91
+ export function prismaFilterToSQL(filter, tableName) {
92
+ if (!filter || Object.keys(filter).length === 0) {
93
+ return 'TRUE'; // No filter means all records
94
+ }
95
+ const conditions = [];
96
+ for (const [key, value] of Object.entries(filter)) {
97
+ // Handle logical operators
98
+ if (key === 'AND') {
99
+ if (!Array.isArray(value))
100
+ continue;
101
+ const andConditions = value
102
+ .map((subFilter) => prismaFilterToSQL(subFilter, tableName))
103
+ .filter((c) => c !== 'TRUE');
104
+ if (andConditions.length > 0) {
105
+ conditions.push(`(${andConditions.join(' AND ')})`);
106
+ }
107
+ continue;
108
+ }
109
+ if (key === 'OR') {
110
+ if (!Array.isArray(value))
111
+ continue;
112
+ const orConditions = value
113
+ .map((subFilter) => prismaFilterToSQL(subFilter, tableName))
114
+ .filter((c) => c !== 'TRUE');
115
+ if (orConditions.length > 0) {
116
+ conditions.push(`(${orConditions.join(' OR ')})`);
117
+ }
118
+ continue;
119
+ }
120
+ if (key === 'NOT') {
121
+ const notCondition = prismaFilterToSQL(value, tableName);
122
+ if (notCondition !== 'TRUE') {
123
+ conditions.push(`NOT (${notCondition})`);
124
+ }
125
+ continue;
126
+ }
127
+ // Handle field conditions
128
+ const columnName = tableName ? `"${tableName}"."${key}"` : `"${key}"`;
129
+ if (value === null) {
130
+ conditions.push(`${columnName} IS NULL`);
131
+ continue;
132
+ }
133
+ if (typeof value !== 'object' || value === null) {
134
+ // Direct equality
135
+ const escapedValue = escapeSQLValue(value);
136
+ conditions.push(`${columnName} = ${escapedValue}`);
137
+ continue;
138
+ }
139
+ // Handle nested field conditions
140
+ const fieldConditions = [];
141
+ for (const [operator, operatorValue] of Object.entries(value)) {
142
+ switch (operator) {
143
+ case 'equals':
144
+ if (operatorValue === null) {
145
+ fieldConditions.push(`${columnName} IS NULL`);
146
+ }
147
+ else {
148
+ fieldConditions.push(`${columnName} = ${escapeSQLValue(operatorValue)}`);
149
+ }
150
+ break;
151
+ case 'not':
152
+ if (operatorValue === null) {
153
+ fieldConditions.push(`${columnName} IS NOT NULL`);
154
+ }
155
+ else {
156
+ fieldConditions.push(`${columnName} != ${escapeSQLValue(operatorValue)}`);
157
+ }
158
+ break;
159
+ case 'in':
160
+ if (Array.isArray(operatorValue) && operatorValue.length > 0) {
161
+ const values = operatorValue.map((v) => escapeSQLValue(v)).join(', ');
162
+ fieldConditions.push(`${columnName} IN (${values})`);
163
+ }
164
+ break;
165
+ case 'notIn':
166
+ if (Array.isArray(operatorValue) && operatorValue.length > 0) {
167
+ const values = operatorValue.map((v) => escapeSQLValue(v)).join(', ');
168
+ fieldConditions.push(`${columnName} NOT IN (${values})`);
169
+ }
170
+ break;
171
+ case 'lt':
172
+ fieldConditions.push(`${columnName} < ${escapeSQLValue(operatorValue)}`);
173
+ break;
174
+ case 'lte':
175
+ fieldConditions.push(`${columnName} <= ${escapeSQLValue(operatorValue)}`);
176
+ break;
177
+ case 'gt':
178
+ fieldConditions.push(`${columnName} > ${escapeSQLValue(operatorValue)}`);
179
+ break;
180
+ case 'gte':
181
+ fieldConditions.push(`${columnName} >= ${escapeSQLValue(operatorValue)}`);
182
+ break;
183
+ case 'contains':
184
+ fieldConditions.push(`${columnName} LIKE ${escapeSQLValue(`%${operatorValue}%`)}`);
185
+ break;
186
+ case 'startsWith':
187
+ fieldConditions.push(`${columnName} LIKE ${escapeSQLValue(`${operatorValue}%`)}`);
188
+ break;
189
+ case 'endsWith':
190
+ fieldConditions.push(`${columnName} LIKE ${escapeSQLValue(`%${operatorValue}`)}`);
191
+ break;
192
+ case 'isNull':
193
+ if (operatorValue === true) {
194
+ fieldConditions.push(`${columnName} IS NULL`);
195
+ }
196
+ else {
197
+ fieldConditions.push(`${columnName} IS NOT NULL`);
198
+ }
199
+ break;
200
+ // Add more operators as needed
201
+ default:
202
+ console.warn(`Unsupported Prisma filter operator: ${operator}`);
203
+ }
204
+ }
205
+ if (fieldConditions.length > 0) {
206
+ conditions.push(fieldConditions.join(' AND '));
207
+ }
208
+ }
209
+ if (conditions.length === 0) {
210
+ return 'TRUE';
211
+ }
212
+ if (conditions.length === 1) {
213
+ return conditions[0];
214
+ }
215
+ return conditions.join(' AND ');
216
+ }
217
+ /**
218
+ * Escape SQL values to prevent SQL injection
219
+ * Basic escaping - in production, use parameterized queries
220
+ */
221
+ function escapeSQLValue(value) {
222
+ if (value === null) {
223
+ return 'NULL';
224
+ }
225
+ if (typeof value === 'string') {
226
+ // Escape single quotes by doubling them
227
+ return `'${value.replace(/'/g, "''")}'`;
228
+ }
229
+ if (typeof value === 'number') {
230
+ return value.toString();
231
+ }
232
+ if (typeof value === 'boolean') {
233
+ return value ? 'TRUE' : 'FALSE';
234
+ }
235
+ if (value instanceof Date) {
236
+ return `'${value.toISOString()}'`;
237
+ }
238
+ // Fallback for other types
239
+ return `'${String(value).replace(/'/g, "''")}'`;
240
+ }
241
+ //# sourceMappingURL=access-filter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"access-filter.js","sourceRoot":"","sources":["../../src/storage/access-filter.ts"],"names":[],"mappings":"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"}
@@ -36,6 +36,8 @@ export declare function registerVectorStorage(type: string, factory: (config: Ve
36
36
  export declare function createVectorStorage(config: VectorStorageConfig): VectorStorage;
37
37
  export * from './types.js';
38
38
  export { JsonVectorStorage, createJsonStorage } from './json.js';
39
+ export { JsonFileStorage, createJsonFileStorage } from './json-file.js';
39
40
  export { PgVectorStorage, createPgVectorStorage } from './pgvector.js';
40
41
  export { SqliteVssStorage, createSqliteVssStorage } from './sqlite-vss.js';
42
+ export { buildAccessControlFilter, mergeAccessFilter, prismaFilterToSQL } from './access-filter.js';
41
43
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/storage/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAC/C,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAA;AA4B7D;;;;;;;;;;;;GAYG;AACH,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,CAAC,MAAM,EAAE,mBAAmB,KAAK,aAAa,GACtD,IAAI,CAEN;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,mBAAmB,GAAG,aAAa,CAW9E;AAGD,cAAc,YAAY,CAAA;AAC1B,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAA;AAChE,OAAO,EAAE,eAAe,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAA;AACtE,OAAO,EAAE,gBAAgB,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/storage/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAC/C,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAA;AA4B7D;;;;;;;;;;;;GAYG;AACH,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,CAAC,MAAM,EAAE,mBAAmB,KAAK,aAAa,GACtD,IAAI,CAEN;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,mBAAmB,GAAG,aAAa,CAW9E;AAGD,cAAc,YAAY,CAAA;AAC1B,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAA;AAChE,OAAO,EAAE,eAAe,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAA;AACvE,OAAO,EAAE,eAAe,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAA;AACtE,OAAO,EAAE,gBAAgB,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAA;AAG1E,OAAO,EAAE,wBAAwB,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAA"}
@@ -68,6 +68,9 @@ export function createVectorStorage(config) {
68
68
  // Export types and individual storage backends
69
69
  export * from './types.js';
70
70
  export { JsonVectorStorage, createJsonStorage } from './json.js';
71
+ export { JsonFileStorage, createJsonFileStorage } from './json-file.js';
71
72
  export { PgVectorStorage, createPgVectorStorage } from './pgvector.js';
72
73
  export { SqliteVssStorage, createSqliteVssStorage } from './sqlite-vss.js';
74
+ // Export access control utilities
75
+ export { buildAccessControlFilter, mergeAccessFilter, prismaFilterToSQL } from './access-filter.js';
73
76
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/storage/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAA;AAC7C,OAAO,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAA;AACrD,OAAO,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAA;AAExD;;;GAGG;AACH,MAAM,gBAAgB,GAAG,IAAI,GAAG,EAA0D,CAAA;AAE1F;;GAEG;AACH,gBAAgB,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,iBAAiB,EAAE,CAAC,CAAA;AACvD,gBAAgB,CAAC,GAAG,CAAC,UAAU,EAAE,CAAC,MAAM,EAAE,EAAE;IAC1C,IAAI,MAAM,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;QAC/B,MAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAA;IAC7D,CAAC;IACD,OAAO,qBAAqB,CAAC,MAA4D,CAAC,CAAA;AAC5F,CAAC,CAAC,CAAA;AACF,gBAAgB,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC,MAAM,EAAE,EAAE;IAC5C,IAAI,MAAM,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;QACjC,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAA;IAC/D,CAAC;IACD,OAAO,sBAAsB,CAAC,MAA6D,CAAC,CAAA;AAC9F,CAAC,CAAC,CAAA;AAEF;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,qBAAqB,CACnC,IAAY,EACZ,OAAuD;IAEvD,gBAAgB,CAAC,GAAG,CAAC,IAAI,EAAE,OAAO,CAAC,CAAA;AACrC,CAAC;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,UAAU,mBAAmB,CAAC,MAA2B;IAC7D,MAAM,OAAO,GAAG,gBAAgB,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;IAEjD,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CACb,gCAAgC,MAAM,CAAC,IAAI,IAAI;YAC7C,uBAAuB,KAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAC1E,CAAA;IACH,CAAC;IAED,OAAO,OAAO,CAAC,MAAM,CAAC,CAAA;AACxB,CAAC;AAED,+CAA+C;AAC/C,cAAc,YAAY,CAAA;AAC1B,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAA;AAChE,OAAO,EAAE,eAAe,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAA;AACtE,OAAO,EAAE,gBAAgB,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/storage/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAA;AAC7C,OAAO,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAA;AACrD,OAAO,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAA;AAExD;;;GAGG;AACH,MAAM,gBAAgB,GAAG,IAAI,GAAG,EAA0D,CAAA;AAE1F;;GAEG;AACH,gBAAgB,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,iBAAiB,EAAE,CAAC,CAAA;AACvD,gBAAgB,CAAC,GAAG,CAAC,UAAU,EAAE,CAAC,MAAM,EAAE,EAAE;IAC1C,IAAI,MAAM,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;QAC/B,MAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAA;IAC7D,CAAC;IACD,OAAO,qBAAqB,CAAC,MAA4D,CAAC,CAAA;AAC5F,CAAC,CAAC,CAAA;AACF,gBAAgB,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC,MAAM,EAAE,EAAE;IAC5C,IAAI,MAAM,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;QACjC,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAA;IAC/D,CAAC;IACD,OAAO,sBAAsB,CAAC,MAA6D,CAAC,CAAA;AAC9F,CAAC,CAAC,CAAA;AAEF;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,qBAAqB,CACnC,IAAY,EACZ,OAAuD;IAEvD,gBAAgB,CAAC,GAAG,CAAC,IAAI,EAAE,OAAO,CAAC,CAAA;AACrC,CAAC;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,UAAU,mBAAmB,CAAC,MAA2B;IAC7D,MAAM,OAAO,GAAG,gBAAgB,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;IAEjD,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CACb,gCAAgC,MAAM,CAAC,IAAI,IAAI;YAC7C,uBAAuB,KAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAC1E,CAAA;IACH,CAAC;IAED,OAAO,OAAO,CAAC,MAAM,CAAC,CAAA;AACxB,CAAC;AAED,+CAA+C;AAC/C,cAAc,YAAY,CAAA;AAC1B,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAA;AAChE,OAAO,EAAE,eAAe,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAA;AACvE,OAAO,EAAE,eAAe,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAA;AACtE,OAAO,EAAE,gBAAgB,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAA;AAE1E,kCAAkC;AAClC,OAAO,EAAE,wBAAwB,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAA"}
@@ -0,0 +1,53 @@
1
+ import type { VectorStorage, SearchOptions } from './types.js';
2
+ import type { SearchResult, EmbeddingsIndex } from '../config/types.js';
3
+ /**
4
+ * JSON file-based vector storage
5
+ * Loads embeddings from a JSON file generated at build time
6
+ * Performs similarity search in JavaScript without database queries
7
+ * Ideal for static sites, documentation, and build-time generated embeddings
8
+ */
9
+ export declare class JsonFileStorage implements VectorStorage {
10
+ readonly type = "json-file";
11
+ private index;
12
+ private filePath;
13
+ constructor(filePath: string);
14
+ /**
15
+ * Load embeddings index from file
16
+ * Caches the result in memory
17
+ */
18
+ private loadIndex;
19
+ /**
20
+ * Search for similar documents using JavaScript-based cosine similarity
21
+ * Note: listKey parameter is included for interface compatibility but not used
22
+ * since this storage is typically used for standalone content (e.g., docs)
23
+ */
24
+ search<T = unknown>(_listKey: string, _fieldName: string, queryVector: number[], options: SearchOptions): Promise<SearchResult<T>[]>;
25
+ /**
26
+ * Calculate cosine similarity between two vectors
27
+ */
28
+ cosineSimilarity(a: number[], b: number[]): number;
29
+ /**
30
+ * Get the loaded index for inspection
31
+ */
32
+ getIndex(): EmbeddingsIndex | null;
33
+ /**
34
+ * Force reload the index from disk
35
+ */
36
+ reloadIndex(): void;
37
+ }
38
+ /**
39
+ * Create a JSON file vector storage instance
40
+ *
41
+ * @example
42
+ * ```typescript
43
+ * import { createJsonFileStorage } from '@opensaas/stack-rag/storage'
44
+ *
45
+ * const storage = createJsonFileStorage('.embeddings/docs.json')
46
+ * const results = await storage.search('', '', queryVector, {
47
+ * limit: 10,
48
+ * minScore: 0.7
49
+ * })
50
+ * ```
51
+ */
52
+ export declare function createJsonFileStorage(filePath: string): JsonFileStorage;
53
+ //# sourceMappingURL=json-file.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"json-file.d.ts","sourceRoot":"","sources":["../../src/storage/json-file.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAC9D,OAAO,KAAK,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA;AAGvE;;;;;GAKG;AACH,qBAAa,eAAgB,YAAW,aAAa;IACnD,QAAQ,CAAC,IAAI,eAAc;IAE3B,OAAO,CAAC,KAAK,CAA+B;IAC5C,OAAO,CAAC,QAAQ,CAAQ;gBAEZ,QAAQ,EAAE,MAAM;IAI5B;;;OAGG;IACH,OAAO,CAAC,SAAS;IAoBjB;;;;OAIG;IACG,MAAM,CAAC,CAAC,GAAG,OAAO,EACtB,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,MAAM,EAAE,EACrB,OAAO,EAAE,aAAa,GACrB,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC;IA8D7B;;OAEG;IACH,gBAAgB,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,MAAM,EAAE,GAAG,MAAM;IAIlD;;OAEG;IACH,QAAQ,IAAI,eAAe,GAAG,IAAI;IAIlC;;OAEG;IACH,WAAW,IAAI,IAAI;CAIpB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,eAAe,CAEvE"}
@@ -0,0 +1,124 @@
1
+ import { readFileSync, existsSync } from 'node:fs';
2
+ import { cosineSimilarity as calculateCosineSimilarity } from './types.js';
3
+ /**
4
+ * JSON file-based vector storage
5
+ * Loads embeddings from a JSON file generated at build time
6
+ * Performs similarity search in JavaScript without database queries
7
+ * Ideal for static sites, documentation, and build-time generated embeddings
8
+ */
9
+ export class JsonFileStorage {
10
+ type = 'json-file';
11
+ index = null;
12
+ filePath;
13
+ constructor(filePath) {
14
+ this.filePath = filePath;
15
+ }
16
+ /**
17
+ * Load embeddings index from file
18
+ * Caches the result in memory
19
+ */
20
+ loadIndex() {
21
+ if (this.index) {
22
+ return this.index;
23
+ }
24
+ if (!existsSync(this.filePath)) {
25
+ throw new Error(`Embeddings file not found: ${this.filePath}. Run embeddings generation first.`);
26
+ }
27
+ try {
28
+ const content = readFileSync(this.filePath, 'utf-8');
29
+ this.index = JSON.parse(content);
30
+ return this.index;
31
+ }
32
+ catch (error) {
33
+ throw new Error(`Failed to load embeddings from ${this.filePath}: ${error}`);
34
+ }
35
+ }
36
+ /**
37
+ * Search for similar documents using JavaScript-based cosine similarity
38
+ * Note: listKey parameter is included for interface compatibility but not used
39
+ * since this storage is typically used for standalone content (e.g., docs)
40
+ */
41
+ async search(_listKey, _fieldName, queryVector, options) {
42
+ const { limit = 10, minScore = 0.0, where = {} } = options;
43
+ const index = this.loadIndex();
44
+ // Validate query vector dimensions against index config
45
+ if (queryVector.length !== index.config.dimensions) {
46
+ throw new Error(`Query vector dimensions (${queryVector.length}) don't match index dimensions (${index.config.dimensions})`);
47
+ }
48
+ const results = [];
49
+ // Search through all documents and chunks
50
+ for (const [documentId, document] of Object.entries(index.documents)) {
51
+ // Apply where filters if provided (simple equality check)
52
+ if (where && Object.keys(where).length > 0) {
53
+ let matches = true;
54
+ for (const [key, value] of Object.entries(where)) {
55
+ if (document[key] !== value) {
56
+ matches = false;
57
+ break;
58
+ }
59
+ }
60
+ if (!matches)
61
+ continue;
62
+ }
63
+ // Search through each chunk
64
+ for (const chunk of document.chunks) {
65
+ const score = this.cosineSimilarity(queryVector, chunk.embedding);
66
+ if (score >= minScore) {
67
+ results.push({
68
+ item: {
69
+ documentId,
70
+ title: document.title,
71
+ content: chunk.text,
72
+ chunkIndex: chunk.metadata.chunkIndex,
73
+ metadata: chunk.metadata,
74
+ },
75
+ score,
76
+ distance: 1 - score,
77
+ documentId,
78
+ chunkIndex: chunk.metadata.chunkIndex,
79
+ });
80
+ }
81
+ }
82
+ }
83
+ // Sort by score (descending) and limit results
84
+ results.sort((a, b) => b.score - a.score);
85
+ return results.slice(0, limit);
86
+ }
87
+ /**
88
+ * Calculate cosine similarity between two vectors
89
+ */
90
+ cosineSimilarity(a, b) {
91
+ return calculateCosineSimilarity(a, b);
92
+ }
93
+ /**
94
+ * Get the loaded index for inspection
95
+ */
96
+ getIndex() {
97
+ return this.index;
98
+ }
99
+ /**
100
+ * Force reload the index from disk
101
+ */
102
+ reloadIndex() {
103
+ this.index = null;
104
+ this.loadIndex();
105
+ }
106
+ }
107
+ /**
108
+ * Create a JSON file vector storage instance
109
+ *
110
+ * @example
111
+ * ```typescript
112
+ * import { createJsonFileStorage } from '@opensaas/stack-rag/storage'
113
+ *
114
+ * const storage = createJsonFileStorage('.embeddings/docs.json')
115
+ * const results = await storage.search('', '', queryVector, {
116
+ * limit: 10,
117
+ * minScore: 0.7
118
+ * })
119
+ * ```
120
+ */
121
+ export function createJsonFileStorage(filePath) {
122
+ return new JsonFileStorage(filePath);
123
+ }
124
+ //# sourceMappingURL=json-file.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"json-file.js","sourceRoot":"","sources":["../../src/storage/json-file.ts"],"names":[],"mappings":"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"}