@socialbaking/karma v1.0.0-beta.128
Karma - Node & JavaScript implementation
Support
Test Coverage
Client's TypeScript Interface
export interface ClientOptions {
partnerId?: string;
accessToken?: string;
version?: number;
prefix?: string;
url?: string | URL;
fetch?: typeof fetch
}
export interface Client {
addPartner(partner: PartnerData): Promise<Partner>;
addCategory(category: CategoryData): Promise<Category>;
addProduct(product: ProductData): Promise<Product>;
addReport(report: ReportData): Promise<Report>;
addReportMetrics(data: ReportMetricsData): Promise<ReportMetrics>;
getProduct(productId: string): Promise<Product | undefined>;
getReport(reportId: string): Promise<Report | undefined>;
listPartners(): Promise<Partner[]>;
listOrganisations(): Promise<Organisation[]>;
listSystemLogs(): Promise<SystemLog[]>;
listProducts(): Promise<Product[]>;
listReports(): Promise<Report[]>;
listCategories(): Promise<Category[]>;
listDailyMetrics(): Promise<CountryProductMetrics[]>;
listMonthlyMetrics(): Promise<CountryProductMetrics[]>;
listMetrics(): Promise<CountryProductMetrics[]>;
listReportMetrics(): Promise<ReportMetrics[]>;
listProductMetrics(productId: string): Promise<CountryProductMetrics[]>;
listCalculationKeys(): Promise<string[]>;
listCalculations(): Promise<CalculationSource[]>;
background(query: Record<string, string> | URLSearchParams): Promise<void>;
}
export type KarmaAuthenticationRole =
| "moderator"
| "admin"
| "owner"
| "patient"
| "industry"
| "member"
| "pharmacy"
| "clinic"
| "booster"
| "developer"
| "coordinator"
| "partner";
declare global {
interface AuthenticationRoles extends Record<KarmaAuthenticationRole, KarmaAuthenticationRole> {
}
}
// Used by client
type AuthenticationRole =
| KarmaAuthenticationRole
| keyof AuthenticationRoles;
export interface CalculationSource {
calculationKey: string;
title: string;
description: string;
anonymous: boolean;
}
export interface CategoryData extends Record<string, unknown> {
categoryName: string;
defaultUnit?: string;
defaultSizes?: ProductSizeData[];
countryCode?: string;
order?: number;
associatedTerms?: string[];
}
export interface Category extends CategoryData {
categoryId: string;
createdAt: string;
updatedAt: string;
}
export interface Expiring {
expiresAt?: string;
}
export type BaseFileStoreType = "product" | "inventory" | "productFile" | "inventoryFile"
export type BaseFileRemoteSourceName = "discord" | BaseFileStoreType;
export type RemoteFileSourceName = BaseFileRemoteSourceName | `${BaseFileRemoteSourceName}_${number}`;
export type FileUploadedSynced = "r2" | "disk";
export type FileType = BaseFileStoreType | `${RemoteFileSourceName}_import`;
export interface ResolvedFilePart extends Record<string, unknown> {
}
export interface FileImageSize extends Expiring {
width: number;
height: number;
signed?: boolean;
fileName?: string;
checksum?: Record<string, string>
}
export interface FileSize extends FileImageSize {
url: string;
synced: FileUploadedSynced;
syncedAt: string;
version: number;
watermark?: boolean;
copyright?: string;
license?: string;
fileName?: string;
signed?: boolean;
}
export interface FileErrorDescription {
stack?: string;
message: string;
createdAt: string;
repeated?: number;
}
export interface FileData extends Record<string, unknown>, Partial<FileImageSize> {
fileName: string;
contentType: string;
size?: number;
path?: string;
url?: string;
pinned?: boolean;
uploadedAt?: string;
uploadedByUsername?: string;
source?: RemoteFileSourceName;
sourceId?: string;
synced?: FileUploadedSynced;
syncedAt?: string;
version?: number;
type?: FileType | string;
sizes?: FileSize[];
/** @deprecated use remoteUrl */
externalUrl?: string;
remoteUrl?: string;
reactionCounts?: Record<string, number>;
reactionCountsUpdatedAt?: string;
resolved?: ResolvedFilePart[];
resolvedAt?: string;
errors?: FileErrorDescription[];
}
export interface File extends FileData {
fileId: string;
createdAt: string;
updatedAt: string;
uploadedAt: string;
}
export interface ResolvedFile extends File {
url: string;
synced: FileUploadedSynced;
}
import {
CalculationConsent,
CalculationConsentItem,
ReportDateData,
ReportRoleData,
} from "../report";
export interface ActiveIngredientMetrics extends Record<string, unknown> {
type: string;
unit: string;
value: string;
// If the calculation of cost takes into account the
// proportion of this vs total active ingredients
proportional?: boolean;
mean?: boolean;
size?: ProductSizeData;
prefix?: string;
calculation?: "minimum" | "maximum" | "mean" | string;
}
export interface ProductMetricData extends Record<string, unknown> {
productId: string;
activeIngredients: ActiveIngredientMetrics[];
}
export interface MetricsData
extends ReportDateData,
Expiring,
CalculationConsent {
products: ProductMetricData[];
countryCode: string;
currencySymbol?: string; // "$"
timezone?: string; // Pacific/Auckland
anonymous?: boolean;
}
export interface ReportMetricsData extends MetricsData {
parentReportId?: string;
type?: string;
}
export interface ReportMetrics
extends ReportMetricsData,
ReportRoleData,
Record<string, unknown> {
type?: string;
metricsId: string;
reportId: string;
reportedAt: string;
createdAt: string;
updatedAt: string;
// consent required to be stored
calculationConsent: CalculationConsentItem[];
}
export type CountryProductMetricDuration = "day" | "month";
export interface CountryProductMetrics extends MetricsData {
metricsId: string;
createdAt: string;
updatedAt: string;
currencySymbol: string; // "$"
timezone: string;
duration: CountryProductMetricDuration;
reportingDateKey: keyof ReportDateData;
}
export {
Offer,
OfferData,
OfferItem,
OfferItemType,
OfferPrice,
OfferStatus,
InventoryOffer,
OrderOfferItem,
ProductOfferItem,
} from "@opennetwork/logistics";
export interface OrganisationBaseData extends Record<string, unknown> {
countryCode?: string; // "NZ"
location?: string;
remote?: boolean;
onsite?: boolean;
pharmacy?: boolean;
delivery?: boolean;
clinic?: boolean;
website?: string;
associatedBrandingTerms?: string[]; // Eg common names used to refer to the organisation by way of brand
}
export interface OrganisationData extends OrganisationBaseData {
organisationName: string;
partnerId?: string;
approved?: boolean;
approvedAt?: string;
}
export interface Organisation extends OrganisationData {
organisationId: string;
createdAt: string;
updatedAt: string;
approvedByUserId?: string;
}
export interface PartnerData extends Record<string, unknown> {
partnerName: string;
countryCode?: string;
}
export interface AddPartnerData extends PartnerData, OrganisationBaseData {}
export interface Partner extends PartnerData {
partnerId: string;
organisationId: string;
accessToken?: string;
createdAt: string;
updatedAt: string;
approved?: boolean;
approvedAt?: string;
approvedByUserId?: string;
}
export interface ProductTemperature {
value: string;
unit?: string;
}
export interface ProductIngredient {
name: string;
active?: boolean;
boil?: ProductTemperature;
}
export interface ProductSizeData extends Record<string, unknown> {
value: string;
unit: string;
}
export interface ProductInfo {
title?: string;
text: string;
url?: string;
description?: string;
}
export interface ProductFile extends Partial<FileData> {
fileId: string;
}
export interface ProductData extends Record<string, unknown> {
productName: string;
order?: number;
countryCode?: string;
organisationId?: string;
licencedOrganisationId?: string;
// Flag for products we don't have the exact licence date for
licenceApprovedBeforeGivenDate?: boolean;
licenceApprovedAt?: string;
licenceExpiredAt?: string;
licenceApprovalWebsite?: string;
// ISO 3166-1 alpha-3 country code
licenceCountryCode?: string;
// Flag for products we don't have the exact availability date for
availableBeforeGivenDate?: boolean;
availableAt?: string;
// For products that we will no longer have available
availableUntil?: string;
sizes?: ProductSizeData[];
// Direct text about the active ingredients, not specific values
activeIngredientDescriptions?: string[];
categoryId?: string;
generic?: boolean;
public?: boolean;
branded?: boolean;
genericSearchTerm?: string;
genericCategoryNames?: string[];
genericAcronym?: string;
info?: ProductInfo[];
files?: ProductFile[];
obsoleteAt?: string;
ingredients?: ProductIngredient[];
}
export interface ProductActiveIngredient {
type: string;
unit: string;
value: string;
prefix?: string;
calculated?: boolean;
calculatedUnit?: string;
size?: ProductSizeData;
proportional?: boolean;
}
export interface Product extends ProductData {
productId: string;
createdAt: string;
updatedAt: string;
activeIngredients?: ProductActiveIngredient[];
}
export interface ReportDateData {
orderedAt?: string;
shippedAt?: string;
receivedAt?: string;
updatedAt?: string;
createdAt?: string;
reportedAt?: string;
}
export interface CalculationConsentItem extends Record<string, unknown> {
calculationKey: string;
consented?: boolean;
consentedAt?: string;
}
export interface CalculationConsent {
calculationConsent?: CalculationConsentItem[];
}
export interface ReportRoleData {
roles: AuthenticationRole[];
}
export type ReportType = "purchase" | "product" | "poll";
export interface DeprecatedReportData {
// TODO No longer used fields, but keeping around until v1.0.0
productPurchase?: boolean;
productPurchaseTotalCost?: string | number; // "908.50", capture the user input raw
productPurchaseItems?: string | number; // "2", capture the user input raw
productPurchaseItemCost?: string | number; // "450", capture the user input raw
productPurchaseDeliveryCost?: string | number; // "8.50", capture the user input raw
productPurchaseFeeCost?: string | number; // "3.50", capture the user input raw
productPurchaseOrganisationId?: string;
productPurchaseOrganisationName?: string; // Actual organisationName, not free text
productPurchaseOrganisationText?: string; // User free text of the organisationName
}
type StringNumber = `${number}` | number | string;
export interface ProductReviewReportData {
comment?: string;
rating?: string | `${number}` | number;
vibes?: string;
}
export interface ProductReportData extends DeprecatedReportData, ProductReviewReportData {
productId?: string;
productName?: string; // Actual productName, not free text
productText?: string; // User free text of the product
productSize?: ProductSizeData;
productTotalCost: StringNumber; // "908.50", capture the user input raw
productItems: StringNumber; // "2", capture the user input raw
productItemCost: StringNumber; // "450", capture the user input raw
productDeliveryCost?: StringNumber; // "8.50", capture the user input raw
productFeeCost?: StringNumber; // "3.50", capture the user input raw
productOrganisationId?: string;
productOrganisationName?: string; // Actual organisationName, not free text
productOrganisationText?: string; // User free text of the organisationName
}
export interface PollReportOptionData extends Partial<ActiveIngredientMetrics> {
title: string;
votes: `${number}` | string;
}
export interface PollReportData {
title: string;
url?: string;
options: PollReportOptionData[];
}
export type PartialReportData = Partial<PollReportData> & Partial<ProductReportData>
export interface ReportData
extends ReportDateData,
Expiring,
CalculationConsent,
PartialReportData,
Record<string, unknown> {
type: ReportType | string;
countryCode: string; // "NZ"
currencySymbol?: string; // "$"
timezone?: string; // Pacific/Auckland
note?: string;
parentReportId?: string;
createdByUserId?: string;
createdByPartnerId?: string;
anonymous?: boolean;
}
export interface Report extends ReportData, ReportRoleData {
reportId: string;
createdAt: string;
updatedAt: string;
reportedAt: string;
reports?: Report[];
}
export interface SystemLogData extends Record<string, unknown> {
uniqueCode?: string;
value?: number;
partnerId: string;
message: string;
timestamp?: string;
action?: string;
}
export interface SystemLog extends SystemLogData {
systemLogId: string;
timestamp: string;
}
Local Development
Dependencies
You will need to install the dependencies with yarn
Once you have yarn installed, use the command:
yarn
.env
First you will need to set up a .env
file in the same directory as this README.md file
Copy the .env.example
to make your .env
file
To setup reddit authentication, you will need to either be provided a client ID if you're working with the socialbaking team, or you will need to create a new application at the bottom of this screen
The local redirect url is http://localhost:3000/api/authentication/reddit/callback
Once created, copy the value under "web app" and set that as your REDDIT_CLIENT_ID
Copy the "secret" and set that as REDDIT_CLIENT_SECRET
Set the reddit community name, and associated flair, as you see fit:
REDDIT_NAME=MedicalCannabisNZ
REDDIT_FLAIR="Medical Patient"
4 months ago
4 months ago
4 months ago
5 months ago
5 months ago
7 months ago
7 months ago
7 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago