Skip to content

Commit

Permalink
Merge pull request #260 from litencatt/support-db-query-more-params-f…
Browse files Browse the repository at this point in the history
…or-non-interactive-mode

Support db query more params for non-interactive mode
  • Loading branch information
litencatt committed Jan 3, 2024
2 parents 0d3b0ac + 347fd53 commit 94cb5e7
Show file tree
Hide file tree
Showing 4 changed files with 202 additions and 95 deletions.
56 changes: 39 additions & 17 deletions docs/db.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,22 +66,28 @@ Query a database

```
USAGE
$ notion-cli db query [DATABASE_ID] [-a <value>] [-f <value>] [-r] [--columns <value> | -x] [--sort <value>]
[--filter <value>] [--output csv|json|yaml | | [--csv | --no-truncate]] [--no-header | ]
$ notion-cli db query [DATABASE_ID] [-a <value>] [-f <value>] [-p <value>] [-A] [-s <value>] [-d asc|desc]
[-r] [--columns <value> | -x] [--sort <value>] [--filter <value>] [--output csv|json|yaml | | [--csv |
--no-truncate]] [--no-header | ]
FLAGS
-a, --rawFilter=<value> JSON stringified filter string
-f, --fileFilter=<value> JSON filter file path
-r, --raw output raw json
-x, --extended show extra columns
--columns=<value> only show provided columns (comma-separated)
--csv output is csv format [alias: --output=csv]
--filter=<value> filter property by partial string matching, ex: name=foo
--no-header hide table header from output
--no-truncate do not truncate output to fit screen
--output=<option> output in a more machine friendly format
<options: csv|json|yaml>
--sort=<value> property to sort by (prepend '-' for descending)
-A, --pageAll get all pages
-a, --rawFilter=<value> JSON stringified filter string
-d, --sortDirection=<option> [default: asc] The direction to sort results
<options: asc|desc>
-f, --fileFilter=<value> JSON filter file path
-p, --pageSize=<value> [default: 10] The number of results to return(1-100).
-r, --raw output raw json
-s, --sortProperty=<value> The property to sort results by
-x, --extended show extra columns
--columns=<value> only show provided columns (comma-separated)
--csv output is csv format [alias: --output=csv]
--filter=<value> filter property by partial string matching, ex: name=foo
--no-header hide table header from output
--no-truncate do not truncate output to fit screen
--output=<option> output in a more machine friendly format
<options: csv|json|yaml>
--sort=<value> property to sort by (prepend '-' for descending)
DESCRIPTION
Query a database
Expand All @@ -94,21 +100,37 @@ EXAMPLES
$ notion-cli db query
Query a db via interactive mode with a specific database_id
Query a db with a specific database_id
$ notion-cli db query DATABASE_ID
Query a db with a specific database_id and raw filter string
$ notion-cli db query -a='{"and": ...}' DATABASE_ID
$ notion-cli db query -a '{"and": ...}' DATABASE_ID
Query a db with a specific database_id and filter file
$ notion-cli db query -f ./path/to/filter.json DATABASE_ID
Query a db with a specific database_id and output format
Query a db with a specific database_id and output CSV
$ notion-cli db query --csv DATABASE_ID
Query a db with a specific database_id and output raw json
$ notion-cli db query --raw DATABASE_ID
Query a db with a specific database_id and page size
$ notion-cli db query -s 10 DATABASE_ID
Query a db with a specific database_id and get all pages
$ notion-cli db query -A DATABASE_ID
Query a db with a specific database_id and sort property and sort direction
$ notion-cli db query -s Name -d desc DATABASE_ID
```


Expand Down
237 changes: 161 additions & 76 deletions src/commands/db/query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import * as notion from '../../notion'
import {
PageObjectResponse,
DatabaseObjectResponse,
QueryDatabaseResponse,
QueryDatabaseParameters,
} from '@notionhq/client/build/src/api-endpoints'
import * as fs from 'fs'
import * as path from 'path'
Expand All @@ -18,6 +20,7 @@ import {
getDbTitle,
getPageTitle,
} from '../../helper'
import { client } from '../../notion'

