Compare commits

...
Author SHA1 Message Date
StandardNotes CI 321a055bae chore(release): publish
- @standardnotes/[email protected]
2022-07-06 11:47:54 +00:00
Karol Sójko bc666aa983 fix: add missing utils dependency on api 2022-07-06 13:39:23 +02:00
Karol Sójko a9fe67977c fix: remove continuing on error with publishing packages 2022-07-06 13:30:58 +02:00
StandardNotes CI 0c2b1fb03f chore(release): publish
- @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].0
 - @standardnotes/[email protected].1
 - @standardnotes/[email protected].0
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].0
 - @standardnotes/[email protected].0
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].0
 - @standardnotes/[email protected].0
 - @standardnotes/[email protected].0
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].0
 - @standardnotes/[email protected]
2022-07-06 11:30:05 +00:00
StandardNotes CI 7946a3a9c7 chore(release): components 2022-07-06 11:29:47 +00:00
Karol Sójko 21d8a99b3d fix: add dompurify to mobile package to fix the build process 2022-07-06 13:14:45 +02:00
Karol Sójko 57510921c2 fix: import from dompurify on utils 2022-07-06 13:06:22 +02:00
Karol Sójko 6751f30db6 fix: dompurify deps on utils 2022-07-06 12:48:52 +02:00
Karol Sójko 93679df645 fix: composite option for sncrypto-web 2022-07-06 12:35:33 +02:00
Karol Sójko 46fe66256b fix: not supported auth dependency 2022-07-06 12:30:41 +02:00
Karol Sójko 6ec66795d2 feat: add sncrypto client side packages 2022-07-06 12:21:21 +02:00
Karol Sójko 9d1f7043e5 feat: add responses package 2022-07-06 11:59:04 +02:00
Karol Sójko 67b0918ba8 fix: dompurify dep on utils 2022-07-06 11:54:55 +02:00
Karol Sójko 9d7d18e7f2 feat: add api package 2022-07-06 11:53:39 +02:00
Karol Sójko e2e9a11984 fix: missing utils dep on mobile 2022-07-06 11:42:50 +02:00
Karol Sójko aef4ceb7f8 feat: add utils package 2022-07-06 11:34:54 +02:00
StandardNotes CI d273770831 chore(release): publish
- @standardnotes/[email protected]
 - @standardnotes/[email protected].1
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].3
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].2
2022-07-06 07:49:27 +00:00
Karol Sójko c4e16e4346 fix: files system access api dependency on filepicker 2022-07-06 09:37:56 +02:00
253 changed files with 13144 additions and 126 deletions
-1
View File
@@ -7,7 +7,6 @@ on:
jobs:
Build:
if: "${{ contains(github.event.head_commit.message, 'chore(release): publish') == false }}"
continue-on-error: true
runs-on: ubuntu-latest
steps:
- name: Checkout code
+5
View File
@@ -21,6 +21,11 @@ packages/encryption/dist
packages/files/dist
packages/models/dist
packages/services/dist
packages/utils/dist
packages/api/dist
packages/responses/dist
packages/sncrypto-common/dist
packages/sncrypto-web/dist
**/.pnp.*
**/.yarn/*
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+2
View File
@@ -0,0 +1,2 @@
node_modules
dist
+6
View File
@@ -0,0 +1,6 @@
{
"extends": "../../.eslintrc",
"parserOptions": {
"project": "./linter.tsconfig.json"
}
}
+131
View File
@@ -0,0 +1,131 @@
# Change Log
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.4.1](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-07-06)
### Bug Fixes
* add missing utils dependency on api ([bc666aa](https://github.com/standardnotes/app/commit/bc666aa98301ece42e259be2ed60b9201665988f))
# 1.4.0 (2022-07-06)
### Features
* add api package ([9d7d18e](https://github.com/standardnotes/app/commit/9d7d18e7f20b3023aac078017efb16bbbc3da226))
* add responses package ([9d1f704](https://github.com/standardnotes/app/commit/9d1f7043e55cc8072e669606438e932183770f30))
# [1.3.0](https://github.com/standardnotes/snjs/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-07-06)
### Features
* remove filepicker, features, services and models packages in favor of standardnotes/app repository ([27f474e](https://github.com/standardnotes/snjs/commit/27f474e859701c5713c8b6ed27cd1a4d5e4392bb))
## [1.2.1](https://github.com/standardnotes/snjs/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-07-05)
**Note:** Version bump only for package @standardnotes/api
# [1.2.0](https://github.com/standardnotes/snjs/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-07-05)
### Features
* remove encryption package in favor of standardnotes/app repository ([f6d1c9e](https://github.com/standardnotes/snjs/commit/f6d1c9ee538bb59ee7ac28c0d49ca682d4eb4d38))
## [1.1.20](https://github.com/standardnotes/snjs/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-07-04)
### Bug Fixes
* add missing reflect-metadata package to all packages ([ce3a5bb](https://github.com/standardnotes/snjs/commit/ce3a5bbf3f1d2276ac4abc3eec3c6a44c8c3ba9b))
## [1.1.19](https://github.com/standardnotes/snjs/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-06-29)
**Note:** Version bump only for package @standardnotes/api
## [1.1.18](https://github.com/standardnotes/snjs/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-06-28)
### Bug Fixes
* setting custom host ([#773](https://github.com/standardnotes/snjs/issues/773)) ([2fe27b0](https://github.com/standardnotes/snjs/commit/2fe27b0324486fad915a91096142579e649995b8))
## [1.1.17](https://github.com/standardnotes/snjs/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-06-27)
**Note:** Version bump only for package @standardnotes/api
## [1.1.16](https://github.com/standardnotes/snjs/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-06-27)
**Note:** Version bump only for package @standardnotes/api
## [1.1.15](https://github.com/standardnotes/snjs/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-06-23)
### Bug Fixes
* set host on user server ([#771](https://github.com/standardnotes/snjs/issues/771)) ([62d2c60](https://github.com/standardnotes/snjs/commit/62d2c60834b20b386b8c60f0ee172aec3e57ec05))
## [1.1.14](https://github.com/standardnotes/snjs/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-06-22)
**Note:** Version bump only for package @standardnotes/api
## [1.1.13](https://github.com/standardnotes/snjs/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-06-22)
### Bug Fixes
* missing dependency ([b748571](https://github.com/standardnotes/snjs/commit/b748571c3288ecec3a2c0aed333ceaaf718832cd))
## [1.1.12](https://github.com/standardnotes/snjs/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-06-20)
**Note:** Version bump only for package @standardnotes/api
## [1.1.11](https://github.com/standardnotes/snjs/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-06-16)
**Note:** Version bump only for package @standardnotes/api
## [1.1.10](https://github.com/standardnotes/snjs/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-06-16)
**Note:** Version bump only for package @standardnotes/api
## [1.1.9](https://github.com/standardnotes/snjs/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-06-15)
**Note:** Version bump only for package @standardnotes/api
## [1.1.8](https://github.com/standardnotes/snjs/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-06-10)
**Note:** Version bump only for package @standardnotes/api
## [1.1.7](https://github.com/standardnotes/snjs/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-06-09)
**Note:** Version bump only for package @standardnotes/api
## [1.1.6](https://github.com/standardnotes/snjs/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-06-09)
**Note:** Version bump only for package @standardnotes/api
## [1.1.5](https://github.com/standardnotes/snjs/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-06-09)
**Note:** Version bump only for package @standardnotes/api
## [1.1.4](https://github.com/standardnotes/snjs/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-06-06)
**Note:** Version bump only for package @standardnotes/api
## [1.1.3](https://github.com/standardnotes/snjs/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-06-03)
**Note:** Version bump only for package @standardnotes/api
## [1.1.2](https://github.com/standardnotes/snjs/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-06-03)
### Bug Fixes
* add option to define additional params to the user registration request if needed ([78f169f](https://github.com/standardnotes/snjs/commit/78f169f993cb0d1950e553fe251f6bc903dd6da8))
## [1.1.1](https://github.com/standardnotes/snjs/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-06-03)
### Bug Fixes
* make response headers optional for ease of defining on the server side ([#755](https://github.com/standardnotes/snjs/issues/755)) ([b5c2092](https://github.com/standardnotes/snjs/commit/b5c2092fc33dbd389fa67c122b3907956ca2eafa))
# 1.1.0 (2022-06-03)
### Features
* api service refactor -extract registration ([#733](https://github.com/standardnotes/snjs/issues/733)) ([1d7fac8](https://github.com/standardnotes/snjs/commit/1d7fac8c9dbb0fdb78a88743965a33c6d6a7d7d3))
+19
View File
@@ -0,0 +1,19 @@
// eslint-disable-next-line @typescript-eslint/no-var-requires
const base = require('../../node_modules/@standardnotes/config/src/jest.json');
module.exports = {
...base,
globals: {
'ts-jest': {
tsconfig: 'tsconfig.json',
},
},
coverageThreshold: {
global: {
branches: 17,
functions: 43,
lines: 46,
statements: 46
}
}
};
+4
View File
@@ -0,0 +1,4 @@
{
"extends": "./tsconfig.json",
"exclude": ["dist"]
}
+45
View File
@@ -0,0 +1,45 @@
{
"name": "@standardnotes/api",
"version": "1.4.1",
"engines": {
"node": ">=16.0.0 <17.0.0"
},
"description": "Interfaces for dealing with SN server-side API",
"main": "dist/index.js",
"author": "Standard Notes",
"types": "dist/index.d.ts",
"files": [
"dist"
],
"publishConfig": {
"access": "public"
},
"license": "AGPL-3.0-or-later",
"scripts": {
"clean": "rm -fr dist",
"prestart": "yarn clean",
"start": "tsc -p tsconfig.json --watch",
"prebuild": "yarn clean",
"build": "tsc -p tsconfig.json",
"lint": "eslint . --ext .ts",
"test:unit": "jest spec --coverage"
},
"devDependencies": {
"@types/jest": "^27.4.1",
"@types/lodash": "^4.14.182",
"@typescript-eslint/eslint-plugin": "^5.30.0",
"eslint-plugin-prettier": "^4.2.1",
"jest": "^27.5.1",
"ts-jest": "^27.1.3"
},
"dependencies": {
"@standardnotes/common": "^1.23.1",
"@standardnotes/encryption": "workspace:*",
"@standardnotes/models": "workspace:*",
"@standardnotes/responses": "^1.9.0",
"@standardnotes/security": "^1.1.0",
"@standardnotes/services": "workspace:*",
"@standardnotes/utils": "workspace:*",
"reflect-metadata": "^0.1.13"
}
}
@@ -0,0 +1,3 @@
export enum ApiVersion {
v0 = '20200115',
}
+1
View File
@@ -0,0 +1 @@
export * from './ApiVersion'
@@ -0,0 +1,77 @@
import { ProtocolVersion } from '@standardnotes/common'
import { RootKeyParamsInterface } from '@standardnotes/models'
import { UserRegistrationResponse } from '../../Response/User/UserRegistrationResponse'
import { UserServerInterface } from '../../Server'
import { UserApiService } from './UserApiService'
describe('UserApiService', () => {
let userServer: UserServerInterface
let keyParams: RootKeyParamsInterface
const createService = () => new UserApiService(userServer)
beforeEach(() => {
userServer = {} as jest.Mocked<UserServerInterface>
userServer.register = jest.fn().mockReturnValue({
data: { user: { email: '[email protected]', uuid: '1-2-3' } },
} as jest.Mocked<UserRegistrationResponse>)
keyParams = {} as jest.Mocked<RootKeyParamsInterface>
keyParams.getPortableValue = jest.fn().mockReturnValue({
identifier: '[email protected]',
version: ProtocolVersion.V004,
})
})
it('should register a user', async () => {
const response = await createService().register('[email protected]', 'testpasswd', keyParams, false)
expect(response).toEqual({
data: {
user: {
email: '[email protected]',
uuid: '1-2-3',
},
},
})
expect(userServer.register).toHaveBeenCalledWith({
api: '20200115',
email: '[email protected]',
ephemeral: false,
identifier: '[email protected]',
password: 'testpasswd',
version: '004',
})
})
it('should not register a user if it is already registering', async () => {
const service = createService()
Object.defineProperty(service, 'registering', {
get: () => true,
})
let error = null
try {
await service.register('[email protected]', 'testpasswd', keyParams, false)
} catch (caughtError) {
error = caughtError
}
expect(error).not.toBeNull()
})
it('should not register a user if the server fails', async () => {
userServer.register = jest.fn().mockImplementation(() => {
throw new Error('Oops')
})
let error = null
try {
await createService().register('[email protected]', 'testpasswd', keyParams, false)
} catch (caughtError) {
error = caughtError
}
expect(error).not.toBeNull()
})
})
@@ -0,0 +1,45 @@
import { RootKeyParamsInterface } from '@standardnotes/models'
import { ErrorMessage } from '../../Error/ErrorMessage'
import { ApiCallError } from '../../Error/ApiCallError'
import { UserRegistrationResponse } from '../../Response/User/UserRegistrationResponse'
import { UserServerInterface } from '../../Server/User/UserServerInterface'
import { ApiVersion } from '../../Api/ApiVersion'
import { ApiEndpointParam } from '../../Request/ApiEndpointParam'
import { UserApiServiceInterface } from './UserApiServiceInterface'
export class UserApiService implements UserApiServiceInterface {
private registering: boolean
constructor(private userServer: UserServerInterface) {
this.registering = false
}
async register(
email: string,
serverPassword: string,
keyParams: RootKeyParamsInterface,
ephemeral: boolean,
): Promise<UserRegistrationResponse> {
if (this.registering) {
throw new ApiCallError(ErrorMessage.RegistrationInProgress)
}
this.registering = true
try {
const response = await this.userServer.register({
[ApiEndpointParam.ApiVersion]: ApiVersion.v0,
password: serverPassword,
email,
ephemeral,
...keyParams.getPortableValue(),
})
this.registering = false
return response
} catch (error) {
throw new ApiCallError(ErrorMessage.GenericRegistrationFail)
}
}
}
@@ -0,0 +1,11 @@
import { RootKeyParamsInterface } from '@standardnotes/models'
import { UserRegistrationResponse } from '../../Response/User/UserRegistrationResponse'
export interface UserApiServiceInterface {
register(
email: string,
serverPassword: string,
keyParams: RootKeyParamsInterface,
ephemeral: boolean,
): Promise<UserRegistrationResponse>
}
+2
View File
@@ -0,0 +1,2 @@
export * from './User/UserApiService'
export * from './User/UserApiServiceInterface'
@@ -0,0 +1,6 @@
export class ApiCallError extends Error {
constructor(message: string) {
super(message)
Object.setPrototypeOf(this, ApiCallError.prototype)
}
}
@@ -0,0 +1,7 @@
export enum ErrorMessage {
RegistrationInProgress = 'An existing registration request is already in progress.',
GenericRegistrationFail = 'A server error occurred while trying to register. Please try again.',
RateLimited = 'Too many successive server requests. Please wait a few minutes and try again.',
InsufficientPasswordMessage = 'Your password must be at least %LENGTH% characters in length. For your security, please choose a longer password or, ideally, a passphrase, and try again.',
PasscodeRequired = 'Your passcode is required in order to register for an account.',
}
+2
View File
@@ -0,0 +1,2 @@
export * from './ApiCallError'
export * from './ErrorMessage'
+11
View File
@@ -0,0 +1,11 @@
export enum ErrorTag {
MfaInvalid = 'mfa-invalid',
MfaRequired = 'mfa-required',
RefreshTokenInvalid = 'invalid-refresh-token',
RefreshTokenExpired = 'expired-refresh-token',
AccessTokenExpired = 'expired-access-token',
ParametersInvalid = 'invalid-parameters',
RevokedSession = 'revoked-session',
AuthInvalid = 'invalid-auth',
ReadOnlyAccess = 'read-only-access',
}
@@ -0,0 +1,8 @@
import { ErrorTag } from './ErrorTag'
export type HttpErrorResponseBody = {
error: {
message: string
tag?: ErrorTag
}
}
@@ -0,0 +1 @@
export type HttpHeaders = Map<string, string | null>
@@ -0,0 +1,13 @@
import { HttpRequestParams } from './HttpRequestParams'
import { HttpVerb } from './HttpVerb'
export type HttpRequest = {
url: string
params?: HttpRequestParams
rawBytes?: Uint8Array
verb: HttpVerb
authentication?: string
customHeaders?: Record<string, string>[]
responseType?: XMLHttpRequestResponseType
external?: boolean
}
@@ -0,0 +1 @@
export type HttpRequestParams = Record<string, unknown>
@@ -0,0 +1,12 @@
import { HttpStatusCode } from './HttpStatusCode'
import { HttpResponseBody } from './HttpResponseBody'
import { HttpErrorResponseBody } from './HttpErrorResponseBody'
import { HttpResponseMeta } from './HttpResponseMeta'
import { HttpHeaders } from './HttpHeaders'
export interface HttpResponse {
status: HttpStatusCode
data?: HttpResponseBody | HttpErrorResponseBody
meta?: HttpResponseMeta
headers?: HttpHeaders
}
@@ -0,0 +1 @@
export type HttpResponseBody = Record<string, unknown>
@@ -0,0 +1,12 @@
import { Role } from '@standardnotes/security'
import { Uuid } from '@standardnotes/common'
export type HttpResponseMeta = {
auth: {
userUuid?: Uuid
roles?: Role[]
}
server: {
filesServerUrl?: string
}
}
@@ -0,0 +1,27 @@
import { Environment } from '@standardnotes/services'
import { HttpResponseMeta } from './HttpResponseMeta'
import { HttpService } from './HttpService'
describe('HttpService', () => {
const environment = Environment.Web
const appVersion = '1.2.3'
const snjsVersion = '2.3.4'
const host = 'http://bar'
let updateMetaCallback: (meta: HttpResponseMeta) => void
const createService = () => new HttpService(environment, appVersion, snjsVersion, host, updateMetaCallback)
beforeEach(() => {
updateMetaCallback = jest.fn()
})
it('should set host', () => {
const service = createService()
expect(service['host']).toEqual('http://bar')
service.setHost('http://foo')
expect(service['host']).toEqual('http://foo')
})
})
+190
View File
@@ -0,0 +1,190 @@
import { isString, joinPaths } from '@standardnotes/utils'
import { Environment } from '@standardnotes/services'
import { HttpRequestParams } from './HttpRequestParams'
import { HttpVerb } from './HttpVerb'
import { HttpRequest } from './HttpRequest'
import { HttpResponse } from './HttpResponse'
import { HttpServiceInterface } from './HttpServiceInterface'
import { HttpStatusCode } from './HttpStatusCode'
import { XMLHttpRequestState } from './XMLHttpRequestState'
import { ErrorMessage } from '../Error/ErrorMessage'
import { HttpResponseMeta } from './HttpResponseMeta'
import { HttpErrorResponseBody } from './HttpErrorResponseBody'
export class HttpService implements HttpServiceInterface {
constructor(
private environment: Environment,
private appVersion: string,
private snjsVersion: string,
private host: string,
private updateMetaCallback: (meta: HttpResponseMeta) => void,
) {}
setHost(host: string): void {
this.host = host
}
async get(path: string, params?: HttpRequestParams, authentication?: string): Promise<HttpResponse> {
return this.runHttp({ url: joinPaths(this.host, path), params, verb: HttpVerb.Get, authentication })
}
async post(path: string, params?: HttpRequestParams, authentication?: string): Promise<HttpResponse> {
return this.runHttp({ url: joinPaths(this.host, path), params, verb: HttpVerb.Post, authentication })
}
async put(path: string, params?: HttpRequestParams, authentication?: string): Promise<HttpResponse> {
return this.runHttp({ url: joinPaths(this.host, path), params, verb: HttpVerb.Put, authentication })
}
async patch(path: string, params: HttpRequestParams, authentication?: string): Promise<HttpResponse> {
return this.runHttp({ url: joinPaths(this.host, path), params, verb: HttpVerb.Patch, authentication })
}
async delete(path: string, params?: HttpRequestParams, authentication?: string): Promise<HttpResponse> {
return this.runHttp({ url: joinPaths(this.host, path), params, verb: HttpVerb.Delete, authentication })
}
private async runHttp(httpRequest: HttpRequest): Promise<HttpResponse> {
const request = this.createXmlRequest(httpRequest)
const response = await this.runRequest(request, this.createRequestBody(httpRequest))
if (response.meta) {
this.updateMetaCallback(response.meta)
}
return response
}
private createRequestBody(httpRequest: HttpRequest): string | Uint8Array | undefined {
if (
httpRequest.params !== undefined &&
[HttpVerb.Post, HttpVerb.Put, HttpVerb.Patch, HttpVerb.Delete].includes(httpRequest.verb)
) {
return JSON.stringify(httpRequest.params)
}
return httpRequest.rawBytes
}
private createXmlRequest(httpRequest: HttpRequest) {
const request = new XMLHttpRequest()
if (httpRequest.params && httpRequest.verb === HttpVerb.Get && Object.keys(httpRequest.params).length > 0) {
httpRequest.url = this.urlForUrlAndParams(httpRequest.url, httpRequest.params)
}
request.open(httpRequest.verb, httpRequest.url, true)
request.responseType = httpRequest.responseType ?? ''
if (!httpRequest.external) {
request.setRequestHeader('X-SNJS-Version', this.snjsVersion)
const appVersionHeaderValue = `${Environment[this.environment]}-${this.appVersion}`
request.setRequestHeader('X-Application-Version', appVersionHeaderValue)
if (httpRequest.authentication) {
request.setRequestHeader('Authorization', 'Bearer ' + httpRequest.authentication)
}
}
let contenTypeIsSet = false
if (httpRequest.customHeaders && httpRequest.customHeaders.length > 0) {
httpRequest.customHeaders.forEach(({ key, value }) => {
request.setRequestHeader(key, value)
if (key === 'Content-Type') {
contenTypeIsSet = true
}
})
}
if (!contenTypeIsSet && !httpRequest.external) {
request.setRequestHeader('Content-Type', 'application/json')
}
return request
}
private async runRequest(request: XMLHttpRequest, body?: string | Uint8Array): Promise<HttpResponse> {
return new Promise((resolve, reject) => {
request.onreadystatechange = () => {
this.stateChangeHandlerForRequest(request, resolve, reject)
}
request.send(body)
})
}
private stateChangeHandlerForRequest(
request: XMLHttpRequest,
resolve: (response: HttpResponse) => void,
reject: (response: HttpResponse) => void,
) {
if (request.readyState !== XMLHttpRequestState.Completed) {
return
}
const httpStatus = request.status
const response: HttpResponse = {
status: httpStatus,
headers: new Map<string, string | null>(),
}
const responseHeaderLines = request
.getAllResponseHeaders()
?.trim()
.split(/[\r\n]+/)
responseHeaderLines?.forEach((responseHeaderLine) => {
const parts = responseHeaderLine.split(': ')
const name = parts.shift() as string
const value = parts.join(': ')
;(<Map<string, string | null>>response.headers).set(name, value)
})
try {
if (httpStatus !== HttpStatusCode.NoContent) {
let body
const contentTypeHeader = response.headers?.get('content-type') || response.headers?.get('Content-Type')
if (contentTypeHeader?.includes('application/json')) {
body = JSON.parse(request.responseText)
} else {
body = request.response
}
/**
* v0 APIs do not have a `data` top-level object. In such cases, mimic
* the newer response body style by putting all the top-level
* properties inside a `data` object.
*/
if (!body.data) {
response.data = body
}
if (!isString(body)) {
Object.assign(response, body)
}
}
} catch (error) {
console.error(error)
}
if (httpStatus >= HttpStatusCode.Success && httpStatus < HttpStatusCode.MultipleChoices) {
resolve(response)
} else {
if (httpStatus === HttpStatusCode.Forbidden && response.data && response.data.error !== undefined) {
;(response.data as HttpErrorResponseBody).error.message = ErrorMessage.RateLimited
}
reject(response)
}
}
private urlForUrlAndParams(url: string, params: HttpRequestParams) {
const keyValueString = Object.keys(params)
.map((key) => {
return key + '=' + encodeURIComponent(params[key] as string)
})
.join('&')
if (url.includes('?')) {
return url + '&' + keyValueString
} else {
return url + '?' + keyValueString
}
}
}
@@ -0,0 +1,11 @@
import { HttpRequestParams } from './HttpRequestParams'
import { HttpResponse } from './HttpResponse'
export interface HttpServiceInterface {
setHost(host: string): void
get(path: string, params?: HttpRequestParams, authentication?: string): Promise<HttpResponse>
post(path: string, params?: HttpRequestParams, authentication?: string): Promise<HttpResponse>
put(path: string, params?: HttpRequestParams, authentication?: string): Promise<HttpResponse>
patch(path: string, params: HttpRequestParams, authentication?: string): Promise<HttpResponse>
delete(path: string, params?: HttpRequestParams, authentication?: string): Promise<HttpResponse>
}
@@ -0,0 +1,9 @@
export enum HttpStatusCode {
Success = 200,
NoContent = 204,
MultipleChoices = 300,
BadRequest = 400,
Unauthorized = 401,
Forbidden = 403,
ExpiredAccessToken = 498,
}
+7
View File
@@ -0,0 +1,7 @@
export enum HttpVerb {
Get = 'GET',
Post = 'POST',
Put = 'PUT',
Patch = 'PATCH',
Delete = 'DELETE',
}
@@ -0,0 +1,3 @@
export enum XMLHttpRequestState {
Completed = 4,
}
+13
View File
@@ -0,0 +1,13 @@
export * from './ErrorTag'
export * from './HttpErrorResponseBody'
export * from './HttpHeaders'
export * from './HttpRequest'
export * from './HttpRequestParams'
export * from './HttpResponse'
export * from './HttpResponseBody'
export * from './HttpResponseMeta'
export * from './HttpService'
export * from './HttpServiceInterface'
export * from './HttpStatusCode'
export * from './HttpVerb'
export * from './XMLHttpRequestState'
@@ -0,0 +1,7 @@
export enum ApiEndpointParam {
LastSyncToken = 'sync_token',
PaginationToken = 'cursor_token',
SyncDlLimit = 'limit',
SyncPayloads = 'items',
ApiVersion = 'api',
}
@@ -0,0 +1,11 @@
import { AnyKeyParamsContent } from '@standardnotes/common'
import { ApiEndpointParam } from '../ApiEndpointParam'
import { ApiVersion } from '../../Api/ApiVersion'
export type UserRegistrationRequestParams = AnyKeyParamsContent & {
[ApiEndpointParam.ApiVersion]: ApiVersion.v0
password: string
email: string
ephemeral: boolean
[additionalParam: string]: unknown
}
+2
View File
@@ -0,0 +1,2 @@
export * from './ApiEndpointParam'
export * from './User/UserRegistrationRequestParams'
@@ -0,0 +1,7 @@
import { HttpErrorResponseBody } from '../../Http/HttpErrorResponseBody'
import { HttpResponse } from '../../Http/HttpResponse'
import { UserRegistrationResponseBody } from './UserRegistrationResponseBody'
export interface UserRegistrationResponse extends HttpResponse {
data: UserRegistrationResponseBody | HttpErrorResponseBody
}
@@ -0,0 +1,11 @@
import { Uuid } from '@standardnotes/common'
import { KeyParamsData, SessionBody } from '@standardnotes/responses'
export type UserRegistrationResponseBody = {
session: SessionBody
key_params: KeyParamsData
user: {
uuid: Uuid
email: string
}
}
@@ -0,0 +1,2 @@
export * from './User/UserRegistrationResponse'
export * from './User/UserRegistrationResponseBody'
@@ -0,0 +1,9 @@
const UserPaths = {
register: '/v1/users',
}
export const Paths = {
v1: {
...UserPaths,
},
}
@@ -0,0 +1,39 @@
import { ProtocolVersion } from '@standardnotes/common'
import { ApiVersion } from '../../Api'
import { HttpServiceInterface } from '../../Http'
import { UserRegistrationResponse } from '../../Response'
import { UserServer } from './UserServer'
describe('UserServer', () => {
let httpService: HttpServiceInterface
const createServer = () => new UserServer(httpService)
beforeEach(() => {
httpService = {} as jest.Mocked<HttpServiceInterface>
httpService.post = jest.fn().mockReturnValue({
data: { user: { email: '[email protected]', uuid: '1-2-3' } },
} as jest.Mocked<UserRegistrationResponse>)
})
it('should register a user', async () => {
const response = await createServer().register({
password: 'test',
api: ApiVersion.v0,
email: '[email protected]',
ephemeral: false,
version: ProtocolVersion.V004,
pw_nonce: 'test',
identifier: '[email protected]',
})
expect(response).toEqual({
data: {
user: {
email: '[email protected]',
uuid: '1-2-3',
},
},
})
})
})
@@ -0,0 +1,15 @@
import { HttpServiceInterface } from '../../Http/HttpServiceInterface'
import { UserRegistrationRequestParams } from '../../Request/User/UserRegistrationRequestParams'
import { UserRegistrationResponse } from '../../Response/User/UserRegistrationResponse'
import { Paths } from './Paths'
import { UserServerInterface } from './UserServerInterface'
export class UserServer implements UserServerInterface {
constructor(private httpService: HttpServiceInterface) {}
async register(params: UserRegistrationRequestParams): Promise<UserRegistrationResponse> {
const response = await this.httpService.post(Paths.v1.register, params)
return response as UserRegistrationResponse
}
}
@@ -0,0 +1,6 @@
import { UserRegistrationRequestParams } from '../../Request/User/UserRegistrationRequestParams'
import { UserRegistrationResponse } from '../../Response/User/UserRegistrationResponse'
export interface UserServerInterface {
register(params: UserRegistrationRequestParams): Promise<UserRegistrationResponse>
}
+3
View File
@@ -0,0 +1,3 @@
export * from './User/Paths'
export * from './User/UserServer'
export * from './User/UserServerInterface'
+7
View File
@@ -0,0 +1,7 @@
export * from './Api'
export * from './Client'
export * from './Error'
export * from './Http'
export * from './Request'
export * from './Response'
export * from './Server'
+1
View File
@@ -0,0 +1 @@
export * from './Domain'
+13
View File
@@ -0,0 +1,13 @@
{
"extends": "../../node_modules/@standardnotes/config/src/tsconfig.json",
"compilerOptions": {
"skipLibCheck": true,
"rootDir": "./src",
"outDir": "./dist",
},
"include": [
"src/**/*"
],
"references": [],
"exclude": ["**/*.spec.ts", "dist", "node_modules"]
}
+6
View File
@@ -3,6 +3,12 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
# [2.7.0](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-07-06)
### Features
* add utils package ([aef4ceb](https://github.com/standardnotes/app/commit/aef4ceb7f85948f1f08b8b09a4db5d187daa371b))
## [2.6.6](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-07-05)
### Bug Fixes
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+5 -5
View File
@@ -71,8 +71,8 @@
},
"org.standardnotes.markdown-visual-editor": {
"version": "1.1.1",
"base64": "d0f20fffcfee7ddb43fe47891e930688378df4044b3471b084b4ecf5986dd109",
"binary": "10c4caf0205901b9ea5f0b83480a1c9986ca78c8609e225e60f9fa7de3e45538"
"base64": "6182ced07fbe9281cf46c1b8818213415e6d34d360bb64883514a7179cf1d7e0",
"binary": "1a99a8ccac07678d0e2e2423b302e5e98cfb100777c37f1795b7874b2d31dcf9"
},
"org.standardnotes.simple-task-editor": {
"version": "1.4.0",
@@ -90,9 +90,9 @@
"binary": "5c8ec3876eef0ff3058fd1b2804fa01b53a869a281a0ff3430f4ddd08abc824d"
},
"org.standardnotes.advanced-checklist": {
"version": "0.1.6",
"base64": "2c23c1f38796d0f725954c478fe0481560f8370c7bd7581433ae612c226e3f70",
"binary": "f218df940adb51641c3ca58a3f225d49aa1b9e2fdd83dfd309b053a32b789160"
"version": "0.2.0",
"base64": "39c032d434210b77e6f8bafa2891a2239b99f0d05f8662a7dbda7c426fe10b4b",
"binary": "1c06d1a846900dcc2818177df6cfaa39e23b56843f8c18f210c6ed73ffdf9cc3"
},
"org.standardnotes.file-safe": {
"version": "2.0.16",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@standardnotes/components-meta",
"version": "2.6.6",
"version": "2.7.0",
"private": true,
"author": "Standard Notes.",
"main": "dist",
@@ -3,6 +3,12 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
# [0.2.0](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-07-06)
### Features
* add utils package ([aef4ceb](https://github.com/standardnotes/app/commit/aef4ceb7f85948f1f08b8b09a4db5d187daa371b))
## [0.1.6](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-07-05)
### Bug Fixes
@@ -1,6 +1,6 @@
{
"name": "@standardnotes/advanced-checklist",
"version": "0.1.6",
"version": "0.2.0",
"description": "A task editor with grouping functionality.",
"author": "Standard Notes.",
"keywords": [
@@ -87,7 +87,7 @@
"@reduxjs/toolkit": "1.8.0",
"@standardnotes/editor-kit": "2.2.5",
"@standardnotes/stylekit": "5.23.0",
"@standardnotes/utils": "1.6.2",
"@standardnotes/utils": "workspace:*",
"@testing-library/dom": "8.11.3",
"@testing-library/jest-dom": "5.16.2",
"@testing-library/react": "12.1.4",
+8
View File
@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [3.23.51](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-07-06)
**Note:** Version bump only for package @standardnotes/desktop
## [3.23.50](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-07-06)
**Note:** Version bump only for package @standardnotes/desktop
## [3.23.49](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-07-05)
**Note:** Version bump only for package @standardnotes/desktop
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "@standardnotes/desktop",
"main": "./app/dist/index.js",
"version": "3.23.49",
"version": "3.23.51",
"license": "AGPL-3.0-or-later",
"author": "Standard Notes.",
"private": true,
+7
View File
@@ -3,6 +3,13 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
# [1.13.0](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-07-06)
### Features
* add sncrypto client side packages ([6ec6679](https://github.com/standardnotes/app/commit/6ec66795d21bdfa5abfa08c3b79b19b5c4cd0449))
* add utils package ([aef4ceb](https://github.com/standardnotes/app/commit/aef4ceb7f85948f1f08b8b09a4db5d187daa371b))
# [1.12.0](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-07-05)
### Features
+4 -4
View File
@@ -1,6 +1,6 @@
{
"name": "@standardnotes/encryption",
"version": "1.12.0",
"version": "1.13.0",
"engines": {
"node": ">=16.0.0 <17.0.0"
},
@@ -40,10 +40,10 @@
"dependencies": {
"@standardnotes/common": "^1.23.1",
"@standardnotes/models": "workspace:*",
"@standardnotes/responses": "^1.6.39",
"@standardnotes/responses": "^1.9.0",
"@standardnotes/services": "workspace:*",
"@standardnotes/sncrypto-common": "^1.9.0",
"@standardnotes/utils": "^1.6.12",
"@standardnotes/sncrypto-common": "workspace:*",
"@standardnotes/utils": "workspace:*",
"reflect-metadata": "^0.1.13"
}
}
+6
View File
@@ -3,6 +3,12 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.50.1](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-07-06)
### Bug Fixes
* not supported auth dependency ([46fe662](https://github.com/standardnotes/app/commit/46fe66256b4cddd70c5401958d29e879a42e431d))
# [1.50.0](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-07-05)
### Features
+2 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@standardnotes/features",
"version": "1.50.0",
"version": "1.50.1",
"engines": {
"node": ">=16.0.0 <17.0.0"
},
@@ -27,6 +27,7 @@
"dependencies": {
"@standardnotes/auth": "^3.19.4",
"@standardnotes/common": "^1.23.1",
"@standardnotes/security": "^1.2.0",
"reflect-metadata": "^0.1.13"
},
"devDependencies": {
+14
View File
@@ -3,6 +3,20 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
# [1.20.0](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-07-06)
### Features
* add responses package ([9d1f704](https://github.com/standardnotes/app/commit/9d1f7043e55cc8072e669606438e932183770f30))
* add sncrypto client side packages ([6ec6679](https://github.com/standardnotes/app/commit/6ec66795d21bdfa5abfa08c3b79b19b5c4cd0449))
* add utils package ([aef4ceb](https://github.com/standardnotes/app/commit/aef4ceb7f85948f1f08b8b09a4db5d187daa371b))
## [1.19.1](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-07-06)
### Bug Fixes
* files system access api dependency on filepicker ([c4e16e4](https://github.com/standardnotes/app/commit/c4e16e4346cb4cc5892ce31a2be7c05331c4dedc))
# [1.19.0](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-07-05)
### Features

Some files were not shown because too many files have changed in this diff Show More