@green-stack/corescriptshelpersscriptUtils
Alt description missing in image

Script Utils

import * as scriptUtils from '@green-stack/scripts/helpers/scriptUtils'
          • scriptUtils.ts

A collection of utility functions for working with scripts, file paths, and workspace management in the Green Stack ecosystem.

File System Utilities

excludeDirs()

Filter function to exclude folders and directories. Returns true if the path contains a file (has an extension).

excludeDirs('path/to/file.ts') // => true
excludeDirs('path/to/folder') // => false
 
// Usage as a filter function:
 
const paths = [
    '/components/Button.tsx',
    '/components/Input.tsx',
    '/components/',
    '/schemas'
]
 
const filteredPaths = paths.filter(excludeDirs)
// => ['/components/Button.tsx', '/components/Input.tsx']

excludeModules()

Filter function to exclude node_modules folders. Returns true if the path does not include ‘node_modules’.

excludeModules('src/components/Button.tsx') // => true
excludeModules('node_modules/react/index.js') // => false
 
// Usage as a filter function:
 
const paths = [
    'src/components/Button.tsx',
    'src/components/Input.tsx',
    'node_modules/react/index.js',
    'node_modules/@app-core/utils.js'
]
 
const filteredPaths = paths.filter(excludeModules)
// => ['src/components/Button.tsx', 'src/components/Input.tsx']

globRel()

Gets the relative glob path of a glob-style selector using globSync. The path must contain one of the workspace folder locations (‘features’, ‘packages’, or ‘apps’).

globRel('packages/**/*.ts')
// => ['packages/@green-stack-core/utils.ts', 'packages/@app-core/components.ts']
 
globRel('features/**/components/*.tsx')
// => ['features/@app-core/components/Button.tsx', 'features/@app-core/components/Input.tsx']

hasOptOutPatterns()

Checks if file content has opt-out patterns to determine if the file should be ignored.

const content = `
export const optOut = true
// Rest of the file...
`
hasOptOutPatterns(content) // => true
 
const content2 = `
// @automation optOut = true
// Rest of the file...
`
hasOptOutPatterns(content2) // => true

String Utilities

normalizeName()

Makes sure only lowercase and uppercase letters are left in a given string by removing all other characters.

normalizeName('user-profile') // => 'userprofile'
normalizeName('User_Profile_123') // => 'UserProfile'

matchMethods()

Checks that a certain method (like ‘GET’, ‘POST’, etc.) is included in a list of method names.

const methods = ['GET', 'POST', 'PUT']
matchMethods(methods, 'GET') // => true
matchMethods(methods, 'DELETE') // => false

createDivider()

Creates a code divider that’s always 100 chars wide. Can be used for documentation or code comments.

createDivider('Section Title')
// => '/* --- Section Title ----------------------------------------------------------------------------------- */'
 
createDivider('Section Title', true)
// => '/** --- Section Title ----------------------------------------------------------------------------------- */'

validateNonEmptyNoSpaces()

Validates that a string is not empty and does not contain spaces.

validateNonEmptyNoSpaces('validName') // => true
validateNonEmptyNoSpaces('') // => 'Please enter a non-empty value'
validateNonEmptyNoSpaces('invalid name') // => 'Please enter a value without spaces'

Handy for plop prompt input validation.

Workspace Management

parseWorkspaces()

Figure out all info about all workspaces in the monorepo and return mapped linking info for use in scripts and generators.

