Change googleDriveAdapterHelper.js to use return statement

Reverted from object literal to function with return statement

Rationale:
- User requested explicit 'return' statement for clarity
- Function wrapper with 'return' is more conventional and readable
- Makes it clear the code returns an object when executed
- Matches common module pattern expectations

Structure:
```javascript
(function() {
  // Define all classes and functions
  class DocumentCountExceededError extends Error {...}
  function generateRequestId() {...}
  // ... all other functions

  // Return object with all exports
  return {
    DocumentCountExceededError,
    generateRequestId,
    // ... all other functions
  };
})();
```

Changes:
- Wrapped entire file in IIFE: (function() { ... })()
- Changed final expression from ({ ... }) to return { ... };
- Re-added 2-space indentation for content inside function
- Updated header comment: 'Returns' → 'Function that returns'

Benefits:
 Explicit return statement (clearer intent)
 Standard IIFE module pattern
 More conventional JavaScript style
 Easier to understand for new developers
 Same functionality as before

Testing:
✓ Syntax validated
✓ Server starts successfully
✓ Module loads: 'Loaded global functions: googleDriveAdapterHelper'
✓ All function calls work correctly
✓ Request handling functional

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
2026-03-07 12:14:45 -06:00
parent c094d4d472
commit 07968927fc

View File

