Skip to content
Draft
7 changes: 7 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,12 @@ module.exports = {
"@typescript-eslint/no-var-requires": "off",
},
},
{
files: ["*.ts"],
excludedFiles: ["example/**/*.ts", "examples/**/*.ts", "**/*.test.ts"],
rules: {
"no-console": "error",
},
},
],
};
10 changes: 10 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
"typedoc-plugin-markdown": "^3.17.1",
"typedoc-plugin-no-inherit": "^1.4.0",
"typescript": "^5.3.3",
"vite-plugin-environment": "^1.1.3",
"vitest": "^1.3.1"
},
"dependencies": {
Expand Down
42 changes: 22 additions & 20 deletions src/client/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import {
DeleteModulesRequest,
PostWorkflowsRequest,
} from "clarifai-nodejs-grpc/proto/clarifai/api/service_pb";
import { UserError } from "../errors";
import { APIError, UserError } from "../errors";
import { ClarifaiAppUrl, ClarifaiUrlHelper } from "../urls/helper";
import { promisifyGrpcCall } from "../utils/misc";
import { AuthConfig, PaginationRequestParams } from "../utils/types";
Expand Down Expand Up @@ -49,6 +49,7 @@ import { v4 as uuid } from "uuid";
import { fromProtobufObject } from "from-protobuf-object";
import { fromPartialProtobufObject } from "../utils/fromPartialProtobufObject";
import { flatten } from "safe-flat";
import { logger } from "../utils/logging";

export type AuthAppConfig = Omit<AuthConfig, "appId" | "userId"> & {
appId?: undefined;
Expand Down Expand Up @@ -446,10 +447,10 @@ export class App extends Lister {
const responseObject = response.toObject();

if (responseObject.status?.code !== StatusCode.SUCCESS) {
throw new Error(responseObject.status?.description);
throw new APIError("Failed to create Dataset", responseObject);
}

console.info("\nDataset created\n%s", responseObject.status.description);
logger.info(`\nDataset created\n${responseObject.status.description}`);

return responseObject.datasetsList?.[0];
}
Expand Down Expand Up @@ -488,9 +489,9 @@ export class App extends Lister {
responseObject.status?.code !== StatusCode.SUCCESS ||
!responseObject.model
) {
throw new Error(responseObject.status?.description);
throw new APIError("Failed to create Model", responseObject);
}
console.info("\nModel created\n%s", responseObject.status.description);
logger.info(`\nModel created\n${responseObject.status.description}`);
return responseObject.model;
}

Expand Down Expand Up @@ -523,9 +524,9 @@ export class App extends Lister {
const response = await this.grpcRequest(postModules, request);
const responseObject = response.toObject();
if (responseObject.status?.code !== StatusCode.SUCCESS) {
throw new Error(responseObject.status?.description);
throw new APIError("Failed to create Module", responseObject);
}
console.info("\nModule created\n%s", responseObject.status.description);
logger.info(`\nModule created\n${responseObject.status.description}`);
return responseObject.modulesList?.[0];
}

Expand Down Expand Up @@ -657,12 +658,13 @@ export class App extends Lister {
const response = await this.grpcRequest(postWorkflows, request);
const responseObject = response.toObject();
if (responseObject.status?.code !== StatusCode.SUCCESS) {
throw new Error(responseObject.status?.description);
throw new APIError("Failed to create workflow", responseObject);
}
console.info("\nWorkflow created\n%s", responseObject.status?.description);
logger.info(`\nWorkflow created\n${responseObject.status?.description}`);

// Display the workflow nodes tree.
if (display) {
// eslint-disable-next-line no-console -- console.table is used for displaying the workflow info
console.table(flatten(responseObject.workflowsList?.[0]?.nodesList));
}
return responseObject.workflowsList?.[0];
Expand Down Expand Up @@ -711,7 +713,7 @@ export class App extends Lister {
const response = await this.grpcRequest(getModel, request);
const responseObject = response.toObject();
if (responseObject.status?.code !== StatusCode.SUCCESS) {
throw new Error(responseObject.status?.description);
throw new APIError("", responseObject);
}
return responseObject.model;
}
Expand Down Expand Up @@ -739,7 +741,7 @@ export class App extends Lister {
const response = await this.grpcRequest(getWorkflow, request);
const responseObject = response.toObject();
if (responseObject.status?.code !== StatusCode.SUCCESS) {
throw new Error(responseObject.status?.description);
throw new APIError("", responseObject);
}
return responseObject.workflow;
}
Expand Down Expand Up @@ -767,7 +769,7 @@ export class App extends Lister {
const response = await this.grpcRequest(getDataset, request);
const responseObject = response.toObject();
if (responseObject.status?.code !== StatusCode.SUCCESS) {
throw new Error(responseObject.status?.description);
throw new APIError("", responseObject);
}
return responseObject.dataset;
}
Expand All @@ -790,9 +792,9 @@ export class App extends Lister {
const response = await this.grpcRequest(deleteDatasets, request);
const responseObject = response.toObject();
if (responseObject.status?.code !== StatusCode.SUCCESS) {
throw new Error(responseObject.status?.description);
throw new APIError("Failed to delete dataset", responseObject);
}
console.info("\nDataset Deleted\n%s", responseObject.status?.description);
logger.info(`\nDataset Deleted\n${responseObject.status?.description}`);
}

/**
Expand All @@ -813,9 +815,9 @@ export class App extends Lister {
const response = await this.grpcRequest(deleteModels, request);
const responseObject = response.toObject();
if (responseObject.status?.code !== StatusCode.SUCCESS) {
throw new Error(responseObject.status?.description);
throw new APIError("Failed to delete model", responseObject);
}
console.info("\nModel Deleted\n%s", responseObject.status?.description);
logger.info(`\nModel Deleted\n${responseObject.status?.description}`);
}

/**
Expand All @@ -836,9 +838,9 @@ export class App extends Lister {
const response = await this.grpcRequest(deleteWorkflows, request);
const responseObject = response.toObject();
if (responseObject.status?.code !== StatusCode.SUCCESS) {
throw new Error(responseObject.status?.description);
throw new APIError("Failed to delete workflow", responseObject);
}
console.info("\nWorkflow Deleted\n%s", responseObject.status?.description);
logger.info(`\nWorkflow Deleted\n${responseObject.status?.description}`);
}

/**
Expand All @@ -859,8 +861,8 @@ export class App extends Lister {
const response = await this.grpcRequest(deleteModules, request);
const responseObject = response.toObject();
if (responseObject.status?.code !== StatusCode.SUCCESS) {
throw new Error(responseObject.status?.description);
throw new APIError("Failed to delete module", responseObject);
}
console.info("\nModule Deleted\n%s", responseObject.status?.description);
logger.info(`\nModule Deleted\n${responseObject.status?.description}`);
}
}
17 changes: 9 additions & 8 deletions src/client/auth/helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import resources_pb2 from "clarifai-nodejs-grpc/proto/clarifai/api/resources_pb"
import { grpc } from "clarifai-nodejs-grpc";
import { V2Client } from "clarifai-nodejs-grpc/proto/clarifai/api/service_grpc_pb";
import process from "process";
import { UserError } from "../../errors";

// TypeScript interface for the cache
export interface Cache {
Expand Down Expand Up @@ -60,7 +61,7 @@ export function httpsCache(cache: Cache, url: string): string {
cache[url] = HTTPS;
} else {
// For URLs without a scheme and not ending with .clarifai.com, prompt user to provide the scheme
throw new Error(
throw new UserError(
`Please provide a valid scheme for the ${url}, either use http:// or https://`,
);
}
Expand Down Expand Up @@ -125,21 +126,21 @@ export class ClarifaiAuthHelper {

private validate(): void {
if (this.userId === "") {
throw new Error(
throw new UserError(
"Need 'user_id' to not be empty in the query params or use CLARIFAI_USER_ID env var",
);
}
if (this.appId === "") {
throw new Error(
throw new UserError(
"Need 'app_id' to not be empty in the query params or use CLARIFAI_APP_ID env var",
);
}
if (this._pat !== "" && this.token !== "") {
throw new Error(
throw new UserError(
"A personal access token OR a session token need to be provided, but you cannot provide both.",
);
} else if (this._pat === "" && this.token === "") {
throw new Error(
throw new UserError(
"Need 'pat' or 'token' in the query params or use one of the CLARIFAI_PAT or CLARIFAI_SESSION_TOKEN env vars",
);
}
Expand Down Expand Up @@ -205,7 +206,7 @@ export class ClarifaiAuthHelper {
} else if (this.token !== "") {
return [["x-clarifai-session-token", this.token]];
} else {
throw new Error(
throw new UserError(
"'token' or 'pat' needed to be provided in the query params or env vars.",
);
}
Expand Down Expand Up @@ -333,7 +334,7 @@ export class ClarifaiAuthHelper {

for (const [key, value] of Object.entries(tomlDict)) {
if (authKeys.includes(key) && value === "") {
throw new Error(`'${key}' in secrets.toml cannot be empty`);
throw new UserError(`'${key}' in secrets.toml cannot be empty`);
}
}
// Assuming all non-present keys have non-empty values.
Expand All @@ -350,7 +351,7 @@ export class ClarifaiAuthHelper {
versionId?: string;
}): string {
if (!validResourceTypes.includes(resourceType)) {
throw new Error(
throw new UserError(
`resourceType must be one of ${validResourceTypes.join(", ")} but was ${resourceType}`,
);
}
Expand Down
8 changes: 5 additions & 3 deletions src/client/auth/stub.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { V2Stub } from "./register";
import { grpc } from "clarifai-nodejs-grpc";
import * as jspb from "google-protobuf";
import { Status } from "clarifai-nodejs-grpc/proto/clarifai/api/status/status_pb";
import { logger } from "../../utils/logging";

const throttleStatusCodes = new Set([
StatusCode.CONN_THROTTLED,
Expand Down Expand Up @@ -86,7 +87,8 @@ export class AuthorizedStub {
reject(err);
} else {
// TODO - Fix the type issue with the response
// @ts-expect-error - Response type is not fully inferred
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore - @ts-expect-error directive not working here
resolve(response);
}
});
Expand Down Expand Up @@ -148,7 +150,7 @@ export class RetryStub extends AuthorizedStub {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(err as any).status?.code in throttleStatusCodes
) {
console.log(`Attempt ${attempt} failed, retrying...`);
logger.warn(`Attempt ${attempt} failed, retrying...`);
if (attempt < this.maxAttempts) {
await new Promise((resolve) =>
setTimeout(resolve, this.backoffTime * 1000),
Expand Down Expand Up @@ -187,7 +189,7 @@ export class RetryStub extends AuthorizedStub {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(err as any).status?.code in throttleStatusCodes
) {
console.log(`Attempt ${attempt} failed, retrying...`);
logger.warn(`Attempt ${attempt} failed, retrying...`);
if (attempt < this.maxAttempts) {
await new Promise((resolve) =>
setTimeout(resolve, this.backoffTime * 1000),
Expand Down
3 changes: 2 additions & 1 deletion src/client/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { AuthConfig } from "../utils/types";
import * as jspb from "google-protobuf";
import { grpc } from "clarifai-nodejs-grpc";
import { Status } from "clarifai-nodejs-grpc/proto/clarifai/api/status/status_pb";
import { UserError } from "../errors";

/**
* BaseClient is the base class for all the classes interacting with Clarifai endpoints.
Expand Down Expand Up @@ -100,7 +101,7 @@ export class BaseClient {

// Check if the date is valid
if (isNaN(datetimeObj.getTime())) {
throw new Error("Invalid date string");
throw new UserError("Invalid date string");
}

// Convert the Date object to a Timestamp
Expand Down
15 changes: 10 additions & 5 deletions src/client/dataset.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {
Dataset as GrpcDataset,
Input as GrpcInput,
} from "clarifai-nodejs-grpc/proto/clarifai/api/resources_pb";
import { UserError } from "../errors";
import { APIError, UserError } from "../errors";
import { ClarifaiUrl, ClarifaiUrlHelper } from "../urls/helper";
import { AuthConfig } from "../utils/types";
import { Lister } from "./lister";
Expand All @@ -19,6 +19,7 @@ import {
} from "google-protobuf/google/protobuf/struct_pb";
import { promisifyGrpcCall } from "../utils/misc";
import { StatusCode } from "clarifai-nodejs-grpc/proto/clarifai/api/status/status_code_pb";
import { logger } from "../utils/logging";

type DatasetConfig =
| {
Expand Down Expand Up @@ -84,9 +85,11 @@ export class Dataset extends Lister {
const response = await this.grpcRequest(postDatasetVersions, request);
const responseObject = response.toObject();
if (responseObject.status?.code !== StatusCode.SUCCESS) {
throw new Error(responseObject.status?.description);
throw new APIError("Failed to create dataset version", responseObject);
}
console.info("\nDataset Version created\n%s", response.getStatus());
logger.info(
`\nDataset Version created\n${responseObject.status.description}`,
);

return responseObject.datasetVersionsList[0];
}
Expand All @@ -104,9 +107,11 @@ export class Dataset extends Lister {
const response = await this.grpcRequest(deleteDatasetVersions, request);
const responseObject = response.toObject();
if (responseObject.status?.code !== StatusCode.SUCCESS) {
throw new Error(responseObject.status?.description);
throw new APIError("Failed to delete dataset version", responseObject);
}
console.info("\nDataset Version Deleted\n%s", response.getStatus());
logger.info(
`\nDataset Version Deleted\n${responseObject.status.description}`,
);
}

async *listVersions(
Expand Down
Loading