@@ -9,14 +9,14 @@ import type { SnippetShellUserConfig, MongoshBus } from '@mongosh/types';
99import escapeRegexp from 'escape-string-regexp' ;
1010import path from 'path' ;
1111import { promisify , isDeepStrictEqual } from 'util' ;
12- import { Console } from 'console' ;
12+ import { Console , error } from 'console' ;
1313import { promises as fs } from 'fs' ;
1414import stream , { PassThrough } from 'stream' ;
1515import { once } from 'events' ;
1616import tar from 'tar' ;
1717import zlib from 'zlib' ;
1818import bson from 'bson' ;
19- import joi from 'joi ' ;
19+ import { z } from 'zod ' ;
2020import type {
2121 AgentWithInitialize ,
2222 DevtoolsProxyOptions ,
@@ -34,64 +34,45 @@ export interface SnippetOptions {
3434 proxyOptions ?: DevtoolsProxyOptions | AgentWithInitialize ;
3535}
3636
37- export interface ErrorMatcher {
38- matches : RegExp [ ] ;
39- message : string ;
40- }
41-
42- export interface SnippetDescription {
43- name : string ;
44- snippetName : string ;
45- installSpec ?: string ;
46- version : string ;
47- description : string ;
48- license : string ;
49- readme : string ;
50- errorMatchers ?: ErrorMatcher [ ] ;
51- }
52-
53- export interface SnippetIndexFile {
54- indexFileVersion : 1 ;
55- index : SnippetDescription [ ] ;
56- metadata : { homepage : string } ;
57- sourceURL : string ;
58- }
59-
6037interface NpmMetaDataResponse {
6138 dist ?: {
6239 tarball ?: string ;
6340 } ;
6441}
6542
66- const indexFileSchema = joi . object ( {
67- indexFileVersion : joi . number ( ) . integer ( ) . max ( 1 ) . required ( ) ,
43+ const regExpTag = Object . prototype . toString . call ( / f o o / ) ;
44+ const errorMatcherSchema = z . object ( {
45+ message : z . string ( ) ,
46+ matches : z . array (
47+ z . custom < RegExp > ( ( val ) => Object . prototype . toString . call ( val ) === regExpTag )
48+ ) ,
49+ } ) ;
50+ const indexDescriptionSchema = z . object ( {
51+ name : z . string ( ) ,
52+ snippetName : z . string ( ) ,
53+ installSpec : z . string ( ) . optional ( ) ,
54+ version : z . string ( ) ,
55+ description : z . string ( ) ,
56+ license : z . string ( ) ,
57+ readme : z . string ( ) ,
58+ errorMatchers : z . array ( errorMatcherSchema ) ,
59+ } ) ;
60+ const indexFileSchema = z . object ( {
61+ indexFileVersion : z . number ( ) . int ( ) . max ( 1 ) ,
6862
69- metadata : joi . object ( {
70- homepage : joi . string ( ) ,
63+ metadata : z . object ( {
64+ homepage : z . string ( ) ,
7165 } ) ,
7266
73- index : joi
74- . array ( )
75- . required ( )
76- . items (
77- joi . object ( {
78- name : joi . string ( ) . required ( ) ,
79- snippetName : joi . string ( ) . required ( ) ,
80- installSpec : joi . string ( ) ,
81- version : joi . string ( ) . required ( ) ,
82- description : joi . string ( ) . required ( ) . allow ( '' ) ,
83- license : joi . string ( ) . required ( ) ,
84- readme : joi . string ( ) . required ( ) . allow ( '' ) ,
85- errorMatchers : joi . array ( ) . items (
86- joi . object ( {
87- message : joi . string ( ) . required ( ) ,
88- matches : joi . array ( ) . required ( ) . items ( joi . object ( ) . regex ( ) ) ,
89- } )
90- ) ,
91- } )
92- ) ,
67+ index : z . array ( indexDescriptionSchema ) ,
9368} ) ;
9469
70+ export type ErrorMatcher = z . infer < typeof errorMatcherSchema > ;
71+ export type SnippetIndexFile = z . infer < typeof indexFileSchema > & {
72+ sourceURL : string ;
73+ } ;
74+ export type SnippetDescription = z . infer < typeof indexDescriptionSchema > ;
75+
9576async function unpackBSON < T = any > ( data : Buffer ) : Promise < T > {
9677 return bson . deserialize ( await brotliDecompress ( data ) ) as T ;
9778}
@@ -361,9 +342,8 @@ export class SnippetManager implements ShellPlugin {
361342 `The specified index file ${ url } could not be parsed: ${ err . message } `
362343 ) ;
363344 }
364- const { error } = indexFileSchema . validate ( data , {
365- allowUnknown : true ,
366- } ) ;
345+ const { error, data : parsedData } =
346+ indexFileSchema . safeParse ( data ) ;
367347 if ( error ) {
368348 this . messageBus . emit ( 'mongosh-snippets:fetch-index-error' , {
369349 action : 'validate-fetched' ,
@@ -374,7 +354,7 @@ export class SnippetManager implements ShellPlugin {
374354 `The specified index file ${ url } is not a valid index file: ${ error . message } `
375355 ) ;
376356 }
377- return { ...data , sourceURL : url } ;
357+ return { ...parsedData , sourceURL : url } ;
378358 } )
379359 ) ;
380360 // If possible, write the result to disk for caching.
0 commit comments