npm run fmt
This commit is contained in:
parent
21fe35da05
commit
11c595619d
21 changed files with 155 additions and 137 deletions
|
|
@ -7,7 +7,8 @@ export const registerNextAuth = async (
|
||||||
server: Hapi.Server,
|
server: Hapi.Server,
|
||||||
config: IAppConfig
|
config: IAppConfig
|
||||||
): Promise<void> => {
|
): Promise<void> => {
|
||||||
const nextAuthAdapterFactory: any = (request: Hapi.Request) => new NextAuthAdapter(request.db());
|
const nextAuthAdapterFactory: any = (request: Hapi.Request) =>
|
||||||
|
new NextAuthAdapter(request.db());
|
||||||
|
|
||||||
await server.register({
|
await server.register({
|
||||||
plugin: NextAuthPlugin,
|
plugin: NextAuthPlugin,
|
||||||
|
|
|
||||||
|
|
@ -38,5 +38,5 @@ export const register = async (
|
||||||
await registerSwagger(server);
|
await registerSwagger(server);
|
||||||
await registerCloudflareAccessJwt(server, config);
|
await registerCloudflareAccessJwt(server, config);
|
||||||
await registerAuthBearer(server, config);
|
await registerAuthBearer(server, config);
|
||||||
await registerPostgraphile(server, config)
|
await registerPostgraphile(server, config);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -66,7 +66,7 @@ export const VoiceProviderRoutes = Helpers.withDefaults([
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
class VoiceLineRecordController extends CrudControllerBase(VoiceLineRecord) { }
|
class VoiceLineRecordController extends CrudControllerBase(VoiceLineRecord) {}
|
||||||
|
|
||||||
const validator = (): Record<string, Hapi.RouteOptionsValidate> => ({
|
const validator = (): Record<string, Hapi.RouteOptionsValidate> => ({
|
||||||
create: {
|
create: {
|
||||||
|
|
|
||||||
|
|
@ -91,7 +91,7 @@ export const TwilioRoutes = Helpers.noAuth([
|
||||||
},
|
},
|
||||||
async handler(request: Hapi.Request, _h: Hapi.ResponseToolkit) {
|
async handler(request: Hapi.Request, _h: Hapi.ResponseToolkit) {
|
||||||
const { voiceLineId } = request.params;
|
const { voiceLineId } = request.params;
|
||||||
const { To } = request.payload as { To: string; };
|
const { To } = request.payload as { To: string };
|
||||||
const voiceLine = await request.db().voiceLines.findBy({ number: To });
|
const voiceLine = await request.db().voiceLines.findBy({ number: To });
|
||||||
if (!voiceLine) return Boom.notFound();
|
if (!voiceLine) return Boom.notFound();
|
||||||
if (voiceLine.id !== voiceLineId) return Boom.badRequest();
|
if (voiceLine.id !== voiceLineId) return Boom.badRequest();
|
||||||
|
|
@ -193,7 +193,7 @@ export const TwilioRoutes = Helpers.noAuth([
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
async handler(request: Hapi.Request, h: Hapi.ResponseToolkit) {
|
async handler(request: Hapi.Request, h: Hapi.ResponseToolkit) {
|
||||||
const { providerId } = request.params as { providerId: string; };
|
const { providerId } = request.params as { providerId: string };
|
||||||
const provider: SavedVoiceProvider = await request
|
const provider: SavedVoiceProvider = await request
|
||||||
.db()
|
.db()
|
||||||
.voiceProviders.findById({ id: providerId });
|
.voiceProviders.findById({ id: providerId });
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,2 @@
|
||||||
export * from "./server/index.js"
|
export * from "./server/index.js";
|
||||||
export * from "./logger.js"
|
export * from "./logger.js";
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,3 @@
|
||||||
export {default as AppBar} from "./AppBar";
|
export { default as AppBar } from "./AppBar";
|
||||||
export {default as Layout} from "./Layout";
|
export { default as Layout } from "./Layout";
|
||||||
export {default as Menu} from "./Menu";
|
export { default as Menu } from "./Menu";
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,9 @@ export const theme = {
|
||||||
background: {
|
background: {
|
||||||
default: "#fff",
|
default: "#fff",
|
||||||
},
|
},
|
||||||
getContrastText(color: string) { return color === "#ffffff" ? "#000" : "#fff"; },
|
getContrastText(color: string) {
|
||||||
|
return color === "#ffffff" ? "#000" : "#fff";
|
||||||
|
},
|
||||||
},
|
},
|
||||||
shape: {
|
shape: {
|
||||||
borderRadius: 5,
|
borderRadius: 5,
|
||||||
|
|
|
||||||
|
|
@ -25,8 +25,7 @@ const customEnglishMessages: TranslationMessages = {
|
||||||
signalBots: {
|
signalBots: {
|
||||||
name: "Signal Bot |||| Signal Bots",
|
name: "Signal Bot |||| Signal Bots",
|
||||||
verifyDialog: {
|
verifyDialog: {
|
||||||
sms:
|
sms: "Please enter the verification code sent via SMS to %{phoneNumber}",
|
||||||
"Please enter the verification code sent via SMS to %{phoneNumber}",
|
|
||||||
voice:
|
voice:
|
||||||
"Please answer the call from Signal to %{phoneNumber} and enter the verification code",
|
"Please answer the call from Signal to %{phoneNumber} and enter the verification code",
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -100,13 +100,15 @@ export const getIdentity = async (
|
||||||
|
|
||||||
const cloudflareAccountProvider = "cloudflare-access";
|
const cloudflareAccountProvider = "cloudflare-access";
|
||||||
|
|
||||||
const cloudflareAuthorizeCallback = (
|
const cloudflareAuthorizeCallback =
|
||||||
req: IncomingMessage,
|
(
|
||||||
domain: string,
|
req: IncomingMessage,
|
||||||
verifier: VerifyFn,
|
domain: string,
|
||||||
adapter: Adapter
|
verifier: VerifyFn,
|
||||||
): (() => Promise<any>) => async () => {
|
adapter: Adapter
|
||||||
/*
|
): (() => Promise<any>) =>
|
||||||
|
async () => {
|
||||||
|
/*
|
||||||
|
|
||||||
lots of little variables in here.
|
lots of little variables in here.
|
||||||
|
|
||||||
|
|
@ -118,75 +120,75 @@ const cloudflareAuthorizeCallback = (
|
||||||
profile: this is the accumulated user information we have that we will fetch/build the user record with
|
profile: this is the accumulated user information we have that we will fetch/build the user record with
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const { token, decoded } = await verifyRequest(verifier, req);
|
const { token, decoded } = await verifyRequest(verifier, req);
|
||||||
|
|
||||||
const profile = {
|
const profile = {
|
||||||
email: undefined,
|
email: undefined,
|
||||||
name: undefined,
|
name: undefined,
|
||||||
avatar: undefined,
|
avatar: undefined,
|
||||||
|
};
|
||||||
|
if (decoded.email) profile.email = decoded.email;
|
||||||
|
if (decoded.name) profile.name = decoded.name;
|
||||||
|
const identity = await getIdentity(domain, token);
|
||||||
|
|
||||||
|
if (identity.email) profile.email = identity.email;
|
||||||
|
if (identity.name) profile.name = identity.name;
|
||||||
|
|
||||||
|
if (!profile.email)
|
||||||
|
throw new Error("cloudflare access authorization: email not found");
|
||||||
|
|
||||||
|
const providerId = `cfaccess|${identity.idp.type}|${identity.idp.id}`;
|
||||||
|
const providerAccountId = identity.user_uuid;
|
||||||
|
|
||||||
|
if (!providerAccountId)
|
||||||
|
throw new Error(
|
||||||
|
"cloudflare access authorization: missing provider account id"
|
||||||
|
);
|
||||||
|
|
||||||
|
const {
|
||||||
|
getUserByProviderAccountId,
|
||||||
|
getUserByEmail,
|
||||||
|
createUser,
|
||||||
|
linkAccount,
|
||||||
|
} =
|
||||||
|
// @ts-expect-error: non-existent property
|
||||||
|
await adapter.getAdapter({} as any);
|
||||||
|
|
||||||
|
const userByProviderAccountId = await getUserByProviderAccountId(
|
||||||
|
providerId,
|
||||||
|
providerAccountId
|
||||||
|
);
|
||||||
|
if (userByProviderAccountId) {
|
||||||
|
return userByProviderAccountId;
|
||||||
|
}
|
||||||
|
|
||||||
|
const userByEmail = await getUserByEmail(profile.email);
|
||||||
|
if (userByEmail) {
|
||||||
|
// we will not explicitly link accounts
|
||||||
|
throw new Error(
|
||||||
|
"cloudflare access authorization: user exists for email address, but is not linked."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const user = await createUser(profile);
|
||||||
|
|
||||||
|
// between the previous line and the next line exists a transactional bug
|
||||||
|
// https://github.com/nextauthjs/next-auth/issues/876
|
||||||
|
// hopefully we don't experience it
|
||||||
|
|
||||||
|
await linkAccount(
|
||||||
|
user.id,
|
||||||
|
providerId,
|
||||||
|
cloudflareAccountProvider,
|
||||||
|
providerAccountId,
|
||||||
|
// the following are unused but are specified for completness
|
||||||
|
undefined,
|
||||||
|
undefined,
|
||||||
|
undefined
|
||||||
|
);
|
||||||
|
|
||||||
|
return user;
|
||||||
};
|
};
|
||||||
if (decoded.email) profile.email = decoded.email;
|
|
||||||
if (decoded.name) profile.name = decoded.name;
|
|
||||||
const identity = await getIdentity(domain, token);
|
|
||||||
|
|
||||||
if (identity.email) profile.email = identity.email;
|
|
||||||
if (identity.name) profile.name = identity.name;
|
|
||||||
|
|
||||||
if (!profile.email)
|
|
||||||
throw new Error("cloudflare access authorization: email not found");
|
|
||||||
|
|
||||||
const providerId = `cfaccess|${identity.idp.type}|${identity.idp.id}`;
|
|
||||||
const providerAccountId = identity.user_uuid;
|
|
||||||
|
|
||||||
if (!providerAccountId)
|
|
||||||
throw new Error(
|
|
||||||
"cloudflare access authorization: missing provider account id"
|
|
||||||
);
|
|
||||||
|
|
||||||
const {
|
|
||||||
getUserByProviderAccountId,
|
|
||||||
getUserByEmail,
|
|
||||||
createUser,
|
|
||||||
linkAccount,
|
|
||||||
} =
|
|
||||||
// @ts-expect-error: non-existent property
|
|
||||||
await adapter.getAdapter({} as any);
|
|
||||||
|
|
||||||
const userByProviderAccountId = await getUserByProviderAccountId(
|
|
||||||
providerId,
|
|
||||||
providerAccountId
|
|
||||||
);
|
|
||||||
if (userByProviderAccountId) {
|
|
||||||
return userByProviderAccountId;
|
|
||||||
}
|
|
||||||
|
|
||||||
const userByEmail = await getUserByEmail(profile.email);
|
|
||||||
if (userByEmail) {
|
|
||||||
// we will not explicitly link accounts
|
|
||||||
throw new Error(
|
|
||||||
"cloudflare access authorization: user exists for email address, but is not linked."
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const user = await createUser(profile);
|
|
||||||
|
|
||||||
// between the previous line and the next line exists a transactional bug
|
|
||||||
// https://github.com/nextauthjs/next-auth/issues/876
|
|
||||||
// hopefully we don't experience it
|
|
||||||
|
|
||||||
await linkAccount(
|
|
||||||
user.id,
|
|
||||||
providerId,
|
|
||||||
cloudflareAccountProvider,
|
|
||||||
providerAccountId,
|
|
||||||
// the following are unused but are specified for completness
|
|
||||||
undefined,
|
|
||||||
undefined,
|
|
||||||
undefined
|
|
||||||
);
|
|
||||||
|
|
||||||
return user;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param audience the cloudflare access audience id
|
* @param audience the cloudflare access audience id
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,10 @@
|
||||||
/* eslint-disable unicorn/no-null */
|
/* eslint-disable unicorn/no-null */
|
||||||
import type { Adapter, AdapterAccount, AdapterSession, AdapterUser } from "next-auth/adapters";
|
import type {
|
||||||
|
Adapter,
|
||||||
|
AdapterAccount,
|
||||||
|
AdapterSession,
|
||||||
|
AdapterUser,
|
||||||
|
} from "next-auth/adapters";
|
||||||
import * as Wreck from "@hapi/wreck";
|
import * as Wreck from "@hapi/wreck";
|
||||||
import * as Boom from "@hapi/boom";
|
import * as Boom from "@hapi/boom";
|
||||||
|
|
||||||
|
|
@ -15,7 +20,7 @@ export interface Profile {
|
||||||
createdBy: string;
|
createdBy: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type User = Profile & { id: string; createdAt: Date; updatedAt: Date; };
|
export type User = Profile & { id: string; createdAt: Date; updatedAt: Date };
|
||||||
|
|
||||||
export interface Session {
|
export interface Session {
|
||||||
userId: string;
|
userId: string;
|
||||||
|
|
@ -103,7 +108,13 @@ export const MetamigoAdapter = (config: IAppConfig): Adapter => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getUserByAccount({ providerAccountId, provider }: { providerAccountId: string, provider: string }) {
|
async function getUserByAccount({
|
||||||
|
providerAccountId,
|
||||||
|
provider,
|
||||||
|
}: {
|
||||||
|
providerAccountId: string;
|
||||||
|
provider: string;
|
||||||
|
}) {
|
||||||
try {
|
try {
|
||||||
const { payload } = await wreck.get(
|
const { payload } = await wreck.get(
|
||||||
`getUserByAccount/${provider}/${providerAccountId}`
|
`getUserByAccount/${provider}/${providerAccountId}`
|
||||||
|
|
@ -112,7 +123,7 @@ export const MetamigoAdapter = (config: IAppConfig): Adapter => {
|
||||||
return payload;
|
return payload;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (Boom.isBoom(error, 404)) return null;
|
if (Boom.isBoom(error, 404)) return null;
|
||||||
console.log(error)
|
console.log(error);
|
||||||
throw new Error("GET_USER_BY_ACCOUNT");
|
throw new Error("GET_USER_BY_ACCOUNT");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -129,12 +140,10 @@ export const MetamigoAdapter = (config: IAppConfig): Adapter => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function linkAccount(
|
async function linkAccount(account: AdapterAccount) {
|
||||||
account: AdapterAccount
|
|
||||||
) {
|
|
||||||
try {
|
try {
|
||||||
await wreck.put("linkAccount", {payload: account} as any );
|
await wreck.put("linkAccount", { payload: account } as any);
|
||||||
} catch(error) {
|
} catch (error) {
|
||||||
console.log(error);
|
console.log(error);
|
||||||
throw new Error("LINK_ACCOUNT_ERROR");
|
throw new Error("LINK_ACCOUNT_ERROR");
|
||||||
}
|
}
|
||||||
|
|
@ -142,25 +151,33 @@ export const MetamigoAdapter = (config: IAppConfig): Adapter => {
|
||||||
|
|
||||||
async function createSession(user: User) {
|
async function createSession(user: User) {
|
||||||
try {
|
try {
|
||||||
const { payload }: {payload: AdapterSession} = await wreck.post("createSession", {
|
const { payload }: { payload: AdapterSession } = await wreck.post(
|
||||||
payload: user,
|
"createSession",
|
||||||
});
|
{
|
||||||
payload.expires = new Date(payload.expires)
|
payload: user,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
payload.expires = new Date(payload.expires);
|
||||||
return payload;
|
return payload;
|
||||||
} catch(error) {
|
} catch (error) {
|
||||||
console.log(error)
|
console.log(error);
|
||||||
throw new Error("CREATE_SESSION_ERROR");
|
throw new Error("CREATE_SESSION_ERROR");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getSessionAndUser(sessionToken: string) {
|
async function getSessionAndUser(sessionToken: string) {
|
||||||
try {
|
try {
|
||||||
const {payload}: {payload: any} = await wreck.get(`getSessionAndUser/${sessionToken}`);
|
const { payload }: { payload: any } = await wreck.get(
|
||||||
const { session, user }: {session: AdapterSession, user: AdapterUser} = payload;
|
`getSessionAndUser/${sessionToken}`
|
||||||
session.expires = new Date(session.expires)
|
);
|
||||||
return {session, user}
|
const {
|
||||||
|
session,
|
||||||
|
user,
|
||||||
|
}: { session: AdapterSession; user: AdapterUser } = payload;
|
||||||
|
session.expires = new Date(session.expires);
|
||||||
|
return { session, user };
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error)
|
console.log(error);
|
||||||
if (Boom.isBoom(error, 404)) return null;
|
if (Boom.isBoom(error, 404)) return null;
|
||||||
throw new Error("GET_SESSION_AND_USER_ERROR");
|
throw new Error("GET_SESSION_AND_USER_ERROR");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,8 @@ export const E164Regex = /^\+[1-9]\d{1,14}$/;
|
||||||
/**
|
/**
|
||||||
* Returns true if the number is a valid E164 number
|
* Returns true if the number is a valid E164 number
|
||||||
*/
|
*/
|
||||||
export const isValidE164Number = (phoneNumber: string) => E164Regex.test(phoneNumber);
|
export const isValidE164Number = (phoneNumber: string) =>
|
||||||
|
E164Regex.test(phoneNumber);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Given a phone number approximation, will clean out whitespace and punctuation.
|
* Given a phone number approximation, will clean out whitespace and punctuation.
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@
|
||||||
"test": "echo no tests",
|
"test": "echo no tests",
|
||||||
"lint": "eslint --ext .js,.jsx,.ts,.tsx,.graphql && next lint && prettier --ignore-path .eslintignore \"**/*.{js,jsx,ts,tsx,graphql,md}\" --write",
|
"lint": "eslint --ext .js,.jsx,.ts,.tsx,.graphql && next lint && prettier --ignore-path .eslintignore \"**/*.{js,jsx,ts,tsx,graphql,md}\" --write",
|
||||||
"fix:lint": "eslint --ext .js,.jsx,.ts,.tsx,.graphql --fix",
|
"fix:lint": "eslint --ext .js,.jsx,.ts,.tsx,.graphql --fix",
|
||||||
"fmt": "prettier --ignore-path .eslintignore \"**/*.{js,jsx,ts,tsx,graphql,md}\" --list-different"
|
"fmt": "prettier --ignore-path .eslintignore \"**/*.{js,jsx,ts,tsx,graphql,md}\" --write"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@next/eslint-plugin-next": "^13.4.4",
|
"@next/eslint-plugin-next": "^13.4.4",
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,8 @@
|
||||||
"dev": "dotenv -- turbo run dev --concurrency 30",
|
"dev": "dotenv -- turbo run dev --concurrency 30",
|
||||||
"build": "turbo build --concurrency 30",
|
"build": "turbo build --concurrency 30",
|
||||||
"dev:metamigo": "make dev-metamigo && dotenv -- turbo run dev --concurrency 30 --filter=!link --filter=!leafcutter",
|
"dev:metamigo": "make dev-metamigo && dotenv -- turbo run dev --concurrency 30 --filter=!link --filter=!leafcutter",
|
||||||
"migrate": "dotenv -- npm run migrate --workspace=@digiresilience/metamigo-cli"
|
"migrate": "dotenv -- npm run migrate --workspace=@digiresilience/metamigo-cli",
|
||||||
|
"fmt": "turbo run fmt"
|
||||||
},
|
},
|
||||||
"packageManager": "npm@9.3.1",
|
"packageManager": "npm@9.3.1",
|
||||||
"workspaces": [
|
"workspaces": [
|
||||||
|
|
|
||||||
|
|
@ -62,12 +62,11 @@ const register = async (
|
||||||
server: Hapi.Server,
|
server: Hapi.Server,
|
||||||
pluginOpts?: any
|
pluginOpts?: any
|
||||||
): Promise<void> => {
|
): Promise<void> => {
|
||||||
const options: any =
|
const options: any = Hoek.applyToDefaults(
|
||||||
Hoek.applyToDefaults(
|
// a little type gymnastics here to workaround poor typing
|
||||||
// a little type gymnastics here to workaround poor typing
|
defaultOptions as any,
|
||||||
defaultOptions as any,
|
pluginOpts
|
||||||
pluginOpts
|
) as any;
|
||||||
) as any;
|
|
||||||
|
|
||||||
if (!options.nextAuthAdapterFactory) {
|
if (!options.nextAuthAdapterFactory) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,7 @@ import type { Adapter } from "next-auth/adapters";
|
||||||
import type { NumberSchema, StringSchema, ObjectSchema } from "joi";
|
import type { NumberSchema, StringSchema, ObjectSchema } from "joi";
|
||||||
import type { Request } from "@hapi/hapi";
|
import type { Request } from "@hapi/hapi";
|
||||||
|
|
||||||
export type AdapterFactory = (
|
export type AdapterFactory = (request: Request) => Adapter;
|
||||||
request: Request
|
|
||||||
) => Adapter;
|
|
||||||
|
|
||||||
export interface NextAuthPluginOptions {
|
export interface NextAuthPluginOptions {
|
||||||
nextAuthAdapterFactory: Adapter;
|
nextAuthAdapterFactory: Adapter;
|
||||||
|
|
|
||||||
|
|
@ -268,60 +268,60 @@ export const configSchema = {
|
||||||
doc: "The full base zammad api url",
|
doc: "The full base zammad api url",
|
||||||
format: String,
|
format: String,
|
||||||
default: undefined,
|
default: undefined,
|
||||||
env: "ZAMMAD_API_URL"
|
env: "ZAMMAD_API_URL",
|
||||||
},
|
},
|
||||||
zammadApiKey: {
|
zammadApiKey: {
|
||||||
doc: "The zammad api key",
|
doc: "The zammad api key",
|
||||||
format: String,
|
format: String,
|
||||||
default: undefined,
|
default: undefined,
|
||||||
sensitive: true,
|
sensitive: true,
|
||||||
env: "ZAMMAD_API_KEY"
|
env: "ZAMMAD_API_KEY",
|
||||||
},
|
},
|
||||||
labelStudioApiUrl: {
|
labelStudioApiUrl: {
|
||||||
doc: "The full base label studio api url",
|
doc: "The full base label studio api url",
|
||||||
format: String,
|
format: String,
|
||||||
default: undefined,
|
default: undefined,
|
||||||
env: "LABEL_STUDIO_API_URL"
|
env: "LABEL_STUDIO_API_URL",
|
||||||
},
|
},
|
||||||
labelStudioApiKey: {
|
labelStudioApiKey: {
|
||||||
doc: "The label studio api key",
|
doc: "The label studio api key",
|
||||||
format: String,
|
format: String,
|
||||||
default: undefined,
|
default: undefined,
|
||||||
sensitive: true,
|
sensitive: true,
|
||||||
env: "LABEL_STUDIO_API_KEY"
|
env: "LABEL_STUDIO_API_KEY",
|
||||||
},
|
},
|
||||||
contributorId: {
|
contributorId: {
|
||||||
doc: "The leafcutter contributor id",
|
doc: "The leafcutter contributor id",
|
||||||
format: String,
|
format: String,
|
||||||
default: undefined,
|
default: undefined,
|
||||||
env: "LEAFCUTTER_CONTRIBUTOR_ID"
|
env: "LEAFCUTTER_CONTRIBUTOR_ID",
|
||||||
},
|
},
|
||||||
contributorName: {
|
contributorName: {
|
||||||
doc: "The leafcutter contributor name",
|
doc: "The leafcutter contributor name",
|
||||||
format: String,
|
format: String,
|
||||||
default: undefined,
|
default: undefined,
|
||||||
env: "LEAFCUTTER_CONTRIBUTOR_NAME"
|
env: "LEAFCUTTER_CONTRIBUTOR_NAME",
|
||||||
},
|
},
|
||||||
opensearchApiUrl: {
|
opensearchApiUrl: {
|
||||||
doc: "The opensearch api url",
|
doc: "The opensearch api url",
|
||||||
format: String,
|
format: String,
|
||||||
default: undefined,
|
default: undefined,
|
||||||
env: "OPENSEARCH_API_URL"
|
env: "OPENSEARCH_API_URL",
|
||||||
},
|
},
|
||||||
opensearchUsername: {
|
opensearchUsername: {
|
||||||
doc: "The opensearch username",
|
doc: "The opensearch username",
|
||||||
format: String,
|
format: String,
|
||||||
default: undefined,
|
default: undefined,
|
||||||
env: "OPENSEARCH_USERNAME"
|
env: "OPENSEARCH_USERNAME",
|
||||||
},
|
},
|
||||||
opensearchPassword: {
|
opensearchPassword: {
|
||||||
doc: "The opensearch password",
|
doc: "The opensearch password",
|
||||||
format: String,
|
format: String,
|
||||||
default: undefined,
|
default: undefined,
|
||||||
sensative: true,
|
sensative: true,
|
||||||
env: "OPENSEARCH_PASSWORD"
|
env: "OPENSEARCH_PASSWORD",
|
||||||
},
|
},
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
// define the interfaces for the concrete config objects
|
// define the interfaces for the concrete config objects
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import process from "node:process";
|
||||||
import { existsSync } from "node:fs";
|
import { existsSync } from "node:fs";
|
||||||
import path from "node:path";
|
import path from "node:path";
|
||||||
import { exec } from "node:child_process";
|
import { exec } from "node:child_process";
|
||||||
import { fileURLToPath } from 'node:url';
|
import { fileURLToPath } from "node:url";
|
||||||
import type { IAppConfig } from "@digiresilience/metamigo-config";
|
import type { IAppConfig } from "@digiresilience/metamigo-config";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -37,8 +37,8 @@ export const migrateWrapper = async (
|
||||||
};
|
};
|
||||||
const cmd = `npx --no-install graphile-migrate ${commands.join(" ")}`;
|
const cmd = `npx --no-install graphile-migrate ${commands.join(" ")}`;
|
||||||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||||
const dbDir = path.resolve(__dirname, '../../');
|
const dbDir = path.resolve(__dirname, "../../");
|
||||||
const gmrcPath = path.resolve(__dirname, '../../.gmrc');
|
const gmrcPath = path.resolve(__dirname, "../../.gmrc");
|
||||||
if (!existsSync(gmrcPath)) {
|
if (!existsSync(gmrcPath)) {
|
||||||
throw new Error(`graphile migrate config not found at ${gmrcPath}`);
|
throw new Error(`graphile migrate config not found at ${gmrcPath}`);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -81,7 +81,7 @@ export const SettingsService = (
|
||||||
return s.value;
|
return s.value;
|
||||||
},
|
},
|
||||||
|
|
||||||
async save<T>(settingInfo: SettingInfo<T>, value: T): Promise<T> {
|
async save<T>(settingInfo: SettingInfo<T>, value: T): Promise<T> {
|
||||||
const s = await repo.upsert(settingInfo.name, value);
|
const s = await repo.upsert(settingInfo.name, value);
|
||||||
return s.value;
|
return s.value;
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -50,5 +50,4 @@ export class WhatsappBotRecordRepository extends RepositoryBase(
|
||||||
[this.schemaTable, verified, bot.id]
|
[this.schemaTable, verified, bot.id]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue