require
- Loading Private Modules
- Type:
Function(path: string) => any
- Description: Loads JavaScript modules or JSON files from
_private
directories, following an upward directory traversal pattern to find the requested file.
Directory Resolution
PocketPages looks for required files in _private
directories, starting from the current template's directory and working up through parent directories until the file is found. This system provides:
- Secure file access (directories starting with
_private
are never routed) - Ability to share common modules by "hoisting" them to ancestor directories
- Section-specific private modules that are only available to that section
- Ability to override parent modules by having a local version with the same name
- Simplified path management since you rarely need relative paths
Example Directory Structure
pb_hooks/
pages/
_private/ # Global private files
config.js
auth.js
products/
_private/ # Product-specific files
queries.js
helpers.js
categories/
_private/ # Category-specific files
formatter.js
index.ejs
index.ejs
index.ejs
Using require
Basic Usage
<%
// Looks for config.js in _private directories, starting from current directory up
const config = require('config')
// Use the loaded module
const apiKey = config.apiKey
%>
Resolution Rules
When resolving a file path, PocketPages will:
- Start in the current template's directory, looking for
_private/filename
- If not found, check the parent directory for
_private/filename
- Continue up the directory tree until the file is found or the root is reached
You have several options for controlling this resolution:
- Simple name: Just specify the file name (e.g.,
config
) to use the automatic resolution system - Absolute paths: Start with
/
to specify an explicit path from the root (e.g.,/products/_private/queries
) - Level jumping: Use
../
prefix to skip the local_private
directory and force resolution from a parent level
Examples
Given the directory structure above:
<%
// In /products/categories/index.ejs:
const formatter = require('formatter') // Uses /products/categories/_private/formatter.js
const queries = require('queries') // Uses /products/_private/queries.js
const config = require('config') // Uses /_private/config.js
// Using absolute path
const productQueries = require('/products/_private/queries')
// Level jumping
const parentHelpers = require('../helpers') // Skips local _private/helpers.js and uses parent's version
%>
Example Private Files
Global Configuration
// _private/config.js
module.exports = {
apiKey: env.API_KEY,
baseUrl: 'https://api.example.com',
limits: {
maxUploadSize: 5 * 1024 * 1024,
maxResults: 100,
},
}
Section-Specific Utilities
// products/_private/queries.js
module.exports = {
getActiveProducts: () => {
return $app.dao().findRecordsByExpr('products', 'status = ?', ['active'])
},
getCategoryProducts: (categoryId) => {
return $app
.dao()
.findRecordsByExpr('products', 'category = ?', [categoryId])
},
}
Best Practices
Organize by Function: Group related functionality into logical directories
_private/ config/ development.js production.js auth/ permissions.js validation.js
Use Environment Variables: For sensitive data
// _private/config.js module.exports = { apiKey: env.API_KEY, // Good secret: 'hardcoded-bad', // Bad }
Export Clean Interfaces: Make your modules easy to use
// _private/database.js module.exports = { query: (sql, params) => { return $app.dao().findRecordsByExpr('table', sql, params) }, getRecord: (collection, id) => { return $app.dao().findRecordById(collection, id) }, }
Important Notes
- Files must be in a
_private
directory - Use for server-side logic and configuration only
- Don't store sensitive credentials directly in files - use environment variables
- Changes to private files require a server restart in production
- Async/await is not available in the JSVM - use promises or callbacks instead
See Private Files for more information about working with private files and directories in PocketPages.