const prompts = require('prompts')

Expand All @@ -32,25 +35,43 @@ export default class DbQuery extends Command {
command: `$ notion-cli db query`,
},
{
description: 'Query a db via interactive mode with a specific database_id',
description: 'Query a db with a specific database_id',
command: `$ notion-cli db query DATABASE_ID`,
},
{
description: 'Query a db with a specific database_id and raw filter string',
command: `$ notion-cli db query -a='{"and": ...}' DATABASE_ID`,
command: `$ notion-cli db query -a '{"and": ...}' DATABASE_ID`,
},
{
description: 'Query a db with a specific database_id and filter file',
command: `$ notion-cli db query -f ./path/to/filter.json DATABASE_ID`,
},
{
description: 'Query a db with a specific database_id and output format',
description: 'Query a db with a specific database_id and output CSV',
command: `$ notion-cli db query --csv DATABASE_ID`,
},
{
description: 'Query a db with a specific database_id and output raw json',
command: `$ notion-cli db query --raw DATABASE_ID`,
},
{
description: 'Query a db with a specific database_id and page size',
command: `$ notion-cli db query -s 10 DATABASE_ID`,
},
{
description: 'Query a db with a specific database_id and get all pages',
command: `$ notion-cli db query -A DATABASE_ID`,
},
{
description: 'Query a db with a specific database_id and sort property and sort direction',
command: `$ notion-cli db query -s Name -d desc DATABASE_ID`,
},
]

static args = {
database_id: Args.string(),
database_id: Args.string({
required: false,
}),
}

static flags = {
Expand All @@ -62,9 +83,32 @@ export default class DbQuery extends Command {
char: 'f',
description: 'JSON filter file path',
}),
pageSize: Flags.integer({
char: 'p',
description: 'The number of results to return(1-100). ',
min: 1,
max: 100,
default: 10,
}),
pageAll: Flags.boolean({
char: 'A',
description: 'get all pages',
default: false,
}),
sortProperty: Flags.string({
char: 's',
description: 'The property to sort results by',
}),
sortDirection: Flags.string({
char: 'd',
options: ['asc', 'desc'],
description: 'The direction to sort results',
default: 'asc',
}),
raw: Flags.boolean({
char: 'r',
description: 'output raw json',
default: false,
}),
...ux.table.flags(),
}
Expand All @@ -73,37 +117,64 @@ export default class DbQuery extends Command {
const { flags, args } = await this.parse(DbQuery)

let databaseId = args.database_id
if (databaseId == undefined) {
const dbChoices = await getDbChoices()
const promptSelectedDbResult = await prompts(
[
{
message: 'Select a database to query',
type: 'autocomplete',
name: 'database_id',
choices: dbChoices,
},
],
{ onCancel }
)
if (process.env.DEBUG) {
this.log(promptSelectedDbResult)
}
databaseId = promptSelectedDbResult.database_id
}

let filter: object | undefined
let queryParams: QueryDatabaseParameters
try {
// If args is set, run as non-interactive mode.
// If args(database_id) is set, run as non-interactive mode.
if (Object.keys(args).length !== 0) {
if (flags.rawFilter != undefined) {
filter = JSON.parse(flags.rawFilter)
const filter = JSON.parse(flags.rawFilter)
queryParams = {
database_id: databaseId,
filter: filter as QueryDatabaseParameters['filter'],
page_size: flags.pageSize,
}
} else if (flags.fileFilter != undefined) {
const fp = path.join('./', flags.fileFilter)
const fj = fs.readFileSync(fp, { encoding: 'utf-8' })
filter = JSON.parse(fj)
const filter = JSON.parse(fj)
queryParams = {
database_id: databaseId,
filter: filter as QueryDatabaseParameters['filter'],
page_size: flags.pageSize,
}
} else {
let sorts: QueryDatabaseParameters['sorts'] = []
const direction = flags.sortDirection == 'desc' ? 'descending' : 'ascending'
if (flags.sortProperty != undefined) {
sorts.push({
property: flags.sortProperty,
direction: direction,
})
}
queryParams = {
database_id: databaseId,
sorts: sorts,
page_size: flags.pageSize,
}
}
} else {
// interactive mode start
let filter: object | undefined

// select a database
const dbChoices = await getDbChoices()
const promptSelectedDbResult = await prompts(
[
{
message: 'Select a database to query',
type: 'autocomplete',
name: 'database_id',
choices: dbChoices,
},
],
{ onCancel }
)
if (process.env.DEBUG) {
this.log(promptSelectedDbResult)
}
databaseId = promptSelectedDbResult.database_id

// select a filter
let CombineOperator = undefined
const promptAddFilterResult = await prompts(
[
Expand Down Expand Up @@ -238,65 +309,79 @@ export default class DbQuery extends Command {
break
}
}

queryParams = {
database_id: databaseId,
filter: filter as QueryDatabaseParameters['filter'],
page_size: flags.pageSize,
}

// save filter to file
if (filter != undefined) {
console.log('')
console.log('Filter:')
console.dir(filter, { depth: null })
console.log('')

const promptConfirmSaveFilterResult = await prompts(
[
{
message: 'Save this filter to a file?',
type: 'confirm',
name: 'value',
initial: false,
},
],
{ onCancel }
)
if (promptConfirmSaveFilterResult.value) {
const promptFileNameResult = await prompts({
message: 'Filename',
type: 'text',
name: 'filename',
initial: dayjs().format('YYYYMMDD_HHmmss'),
})
const fileName = `${promptFileNameResult.filename}.json`
fs.writeFileSync(fileName, JSON.stringify(filter, null, 2))
this.logToStderr(`Saved to ${fileName}\n`)
}
}
}
} catch (e) {
this.error(e, { exit: 1 })
}

if (filter != undefined && flags.rawFilter == undefined && flags.fileFilter == undefined) {
console.log('')
console.log('Filter:')
console.dir(filter, { depth: null })
console.log('')

const promptConfirmSaveFilterResult = await prompts(
[
{
message: 'Save this filter to a file?',
type: 'confirm',
name: 'value',
initial: false,
},
],
{ onCancel }
)
if (promptConfirmSaveFilterResult.value) {
const promptFileNameResult = await prompts({
message: 'Filename',
type: 'text',
name: 'filename',
initial: dayjs().format('YYYYMMDD_HHmmss'),
})
const fileName = `${promptFileNameResult.filename}.json`
fs.writeFileSync(fileName, JSON.stringify(filter, null, 2))
this.logToStderr(`Saved to ${fileName}\n`)
}
let pages = []
if (flags.pageAll) {
pages = await notion.fetchAllPagesInDB(databaseId, queryParams.filter)
} else {
const res = await client.databases.query(queryParams)
pages.push(...res.results)
}

const res = await notion.queryDb(databaseId, filter)

// output
if (flags.raw) {
outputRawJson(res)
outputRawJson(pages)
this.exit(0)
}

const columns = {
title: {
get: (row: DatabaseObjectResponse | PageObjectResponse) => {
if (row.object == 'database') {
return getDbTitle(row)
}
return getPageTitle(row)
} else {
const columns = {
title: {
get: (row: DatabaseObjectResponse | PageObjectResponse) => {
if (row.object == 'database') {
return getDbTitle(row)
}
return getPageTitle(row)
},
},
},
object: {},
id: {},
url: {},
}
const options = {
printLine: this.log.bind(this),
...flags,
object: {},
id: {},
url: {},
}
const options = {
printLine: this.log.bind(this),
...flags,
}
ux.table(pages, columns, options)
}
ux.table(res, columns, options)
}
}

0 comments on commit 94cb5e7

Please sign in to comment.