{"version":3,"sources":["jsdelivr-header.js","/npm/raneto@0.18.1/app/index.js"],"names":[],"mappings":"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","file":"/npm/raneto@0.18.1/app/index.js","sourceRoot":"","sourcesContent":["/**\n * Minified by jsDelivr using Terser v5.39.0.\n * Original file: /npm/raneto@0.18.1/app/index.js\n *\n * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files\n */\n","// Modules\nimport crypto from 'node:crypto';\nimport path from 'node:path';\nimport express from 'express';\nimport logger from 'morgan';\nimport cookie_parser from 'cookie-parser';\nimport body_parser from 'body-parser';\nimport moment from 'moment';\nimport helmet from 'helmet';\nimport rateLimit from 'express-rate-limit';\nimport mustacheExpress from 'mustache-express';\nimport session from 'express-session';\nimport FileStore from 'session-file-store';\nimport passport from 'passport';\nimport validateConfig from './core/configValidation.js';\nimport languageLoad from './core/language.js';\nimport authenticate from './middleware/authenticate.mw.js';\nimport authReadonly from './middleware/authenticateReadAccess.mw.js';\nimport errorHandler from './middleware/errorHandler.mw.js';\nimport oauth2 from './middleware/oauth2.mw.js';\nimport routeLogin from './routes/login.route.js';\nimport routeLoginPage from './routes/loginPage.route.js';\nimport routeLogout from './routes/logout.route.js';\nimport routePageEdit from './routes/pageEdit.route.js';\nimport routePageDelete from './routes/pageDelete.route.js';\nimport routePageCreate from './routes/pageCreate.route.js';\nimport routeCategoryCreate from './routes/categoryCreate.route.js';\nimport routeSearch from './routes/search.route.js';\nimport routeHome from './routes/home.route.js';\nimport routeWildcard from './routes/wildcard.route.js';\nimport routeSitemap from './routes/sitemap.route.js';\nconst __dirname = import.meta.dirname;\n\nconst RATE_LIMIT_WINDOW_MS = 60 * 1000; // 1 minute\nconst RATE_LIMIT_MAX_REQUESTS = 200;\nconst SESSION_TTL_SECONDS = 86400; // 24 hours\nconst SESSION_REAP_INTERVAL_SECONDS = 3600; // 1 hour\nconst COOKIE_MAX_AGE_MS = 86400000; // 24 hours\n\nfunction initialize(config) {\n  // Validate configuration\n  validateConfig(config);\n\n  // Load Translations\n  if (!config.locale) {\n    config.locale = 'en';\n  }\n  if (!config.lang) {\n    config.lang = languageLoad(config.locale);\n  }\n\n  // Content_Dir requires trailing slash\n  if (config.content_dir[config.content_dir.length - 1] !== path.sep) {\n    config.content_dir += path.sep;\n  }\n\n  // Load Middleware\n  const authMiddleware = authenticate(config);\n  const alwaysAuthenticate = authenticate(config, { required: true });\n  const handleError = errorHandler(config);\n\n  // Load Multiple-Use Pages\n  const searchInit = routeSearch(config);\n  const homeInit = routeHome(config);\n  const wildcardInit = routeWildcard(config);\n  const sitemapInit = routeSitemap(config);\n\n  // New Express App\n  const app = express();\n  const router = express.Router();\n\n  // Set IP Address and Port\n  app.set('host', process.env.HOST || '127.0.0.1');\n  app.set('port', process.env.PORT || 8080);\n\n  // set locale as date and time format\n  moment.locale(config.locale);\n\n  // Setup Views\n  if (!config.theme_dir) {\n    config.theme_dir = path.join(__dirname, '..', 'themes');\n  }\n  if (!config.theme_name) {\n    config.theme_name = 'default';\n  }\n  if (!config.public_dir) {\n    config.public_dir = path.join(\n      config.theme_dir,\n      config.theme_name,\n      'public',\n    );\n  }\n  const viewsDir = path.join(config.theme_dir, config.theme_name, 'templates');\n  app.set('views', viewsDir);\n  app.set('view engine', 'html');\n  app.enable('view cache');\n  app.engine('html', mustacheExpress(path.join(viewsDir, 'partials'), '.html'));\n\n  // Setup Express\n  app.use(logger('dev'));\n\n  // Rate limiting - 200 requests per minute per IP\n  app.use(\n    rateLimit({\n      windowMs: RATE_LIMIT_WINDOW_MS,\n      max: RATE_LIMIT_MAX_REQUESTS,\n      standardHeaders: true,\n      legacyHeaders: false,\n    }),\n  );\n\n  // Generate CSP nonce per request\n  app.use((req, res, next) => {\n    res.locals.csp_nonce = crypto.randomBytes(16).toString('base64');\n    next();\n  });\n\n  app.use(\n    helmet({\n      contentSecurityPolicy: {\n        directives: {\n          defaultSrc: [\"'self'\"],\n          scriptSrc: [\"'self'\", 'https://cdnjs.cloudflare.com'],\n          styleSrc: [\"'self'\", (req, res) => `'nonce-${res.locals.csp_nonce}'`],\n          imgSrc: [\"'self'\", 'data:', 'https:'],\n          fontSrc: [\"'self'\", 'data:'],\n          connectSrc: [\"'self'\"],\n          frameSrc: [\"'none'\"],\n          objectSrc: [\"'none'\"],\n          upgradeInsecureRequests: [],\n        },\n      },\n      crossOriginEmbedderPolicy: false,\n    }),\n  );\n  app.use(body_parser.json());\n  app.use(body_parser.urlencoded({ extended: false }));\n  app.use(cookie_parser());\n  app.use(express.static(config.public_dir));\n  if (config.theme_dir !== path.join(__dirname, '..', 'themes')) {\n    router.use(\n      express.static(path.join(config.theme_dir, config.theme_name, 'public')),\n    );\n  }\n  router.use(\n    config.image_url,\n    express.static(path.join(config.content_dir, config.image_url)),\n  );\n  router.use(\n    '/translations',\n    express.static(path.normalize(path.join(__dirname, 'translations'))),\n  );\n\n  // HTTP Authentication\n  if (\n    config.authentication === true ||\n    config.authentication_for_edit ||\n    config.authentication_for_read\n  ) {\n    const SessionFileStore = FileStore(session);\n    app.use(\n      session({\n        store: new SessionFileStore({\n          path: './sessions',\n          ttl: SESSION_TTL_SECONDS,\n          retries: 0,\n          reapInterval: SESSION_REAP_INTERVAL_SECONDS,\n        }),\n        secret: config.secret,\n        name: 'raneto.sid',\n        resave: false,\n        saveUninitialized: false,\n        cookie: {\n          maxAge: COOKIE_MAX_AGE_MS,\n          secure: process.env.NODE_ENV === 'production',\n          httpOnly: true,\n          sameSite: 'Lax',\n        },\n      }),\n    );\n    app.use(authReadonly(config));\n    // OAuth2\n    if (config.googleoauth === true) {\n      app.use(passport.initialize());\n      app.use(passport.session());\n      router.use(oauth2.router(config));\n      app.use(oauth2.template);\n    }\n\n    router.post('/rn-login', routeLogin(config));\n    router.get('/logout', routeLogout(config));\n    router.get('/login', routeLoginPage(config));\n  }\n\n  // Online Editor Routes\n  if (config.allow_editing === true) {\n    let middlewareToUse = authMiddleware;\n    if (config.authentication_for_edit === true) {\n      middlewareToUse = alwaysAuthenticate;\n    }\n    if (config.googleoauth === true) {\n      middlewareToUse = oauth2.required;\n    }\n\n    router.post('/rn-edit', middlewareToUse, routePageEdit(config));\n    router.post('/rn-delete', middlewareToUse, routePageDelete(config));\n    router.post('/rn-add-page', middlewareToUse, routePageCreate(config));\n    router.post(\n      '/rn-add-category',\n      middlewareToUse,\n      routeCategoryCreate(config),\n    );\n  }\n\n  // Select read-access middleware based on auth config\n  let readMiddleware = (req, res, next) => next();\n  if (config.googleoauth) {\n    readMiddleware = oauth2.required;\n  } else if (config.authentication_for_read) {\n    readMiddleware = authMiddleware;\n  }\n\n  router.get('/sitemap.xml', readMiddleware, sitemapInit);\n  router.get('/', readMiddleware, searchInit, homeInit);\n  router.get(/^([^.]*)/, readMiddleware, wildcardInit);\n\n  // Handle Errors\n  router.use(handleError);\n  app.use(config.prefix_url || '/', router);\n\n  // Wrap App if base_url is set\n  if (config.base_url !== '' && config.nowrap !== true) {\n    const wrapApp = express();\n    wrapApp.set('port', process.env.PORT || 8080);\n    wrapApp.use(config.base_url, app);\n    return wrapApp;\n  } else {\n    return app;\n  }\n}\n\n// Exports\nexport default initialize;\n"]}