const workspaceInfo = parseWorkspaces(
    folderLevel = '../../',
    includeApps = false,
)
// => {
//
//        /** -i- Map of { [path]: package.json config, ... } */
//        workspaceConfigs: { ... },
//
//        /** -i- Map of { [path]: pkgName, ... } */
//        workspaceImports: { ... },
//
//        /** -i- Map of { [pkgName]: path, ... } */
//        workspacePathsMap: { ... },
//
//        /** -i- Array of all workspace packages, e.g. ['features/@app-core', 'packages/@green-stack-core', ...] */
//        workspacePaths: [ ... ],
//
//        /** -i- Array of all workspace packages, e.g. ['@app/core', '@green-stack/core', ...] */
//        workspacePackages: [ ... ]
//
//        // -- Aliases and Constants --
//
//        /** -i- Map of { [path]: package.json config, ... } */
//        PATH_CONFIGS: { ... },
//
//        /** -i- Map of { [pkgName]: package.json config, ... } */
//        PKG_CONFIGS: { ... },
//
//        /** -i- Map of { [path]: pkgName, ... } */
//        PATH_PKGS: { ... },
//
//        /** -i- Map of { [pkgName]: path, ... } */
//        PKG_PATHS: { ... },
//
//    }

getWorkspaceOptions()

List all the available workspaces for generators to use.

const options = getWorkspaceOptions(folderLevel = '../../', {
    filter: ['@app'], // string[]
    exclude = [], // string[] -i- (List of packages to exclude)
    excludePackages = false, // boolean -i- (Exclude workspaces from /packages/?)
    includeApps = false, // boolean -i- (Include workspaces from /apps/?)
    includeGreenStack = false, // boolean -i- (Include /packages/@green-stack-core/?)
    skipFormatting = false, // boolean -i- (Skip formatting the output)
    prefer = [], // string[] -i- (Puts these options at the top of the list)
})
// => {
//        '@app/core  --  from features/@app-core': 'features/@app-core',
//        '@app/ui  --  from features/@app-ui': 'features/@app-ui'
//    }

getAvailableSchemas()

List all the available schemas in the codebase that generators can use.

const schemas = getAvailableSchemas(folderLevel = '../../', {
    schemaKey = 'schemaName', // 'schemaName' | 'schemaPath' | 'schemaOption'
    includeOptOut = false, // boolean
})
// => {
//        'UserSchema': {
//            schemaPath: 'features/@app-core/schemas/User.ts',
//            schemaName: 'UserSchema',
//            schemaFileName: 'User.ts',
//            schemaOption: '@app/core - User (♻ - Schema)',
//            workspacePath: 'features/@app-core',
//            workspaceName: '@app/core',
//            isNamedExport: true,
//            isDefaultExport: false,
//            schema?: ZodSchema | undefined
//        },
//        ... (more schemas)
//    }

The default arguments for folderLevel and schemaKey are '../../' and 'schemaName', respectively. You can adjust these based on your project structure. If you want the resulting lookup object to be keyed by either the path or option, you can pass schemaPath or schemaOption as the schemaKey.

getAvailableDataBridges()

List all the available data bridges for generators to use.

const bridges = getAvailableDataBridges('../../', {
    filterType?: 'query', // 'query' | 'mutation'
    bridgeKey?: 'bridgeName', // 'bridgeName' | 'bridgePath' | 'bridgeOption' | 'bridgeInputOption'
    allowNonGraphql?: false, // boolean
    includeOptOut?: false, // boolean
})
// => {
//        'UserBridge': {
//            bridgePath: 'features/@app-core/resolvers/healthCheck.bridge.ts',
//            bridgeName: 'healthCheckBridge',
//            bridgeOption: '@app/core >>> healthCheck() (♻ - Resolver)',
//            bridgeInputOption: '@app/core >>> healthCheck() (♻ - Input)',
//            workspacePath: 'features/@app-core',
//            workspaceName: '@app/core',
//            resolverName: 'healthCheck',
//            resolverType: 'query' | 'mutation',
//            operationType: 'search' | 'add' | 'update' | 'delete' | 'get' | 'list',
//            fetcherName: 'healthCheckQuery',
//            inputSchemaName: 'HealthCheckInput',
//            outputSchemaName: 'HealthCheckOutput',
//            allowedMethods: ['GET', 'POST'],
//            isNamedExport: true,
//            isDefaultExport: false,
//            isMutation: false,
//            isQuery: true,
//            bridge?: DataBridgeType | undefined,
//        },
//        ... (more bridges)
//    }

Import Management

readImportAliases()

