Socket
Socket
Sign inDemoInstall

@furystack/rest-service

Package Overview
Dependencies
Maintainers
0
Versions
169
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@furystack/rest-service - npm Package Compare versions

Comparing version 10.0.1 to 10.0.2

2

esm/actions/login-action.spec.js

@@ -29,3 +29,3 @@ import { Injector } from '@furystack/inject';

await usingAsync(new Injector(), async (i) => {
i.setExplicitInstance({ cookieLogin: async () => Promise.reject(':(') }, HttpUserContext);
i.setExplicitInstance({ cookieLogin: async () => Promise.reject(new Error(':(')) }, HttpUserContext);
await expect(LoginAction({ request, response, injector: i, getBody: async () => ({ username: '', password: '' }) })).rejects.toThrowError('Login Failed');

@@ -32,0 +32,0 @@ });

@@ -1,2 +0,2 @@

import { describe, it, expect, vi } from 'vitest';
import { describe, expect, it, vi } from 'vitest';
import { addCorsHeaders } from './add-cors-header.js';

@@ -3,0 +3,0 @@ describe('AddCorsHeaders', () => {

@@ -128,3 +128,5 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {

const fullUrl = new URL(PathHelper.joinPaths('http://', `${options.hostName || ServerManager.DEFAULT_HOST}:${options.port}`, options.req.url));
options.cors && addCorsHeaders(options.cors, options.req, options.res);
if (options.cors) {
addCorsHeaders(options.cors, options.req, options.res);
}
if (options.req.method === 'OPTIONS') {

@@ -131,0 +133,0 @@ options.res.writeHead(200);

@@ -0,8 +1,8 @@

import { IdentityContext } from '@furystack/core';
import { Injector } from '@furystack/inject';
import { usingAsync } from '@furystack/utils';
import { describe, expect, it, vi } from 'vitest';
import { Authenticate } from './authenticate.js';
import { HttpUserContext } from './http-user-context.js';
import { Authenticate } from './authenticate.js';
import { IdentityContext } from '@furystack/core';
import { EmptyResult } from './request-action-implementation.js';
import { describe, it, expect, vi } from 'vitest';
describe('Authenticate', () => {

@@ -14,3 +14,3 @@ const response = {};

const isAuthenticatedAction = vi.fn(async () => false);
i.setExplicitInstance({ isAuthenticated: isAuthenticatedAction, getCurrentUser: async () => Promise.reject(':(') }, IdentityContext);
i.setExplicitInstance({ isAuthenticated: isAuthenticatedAction, getCurrentUser: async () => Promise.reject(new Error(':(')) }, IdentityContext);
i.setExplicitInstance({

@@ -33,3 +33,3 @@ authentication: { enableBasicAuth: false },

isAuthenticated: isAuthenticatedAction,
getCurrentUser: async () => Promise.reject(':('),
getCurrentUser: async () => Promise.reject(new Error(':(')),
authentication: { enableBasicAuth: true },

@@ -49,3 +49,3 @@ }, HttpUserContext);

const isAuthenticatedAction = vi.fn(async () => true);
i.setExplicitInstance({ isAuthenticated: isAuthenticatedAction, getCurrentUser: async () => Promise.reject(':(') }, IdentityContext);
i.setExplicitInstance({ isAuthenticated: isAuthenticatedAction, getCurrentUser: async () => Promise.reject(new Error(':(')) }, IdentityContext);
const exampleAuthenticatedAction = vi.fn(async () => EmptyResult());

@@ -52,0 +52,0 @@ const authorized = Authenticate()(exampleAuthenticatedAction);

@@ -0,7 +1,7 @@

import { AuthorizationError, IdentityContext } from '@furystack/core';
import { Injector } from '@furystack/inject';
import { usingAsync } from '@furystack/utils';
import { AuthorizationError, IdentityContext } from '@furystack/core';
import { describe, expect, it, vi } from 'vitest';
import { Authorize } from './authorize.js';
import { EmptyResult } from './request-action-implementation.js';
import { describe, it, expect, vi } from 'vitest';
describe('Authorize', () => {

@@ -13,3 +13,3 @@ const response = {};

const isAuthorizedAction = vi.fn(async () => false);
i.setExplicitInstance({ isAuthorized: isAuthorizedAction, getCurrentUser: () => Promise.reject(':(') }, IdentityContext);
i.setExplicitInstance({ isAuthorized: isAuthorizedAction, getCurrentUser: () => Promise.reject(new Error(':(')) }, IdentityContext);
const exampleAuthorizedAction = vi.fn(async () => EmptyResult());

@@ -16,0 +16,0 @@ const authorized = Authorize('Role1')(exampleAuthorizedAction);

@@ -1,9 +0,10 @@

import { usingAsync } from '@furystack/utils';
/* eslint-disable @typescript-eslint/ban-ts-comment */
import { InMemoryStore, StoreManager, User, addStore } from '@furystack/core';
import { Injector } from '@furystack/inject';
import { User, StoreManager, InMemoryStore, addStore } from '@furystack/core';
import { DefaultSession } from './models/default-session.js';
import { HttpUserContext } from './http-user-context.js';
import { PasswordAuthenticator, PasswordCredential, UnauthenticatedError } from '@furystack/security';
import { usingAsync } from '@furystack/utils';
import { describe, expect, it, vi } from 'vitest';
import { useHttpAuthentication } from './helpers.js';
import { describe, it, expect, vi } from 'vitest';
import { HttpUserContext } from './http-user-context.js';
import { DefaultSession } from './models/default-session.js';
export const prepareInjector = async (i) => {

@@ -97,3 +98,3 @@ addStore(i, new InMemoryStore({ model: User, primaryKey: 'username' }))

await setupUser(i, 'otherUser', 'pass123');
expect(i.getInstance(HttpUserContext).authenticateUser('user', 'pass123')).rejects.toThrowError(UnauthenticatedError);
await expect(i.getInstance(HttpUserContext).authenticateUser('user', 'pass123')).rejects.toThrowError(UnauthenticatedError);
});

@@ -195,3 +196,3 @@ });

const ctx = i.getInstance(HttpUserContext);
ctx.authentication
await ctx.authentication
.getSessionStore(i.getInstance(StoreManager))

@@ -208,6 +209,6 @@ .add({ sessionId: '666', username: testUser.username });

const ctx = i.getInstance(HttpUserContext);
ctx.authentication
await ctx.authentication
.getSessionStore(i.getInstance(StoreManager))
.add({ sessionId: '666', username: testUser.username });
ctx.authentication.getUserStore(i.getInstance(StoreManager)).add({ ...testUser });
await ctx.authentication.getUserStore(i.getInstance(StoreManager)).add({ ...testUser });
const result = await ctx.authenticateRequest({

@@ -240,2 +241,3 @@ headers: { cookie: `${ctx.authentication.cookieName}=666;a=3` },

const setHeader = vi.fn();
// @ts-expect-error
ctx.getSessionStore().add = vi.fn(async () => {

@@ -257,2 +259,3 @@ return {};

const setHeader = vi.fn();
// @ts-expect-error
ctx.getSessionStore().add = vi.fn(async () => {

@@ -278,3 +281,3 @@ return {};

const userStore = i.getInstance(StoreManager).getStoreFor(User, 'username');
userStore.add(testUser);
await userStore.add(testUser);
const pw = await i.getInstance(PasswordAuthenticator).hasher.createCredential(testUser.username, 'test');

@@ -299,3 +302,3 @@ await i.getInstance(StoreManager).getStoreFor(PasswordCredential, 'userName').add(pw);

const userStore = i.getInstance(StoreManager).getStoreFor(User, 'username');
userStore.add(testUser);
await userStore.add(testUser);
const pw = await i.getInstance(PasswordAuthenticator).hasher.createCredential(testUser.username, 'test');

@@ -315,3 +318,3 @@ await i.getInstance(StoreManager).getStoreFor(PasswordCredential, 'userName').add(pw);

const userStore = i.getInstance(StoreManager).getStoreFor(User, 'username');
userStore.add(testUser);
await userStore.add(testUser);
let sessionId = '';

@@ -318,0 +321,0 @@ const pw = await i.getInstance(PasswordAuthenticator).hasher.createCredential(testUser.username, 'test');

import type { Options } from 'ajv';
export declare class SchemaValidator<TSchema extends {
definitions: {};
definitions: object;
}> {

@@ -5,0 +5,0 @@ private readonly schema;

import type { IncomingMessage, Server, ServerResponse } from 'http';
import { EventEmitter } from 'stream';
export interface ServerOptions {

@@ -18,3 +19,5 @@ hostName?: string;

}
export declare class ServerManager implements AsyncDisposable {
export declare class ServerManager extends EventEmitter<{
onRequestFailed: [unknown, IncomingMessage, ServerResponse<IncomingMessage>];
}> implements AsyncDisposable {
static DEFAULT_HOST: string;

@@ -21,0 +24,0 @@ servers: Map<string, ServerRecord>;

@@ -11,3 +11,4 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {

import { Lock } from 'semaphore-async-await';
let ServerManager = class ServerManager {
import { EventEmitter } from 'stream';
let ServerManager = class ServerManager extends EventEmitter {
static { ServerManager_1 = this; }

@@ -48,3 +49,5 @@ static DEFAULT_HOST = 'localhost';

if (apiMatch) {
apiMatch.onRequest({ req, res });
apiMatch.onRequest({ req, res }).catch((error) => {
this.emit('onRequestFailed', error, req, res);
});
}

@@ -51,0 +54,0 @@ else {

import type { RequestAction } from './request-action-implementation.js';
export declare const Validate: <TSchema extends {
definitions: {
[K: string]: {
required?: string[];
} | any;
[K: string]: any;
};

@@ -8,0 +6,0 @@ }>(validationOptions: {

@@ -125,3 +125,3 @@ import { getStoreManager, InMemoryStore, User } from '@furystack/core';

const responseJson = await error.response.json();
expect(responseJson.errors.find((e) => e.keyword === 'required' && e.message.includes('foo'))).toBeDefined();
expect(responseJson.errors.find((e) => e.keyword === 'required' && e.message?.includes('foo'))).toBeDefined();
}

@@ -128,0 +128,0 @@ }

@@ -32,2 +32,3 @@ import { SchemaValidator } from './schema-validator/schema-validator.js';

}, { schemaName: validationOptions.schemaName });
// @ts-expect-error
return await action({

@@ -34,0 +35,0 @@ request: args.request,

{
"name": "@furystack/rest-service",
"version": "10.0.1",
"version": "10.0.2",
"description": "Repository implementation for FuryStack",

@@ -40,8 +40,8 @@ "type": "module",

"dependencies": {
"@furystack/core": "^15.0.1",
"@furystack/inject": "^12.0.1",
"@furystack/repository": "^10.0.1",
"@furystack/rest": "^8.0.1",
"@furystack/security": "^6.0.1",
"@furystack/utils": "^8.0.1",
"@furystack/core": "^15.0.2",
"@furystack/inject": "^12.0.2",
"@furystack/repository": "^10.0.2",
"@furystack/rest": "^8.0.2",
"@furystack/security": "^6.0.2",
"@furystack/utils": "^8.0.2",
"ajv": "^8.17.1",

@@ -53,8 +53,8 @@ "ajv-formats": "^3.0.1",

"devDependencies": {
"@furystack/rest-client-fetch": "^8.0.1",
"@types/node": "^20.14.11",
"typescript": "^5.5.3",
"vitest": "^2.0.3"
"@furystack/rest-client-fetch": "^8.0.2",
"@types/node": "^22.2.0",
"typescript": "^5.5.4",
"vitest": "^2.0.5"
},
"gitHead": "1045d854bfd8c475b7035471d130d401417a2321"
}

@@ -36,3 +36,3 @@ import { Injector } from '@furystack/inject'

await usingAsync(new Injector(), async (i) => {
i.setExplicitInstance({ cookieLogin: async () => Promise.reject(':(') }, HttpUserContext)
i.setExplicitInstance({ cookieLogin: async () => Promise.reject(new Error(':(')) }, HttpUserContext)
await expect(

@@ -39,0 +39,0 @@ LoginAction({ request, response, injector: i, getBody: async () => ({ username: '', password: '' }) }),

import type { IncomingMessage, ServerResponse } from 'http'
import { describe, it, expect, vi } from 'vitest'
import { describe, expect, it, vi } from 'vitest'
import { addCorsHeaders } from './add-cors-header.js'

@@ -4,0 +4,0 @@

@@ -165,3 +165,3 @@ import type { User } from '@furystack/core'

fullUrl: URL
action: RequestAction<{ body: {}; result: {}; query: {}; url: {}; headers: {} }>
action: RequestAction<{ body: object; result: object; query: object; url: object; headers: object }>
params: unknown

@@ -189,3 +189,3 @@ }) {

getUrlParams: () => {
return params as {}
return params as object
},

@@ -216,3 +216,6 @@ })

options.cors && addCorsHeaders(options.cors, options.req, options.res)
if (options.cors) {
addCorsHeaders(options.cors, options.req, options.res)
}
if (options.req.method === 'OPTIONS') {

@@ -219,0 +222,0 @@ options.res.writeHead(200)

@@ -1,10 +0,9 @@

import type { IncomingMessage } from 'http'
import { IdentityContext } from '@furystack/core'
import { Injector } from '@furystack/inject'
import { usingAsync } from '@furystack/utils'
import type { IncomingMessage, ServerResponse } from 'http'
import { describe, expect, it, vi } from 'vitest'
import { Authenticate } from './authenticate.js'
import { HttpUserContext } from './http-user-context.js'
import { Authenticate } from './authenticate.js'
import type { ServerResponse } from 'http'
import { IdentityContext } from '@furystack/core'
import { EmptyResult } from './request-action-implementation.js'
import { describe, it, expect, vi } from 'vitest'

@@ -20,3 +19,3 @@ describe('Authenticate', () => {

i.setExplicitInstance(
{ isAuthenticated: isAuthenticatedAction, getCurrentUser: async () => Promise.reject(':(') },
{ isAuthenticated: isAuthenticatedAction, getCurrentUser: async () => Promise.reject(new Error(':(')) },
IdentityContext,

@@ -48,3 +47,3 @@ )

isAuthenticated: isAuthenticatedAction,
getCurrentUser: async () => Promise.reject(':('),
getCurrentUser: async () => Promise.reject(new Error(':(')),
authentication: { enableBasicAuth: true },

@@ -69,3 +68,3 @@ },

i.setExplicitInstance(
{ isAuthenticated: isAuthenticatedAction, getCurrentUser: async () => Promise.reject(':(') },
{ isAuthenticated: isAuthenticatedAction, getCurrentUser: async () => Promise.reject(new Error(':(')) },
IdentityContext,

@@ -72,0 +71,0 @@ )

@@ -1,10 +0,9 @@

import type { IncomingMessage } from 'http'
import type { User } from '@furystack/core'
import { AuthorizationError, IdentityContext } from '@furystack/core'
import { Injector } from '@furystack/inject'
import { usingAsync } from '@furystack/utils'
import type { User } from '@furystack/core'
import { AuthorizationError, IdentityContext } from '@furystack/core'
import type { IncomingMessage, ServerResponse } from 'http'
import { describe, expect, it, vi } from 'vitest'
import { Authorize } from './authorize.js'
import type { ServerResponse } from 'http'
import { EmptyResult } from './request-action-implementation.js'
import { describe, it, expect, vi } from 'vitest'

@@ -19,3 +18,3 @@ describe('Authorize', () => {

i.setExplicitInstance(
{ isAuthorized: isAuthorizedAction, getCurrentUser: () => Promise.reject(':(') },
{ isAuthorized: isAuthorizedAction, getCurrentUser: () => Promise.reject(new Error(':(')) },
IdentityContext,

@@ -22,0 +21,0 @@ )

@@ -1,10 +0,11 @@

import type { IncomingMessage, ServerResponse } from 'http'
import { usingAsync } from '@furystack/utils'
/* eslint-disable @typescript-eslint/ban-ts-comment */
import { InMemoryStore, StoreManager, User, addStore } from '@furystack/core'
import { Injector } from '@furystack/inject'
import { User, StoreManager, InMemoryStore, addStore } from '@furystack/core'
import { DefaultSession } from './models/default-session.js'
import { HttpUserContext } from './http-user-context.js'
import { PasswordAuthenticator, PasswordCredential, UnauthenticatedError } from '@furystack/security'
import { usingAsync } from '@furystack/utils'
import type { IncomingMessage, ServerResponse } from 'http'
import { describe, expect, it, vi } from 'vitest'
import { useHttpAuthentication } from './helpers.js'
import { describe, it, expect, vi } from 'vitest'
import { HttpUserContext } from './http-user-context.js'
import { DefaultSession } from './models/default-session.js'

@@ -113,3 +114,3 @@ export const prepareInjector = async (i: Injector) => {

await setupUser(i, 'otherUser', 'pass123')
expect(i.getInstance(HttpUserContext).authenticateUser('user', 'pass123')).rejects.toThrowError(
await expect(i.getInstance(HttpUserContext).authenticateUser('user', 'pass123')).rejects.toThrowError(
UnauthenticatedError,

@@ -231,3 +232,3 @@ )

const ctx = i.getInstance(HttpUserContext)
ctx.authentication
await ctx.authentication
.getSessionStore(i.getInstance(StoreManager))

@@ -248,7 +249,7 @@ .add({ sessionId: '666', username: testUser.username })

const ctx = i.getInstance(HttpUserContext)
ctx.authentication
await ctx.authentication
.getSessionStore(i.getInstance(StoreManager))
.add({ sessionId: '666', username: testUser.username })
ctx.authentication.getUserStore(i.getInstance(StoreManager)).add({ ...testUser })
await ctx.authentication.getUserStore(i.getInstance(StoreManager)).add({ ...testUser })

@@ -285,6 +286,7 @@ const result = await ctx.authenticateRequest({

const setHeader = vi.fn()
// @ts-expect-error
ctx.getSessionStore().add = vi.fn(async () => {
return {} as any
return {}
})
const authResult = await ctx.cookieLogin(testUser, { setHeader } as any)
const authResult = await ctx.cookieLogin(testUser, { setHeader })
expect(authResult).toBe(testUser)

@@ -303,4 +305,5 @@ expect(setHeader).toBeCalled()

const setHeader = vi.fn()
// @ts-expect-error
ctx.getSessionStore().add = vi.fn(async () => {
return {} as any
return {}
})

@@ -311,3 +314,3 @@ ctx.authenticateRequest = vi.fn(async () => testUser)

response.setHeader = vi.fn(() => response)
await ctx.cookieLogin(testUser, { setHeader } as any)
await ctx.cookieLogin(testUser, { setHeader })
await ctx.cookieLogout(request, response)

@@ -326,3 +329,3 @@ expect(response.setHeader).toBeCalledWith('Set-Cookie', 'fss=; Path=/; HttpOnly')

const userStore = i.getInstance(StoreManager).getStoreFor(User, 'username')
userStore.add(testUser)
await userStore.add(testUser)

@@ -353,3 +356,3 @@ const pw = await i.getInstance(PasswordAuthenticator).hasher.createCredential(testUser.username, 'test')

const userStore = i.getInstance(StoreManager).getStoreFor(User, 'username')
userStore.add(testUser)
await userStore.add(testUser)

@@ -375,3 +378,3 @@ const pw = await i.getInstance(PasswordAuthenticator).hasher.createCredential(testUser.username, 'test')

const userStore = i.getInstance(StoreManager).getStoreFor(User, 'username')
userStore.add(testUser)
await userStore.add(testUser)

@@ -378,0 +381,0 @@ let sessionId = ''

@@ -6,3 +6,3 @@ import type { ErrorObject, Options } from 'ajv'

export class SchemaValidator<TSchema extends { definitions: {} }> {
export class SchemaValidator<TSchema extends { definitions: object }> {
private readonly ajv: Ajv.default

@@ -9,0 +9,0 @@ constructor(

@@ -6,2 +6,3 @@ import { Injectable } from '@furystack/inject'

import { Lock } from 'semaphore-async-await'
import { EventEmitter } from 'stream'

@@ -29,10 +30,10 @@ export interface ServerOptions {

@Injectable({ lifetime: 'singleton' })
export class ServerManager implements AsyncDisposable {
export class ServerManager
extends EventEmitter<{ onRequestFailed: [unknown, IncomingMessage, ServerResponse<IncomingMessage>] }>
implements AsyncDisposable
{
public static DEFAULT_HOST = 'localhost'
public servers = new Map<string, ServerRecord>()
private openedSockets = new Set<Socket>()
private readonly listenLock = new Lock()
private getHostUrl = (options: ServerOptions) =>

@@ -45,3 +46,2 @@ `http://${options.hostName || ServerManager.DEFAULT_HOST}:${options.port}`

}
public async [Symbol.asyncDispose]() {

@@ -77,3 +77,5 @@ try {

if (apiMatch) {
apiMatch.onRequest({ req, res })
apiMatch.onRequest({ req, res }).catch((error) => {
this.emit('onRequestFailed', error, req, res)
})
} else {

@@ -80,0 +82,0 @@ res.destroy()

@@ -6,2 +6,3 @@ import { getStoreManager, InMemoryStore, User } from '@furystack/core'

import { usingAsync } from '@furystack/utils'
import type Ajv from 'ajv'
import { describe, expect, it } from 'vitest'

@@ -88,3 +89,3 @@ import { useRestService } from './helpers.js'

expect(error.response?.status).toBe(400)
const responseJson = await error.response.json()
const responseJson: { errors: Ajv.ErrorObject[] } = await error.response.json()
expect(responseJson.errors[0].params.missingProperty).toEqual('foo')

@@ -110,3 +111,3 @@ expect(responseJson.errors[1].params.missingProperty).toEqual('bar')

expect(error.response?.status).toBe(400)
const responseJson = await error.response.json()
const responseJson: { errors: Ajv.ErrorObject[] } = await error.response.json()
expect(responseJson.errors[0].params.type).toEqual('number')

@@ -131,5 +132,5 @@ expect(responseJson.errors[0].instancePath).toEqual('/url/id')

expect(error.response?.status).toBe(400)
const responseJson = await error.response.json()
const responseJson: { errors: Ajv.ErrorObject[] } = await error.response.json()
expect(
responseJson.errors.find((e: any) => e.keyword === 'required' && e.message.includes('foo')),
responseJson.errors.find((e) => e.keyword === 'required' && e.message?.includes('foo')),
).toBeDefined()

@@ -153,3 +154,3 @@ }

expect(error.response?.status).toBe(400)
const responseJson = await error.response.json()
const responseJson: { errors: Ajv.ErrorObject[] } = await error.response.json()
expect(responseJson.errors[0].params.missingProperty).toEqual('body')

@@ -156,0 +157,0 @@ }

@@ -0,1 +1,5 @@

/* eslint-disable @typescript-eslint/no-unsafe-return */
/* eslint-disable @typescript-eslint/ban-ts-comment */
/* eslint-disable @typescript-eslint/no-unsafe-call */
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
import type { ActionResult, RequestAction, RequestActionOptions } from './request-action-implementation.js'

@@ -5,3 +9,3 @@ import { SchemaValidator } from './schema-validator/schema-validator.js'

export const Validate =
<TSchema extends { definitions: { [K: string]: { required?: string[] } | any } }>(validationOptions: {
<TSchema extends { definitions: { [K: string]: any } }>(validationOptions: {
/**

@@ -51,2 +55,3 @@ * The Schema object

)
// @ts-expect-error
return await action({

@@ -60,4 +65,4 @@ request: args.request,

getBody: () => Promise.resolve(body),
} as any)
})
}
}

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc