@@ -39,7 +39,21 @@ interface NonprofitsPublicResponse {
3939 } ;
4040}
4141
42- const QueryNonprofitsPublic : TypedDocumentNode < { perPage : number , filter : { ein : { in : string [ ] } , } } > = gql `
42+ interface NonprofitsPublicVariables {
43+ perPage ?: number ;
44+ page ?: number ;
45+ resultSize ?: number ;
46+ filter : {
47+ ein : {
48+ in : string [ ] ;
49+ } ;
50+ } ;
51+ }
52+
53+ const QueryNonprofitsPublic : TypedDocumentNode <
54+ NonprofitsPublicResponse ,
55+ NonprofitsPublicVariables
56+ > = gql `
4357 query NonprofitsPublic(
4458 $perPage: Int!
4559 $filter: NonprofitFilters
@@ -69,14 +83,11 @@ const QueryNonprofitsPublic: TypedDocumentNode<{ perPage: number, filter: { ein:
6983` ;
7084
7185const isNonprofitPublic = ( edge : object ) : edge is NonprofitPublic => {
72- if ( typeof edge !== 'object' || edge === null ) {
73- return false ;
74- }
7586 const obj = edge as Record < string , unknown > ;
7687 return (
7788 typeof obj . ein === 'string'
7889 && typeof obj . name === 'string'
79- && typeof obj . updated === 'string'
90+ && typeof obj . updatedAt === 'string'
8091 ) ;
8192} ;
8293
@@ -108,7 +119,7 @@ const API_URL = 'https://api.charitynavigator.org/graphql';
108119const getCharityNavigatorProfiles = async (
109120 apiKey : string ,
110121 eins : string [ ] ,
111- ) : Promise < ApolloClient . QueryResult > => {
122+ ) : Promise < ApolloClient . QueryResult < NonprofitsPublicResponse > > => {
112123 logger . info ( `Looking up EINs ${ JSON . stringify ( eins ) } in Charity Navigator GraphQL API` ) ;
113124 const apollo = apolloInit ( API_URL , apiKey ) ;
114125 const variables = {
@@ -129,13 +140,13 @@ const getCharityNavigatorProfiles = async (
129140} ;
130141
131142interface LookupCommandArgs {
132- 'charity-navigator-api-key' : string ;
143+ 'charity-navigator-api-key' ? : string ;
133144 eins : string [ ] ;
134145 outputFile ?: string ;
135146}
136147
137148interface UpdateAllCommandArgs {
138- 'charity-navigator-api-key' : string ;
149+ 'charity-navigator-api-key' ? : string ;
139150 'oidc-base-url' : string ,
140151 'oidc-client-id' : string ,
141152 'oidc-client-secret' : string ,
@@ -147,10 +158,16 @@ const lookupCommand: CommandModule<unknown, LookupCommandArgs> = {
147158 describe : 'Fetch and display information about organizations by EIN' ,
148159 builder : ( y ) => ( y
149160 . option ( 'charity-navigator-api-key' , {
150- describe : 'CharityNavigator API key; get from account management at https://developer.charitynavigator.org/' ,
151- demandOption : true ,
161+ describe : 'CharityNavigator API key; get from account management at https://developer.charitynavigator.org/ (can also be set via DS_CHARITY_NAVIGATOR_API_KEY env var) ' ,
162+ demandOption : false ,
152163 type : 'string' ,
153164 } )
165+ . check ( ( argv ) => {
166+ if ( ! argv . charityNavigatorApiKey ) {
167+ throw new Error ( 'Missing required argument: charity-navigator-api-key (set via CLI or DS_CHARITY_NAVIGATOR_API_KEY env var)' ) ;
168+ }
169+ return true ;
170+ } )
154171 . option ( 'output-file' , {
155172 alias : 'write' ,
156173 describe : 'Write organization information to the specified JSON file' ,
@@ -166,7 +183,11 @@ const lookupCommand: CommandModule<unknown, LookupCommandArgs> = {
166183 . check ( ( { eins } ) => ! ( new Set ( eins . map ( isValidEin ) ) . has ( false ) ) )
167184 ) ,
168185 handler : async ( args ) => {
169- const result = await getCharityNavigatorProfiles ( args . charityNavigatorApiKey , args . eins )
186+ const { charityNavigatorApiKey : apiKey } = args ;
187+ if ( ! apiKey ) {
188+ throw new Error ( 'Missing required argument: charity-navigator-api-key' ) ;
189+ }
190+ const result = await getCharityNavigatorProfiles ( apiKey , args . eins )
170191 . catch ( ( err ) => {
171192 logger . error ( err , 'error calling primary graphql api' ) ;
172193 throw err ;
@@ -206,8 +227,8 @@ const updateAllCommand: CommandModule<unknown, UpdateAllCommandArgs> = {
206227 builder : {
207228 ...oidcOptions ,
208229 'charity-navigator-api-key' : {
209- describe : 'CharityNavigator API key; get from account management at https://developer.charitynavigator.org/' ,
210- demandOption : true ,
230+ describe : 'CharityNavigator API key; get from account management at https://developer.charitynavigator.org/ (can also be set via DS_CHARITY_NAVIGATOR_API_KEY env var) ' ,
231+ demandOption : false ,
211232 type : 'string' ,
212233 } ,
213234 'pdc-api-base-url' : {
@@ -217,6 +238,10 @@ const updateAllCommand: CommandModule<unknown, UpdateAllCommandArgs> = {
217238 } ,
218239 } ,
219240 handler : async ( args ) => {
241+ const apiKey = args . charityNavigatorApiKey ;
242+ if ( ! apiKey ) {
243+ throw new Error ( 'Missing required argument: charity-navigator-api-key (set via CLI or DS_CHARITY_NAVIGATOR_API_KEY env var)' ) ;
244+ }
220245 const changemakers = await getChangemakers ( args . pdcApiBaseUrl ) ;
221246 const eins = changemakers . entries . flatMap ( ( c ) => c . taxId ) ;
222247 // Charity Navigator expects no hyphens, strip them from EINs after validation.
@@ -227,7 +252,7 @@ const updateAllCommand: CommandModule<unknown, UpdateAllCommandArgs> = {
227252 }
228253 logger . info ( validEins , 'Found these valid EINs which will be requested from Charity Navigator' ) ;
229254 const charityNavResponse = await getCharityNavigatorProfiles (
230- args . charityNavigatorApiKey ,
255+ apiKey ,
231256 validEins ,
232257 ) ;
233258 logger . info ( { charityNavResponse } , 'CharityNavigator result' ) ;
@@ -240,29 +265,10 @@ const updateAllCommand: CommandModule<unknown, UpdateAllCommandArgs> = {
240265 // First, find the existing source. As of this writing, it cannot be created by non-admins.
241266 const source = await getOrCreateSource ( args . pdcApiBaseUrl , token ) ;
242267 logger . info ( source , 'The PDC Source for Charity Navigator was found' ) ;
243- // Second, post the fields to PDC, except we need to type-safe this thing
244- // See the difficulty shown at
245- // https://www.apollographql.com/docs/react/data/typescript#type-narrowing-data-with-datastate
246- // const fieldValues = charityNavResponse.data.nonprofitsPublic.edges.flatMap();
247-
248- if ( charityNavResponse . dataState !== undefined
249- && charityNavResponse . dataState !== null
250- && charityNavResponse . dataState === 'complete'
251- && charityNavResponse . data !== undefined
252- && charityNavResponse . data !== null
253- && typeof charityNavResponse . data === 'object'
254- && charityNavResponse . data . nonprofitsPublic !== undefined
255- && charityNavResponse . data . nonprofitsPublic !== null
256- && typeof charityNavResponse . data . nonprofitsPublic === 'object'
257- && charityNavResponse . data . nonprofitsPublic . edges !== undefined
258- && charityNavResponse . data . nonprofitsPublic . edges !== null
259- && Array . isArray ( charityNavResponse . data . nonprofitsPublic . edges )
260- ) {
261- const nonprofits : NonprofitPublic [ ] = charityNavResponse . data . nonprofitsPublic . edges . flatMap ( ( e ) => {
262- if ( isNonprofitPublic ( e ) ) {
263- return e ;
264- }
265- } ) ;
268+ // Second, post the fields to PDC
269+ if ( charityNavResponse . data ) {
270+ const { edges } = charityNavResponse . data . nonprofitsPublic ;
271+ const nonprofits = edges . filter ( ( e ) : e is NonprofitPublic => isNonprofitPublic ( e ) ) ;
266272 logger . info ( nonprofits , 'Found these nonprofits' ) ;
267273 }
268274 } ,
0 commit comments