Skip to content

Commit

Permalink
Merge branch 'main' into shorthand-columns
Browse files Browse the repository at this point in the history
  • Loading branch information
jacobmischka committed Jun 29, 2022
2 parents 680f185 + 8b7ca80 commit 95c8393
Show file tree
Hide file tree
Showing 9 changed files with 112 additions and 55 deletions.
72 changes: 56 additions & 16 deletions src/classes/IOClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import { IOPromise, ExclusiveIOPromise } from './IOPromise'
import IOError from './IOError'
import spreadsheet from '../components/spreadsheet'
import { selectTable, displayTable } from '../components/table'
import findAndSelectUser from '../components/selectUser'
import selectSingle from '../components/selectSingle'
import search from '../components/search'
import selectMultiple from '../components/selectMultiple'
Expand All @@ -30,7 +29,10 @@ import {
ExclusiveIOComponentFunction,
ComponentRenderer,
IOComponentDefinition,
RequiredPropsIOComponentFunction,
RequiredPropsExclusiveIOComponentFunction,
} from '../types'
import { stripUndefined } from '../utils/deserialize'

interface ClientConfig {
logger: Logger
Expand Down Expand Up @@ -90,7 +92,7 @@ export class IOClient {
toRender: components
.map(c => c.getRenderInfo())
.map(({ props, ...renderInfo }) => {
const { json, meta } = superjson.serialize(props)
const { json, meta } = superjson.serialize(stripUndefined(props))
return {
...renderInfo,
props: json,
Expand Down Expand Up @@ -237,8 +239,29 @@ export class IOClient {
Output = T_IO_RETURNS<MethodName>
>(
methodName: MethodName,
propsRequired?: false,
componentDef?: IOComponentDefinition<MethodName, Props, Output>
): IOComponentFunction<MethodName, Props, Output> {
): IOComponentFunction<MethodName, Props, Output>
createIOMethod<
MethodName extends T_IO_METHOD_NAMES,
Props extends object = T_IO_PROPS<MethodName>,
Output = T_IO_RETURNS<MethodName>
>(
methodName: MethodName,
propsRequired?: true,
componentDef?: IOComponentDefinition<MethodName, Props, Output>
): RequiredPropsIOComponentFunction<MethodName, Props, Output>
createIOMethod<
MethodName extends T_IO_METHOD_NAMES,
Props extends object = T_IO_PROPS<MethodName>,
Output = T_IO_RETURNS<MethodName>
>(
methodName: MethodName,
_propsRequired = false,
componentDef?: IOComponentDefinition<MethodName, Props, Output>
):
| IOComponentFunction<MethodName, Props, Output>
| RequiredPropsIOComponentFunction<MethodName, Props, Output> {
return (label: string, props?: Props) => {
let internalProps = props ? (props as T_IO_PROPS<MethodName>) : {}
let getValue = (r: T_IO_RETURNS<MethodName>) => r as unknown as Output
Expand Down Expand Up @@ -280,7 +303,16 @@ export class IOClient {
* ExclusiveIOPromise, which cannot be rendered in a group.
*/
makeExclusive<MethodName extends T_IO_METHOD_NAMES, Props, Output>(
inner: IOComponentFunction<MethodName, Props, Output>
inner: IOComponentFunction<MethodName, Props, Output>,
propsRequired: false
): ExclusiveIOComponentFunction<MethodName, Props, Output>
makeExclusive<MethodName extends T_IO_METHOD_NAMES, Props, Output>(
inner: IOComponentFunction<MethodName, Props, Output>,
propsRequired?: true
): RequiredPropsExclusiveIOComponentFunction<MethodName, Props, Output>
makeExclusive<MethodName extends T_IO_METHOD_NAMES, Props, Output>(
inner: IOComponentFunction<MethodName, Props, Output>,
_propsRequired = false
): ExclusiveIOComponentFunction<MethodName, Props, Output> {
return (label: string, props?: Props) => {
return new ExclusiveIOPromise(inner(label, props))
Expand All @@ -296,7 +328,7 @@ export class IOClient {

confirm: this.makeExclusive(this.createIOMethod('CONFIRM')),

search: this.createIOMethod('SEARCH', search),
search: this.createIOMethod('SEARCH', true, search),

input: {
text: this.createIOMethod('INPUT_TEXT'),
Expand All @@ -306,28 +338,36 @@ export class IOClient {
richText: this.createIOMethod('INPUT_RICH_TEXT'),
},
select: {
single: this.createIOMethod('SELECT_SINGLE', selectSingle),
multiple: this.createIOMethod('SELECT_MULTIPLE', selectMultiple),
table: this.createIOMethod('SELECT_TABLE', selectTable(this.logger)),
single: this.createIOMethod('SELECT_SINGLE', true, selectSingle),
multiple: this.createIOMethod('SELECT_MULTIPLE', true, selectMultiple),
table: this.createIOMethod(
'SELECT_TABLE',
true,
selectTable(this.logger)
),
},
display: {
heading: this.createIOMethod('DISPLAY_HEADING'),
markdown: this.createIOMethod('DISPLAY_MARKDOWN'),
link: this.createIOMethod('DISPLAY_LINK'),
object: this.createIOMethod('DISPLAY_OBJECT'),
table: this.createIOMethod('DISPLAY_TABLE', displayTable(this.logger)),
table: this.createIOMethod(
'DISPLAY_TABLE',
true,
displayTable(this.logger)
),
},
experimental: {
spreadsheet: this.createIOMethod('INPUT_SPREADSHEET', spreadsheet),
findAndSelectUser: this.createIOMethod(
'SELECT_USER',
findAndSelectUser
spreadsheet: this.createIOMethod(
'INPUT_SPREADSHEET',
true,
spreadsheet
),
date: this.createIOMethod('INPUT_DATE', date),
date: this.createIOMethod('INPUT_DATE', false, date),
time: this.createIOMethod('INPUT_TIME'),
datetime: this.createIOMethod('INPUT_DATETIME', datetime),
datetime: this.createIOMethod('INPUT_DATETIME', false, datetime),
input: {
file: this.createIOMethod('UPLOAD_FILE', file),
file: this.createIOMethod('UPLOAD_FILE', false, file),
},
},
}
Expand Down
15 changes: 13 additions & 2 deletions src/classes/IOPromise.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,19 @@ export class IOPromise<
)
}

optional(): OptionalIOPromise<MethodName, Props, Output> {
return new OptionalIOPromise(this)
optional(isOptional?: true): OptionalIOPromise<MethodName, Props, Output>
optional(isOptional?: false): IOPromise<MethodName, Props, Output>
optional(
isOptional?: boolean
):
| OptionalIOPromise<MethodName, Props, Output>
| IOPromise<MethodName, Props, Output>
optional(
isOptional = true
):
| OptionalIOPromise<MethodName, Props, Output>
| IOPromise<MethodName, Props, Output> {
return isOptional ? new OptionalIOPromise(this) : this
}
}

Expand Down
6 changes: 2 additions & 4 deletions src/components/search.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,8 @@ type InternalResults = T_IO_PROPS<'SEARCH'>['results']
export default function search<Result = any>({
onSearch,
initialResults = [],
placeholder,
renderResult,
helpText,
...rest
}: {
placeholder?: string
helpText?: string
Expand Down Expand Up @@ -54,8 +53,7 @@ export default function search<Result = any>({
}

const props: T_IO_PROPS<'SEARCH'> = {
placeholder,
helpText,
...rest,
results: renderResults(initialResults),
}

Expand Down
14 changes: 0 additions & 14 deletions src/components/selectUser.ts

This file was deleted.

2 changes: 2 additions & 0 deletions src/examples/basic/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ const prod = new Interval({
actions: {
ImportUsers: {
backgroundable: true,
name: 'Import users',
description: "Doesn't actually import users",
handler: async io => {
console.log("I'm a live mode action")
const name = await io.input.text('Enter the name for a user')
Expand Down
2 changes: 2 additions & 0 deletions src/internalRpcSchema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ export type LoadingState = z.input<typeof LOADING_STATE>

export const ACTION_DEFINITION = z.object({
slug: z.string(),
name: z.string().optional(),
description: z.string().optional(),
backgroundable: z.boolean().optional(),
})

Expand Down
19 changes: 0 additions & 19 deletions src/ioSchema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -388,25 +388,6 @@ export const ioSchema = {
state: z.null(),
returns: z.array(labelValue),
},
SELECT_USER: {
props: z.object({
userList: z.array(
z.object({
id: z.union([z.string(), z.number()]),
name: z.string(),
email: z.string().optional(),
imageUrl: z.string().optional(),
})
),
}),
state: z.object({ queryTerm: z.string() }),
returns: z.object({
id: z.union([z.string(), z.number()]),
name: z.string(),
email: z.string().optional(),
imageUrl: z.string().optional(),
}),
},
DISPLAY_HEADING: {
props: z.object({}),
state: z.null(),
Expand Down
20 changes: 20 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,12 +54,32 @@ export interface IntervalActionStore {
export interface ExplicitIntervalActionDefinition {
handler: IntervalActionHandler
backgroundable?: boolean
name?: string
description?: string
}

export type IntervalActionDefinition =
| IntervalActionHandler
| ExplicitIntervalActionDefinition

export type RequiredPropsIOComponentFunction<
MethodName extends T_IO_METHOD_NAMES,
Props,
Output = ComponentReturnValue<MethodName>
> = (
label: string,
props: Props
) => IOPromise<MethodName, T_IO_PROPS<MethodName>, Output>

export type RequiredPropsExclusiveIOComponentFunction<
MethodName extends T_IO_METHOD_NAMES,
Props,
Output = ComponentReturnValue<MethodName>
> = (
label: string,
props: Props
) => ExclusiveIOPromise<MethodName, T_IO_PROPS<MethodName>, Output>

export type IOComponentFunction<
MethodName extends T_IO_METHOD_NAMES,
Props,
Expand Down
17 changes: 17 additions & 0 deletions src/utils/deserialize.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,3 +55,20 @@ export function deserializeDates<V extends any>(

return ret
}

export function stripUndefined<
K extends string | number | symbol,
V,
T extends Record<K, V> | undefined
>(obj: T): T {
if (!obj) return obj

const newObj = { ...obj } as Exclude<typeof obj, undefined>
for (const [key, val] of Object.entries(newObj)) {
if (val === undefined) {
delete newObj[key as K]
}
}

return newObj
}

0 comments on commit 95c8393

Please sign in to comment.