Retrieve the import aliases from the main tsconfig.json in @app/core.

const aliases = readImportAliases('../../')
// => {
//       '@app/core/appConfig': '@app/config',
//       '@app/core/schemas': '@app/schemas',
//       '@app/core/utils': '@app/utils',
//       '@app/core/hooks': '@app/hooks',
//       '@app/core/components/styled': '@app/primitives',
//       '@app/core/components': '@app/components',
//       '@app/core/forms': '@app/forms',
//       '@app/core/screens': '@app/screens',
//       '@app/core/assets': '@app/assets',
//       '@app/core/resolvers': '@app/resolvers',
//       '@app/core/middleware': '@app/middleware',
//       '@green-stack/core/schemas': '@green-stack/schemas',
//       '@green-stack/core/navigation/index': '@green-stack/navigation',
//       '@green-stack/core/navigation': '@green-stack/navigation',
//       '@green-stack/core/utils': '@green-stack/utils',
//       '@green-stack/core/hooks': '@green-stack/hooks',
//       '@green-stack/core/components': '@green-stack/components',
//       '@green-stack/core/styles/index': '@green-stack/styles',
//       '@green-stack/core/styles': '@green-stack/styles',
//       '@green-stack/core/forms': '@green-stack/forms',
//       '@green-stack/core/context': '@green-stack/context',
//       '@green-stack/core/scripts': '@green-stack/scripts',
//       '@green-stack/core/svg/svg.primitives': '@green-stack/svg',
//    }

swapImportAlias()

Swap an import path with an alias if a match occurs.

swapImportAlias('@app/core/appConfig')
// => '@app/config'
 
swapImportAlias('@app/config')
// => '@app/config'

CLI Utilities

opt()

Format a CLI option with proper styling and hierarchy.

Will grey out the anything after the -- when displayed in the terminal.

opt('Some Option')
// => 'Some Option' (nothing greyed out using ansi colors)
 
opt('Some Option  --  This extra info is greyed out')
// => 'Some option  --  This extra info is greyed out'

Helper Functions

includesOption()

Higher-order function to prefill a list of options that are checked against in the actual filter method.

const includesGetOrPost = includesOption(['GET', 'POST'])
const methods = ['GET', 'POST', 'PUT']
methods.filter(includesGetOrPost) // => ['GET', 'POST']

maybeImport()

Attempts to require() a file, but returns an empty object if it fails or the file doesn’t exist.

// File exists
maybeImport('./config.js')
// => { port: 3000, host: 'localhost' }
 
// File doesn't exist
maybeImport('./nonexistent.js')
// => {}
 
// With error logging
maybeImport('./config.js', 'logErrors')
// => Logs error if file doesn't exist

Types

SchemaFileMeta

Metadata about a schema file:

type SchemaFileMeta = {
    schema?: ZodSchema | {}
    schemaPath: string
    schemaName: string
    schemaFileName: string
    schemaOption: string
    workspacePath: string
    workspaceName: string
    isNamedExport: boolean
    isDefaultExport: boolean
}

FetcherFileMeta

Metadata about a fetcher file:

type FetcherFileMeta = {
    resolverName: string
    fetcherName: string
    fetcherType: 'query' | 'mutation'
}

BridgeFileMeta

Metadata about a data bridge file:

type BridgeFileMeta = {
    bridge?: DataBridgeType | {}
    bridgePath: string
    bridgeName: string
    bridgeOption: string
    bridgeInputOption: string
    workspacePath: string
    workspaceName: string
    resolverName: string
    resolverType: 'query' | 'mutation'
    operationType: 'add' | 'update' | 'delete' | 'get' | 'list' | 'search'
    fetcherName: string
    inputSchemaName: string
    outputSchemaName: string
    allowedMethods: ALLOWED_METHODS[]
    isNamedExport: boolean
    isDefaultExport: boolean
    isMutation: boolean
    isQuery: boolean
}

Re-exports

Utils from stringUtils

Re-exports all the utility functions from @green-stack/core/utils/stringUtils: