This commit is contained in:
Tutur33
2023-11-24 22:35:41 +01:00
parent 3c0b507a93
commit 7644b2a0f7
45165 changed files with 4803356 additions and 3 deletions
+9
View File
@@ -0,0 +1,9 @@
# The MIT License
Copyright 2022 Harminder Virk, contributors
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+53
View File
@@ -0,0 +1,53 @@
<div align="center">
<img src="https://res.cloudinary.com/adonisjs/image/upload/q_100/v1558612869/adonis-readme_zscycu.jpg" width="600px">
</div>
<br />
<div align="center">
<h3>Sessions</h3>
<p>This package adds support for sessions to AdonisJS</p>
</div>
<br />
<div align="center">
[![gh-workflow-image]][gh-workflow-url] [![typescript-image]][typescript-url] [![npm-image]][npm-url] [![license-image]][license-url] [![synk-image]][synk-url]
</div>
<div align="center">
<h3>
<a href="https://adonisjs.com">
Website
</a>
<span> | </span>
<a href="https://docs.adonisjs.com/guides/session">
Guides
</a>
<span> | </span>
<a href="CONTRIBUTING.md">
Contributing
</a>
</h3>
</div>
<div align="center">
<sub>Built with ❤︎ by <a href="https://twitter.com/AmanVirk1">Harminder Virk</a>
</div>
[gh-workflow-image]: https://img.shields.io/github/workflow/status/adonisjs/session/test?style=for-the-badge
[gh-workflow-url]: https://github.com/adonisjs/session/actions/workflows/test.yml "Github action"
[typescript-image]: https://img.shields.io/badge/Typescript-294E80.svg?style=for-the-badge&logo=typescript
[typescript-url]: "typescript"
[npm-image]: https://img.shields.io/npm/v/@adonisjs/session/latest.svg?style=for-the-badge&logo=npm
[npm-url]: https://www.npmjs.com/package/@adonisjs/session/v/latest "npm"
[license-image]: https://img.shields.io/npm/l/@adonisjs/session?color=blueviolet&style=for-the-badge
[license-url]: LICENSE.md "license"
[synk-image]: https://img.shields.io/snyk/vulnerabilities/github/adonisjs/session?label=Synk%20Vulnerabilities&style=for-the-badge
[synk-url]: https://snyk.io/test/github/adonisjs/session?targetFile=package.json "synk"
@@ -0,0 +1,14 @@
/**
* @adonisjs/session
*
* (c) Harminder Virk <virk@adonisjs.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
declare module '@ioc:Adonis/Core/Application' {
import { SessionManagerContract } from '@ioc:Adonis/Addons/Session';
interface ContainerBindings {
'Adonis/Addons/Session': SessionManagerContract;
}
}
@@ -0,0 +1,8 @@
/**
* @adonisjs/session
*
* (c) Harminder Virk <virk@adonisjs.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
+14
View File
@@ -0,0 +1,14 @@
/**
* @adonisjs/session
*
* (c) Harminder Virk <virk@adonisjs.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
declare module '@ioc:Adonis/Core/HttpContext' {
import { SessionContract } from '@ioc:Adonis/Addons/Session';
interface HttpContextContract {
session: SessionContract;
}
}
+8
View File
@@ -0,0 +1,8 @@
/**
* @adonisjs/session
*
* (c) Harminder Virk <virk@adonisjs.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
+4
View File
@@ -0,0 +1,4 @@
/// <reference path="session.d.ts" />
/// <reference path="context.d.ts" />
/// <reference path="container.d.ts" />
/// <reference path="tests.d.ts" />
+12
View File
@@ -0,0 +1,12 @@
/*
* @adonisjs/session
*
* (c) Harminder Virk <virk@adonisjs.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/// <reference path="./session.ts" />
/// <reference path="./context.ts" />
/// <reference path="./container.ts" />
/// <reference path="./tests.ts" />
+265
View File
@@ -0,0 +1,265 @@
/// <reference types="@adonisjs/http-server/build/adonis-typings" />
/// <reference types="@adonisjs/application/build/adonis-typings" />
declare module '@ioc:Adonis/Addons/Session' {
import { CookieOptions } from '@ioc:Adonis/Core/Response';
import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext';
import { ApplicationContract } from '@ioc:Adonis/Core/Application';
/**
* Shape of session config.
*/
export interface SessionConfig {
/**
* Enable/disable session for the entire application lifecycle
*/
enabled: boolean;
/**
* The driver in play
*/
driver: string;
/**
* Cookie name.
*/
cookieName: string;
/**
* Clear session when browser closes
*/
clearWithBrowser: boolean;
/**
* Age of session cookie
*/
age: string | number;
/**
* Config for the cookie driver and also the session id
* cookie
*/
cookie: Omit<Partial<CookieOptions>, 'maxAge' | 'expires'>;
/**
* Config for the file driver
*/
file?: {
location: string;
};
/**
* The redis connection to use from the `config/redis` file
*/
redisConnection?: string;
}
/**
* Shape of a driver that every session driver must have
*/
export interface SessionDriverContract {
read(sessionId: string): Promise<Record<string, any> | null> | Record<string, any> | null;
write(sessionId: string, values: Record<string, any>): Promise<void> | void;
destroy(sessionId: string): Promise<void> | void;
touch(sessionId: string): Promise<void> | void;
}
/**
* The callback to be passed to the `extend` method. It is invoked
* for each request (if extended driver is in use).
*/
export type ExtendCallback = (manager: SessionManagerContract, config: SessionConfig, ctx: HttpContextContract) => SessionDriverContract;
/**
* The values allowed by the `session.put` method
*/
export type AllowedSessionValues = string | boolean | number | object | Date | Array<any>;
/**
* Store used for storing session values + flash messages
*/
export interface StoreContract {
/**
* A boolean to know if store is empty
*/
isEmpty: boolean;
/**
* Set value for a key
*/
set(key: string, value: AllowedSessionValues): void;
/**
* Increment value for a key. An exception is raised when existing
* value is not a number
*/
increment(key: string, steps?: number): void;
/**
* Decrement value for a key. An exception is raised when existing
* value is not a number
*/
decrement(key: string, steps?: number): void;
/**
* Replace existing values with new ones
*/
update(values: Record<string, any>): void;
/**
* Merge values with existing ones
*/
merge(values: Record<string, any>): any;
/**
* Get all values
*/
all(): any;
/**
* Get value for a given key or use the default value
*/
get(key: string, defaultValue?: any): any;
/**
* Find if a value exists. Optionally you can also check arrays
* to have length too
*/
has(key: string, checkForArraysLength?: boolean): boolean;
/**
* Unset value
*/
unset(key: string): void;
/**
* Clear all values
*/
clear(): void;
/**
* Read value and then unset it at the same time
*/
pull(key: string, defaultValue?: any): any;
/**
* Convert store values toObject
*/
toObject(): any;
/**
* Convert store values to toJSON
*/
toJSON(): any;
}
/**
* Shape of the actual session store
*/
export interface SessionContract {
/**
* Has the store being initiated
*/
initiated: boolean;
/**
* Is session store readonly. Will be during Websockets
* request
*/
readonly: boolean;
/**
* Is session just created or we read received the
* session id from the request
*/
fresh: boolean;
/**
* Session id
*/
sessionId: string;
/**
* Previous request flash messages
*/
flashMessages: StoreContract;
/**
* Flash messages that will be sent in the current
* request response
*/
responseFlashMessages: StoreContract;
/**
* Initiate session store
*/
initiate(readonly: boolean): Promise<void>;
/**
* Commit session mutations
*/
commit(): Promise<void>;
/**
* Re-generate session id. This help avoid session
* replay attacks.
*/
regenerate(): void;
/**
* Store API
*/
has(key: string): boolean;
put(key: string, value: AllowedSessionValues): void;
get(key: string, defaultValue?: any): any;
all(): any;
forget(key: string): void;
pull(key: string, defaultValue?: any): any;
increment(key: string, steps?: number): any;
decrement(key: string, steps?: number): any;
clear(): void;
/**
* Flash a key-value pair
*/
flash(values: {
[key: string]: AllowedSessionValues;
}): void;
flash(key: string, value: AllowedSessionValues): void;
/**
* Flash request body
*/
flashAll(): void;
/**
* Flash selected keys from the request body
*/
flashOnly(keys: string[]): void;
/**
* Omit selected keys from the request data and flash
* the rest of values
*/
flashExcept(keys: string[]): void;
/**
* Reflash existing flash messages
*/
reflash(): void;
/**
* Reflash selected keys from the existing flash messages
*/
reflashOnly(keys: string[]): void;
/**
* Omit selected keys from the existing flash messages
* and flash the rest of values
*/
reflashExcept(keys: string[]): void;
}
/**
* SessionClient exposes the API to set session data as a client
*/
export interface SessionClientContract extends StoreContract {
/**
* Find if the sessions are enabled
*/
isEnabled(): boolean;
/**
* Flash messages store to set flash messages
*/
flashMessages: StoreContract;
/**
* Load session data from the driver
*/
load(cookies: Record<string, any>): Promise<{
session: Record<string, any>;
flashMessages: Record<string, any> | null;
}>;
/**
* Commits the session data to the session store and returns
* the session id and cookie name for it to be accessible
* by the server
*/
commit(): Promise<{
cookieName: string;
sessionId: string;
signedSessionId: string;
}>;
/**
* Forget the session data.
*/
forget(): Promise<void>;
}
/**
* Session manager shape
*/
export interface SessionManagerContract {
isEnabled(): boolean;
application: ApplicationContract;
client(): SessionClientContract;
create(ctx: HttpContextContract): SessionContract;
extend(driver: string, callback: ExtendCallback): void;
}
const Session: SessionManagerContract;
export default Session;
}
+8
View File
@@ -0,0 +1,8 @@
/*
* @adonisjs/session
*
* (c) Harminder Virk <virk@adonisjs.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
+56
View File
@@ -0,0 +1,56 @@
/// <reference types="node" />
import '@japa/api-client';
import { InspectOptions } from 'util';
import { AllowedSessionValues, SessionClientContract } from '@ioc:Adonis/Addons/Session';
declare module '@japa/api-client' {
interface ApiRequest {
sessionClient: SessionClientContract;
/**
* Send session values in the request
*/
session(session: Record<string, AllowedSessionValues>): this;
/**
* Send flash messages in the request
*/
flashMessages(messages: Record<string, AllowedSessionValues>): this;
}
interface ApiResponse {
/**
* A copy of session data loaded from the driver
*/
sessionJar: {
session: Record<string, any>;
flashMessages: Record<string, any> | null;
};
/**
* Get session data
*/
session(): Record<string, any>;
/**
* Dump session
*/
dumpSession(options?: InspectOptions): this;
/**
* Get flash messages set by the server
*/
flashMessages(): Record<string, any>;
/**
* Assert response to contain a given session and optionally
* has the expected value
*/
assertSession(key: string, value?: any): void;
/**
* Assert response to not contain a given session
*/
assertSessionMissing(key: string): void;
/**
* Assert response to contain a given flash message and optionally
* has the expected value
*/
assertFlashMessage(key: string, value?: any): void;
/**
* Assert response to not contain a given session
*/
assertFlashMissing(key: string): void;
}
}
+11
View File
@@ -0,0 +1,11 @@
"use strict";
/*
* @adonisjs/session
*
* (c) AdonisJS
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
Object.defineProperty(exports, "__esModule", { value: true });
require("@japa/api-client");
+13
View File
@@ -0,0 +1,13 @@
/**
* @adonisjs/session
*
* (c) Harminder Virk <virk@adonisjs.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
import { SessionConfig } from '@ioc:Adonis/Addons/Session';
/**
* Helper to define session config
*/
export declare function sessionConfig<Config extends SessionConfig>(config: Config): Config;
+18
View File
@@ -0,0 +1,18 @@
"use strict";
/**
* @adonisjs/session
*
* (c) Harminder Virk <virk@adonisjs.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.sessionConfig = void 0;
/**
* Helper to define session config
*/
function sessionConfig(config) {
return config;
}
exports.sessionConfig = sessionConfig;
+10
View File
@@ -0,0 +1,10 @@
The package has been configured successfully. The session configuration stored inside `config/session.ts` file relies on the following environment variables and hence we recommend validating them.
Open the `env.ts` file and paste the following code inside the `Env.rules` object.
```ts
SESSION_DRIVER: Env.schema.string()
```
- Here we expect the `SESSION_DRIVER` environment variable to be always present
- And should be a valid string
@@ -0,0 +1,31 @@
/**
* @adonisjs/session
*
* (c) Harminder Virk <virk@adonisjs.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/// <reference types="@adonisjs/application/build/adonis-typings" />
import { ApplicationContract } from '@ioc:Adonis/Core/Application';
/**
* Session provider for AdonisJS
*/
export default class SessionProvider {
protected app: ApplicationContract;
constructor(app: ApplicationContract);
static needsApplication: boolean;
/**
* Register Session Manager
*/
register(): void;
/**
* Register bindings for tests
*/
protected registerTestsBindings(): void;
/**
* Register server bindings
*/
protected registerServerBindings(): void;
boot(): void;
}
@@ -0,0 +1,56 @@
"use strict";
/**
* @adonisjs/session
*
* (c) Harminder Virk <virk@adonisjs.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
Object.defineProperty(exports, "__esModule", { value: true });
/**
* Session provider for AdonisJS
*/
class SessionProvider {
constructor(app) {
this.app = app;
}
/**
* Register Session Manager
*/
register() {
this.app.container.singleton('Adonis/Addons/Session', () => {
const { SessionManager } = require('../src/SessionManager');
return new SessionManager(this.app, this.app.config.get('session', {}));
});
}
/**
* Register bindings for tests
*/
registerTestsBindings() {
this.app.container.withBindings([
'Japa/Preset/ApiRequest',
'Japa/Preset/ApiResponse',
'Japa/Preset/ApiClient',
'Adonis/Addons/Session',
], (ApiRequest, ApiResponse, ApiClient, Session) => {
const { defineTestsBindings } = require('../src/Bindings/Tests');
defineTestsBindings(ApiRequest, ApiResponse, ApiClient, Session);
});
}
/**
* Register server bindings
*/
registerServerBindings() {
this.app.container.withBindings(['Adonis/Core/Server', 'Adonis/Core/HttpContext', 'Adonis/Addons/Session'], (Server, HttpContext, Session) => {
const { defineServerBindings } = require('../src/Bindings/Server');
defineServerBindings(HttpContext, Server, Session);
});
}
boot() {
this.registerServerBindings();
this.registerTestsBindings();
}
}
exports.default = SessionProvider;
SessionProvider.needsApplication = true;
+10
View File
@@ -0,0 +1,10 @@
/// <reference path="../../adonis-typings/index.d.ts" />
/// <reference types="@adonisjs/http-server/build/adonis-typings" />
import { ServerContract } from '@ioc:Adonis/Core/Server';
import { SessionManagerContract } from '@ioc:Adonis/Addons/Session';
import { HttpContextConstructorContract } from '@ioc:Adonis/Core/HttpContext';
/**
* Share "session" with the HTTP context. Define hooks to initiate and
* commit session when sessions are enabled.
*/
export declare function defineServerBindings(HttpContext: HttpContextConstructorContract, Server: ServerContract, Session: SessionManagerContract): void;
+42
View File
@@ -0,0 +1,42 @@
"use strict";
/*
* @adonisjs/session
*
* (c) AdonisJS
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.defineServerBindings = void 0;
/**
* Share "session" with the HTTP context. Define hooks to initiate and
* commit session when sessions are enabled.
*/
function defineServerBindings(HttpContext, Server, Session) {
/**
* Sharing session with the context
*/
HttpContext.getter('session', function session() {
return Session.create(this);
}, true);
/**
* Do not register hooks when sessions are disabled
*/
if (!Session.isEnabled()) {
return;
}
/**
* Initiate session store
*/
Server.hooks.before(async (ctx) => {
await ctx.session.initiate(false);
});
/**
* Commit store mutations
*/
Server.hooks.after(async (ctx) => {
await ctx.session.commit();
});
}
exports.defineServerBindings = defineServerBindings;
+7
View File
@@ -0,0 +1,7 @@
/// <reference path="../../adonis-typings/index.d.ts" />
import { ContainerBindings } from '@ioc:Adonis/Core/Application';
import { SessionManagerContract } from '@ioc:Adonis/Addons/Session';
/**
* Define test bindings
*/
export declare function defineTestsBindings(ApiRequest: ContainerBindings['Japa/Preset/ApiRequest'], ApiResponse: ContainerBindings['Japa/Preset/ApiResponse'], ApiClient: ContainerBindings['Japa/Preset/ApiClient'], SessionManager: SessionManagerContract): void;
+140
View File
@@ -0,0 +1,140 @@
"use strict";
/*
* @adonisjs/session
*
* (c) AdonisJS
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.defineTestsBindings = void 0;
const util_1 = require("util");
/**
* Define test bindings
*/
function defineTestsBindings(ApiRequest, ApiResponse, ApiClient, SessionManager) {
/**
* Set "sessionClient" on the api request
*/
ApiRequest.getter('sessionClient', function () {
return SessionManager.client();
}, true);
/**
* Send session values in the request
*/
ApiRequest.macro('session', function (session) {
if (!this.sessionClient.isEnabled()) {
throw new Error('Cannot set session. Make sure to enable it inside "config/session" file');
}
this.sessionClient.merge(session);
return this;
});
/**
* Send flash messages in the request
*/
ApiRequest.macro('flashMessages', function (messages) {
if (!this.sessionClient.isEnabled()) {
throw new Error('Cannot set flash messages. Make sure to enable the session inside "config/session" file');
}
this.sessionClient.flashMessages.merge(messages);
return this;
});
/**
* Returns reference to the session data from the session
* jar
*/
ApiResponse.macro('session', function () {
return this.sessionJar.session;
});
/**
* Returns reference to the flash messages from the session
* jar
*/
ApiResponse.macro('flashMessages', function () {
return this.sessionJar.flashMessages || {};
});
/**
* Assert response to contain a given session and optionally
* has the expected value
*/
ApiResponse.macro('assertSession', function (name, value) {
this.ensureHasAssert();
this.assert.property(this.session(), name);
if (value !== undefined) {
this.assert.deepEqual(this.session()[name], value);
}
});
/**
* Assert response to not contain a given session
*/
ApiResponse.macro('assertSessionMissing', function (name) {
this.ensureHasAssert();
this.assert.notProperty(this.session(), name);
});
/**
* Assert response to contain a given flash message and optionally
* has the expected value
*/
ApiResponse.macro('assertFlashMessage', function (name, value) {
this.ensureHasAssert();
this.assert.property(this.flashMessages(), name);
if (value !== undefined) {
this.assert.deepEqual(this.flashMessages()[name], value);
}
});
/**
* Assert response to not contain a given session
*/
ApiResponse.macro('assertFlashMissing', function (name) {
this.ensureHasAssert();
this.assert.notProperty(this.flashMessages(), name);
});
/**
* Dump session to the console
*/
ApiResponse.macro('dumpSession', function (options) {
const inspectOptions = { depth: 2, showHidden: false, colors: true, ...options };
console.log(`"session" => ${(0, util_1.inspect)(this.session(), inspectOptions)}`);
console.log(`"flashMessages" => ${(0, util_1.inspect)(this.flashMessages(), inspectOptions)}`);
});
/**
* Adding hooks directly on the request object moves the hooks to
* the end of the queue (basically after the globally hooks)
*/
ApiClient.onRequest((req) => {
/**
* Hook into request and persist session data to be available
* on the server during the request.
*/
req.setup(async (request) => {
/**
* Persist session data and set the session id within the
* cookie
*/
const { cookieName, sessionId } = await request.sessionClient.commit();
request.cookie(cookieName, sessionId);
/**
* Cleanup if request has error. Otherwise the teardown
* hook will clear
*/
return async (error) => {
if (error) {
await request.sessionClient.forget();
}
};
});
/**
* Load messages from the session store and keep a reference to it
* inside the response object.
*
* We also destroy the session after getting a copy of the session
* data
*/
req.teardown(async (response) => {
response.sessionJar = await response.request.sessionClient.load(response.cookies());
await response.request.sessionClient.forget();
});
});
}
exports.defineTestsBindings = defineTestsBindings;
+55
View File
@@ -0,0 +1,55 @@
/// <reference path="../../adonis-typings/index.d.ts" />
/// <reference types="@adonisjs/http-server/build/adonis-typings" />
import { SessionConfig, SessionDriverContract, SessionClientContract } from '@ioc:Adonis/Addons/Session';
import { CookieClientContract } from '@ioc:Adonis/Core/CookieClient';
import { Store } from '../Store';
/**
* SessionClient exposes the API to set session data as a client
*/
export declare class SessionClient extends Store implements SessionClientContract {
private config;
private driver;
private cookieClient;
/**
* Each instance of client works on a single session id. Generate
* multiple client instances for a different session id
*/
private sessionId;
/**
* Session key for setting flash messages
*/
private flashMessagesKey;
/**
* Flash messages store. They are merged with the session data during
* commit
*/
flashMessages: Store;
constructor(config: SessionConfig, driver: SessionDriverContract, cookieClient: CookieClientContract, values: {
[key: string]: any;
} | null);
/**
* Find if the sessions are enabled
*/
isEnabled(): boolean;
/**
* Load session from the driver
*/
load(cookies: Record<string, any>): Promise<{
session: any;
flashMessages: any;
}>;
/**
* Commits the session data to the session store and returns
* the session id and cookie name for it to be accessible
* by the server
*/
commit(): Promise<{
sessionId: string;
signedSessionId: string;
cookieName: string;
}>;
/**
* Clear the session store
*/
forget(): Promise<void>;
}
+93
View File
@@ -0,0 +1,93 @@
"use strict";
/*
* @adonisjs/session
*
* (c) Harminder Virk <virk@adonisjs.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.SessionClient = void 0;
/// <reference path="../../adonis-typings/index.ts" />
const helpers_1 = require("@poppinss/utils/build/helpers");
const Store_1 = require("../Store");
/**
* SessionClient exposes the API to set session data as a client
*/
class SessionClient extends Store_1.Store {
constructor(config, driver, cookieClient, values) {
super(values);
this.config = config;
this.driver = driver;
this.cookieClient = cookieClient;
/**
* Each instance of client works on a single session id. Generate
* multiple client instances for a different session id
*/
this.sessionId = (0, helpers_1.cuid)();
/**
* Session key for setting flash messages
*/
this.flashMessagesKey = '__flash__';
/**
* Flash messages store. They are merged with the session data during
* commit
*/
this.flashMessages = new Store_1.Store({});
}
/**
* Find if the sessions are enabled
*/
isEnabled() {
return this.config.enabled;
}
/**
* Load session from the driver
*/
async load(cookies) {
const sessionIdCookie = cookies[this.config.cookieName];
const sessionId = sessionIdCookie ? sessionIdCookie.value : this.sessionId;
const contents = await this.driver.read(sessionId);
const store = new Store_1.Store(contents);
const flashMessages = store.pull(this.flashMessagesKey, null);
return {
session: store.all(),
flashMessages,
};
}
/**
* Commits the session data to the session store and returns
* the session id and cookie name for it to be accessible
* by the server
*/
async commit() {
this.set(this.flashMessagesKey, this.flashMessages.all());
await this.driver.write(this.sessionId, this.toJSON());
/**
* Clear from the session client memory
*/
this.clear();
this.flashMessages.clear();
return {
sessionId: this.sessionId,
signedSessionId: this.cookieClient.sign(this.config.cookieName, this.sessionId),
cookieName: this.config.cookieName,
};
}
/**
* Clear the session store
*/
async forget() {
/**
* Clear from the session client memory
*/
this.clear();
this.flashMessages.clear();
/**
* Clear with the driver
*/
await this.driver.destroy(this.sessionId);
}
}
exports.SessionClient = SessionClient;
+31
View File
@@ -0,0 +1,31 @@
/// <reference path="../../adonis-typings/session.d.ts" />
import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext';
import { SessionDriverContract, SessionConfig } from '@ioc:Adonis/Addons/Session';
/**
* Cookie driver utilizes the encrypted HTTP cookies to write session value.
*/
export declare class CookieDriver implements SessionDriverContract {
private config;
private ctx;
constructor(config: SessionConfig, ctx: HttpContextContract);
/**
* Read session value from the cookie
*/
read(sessionId: string): {
[key: string]: any;
} | null;
/**
* Write session values to the cookie
*/
write(sessionId: string, values: {
[key: string]: any;
}): void;
/**
* Removes the session cookie
*/
destroy(sessionId: string): void;
/**
* Updates the cookie with existing cookie values
*/
touch(sessionId: string): void;
}
+58
View File
@@ -0,0 +1,58 @@
"use strict";
/*
* @adonisjs/session
*
* (c) Harminder Virk <virk@adonisjs.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.CookieDriver = void 0;
/**
* Cookie driver utilizes the encrypted HTTP cookies to write session value.
*/
class CookieDriver {
constructor(config, ctx) {
this.config = config;
this.ctx = ctx;
}
/**
* Read session value from the cookie
*/
read(sessionId) {
const cookieValue = this.ctx.request.encryptedCookie(sessionId);
if (typeof cookieValue !== 'object') {
return null;
}
return cookieValue;
}
/**
* Write session values to the cookie
*/
write(sessionId, values) {
if (typeof values !== 'object') {
throw new Error('Session cookie driver expects an object of values');
}
this.ctx.response.encryptedCookie(sessionId, values, this.config.cookie);
}
/**
* Removes the session cookie
*/
destroy(sessionId) {
if (this.ctx.request.cookiesList()[sessionId]) {
this.ctx.response.clearCookie(sessionId);
}
}
/**
* Updates the cookie with existing cookie values
*/
touch(sessionId) {
const value = this.read(sessionId);
if (!value) {
return;
}
this.write(sessionId, value);
}
}
exports.CookieDriver = CookieDriver;
+42
View File
@@ -0,0 +1,42 @@
/**
* @adonisjs/session
*
* (c) Harminder Virk <virk@adonisjs.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/// <reference path="../../adonis-typings/index.d.ts" />
import { SessionDriverContract, SessionConfig } from '@ioc:Adonis/Addons/Session';
/**
* File driver to read/write session to filesystem
*/
export declare class FileDriver implements SessionDriverContract {
private config;
constructor(config: SessionConfig);
/**
* Returns complete path to the session file
*/
private getFilePath;
/**
* Returns file contents. A new file will be created if it's
* missing.
*/
read(sessionId: string): Promise<{
[key: string]: any;
} | null>;
/**
* Write session values to a file
*/
write(sessionId: string, values: {
[key: string]: any;
}): Promise<void>;
/**
* Cleanup session file by removing it
*/
destroy(sessionId: string): Promise<void>;
/**
* Writes the value by reading it from the store
*/
touch(sessionId: string): Promise<void>;
}
+80
View File
@@ -0,0 +1,80 @@
"use strict";
/**
* @adonisjs/session
*
* (c) Harminder Virk <virk@adonisjs.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.FileDriver = void 0;
/// <reference path="../../adonis-typings/index.ts" />
const path_1 = require("path");
const utils_1 = require("@poppinss/utils");
const helpers_1 = require("@poppinss/utils/build/helpers");
const fs_extra_1 = require("fs-extra");
/**
* File driver to read/write session to filesystem
*/
class FileDriver {
constructor(config) {
this.config = config;
if (!this.config.file || !this.config.file.location) {
throw new utils_1.Exception('Missing "file.location" for session file driver inside "config/session" file', 500, 'E_INVALID_SESSION_DRIVER_CONFIG');
}
}
/**
* Returns complete path to the session file
*/
getFilePath(sessionId) {
return (0, path_1.join)(this.config.file.location, `${sessionId}.txt`);
}
/**
* Returns file contents. A new file will be created if it's
* missing.
*/
async read(sessionId) {
const filePath = this.getFilePath(sessionId);
await (0, fs_extra_1.ensureFile)(filePath);
const contents = await (0, fs_extra_1.readFile)(filePath, 'utf-8');
if (!contents.trim()) {
return null;
}
/**
* Verify contents with the session id and return them as an object.
*/
const verifiedContents = new helpers_1.MessageBuilder().verify(contents.trim(), sessionId);
if (typeof verifiedContents !== 'object') {
return null;
}
return verifiedContents;
}
/**
* Write session values to a file
*/
async write(sessionId, values) {
if (typeof values !== 'object') {
throw new Error('Session file driver expects an object of values');
}
const message = new helpers_1.MessageBuilder().build(values, undefined, sessionId);
await (0, fs_extra_1.outputFile)(this.getFilePath(sessionId), message);
}
/**
* Cleanup session file by removing it
*/
async destroy(sessionId) {
await (0, fs_extra_1.remove)(this.getFilePath(sessionId));
}
/**
* Writes the value by reading it from the store
*/
async touch(sessionId) {
const value = await this.read(sessionId);
if (!value) {
return;
}
await this.write(sessionId, value);
}
}
exports.FileDriver = FileDriver;
+33
View File
@@ -0,0 +1,33 @@
/**
* @adonisjs/session
*
* (c) Harminder Virk <virk@adonisjs.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/// <reference path="../../adonis-typings/index.d.ts" />
import { SessionDriverContract } from '@ioc:Adonis/Addons/Session';
/**
* Memory driver is meant to be used for writing tests.
*/
export declare class MemoryDriver implements SessionDriverContract {
static sessions: Map<string, Object>;
/**
* Read session id value from the memory
*/
read(sessionId: string): {
[key: string]: any;
} | null;
/**
* Save in memory value for a given session id
*/
write(sessionId: string, values: {
[key: string]: any;
}): void;
/**
* Cleanup for a single session
*/
destroy(sessionId: string): void;
touch(): void;
}
+40
View File
@@ -0,0 +1,40 @@
"use strict";
/**
* @adonisjs/session
*
* (c) Harminder Virk <virk@adonisjs.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.MemoryDriver = void 0;
/**
* Memory driver is meant to be used for writing tests.
*/
class MemoryDriver {
/**
* Read session id value from the memory
*/
read(sessionId) {
return MemoryDriver.sessions.get(sessionId) || null;
}
/**
* Save in memory value for a given session id
*/
write(sessionId, values) {
if (typeof values !== 'object') {
throw new Error('Session memory driver expects an object of values');
}
MemoryDriver.sessions.set(sessionId, values);
}
/**
* Cleanup for a single session
*/
destroy(sessionId) {
MemoryDriver.sessions.delete(sessionId);
}
touch() { }
}
exports.MemoryDriver = MemoryDriver;
MemoryDriver.sessions = new Map();
+46
View File
@@ -0,0 +1,46 @@
/**
* @adonisjs/session
*
* (c) Harminder Virk <virk@adonisjs.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/// <reference path="../../adonis-typings/index.d.ts" />
import { SessionDriverContract, SessionConfig } from '@ioc:Adonis/Addons/Session';
import { RedisManagerContract } from '@ioc:Adonis/Addons/Redis';
/**
* File driver to read/write session to filesystem
*/
export declare class RedisDriver implements SessionDriverContract {
private config;
private redis;
/**
* Convert milliseconds to seconds
*/
private ttl;
constructor(config: SessionConfig, redis: RedisManagerContract);
/**
* Returns instance of the redis connection
*/
private getRedisConnection;
/**
* Returns file contents. A new file will be created if it's
* missing.
*/
read(sessionId: string): Promise<{
[key: string]: any;
} | null>;
/**
* Write session values to a file
*/
write(sessionId: string, values: Object): Promise<void>;
/**
* Cleanup session file by removing it
*/
destroy(sessionId: string): Promise<void>;
/**
* Updates the value expiry
*/
touch(sessionId: string): Promise<void>;
}
+73
View File
@@ -0,0 +1,73 @@
"use strict";
/**
* @adonisjs/session
*
* (c) Harminder Virk <virk@adonisjs.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.RedisDriver = void 0;
/// <reference path="../../adonis-typings/index.ts" />
const utils_1 = require("@poppinss/utils");
const helpers_1 = require("@poppinss/utils/build/helpers");
/**
* File driver to read/write session to filesystem
*/
class RedisDriver {
constructor(config, redis) {
this.config = config;
this.redis = redis;
/**
* Convert milliseconds to seconds
*/
this.ttl = Math.round((typeof this.config.age === 'string' ? helpers_1.string.toMs(this.config.age) : this.config.age) / 1000);
if (!this.config.redisConnection) {
throw new utils_1.Exception('Missing redisConnection for session redis driver inside "config/session" file', 500, 'E_INVALID_SESSION_DRIVER_CONFIG');
}
}
/**
* Returns instance of the redis connection
*/
getRedisConnection() {
return this.redis.connection(this.config.redisConnection);
}
/**
* Returns file contents. A new file will be created if it's
* missing.
*/
async read(sessionId) {
const contents = await this.getRedisConnection().get(sessionId);
if (!contents) {
return null;
}
const verifiedContents = new helpers_1.MessageBuilder().verify(contents, sessionId);
if (typeof verifiedContents !== 'object') {
return null;
}
return verifiedContents;
}
/**
* Write session values to a file
*/
async write(sessionId, values) {
if (typeof values !== 'object') {
throw new Error('Session file driver expects an object of values');
}
await this.getRedisConnection().setex(sessionId, this.ttl, new helpers_1.MessageBuilder().build(values, undefined, sessionId));
}
/**
* Cleanup session file by removing it
*/
async destroy(sessionId) {
await this.getRedisConnection().del(sessionId);
}
/**
* Updates the value expiry
*/
async touch(sessionId) {
await this.getRedisConnection().expire(sessionId, this.ttl);
}
}
exports.RedisDriver = RedisDriver;
+193
View File
@@ -0,0 +1,193 @@
/// <reference path="../../adonis-typings/session.d.ts" />
import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext';
import { SessionConfig, SessionContract, AllowedSessionValues, SessionDriverContract } from '@ioc:Adonis/Addons/Session';
import { Store } from '../Store';
/**
* Session class exposes the API to read/write values to the session for
* a given request.
*/
export declare class Session implements SessionContract {
private ctx;
private config;
private driver;
/**
* Set to true inside the `initiate` method
*/
initiated: boolean;
/**
* A boolean to know if it's a fresh session or not. Fresh
* sessions are those, whose session id is not present
* in cookie
*/
fresh: boolean;
/**
* A boolean to know if store is initiated in readonly mode
* or not. This is done during Websocket requests
*/
readonly: boolean;
/**
* Session id for the given request. A new session id is only
* generated when the cookie for the session id is missing
*/
sessionId: string;
/**
* A copy of previously set flash messages
*/
flashMessages: Store;
/**
* Session id for the current request. It will be different
* from the "this.sessionId" when regenerate is called.
*/
private currentSessionId;
/**
* A instance of store with values read from the driver. The store
* in initiated inside the [[initiate]] method
*/
private store;
/**
* Whether or not to re-generate the session id before comitting
* session values.
*/
private regeneratedSessionId;
/**
* A copy of flash messages. The `input` messages
* are overwritten when any of the input related
* methods are used.
*
* The `others` object is expanded with each call.
*/
responseFlashMessages: Store;
/**
* Session key for setting flash messages
*/
private flashMessagesKey;
constructor(ctx: HttpContextContract, config: SessionConfig, driver: SessionDriverContract);
/**
* Returns a merged copy of flash messages or null
* when nothing is set
*/
private setFlashMessages;
/**
* Returns the existing session id or creates one.
*/
private getSessionId;
/**
* Ensures the session store is initialized
*/
private ensureIsReady;
/**
* Raises exception when session store is in readonly mode
*/
private ensureIsMutable;
/**
* Touches the session cookie
*/
private touchSessionCookie;
/**
* Commits the session value to the store
*/
private commitValuesToStore;
/**
* Touches the driver to make sure the session values doesn't expire
*/
private touchDriver;
/**
* Reading flash messages from the last HTTP request and
* updating the flash messages bag
*/
private readLastRequestFlashMessage;
/**
* Share flash messages & read only session's functions with views
* (only when view property exists)
*/
private shareLocalsWithView;
/**
* Initiating the session by reading it's value from the
* driver and feeding it to a store.
*
* Multiple calls to `initiate` results in a noop.
*/
initiate(readonly: boolean): Promise<void>;
/**
* Re-generates the session id. This can is used to avoid
* session fixation attacks.
*/
regenerate(): void;
/**
* Set/update session value
*/
put(key: string, value: AllowedSessionValues): void;
/**
* Find if the value exists in the session
*/
has(key: string): boolean;
/**
* Get value from the session. The default value is returned
* when actual value is `undefined`
*/
get(key: string, defaultValue?: any): any;
/**
* Returns everything from the session
*/
all(): any;
/**
* Remove value for a given key from the session
*/
forget(key: string): void;
/**
* The method is equivalent to calling `session.get` followed
* by `session.forget`
*/
pull(key: string, defaultValue?: any): any;
/**
* Increment value for a number inside the session store. The
* method raises an error when underlying value is not
* a number
*/
increment(key: string, steps?: number): void;
/**
* Decrement value for a number inside the session store. The
* method raises an error when underlying value is not
* a number
*/
decrement(key: string, steps?: number): void;
/**
* Remove everything from the session
*/
clear(): void;
/**
* Add a new flash message
*/
flash(key: string | {
[key: string]: AllowedSessionValues;
}, value?: AllowedSessionValues): void;
/**
* Flash all form values
*/
flashAll(): void;
/**
* Flash all form values except mentioned keys
*/
flashExcept(keys: string[]): void;
/**
* Flash only defined keys from the form values
*/
flashOnly(keys: string[]): void;
/**
* Reflash existing flash messages
*/
reflash(): void;
/**
* Reflash selected keys from the existing flash messages
*/
reflashOnly(keys: string[]): void;
/**
* Omit selected keys from the existing flash messages
* and flash the rest of values
*/
reflashExcept(keys: string[]): void;
/**
* Writes value to the underlying session driver.
*/
commit(): Promise<void>;
}
+352
View File
@@ -0,0 +1,352 @@
"use strict";
/*
* @adonisjs/session
*
* (c) Harminder Virk <virk@adonisjs.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.Session = void 0;
/// <reference path="../../adonis-typings/session.ts" />
const utils_1 = require("@poppinss/utils");
const helpers_1 = require("@poppinss/utils/build/helpers");
const Store_1 = require("../Store");
/**
* Session class exposes the API to read/write values to the session for
* a given request.
*/
class Session {
constructor(ctx, config, driver) {
this.ctx = ctx;
this.config = config;
this.driver = driver;
/**
* Set to true inside the `initiate` method
*/
this.initiated = false;
/**
* A boolean to know if it's a fresh session or not. Fresh
* sessions are those, whose session id is not present
* in cookie
*/
this.fresh = false;
/**
* A boolean to know if store is initiated in readonly mode
* or not. This is done during Websocket requests
*/
this.readonly = false;
/**
* Session id for the given request. A new session id is only
* generated when the cookie for the session id is missing
*/
this.sessionId = this.getSessionId();
/**
* A copy of previously set flash messages
*/
this.flashMessages = new Store_1.Store({});
/**
* Session id for the current request. It will be different
* from the "this.sessionId" when regenerate is called.
*/
this.currentSessionId = this.sessionId;
/**
* Whether or not to re-generate the session id before comitting
* session values.
*/
this.regeneratedSessionId = false;
/**
* A copy of flash messages. The `input` messages
* are overwritten when any of the input related
* methods are used.
*
* The `others` object is expanded with each call.
*/
this.responseFlashMessages = new Store_1.Store({});
/**
* Session key for setting flash messages
*/
this.flashMessagesKey = '__flash__';
}
/**
* Returns a merged copy of flash messages or null
* when nothing is set
*/
setFlashMessages() {
if (this.responseFlashMessages.isEmpty) {
return;
}
const { input, ...others } = this.responseFlashMessages.all();
this.put(this.flashMessagesKey, { ...input, ...others });
}
/**
* Returns the existing session id or creates one.
*/
getSessionId() {
const sessionId = this.ctx.request.cookie(this.config.cookieName);
if (sessionId) {
this.ctx.logger.trace('existing session found');
return sessionId;
}
this.fresh = true;
this.ctx.logger.trace('generating new session id');
return (0, helpers_1.cuid)();
}
/**
* Ensures the session store is initialized
*/
ensureIsReady() {
if (!this.initiated) {
throw new utils_1.Exception('Session store is not initiated yet. Make sure you are using the session hook', 500, 'E_RUNTIME_EXCEPTION');
}
}
/**
* Raises exception when session store is in readonly mode
*/
ensureIsMutable() {
if (this.readonly) {
throw new utils_1.Exception('Session store is in readonly mode and cannot be mutated', 500, 'E_RUNTIME_EXCEPTION');
}
}
/**
* Touches the session cookie
*/
touchSessionCookie() {
this.ctx.logger.trace('touching session cookie');
this.ctx.response.cookie(this.config.cookieName, this.sessionId, this.config.cookie);
}
/**
* Commits the session value to the store
*/
async commitValuesToStore() {
this.ctx.logger.trace('persist session store with driver');
await this.driver.write(this.sessionId, this.store.toJSON());
}
/**
* Touches the driver to make sure the session values doesn't expire
*/
async touchDriver() {
this.ctx.logger.trace('touch driver for liveliness');
await this.driver.touch(this.sessionId);
}
/**
* Reading flash messages from the last HTTP request and
* updating the flash messages bag
*/
readLastRequestFlashMessage() {
if (this.readonly) {
return;
}
this.flashMessages.update(this.pull(this.flashMessagesKey, null));
}
/**
* Share flash messages & read only session's functions with views
* (only when view property exists)
*/
shareLocalsWithView() {
if (!this.ctx['view'] || typeof this.ctx['view'].share !== 'function') {
return;
}
this.ctx['view'].share({
flashMessages: this.flashMessages,
session: {
get: this.get.bind(this),
has: this.has.bind(this),
all: this.all.bind(this),
},
});
}
/**
* Initiating the session by reading it's value from the
* driver and feeding it to a store.
*
* Multiple calls to `initiate` results in a noop.
*/
async initiate(readonly) {
if (this.initiated) {
return;
}
this.readonly = readonly;
/**
* Profiling the driver read method
*/
await this.ctx.profiler.profileAsync('session:initiate', { driver: this.config.driver }, async () => {
const contents = await this.driver.read(this.sessionId);
this.store = new Store_1.Store(contents);
});
this.initiated = true;
this.readLastRequestFlashMessage();
this.shareLocalsWithView();
}
/**
* Re-generates the session id. This can is used to avoid
* session fixation attacks.
*/
regenerate() {
this.ctx.logger.trace('explicitly re-generating session id');
this.sessionId = (0, helpers_1.cuid)();
this.regeneratedSessionId = true;
}
/**
* Set/update session value
*/
put(key, value) {
this.ensureIsReady();
this.ensureIsMutable();
this.store.set(key, value);
}
/**
* Find if the value exists in the session
*/
has(key) {
this.ensureIsReady();
return this.store.has(key);
}
/**
* Get value from the session. The default value is returned
* when actual value is `undefined`
*/
get(key, defaultValue) {
this.ensureIsReady();
return this.store.get(key, defaultValue);
}
/**
* Returns everything from the session
*/
all() {
this.ensureIsReady();
return this.store.all();
}
/**
* Remove value for a given key from the session
*/
forget(key) {
this.ensureIsReady();
this.ensureIsMutable();
this.store.unset(key);
}
/**
* The method is equivalent to calling `session.get` followed
* by `session.forget`
*/
pull(key, defaultValue) {
this.ensureIsReady();
this.ensureIsMutable();
return this.store.pull(key, defaultValue);
}
/**
* Increment value for a number inside the session store. The
* method raises an error when underlying value is not
* a number
*/
increment(key, steps = 1) {
this.ensureIsReady();
this.ensureIsMutable();
this.store.increment(key, steps);
}
/**
* Decrement value for a number inside the session store. The
* method raises an error when underlying value is not
* a number
*/
decrement(key, steps = 1) {
this.ensureIsReady();
this.ensureIsMutable();
this.store.decrement(key, steps);
}
/**
* Remove everything from the session
*/
clear() {
this.ensureIsReady();
this.ensureIsMutable();
this.store.clear();
}
/**
* Add a new flash message
*/
flash(key, value) {
this.ensureIsReady();
this.ensureIsMutable();
/**
* Update value
*/
if (typeof key === 'string') {
if (value) {
this.responseFlashMessages.set(key, value);
}
}
else {
this.responseFlashMessages.merge(key);
}
}
/**
* Flash all form values
*/
flashAll() {
this.ensureIsReady();
this.ensureIsMutable();
this.responseFlashMessages.set('input', this.ctx.request.original());
}
/**
* Flash all form values except mentioned keys
*/
flashExcept(keys) {
this.ensureIsReady();
this.ensureIsMutable();
this.responseFlashMessages.set('input', utils_1.lodash.omit(this.ctx.request.original(), keys));
}
/**
* Flash only defined keys from the form values
*/
flashOnly(keys) {
this.ensureIsReady();
this.ensureIsMutable();
this.responseFlashMessages.set('input', utils_1.lodash.pick(this.ctx.request.original(), keys));
}
/**
* Reflash existing flash messages
*/
reflash() {
this.flash(this.flashMessages.all());
}
/**
* Reflash selected keys from the existing flash messages
*/
reflashOnly(keys) {
this.flash(utils_1.lodash.pick(this.flashMessages.all(), keys));
}
/**
* Omit selected keys from the existing flash messages
* and flash the rest of values
*/
reflashExcept(keys) {
this.flash(utils_1.lodash.omit(this.flashMessages.all(), keys));
}
/**
* Writes value to the underlying session driver.
*/
async commit() {
await this.ctx.profiler.profileAsync('session:commit', { driver: this.config.driver }, async () => {
if (!this.initiated) {
this.touchSessionCookie();
await this.touchDriver();
return;
}
/**
* Cleanup old session and re-generate new session
*/
if (this.regeneratedSessionId) {
await this.driver.destroy(this.currentSessionId);
}
/**
* Touch the session cookie to keep it alive.
*/
this.touchSessionCookie();
this.setFlashMessages();
await this.commitValuesToStore();
});
}
}
exports.Session = Session;
@@ -0,0 +1,78 @@
/**
* @adonisjs/session
*
* (c) Harminder Virk <virk@adonisjs.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/// <reference types="@adonisjs/application/build/adonis-typings" />
import { ApplicationContract } from '@ioc:Adonis/Core/Application';
import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext';
import { SessionConfig, ExtendCallback, SessionManagerContract, SessionClientContract } from '@ioc:Adonis/Addons/Session';
import { Session } from '../Session';
/**
* Session manager exposes the API to create session instance for a given
* request and also add new drivers.
*/
export declare class SessionManager implements SessionManagerContract {
application: ApplicationContract;
/**
* A private map of drivers added from outside in.
*/
private extendedDrivers;
/**
* Reference to session config
*/
private config;
constructor(application: ApplicationContract, config: SessionConfig);
/**
* Validates the config
*/
private validateConfig;
/**
* Processes the config and decides the `expires` option for the cookie
*/
private processConfig;
/**
* Returns an instance of cookie driver
*/
private createCookieDriver;
/**
* Returns an instance of the memory driver
*/
private createMemoryDriver;
/**
* Returns an instance of file driver
*/
private createFileDriver;
/**
* Returns an instance of redis driver
*/
private createRedisDriver;
/**
* Creates an instance of extended driver
*/
private createExtendedDriver;
/**
* Creates an instance of driver by looking at the config value `driver`.
* An hard exception is raised in case of invalid driver name
*/
private createDriver;
/**
* Find if the sessions are enabled
*/
isEnabled(): boolean;
/**
* Creates an instance of the session client
*/
client(): SessionClientContract;
/**
* Creates a new session instance for a given HTTP request
*/
create(ctx: HttpContextContract): Session;
/**
* Extend the drivers list by adding a new one.
*/
extend(driver: string, callback: ExtendCallback): void;
}
+148
View File
@@ -0,0 +1,148 @@
"use strict";
/**
* @adonisjs/session
*
* (c) Harminder Virk <virk@adonisjs.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.SessionManager = void 0;
const helpers_1 = require("@poppinss/utils/build/helpers");
const utils_1 = require("@poppinss/utils");
const Session_1 = require("../Session");
/**
* Session manager exposes the API to create session instance for a given
* request and also add new drivers.
*/
class SessionManager {
constructor(application, config) {
this.application = application;
/**
* A private map of drivers added from outside in.
*/
this.extendedDrivers = new Map();
this.validateConfig(config);
this.processConfig(config);
}
/**
* Validates the config
*/
validateConfig(config) {
const validator = new utils_1.ManagerConfigValidator(config, 'session', 'config/session');
validator.validateDefault('driver');
}
/**
* Processes the config and decides the `expires` option for the cookie
*/
processConfig(config) {
/**
* Explicitly overwriting `cookie.expires` and `cookie.maxAge` from
* the user defined config
*/
const processedConfig = Object.assign({ enabled: true }, config, {
cookie: {
...config.cookie,
expires: undefined,
maxAge: undefined,
},
});
/**
* Set the max age when `clearWithBrowser = false`. Otherwise cookie
* is a session cookie
*/
if (!processedConfig.clearWithBrowser) {
const age = typeof processedConfig.age === 'string'
? Math.round(helpers_1.string.toMs(processedConfig.age) / 1000)
: processedConfig.age;
processedConfig.cookie.maxAge = age;
}
this.config = processedConfig;
}
/**
* Returns an instance of cookie driver
*/
createCookieDriver(ctx) {
const { CookieDriver } = require('../Drivers/Cookie');
return new CookieDriver(this.config, ctx);
}
/**
* Returns an instance of the memory driver
*/
createMemoryDriver() {
const { MemoryDriver } = require('../Drivers/Memory');
return new MemoryDriver();
}
/**
* Returns an instance of file driver
*/
createFileDriver() {
const { FileDriver } = require('../Drivers/File');
return new FileDriver(this.config);
}
/**
* Returns an instance of redis driver
*/
createRedisDriver() {
const { RedisDriver } = require('../Drivers/Redis');
if (!this.application.container.hasBinding('Adonis/Addons/Redis')) {
throw new Error('Install "@adonisjs/redis" in order to use the redis driver for storing sessions');
}
return new RedisDriver(this.config, this.application.container.use('Adonis/Addons/Redis'));
}
/**
* Creates an instance of extended driver
*/
createExtendedDriver(ctx) {
if (!this.extendedDrivers.has(this.config.driver)) {
throw new utils_1.Exception(`"${this.config.driver}" is not a valid session driver`, 500, 'E_INVALID_SESSION_DRIVER');
}
return this.extendedDrivers.get(this.config.driver)(this, this.config, ctx);
}
/**
* Creates an instance of driver by looking at the config value `driver`.
* An hard exception is raised in case of invalid driver name
*/
createDriver(ctx) {
switch (this.config.driver) {
case 'cookie':
return this.createCookieDriver(ctx);
case 'file':
return this.createFileDriver();
case 'redis':
return this.createRedisDriver();
case 'memory':
return this.createMemoryDriver();
default:
return this.createExtendedDriver(ctx);
}
}
/**
* Find if the sessions are enabled
*/
isEnabled() {
return this.config.enabled;
}
/**
* Creates an instance of the session client
*/
client() {
const { SessionClient } = require('../Client');
const CookieClient = this.application.container.resolveBinding('Adonis/Core/CookieClient');
return new SessionClient(this.config, this.createMemoryDriver(), CookieClient, {});
}
/**
* Creates a new session instance for a given HTTP request
*/
create(ctx) {
return new Session_1.Session(ctx, this.config, this.createDriver(ctx));
}
/**
* Extend the drivers list by adding a new one.
*/
extend(driver, callback) {
this.extendedDrivers.set(driver, callback);
}
}
exports.SessionManager = SessionManager;
+82
View File
@@ -0,0 +1,82 @@
/// <reference path="../../adonis-typings/index.d.ts" />
import { AllowedSessionValues, StoreContract } from '@ioc:Adonis/Addons/Session';
/**
* Session store to mutate and access values from the session object
*/
export declare class Store implements StoreContract {
/**
* Underlying store values
*/
private values;
constructor(values: {
[key: string]: any;
} | null);
/**
* Find if store is empty or not
*/
get isEmpty(): boolean;
/**
* Set key/value pair
*/
set(key: string, value: AllowedSessionValues): void;
/**
* Get value for a given key
*/
get(key: string, defaultValue?: any): any;
/**
* Remove key
*/
unset(key: string): void;
/**
* Reset store by clearing it's values.
*/
clear(): void;
/**
* Pull value from the store. It is same as calling
* store.get and then store.unset
*/
pull(key: string, defaultValue?: any): any;
/**
* Increment number. The method raises an error when
* nderlying value is not a number
*/
increment(key: string, steps?: number): void;
/**
* Increment number. The method raises an error when
* nderlying value is not a number
*/
decrement(key: string, steps?: number): void;
/**
* Overwrite the underlying values object
*/
update(values: {
[key: string]: any;
}): void;
/**
* Update to merge values
*/
merge(values: {
[key: string]: any;
}): any;
/**
* A boolean to know if value exists. Extra guards to check
* arrays for it's length as well.
*/
has(key: string, checkForArraysLength?: boolean): boolean;
/**
* Get all values
*/
all(): any;
/**
* Returns object representation of values
*/
toObject(): any;
/**
* Returns the store values
*/
toJSON(): any;
/**
* Returns string representation of the store
*/
toString(): string;
}
+131
View File
@@ -0,0 +1,131 @@
"use strict";
/*
* @adonisjs/redis
*
* (c) Harminder Virk <virk@adonisjs.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.Store = void 0;
/// <reference path="../../adonis-typings/index.ts" />
const utils_1 = require("@poppinss/utils");
/**
* Session store to mutate and access values from the session object
*/
class Store {
constructor(values) {
this.values = values || {};
}
/**
* Find if store is empty or not
*/
get isEmpty() {
return !this.values || Object.keys(this.values).length === 0;
}
/**
* Set key/value pair
*/
set(key, value) {
utils_1.lodash.set(this.values, key, value);
}
/**
* Get value for a given key
*/
get(key, defaultValue) {
return utils_1.lodash.get(this.values, key, defaultValue);
}
/**
* Remove key
*/
unset(key) {
utils_1.lodash.unset(this.values, key);
}
/**
* Reset store by clearing it's values.
*/
clear() {
this.update({});
}
/**
* Pull value from the store. It is same as calling
* store.get and then store.unset
*/
pull(key, defaultValue) {
return ((value) => {
this.unset(key);
return value;
})(this.get(key, defaultValue));
}
/**
* Increment number. The method raises an error when
* nderlying value is not a number
*/
increment(key, steps = 1) {
const value = this.get(key, 0);
if (typeof value !== 'number') {
throw new utils_1.Exception(`Cannot increment "${key}", since original value is not a number`);
}
this.set(key, value + steps);
}
/**
* Increment number. The method raises an error when
* nderlying value is not a number
*/
decrement(key, steps = 1) {
const value = this.get(key, 0);
if (typeof value !== 'number') {
throw new utils_1.Exception(`Cannot increment "${key}", since original value is not a number`);
}
this.set(key, value - steps);
}
/**
* Overwrite the underlying values object
*/
update(values) {
this.values = values;
}
/**
* Update to merge values
*/
merge(values) {
utils_1.lodash.merge(this.values, values);
}
/**
* A boolean to know if value exists. Extra guards to check
* arrays for it's length as well.
*/
has(key, checkForArraysLength = true) {
const value = this.get(key);
if (!Array.isArray(value)) {
return !!value;
}
return checkForArraysLength ? value.length > 0 : !!value;
}
/**
* Get all values
*/
all() {
return this.values;
}
/**
* Returns object representation of values
*/
toObject() {
return this.all();
}
/**
* Returns the store values
*/
toJSON() {
return this.all();
}
/**
* Returns string representation of the store
*/
toString() {
return JSON.stringify(this.all());
}
}
exports.Store = Store;
+116
View File
@@ -0,0 +1,116 @@
/**
* Config source: https://git.io/JeYHp
*
* Feel free to let us know via PR, if you find something broken in this config
* file.
*/
import Env from '@ioc:Adonis/Core/Env'
import Application from '@ioc:Adonis/Core/Application'
import { sessionConfig } from '@adonisjs/session/build/config'
export default sessionConfig({
/*
|--------------------------------------------------------------------------
| Enable/Disable sessions
|--------------------------------------------------------------------------
|
| Setting the following property to "false" will disable the session for the
| entire application
|
*/
enabled: true,
/*
|--------------------------------------------------------------------------
| Driver
|--------------------------------------------------------------------------
|
| The session driver to use. You can choose between one of the following
| drivers.
|
| - cookie (Uses signed cookies to store session values)
| - file (Uses filesystem to store session values)
| - redis (Uses redis. Make sure to install "@adonisjs/redis" as well)
|
| Note: Switching drivers will make existing sessions invalid.
|
*/
driver: Env.get('SESSION_DRIVER'),
/*
|--------------------------------------------------------------------------
| Cookie name
|--------------------------------------------------------------------------
|
| The name of the cookie that will hold the session id.
|
*/
cookieName: 'adonis-session',
/*
|--------------------------------------------------------------------------
| Clear session when browser closes
|--------------------------------------------------------------------------
|
| Whether or not you want to destroy the session when browser closes. Setting
| this value to `true` will ignore the `age`.
|
*/
clearWithBrowser: false,
/*
|--------------------------------------------------------------------------
| Session age
|--------------------------------------------------------------------------
|
| The duration for which session stays active after no activity. A new HTTP
| request to the server is considered as activity.
|
| The value can be a number in milliseconds or a string that must be valid
| as per https://npmjs.org/package/ms package.
|
| Example: `2 days`, `2.5 hrs`, `1y`, `5s` and so on.
|
*/
age: '2h',
/*
|--------------------------------------------------------------------------
| Cookie values
|--------------------------------------------------------------------------
|
| The cookie settings are used to setup the session id cookie and also the
| driver will use the same values.
|
*/
cookie: {
path: '/',
httpOnly: true,
sameSite: false,
},
/*
|--------------------------------------------------------------------------
| Configuration for the file driver
|--------------------------------------------------------------------------
|
| The file driver needs absolute path to the directory in which sessions
| must be stored.
|
*/
file: {
location: Application.tmpPath('sessions'),
},
/*
|--------------------------------------------------------------------------
| Redis driver
|--------------------------------------------------------------------------
|
| The redis connection you want session driver to use. The same connection
| must be defined inside `config/redis.ts` file as well.
|
*/
redisConnection: 'local',
})
@@ -0,0 +1,9 @@
# The MIT License
Copyright 2021 Harminder Virk, contributors
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
File diff suppressed because it is too large Load Diff
@@ -0,0 +1 @@
export * from './src/Helpers';
@@ -0,0 +1,25 @@
"use strict";
/*
* @poppinss/utils
*
* (c) Harminder Virk <virk@adonisjs.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
__exportStar(require("./src/Helpers"), exports);
@@ -0,0 +1,10 @@
export * as lodash from './src/lodash';
export { slash } from './src/slash';
export { flatten } from './src/flatten';
export { Exception } from './src/Exception';
export { safeParse } from './src/safeParse';
export { esmRequire } from './src/esmRequire';
export { esmResolver } from './src/esmResolver';
export { safeStringify } from './src/safeStringify';
export { defineStaticProperty } from './src/defineStaticProperty';
export { ManagerConfigValidator } from './src/ManagerConfigValidator';
@@ -0,0 +1,53 @@
"use strict";
/*
* @poppinss/utils
*
* (c) Harminder Virk <virk@adonisjs.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ManagerConfigValidator = exports.defineStaticProperty = exports.safeStringify = exports.esmResolver = exports.esmRequire = exports.safeParse = exports.Exception = exports.flatten = exports.slash = exports.lodash = void 0;
exports.lodash = __importStar(require("./src/lodash"));
var slash_1 = require("./src/slash");
Object.defineProperty(exports, "slash", { enumerable: true, get: function () { return slash_1.slash; } });
var flatten_1 = require("./src/flatten");
Object.defineProperty(exports, "flatten", { enumerable: true, get: function () { return flatten_1.flatten; } });
var Exception_1 = require("./src/Exception");
Object.defineProperty(exports, "Exception", { enumerable: true, get: function () { return Exception_1.Exception; } });
var safeParse_1 = require("./src/safeParse");
Object.defineProperty(exports, "safeParse", { enumerable: true, get: function () { return safeParse_1.safeParse; } });
var esmRequire_1 = require("./src/esmRequire");
Object.defineProperty(exports, "esmRequire", { enumerable: true, get: function () { return esmRequire_1.esmRequire; } });
var esmResolver_1 = require("./src/esmResolver");
Object.defineProperty(exports, "esmResolver", { enumerable: true, get: function () { return esmResolver_1.esmResolver; } });
var safeStringify_1 = require("./src/safeStringify");
Object.defineProperty(exports, "safeStringify", { enumerable: true, get: function () { return safeStringify_1.safeStringify; } });
var defineStaticProperty_1 = require("./src/defineStaticProperty");
Object.defineProperty(exports, "defineStaticProperty", { enumerable: true, get: function () { return defineStaticProperty_1.defineStaticProperty; } });
var ManagerConfigValidator_1 = require("./src/ManagerConfigValidator");
Object.defineProperty(exports, "ManagerConfigValidator", { enumerable: true, get: function () { return ManagerConfigValidator_1.ManagerConfigValidator; } });
@@ -0,0 +1,17 @@
/**
* Extended Error object with the option to set error `status` and `code`.
* At AdonisJs, we prefer exceptions with proper error codes to handle
* them without relying on message pattern matching.
*
* ```js
* new Exception('message', 500, 'E_RUNTIME_EXCEPTION')
* ```
*/
export declare class Exception extends Error {
name: string;
message: string;
help?: string;
code?: string;
status: number;
constructor(message: string, status?: number, code?: string);
}
@@ -0,0 +1,68 @@
"use strict";
/*
* @poppinss/utils
*
* (c) Harminder Virk <virk@adonisjs.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.Exception = void 0;
/**
* Extended Error object with the option to set error `status` and `code`.
* At AdonisJs, we prefer exceptions with proper error codes to handle
* them without relying on message pattern matching.
*
* ```js
* new Exception('message', 500, 'E_RUNTIME_EXCEPTION')
* ```
*/
class Exception extends Error {
constructor(message, status = 500, code) {
super(message);
/**
* Set error message
*/
Object.defineProperty(this, 'message', {
configurable: true,
enumerable: false,
value: code ? `${code}: ${message}` : message,
writable: true,
});
/**
* Set error name as a public property
*/
Object.defineProperty(this, 'name', {
configurable: true,
enumerable: false,
value: this.constructor.name,
writable: true,
});
/**
* Set status as a public property
*/
Object.defineProperty(this, 'status', {
configurable: true,
enumerable: false,
value: status,
writable: true,
});
/**
* Set error code as a public property (only when defined)
*/
if (code) {
Object.defineProperty(this, 'code', {
configurable: true,
enumerable: false,
value: code,
writable: true,
});
}
/**
* Update the stack trace
*/
Error.captureStackTrace(this, this.constructor);
}
}
exports.Exception = Exception;
@@ -0,0 +1,28 @@
/**
* Message builder exposes an API to JSON.stringify values by encoding purpose
* and expiryDate inside them. It returns a readable string, which is the
* output of `JSON.stringify`.
*
* Why use this over `JSON.stringify`?
*
* - It protects you from JSON poisioning
* - Allows encoding expiry dates to the message. It means, the message builer is
* helpful, when you want to encode a message and pass it around, but also control
* the TTL of the message
* - Allows encoding purpose. Again, useful for distribution.
*/
export declare class MessageBuilder {
private getExpiryDate;
/**
* Returns a boolean telling, if message has been expired or not
*/
private isExpired;
/**
* Builds a message by encoding expiry and purpose inside it
*/
build(message: any, expiresIn?: string | number, purpose?: string): string;
/**
* Verifies the message for expiry and purpose
*/
verify<T extends any>(message: any, purpose?: string): null | T;
}
@@ -0,0 +1,97 @@
"use strict";
/*
* @adonisjs/encryption
*
* (c) Harminder Virk <virk@adonisjs.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.MessageBuilder = void 0;
const ms_1 = __importDefault(require("ms"));
const safeParse_1 = require("../safeParse");
const safeStringify_1 = require("../safeStringify");
/**
* Message builder exposes an API to JSON.stringify values by encoding purpose
* and expiryDate inside them. It returns a readable string, which is the
* output of `JSON.stringify`.
*
* Why use this over `JSON.stringify`?
*
* - It protects you from JSON poisioning
* - Allows encoding expiry dates to the message. It means, the message builer is
* helpful, when you want to encode a message and pass it around, but also control
* the TTL of the message
* - Allows encoding purpose. Again, useful for distribution.
*/
class MessageBuilder {
getExpiryDate(expiresIn) {
if (!expiresIn) {
return undefined;
}
const expiryMs = typeof expiresIn === 'string' ? (0, ms_1.default)(expiresIn) : expiresIn;
if (expiryMs === undefined || expiryMs === null) {
throw new Error(`Invalid value for expiresIn "${expiresIn}"`);
}
return new Date(Date.now() + expiryMs);
}
/**
* Returns a boolean telling, if message has been expired or not
*/
isExpired(message) {
if (!message.expiryDate) {
return false;
}
try {
const expiryDate = new Date(message.expiryDate);
return isNaN(expiryDate.getTime()) || expiryDate < new Date();
}
catch (error) {
return true;
}
}
/**
* Builds a message by encoding expiry and purpose inside it
*/
build(message, expiresIn, purpose) {
const expiryDate = this.getExpiryDate(expiresIn);
return (0, safeStringify_1.safeStringify)({ message, purpose, expiryDate });
}
/**
* Verifies the message for expiry and purpose
*/
verify(message, purpose) {
const parsed = (0, safeParse_1.safeParse)(message);
/**
* Safe parse returns the value as it is when unable to JSON.parse it. However, in
* our case if value was correctly parsed, it should never match the input
*/
if (parsed === message) {
return null;
}
/**
* Missing ".message" property
*/
if (!parsed.message) {
return null;
}
/**
* Ensure purposes are same.
*/
if (parsed.purpose !== purpose) {
return null;
}
/**
* Ensure isn't expired
*/
if (this.isExpired(parsed)) {
return null;
}
return parsed.message;
}
}
exports.MessageBuilder = MessageBuilder;
@@ -0,0 +1,46 @@
/**
* A simple class to build an object incrementally. It is helpful when you
* want to add properties to the object conditionally.
*
* Instead of writing
* ```
* const obj = {
* ...(user.id ? { id: user.id } : {}),
* ...(user.firstName && user.lastName ? { name: `${user.firstName} ${user.lastName}` } : {}),
* }
* ```
*
* You can write
*
* const obj = new ObjectBuilder()
* .add('id', user.id)
* .add(
* 'fullName',
* user.firstName && user.lastName ? `${user.firstName} ${user.lastName}` : undefined
* )
* .value
*/
export declare class ObjectBuilder {
private ignoreNull?;
value: any;
constructor(ignoreNull?: boolean | undefined);
/**
* Add value to the property.
*
* - Undefined values are ignored
* - Null values are ignored, when `ignoreNull` is set to true
*/
add(key: string, value: any): this;
/**
* Remove value from the object
*/
remove(key: string): this;
/**
* Find if a value exists
*/
has(key: string): boolean;
/**
* Get the existing value
*/
get<T extends any>(key: string): T;
}
@@ -0,0 +1,75 @@
"use strict";
/*
* @poppinss/utils
*
* (c) Harminder Virk <virk@adonisjs.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.ObjectBuilder = void 0;
/**
* A simple class to build an object incrementally. It is helpful when you
* want to add properties to the object conditionally.
*
* Instead of writing
* ```
* const obj = {
* ...(user.id ? { id: user.id } : {}),
* ...(user.firstName && user.lastName ? { name: `${user.firstName} ${user.lastName}` } : {}),
* }
* ```
*
* You can write
*
* const obj = new ObjectBuilder()
* .add('id', user.id)
* .add(
* 'fullName',
* user.firstName && user.lastName ? `${user.firstName} ${user.lastName}` : undefined
* )
* .value
*/
class ObjectBuilder {
constructor(ignoreNull) {
this.ignoreNull = ignoreNull;
this.value = {};
}
/**
* Add value to the property.
*
* - Undefined values are ignored
* - Null values are ignored, when `ignoreNull` is set to true
*/
add(key, value) {
if (value === undefined) {
return this;
}
if (this.ignoreNull === true && value === null) {
return this;
}
this.value[key] = value;
return this;
}
/**
* Remove value from the object
*/
remove(key) {
delete this.value[key];
return this;
}
/**
* Find if a value exists
*/
has(key) {
return this.get(key) !== undefined;
}
/**
* Get the existing value
*/
get(key) {
return this.value[key];
}
}
exports.ObjectBuilder = ObjectBuilder;
@@ -0,0 +1,33 @@
/// <reference types="node" />
/**
* Helper class to base64 encode/decode values with option
* for url encoding and decoding
*/
declare class Base64 {
/**
* Base64 encode Buffer or string
*/
encode(arrayBuffer: ArrayBuffer | SharedArrayBuffer): string;
encode(data: string, encoding?: BufferEncoding): string;
/**
* Base64 decode a previously encoded string or Buffer.
*/
decode(encode: string, encoding: BufferEncoding, strict: true): string | null;
decode(encode: string, encoding: undefined, strict: true): string | null;
decode(encode: string, encoding?: BufferEncoding, strict?: false): string;
decode(encode: Buffer, encoding?: BufferEncoding): string;
/**
* Base64 encode Buffer or string to be URL safe. (RFC 4648)
*/
urlEncode(arrayBuffer: ArrayBuffer | SharedArrayBuffer): string;
urlEncode(data: string, encoding?: BufferEncoding): string;
/**
* Base64 URL decode a previously encoded string or Buffer. (RFC 4648)
*/
urlDecode(encode: string, encoding: BufferEncoding, strict: true): string | null;
urlDecode(encode: string, encoding: undefined, strict: true): string | null;
urlDecode(encode: string, encoding?: BufferEncoding, strict?: false): string;
urlDecode(encode: Buffer, encoding?: BufferEncoding): string;
}
export declare const base64: Base64;
export {};
@@ -0,0 +1,48 @@
"use strict";
/*
* @poppinss/utils
*
* (c) Harminder Virk <virk@adonisjs.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.base64 = void 0;
/**
* Helper class to base64 encode/decode values with option
* for url encoding and decoding
*/
class Base64 {
encode(data, encoding) {
if (typeof data === 'string') {
return Buffer.from(data, encoding).toString('base64');
}
return Buffer.from(data).toString('base64');
}
decode(encoded, encoding = 'utf-8', strict = false) {
if (Buffer.isBuffer(encoded)) {
return encoded.toString(encoding);
}
const decoded = Buffer.from(encoded, 'base64').toString(encoding);
if (strict && this.encode(decoded, encoding) !== encoded) {
return null;
}
return decoded;
}
urlEncode(data, encoding) {
const encoded = typeof data === 'string' ? this.encode(data, encoding) : this.encode(data);
return encoded.replace(/\+/g, '-').replace(/\//g, '_').replace(/\=/g, '');
}
urlDecode(encoded, encoding = 'utf-8', strict = false) {
if (Buffer.isBuffer(encoded)) {
return encoded.toString(encoding);
}
const decoded = Buffer.from(encoded, 'base64').toString(encoding);
if (strict && this.urlEncode(decoded, encoding) !== encoded) {
return null;
}
return decoded;
}
}
exports.base64 = new Base64();
@@ -0,0 +1,21 @@
declare type Constructor = new (...args: any[]) => any;
/**
* Converting unions to intersection
*/
declare type UnionToIntersection<T> = (T extends any ? (x: T) => any : never) extends (x: infer R) => any ? R : never;
/**
* Normalizes constructor to work with mixins. There is an open bug for mixins
* to allow constructors other than `...args: any[]`
*
* https://github.com/microsoft/TypeScript/issues/37142
*/
export declare type NormalizeConstructor<T extends Constructor> = {
new (...args: any[]): InstanceType<T>;
} & Omit<T, 'constructor'>;
/**
* Compose a class by applying mixins to it.
* The code is inspired by https://justinfagnani.com/2015/12/21/real-mixins-with-javascript-classes/, its
* just that I have added the support for static types too.
*/
export declare const compose: <SuperClass extends Constructor, M extends ((superclass: SuperClass) => Constructor)[]>(superclass: SuperClass, ...mixins: M) => SuperClass & UnionToIntersection<ReturnType<M[number]>>;
export {};
@@ -0,0 +1,20 @@
"use strict";
/*
* @poppinss/utils
*
* (c) Harminder Virk <virk@adonisjs.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.compose = void 0;
/**
* Compose a class by applying mixins to it.
* The code is inspired by https://justinfagnani.com/2015/12/21/real-mixins-with-javascript-classes/, its
* just that I have added the support for static types too.
*/
const compose = (superclass, ...mixins) => {
return mixins.reduce((c, mixin) => mixin(c), superclass);
};
exports.compose = compose;
@@ -0,0 +1,4 @@
/**
* Returns an array of file paths from the given location.
*/
export declare function fsReadAll(location: string, callback?: (file: string) => boolean): string[];
@@ -0,0 +1,23 @@
"use strict";
/*
* @poppinss/utils
*
* (c) Harminder Virk <virk@adonisjs.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.fsReadAll = void 0;
const fs_readdir_recursive_1 = __importDefault(require("fs-readdir-recursive"));
const isScriptFile_1 = require("../isScriptFile");
/**
* Returns an array of file paths from the given location.
*/
function fsReadAll(location, callback) {
return (0, fs_readdir_recursive_1.default)(location).filter(typeof callback === 'function' ? callback : isScriptFile_1.isScriptFile);
}
exports.fsReadAll = fsReadAll;
@@ -0,0 +1,14 @@
export { default as cuid } from 'cuid';
export * as file from '@poppinss/file-generator';
export { base64 } from './base64';
export { compose, NormalizeConstructor } from './compose';
export { fsReadAll } from './fsReadAll';
export { interpolate } from './interpolate';
export { MessageBuilder } from './MessageBuilder';
export { ObjectBuilder } from './ObjectBuilder';
export { requireAll } from './requireAll';
export { resolveDir } from './resolveDir';
export { resolveFrom } from './resolveFrom';
export { safeEqual } from './safeEqual';
export * as string from './string';
export * as types from './types';
@@ -0,0 +1,62 @@
"use strict";
/*
* @poppinss/utils
*
* (c) Harminder Virk <virk@adonisjs.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.types = exports.string = exports.safeEqual = exports.resolveFrom = exports.resolveDir = exports.requireAll = exports.ObjectBuilder = exports.MessageBuilder = exports.interpolate = exports.fsReadAll = exports.compose = exports.base64 = exports.file = exports.cuid = void 0;
var cuid_1 = require("cuid");
Object.defineProperty(exports, "cuid", { enumerable: true, get: function () { return __importDefault(cuid_1).default; } });
exports.file = __importStar(require("@poppinss/file-generator"));
var base64_1 = require("./base64");
Object.defineProperty(exports, "base64", { enumerable: true, get: function () { return base64_1.base64; } });
var compose_1 = require("./compose");
Object.defineProperty(exports, "compose", { enumerable: true, get: function () { return compose_1.compose; } });
var fsReadAll_1 = require("./fsReadAll");
Object.defineProperty(exports, "fsReadAll", { enumerable: true, get: function () { return fsReadAll_1.fsReadAll; } });
var interpolate_1 = require("./interpolate");
Object.defineProperty(exports, "interpolate", { enumerable: true, get: function () { return interpolate_1.interpolate; } });
var MessageBuilder_1 = require("./MessageBuilder");
Object.defineProperty(exports, "MessageBuilder", { enumerable: true, get: function () { return MessageBuilder_1.MessageBuilder; } });
var ObjectBuilder_1 = require("./ObjectBuilder");
Object.defineProperty(exports, "ObjectBuilder", { enumerable: true, get: function () { return ObjectBuilder_1.ObjectBuilder; } });
var requireAll_1 = require("./requireAll");
Object.defineProperty(exports, "requireAll", { enumerable: true, get: function () { return requireAll_1.requireAll; } });
var resolveDir_1 = require("./resolveDir");
Object.defineProperty(exports, "resolveDir", { enumerable: true, get: function () { return resolveDir_1.resolveDir; } });
var resolveFrom_1 = require("./resolveFrom");
Object.defineProperty(exports, "resolveFrom", { enumerable: true, get: function () { return resolveFrom_1.resolveFrom; } });
var safeEqual_1 = require("./safeEqual");
Object.defineProperty(exports, "safeEqual", { enumerable: true, get: function () { return safeEqual_1.safeEqual; } });
exports.string = __importStar(require("./string"));
exports.types = __importStar(require("./types"));
@@ -0,0 +1,7 @@
/**
* A simple function interpolate values inside curly braces.
*
* @example
* `interpolate('hello {{ username }}', { username: 'virk' })`
*/
export declare function interpolate(input: string, data: any): string;
@@ -0,0 +1,46 @@
"use strict";
/*
* @poppinss/utils
*
* (c) Harminder Virk <virk@adonisjs.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.interpolate = void 0;
function uncurryThis(fn) {
return function (...args) {
return Function.call.apply(fn, args);
};
}
const hasOwnProperty = uncurryThis(Object.prototype.hasOwnProperty);
/**
* Parses prop
*/
function parseProp(data, key) {
const tokens = key.split('.');
while (tokens.length) {
if (data === null || typeof data !== 'object') {
return;
}
const token = tokens.shift();
data = hasOwnProperty(data, token) ? data[token] : undefined;
}
return data;
}
/**
* A simple function interpolate values inside curly braces.
*
* @example
* `interpolate('hello {{ username }}', { username: 'virk' })`
*/
function interpolate(input, data) {
return input.replace(/(\\)?{{(.*?)}}/g, (_, escapeChar, key) => {
if (escapeChar) {
return `{{${key}}}`;
}
return parseProp(data, key.trim());
});
}
exports.interpolate = interpolate;
@@ -0,0 +1,8 @@
/**
* Require all files from a given directory. The method automatically looks
* for files ending with `.ts`, `.js` and `.json`. Also files ending with
* `.d.ts` are ignored.
*/
export declare function requireAll(location: string, recursive?: boolean, optional?: boolean, filter?: (file: string) => boolean | string): {
[key: string]: any;
} | undefined;
@@ -0,0 +1,65 @@
"use strict";
/*
* @poppinss/utils
*
* (c) Harminder Virk <virk@adonisjs.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.requireAll = void 0;
const path_1 = require("path");
const require_all_1 = __importDefault(require("require-all"));
const esmResolver_1 = require("../esmResolver");
const isScriptFile_1 = require("../isScriptFile");
/**
* Function to filter and keep script files only
*/
function fileFilter(file) {
return (0, isScriptFile_1.isScriptFile)(file);
}
/**
* Require all files from a given directory. The method automatically looks
* for files ending with `.ts`, `.js` and `.json`. Also files ending with
* `.d.ts` are ignored.
*/
function requireAll(location, recursive = true, optional = false, filter = fileFilter) {
try {
return (0, require_all_1.default)({
dirname: location,
recursive,
filter: (file) => {
let result = true;
/**
* Invoke user defined function
*/
if (typeof filter === 'function') {
result = filter(file);
}
/**
* Use the default file name when file is meant to
* be kept
*/
if (result === true) {
const ext = (0, path_1.extname)(file);
return file.replace(new RegExp(`${ext}$`), '');
}
return result;
},
resolve: esmResolver_1.esmResolver,
});
}
catch (error) {
if (error.code === 'ENOENT' && optional) {
return;
}
else {
throw error;
}
}
}
exports.requireAll = requireAll;
@@ -0,0 +1,5 @@
/**
* Resolves path to a given directory. The method is similar to `require.resolve`,
* but also works for directories with no `index.js` file.
*/
export declare function resolveDir(fromLocation: string, dirPath: string): string;
@@ -0,0 +1,46 @@
"use strict";
/*
* @poppinss/utils
*
* (c) Harminder Virk <virk@adonisjs.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.resolveDir = void 0;
const resolve_from_1 = __importDefault(require("resolve-from"));
const path_1 = require("path");
/**
* Resolves path to a given directory. The method is similar to `require.resolve`,
* but also works for directories with no `index.js` file.
*/
function resolveDir(fromLocation, dirPath) {
if ((0, path_1.isAbsolute)(dirPath)) {
return dirPath;
}
/**
* Relative paths are made by joining the baseDir
*/
if (dirPath.startsWith('./') || dirPath.startsWith(`.${path_1.sep}`)) {
return (0, path_1.join)(fromLocation, dirPath);
}
/**
* From here on, we are dealing with a package inside node module.
*/
let packageName = '';
const tokens = dirPath.replace(/\\/g, '/').split('/');
if (tokens.length && tokens[0].startsWith('@')) {
packageName = `${tokens.shift()}/`;
}
packageName += tokens.shift();
const resolved = resolve_from_1.default.silent(fromLocation, (0, path_1.join)(packageName, 'package.json'));
if (!resolved) {
throw new Error(`Cannot locate directory "${dirPath}"`);
}
return (0, path_1.join)((0, path_1.dirname)(resolved), tokens.join('/'));
}
exports.resolveDir = resolveDir;
@@ -0,0 +1,5 @@
/**
* Resolves module from a given directory. It is similar to `require.resolve`
* but carefull handles the absolute paths.
*/
export declare function resolveFrom(fromLocation: string, modulePath: string): string;
@@ -0,0 +1,27 @@
"use strict";
/*
* @poppinss/utils
*
* (c) Harminder Virk <virk@adonisjs.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.resolveFrom = void 0;
const path_1 = require("path");
const resolve_from_1 = __importDefault(require("resolve-from"));
/**
* Resolves module from a given directory. It is similar to `require.resolve`
* but carefull handles the absolute paths.
*/
function resolveFrom(fromLocation, modulePath) {
if ((0, path_1.isAbsolute)(modulePath)) {
return modulePath;
}
return (0, resolve_from_1.default)(fromLocation, modulePath);
}
exports.resolveFrom = resolveFrom;
@@ -0,0 +1,10 @@
declare type BufferSafeValue = ArrayBuffer | SharedArrayBuffer | number[] | string | {
valueOf(): string | object;
} | {
[Symbol.toPrimitive](hint: 'string'): string;
};
/**
* Generates a random string for a given size
*/
export declare function safeEqual<T extends BufferSafeValue>(value: T, comparisonValue: T): boolean;
export {};
@@ -0,0 +1,42 @@
"use strict";
/*
* @poppinss/utils
*
* (c) Harminder Virk <virk@adonisjs.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.safeEqual = void 0;
const buffer_1 = require("buffer");
const crypto_1 = require("crypto");
/**
* Generates a random string for a given size
*/
function safeEqual(value, comparisonValue) {
if (typeof value === 'string' && typeof comparisonValue === 'string') {
/**
* The length of the main value to ensure that we compare equal strings
* against each other to get a constant time.
*/
const expectedLength = buffer_1.Buffer.byteLength(value);
/**
* Value A
*/
const valueBuffer = buffer_1.Buffer.alloc(expectedLength, 0, 'utf-8');
valueBuffer.write(value);
/**
* Value B
*/
const comparisonValueBuffer = buffer_1.Buffer.alloc(expectedLength, 0, 'utf-8');
comparisonValueBuffer.write(comparisonValue);
/**
* Ensure values are same and also have same length
*/
return ((0, crypto_1.timingSafeEqual)(valueBuffer, comparisonValueBuffer) &&
expectedLength === buffer_1.Buffer.byteLength(comparisonValue));
}
return (0, crypto_1.timingSafeEqual)(buffer_1.Buffer.from(value), buffer_1.Buffer.from(comparisonValue));
}
exports.safeEqual = safeEqual;
@@ -0,0 +1,124 @@
import { EncodeOptions } from 'he';
import { BytesOptions } from 'bytes';
export { default as toSlug } from 'slugify';
/**
* The method is a copy/paste from the "title-case" package. They have
* a dependency on "tslib", which I don't want.
*/
export declare function titleCase(input: string): string;
/**
* Define an irregular rule
*/
export declare function defineIrregularRule(singleValue: string, pluralValue: string): void;
/**
* Define uncountable rule
*/
export declare function defineUncountableRule(word: string): void;
/**
* Convert string to camelcase
*/
export declare function camelCase(value: string): string;
/**
* Convert string to snakecase
*/
export declare function snakeCase(value: string): string;
/**
* Convert string to dashcase
*/
export declare function dashCase(value: string, options?: {
capitalize?: boolean;
}): string;
/**
* Convert string to pascal case
*/
export declare function pascalCase(value: string): string;
/**
* Convert string to capital case
*/
export declare function capitalCase(value: string): string;
/**
* Convert string to sentence case
*/
export declare function sentenceCase(value: string): string;
/**
* Convert string to dot case
*/
export declare function dotCase(value: string): string;
/**
* Remove all sort of casing from the string
*/
export declare function noCase(value: string): string;
/**
* Pluralize a word
*/
export declare function pluralize(word: string): string;
/**
* Singularize a word
*/
export declare function singularize(word: string): string;
/**
* Truncate a sentence till a give limit of characters
*/
export declare function truncate(sentence: string, charactersLimit: number, options?: {
completeWords?: boolean;
suffix?: string;
}): string;
/**
* Same as truncate, but strips out the HTML
*/
export declare function excerpt(sentence: string, charactersLimit: number, options?: {
completeWords?: boolean;
suffix?: string;
}): string;
/**
* Condenses multiple whitespaces from a string
*/
export declare function condenseWhitespace(value: string): string;
/**
* Escape HTML entities
*/
export declare function escapeHTML(value: string, options?: {
encodeSymbols?: boolean;
}): string;
/**
* Encode symbols that arent printable ASCII symbols
*/
export declare function encodeSymbols(value: string, options?: EncodeOptions): string;
/**
* Convert array of values to a sentence
*/
export declare function toSentence(values: any[], options?: {
separator?: string;
pairSeparator?: string;
lastSeparator?: string;
}): string;
/**
* Convert a number to a human readable string
*/
export declare function prettyBytes(value: number, options?: BytesOptions): string;
/**
* Convert milliseconds to a human readable string
*/
export declare function prettyMs(value: number, options?: {
long: boolean;
}): string;
/**
* Find if a string is empty. Including any number of whitespaces
*/
export declare function isEmpty(value: string): boolean;
/**
* Ordinalize a give number or string
*/
export declare function ordinalize(value: string | number): string;
/**
* Converts unit expression to bytes
*/
export declare function toBytes(value: string | number): number;
/**
* Converts time expression to milliseconds
*/
export declare function toMs(value: string | number): number;
/**
* Generates a random string for a given size
*/
export declare function generateRandom(size: number): string;
@@ -0,0 +1,328 @@
"use strict";
/*
* @poppinss/utils
*
* (c) Harminder Virk <virk@adonisjs.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateRandom = exports.toMs = exports.toBytes = exports.ordinalize = exports.isEmpty = exports.prettyMs = exports.prettyBytes = exports.toSentence = exports.encodeSymbols = exports.escapeHTML = exports.condenseWhitespace = exports.excerpt = exports.truncate = exports.singularize = exports.pluralize = exports.noCase = exports.dotCase = exports.sentenceCase = exports.capitalCase = exports.pascalCase = exports.dashCase = exports.snakeCase = exports.camelCase = exports.defineUncountableRule = exports.defineIrregularRule = exports.titleCase = exports.toSlug = void 0;
const ms_1 = __importDefault(require("ms"));
const truncatise_1 = __importDefault(require("truncatise"));
const crypto_1 = require("crypto");
const he_1 = __importDefault(require("he"));
const changeCase = __importStar(require("change-case"));
const bytes_1 = __importDefault(require("bytes"));
const pluralize_1 = require("pluralize");
var slugify_1 = require("slugify");
Object.defineProperty(exports, "toSlug", { enumerable: true, get: function () { return __importDefault(slugify_1).default; } });
const SMALL_WORDS = /\b(?:an?d?|a[st]|because|but|by|en|for|i[fn]|neither|nor|o[fnr]|only|over|per|so|some|tha[tn]|the|to|up|upon|vs?\.?|versus|via|when|with|without|yet)\b/i;
const TOKENS = /[^\s:–—-]+|./g;
const WHITESPACE = /\s/;
const IS_MANUAL_CASE = /.(?=[A-Z]|\..)/;
const ALPHANUMERIC_PATTERN = /[A-Za-z0-9\u00C0-\u00FF]/;
/**
* The method is a copy/paste from the "title-case" package. They have
* a dependency on "tslib", which I don't want.
*/
function titleCase(input) {
let output = '';
let result;
while ((result = TOKENS.exec(input)) !== null) {
const { 0: token, index } = result;
if (!IS_MANUAL_CASE.test(token) &&
(!SMALL_WORDS.test(token) || index === 0 || index + token.length === input.length) &&
(input.charAt(index + token.length) !== ':' ||
WHITESPACE.test(input.charAt(index + token.length + 1)))) {
output += token.replace(ALPHANUMERIC_PATTERN, (char) => char.toUpperCase());
continue;
}
output += token;
}
return output;
}
exports.titleCase = titleCase;
/**
* Normalizes base64 string by removing special chars and padding
*/
function normalizeBase64(value) {
return value.replace(/\+/g, '-').replace(/\//g, '_').replace(/\=/g, '');
}
/**
* Define an irregular rule
*/
function defineIrregularRule(singleValue, pluralValue) {
(0, pluralize_1.addIrregularRule)(singleValue, pluralValue);
}
exports.defineIrregularRule = defineIrregularRule;
/**
* Define uncountable rule
*/
function defineUncountableRule(word) {
(0, pluralize_1.addUncountableRule)(word);
}
exports.defineUncountableRule = defineUncountableRule;
/**
* Convert string to camelcase
*/
function camelCase(value) {
return changeCase.camelCase(value);
}
exports.camelCase = camelCase;
/**
* Convert string to snakecase
*/
function snakeCase(value) {
return changeCase.snakeCase(value);
}
exports.snakeCase = snakeCase;
/**
* Convert string to dashcase
*/
function dashCase(value, options) {
if (options && options.capitalize) {
return changeCase.headerCase(value);
}
return changeCase.paramCase(value);
}
exports.dashCase = dashCase;
/**
* Convert string to pascal case
*/
function pascalCase(value) {
return changeCase.pascalCase(value);
}
exports.pascalCase = pascalCase;
/**
* Convert string to capital case
*/
function capitalCase(value) {
return changeCase.capitalCase(value);
}
exports.capitalCase = capitalCase;
/**
* Convert string to sentence case
*/
function sentenceCase(value) {
return changeCase.sentenceCase(value);
}
exports.sentenceCase = sentenceCase;
/**
* Convert string to dot case
*/
function dotCase(value) {
return changeCase.dotCase(value);
}
exports.dotCase = dotCase;
/**
* Remove all sort of casing from the string
*/
function noCase(value) {
return changeCase.noCase(value);
}
exports.noCase = noCase;
/**
* Pluralize a word
*/
function pluralize(word) {
return (0, pluralize_1.plural)(word);
}
exports.pluralize = pluralize;
/**
* Singularize a word
*/
function singularize(word) {
return (0, pluralize_1.singular)(word);
}
exports.singularize = singularize;
/**
* Truncate a sentence till a give limit of characters
*/
function truncate(sentence, charactersLimit, options) {
return (0, truncatise_1.default)(sentence, {
TruncateLength: charactersLimit,
/**
* Do not complete words when "completeWords" is not explicitly set
* to true
*/
Strict: options && options.completeWords === true ? false : true,
StripHTML: false,
TruncateBy: 'characters',
Suffix: options && options.suffix,
});
}
exports.truncate = truncate;
/**
* Same as truncate, but strips out the HTML
*/
function excerpt(sentence, charactersLimit, options) {
return (0, truncatise_1.default)(sentence, {
TruncateLength: charactersLimit,
/**
* Do not complete words when "completeWords" is not explicitly set
* to true
*/
Strict: options && options.completeWords === true ? false : true,
StripHTML: true,
TruncateBy: 'characters',
Suffix: options && options.suffix,
});
}
exports.excerpt = excerpt;
/**
* Condenses multiple whitespaces from a string
*/
function condenseWhitespace(value) {
return value.trim().replace(/\s{2,}/g, ' ');
}
exports.condenseWhitespace = condenseWhitespace;
/**
* Escape HTML entities
*/
function escapeHTML(value, options) {
value = he_1.default.escape(value);
if (options && options.encodeSymbols) {
value = encodeSymbols(value, { allowUnsafeSymbols: true });
}
return value;
}
exports.escapeHTML = escapeHTML;
/**
* Encode symbols that arent printable ASCII symbols
*/
function encodeSymbols(value, options) {
return he_1.default.encode(value, options);
}
exports.encodeSymbols = encodeSymbols;
/**
* Convert array of values to a sentence
*/
function toSentence(values, options) {
/**
* Empty array
*/
if (values.length === 0) {
return '';
}
/**
* Just one item
*/
if (values.length === 1) {
return values[0];
}
/**
* Giving some love to two items, so that one can use oxford comma's
*/
if (values.length === 2) {
return `${values[0]}${options?.pairSeparator || ' and '}${values[1]}`;
}
const normalized = Object.assign({ separator: ', ', lastSeparator: ', and ' }, options);
/**
* Make sentence
*/
return `${values.slice(0, -1).join(normalized.separator)}${normalized.lastSeparator}${values[values.length - 1]}`;
}
exports.toSentence = toSentence;
/**
* Convert a number to a human readable string
*/
function prettyBytes(value, options) {
return bytes_1.default.format(value, options);
}
exports.prettyBytes = prettyBytes;
/**
* Convert milliseconds to a human readable string
*/
function prettyMs(value, options) {
return (0, ms_1.default)(value, options);
}
exports.prettyMs = prettyMs;
/**
* Find if a string is empty. Including any number of whitespaces
*/
function isEmpty(value) {
return value.trim().length === 0;
}
exports.isEmpty = isEmpty;
/**
* Ordinalize a give number or string
*/
function ordinalize(value) {
const transformedValue = Math.abs(typeof value === 'string' ? parseInt(value) : value);
if (!Number.isFinite(transformedValue) || Number.isNaN(transformedValue)) {
throw new Error('Cannot ordinalize NAN or infinite numbers');
}
const percent = transformedValue % 100;
if (percent >= 10 && percent <= 20) {
return `${value}th`;
}
const decimal = transformedValue % 10;
switch (decimal) {
case 1:
return `${value}st`;
case 2:
return `${value}nd`;
case 3:
return `${value}rd`;
default:
return `${value}th`;
}
}
exports.ordinalize = ordinalize;
/**
* Converts unit expression to bytes
*/
function toBytes(value) {
if (typeof value === 'number') {
return value;
}
return bytes_1.default.parse(value);
}
exports.toBytes = toBytes;
/**
* Converts time expression to milliseconds
*/
function toMs(value) {
if (typeof value === 'number') {
return value;
}
return (0, ms_1.default)(value);
}
exports.toMs = toMs;
/**
* Generates a random string for a given size
*/
function generateRandom(size) {
const bits = (size + 1) * 6;
const buffer = (0, crypto_1.randomBytes)(Math.ceil(bits / 8));
return normalizeBase64(buffer.toString('base64')).slice(0, size);
}
exports.generateRandom = generateRandom;
@@ -0,0 +1,86 @@
/// <reference types="node" />
/**
* Lookup the type for a given value
*/
export declare function lookup(value: any): 'undefined' | 'null' | 'boolean' | 'buffer' | 'number' | 'string' | 'arguments' | 'object' | 'date' | 'array' | 'regexp' | 'error' | 'function' | 'class' | 'generatorfunction' | 'symbol' | 'map' | 'weakmap' | 'set' | 'weakset' | 'int8array' | 'uint8array' | 'uint8clampedarray' | 'int16array' | 'uint16array' | 'int32array' | 'uint32array' | 'float32array' | 'float64array';
/**
* Find if a given value is undefined
*/
export declare function isUndefined(value: any): value is undefined;
/**
* Find if a given value is null
*/
export declare function isNull(value: any): value is null;
/**
* Find if a given value is a boolean
*/
export declare function isBoolean(value: any): value is boolean;
/**
* Find if a given value is a buffer
*/
export declare function isBuffer(value: any): value is Buffer;
/**
* Find if a given value is a number
*/
export declare function isNumber(value: any): value is number;
/**
* Find if a given value is a string
*/
export declare function isString(value: any): value is string;
/**
* Find if a given value is function arguments
*/
export declare function isArguments(value: any): boolean;
/**
* Find if a given value is a plain object
*/
export declare function isObject(value: any): boolean;
/**
* Find if a given value is a date instance
*/
export declare function isDate(value: any): value is Date;
/**
* Find if a given value is an array
*/
export declare function isArray(value: any): value is any[];
/**
* Find if a given value is an regularExpression
*/
export declare function isRegexp(value: any): value is RegExp;
/**
* Find if a given value is an instance of Error class
*/
export declare function isError(value: any): boolean;
/**
* Find if a given value is a Function
*/
export declare function isFunction(value: any): value is Function;
/**
* Find if a given value is a class. Uses regular expression, since there
* is no way to natively distinguish a class and a function in Javascript
*/
export declare function isClass(value: any): boolean;
/**
* Find if a value is an integer or not
*/
export declare function isInteger(value: number): value is number;
/**
* Find if a value is float value or not. The values with more than
* zero remainder returns true
*/
export declare function isFloat(value: number): value is number;
/**
* Find if the value has given decimal place or not.
*
* Since there is no direct way in Javascript to check for decimal place. We make
* use of regex to find it out.
*
* Numeric values are converted to string by calling `value.toString()` before
* testing it against the regex.
*
* If this method returns `true`, then you can safely parse the string with `parseFloat`
* method.
*/
export declare function isDecimal(value: string | number, options?: {
decimalPlaces?: string;
}): boolean;
@@ -0,0 +1,161 @@
"use strict";
/*
* @poppinss/utils
*
* (c) Harminder Virk <virk@adonisjs.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.isDecimal = exports.isFloat = exports.isInteger = exports.isClass = exports.isFunction = exports.isError = exports.isRegexp = exports.isArray = exports.isDate = exports.isObject = exports.isArguments = exports.isString = exports.isNumber = exports.isBuffer = exports.isBoolean = exports.isNull = exports.isUndefined = exports.lookup = void 0;
const kind_of_1 = __importDefault(require("kind-of"));
const toString = Function.prototype.toString;
/**
* Lookup the type for a given value
*/
function lookup(value) {
const kind = (0, kind_of_1.default)(value);
if (kind === 'function' && /^class\s/.test(toString.call(value))) {
return 'class';
}
return kind;
}
exports.lookup = lookup;
/**
* Find if a given value is undefined
*/
function isUndefined(value) {
return lookup(value) === 'undefined';
}
exports.isUndefined = isUndefined;
/**
* Find if a given value is null
*/
function isNull(value) {
return lookup(value) === 'null';
}
exports.isNull = isNull;
/**
* Find if a given value is a boolean
*/
function isBoolean(value) {
return lookup(value) === 'boolean';
}
exports.isBoolean = isBoolean;
/**
* Find if a given value is a buffer
*/
function isBuffer(value) {
return lookup(value) === 'buffer';
}
exports.isBuffer = isBuffer;
/**
* Find if a given value is a number
*/
function isNumber(value) {
return lookup(value) === 'number';
}
exports.isNumber = isNumber;
/**
* Find if a given value is a string
*/
function isString(value) {
return lookup(value) === 'string';
}
exports.isString = isString;
/**
* Find if a given value is function arguments
*/
function isArguments(value) {
return lookup(value) === 'arguments';
}
exports.isArguments = isArguments;
/**
* Find if a given value is a plain object
*/
function isObject(value) {
return lookup(value) === 'object';
}
exports.isObject = isObject;
/**
* Find if a given value is a date instance
*/
function isDate(value) {
return lookup(value) === 'date';
}
exports.isDate = isDate;
/**
* Find if a given value is an array
*/
function isArray(value) {
return lookup(value) === 'array';
}
exports.isArray = isArray;
/**
* Find if a given value is an regularExpression
*/
function isRegexp(value) {
return lookup(value) === 'regexp';
}
exports.isRegexp = isRegexp;
/**
* Find if a given value is an instance of Error class
*/
function isError(value) {
return lookup(value) === 'error';
}
exports.isError = isError;
/**
* Find if a given value is a Function
*/
function isFunction(value) {
return lookup(value) === 'function';
}
exports.isFunction = isFunction;
/**
* Find if a given value is a class. Uses regular expression, since there
* is no way to natively distinguish a class and a function in Javascript
*/
function isClass(value) {
return lookup(value) === 'class';
}
exports.isClass = isClass;
/**
* Find if a value is an integer or not
*/
function isInteger(value) {
return Number.isInteger(value);
}
exports.isInteger = isInteger;
/**
* Find if a value is float value or not. The values with more than
* zero remainder returns true
*/
function isFloat(value) {
return value !== (value | 0);
}
exports.isFloat = isFloat;
/**
* Find if the value has given decimal place or not.
*
* Since there is no direct way in Javascript to check for decimal place. We make
* use of regex to find it out.
*
* Numeric values are converted to string by calling `value.toString()` before
* testing it against the regex.
*
* If this method returns `true`, then you can safely parse the string with `parseFloat`
* method.
*/
function isDecimal(value, options) {
if (typeof value === 'number') {
value = value.toString();
}
const decimalPlaces = (options && options.decimalPlaces) || '1,';
return new RegExp(`^[-+]?([0-9]+)?(\\.[0-9]{${decimalPlaces}})$`).test(value);
}
exports.isDecimal = isDecimal;
@@ -0,0 +1,20 @@
/**
* A simple class to raise consistent exceptions for invalid config
* for driver based implementations.
*/
export declare class ManagerConfigValidator {
private config;
private serviceName;
private configLocation;
constructor(config: any, serviceName: string, configLocation: string);
/**
* Validates that the default key name is defined inside the config
* for a given module/service
*/
validateDefault(keyName: string): void;
/**
* Validates that the list to ensure that is is defined and the default
* key name is also part of the list.
*/
validateList(listName: string, keyName: string): void;
}
@@ -0,0 +1,55 @@
"use strict";
/*
* @poppinss/utils
*
* (c) Harminder Virk <virk@adonisjs.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.ManagerConfigValidator = void 0;
const Exception_1 = require("./Exception");
/**
* A simple class to raise consistent exceptions for invalid config
* for driver based implementations.
*/
class ManagerConfigValidator {
constructor(config, serviceName, configLocation) {
this.config = config;
this.serviceName = serviceName;
this.configLocation = configLocation;
}
/**
* Validates that the default key name is defined inside the config
* for a given module/service
*/
validateDefault(keyName) {
if (!this.config[keyName]) {
throw new Exception_1.Exception([
`Invalid "${this.serviceName}" config. Missing value for "${keyName}".`,
`Make sure to set it inside the "${this.configLocation}" file`,
].join(' '));
}
}
/**
* Validates that the list to ensure that is is defined and the default
* key name is also part of the list.
*/
validateList(listName, keyName) {
if (!this.config[listName]) {
throw new Exception_1.Exception([
`Invalid "${this.serviceName}" config. Missing value for "${listName}".`,
`Make sure to set it inside the "${this.configLocation}" file`,
].join(' '));
}
const defaultValue = this.config[keyName];
if (!this.config[listName][defaultValue]) {
throw new Exception_1.Exception([
`Invalid "${this.serviceName}" config. "${defaultValue}" is not defined inside "${listName}".`,
`Make sure to set it inside the "${this.configLocation}" file`,
].join(' '));
}
}
}
exports.ManagerConfigValidator = ManagerConfigValidator;
@@ -0,0 +1,11 @@
declare type Constructor = new (...args: any[]) => any;
declare type AbstractConstructor = abstract new (...args: any[]) => any;
/**
* Define static properties on a class with inheritance in play.
*/
export declare function defineStaticProperty<T extends Constructor | AbstractConstructor, Prop extends keyof T>(self: T, BaseClass: Constructor | AbstractConstructor, { propertyName, defaultValue, strategy, }: {
propertyName: Prop;
defaultValue: T[Prop];
strategy: 'inherit' | 'define' | ((value: T[Prop]) => T[Prop]);
}): void;
export {};
@@ -0,0 +1,57 @@
"use strict";
/*
* @poppinss/utils
*
* (c) Harminder Virk <virk@adonisjs.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.defineStaticProperty = void 0;
const cloneDeep_1 = __importDefault(require("lodash/cloneDeep"));
/**
* Define static properties on a class with inheritance in play.
*/
function defineStaticProperty(self, BaseClass, { propertyName, defaultValue, strategy, }) {
if (!self.hasOwnProperty(propertyName)) {
/**
* Class is inhering the base class directly and hence we don't have to
* copy any properties
*/
if (Object.getPrototypeOf(self.prototype) === BaseClass.prototype || strategy === 'define') {
Object.defineProperty(self, propertyName, {
value: defaultValue,
configurable: true,
enumerable: true,
writable: true,
});
return;
}
/**
* Class is inherting another sub class. We must copy the values to the self
* class, otherwise mutating them inside the self class will be reflected
* on the base class.
*/
const value = self[propertyName];
if (value === undefined) {
Object.defineProperty(self, propertyName, {
value: defaultValue,
configurable: true,
enumerable: true,
writable: true,
});
return;
}
Object.defineProperty(self, propertyName, {
value: typeof strategy === 'function' ? strategy(value) : (0, cloneDeep_1.default)(value),
configurable: true,
enumerable: true,
writable: true,
});
}
}
exports.defineStaticProperty = defineStaticProperty;
@@ -0,0 +1,5 @@
/**
* Handles ESM `default` exports and common js vanilla exports. The `default`
* exports are only entertained, when `esmEnabled` is set to true.
*/
export declare function esmRequire(filePath: string): any;
@@ -0,0 +1,20 @@
"use strict";
/*
* @poppinss/utils
*
* (c) Harminder Virk <virk@adonisjs.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.esmRequire = void 0;
const esmResolver_1 = require("./esmResolver");
/**
* Handles ESM `default` exports and common js vanilla exports. The `default`
* exports are only entertained, when `esmEnabled` is set to true.
*/
function esmRequire(filePath) {
return (0, esmResolver_1.esmResolver)(require(filePath));
}
exports.esmRequire = esmRequire;
@@ -0,0 +1 @@
export declare function esmResolver(output: any): any;
@@ -0,0 +1,15 @@
"use strict";
/*
* @poppinss/utils
*
* (c) Harminder Virk <virk@adonisjs.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.esmResolver = void 0;
function esmResolver(output) {
return output && output.__esModule && output.default ? output.default : output;
}
exports.esmResolver = esmResolver;
@@ -0,0 +1,2 @@
export declare type ReplacerFn = (this: any, key: string, value: any) => any;
export declare function stringify(obj: any, replacer?: ReplacerFn, spacer?: string | number): any;
@@ -0,0 +1,101 @@
"use strict";
/*
* @poppinss/utils
*
* (c) Harminder Virk <virk@adonisjs.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.stringify = void 0;
/**
* Exact copy of https://github.com/davidmarkclements/fast-safe-stringify/blob/master/index.js
* with a few changes that were introduced in https://github.com/davidmarkclements/fast-safe-stringify/pull/52 PR.
*/
const arr = [];
const replacerStack = [];
// Regular stringify
function stringify(obj, replacer, spacer) {
decirc(obj, '', [], undefined);
let res;
if (replacerStack.length === 0) {
res = JSON.stringify(obj, replacer, spacer);
}
else {
res = JSON.stringify(obj, replaceGetterValues(replacer), spacer);
}
while (arr.length !== 0) {
var part = arr.pop();
if (part.length === 4) {
Object.defineProperty(part[0], part[1], part[3]);
}
else {
part[0][part[1]] = part[2];
}
}
return res;
}
exports.stringify = stringify;
function decirc(val, k, stack, parent) {
let i;
if (typeof val === 'object' && val !== null) {
for (i = 0; i < stack.length; i++) {
if (stack[i] === val) {
let propertyDescriptor = Object.getOwnPropertyDescriptor(parent, k);
if (propertyDescriptor.get !== undefined) {
if (propertyDescriptor.configurable) {
Object.defineProperty(parent, k, { value: '[Circular]' });
arr.push([parent, k, val, propertyDescriptor]);
}
else {
replacerStack.push([val, k]);
}
}
else {
parent[k] = '[Circular]';
arr.push([parent, k, val]);
}
return;
}
}
stack.push(val);
// Optimize for Arrays. Big arrays could kill the performance otherwise!
if (Array.isArray(val)) {
for (i = 0; i < val.length; i++) {
decirc(val[i], i, stack, val);
}
}
else {
var keys = Object.keys(val);
for (i = 0; i < keys.length; i++) {
var key = keys[i];
decirc(val[key], key, stack, val);
}
}
stack.pop();
}
}
// wraps replacer function to handle values we couldn't replace
// and mark them as [Circular]
function replaceGetterValues(replacer) {
replacer =
replacer !== undefined
? replacer
: function (_, v) {
return v;
};
return function (key, val) {
if (replacerStack.length > 0) {
for (var i = 0; i < replacerStack.length; i++) {
var part = replacerStack[i];
if (part[1] === key && part[0] === val) {
val = '[Circular]';
replacerStack.splice(i, 1);
break;
}
}
}
return replacer.call(this, key, val);
};
}
@@ -0,0 +1 @@
export { flattie as flatten } from 'flattie';
@@ -0,0 +1,13 @@
"use strict";
/*
* @poppinss/utils
*
* (c) Harminder Virk <virk@adonisjs.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.flatten = void 0;
var flattie_1 = require("flattie");
Object.defineProperty(exports, "flatten", { enumerable: true, get: function () { return flattie_1.flattie; } });
@@ -0,0 +1,5 @@
/**
* Returns `true` when file ends with `.js`, `.json` or
* `.ts` but not `.d.ts`.
*/
export declare function isScriptFile(file: string): boolean;
@@ -0,0 +1,28 @@
"use strict";
/*
* @poppinss/utils
*
* (c) Harminder Virk <virk@adonisjs.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.isScriptFile = void 0;
const path_1 = require("path");
const JS_MODULES = ['.js', '.json'];
/**
* Returns `true` when file ends with `.js`, `.json` or
* `.ts` but not `.d.ts`.
*/
function isScriptFile(file) {
const ext = (0, path_1.extname)(file);
if (JS_MODULES.includes(ext)) {
return true;
}
if (ext === '.ts' && !file.endsWith('.d.ts')) {
return true;
}
return false;
}
exports.isScriptFile = isScriptFile;
@@ -0,0 +1,13 @@
/// <reference path="../../types/lodash.types.d.ts" />
export { default as pick } from 'lodash/pick';
export { default as omit } from 'lodash/omit';
export { default as has } from 'lodash/has';
export { default as get } from 'lodash/get';
export { default as set } from 'lodash/set';
export { default as unset } from 'lodash/unset';
export { default as mergeWith } from 'lodash/mergeWith';
export { default as merge } from 'lodash/merge';
export { default as size } from 'lodash/size';
export { default as clone } from 'lodash/clone';
export { default as cloneDeep } from 'lodash/cloneDeep';
export { default as toPath } from 'lodash/toPath';
@@ -0,0 +1,39 @@
"use strict";
/*
* @poppinss/utils
*
* (c) Harminder Virk <virk@adonisjs.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.toPath = exports.cloneDeep = exports.clone = exports.size = exports.merge = exports.mergeWith = exports.unset = exports.set = exports.get = exports.has = exports.omit = exports.pick = void 0;
/// <reference path="../types/lodash.types.d.ts" />
var pick_1 = require("lodash/pick");
Object.defineProperty(exports, "pick", { enumerable: true, get: function () { return __importDefault(pick_1).default; } });
var omit_1 = require("lodash/omit");
Object.defineProperty(exports, "omit", { enumerable: true, get: function () { return __importDefault(omit_1).default; } });
var has_1 = require("lodash/has");
Object.defineProperty(exports, "has", { enumerable: true, get: function () { return __importDefault(has_1).default; } });
var get_1 = require("lodash/get");
Object.defineProperty(exports, "get", { enumerable: true, get: function () { return __importDefault(get_1).default; } });
var set_1 = require("lodash/set");
Object.defineProperty(exports, "set", { enumerable: true, get: function () { return __importDefault(set_1).default; } });
var unset_1 = require("lodash/unset");
Object.defineProperty(exports, "unset", { enumerable: true, get: function () { return __importDefault(unset_1).default; } });
var mergeWith_1 = require("lodash/mergeWith");
Object.defineProperty(exports, "mergeWith", { enumerable: true, get: function () { return __importDefault(mergeWith_1).default; } });
var merge_1 = require("lodash/merge");
Object.defineProperty(exports, "merge", { enumerable: true, get: function () { return __importDefault(merge_1).default; } });
var size_1 = require("lodash/size");
Object.defineProperty(exports, "size", { enumerable: true, get: function () { return __importDefault(size_1).default; } });
var clone_1 = require("lodash/clone");
Object.defineProperty(exports, "clone", { enumerable: true, get: function () { return __importDefault(clone_1).default; } });
var cloneDeep_1 = require("lodash/cloneDeep");
Object.defineProperty(exports, "cloneDeep", { enumerable: true, get: function () { return __importDefault(cloneDeep_1).default; } });
var toPath_1 = require("lodash/toPath");
Object.defineProperty(exports, "toPath", { enumerable: true, get: function () { return __importDefault(toPath_1).default; } });
@@ -0,0 +1,5 @@
/**
* Copied directly from https://github.com/nuxt-contrib/destr/blob/master/src/index.ts but
* instead raises the malformed JSON exceptions vs swallowing them
*/
export declare function safeParse(val: string, reviver?: (this: any, jsonKey: string, jsonValue: any) => any): any;
@@ -0,0 +1,42 @@
"use strict";
/*
* @poppinss/utils
*
* (c) Harminder Virk <virk@adonisjs.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.safeParse = void 0;
// https://github.com/fastify/secure-json-parse
// https://github.com/hapijs/bourne
const suspectProtoRx = /"(?:_|\\u005[Ff])(?:_|\\u005[Ff])(?:p|\\u0070)(?:r|\\u0072)(?:o|\\u006[Ff])(?:t|\\u0074)(?:o|\\u006[Ff])(?:_|\\u005[Ff])(?:_|\\u005[Ff])"\s*:/;
const suspectConstructorRx = /"(?:c|\\u0063)(?:o|\\u006[Ff])(?:n|\\u006[Ee])(?:s|\\u0073)(?:t|\\u0074)(?:r|\\u0072)(?:u|\\u0075)(?:c|\\u0063)(?:t|\\u0074)(?:o|\\u006[Ff])(?:r|\\u0072)"\s*:/;
const JsonSigRx = /^["{[]|^-?[0-9][0-9.]*$/;
function jsonParseTransform(key, value, reviver) {
if (key === '__proto__' || key === 'constructor') {
return;
}
return reviver ? reviver(key, value) : value;
}
/**
* Copied directly from https://github.com/nuxt-contrib/destr/blob/master/src/index.ts but
* instead raises the malformed JSON exceptions vs swallowing them
*/
function safeParse(val, reviver) {
if (typeof val !== 'string') {
return val;
}
if (val === 'null') {
return null;
}
if (!JsonSigRx.test(val)) {
return val;
}
if (suspectProtoRx.test(val) || suspectConstructorRx.test(val)) {
return JSON.parse(val, (key, value) => jsonParseTransform(key, value, reviver));
}
return JSON.parse(val, reviver);
}
exports.safeParse = safeParse;
@@ -0,0 +1,5 @@
import { ReplacerFn } from './fast-safe-stringify';
/**
* Safely stringifies a Javascript native value
*/
export declare function safeStringify(value: any, replacer?: ReplacerFn, space?: string | number): string;
@@ -0,0 +1,39 @@
"use strict";
/*
* @poppinss/utils
*
* (c) Harminder Virk <virk@adonisjs.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.safeStringify = void 0;
const fast_safe_stringify_1 = require("./fast-safe-stringify");
/**
* Replacer to handle bigints and remove Circular values all together
*/
function jsonStringifyReplacer(replacer, removeCircular) {
return function (key, value) {
if (removeCircular && value === '[Circular]') {
return;
}
const val = replacer ? replacer.call(this, key, value) : value;
if (typeof val === 'bigint') {
return val.toString();
}
return val;
};
}
/**
* Safely stringifies a Javascript native value
*/
function safeStringify(value, replacer, space) {
try {
return JSON.stringify(value, jsonStringifyReplacer(replacer, false), space);
}
catch {
return (0, fast_safe_stringify_1.stringify)(value, jsonStringifyReplacer(replacer, true), space);
}
}
exports.safeStringify = safeStringify;
@@ -0,0 +1,5 @@
/**
* Convert windows path to unix.
* Copied from https://github.com/sindresorhus/slash as the package is ESM only
*/
export declare function slash(filePath: string): string;
@@ -0,0 +1,24 @@
"use strict";
/*
* @poppinss/utils
*
* (c) Harminder Virk <virk@adonisjs.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.slash = void 0;
/**
* Convert windows path to unix.
* Copied from https://github.com/sindresorhus/slash as the package is ESM only
*/
function slash(filePath) {
const isExtendedLengthPath = /^\\\\\?\\/.test(filePath);
const hasNonAscii = /[^\u0000-\u0080]+/.test(filePath); // eslint-disable-line no-control-regex
if (isExtendedLengthPath || hasNonAscii) {
return filePath;
}
return filePath.replace(/\\/g, '/');
}
exports.slash = slash;
@@ -0,0 +1,151 @@
{
"name": "@poppinss/utils",
"version": "4.0.4",
"description": "Handy utilities for repetitive work",
"main": "build/index.js",
"files": [
"build/src",
"build/index.d.ts",
"build/index.js",
"types",
"build/helpers.d.ts",
"build/helpers.js"
],
"scripts": {
"mrm": "mrm --preset=@adonisjs/mrm-preset",
"pretest": "npm run lint",
"test": "node .bin/test.js",
"clean": "del build",
"compile": "npm run lint && npm run clean && tsc",
"build": "npm run compile",
"commit": "git-cz",
"release": "np --message=\"chore(release): %s\"",
"version": "npm run build",
"format": "prettier --write .",
"prepublishOnly": "npm run build",
"lint": "eslint . --ext=.ts",
"sync-labels": "github-label-sync --labels ./node_modules/@adonisjs/mrm-preset/gh-labels.json poppinss/utils"
},
"keywords": [
"utils"
],
"author": "virk,poppinss",
"license": "MIT",
"devDependencies": {
"@adonisjs/mrm-preset": "^5.0.3",
"@adonisjs/require-ts": "^2.0.11",
"@poppinss/dev-utils": "^2.0.3",
"@types/fs-readdir-recursive": "^1.0.0",
"@types/lodash": "^4.14.181",
"@types/ms": "^0.7.31",
"@types/node": "^17.0.23",
"@types/pluralize": "0.0.29",
"@types/require-all": "^3.0.3",
"del-cli": "^4.0.1",
"doctoc": "^2.1.0",
"eslint": "^8.13.0",
"eslint-config-prettier": "^8.5.0",
"eslint-plugin-adonis": "^2.1.0",
"eslint-plugin-prettier": "^4.0.0",
"github-label-sync": "^2.2.0",
"husky": "^7.0.4",
"japa": "^4.0.0",
"mrm": "^4.0.0",
"np": "^7.6.1",
"prettier": "^2.6.2",
"typescript": "^4.6.3"
},
"nyc": {
"exclude": [
"test"
],
"extension": [
".ts"
]
},
"config": {
"commitizen": {
"path": "cz-conventional-changelog"
}
},
"np": {
"contents": ".",
"anyBranch": false
},
"dependencies": {
"@poppinss/file-generator": "^1.0.2",
"@types/bytes": "^3.1.1",
"@types/he": "^1.1.2",
"bytes": "^3.1.2",
"change-case": "^4.1.2",
"cuid": "^2.1.8",
"flattie": "^1.1.0",
"fs-readdir-recursive": "^1.1.0",
"he": "^1.2.0",
"kind-of": "^6.0.3",
"lodash": "^4.17.21",
"ms": "^2.1.3",
"pluralize": "^8.0.0",
"require-all": "^3.0.0",
"resolve-from": "^5.0.0",
"slugify": "^1.6.5",
"truncatise": "0.0.8"
},
"directories": {
"doc": "docs",
"test": "test"
},
"repository": {
"type": "git",
"url": "git+https://github.com/poppinss/utils.git"
},
"bugs": {
"url": "https://github.com/poppinss/utils/issues"
},
"homepage": "https://github.com/poppinss/utils#readme",
"eslintConfig": {
"extends": [
"plugin:adonis/typescriptPackage",
"prettier",
"prettier"
],
"plugins": [
"prettier",
"prettier"
],
"rules": {
"prettier/prettier": [
"error",
{
"endOfLine": "auto"
}
]
}
},
"eslintIgnore": [
"build"
],
"prettier": {
"trailingComma": "es5",
"semi": false,
"singleQuote": true,
"useTabs": false,
"quoteProps": "consistent",
"bracketSpacing": true,
"arrowParens": "always",
"printWidth": 100
},
"mrmConfig": {
"core": false,
"license": "MIT",
"services": [
"github-actions"
],
"minNodeVersion": "16.13.1",
"probotApps": [
"stale",
"lock"
],
"runGhActionsOnWindows": true
}
}
@@ -0,0 +1,65 @@
/*
* @poppinss/utils
*
* (c) Harminder Virk <virk@adonisjs.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
type PropertyName = string | number | symbol
type PropertyNames = PropertyName | ReadonlyArray<PropertyName>
declare module 'lodash/pick' {
export default function pick<T>(
object: T | null | undefined,
...props: Array<PropertyNames>
): Partial<T>
}
declare module 'lodash/omit' {
export default function omit<T extends object>(
object: T | null | undefined,
...paths: Array<PropertyNames>
): Partial<T>
}
declare module 'lodash/has' {
export default function has<T>(object: T, path: PropertyNames): boolean
}
declare module 'lodash/get' {
export default function get(object: any, path: PropertyNames, defaultValue?: any): any
}
declare module 'lodash/set' {
export default function set(object: any, path: PropertyNames, value: any): any
}
declare module 'lodash/unset' {
export default function unset(object: any, path: PropertyNames): boolean
}
declare module 'lodash/mergeWith' {
export default function mergeWith(object: any, ...otherArgs: any[]): any
}
declare module 'lodash/merge' {
export default function merge(object: any, ...otherArgs: any[]): any
}
declare module 'lodash/size' {
export default function size(collection: object | string | null | undefined): number
}
declare module 'lodash/clone' {
export default function clone<T>(value: T): T
}
declare module 'lodash/cloneDeep' {
export default function cloneDeep<T>(value: T): T
}
declare module 'lodash/toPath' {
export default function toPath(value: any): string[]
}
+167
View File
@@ -0,0 +1,167 @@
{
"name": "@adonisjs/session",
"version": "6.4.0",
"description": "Session provider for AdonisJS",
"typings": "./build/adonis-typings/index.d.ts",
"main": "build/providers/SessionProvider.js",
"files": [
"build/adonis-typings",
"build/providers",
"build/src",
"build/config.js",
"build/config.d.ts",
"build/templates",
"build/instructions.md"
],
"dependencies": {
"@poppinss/utils": "^4.0.4",
"fs-extra": "^10.1.0"
},
"peerDependencies": {
"@adonisjs/core": "^5.8.0"
},
"devDependencies": {
"@adonisjs/core": "^5.8.2",
"@adonisjs/mrm-preset": "^5.0.3",
"@adonisjs/redis": "^7.3.0",
"@adonisjs/require-ts": "^2.0.11",
"@japa/assert": "^1.3.4",
"@japa/preset-adonis": "^1.0.15",
"@japa/run-failed-tests": "^1.0.7",
"@japa/runner": "^2.0.8",
"@japa/spec-reporter": "^1.1.12",
"@poppinss/dev-utils": "^2.0.3",
"@types/node": "^17.0.34",
"@types/supertest": "^2.0.12",
"commitizen": "^4.2.4",
"copyfiles": "^2.4.1",
"cz-conventional-changelog": "^3.3.0",
"del-cli": "^4.0.1",
"eslint": "^8.15.0",
"eslint-config-prettier": "^8.5.0",
"eslint-plugin-adonis": "^2.1.0",
"eslint-plugin-prettier": "^4.0.0",
"github-label-sync": "^2.2.0",
"husky": "^8.0.1",
"mrm": "^4.0.0",
"np": "^7.6.1",
"prettier": "^2.6.2",
"set-cookie-parser": "^2.4.8",
"supertest": "^6.2.3",
"typescript": "^4.6.4"
},
"scripts": {
"mrm": "mrm --preset=@adonisjs/mrm-preset",
"pretest": "npm run lint",
"test": "node -r @adonisjs/require-ts/build/register ./bin/test.ts",
"clean": "del build",
"compile": "npm run lint && npm run clean && tsc",
"copyfiles": "copyfiles \"templates/**/*.txt\" \"instructions.md\" build",
"build": "npm run compile && npm run copyfiles",
"commit": "git-cz",
"release": "np --message=\"chore(release): %s\"",
"version": "npm run build",
"prepublishOnly": "npm run build",
"lint": "eslint . --ext=.ts",
"format": "prettier --write .",
"sync-labels": "github-label-sync --labels ./node_modules/@adonisjs/mrm-preset/gh-labels.json adonisjs/session"
},
"repository": {
"type": "git",
"url": "git+https://github.com/adonisjs/adonis-session.git"
},
"keywords": [
"session",
"adonisjs"
],
"author": "virk,adonisjs",
"license": "MIT",
"bugs": {
"url": "https://github.com/adonisjs/adonis-session/issues"
},
"homepage": "https://github.com/adonisjs/adonis-session#readme",
"nyc": {
"exclude": [
"test"
],
"extension": [
".ts"
]
},
"husky": {
"hooks": {
"commit-msg": "node ./node_modules/@adonisjs/mrm-preset/validateCommit/conventional/validate.js"
}
},
"config": {
"commitizen": {
"path": "cz-conventional-changelog"
}
},
"publishConfig": {
"tag": "latest",
"access": "public"
},
"adonisjs": {
"instructionsMd": "./build/instructions.md",
"templates": {
"config": [
"session.txt"
]
},
"env": {
"SESSION_DRIVER": "cookie"
},
"types": "@adonisjs/session",
"providers": [
"@adonisjs/session"
]
},
"np": {
"contents": ".",
"anyBranch": false
},
"mrmConfig": {
"core": true,
"license": "MIT",
"services": [
"github-actions"
],
"minNodeVersion": "14.15.4",
"probotApps": [
"stale",
"lock"
],
"runGhActionsOnWindows": false
},
"eslintConfig": {
"extends": [
"plugin:adonis/typescriptPackage",
"prettier"
],
"plugins": [
"prettier"
],
"rules": {
"prettier/prettier": [
"error",
{
"endOfLine": "auto"
}
]
}
},
"eslintIgnore": [
"build"
],
"prettier": {
"trailingComma": "es5",
"semi": false,
"singleQuote": true,
"useTabs": false,
"quoteProps": "consistent",
"bracketSpacing": true,
"arrowParens": "always",
"printWidth": 100
}
}