@nyc-transit-kit/cli 0.1.3 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,209 +1,66 @@
1
- import type { Soda3ExportFormat } from "@nyc-transit-kit/contracts/soda3"
2
- import { exportNycDotDataset, queryNycDotDataset } from "@nyc-transit-kit/nyc-dot/client"
3
1
  import {
2
+ exportNycDotDataset,
4
3
  findNycDotDataset,
5
4
  nycDotDatasets,
6
- nycDotOpenDataDomain
5
+ nycDotOpenDataDomain,
6
+ queryNycDotDataset
7
7
  } from "@nyc-transit-kit/nyc-dot/datasets"
8
- import * as Effect from "effect/Effect"
9
8
  import * as Command from "effect/unstable/cli/Command"
10
- import * as Flag from "effect/unstable/cli/Flag"
11
- import { failCommand, runEffect, soqlFromSelect, writeSuccess } from "./shared"
12
- import { writeResponseToFile, writeSoda3ExportDryRun, writeSoda3QueryDryRun } from "./soda3-shared"
13
- import { CliCommandContext } from "./types"
14
-
15
- export const nycDotCommandPaths: ReadonlyArray<ReadonlyArray<string>> = [
16
- ["nyc-dot", "dataset", "list"],
17
- ["nyc-dot", "dataset", "info"],
18
- ["nyc-dot", "dataset", "query"],
19
- ["nyc-dot", "dataset", "export"]
20
- ]
21
-
22
- export const handleNycDotList = () =>
23
- Effect.gen(function* () {
24
- const context = yield* CliCommandContext
25
- return yield* writeSuccess(context, "nyc-dot", {
26
- datasets: nycDotDatasets
27
- })
28
- })
29
-
30
- export const handleNycDotInfo = (config: { readonly name: string }) =>
31
- Effect.gen(function* () {
32
- const context = yield* CliCommandContext
33
- const descriptor = findNycDotDataset(config.name)
34
-
35
- if (descriptor === undefined) {
36
- return yield* failCommand(
37
- context,
38
- "nyc-dot",
39
- "unsupported-dataset",
40
- `Unsupported NYC DOT dataset: ${config.name}`,
41
- ["nyc-dot", "dataset", "info"]
42
- )
43
- }
44
-
45
- return yield* writeSuccess(context, "nyc-dot", descriptor)
46
- })
47
-
48
- export const handleNycDotQuery = (config: {
49
- readonly name: string
50
- readonly select: string
51
- readonly dryRun: boolean
52
- }) =>
53
- Effect.gen(function* () {
54
- const context = yield* CliCommandContext
55
- const tokens = ["nyc-dot", "dataset", "query"]
56
- const descriptor = findNycDotDataset(config.name)
57
-
58
- if (descriptor === undefined) {
59
- return yield* failCommand(
60
- context,
61
- "nyc-dot",
62
- "unsupported-dataset",
63
- `Unsupported NYC DOT dataset: ${config.name}`,
64
- tokens
65
- )
66
- }
67
-
68
- const request = {
69
- name: config.name,
70
- query: soqlFromSelect(config.select)
71
- }
72
-
73
- if (config.dryRun) {
74
- return yield* writeSoda3QueryDryRun({
75
- context,
76
- apiFamily: "nyc-dot",
77
- tokens,
78
- domain: nycDotOpenDataDomain,
79
- datasetId: String(descriptor.id),
80
- query: request.query,
81
- extra: {
82
- dataset: descriptor
9
+ import { makeDatasetCommands } from "./shared"
10
+
11
+ const unsupportedDataset = (name: string) => ({
12
+ code: "unsupported-dataset",
13
+ message: `Unsupported NYC DOT dataset: ${name}`
14
+ })
15
+
16
+ const resolveNycDotDataset = (name: string) => {
17
+ const descriptor = findNycDotDataset(name)
18
+ return descriptor === undefined
19
+ ? { failure: unsupportedDataset(name) }
20
+ : {
21
+ payload: {
22
+ datasetId: String(descriptor.id),
23
+ extra: {
24
+ dataset: descriptor
25
+ }
83
26
  }
84
- })
85
- }
86
-
87
- return yield* runEffect(
88
- context,
89
- "nyc-dot",
90
- tokens,
91
- queryNycDotDataset(request).pipe(Effect.provide(context.runtime.soda3Layer))
92
- )
93
- })
94
-
95
- export const handleNycDotExport = (config: {
96
- readonly name: string
97
- readonly format: Soda3ExportFormat
98
- readonly output: string
99
- readonly dryRun: boolean
100
- }) =>
101
- Effect.gen(function* () {
102
- const context = yield* CliCommandContext
103
- const tokens = ["nyc-dot", "dataset", "export"]
104
- const descriptor = findNycDotDataset(config.name)
105
-
106
- if (descriptor === undefined) {
107
- return yield* failCommand(
108
- context,
109
- "nyc-dot",
110
- "unsupported-dataset",
111
- `Unsupported NYC DOT dataset: ${config.name}`,
112
- tokens
113
- )
114
- }
115
-
116
- const request = {
117
- name: config.name,
118
- format: config.format
119
- }
120
-
121
- if (config.dryRun) {
122
- return yield* writeSoda3ExportDryRun({
123
- context,
124
- apiFamily: "nyc-dot",
125
- tokens,
126
- domain: nycDotOpenDataDomain,
127
- datasetId: String(descriptor.id),
128
- format: request.format,
129
- output: config.output,
130
- extra: {
131
- dataset: descriptor
132
- }
133
- })
134
- }
135
-
136
- return yield* runEffect(
137
- context,
138
- "nyc-dot",
139
- tokens,
140
- Effect.gen(function* () {
141
- const response = yield* exportNycDotDataset(request).pipe(
142
- Effect.provide(context.runtime.soda3Layer)
143
- )
144
- return yield* writeResponseToFile(config.output, response)
145
- })
146
- )
147
- })
148
-
149
- const nycDotDatasetListCommand = Command.make("list", {}, handleNycDotList).pipe(
150
- Command.withShortDescription("List curated NYC DOT dataset descriptors.")
151
- )
152
-
153
- const nycDotDatasetInfoCommand = Command.make(
154
- "info",
155
- {
156
- name: Flag.string("name").pipe(
157
- Flag.withDescription("Known NYC DOT dataset name, such as traffic-speeds.")
158
- )
159
- },
160
- handleNycDotInfo
161
- ).pipe(Command.withShortDescription("Show NYC DOT dataset metadata."))
162
-
163
- const nycDotDatasetQueryCommand = Command.make(
164
- "query",
165
- {
166
- name: Flag.string("name").pipe(
167
- Flag.withDescription("Known NYC DOT dataset name, such as traffic-speeds.")
168
- ),
169
- select: Flag.string("select").pipe(
170
- Flag.withDescription("SoQL select expression or full SELECT query.")
171
- ),
172
- dryRun: Flag.boolean("dry-run").pipe(
173
- Flag.withDescription("Print the planned request without contacting the provider.")
174
- )
27
+ }
28
+ }
29
+
30
+ const nycDotDatasetCommands = makeDatasetCommands({
31
+ family: "nyc-dot",
32
+ tokens: ["nyc-dot", "dataset"],
33
+ idConfigKey: "name",
34
+ idFlagName: "name",
35
+ idFlagDescription: "Known NYC DOT dataset name, such as traffic-speeds.",
36
+ domain: nycDotOpenDataDomain,
37
+ listShortDescription: "List curated NYC DOT dataset descriptors.",
38
+ infoShortDescription: "Show NYC DOT dataset metadata.",
39
+ queryShortDescription: "Run a NYC DOT SODA3 query.",
40
+ exportShortDescription: "Export a NYC DOT dataset.",
41
+ listPayload: () => ({ datasets: nycDotDatasets }),
42
+ infoPayload: (name) => {
43
+ const descriptor = findNycDotDataset(name)
44
+ return descriptor === undefined
45
+ ? { failure: unsupportedDataset(name) }
46
+ : { payload: descriptor }
175
47
  },
176
- handleNycDotQuery
177
- ).pipe(Command.withShortDescription("Run a NYC DOT SODA3 query."))
178
-
179
- const nycDotDatasetExportCommand = Command.make(
180
- "export",
181
- {
182
- name: Flag.string("name").pipe(
183
- Flag.withDescription("Known NYC DOT dataset name, such as traffic-speeds.")
184
- ),
185
- format: Flag.choice("format", ["csv", "json", "geojson"]).pipe(
186
- Flag.withDefault("csv"),
187
- Flag.withDescription("Export format. Defaults to csv.")
188
- ),
189
- output: Flag.string("output").pipe(
190
- Flag.withDescription("Destination file path for the downloaded response body.")
191
- ),
192
- dryRun: Flag.boolean("dry-run").pipe(
193
- Flag.withDescription("Print the planned request without contacting the provider.")
194
- )
195
- },
196
- handleNycDotExport
197
- ).pipe(Command.withShortDescription("Export a NYC DOT dataset."))
48
+ resolveDataset: resolveNycDotDataset,
49
+ query: ({ id, query }) =>
50
+ queryNycDotDataset({
51
+ name: id,
52
+ query
53
+ }),
54
+ exportResponse: ({ id, format }) =>
55
+ exportNycDotDataset({
56
+ name: id,
57
+ format
58
+ })
59
+ })
198
60
 
199
61
  const nycDotDatasetCommand = Command.make("dataset").pipe(
200
62
  Command.withShortDescription("NYC DOT dataset commands."),
201
- Command.withSubcommands([
202
- nycDotDatasetListCommand,
203
- nycDotDatasetInfoCommand,
204
- nycDotDatasetQueryCommand,
205
- nycDotDatasetExportCommand
206
- ])
63
+ Command.withSubcommands(nycDotDatasetCommands)
207
64
  )
208
65
 
209
66
  export const nycDotCommand = Command.make("nyc-dot").pipe(
@@ -1,29 +1,20 @@
1
- import type { Soda3ExportFormat } from "@nyc-transit-kit/contracts/soda3"
2
- import { searchNycOpenDataCatalog } from "@nyc-transit-kit/nyc-open-data/catalog"
3
- import { exportNycOpenDataDataset } from "@nyc-transit-kit/nyc-open-data/client"
1
+ import {
2
+ exportNycOpenDataDataset,
3
+ queryNycOpenDataDataset,
4
+ searchNycOpenDataCatalog
5
+ } from "@nyc-transit-kit/nyc-open-data/client"
4
6
  import {
5
7
  defaultDomain,
6
8
  findNycOpenDataDataset,
7
9
  knownNycOpenDataDatasets
8
10
  } from "@nyc-transit-kit/nyc-open-data/descriptors"
9
- import { queryNycOpenDataDataset } from "@nyc-transit-kit/nyc-open-data/query"
10
11
  import { buildCatalogSearchUrl } from "@nyc-transit-kit/soda3/endpoints"
11
12
  import * as Effect from "effect/Effect"
12
13
  import * as Command from "effect/unstable/cli/Command"
13
14
  import * as Flag from "effect/unstable/cli/Flag"
14
- import { runEffect, soqlFromSelect, writeSuccess } from "./shared"
15
- import { writeResponseToFile, writeSoda3ExportDryRun, writeSoda3QueryDryRun } from "./soda3-shared"
16
- import { CliCommandContext } from "./types"
17
-
18
- export const nycOpenDataCommandPaths: ReadonlyArray<ReadonlyArray<string>> = [
19
- ["nyc-open-data", "catalog", "search"],
20
- ["nyc-open-data", "dataset", "list"],
21
- ["nyc-open-data", "dataset", "info"],
22
- ["nyc-open-data", "dataset", "query"],
23
- ["nyc-open-data", "dataset", "export"]
24
- ]
15
+ import { CliCommandContext, dryRunFlag, makeDatasetCommands, runEffect } from "./shared"
25
16
 
26
- export const handleNycOpenDataCatalogSearch = (config: {
17
+ const handleNycOpenDataCatalogSearch = (config: {
27
18
  readonly query: string
28
19
  readonly limit: number
29
20
  readonly dryRun: boolean
@@ -62,100 +53,50 @@ export const handleNycOpenDataCatalogSearch = (config: {
62
53
  )
63
54
  })
64
55
 
65
- export const handleNycOpenDataList = () =>
66
- Effect.gen(function* () {
67
- const context = yield* CliCommandContext
68
- return yield* writeSuccess(context, "nyc-open-data", {
69
- datasets: knownNycOpenDataDatasets
70
- })
71
- })
72
-
73
- export const handleNycOpenDataInfo = (config: { readonly datasetId: string }) =>
74
- Effect.gen(function* () {
75
- const context = yield* CliCommandContext
76
- const descriptor = findNycOpenDataDataset(config.datasetId)
77
-
78
- return yield* writeSuccess(context, "nyc-open-data", {
79
- known: descriptor !== undefined,
80
- descriptor:
81
- descriptor === undefined
82
- ? {
83
- id: config.datasetId,
84
- domain: defaultDomain,
85
- backing: "socrata"
86
- }
87
- : descriptor
88
- })
89
- })
90
-
91
- export const handleNycOpenDataQuery = (config: {
92
- readonly datasetId: string
93
- readonly select: string
94
- readonly dryRun: boolean
95
- }) =>
96
- Effect.gen(function* () {
97
- const context = yield* CliCommandContext
98
- const tokens = ["nyc-open-data", "dataset", "query"]
99
- const request = {
100
- datasetId: config.datasetId,
101
- query: soqlFromSelect(config.select)
102
- }
103
-
104
- if (config.dryRun) {
105
- return yield* writeSoda3QueryDryRun({
106
- context,
107
- apiFamily: "nyc-open-data",
108
- tokens,
109
- domain: defaultDomain,
110
- ...request
111
- })
56
+ const nycOpenDataDatasetCommands = makeDatasetCommands({
57
+ family: "nyc-open-data",
58
+ tokens: ["nyc-open-data", "dataset"],
59
+ idConfigKey: "datasetId",
60
+ idFlagName: "dataset",
61
+ idFlagDescription: "NYC Open Data Socrata dataset id.",
62
+ domain: defaultDomain,
63
+ listShortDescription: "List curated NYC Open Data descriptors.",
64
+ infoShortDescription: "Show NYC Open Data dataset metadata.",
65
+ queryShortDescription: "Run a NYC Open Data SODA3 query.",
66
+ exportShortDescription: "Export a NYC Open Data dataset.",
67
+ listPayload: () => ({ datasets: knownNycOpenDataDatasets }),
68
+ infoPayload: (datasetId) => {
69
+ const descriptor = findNycOpenDataDataset(datasetId)
70
+ return {
71
+ payload: {
72
+ known: descriptor !== undefined,
73
+ descriptor:
74
+ descriptor === undefined
75
+ ? {
76
+ id: datasetId,
77
+ domain: defaultDomain,
78
+ backing: "socrata"
79
+ }
80
+ : descriptor
81
+ }
112
82
  }
113
-
114
- return yield* runEffect(
115
- context,
116
- "nyc-open-data",
117
- tokens,
118
- queryNycOpenDataDataset(request).pipe(Effect.provide(context.runtime.soda3Layer))
119
- )
120
- })
121
-
122
- export const handleNycOpenDataExport = (config: {
123
- readonly datasetId: string
124
- readonly format: Soda3ExportFormat
125
- readonly output: string
126
- readonly dryRun: boolean
127
- }) =>
128
- Effect.gen(function* () {
129
- const context = yield* CliCommandContext
130
- const tokens = ["nyc-open-data", "dataset", "export"]
131
- const request = {
132
- datasetId: config.datasetId,
133
- format: config.format
134
- }
135
-
136
- if (config.dryRun) {
137
- return yield* writeSoda3ExportDryRun({
138
- context,
139
- apiFamily: "nyc-open-data",
140
- tokens,
141
- domain: defaultDomain,
142
- output: config.output,
143
- ...request
144
- })
83
+ },
84
+ resolveDataset: (datasetId) => ({
85
+ payload: {
86
+ datasetId
145
87
  }
146
-
147
- return yield* runEffect(
148
- context,
149
- "nyc-open-data",
150
- tokens,
151
- Effect.gen(function* () {
152
- const response = yield* exportNycOpenDataDataset(request).pipe(
153
- Effect.provide(context.runtime.soda3Layer)
154
- )
155
- return yield* writeResponseToFile(config.output, response)
156
- })
157
- )
158
- })
88
+ }),
89
+ query: ({ id, query }) =>
90
+ queryNycOpenDataDataset({
91
+ datasetId: id,
92
+ query
93
+ }),
94
+ exportResponse: ({ id, format }) =>
95
+ exportNycOpenDataDataset({
96
+ datasetId: id,
97
+ format
98
+ })
99
+ })
159
100
 
160
101
  const nycOpenDataCatalogSearchCommand = Command.make(
161
102
  "search",
@@ -165,9 +106,7 @@ const nycOpenDataCatalogSearchCommand = Command.make(
165
106
  Flag.withDefault(10),
166
107
  Flag.withDescription("Maximum catalog results to request. Defaults to 10.")
167
108
  ),
168
- dryRun: Flag.boolean("dry-run").pipe(
169
- Flag.withDescription("Print the planned request without contacting the provider.")
170
- )
109
+ dryRun: dryRunFlag
171
110
  },
172
111
  handleNycOpenDataCatalogSearch
173
112
  ).pipe(Command.withShortDescription("Search the NYC Open Data catalog."))
@@ -177,64 +116,9 @@ const nycOpenDataCatalogCommand = Command.make("catalog").pipe(
177
116
  Command.withSubcommands([nycOpenDataCatalogSearchCommand])
178
117
  )
179
118
 
180
- const nycOpenDataDatasetListCommand = Command.make("list", {}, handleNycOpenDataList).pipe(
181
- Command.withShortDescription("List curated NYC Open Data descriptors.")
182
- )
183
-
184
- const nycOpenDataDatasetInfoCommand = Command.make(
185
- "info",
186
- {
187
- datasetId: Flag.string("dataset").pipe(
188
- Flag.withDescription("NYC Open Data Socrata dataset id.")
189
- )
190
- },
191
- handleNycOpenDataInfo
192
- ).pipe(Command.withShortDescription("Show NYC Open Data dataset metadata."))
193
-
194
- const nycOpenDataDatasetQueryCommand = Command.make(
195
- "query",
196
- {
197
- datasetId: Flag.string("dataset").pipe(
198
- Flag.withDescription("NYC Open Data Socrata dataset id.")
199
- ),
200
- select: Flag.string("select").pipe(
201
- Flag.withDescription("SoQL select expression or full SELECT query.")
202
- ),
203
- dryRun: Flag.boolean("dry-run").pipe(
204
- Flag.withDescription("Print the planned request without contacting the provider.")
205
- )
206
- },
207
- handleNycOpenDataQuery
208
- ).pipe(Command.withShortDescription("Run a NYC Open Data SODA3 query."))
209
-
210
- const nycOpenDataDatasetExportCommand = Command.make(
211
- "export",
212
- {
213
- datasetId: Flag.string("dataset").pipe(
214
- Flag.withDescription("NYC Open Data Socrata dataset id.")
215
- ),
216
- format: Flag.choice("format", ["csv", "json", "geojson"]).pipe(
217
- Flag.withDefault("csv"),
218
- Flag.withDescription("Export format. Defaults to csv.")
219
- ),
220
- output: Flag.string("output").pipe(
221
- Flag.withDescription("Destination file path for the downloaded response body.")
222
- ),
223
- dryRun: Flag.boolean("dry-run").pipe(
224
- Flag.withDescription("Print the planned request without contacting the provider.")
225
- )
226
- },
227
- handleNycOpenDataExport
228
- ).pipe(Command.withShortDescription("Export a NYC Open Data dataset."))
229
-
230
119
  const nycOpenDataDatasetCommand = Command.make("dataset").pipe(
231
120
  Command.withShortDescription("NYC Open Data dataset commands."),
232
- Command.withSubcommands([
233
- nycOpenDataDatasetListCommand,
234
- nycOpenDataDatasetInfoCommand,
235
- nycOpenDataDatasetQueryCommand,
236
- nycOpenDataDatasetExportCommand
237
- ])
121
+ Command.withSubcommands(nycOpenDataDatasetCommands)
238
122
  )
239
123
 
240
124
  export const nycOpenDataCommand = Command.make("nyc-open-data").pipe(
@@ -2,13 +2,11 @@ import * as Effect from "effect/Effect"
2
2
  import * as Command from "effect/unstable/cli/Command"
3
3
  import * as Flag from "effect/unstable/cli/Flag"
4
4
  import { localBinaryName } from "../index"
5
- import { catalogCommand } from "./catalog"
6
5
  import { mtaCommand } from "./mta"
7
6
  import { nycDotCommand } from "./nyc-dot"
8
7
  import { nycOpenDataCommand } from "./nyc-open-data"
9
- import { failCommand } from "./shared"
10
- import { socrataCommand } from "./socrata"
11
- import { CliCommandContext } from "./types"
8
+ import { CliCommandContext, failCommand } from "./shared"
9
+ import { catalogCommand, socrataCommand } from "./socrata"
12
10
 
13
11
  const handleMissingCommand = () =>
14
12
  Effect.gen(function* () {