Skip to content

Commit

Permalink
improve workers-shared (#229)
Browse files Browse the repository at this point in the history
  • Loading branch information
quisido authored Jul 19, 2024
1 parent 8c79048 commit 6e8c8e9
Show file tree
Hide file tree
Showing 193 changed files with 3,608 additions and 1,195 deletions.
1 change: 1 addition & 0 deletions .github/workflows/cd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ jobs:
CLOUDWATCH_RUM_APPLICATION_ID: 8495b9c9-f57e-4395-9ca6-6c01862c107b
CLOUDWATCH_RUM_GUEST_ROLE_ARN: arn:aws:iam::787801101157:role/RUM-Monitor-us-west-2-787801101157-0860829251171-Unauth
CLOUDWATCH_RUM_IDENTITY_POOL_ID: us-west-2:f6379e5a-a304-4608-bf6d-b66f00a5d3fb
CSP_ORIGIN: https://csp.quisi.do
DD_API_KEY: ${{ secrets.DATADOG_API_KEY }}
DD_APPLICATION_ID: e29eb164-e193-4380-b512-ebd70bbfaeb6
DD_CLIENT_TOKEN: pubf0c07bd5003d0c4a65a9f129d9e83a3d
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ jobs:
CLOUDWATCH_RUM_APPLICATION_ID: 9be6a855-9bac-4f07-bae8-6ad0d7a00b00
CLOUDWATCH_RUM_GUEST_ROLE_ARN: arn:aws:iam::787801101157:role/RUM-Monitor-us-west-2-787801101157-5868679251171-Unauth
CLOUDWATCH_RUM_IDENTITY_POOL_ID: us-west-2:9d109fe9-23c3-4e33-a478-143f93445968
CSP_ORIGIN: https://localhost:6586
DD_API_KEY: ${{ secrets.DATADOG_API_KEY }}
DD_APPLICATION_ID: 3e55f7ef-a00a-41ab-9857-baf7ad00daa1
DD_CLIENT_TOKEN: pubee0abcc4e08cef309eda284ba1d44e32
Expand Down
Binary file added assets/logo-dark.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/logo-light.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@
"clean": "rm -rf .yarn/cache .yarn/sdks .yarn/unplugged coverage node_modules sarif && rm -f .yarn/build-state.yml .yarn/install-state.gz && yarn workspaces foreach --all --exclude \"@quisi/do\" --interlaced --jobs unlimited --parallel --verbose run clean",
"cloudflare-analytics": "yarn packages/cloudflare-analytics run dev",
"cloudflare-analytics:init": "yarn packages/cloudflare-analytics run init",
"dev": "concurrently --kill-others-on-fail --names authn,next \"yarn run authn\" \"yarn run next\"",
"csp": "yarn packages/csp run dev",
"dev": "concurrently --kill-others-on-fail --names authn,csp,next \"yarn run authn\" \"yarn run csp\" \"yarn run next\"",
"eslint": "eslint . --cache --color --exit-on-fatal-error --max-warnings 0",
"eslint:fix": "eslint . --cache --color --exit-on-fatal-error --fix --max-warnings 0",
"eslint:fix:workspaces": "yarn workspaces foreach --all --exclude \"@quisi/do\" --exclude \"@quisido/next\" --verbose run eslint:fix",
Expand Down
2 changes: 1 addition & 1 deletion packages/authn/eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export default [
},

{
files: ['src/features/handle-fetch.ts', 'src/features/state.ts'],
files: ['src/features/authn-state.ts', 'src/features/handle-fetch.ts'],
rules: {
'max-params': ['error', { max: 5 }],
},
Expand Down
6 changes: 3 additions & 3 deletions packages/authn/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
"local:reinit": "yarn run local:drop && yarn run local:init",
"login": "wrangler login",
"prepack": "exit 0",
"prepublish": "concurrently --kill-others-on-fail --names eslint,vitest \"yarn run eslint\" \"yarn run vitest:run\"",
"prepublish": "concurrently --kill-others-on-fail --names eslint,tsc,vitest \"yarn run eslint\" \"yarn run tsc\" \"yarn run vitest:run\"",
"production:deploy": "wrangler deploy src/index.ts --env production --outdir dist",
"production:deploy:dry-run": "wrangler deploy src/index.ts --dry-run --env production --outdir dist",
"production:init": "yarn run production:init:emails && yarn run production:init:oauth && yarn run production:init:users",
Expand All @@ -30,6 +30,7 @@
"staging:init:emails": "wrangler d1 execute authn-staging --env staging --file=./sql/emails.sql --remote",
"staging:init:oauth": "wrangler d1 execute authn-staging --env staging --file=./sql/oauth.sql --remote",
"staging:init:users": "wrangler d1 execute authn-staging --env staging --file=./sql/users.sql --remote",
"tsc": "tsc --skipLibCheck",
"vitest": "vitest",
"vitest:run": "vitest run",
"vitest:watch": "vitest watch",
Expand All @@ -42,15 +43,14 @@
"cookie": "^0.6.0",
"fmrs": "workspace:^",
"form-urlencoded": "^6.1.5",
"proposal-async-context": "https://github.com/tc39/proposal-async-context",
"tslib": "^2.6.3"
},
"devDependencies": {
"@babel/core": "^7.24.7",
"@babel/preset-env": "^7.24.7",
"@babel/preset-react": "^7.24.7",
"@babel/preset-typescript": "^7.24.7",
"@cloudflare/workers-types": "^4.20240620.0",
"@cloudflare/workers-types": "^4.20240712.0",
"@microsoft/eslint-formatter-sarif": "^3.1.0",
"@quisido/eslint-config": "workspace:^",
"@quisido/vitest-config": "workspace:^",
Expand Down
2 changes: 1 addition & 1 deletion packages/authn/src/constants/default-return-href.ts
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export default 'https://quisi.do/';
export const DEFAULT_RETURN_HREF = 'https://quisi.do/';
4 changes: 1 addition & 3 deletions packages/authn/src/constants/metric-name.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
enum MetricName {
export enum MetricName {
ErrorCode = 'error.code',
FaviconIco = 'pathname.favicon.ico',
InvalidCookieDomain = 'cookie-domain.invalid',
Expand Down Expand Up @@ -51,5 +51,3 @@ enum MetricName {
InvalidUsageDataset = 'dataset.usage.invalid',
MissingUsageDataset = 'dataset.usage.missing',
}

export default MetricName;
8 changes: 3 additions & 5 deletions packages/authn/src/constants/state-var.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import type State from '../features/state.js';
import RequiredVariable from '../utils/required-variable.js';
import { RequiredVariable } from '@quisido/workers-shared';
import AuthnState from '../features/authn-state.js';

const stateVar: RequiredVariable<State> = new RequiredVariable<State>({
export const STATE_VAR = new RequiredVariable<AuthnState>({
name: 'state',
});

export default stateVar;
36 changes: 36 additions & 0 deletions packages/authn/src/features/authn-state.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { State } from '@quisido/workers-shared';
import { type IncomingRequest } from 'cloudflare-utils';
import { MetricName } from '../constants/metric-name.js';
import type { AuthnMetric } from '../types/authn-metric.js';
import createReturnHref from './create-return-href.js';

export default class AuthnState extends State<AuthnMetric> {
#returnHref: string | null = null;

public constructor(
console: Console,
fetch: Fetcher['fetch'],
request: IncomingRequest,
env: Record<string, unknown>,
ctx: ExecutionContext,
) {
super(console, fetch, request, env, ctx, {
invalidPrivateDatasetMetricName: MetricName.InvalidPrivateDataset,
invalidPublicDatasetMetricName: MetricName.InvalidPublicDataset,
invalidTraceParentMetricName: MetricName.InvalidTraceParent,
invalidUsageDatasetMetricName: MetricName.InvalidUsageDataset,
missingPrivateDatasetMetricName: MetricName.MissingPrivateDataset,
missingPublicDatasetMetricName: MetricName.MissingPublicDataset,
missingTraceParentMetricName: MetricName.MissingTraceParent,
missingUsageDatasetMetricName: MetricName.MissingUsageDataset,
});
}

public get returnHref(): string | null {
return this.#returnHref;
}

public setReturnHref(): void {
this.#returnHref = createReturnHref();
}
}
2 changes: 1 addition & 1 deletion packages/authn/src/features/error-response-init.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { ErrorCode } from '@quisido/authn-shared';
import DEFAULT_RETURN_HREF from '../constants/default-return-href.js';
import { DEFAULT_RETURN_HREF } from '../constants/default-return-href.js';
import StatusCode from '../constants/status-code.js';
import getReturnHref from '../utils/get-return-href.js';
import ResponseInitImpl from '../utils/response-init.js';
Expand Down
15 changes: 6 additions & 9 deletions packages/authn/src/features/get-cookie-domain.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { mapUnknownToString } from 'fmrs';
import MetricName from '../constants/metric-name.js';
import { MetricName } from '../constants/metric-name.js';
import getEnv from '../utils/get-env.js';
import getTelemetry from '../utils/get-telemetry.js';

Expand All @@ -11,25 +11,22 @@ export default function getCookieDomain(): string {
return COOKIE_DOMAIN;
}

const { emitPublicMetric, logPrivateError, logPublicError } = getTelemetry();
const { emitPublicMetric, logPrivateError } = getTelemetry();
if (typeof COOKIE_DOMAIN === 'undefined') {
emitPublicMetric({ name: MetricName.MissingCookieDomain });
return DEFAULT_COOKIE_DOMAIN;
}

emitPublicMetric({ name: MetricName.InvalidCookieDomain });
emitPublicMetric({
name: MetricName.InvalidCookieDomain,
type: typeof COOKIE_DOMAIN,
});

logPrivateError(
new Error('Invalid cookie domain', {
cause: mapUnknownToString(COOKIE_DOMAIN),
}),
);

logPublicError(
new Error('Invalid cookie domain', {
cause: typeof COOKIE_DOMAIN,
}),
);

return DEFAULT_COOKIE_DOMAIN;
}
9 changes: 7 additions & 2 deletions packages/authn/src/features/get-data-bucket.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { isR2Bucket } from 'cloudflare-utils';
import { mapUnknownToString } from 'fmrs';
import MetricName from '../constants/metric-name.js';
import { MetricName } from '../constants/metric-name.js';
import getEnv from '../utils/get-env.js';
import getTelemetry from '../utils/get-telemetry.js';

Expand All @@ -16,11 +16,16 @@ export default function getDataBucket(): R2Bucket | null {
return null;
}

emitPublicMetric({ name: MetricName.InvalidDataBucket });
emitPublicMetric({
name: MetricName.InvalidDataBucket,
type: typeof AUTHN_DATA,
});

logPrivateError(
new Error('Invalid data bucket', {
cause: mapUnknownToString(AUTHN_DATA),
}),
);

return null;
}
2 changes: 1 addition & 1 deletion packages/authn/src/features/get-database-user-id.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { ErrorCode } from '@quisido/authn-shared';
import { AccountNumber, UsageType } from '@quisido/workers-shared';
import MetricName from '../constants/metric-name.js';
import { MetricName } from '../constants/metric-name.js';
import type OAuthProvider from '../constants/oauth-provider.js';
import getTelemetry from '../utils/get-telemetry.js';
import isObject from '../utils/is-object.js';
Expand Down
4 changes: 2 additions & 2 deletions packages/authn/src/features/get-environment-name.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { describe, expect, it } from 'vitest';
import MetricName from '../constants/metric-name.js';
import { MetricName } from '../constants/metric-name.js';
import fetch from '../test/fetch.js';

const DEFAULT_TRACE_FLAGS = 0;
Expand Down Expand Up @@ -34,7 +34,7 @@ describe('getEnvironmentName', (): void => {
});

expectPublicDataPoint({
blobs: [expect.any(String) as string, '0000000000000000'],
blobs: [expect.any(String) as string, '0000000000000000', 'string'],
indexes: [MetricName.InvalidEnvironmentName],

doubles: [
Expand Down
9 changes: 7 additions & 2 deletions packages/authn/src/features/get-environment-name.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { mapUnknownToString } from 'fmrs';
import EnvironmentName from '../constants/environment-name.js';
import MetricName from '../constants/metric-name.js';
import { MetricName } from '../constants/metric-name.js';
import getEnv from '../utils/get-env.js';
import getTelemetry from '../utils/get-telemetry.js';
import isEnvironmentName from '../utils/is-environment-name.js';
Expand All @@ -17,11 +17,16 @@ export default function getEnvironmentName(): EnvironmentName {
return EnvironmentName.Unknown;
}

emitPublicMetric({ name: MetricName.InvalidEnvironmentName });
emitPublicMetric({
name: MetricName.InvalidEnvironmentName,
type: typeof ENVIRONMENT_NAME,
});

logPrivateError(
new Error('Invalid environment name', {
cause: mapUnknownToString(ENVIRONMENT_NAME),
}),
);

return EnvironmentName.Unknown;
}
9 changes: 7 additions & 2 deletions packages/authn/src/features/get-host.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { mapUnknownToString } from 'fmrs';
import MetricName from '../constants/metric-name.js';
import { MetricName } from '../constants/metric-name.js';
import getEnv from '../utils/get-env.js';
import getTelemetry from '../utils/get-telemetry.js';

Expand All @@ -17,9 +17,14 @@ export default function getHost(): string {
return DEFAULT_HOST;
}

emitPublicMetric({ name: MetricName.InvalidHost });
emitPublicMetric({
name: MetricName.InvalidHost,
type: typeof HOST,
});

logPrivateError(
new Error('Invalid host', { cause: mapUnknownToString(HOST) }),
);

return DEFAULT_HOST;
}
2 changes: 1 addition & 1 deletion packages/authn/src/features/handle-fetch-error-cause.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import MetricName from '../constants/metric-name.js';
import { MetricName } from '../constants/metric-name.js';
import type Cause from '../types/cause.js';
import createDataError from '../utils/create-data-error.js';
import getTelemetry from '../utils/get-telemetry.js';
Expand Down
36 changes: 14 additions & 22 deletions packages/authn/src/features/handle-fetch.ts
Original file line number Diff line number Diff line change
@@ -1,41 +1,33 @@
import stateVar from '../constants/state-var.js';
import createTraceId from '../utils/create-trace-id.js';
import { type IncomingRequest } from 'cloudflare-utils';
import { STATE_VAR } from '../constants/state-var.js';
import isObject from '../utils/is-object.js';
import AuthnState from './authn-state.js';
import handleFetchError from './handle-fetch-error.js';
import handleFetchRequest from './handle-fetch-request.js';
import handleInvalidIsolateEnvironment from './handle-invalid-isolate-environment.js';
import handleMissingIsolateEnvironment from './handle-missing-isolate-environment.js';
import State from './state.js';

export default async function handleFetch(
fetch: Fetcher['fetch'],
console: Console,
request: Request,
fetch: Fetcher['fetch'],
request: IncomingRequest,
env: unknown,
ctx: ExecutionContext,
): Promise<Response> {
const traceId: string = createTraceId();
const state: State = new State(fetch, console, request, ctx, traceId);
return stateVar.run(state, async (): Promise<Response> => {
if (typeof env === 'undefined') {
return handleMissingIsolateEnvironment();
}
if (typeof env === 'undefined') {
return handleMissingIsolateEnvironment();
}

if (!isObject(env)) {
return handleInvalidIsolateEnvironment();
}
if (!isObject(env)) {
return handleInvalidIsolateEnvironment();
}

const state = new AuthnState(console, fetch, request, env, ctx);
return STATE_VAR.run(state, async (): Promise<Response> => {
try {
/**
* We cannot set `env` when we instantiate state, because we throw
* stateful errors when validating it here.
*/
state.setEnv(env);
return await handleFetchRequest();
} catch (err: unknown) {
return stateVar.run(state, (): Response => handleFetchError(err));
} finally {
state.flushTelemetry();
return STATE_VAR.run(state, (): Response => handleFetchError(err));
}
});
}
15 changes: 12 additions & 3 deletions packages/authn/src/features/handle-insert-into-emails-error.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,31 @@
import { mapUnknownToError } from 'fmrs';
import MetricName from '../constants/metric-name.js';
import { MetricName } from '../constants/metric-name.js';
import getTelemetry from '../utils/get-telemetry.js';

export default function handleInsertIntoEmailsError(
userId: number,
): (err: unknown) => void {
const { emitPublicMetric, logPrivateError } = getTelemetry();
const { emitPrivateMetric, emitPublicMetric, logPrivateError } =
getTelemetry();
const startTime: number = Date.now();

return function handleCatch(err: unknown): void {
const endTime: number = Date.now();
logPrivateError(mapUnknownToError(err));
emitPublicMetric({

emitPrivateMetric({
duration: endTime - startTime,
endTime,
name: MetricName.EmailInsertError,
startTime,
userId,
});

emitPublicMetric({
duration: endTime - startTime,
endTime,
name: MetricName.EmailInsertError,
startTime,
});
};
}
Loading

0 comments on commit 6e8c8e9

Please sign in to comment.