@@ -6,7 +6,7 @@
* *
* ARCHITECTURE: * ARCHITECTURE:
* - Loaded by server.js using vm.Script (same as proxy.js) * - Loaded by server.js using vm.Script (same as proxy.js)
* - Returns a single object containing all helper functions * - Function that returns a single object containing all helper functions
* - Injected into globalVariableContext for access by proxy.js * - Injected into globalVariableContext for access by proxy.js
* - NO IMPORTS - All dependencies provided via VM context * - NO IMPORTS - All dependencies provided via VM context
* *
@@ -17,41 +17,42 @@
* @returns {Object} Helpers object with all utility functions * @returns {Object} Helpers object with all utility functions
*/ */
/** (function() {
/**
* Custom error for document count exceeding limit * Custom error for document count exceeding limit
*/ */
class DocumentCountExceededError extends Error { class DocumentCountExceededError extends Error {
constructor(count, limit) { constructor(count, limit) {
super(`Document count ${count} exceeds limit of ${limit}`); super(`Document count ${count} exceeds limit of ${limit}`);
this.name = "DocumentCountExceededError"; this.name = "DocumentCountExceededError";
this.count = count; this.count = count;
this.limit = limit; this.limit = limit;
this.statusCode = 413; this.statusCode = 413;
} }
} }
// ============================================================================= // =============================================================================
// Utility Functions // Utility Functions
// ============================================================================= // =============================================================================
/** /**
* Generate a unique request ID for tracing * Generate a unique request ID for tracing
* Uses UUID v4 for uniqueness * Uses UUID v4 for uniqueness
* *
* @returns {string} Request ID in format: req_<uuid> * @returns {string} Request ID in format: req_<uuid>
*/ */
function generateRequestId() { function generateRequestId() {
return `req_${crypto.randomUUID()}`; return `req_${crypto.randomUUID()}`;
} }
/** /**
* Validate document ID format * Validate document ID format
* Google Drive IDs are alphanumeric with hyphens and underscores * Google Drive IDs are alphanumeric with hyphens and underscores
* *
* @param {string} id - Document ID to validate * @param {string} id - Document ID to validate
* @returns {boolean} True if valid * @returns {boolean} True if valid
*/ */
function validateDocumentId(id) { function validateDocumentId(id) {
if (!id || typeof id !== "string") { if (!id || typeof id !== "string") {
return false; return false;
} }
@@ -60,33 +61,33 @@ function validateDocumentId(id) {
// Characters: a-z, A-Z, 0-9, -, _ // Characters: a-z, A-Z, 0-9, -, _
const pattern = /^[a-zA-Z0-9_-]{8,128}$/; const pattern = /^[a-zA-Z0-9_-]{8,128}$/;
return pattern.test(id); return pattern.test(id);
} }
/** /**
* Validate document count against limit * Validate document count against limit
* *
* @param {number} count - Document count * @param {number} count - Document count
* @param {number} limit - Maximum allowed (default: 50000) * @param {number} limit - Maximum allowed (default: 50000)
* @throws {DocumentCountExceededError} If count > limit * @throws {DocumentCountExceededError} If count > limit
*/ */
function validateDocumentCount(count, limit = 50000) { function validateDocumentCount(count, limit = 50000) {
if (count > limit) { if (count > limit) {
throw new DocumentCountExceededError(count, limit); throw new DocumentCountExceededError(count, limit);
} }
} }
// ============================================================================= // =============================================================================
// XML Utilities // XML Utilities
// ============================================================================= // =============================================================================
/** /**
* Escape special XML characters * Escape special XML characters
* Prevents XML injection and ensures valid XML output * Prevents XML injection and ensures valid XML output
* *
* @param {string} str - String to escape * @param {string} str - String to escape
* @returns {string} Escaped string safe for XML * @returns {string} Escaped string safe for XML
*/ */
function escapeXml(str) { function escapeXml(str) {
if (!str) return ""; if (!str) return "";
return str return str
@@ -95,13 +96,13 @@ function escapeXml(str) {
.replace(/>/g, "&gt;") .replace(/>/g, "&gt;")
.replace(/"/g, "&quot;") .replace(/"/g, "&quot;")
.replace(/'/g, "&apos;"); .replace(/'/g, "&apos;");
} }
// ============================================================================= // =============================================================================
// Error Mapping // Error Mapping
// ============================================================================= // =============================================================================
/** /**
* Map Drive API error to HTTP status code and retry info * Map Drive API error to HTTP status code and retry info
* *
* Per specification: * Per specification:
@@ -113,7 +114,7 @@ function escapeXml(str) {
* @param {Error} error - Drive API error * @param {Error} error - Drive API error
* @returns {Object} { statusCode, retryAfter? } * @returns {Object} { statusCode, retryAfter? }
*/ */
function mapDriveErrorToHttp(error) { function mapDriveErrorToHttp(error) {
// Handle DocumentCountExceededError // Handle DocumentCountExceededError
if (error instanceof DocumentCountExceededError) { if (error instanceof DocumentCountExceededError) {
return { statusCode: 413 }; return { statusCode: 413 };
@@ -146,13 +147,13 @@ function mapDriveErrorToHttp(error) {
// All other errors map to 500 // All other errors map to 500
return { statusCode: 500 }; return { statusCode: 500 };
} }
// ============================================================================= // =============================================================================
// Sitemap Functions // Sitemap Functions
// ============================================================================= // =============================================================================
/** /**
* Transform Drive document to sitemap entry * Transform Drive document to sitemap entry
* *
* Creates RESTful URL in format: {baseUrl}/documents/{documentId} * Creates RESTful URL in format: {baseUrl}/documents/{documentId}
@@ -164,7 +165,7 @@ function mapDriveErrorToHttp(error) {
* @param {string} baseUrl - Base URL for the adapter * @param {string} baseUrl - Base URL for the adapter
* @returns {Object} Sitemap entry { loc, lastmod } * @returns {Object} Sitemap entry { loc, lastmod }
*/ */
function toSitemapEntry(document, baseUrl) { function toSitemapEntry(document, baseUrl) {
if (!document || !document.id) { if (!document || !document.id) {
console.error("Invalid document for sitemap entry", { document }); console.error("Invalid document for sitemap entry", { document });
return null; return null;
@@ -191,16 +192,16 @@ function toSitemapEntry(document, baseUrl) {
} }
return { loc, lastmod }; return { loc, lastmod };
} }
/** /**
* Transform array of Drive documents to sitemap entries * Transform array of Drive documents to sitemap entries
* *
* @param {Array<Object>} documents - Array of Drive API documents * @param {Array<Object>} documents - Array of Drive API documents
* @param {string} baseUrl - Base URL for the adapter * @param {string} baseUrl - Base URL for the adapter
* @returns {Array<Object>} Array of sitemap entries * @returns {Array<Object>} Array of sitemap entries
*/ */
function transformDocumentsToSitemapEntries(documents, baseUrl) { function transformDocumentsToSitemapEntries(documents, baseUrl) {
if (!Array.isArray(documents)) { if (!Array.isArray(documents)) {
console.error("Documents must be an array", { documents }); console.error("Documents must be an array", { documents });
return []; return [];
@@ -209,9 +210,9 @@ function transformDocumentsToSitemapEntries(documents, baseUrl) {
return documents return documents
.map((doc) => toSitemapEntry(doc, baseUrl)) .map((doc) => toSitemapEntry(doc, baseUrl))
.filter((entry) => entry !== null); .filter((entry) => entry !== null);
} }
/** /**
* Generate XML sitemap from sitemap entries * Generate XML sitemap from sitemap entries
* *
* Handles empty sitemap (0 documents) case - returns valid XML with empty urlset. * Handles empty sitemap (0 documents) case - returns valid XML with empty urlset.
@@ -219,7 +220,7 @@ function transformDocumentsToSitemapEntries(documents, baseUrl) {
* @param {Array<Object>} sitemapEntries - Array of { loc, lastmod } objects * @param {Array<Object>} sitemapEntries - Array of { loc, lastmod } objects
* @returns {string} Complete XML sitemap string * @returns {string} Complete XML sitemap string
*/ */
function generateSitemapXML(sitemapEntries) { function generateSitemapXML(sitemapEntries) {
let xml = '<?xml version="1.0" encoding="UTF-8"?>\n'; let xml = '<?xml version="1.0" encoding="UTF-8"?>\n';
xml += '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">\n'; xml += '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">\n';
@@ -239,9 +240,9 @@ function generateSitemapXML(sitemapEntries) {
xml += "</urlset>"; xml += "</urlset>";
return xml; return xml;
} }
/** /**
* Main sitemap generation function * Main sitemap generation function
* *
* Combines document transformation and XML generation. * Combines document transformation and XML generation.
@@ -250,22 +251,22 @@ function generateSitemapXML(sitemapEntries) {
* @param {string} baseUrl - Base URL for the adapter * @param {string} baseUrl - Base URL for the adapter
* @returns {string} Complete XML sitemap * @returns {string} Complete XML sitemap
*/ */
function generateSitemap(documents, baseUrl) { function generateSitemap(documents, baseUrl) {
const entries = transformDocumentsToSitemapEntries(documents, baseUrl); const entries = transformDocumentsToSitemapEntries(documents, baseUrl);
return generateSitemapXML(entries); return generateSitemapXML(entries);
} }
// ============================================================================= // =============================================================================
// Route Parsing // Route Parsing
// ============================================================================= // =============================================================================
/** /**
* Parse route from request * Parse route from request
* @param {string} method - HTTP method * @param {string} method - HTTP method
* @param {string} url - Request URL * @param {string} url - Request URL
* @returns {Object} Route info or error * @returns {Object} Route info or error
*/ */
function parseRoute(method, url) { function parseRoute(method, url) {
if (method !== "GET") { if (method !== "GET") {
return { route: null, error: "Method not allowed", statusCode: 405 }; return { route: null, error: "Method not allowed", statusCode: 405 };
} }
@@ -278,35 +279,35 @@ function parseRoute(method, url) {
return { route: "sitemap" }; return { route: "sitemap" };
} }
// All other paths return 404 // All other paths return 404
return { route: null, error: "Not found", statusCode: 404 }; return { route: null, error: "Not found", statusCode: 404 };
} }
// =============================================================================
// Return helpers object with all functions
// =============================================================================
// ============================================================================= return {
// Return helpers object with all functions // Error classes
// ============================================================================= DocumentCountExceededError,
({ // Utilities
// Error classes generateRequestId,
DocumentCountExceededError, validateDocumentId,
validateDocumentCount,
// Utilities // XML
generateRequestId, escapeXml,
validateDocumentId,
validateDocumentCount,
// XML // Error mapping
escapeXml, mapDriveErrorToHttp,
// Error mapping // Sitemap
mapDriveErrorToHttp, toSitemapEntry,
transformDocumentsToSitemapEntries,
generateSitemapXML,
generateSitemap,
// Sitemap // Routing
toSitemapEntry, parseRoute,
transformDocumentsToSitemapEntries, };
generateSitemapXML, })();
generateSitemap,
// Routing
parseRoute,
});