@foal/core
Advanced tools
Comparing version 0.7.7 to 0.8.0
@@ -13,5 +13,5 @@ import * as Ajv from 'ajv'; | ||
* | ||
* This configuration can be overrided using the file `config/ajv.json` or through environment | ||
* variables: AJV_COERCE_TYPES, AJV_REMOVE_ADDITIONAL, USE_DEFAULTS. | ||
* This configuration can be overrided using the file `config/default.json` or through environment | ||
* variables: SETTINGS_AJV_COERCE_TYPES, SETTINGS_AJV_REMOVE_ADDITIONAL, SETTINGS_AJV_USE_DEFAULTS. | ||
*/ | ||
export declare function getAjvInstance(): Ajv.Ajv; |
@@ -19,4 +19,4 @@ "use strict"; | ||
* | ||
* This configuration can be overrided using the file `config/ajv.json` or through environment | ||
* variables: AJV_COERCE_TYPES, AJV_REMOVE_ADDITIONAL, USE_DEFAULTS. | ||
* This configuration can be overrided using the file `config/default.json` or through environment | ||
* variables: SETTINGS_AJV_COERCE_TYPES, SETTINGS_AJV_REMOVE_ADDITIONAL, SETTINGS_AJV_USE_DEFAULTS. | ||
*/ | ||
@@ -26,5 +26,5 @@ function getAjvInstance() { | ||
exports._instanceWrapper.instance = new Ajv({ | ||
coerceTypes: core_1.Config.get('ajv', 'coerceTypes', true), | ||
removeAdditional: core_1.Config.get('ajv', 'removeAdditional', true), | ||
useDefaults: core_1.Config.get('ajv', 'useDefaults', true), | ||
coerceTypes: core_1.Config.get('settings.ajv.coerceTypes', true), | ||
removeAdditional: core_1.Config.get('settings.ajv.removeAdditional', true), | ||
useDefaults: core_1.Config.get('settings.ajv.useDefaults', true), | ||
}); | ||
@@ -31,0 +31,0 @@ } |
@@ -9,3 +9,3 @@ "use strict"; | ||
function render(templatePath, locals, dirname) { | ||
const templateEngine = core_1.Config.get('settings', 'templateEngine', '@foal/ejs'); | ||
const templateEngine = core_1.Config.get('settings.templateEngine', '@foal/ejs'); | ||
const { renderToString } = require(templateEngine); | ||
@@ -12,0 +12,0 @@ if (!renderToString) { |
export declare class Config { | ||
static root: string; | ||
static get(configName: string, propName: string, defaultValue?: number | string | boolean): number | string | boolean | undefined; | ||
private static getEnvironmentVariable; | ||
private static getJsonVariable; | ||
private static toUnderscoreUpperCase; | ||
static get<T = any>(key: string, defaultValue?: T): T; | ||
static clearCache(): void; | ||
private static yaml; | ||
private static cache; | ||
private static readDotEnvValue; | ||
private static readJSONValue; | ||
private static readYAMLValue; | ||
private static getYAMLInstance; | ||
private static dotToUnderscore; | ||
private static convertType; | ||
private static getValue; | ||
get<T = any>(key: string, defaultValue?: T): T; | ||
} |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const fs = require("fs"); | ||
const path = require("path"); | ||
// 3p | ||
const fs_1 = require("fs"); | ||
class Config { | ||
static get(configName, propName, defaultValue) { | ||
const value = Config.getEnvironmentVariable(configName, propName); | ||
if (value !== undefined) { | ||
return value; | ||
static get(key, defaultValue) { | ||
const underscoreName = this.dotToUnderscore(key); | ||
const envValue = process.env[underscoreName]; | ||
if (envValue !== undefined) { | ||
return this.convertType(envValue); | ||
} | ||
const environment = process.env.NODE_ENV || 'development'; | ||
const value2 = Config.getJsonVariable(configName, propName, environment); | ||
if (value2 !== undefined) { | ||
return value2; | ||
const dotEnvValue = this.readDotEnvValue(underscoreName); | ||
if (dotEnvValue !== undefined) { | ||
return dotEnvValue; | ||
} | ||
const value3 = Config.getJsonVariable(configName, propName); | ||
if (value3 !== undefined) { | ||
return value3; | ||
const defaultJSONValue = this.readJSONValue('config/default.json', key); | ||
if (defaultJSONValue !== undefined) { | ||
return defaultJSONValue; | ||
} | ||
const defaultYAMLValue = this.readYAMLValue('config/default.yml', key); | ||
if (defaultYAMLValue !== undefined) { | ||
return defaultYAMLValue; | ||
} | ||
const envJSONFilePath = `config/${process.env.NODE_ENV || 'development'}.json`; | ||
const envJSONValue = this.readJSONValue(envJSONFilePath, key); | ||
if (envJSONValue !== undefined) { | ||
return envJSONValue; | ||
} | ||
const envYamlFilePath = `config/${process.env.NODE_ENV || 'development'}.yml`; | ||
const envYAMLValue = this.readYAMLValue(envYamlFilePath, key); | ||
if (envYAMLValue !== undefined) { | ||
return envYAMLValue; | ||
} | ||
return defaultValue; | ||
} | ||
static getEnvironmentVariable(configName, propName) { | ||
const name = `${Config.toUnderscoreUpperCase(configName)}_${Config.toUnderscoreUpperCase(propName)}`; | ||
const config = process.env[name]; | ||
if (config === undefined) { | ||
return undefined; | ||
static clearCache() { | ||
this.cache = { | ||
dotEnv: undefined, | ||
json: {}, | ||
yaml: {}, | ||
}; | ||
} | ||
static readDotEnvValue(name) { | ||
if (!this.cache.dotEnv) { | ||
if (!fs_1.existsSync('.env')) { | ||
return; | ||
} | ||
const envFileContent = fs_1.readFileSync('.env', 'utf8'); | ||
this.cache.dotEnv = {}; | ||
envFileContent.replace(/\r\n/g, '\n').split('\n').forEach(line => { | ||
const [key, value] = line.split('='); | ||
this.cache.dotEnv[key] = value; | ||
}); | ||
} | ||
if (config === 'true') { | ||
return true; | ||
if (this.cache.dotEnv[name] !== undefined) { | ||
return this.convertType(this.cache.dotEnv[name]); | ||
} | ||
if (config === 'false') { | ||
} | ||
static readJSONValue(path, key) { | ||
if (!this.cache.json[path]) { | ||
if (!fs_1.existsSync(path)) { | ||
return; | ||
} | ||
const fileContent = fs_1.readFileSync(path, 'utf8'); | ||
this.cache.json[path] = JSON.parse(fileContent); | ||
} | ||
return this.getValue(this.cache.json[path], key); | ||
} | ||
static readYAMLValue(path, key) { | ||
if (!this.cache.yaml[path]) { | ||
if (!fs_1.existsSync(path)) { | ||
return; | ||
} | ||
const yaml = this.getYAMLInstance(); | ||
if (!yaml) { | ||
console.log(`Impossible to read ${path}. The package "yamljs" is not installed.`); | ||
return; | ||
} | ||
const fileContent = fs_1.readFileSync(path, 'utf8'); | ||
this.cache.yaml[path] = yaml.parse(fileContent); | ||
} | ||
return this.getValue(this.cache.yaml[path], key); | ||
} | ||
static getYAMLInstance() { | ||
if (this.yaml === false) { | ||
return false; | ||
} | ||
const num = parseInt(config, 10); | ||
if (!isNaN(num)) { | ||
return num; | ||
try { | ||
this.yaml = require('yamljs'); | ||
} | ||
return config; | ||
catch (err) { | ||
if (err.code !== 'MODULE_NOT_FOUND') { | ||
throw err; | ||
} | ||
this.yaml = false; | ||
} | ||
return this.yaml; | ||
} | ||
static getJsonVariable(configName, propName, env) { | ||
const filename = env ? `${configName}.${env}.json` : `${configName}.json`; | ||
const filePath = path.join(Config.root, filename); | ||
if (!fs.existsSync(filePath)) { | ||
return; | ||
static dotToUnderscore(str) { | ||
return str | ||
.replace(/([A-Z])/g, letter => `_${letter}`) | ||
.replace(/\./g, '_') | ||
.toUpperCase(); | ||
} | ||
static convertType(value) { | ||
if (value === 'true') { | ||
return true; | ||
} | ||
const config = require(filePath); | ||
const propType = typeof config[propName]; | ||
if (!['string', 'number', 'boolean', 'undefined'].includes(propType)) { | ||
throw new Error('Config: only string, number and boolean values are supported.' | ||
+ ` ${propName} type is "${propType}" in ${filename}.`); | ||
if (value === 'false') { | ||
return false; | ||
} | ||
return config[propName]; | ||
const n = parseInt(value, 10); | ||
if (!isNaN(n)) { | ||
return n; | ||
} | ||
return value; | ||
} | ||
static toUnderscoreUpperCase(camelCase) { | ||
let result = camelCase.replace(/([A-Z])/g, letter => `_${letter}`); | ||
if (result.startsWith('_')) { | ||
result = result.substring(1); | ||
static getValue(config, propertyPath) { | ||
const properties = propertyPath.split('.'); | ||
let result = config; | ||
for (const property of properties) { | ||
result = result[property]; | ||
if (result === undefined) { | ||
break; | ||
} | ||
} | ||
return result.toUpperCase(); | ||
return result; | ||
} | ||
get(key, defaultValue) { | ||
return Config.get(key, defaultValue); | ||
} | ||
} | ||
Config.root = path.join(process.cwd(), 'config'); | ||
Config.cache = { | ||
dotEnv: undefined, | ||
json: {}, | ||
yaml: {}, | ||
}; | ||
exports.Config = Config; |
@@ -0,3 +1,7 @@ | ||
import { Request } from 'express'; | ||
interface HTTPRequest extends Request { | ||
session: any; | ||
csrfToken: () => string; | ||
} | ||
export declare class Context<User = any> { | ||
request: any; | ||
state: { | ||
@@ -7,3 +11,5 @@ [key: string]: any; | ||
user: User; | ||
request: HTTPRequest; | ||
constructor(request: any); | ||
} | ||
export {}; |
@@ -5,6 +5,6 @@ "use strict"; | ||
constructor(request) { | ||
this.state = {}; | ||
this.request = request; | ||
this.state = {}; | ||
} | ||
} | ||
exports.Context = Context; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
// std | ||
const path = require("path"); | ||
// 3p | ||
const cookieParser = require("cookie-parser"); | ||
const csurf = require("csurf"); | ||
@@ -24,24 +23,25 @@ const express = require("express"); | ||
const app = expressInstance || express(); | ||
const loggerFormat = core_1.Config.get('settings', 'loggerFormat', '[:date] ":method :url HTTP/:http-version" :status - :response-time ms'); | ||
const loggerFormat = core_1.Config.get('settings.loggerFormat', '[:date] ":method :url HTTP/:http-version" :status - :response-time ms'); | ||
app.use(logger(loggerFormat)); | ||
app.use(express.static(path.join(process.cwd(), core_1.Config.get('settings', 'staticUrl', '/public')))); | ||
app.use(express.static(core_1.Config.get('settings.staticUrl', 'public'))); | ||
app.use(helmet()); | ||
app.use(express.json()); | ||
app.use(express.urlencoded({ extended: false })); | ||
app.use(cookieParser()); | ||
app.use(session({ | ||
cookie: { | ||
domain: core_1.Config.get('settings', 'sessionCookieDomain'), | ||
httpOnly: core_1.Config.get('settings', 'sessionCookieHttpOnly'), | ||
maxAge: core_1.Config.get('settings', 'sessionCookieMaxAge'), | ||
path: core_1.Config.get('settings', 'sessionCookiePath'), | ||
sameSite: core_1.Config.get('settings', 'sessionCookieSameSite'), | ||
secure: core_1.Config.get('settings', 'sessionCookieSecure'), | ||
domain: core_1.Config.get('settings.session.cookie.domain'), | ||
httpOnly: core_1.Config.get('settings.session.cookie.httpOnly'), | ||
maxAge: core_1.Config.get('settings.session.cookie.maxAge'), | ||
path: core_1.Config.get('settings.session.cookie.path'), | ||
sameSite: core_1.Config.get('settings.session.cookie.sameSite'), | ||
secure: core_1.Config.get('settings.session.cookie.secure'), | ||
}, | ||
name: core_1.Config.get('settings', 'sessionName'), | ||
resave: core_1.Config.get('settings', 'sessionResave', false), | ||
saveUninitialized: core_1.Config.get('settings', 'sessionSaveUninitialized', true), | ||
secret: core_1.Config.get('settings', 'sessionSecret', 'default_secret'), | ||
name: core_1.Config.get('settings.session.name'), | ||
resave: core_1.Config.get('settings.session.resave', false), | ||
saveUninitialized: core_1.Config.get('settings.session.saveUninitialized', true), | ||
secret: core_1.Config.get('settings.session.secret', 'default_secret'), | ||
store: options.store ? options.store(session) : undefined, | ||
})); | ||
if (core_1.Config.get('settings', 'csrf', false)) { | ||
if (core_1.Config.get('settings.csrf', false)) { | ||
app.use(csurf()); | ||
@@ -90,5 +90,5 @@ } | ||
app.use(not_found_1.notFound()); | ||
app.use(handle_errors_1.handleErrors(core_1.Config.get('settings', 'debug', false), console.error)); | ||
app.use(handle_errors_1.handleErrors(core_1.Config.get('settings.debug', false), console.error)); | ||
return app; | ||
} | ||
exports.createApp = createApp; |
@@ -9,3 +9,2 @@ /** | ||
export * from './core'; | ||
export * from './deprecated'; | ||
export * from './express'; |
@@ -14,3 +14,2 @@ "use strict"; | ||
__export(require("./core")); | ||
__export(require("./deprecated")); | ||
__export(require("./express")); |
{ | ||
"name": "@foal/core", | ||
"version": "0.7.7", | ||
"version": "0.8.0", | ||
"description": "High level web framework to create enterprise-grade Node.JS applications.", | ||
@@ -79,3 +79,5 @@ "main": "./lib/index.js", | ||
"dependencies": { | ||
"@types/express": "^4.16.1", | ||
"ajv": "^6.5.0", | ||
"cookie-parser": "^1.4.3", | ||
"csurf": "^1.9.0", | ||
@@ -89,3 +91,3 @@ "express": "^4.16.3", | ||
"devDependencies": { | ||
"@foal/ejs": "^0.7.3", | ||
"@foal/ejs": "^0.8.0", | ||
"@types/mocha": "^2.2.43", | ||
@@ -105,4 +107,5 @@ "@types/node": "^10.1.2", | ||
"ts-node": "^3.3.0", | ||
"typescript": "^2.5.2" | ||
"typescript": "^2.5.2", | ||
"yamljs": "^0.3.0" | ||
} | ||
} |
@@ -44,2 +44,4 @@ <p align="center"> | ||
FoalTS is a Node.js framework for building HTTP APIs and Web applications with a rich interface (Angular / React / Vue). It is written in TypeScript and offers many built-in dev tools and components to handle extremely common scenarios. Simple, testable and progressive, Foal accelerates development while leaving you in control of your code. | ||
## Get started | ||
@@ -58,3 +60,3 @@ | ||
The development server is started! Go to `http://localhost:3000` and find our welcoming page! | ||
The development server is started! Go to `http://localhost:3001` and find our welcoming page! | ||
@@ -61,0 +63,0 @@ [=> Continue with the tutorial](https://foalts.gitbook.io/docs/content/) |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
70
75730
9
17
99
1750
+ Added@types/express@^4.16.1
+ Addedcookie-parser@^1.4.3
+ Added@types/body-parser@1.19.5(transitive)
+ Added@types/connect@3.4.38(transitive)
+ Added@types/express@4.17.21(transitive)
+ Added@types/express-serve-static-core@4.19.6(transitive)
+ Added@types/http-errors@2.0.4(transitive)
+ Added@types/mime@1.3.5(transitive)
+ Added@types/node@22.7.3(transitive)
+ Added@types/qs@6.9.16(transitive)
+ Added@types/range-parser@1.2.7(transitive)
+ Added@types/send@0.17.4(transitive)
+ Added@types/serve-static@1.15.7(transitive)
+ Addedcookie@0.4.1(transitive)
+ Addedcookie-parser@1.4.6(transitive)
+ Addedundici-types@6.19.8(transitive)