Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions packages/cli/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,23 @@
# @openfn/cli

## 1.35.0

### Minor Changes

- collections: add support for --project-id

### Patch Changes

- Updated dependencies
- @openfn/lexicon@1.5.0

## 1.34.2

### Patch Changes

- 3918358: Override config.endpoint with one from openfn.yaml


## 1.34.1

### Patch Changes
Expand Down
6 changes: 3 additions & 3 deletions packages/cli/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@openfn/cli",
"version": "1.34.2",
"version": "1.35.0",
"description": "CLI devtools for the OpenFn toolchain",
"engines": {
"node": ">=18",
Expand Down Expand Up @@ -33,10 +33,10 @@
"author": "Open Function Group <admin@openfn.org>",
"license": "ISC",
"devDependencies": {
"@openfn/language-collections": "^0.8.3",
"@openfn/language-collections": "^0.9.0",
"@openfn/language-common": "3.2.3",
"@types/lodash-es": "~4.17.12",
"@types/json-diff": "^1.0.3",
"@types/lodash-es": "~4.17.12",
"@types/mock-fs": "^4.13.4",
"@types/node": "^18.19.130",
"@types/rimraf": "^3.0.2",
Expand Down
22 changes: 22 additions & 0 deletions packages/cli/src/collections/command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export type CollectionsOptions = Pick<Opts, 'log' | 'logJson'> & {
token?: string;
key: string;
collectionName: string;
projectId?: string;
};

export type GetOptions = CollectionsOptions &
Expand Down Expand Up @@ -89,6 +90,7 @@ const key = {
};

const endpoint = {
// TODO in docs, prefer endpoint to lightning
name: 'endpoint',
yargs: {
alias: ['e', 'lightning'],
Expand All @@ -105,6 +107,23 @@ const pageSize = {
},
};

const projectId = {
name: 'project-id',
yargs: {
alias: ['p'],
// TODO maybe CLI should be smart and support a local alias here
// Or if inside a workspace, use that
description:
'The UUID of the project which owns this collection. Set via env var OPENFN_PROJECT_ID',
type: 'string',
},
ensure: (opts: any) => {
if (!opts.projectId) {
opts.projectId = process.env.OPENFN_PROJECT_ID;
}
},
};

// TODO not working yet
const limit = {
name: 'limit',
Expand Down Expand Up @@ -151,6 +170,7 @@ const updatedAfter = {

const getOptions = [
collectionName,
projectId,
key,
o.apiKey,
endpoint,
Expand Down Expand Up @@ -192,6 +212,7 @@ const dryRun = {

const removeOptions = [
collectionName,
projectId,
key,
o.apiKey,
endpoint,
Expand Down Expand Up @@ -232,6 +253,7 @@ const items = {

const setOptions = [
collectionName,
projectId,
override(key as any, {
demand: false,
}),
Expand Down
11 changes: 7 additions & 4 deletions packages/cli/src/collections/handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,18 @@ import { QueryOptions } from '@openfn/language-collections/types/collections';

const ensureToken = (opts: CollectionsOptions, logger: Logger) => {
if (!('token' in opts)) {
if (process.env.OPENFN_PAT) {
const token = process.env.OPENFN_PAT;
const token = process.env.OPENFN_API_KEY ?? process.env.OPENFN_PAT;
if (token) {
logger.info(
`Using access token ending in ${token?.substring(
token.length - 10
)} from env (OPENFN_PAT)`
)} from env`
);
opts.token = token;
} else {
logger.error('No access token detected!');
logger.error(
'Ensure you pass a Personal Access Token (PAT) with --token $MY_TOKEN or set the OPENFN_PAT env var'
'Ensure you pass a Personal Access Token (PAT) with --token $MY_TOKEN or set the OPENFN_API_KEY env var'
);
logger.error(
'You can get a PAT from OpenFn, see https://docs.openfn.org/documentation/api-tokens'
Expand Down Expand Up @@ -76,6 +76,7 @@ export const get = async (options: GetOptions, logger: Logger) => {
key: options.key,
collectionName: options.collectionName,
query: buildQuery(options),
projectId: options.projectId,
},
logger
);
Expand Down Expand Up @@ -152,6 +153,7 @@ export const set = async (options: SetOptions, logger: Logger) => {
key: options.key,
collectionName: options.collectionName,
data: { items },
projectId: options.projectId,
},
logger
);
Expand Down Expand Up @@ -179,6 +181,7 @@ export const remove = async (options: RemoveOptions, logger: Logger) => {
token: options.token!,
key: options.key,
collectionName: options.collectionName,
projectId: options.projectId,
},
logger
);
Expand Down
33 changes: 23 additions & 10 deletions packages/cli/src/collections/request.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ type Options = {
collectionName: string;
token: string;
lightning?: string;
projectId?: string;

includeMeta?: boolean; // TODO ignored right now
pageSize?: number;
Expand Down Expand Up @@ -48,6 +49,9 @@ export default async (
},
options.query
);
if (options.projectId) {
query.project_id = options.projectId;
}

const args: Partial<Dispatcher.RequestOptions> = {
headers,
Expand Down Expand Up @@ -128,28 +132,37 @@ async function handleError(logger: Logger, response: Dispatcher.ResponseData) {
logger.error('Error from server', response.statusCode);
let message;
let fix;
let logBody = true;

switch (response.statusCode) {
case 409:
message = `409: multiple collection names matched`;
fix = `Pass --project-id or set OPENFN_PROJECT_ID to disambiguate the request`;
logBody = false;
break;
case 404:
message = `404: collection not found`;
fix = `Ensure the Collection has been created on the admin page`;
logBody = false;
break;
default:
message = `Error from server: ${response.statusCode}`;
}

let contentType = (response.headers?.['content-type'] as string) ?? '';

if (contentType.startsWith('application/json')) {
try {
const body = await response.body.json();
logger.error(body);
} catch (e) {}
} else {
try {
const text = await response.body.text();
logger.error(text);
} catch (e) {}
if (logBody) {
if (contentType.startsWith('application/json')) {
try {
const body = await response.body.json();
logger.error(body);
} catch (e) {}
} else {
try {
const text = await response.body.text();
logger.error(text);
} catch (e) {}
}
}

throwAbortableError(message, fix);
Expand Down
Loading