Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions .github/workflows/quality.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
name: Quality

on:
push:
branches: [main]
pull_request:
branches: [main]

jobs:
quality:
name: Quality
runs-on: ubuntu-latest

strategy:
matrix:
node-version: [18.x, 20.x, 22.x]

steps:
- uses: actions/checkout@v2
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v2
with:
node-version: ${{ matrix.node-version }}

- name: Install dependencies
run: npm install

- name: Eslint
run: npm run eslint

- name: Prettier Check
run: npm run prettier:check
39 changes: 39 additions & 0 deletions .github/workflows/ut.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
name: Unit Tests

on:
push:
branches: [main]
pull_request:
branches: [main]

jobs:
tests:
name: Tests
runs-on: ubuntu-latest

strategy:
matrix:
node-version: [18.x, 20.x, 22.x]

steps:
- uses: actions/checkout@v2
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v2
with:
node-version: ${{ matrix.node-version }}
- name: Install dependencies
run: npm install

- name: Build
run: npm run build

- name: Run Unit Tests
run: npm test

- name: Test Coverage
run: npm run test:coverage

- name: Coveralls
uses: coverallsapp/github-action@master
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
9 changes: 9 additions & 0 deletions .nycrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"check-coverage": true,
"branches": 0,
"lines": 0,
"functions": 0,
"statements": 0,
"include": ["src/**/!(*.test.*).[tj]s?(x)"],
"exclude": ["./config.unit-test.mjs"]
}
3 changes: 2 additions & 1 deletion bin/nil-toolkit.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { ArgumentParser } from 'argparse'
import { loadSystem } from '../dist/entries.js'
import camelCase from 'lodash/camelCase.js'
import esMain from 'es-main'
import { Namespace } from '../dist/types.js'

const _parseArguments = () => {
const parser = new ArgumentParser({
Expand Down Expand Up @@ -55,7 +56,7 @@ const main = async () => {

const system = await loadSystem(args)
const command = camelCase(args.command)
await system.features['nil-toolkit/toolkit'][command](args).catch(e => {
await system.features[Namespace.toolkit][command](args).catch(e => {
console.error(e.message)
console.error(e)
})
Expand Down
8 changes: 5 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@node-in-layers/toolkit",
"type": "module",
"version": "1.0.8",
"version": "1.1.0",
"description": "The official toolkit for creating/updating/maintaining Node In Layer based systems.",
"main": "index.js",
"bin": {
Expand All @@ -15,7 +15,8 @@
"eslint": "eslint .",
"feature-tests": "./node_modules/.bin/cucumber-js -p default",
"prettier": "prettier --write .",
"test": "export TS_NODE_TRANSPILE_ONLY=true && export TS_NODE_PROJECT='./tsconfig.test.json' && mocha -r ts-node/register 'test/**/*.test.ts'",
"prettier:check": "prettier -c .",
"test": "export TS_NODE_PROJECT='./tsconfig.test.json' && mocha -r tsx ./test/src/*.test.ts ./test/src/**/*.test.ts ./test/src/**/**/*.test.ts",
"test:coverage": "nyc --all --reporter cobertura --reporter text --reporter lcov --reporter html npm run test"
},
"config": {
Expand Down Expand Up @@ -60,10 +61,11 @@
"sinon-chai": "^3.5.0",
"source-map-support": "^0.5.21",
"ts-node": "^10.4.0",
"tsx": "^4.19.2",
"typescript": "5.3.3"
},
"dependencies": {
"@node-in-layers/core": "^1.0.4",
"@node-in-layers/core": "^1.1.1",
"argparse": "^2.0.1",
"chalk": "^4.1.2",
"es-main": "^1.3.0",
Expand Down
31 changes: 18 additions & 13 deletions src/app/index.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,25 @@
import { fileURLToPath } from 'node:url'
import path, { dirname } from 'node:path'
import * as glob from 'glob'
import { SimpleFeaturesDependencies } from '@node-in-layers/core/index.js'
import {
FeaturesDependencies,
Config,
ServicesDependencies,
} from '@node-in-layers/core/index.js'
import { PackageServicesLayer, PackageType } from '../package/types.js'
import { Namespace } from '../types.js'
import { AppServicesLayer, AppServices } from './types.js'
import { applyTemplates, createValidAppName } from './libs.js'

const __filename = fileURLToPath(import.meta.url)
const __dirname = dirname(__filename)

const services = {
create: (deps): AppServices => {
create: (deps: ServicesDependencies): AppServices => {
const _getPackageJson = async (): Promise<string | undefined> => {
const wd = `${deps.constants.workingDirectory}/package.json`
return (await glob.glob(wd)).find(
p => deps.fs.lstatSync(p).isFile() && p.endsWith('package.json')
p => deps.node.fs.lstatSync(p).isFile() && p.endsWith('package.json')
)
}

Expand All @@ -25,22 +30,22 @@

const doesAppAlreadyExist = appName => {
const dirPath = path.join(__dirname, appName)
return deps.fs.existsSync(dirPath)
return deps.node.fs.existsSync(dirPath)
}

const getPackageName = async () => {
const packagePath = await _getPackageJson()
if (!packagePath) {
throw new Error(`package.json could not be found`)
}
const data = deps.fs.readFileSync(packagePath, 'utf-8')
const data = deps.node.fs.readFileSync(packagePath, 'utf-8')
const asJson = JSON.parse(data)
return asJson.name
}

const getPackageType = () =>
Promise.resolve().then(() => {
// TODO: Add support for non-typescript

Check warning on line 48 in src/app/index.ts

View workflow job for this annotation

GitHub Actions / Quality (18.x)

Unexpected 'todo' comment: 'TODO: Add support for non-typescript'

Check warning on line 48 in src/app/index.ts

View workflow job for this annotation

GitHub Actions / Quality (20.x)

Unexpected 'todo' comment: 'TODO: Add support for non-typescript'

Check warning on line 48 in src/app/index.ts

View workflow job for this annotation

GitHub Actions / Quality (22.x)

Unexpected 'todo' comment: 'TODO: Add support for non-typescript'
return PackageType.typescript
})

Expand All @@ -50,12 +55,12 @@
`../templates/app/${packageType}/src/**/*`
)
const paths = (await glob.glob(templatePath, { dot: true })).filter(p =>
deps.fs.lstatSync(p).isFile()
deps.node.fs.lstatSync(p).isFile()
)
return paths.map(sourceLocation => {
const dirA = path.join(__dirname, `../templates/app/${packageType}`)
const relativePath = path.relative(dirA, sourceLocation)
const sourceData = deps.fs.readFileSync(sourceLocation, 'utf-8')
const sourceData = deps.node.fs.readFileSync(sourceLocation, 'utf-8')
return {
relativePath,
sourceData,
Expand All @@ -70,8 +75,8 @@
.replaceAll('.handlebars', '')
.replaceAll('APP_NAME', appName)
const dirPath = path.dirname(finalLocation)
deps.fs.mkdirSync(dirPath, { recursive: true })
deps.fs.writeFileSync(finalLocation, t.templatedData)
deps.node.fs.mkdirSync(dirPath, { recursive: true })
deps.node.fs.writeFileSync(finalLocation, t.templatedData)
})
}

Expand All @@ -88,15 +93,15 @@

const features = {
create: (
deps: SimpleFeaturesDependencies<PackageServicesLayer & AppServicesLayer>
deps: FeaturesDependencies<Config, PackageServicesLayer & AppServicesLayer>
) => {
const createApp = async ({ appName }: { appName: string }) => {
const ourServices = deps.services['nil-toolkit/app']
const ourServices = deps.services[Namespace.app]
const logger = deps.log.getLogger('nil-toolkit:createApp')

appName = createValidAppName(appName)

if (!deps.services['nil-toolkit/app'].isPackageRoot()) {
if (!deps.services[Namespace.app].isPackageRoot()) {
throw new Error(
`Must be located in the main directory of your node-in-layers system or package. This is the same directory as the package.json.`
)
Expand Down Expand Up @@ -130,5 +135,5 @@
},
}

const name = 'nil-toolkit/app'
const name = Namespace.app
export { services, features, name }
5 changes: 3 additions & 2 deletions src/app/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
TemplatedFile,
FinalizedTemplate,
} from '../package/types.js'
import { Namespace } from '../types.js'

type AppServices = Readonly<{
isPackageRoot: () => Promise<boolean>
Expand All @@ -17,15 +18,15 @@ type AppServices = Readonly<{
}>

type AppServicesLayer = Readonly<{
'nil-toolkit/app': AppServices
[Namespace.app]: AppServices
}>

type AppFeatures = Readonly<{
createApp: ({ appName }: { appName: string }) => Promise<void>
}>

type AppFeaturesLayer = Readonly<{
'nil-toolkit/app': AppFeatures
[Namespace.app]: AppFeatures
}>

export { AppServices, AppServicesLayer, AppFeatures, AppFeaturesLayer }
9 changes: 7 additions & 2 deletions src/config.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
import { Config, LogFormat, LogLevelNames } from '@node-in-layers/core'
import {
Config,
LogFormat,
LogLevelNames,
CoreNamespace,
} from '@node-in-layers/core/index.js'

const create = async (options: {
logFormat?: LogFormat
logLevel?: LogLevelNames
}): Promise<Config> => {
return {
environment: 'prod',
'nil-core/core': {
[CoreNamespace.root]: {
apps: [
await import('./package/index.js'),
await import('./app/index.js'),
Expand Down
13 changes: 3 additions & 10 deletions src/entries.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import fs from 'node:fs'
import * as core from '@node-in-layers/core'
import { LogFormat, LogLevelNames } from '@node-in-layers/core'
import { create as createConfig } from './config.js'
Expand All @@ -7,17 +6,11 @@ const loadSystem = async (args: {
logFormat?: LogFormat
logLevel?: LogLevelNames
}) => {
const coreServices = core.services.create({
fs,
const config = await createConfig(args)
return core.loadSystem({
environment: 'prod',
workingDirectory: process.cwd(),
config,
})
const features = core.features.create({
services: {
['nil-core/core']: coreServices,
},
})
return features.loadSystem(await createConfig(args))
}

export { loadSystem }
5 changes: 4 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
const name = 'nil-toolkit'
import { Namespace } from './types.js'

const name = Namespace.root

export * as nilPackage from './package/index.js'
export { name }
7 changes: 4 additions & 3 deletions src/package/features.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { SimpleFeaturesDependencies } from '@node-in-layers/core/index.js'
import { FeaturesDependencies, Config } from '@node-in-layers/core/index.js'
import { Namespace } from '../types.js'
import { PackageServicesLayer, PackageType } from './types.js'
import { applyTemplates, createValidPackageName } from './libs.js'

const create = (
dependencies: SimpleFeaturesDependencies<PackageServicesLayer>
dependencies: FeaturesDependencies<Config, PackageServicesLayer>
) => {
const ourServices = dependencies.services['nil-toolkit/package']
const ourServices = dependencies.services[Namespace.package]
const createPackage = async ({
packageName,
packageType,
Expand Down
6 changes: 4 additions & 2 deletions src/package/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { Namespace } from '../types.js'

const name = Namespace.package

export * as services from './services.js'
export * as features from './features.js'

const name = 'nil-toolkit/package'
export { name }
17 changes: 10 additions & 7 deletions src/package/services.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { dirname } from 'path'
import path from 'node:path'
import exec from 'node:child_process'
import * as glob from 'glob'
import { ServicesDependencies } from '@node-in-layers/core'
import { ServicesDependencies } from '@node-in-layers/core/index.js'
import { FinalizedTemplate, PackageServices, TemplatedFile } from './types.js'

const __filename = fileURLToPath(import.meta.url)
Expand All @@ -15,10 +15,10 @@ const create = (dependencies: ServicesDependencies): PackageServices => {
dependencies.constants.workingDirectory,
packageName
)
if (dependencies.fs.existsSync(fullPath)) {
if (dependencies.node.fs.existsSync(fullPath)) {
throw new Error(`${fullPath} already exists. Must be a new directory.`)
}
dependencies.fs.mkdirSync(fullPath)
dependencies.node.fs.mkdirSync(fullPath)
}

const _readAllTemplateFiles = async (
Expand All @@ -29,12 +29,15 @@ const create = (dependencies: ServicesDependencies): PackageServices => {
`../templates/package/${subDirectory}/**/*`
)
const paths = (await glob.glob(templatePath, { dot: true })).filter(p =>
dependencies.fs.lstatSync(p).isFile()
dependencies.node.fs.lstatSync(p).isFile()
)
return paths.map(sourceLocation => {
const dirA = path.join(__dirname, `../templates/package/${subDirectory}`)
const relativePath = path.relative(dirA, sourceLocation)
const sourceData = dependencies.fs.readFileSync(sourceLocation, 'utf-8')
const sourceData = dependencies.node.fs.readFileSync(
sourceLocation,
'utf-8'
)
return {
relativePath,
sourceData,
Expand Down Expand Up @@ -62,8 +65,8 @@ const create = (dependencies: ServicesDependencies): PackageServices => {
.replaceAll('.handlebars', '')
.replaceAll('PACKAGE_NAME', packageName)
const dirPath = path.dirname(finalLocation)
dependencies.fs.mkdirSync(dirPath, { recursive: true })
dependencies.fs.writeFileSync(finalLocation, t.templatedData)
dependencies.node.fs.mkdirSync(dirPath, { recursive: true })
dependencies.node.fs.writeFileSync(finalLocation, t.templatedData)
})
}

Expand Down
Loading
Loading