From ad5aa80a84651ab4649fa38c272270a694cef0a1 Mon Sep 17 00:00:00 2001 From: SrIzan10 <66965250+SrIzan10@users.noreply.github.com> Date: Thu, 4 Jan 2024 19:52:11 +0000 Subject: [PATCH 01/24] some wip code Co-authored-by: Jacob Nguyen --- TEST PLEASE DELETE.js | 20 ++++++++++++++++++++ package.json | 1 + src/core/contracts/emitter.ts | 2 ++ src/core/ioc/base.ts | 23 +++++++++++++++++------ src/core/ioc/container.ts | 4 ++-- src/types/ioc.ts | 4 ++++ yarn.lock | 8 ++++++++ 7 files changed, 54 insertions(+), 8 deletions(-) create mode 100644 TEST PLEASE DELETE.js diff --git a/TEST PLEASE DELETE.js b/TEST PLEASE DELETE.js new file mode 100644 index 00000000..7fe3534f --- /dev/null +++ b/TEST PLEASE DELETE.js @@ -0,0 +1,20 @@ +const { Localization } = require('shrimple-locales'); + +//ok so plan is, +/** + * + * await makeDependencies(({ include })=> { + * include('@sern/localizer') // preconfigure localizer, will expose the translate function + * }); + * + */ +const loc = new Localization({ + defaultLocale: 'en', + fallbackLocale: 'en', + locales: { + en: { somethingInside: { hey: 'hi' }, somethingOutside: 'hello' }, + es: { somethingInside: { hey: 'hola inside' }, somethingOutside: 'hola' } + } +}); + +console.log(loc.get('somethingOutside')); \ No newline at end of file diff --git a/package.json b/package.json index 1aae54ae..bc0485cb 100644 --- a/package.json +++ b/package.json @@ -40,6 +40,7 @@ "callsites": "^3.1.0", "iti": "^0.6.0", "rxjs": "^7.8.0", + "shrimple-locales": "^0.1.1", "ts-results-es": "^4.0.0" }, "devDependencies": { diff --git a/src/core/contracts/emitter.ts b/src/core/contracts/emitter.ts index abb3a29c..11bbc286 100644 --- a/src/core/contracts/emitter.ts +++ b/src/core/contracts/emitter.ts @@ -1,3 +1,5 @@ +//i deleted it, hmm so how should we allow users to enable localization? +// a import type { AnyFunction } from '../../types/utility'; export interface Emitter { diff --git a/src/core/ioc/base.ts b/src/core/ioc/base.ts index 9de0c75f..c04e3be2 100644 --- a/src/core/ioc/base.ts +++ b/src/core/ioc/base.ts @@ -2,7 +2,7 @@ import * as assert from 'assert'; import { composeRoot, useContainer } from './dependency-injection'; import type { DependencyConfiguration } from '../../types/ioc'; import { CoreContainer } from './container'; -import { Result } from 'ts-results-es' +import { Result } from 'ts-results-es'; import { DefaultServices } from '../_internal'; import { AnyFunction } from '../../types/utility'; import type { Logging } from '../contracts/logging'; @@ -29,7 +29,7 @@ export function disposeAll(logger: Logging|undefined) { .then(() => logger?.info({ message: 'Cleaning container and crashing' })); } -const dependencyBuilder = (container: any, excluded: string[]) => { +const dependencyBuilder = (container: any, excluded: string[], included: string[]) => { type Insertable = | ((container: CoreContainer) => unknown ) | Record @@ -50,6 +50,9 @@ const dependencyBuilder = (container: any, excluded: string[]) => { exclude(...keys: (keyof Dependencies)[]) { keys.forEach(key => excluded.push(key)); }, + include(...keys: string[]) { + included.push(...keys); + }, /** * @param key the key of the dependency * @param v The dependency to swap out. @@ -92,13 +95,21 @@ export async function makeDependencies containerSubject = new CoreContainer(); if(typeof conf === 'function') { const excluded: string[] = []; - conf(dependencyBuilder(containerSubject, excluded)); - - if(!excluded.includes('@sern/logger') - && !containerSubject.getTokens()['@sern/logger']) { + const included: string[] = []; + conf(dependencyBuilder(containerSubject, excluded, included)); + + const includeLogger = + !excluded.includes('@sern/logger') + && !containerSubject.getTokens()['@sern/logger']; + if(includeLogger) { insertLogger(containerSubject); } + // well damn i have to go sorry, rip okay dsoo you want me to commit? + //push draft pr okok + const validIncludes = '@sern/localizer'; + if(included.includes(validIncludes)) { + } containerSubject.ready(); } else { composeRoot(containerSubject, conf); diff --git a/src/core/ioc/container.ts b/src/core/ioc/container.ts index ff61173c..6bf1c796 100644 --- a/src/core/ioc/container.ts +++ b/src/core/ioc/container.ts @@ -3,7 +3,7 @@ import { Disposable, SernEmitter } from '../'; import * as assert from 'node:assert'; import { Subject } from 'rxjs'; import { DefaultServices, ModuleStore } from '../_internal'; -import * as Hooks from './hooks' +import * as Hooks from './hooks'; /** @@ -44,7 +44,7 @@ export class CoreContainer> extends Container dep.dispose() } as never); } - await super.disposeAll() + await super.disposeAll(); } ready() { this.ready$.complete(); diff --git a/src/types/ioc.ts b/src/types/ioc.ts index bbfb02e5..9b821fd0 100644 --- a/src/types/ioc.ts +++ b/src/types/ioc.ts @@ -42,6 +42,10 @@ export type IntoDependencies = { export interface DependencyConfiguration { //@deprecated. Loggers will always be included in the future exclude?: Set<'@sern/logger'>; + + //Extra modules that are preconfigured and ready to use! @sern/localizer is an example + include?: string[] + build: ( root: Container, {}>, ) => Container; diff --git a/yarn.lock b/yarn.lock index 701090b2..4085630c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -634,6 +634,7 @@ __metadata: iti: ^0.6.0 prettier: 2.8.8 rxjs: ^7.8.0 + shrimple-locales: ^0.1.1 ts-results-es: ^4.0.0 tsup: ^6.7.0 typescript: 5.0.2 @@ -3114,6 +3115,13 @@ __metadata: languageName: node linkType: hard +"shrimple-locales@npm:^0.1.1": + version: 0.1.1 + resolution: "shrimple-locales@npm:0.1.1" + checksum: 78db184b1f3a1a6f00b6f6a1de1a283668ac8f2497673a1a1592ac245983923ea0089c4590a2dd2cd256a2977873c284278ec14067173e51e758d632bd025b78 + languageName: node + linkType: hard + "siginfo@npm:^2.0.0": version: 2.0.0 resolution: "siginfo@npm:2.0.0" From 18a420a751e17b84eb1416d4c3a03d3525f7f0c6 Mon Sep 17 00:00:00 2001 From: Jacob Nguyen <76754747+jacoobes@users.noreply.github.com> Date: Thu, 4 Jan 2024 14:39:55 -0600 Subject: [PATCH 02/24] general idea --- src/core/ioc/base.ts | 7 ++++++- src/core/ioc/dependency-injection.ts | 4 ++++ src/core/module-loading.ts | 2 +- 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/core/ioc/base.ts b/src/core/ioc/base.ts index c04e3be2..d0d8ee47 100644 --- a/src/core/ioc/base.ts +++ b/src/core/ioc/base.ts @@ -6,6 +6,8 @@ import { Result } from 'ts-results-es'; import { DefaultServices } from '../_internal'; import { AnyFunction } from '../../types/utility'; import type { Logging } from '../contracts/logging'; +import { requir } from '../module-loading'; + //SIDE EFFECT: GLOBAL DI let containerSubject: CoreContainer>; @@ -107,9 +109,12 @@ export async function makeDependencies // well damn i have to go sorry, rip okay dsoo you want me to commit? //push draft pr okok const validIncludes = '@sern/localizer'; - if(included.includes(validIncludes)) { + if(included.includes(validIncludes)) { + //Would be preferred if we can get away without awaiting + containerSubject.add({ '@sern/localizer': requir('shrimple-locales') }); } + containerSubject.ready(); } else { composeRoot(containerSubject, conf); diff --git a/src/core/ioc/dependency-injection.ts b/src/core/ioc/dependency-injection.ts index 126efe3b..f98db9a8 100644 --- a/src/core/ioc/dependency-injection.ts +++ b/src/core/ioc/dependency-injection.ts @@ -1,4 +1,5 @@ import type { CoreDependencies, DependencyConfiguration, IntoDependencies } from '../../types/ioc'; +import { requir } from '../module-loading'; import { insertLogger, useContainerRaw } from './base'; import { CoreContainer } from './container'; @@ -61,6 +62,9 @@ export function composeRoot( if (!hasLogger) { insertLogger(container); } + if(conf.include?.includes('@sern/localizer')) { + container.add({ '@sern/localizer': requir('shrimple-locales') }); + } //Build the container based on the callback provided by the user conf.build(container as CoreContainer>); diff --git a/src/core/module-loading.ts b/src/core/module-loading.ts index a7c6d36d..94758e0a 100644 --- a/src/core/module-loading.ts +++ b/src/core/module-loading.ts @@ -107,7 +107,7 @@ async function* readPaths(dir: string): AsyncGenerator { } } -const requir = createRequire(import.meta.url); +export const requir = createRequire(import.meta.url); export function loadConfig(wrapper: Wrapper | 'file'): Wrapper { if (wrapper !== 'file') { From 50043858f44f3f783bf78b2b1e944fbf09c58d44 Mon Sep 17 00:00:00 2001 From: Jacob Nguyen <76754747+jacoobes@users.noreply.github.com> Date: Thu, 4 Jan 2024 16:58:36 -0600 Subject: [PATCH 03/24] style --- src/core/ioc/container.ts | 6 +++++- src/core/ioc/dependency-injection.ts | 2 +- src/core/ioc/hooks.ts | 3 ++- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/core/ioc/container.ts b/src/core/ioc/container.ts index 6bf1c796..50526ad0 100644 --- a/src/core/ioc/container.ts +++ b/src/core/ioc/container.ts @@ -17,11 +17,12 @@ export class CoreContainer> extends Container) - .add({ '@sern/errors': () => new DefaultServices.DefaultErrorHandling(), + .add({ '@sern/errors': () => new DefaultServices.DefaultErrorHandling, '@sern/emitter': () => new SernEmitter, '@sern/store': () => new ModuleStore }) .add(ctx => { @@ -46,6 +47,9 @@ export class CoreContainer> extends Container(...keys: [...T] } /** - * Given the user's conf, check for any excluded dependency keys. + * Given the user's conf, check for any excluded/included dependency keys. * Then, call conf.build to get the rest of the users' dependencies. * Finally, update the containerSubject with the new container state * @param conf diff --git a/src/core/ioc/hooks.ts b/src/core/ioc/hooks.ts index a1db322e..0a325572 100644 --- a/src/core/ioc/hooks.ts +++ b/src/core/ioc/hooks.ts @@ -9,7 +9,7 @@ type HookName = 'init'; export const createInitListener = (coreContainer : CoreContainer) => { const initCalled = new Set(); const hasCallableMethod = createPredicate(initCalled); - const unsubscribe = coreContainer.on('containerUpserted', async (event) => { + const unsubscribe = coreContainer.on('containerUpserted', async event => { if(isNotHookable(event)) { return; @@ -21,6 +21,7 @@ export const createInitListener = (coreContainer : CoreContainer) => { } }); + return { unsubscribe }; } From e98f9f99ceec9aabf27017f1470c81f71f68a82c Mon Sep 17 00:00:00 2001 From: Jacob Nguyen <76754747+jacoobes@users.noreply.github.com> Date: Sat, 6 Jan 2024 12:17:41 -0600 Subject: [PATCH 04/24] making shrimple truly optional --- package.json | 6 ++++-- src/core/contracts/error-handling.ts | 2 -- src/core/contracts/index.ts | 1 + src/core/contracts/init.ts | 3 +-- src/core/contracts/localizer.ts | 4 ++++ src/core/ioc/base.ts | 20 ++++++++++++-------- src/core/ioc/container.ts | 4 ++++ src/core/structures/optional/localizer.ts | 20 ++++++++++++++++++++ tsup.config.js | 4 ++-- yarn.lock | 13 ++++++++----- 10 files changed, 56 insertions(+), 21 deletions(-) create mode 100644 src/core/contracts/localizer.ts create mode 100644 src/core/structures/optional/localizer.ts diff --git a/package.json b/package.json index bc0485cb..ef828121 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,6 @@ "callsites": "^3.1.0", "iti": "^0.6.0", "rxjs": "^7.8.0", - "shrimple-locales": "^0.1.1", "ts-results-es": "^4.0.0" }, "devDependencies": { @@ -96,5 +95,8 @@ "type": "git", "url": "git+https://github.com/sern-handler/handler.git" }, - "homepage": "https://sern.dev" + "homepage": "https://sern.dev", + "optionalDependencies": { + "shrimple-locales": "^0.1.2" + } } diff --git a/src/core/contracts/error-handling.ts b/src/core/contracts/error-handling.ts index 7d17a563..d5e94550 100644 --- a/src/core/contracts/error-handling.ts +++ b/src/core/contracts/error-handling.ts @@ -1,5 +1,3 @@ -import type { CommandModule,Processed, EventModule } from "../../types/core-modules"; - /** * @since 2.0.0 */ diff --git a/src/core/contracts/index.ts b/src/core/contracts/index.ts index 7d123b1e..5c336761 100644 --- a/src/core/contracts/index.ts +++ b/src/core/contracts/index.ts @@ -5,3 +5,4 @@ export * from './module-store'; export * from './init'; export * from './emitter'; export * from './disposable' +export * from './localizer' diff --git a/src/core/contracts/init.ts b/src/core/contracts/init.ts index eec1e4ce..5769d239 100644 --- a/src/core/contracts/init.ts +++ b/src/core/contracts/init.ts @@ -1,9 +1,8 @@ -import type { Awaitable } from '../../types/utility'; /** * Represents an initialization contract. * Let dependencies implement this to initiate some logic. */ export interface Init { - init(): Awaitable; + init(): PromiseLike | unknown; } diff --git a/src/core/contracts/localizer.ts b/src/core/contracts/localizer.ts new file mode 100644 index 00000000..c7e76b27 --- /dev/null +++ b/src/core/contracts/localizer.ts @@ -0,0 +1,4 @@ + +export interface Localizer { + translate(text: string) : string; +} diff --git a/src/core/ioc/base.ts b/src/core/ioc/base.ts index d0d8ee47..06c35e68 100644 --- a/src/core/ioc/base.ts +++ b/src/core/ioc/base.ts @@ -92,6 +92,15 @@ export const insertLogger = (containerSubject: CoreContainer) => { containerSubject .upsert({'@sern/logger': () => new DefaultServices.DefaultLogging}); } + +export const insertLocalizer = async (containerSubject: CoreContainer) => { + const { ShrimpleLocalizer } = requir('../structures/services/localizer'); + containerSubject + .add({'@sern/localizer': new ShrimpleLocalizer() }); +} + + + export async function makeDependencies (conf: ValidDependencyConfig) { containerSubject = new CoreContainer(); @@ -103,16 +112,13 @@ export async function makeDependencies const includeLogger = !excluded.includes('@sern/logger') && !containerSubject.getTokens()['@sern/logger']; + if(includeLogger) { insertLogger(containerSubject); } - // well damn i have to go sorry, rip okay dsoo you want me to commit? - //push draft pr okok - const validIncludes = '@sern/localizer'; - if(included.includes(validIncludes)) { - //Would be preferred if we can get away without awaiting - containerSubject.add({ '@sern/localizer': requir('shrimple-locales') }); + if(included.includes('@sern/localizer')) { + await insertLocalizer(containerSubject); } containerSubject.ready(); @@ -123,5 +129,3 @@ export async function makeDependencies return useContainer(); } - - diff --git a/src/core/ioc/container.ts b/src/core/ioc/container.ts index 50526ad0..9f6b024c 100644 --- a/src/core/ioc/container.ts +++ b/src/core/ioc/container.ts @@ -34,6 +34,10 @@ export class CoreContainer> extends Container)._context[key]); + } override async disposeAll() { diff --git a/src/core/structures/optional/localizer.ts b/src/core/structures/optional/localizer.ts new file mode 100644 index 00000000..c248111c --- /dev/null +++ b/src/core/structures/optional/localizer.ts @@ -0,0 +1,20 @@ +import { Localizer, Init } from '../../contracts' +import { Localization } from 'shrimple-locales' +/** + * @internal + * @since 2.0.0 + * Version 4.0.0 will internalize this api. Please refrain from using ModuleStore! + */ +export class ShrimpleLocalizer implements Localizer, Init { + + __localization!: Localization; + translate(text: string): string { + return this.__localization.get(text); + } + + async init() { + //TODO + this.__localization = new Localization({ } as any); + } + +} diff --git a/tsup.config.js b/tsup.config.js index 812c2a60..73a6edf4 100644 --- a/tsup.config.js +++ b/tsup.config.js @@ -1,7 +1,7 @@ import { defineConfig } from 'tsup'; const shared = { - entry: ['src/index.ts'], - external: ['discord.js', 'iti'], + entry: ['src/index.ts', 'src/core/structures/optional/localizer.ts'], + external: ['discord.js', 'iti', 'shrimple-locales'], platform: 'node', clean: true, sourcemap: true, diff --git a/yarn.lock b/yarn.lock index 4085630c..bcc54eb8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -634,11 +634,14 @@ __metadata: iti: ^0.6.0 prettier: 2.8.8 rxjs: ^7.8.0 - shrimple-locales: ^0.1.1 + shrimple-locales: ^0.1.2 ts-results-es: ^4.0.0 tsup: ^6.7.0 typescript: 5.0.2 vitest: latest + dependenciesMeta: + shrimple-locales: + optional: true languageName: unknown linkType: soft @@ -3115,10 +3118,10 @@ __metadata: languageName: node linkType: hard -"shrimple-locales@npm:^0.1.1": - version: 0.1.1 - resolution: "shrimple-locales@npm:0.1.1" - checksum: 78db184b1f3a1a6f00b6f6a1de1a283668ac8f2497673a1a1592ac245983923ea0089c4590a2dd2cd256a2977873c284278ec14067173e51e758d632bd025b78 +"shrimple-locales@npm:^0.1.2": + version: 0.1.2 + resolution: "shrimple-locales@npm:0.1.2" + checksum: 3e30c4a6aff792e5ef51495f37e45704526a3b42d58fb21d5219fd7ae81007e7ca9b651d0551d2e89ab00c28457284d8f1fad2f2295095a22cd6b272172d55d1 languageName: node linkType: hard From 14e231af7d9e001ac70a10bf84af7571898fa6d9 Mon Sep 17 00:00:00 2001 From: Jacob Nguyen <76754747+jacoobes@users.noreply.github.com> Date: Tue, 9 Jan 2024 15:46:09 -0600 Subject: [PATCH 05/24] got optional localizer working --- package.json | 4 +-- src/core/ioc/base.ts | 42 +++++++++++++++++++---- src/core/ioc/dependency-injection.ts | 32 ++--------------- src/core/structures/optional/localizer.ts | 20 ----------- src/optional/localizer.ts | 35 +++++++++++++++++++ tsup.config.js | 2 +- yarn.lock | 8 ++--- 7 files changed, 79 insertions(+), 64 deletions(-) delete mode 100644 src/core/structures/optional/localizer.ts create mode 100644 src/optional/localizer.ts diff --git a/package.json b/package.json index 78b707b6..9dd90f30 100644 --- a/package.json +++ b/package.json @@ -48,9 +48,9 @@ "@typescript-eslint/eslint-plugin": "5.58.0", "@typescript-eslint/parser": "5.59.1", "discord.js": "^14.11.0", - "esbuild": "^0.17.0", "eslint": "8.39.0", "prettier": "2.8.8", + "shrimple-locales": "^0.1.2", "tsup": "^6.7.0", "typescript": "5.0.2", "vitest": "latest" @@ -96,7 +96,7 @@ "url": "git+https://github.com/sern-handler/handler.git" }, "homepage": "https://sern.dev", - "optionalDependencies": { + "peerDependencies": { "shrimple-locales": "^0.1.2" } } diff --git a/src/core/ioc/base.ts b/src/core/ioc/base.ts index 06c35e68..fdd0c6c6 100644 --- a/src/core/ioc/base.ts +++ b/src/core/ioc/base.ts @@ -1,12 +1,14 @@ import * as assert from 'assert'; -import { composeRoot, useContainer } from './dependency-injection'; -import type { DependencyConfiguration } from '../../types/ioc'; +import { useContainer } from './dependency-injection'; +import type { CoreDependencies, DependencyConfiguration } from '../../types/ioc'; import { CoreContainer } from './container'; import { Result } from 'ts-results-es'; import { DefaultServices } from '../_internal'; import { AnyFunction } from '../../types/utility'; import type { Logging } from '../contracts/logging'; import { requir } from '../module-loading'; +import { fileURLToPath } from 'node:url'; +import path from 'path'; //SIDE EFFECT: GLOBAL DI let containerSubject: CoreContainer>; @@ -93,13 +95,41 @@ export const insertLogger = (containerSubject: CoreContainer) => { .upsert({'@sern/logger': () => new DefaultServices.DefaultLogging}); } -export const insertLocalizer = async (containerSubject: CoreContainer) => { - const { ShrimpleLocalizer } = requir('../structures/services/localizer'); +const insertLocalizer = async (containerSubject: CoreContainer) => { + const packageDirectory = fileURLToPath(import.meta.url); + const pathToLocalizer= path.resolve(packageDirectory, "../", "optional", "localizer"); + const { ShrimpleLocalizer } = requir(pathToLocalizer); containerSubject - .add({'@sern/localizer': new ShrimpleLocalizer() }); + .upsert({'@sern/localizer': new ShrimpleLocalizer() }); } +/** + * Given the user's conf, check for any excluded/included dependency keys. + * Then, call conf.build to get the rest of the users' dependencies. + * Finally, update the containerSubject with the new container state + * @param conf + */ +function composeRoot( + container: CoreContainer>, + conf: DependencyConfiguration, +) { + //container should have no client or logger yet. + const hasLogger = conf.exclude?.has('@sern/logger'); + if (!hasLogger) { + insertLogger(container); + } + if(conf.include?.includes('@sern/localizer')) { + insertLocalizer(container); + } + //Build the container based on the callback provided by the user + conf.build(container as CoreContainer>); + + if (!hasLogger) { + container.get('@sern/logger')?.info({ message: 'All dependencies loaded successfully.' }); + } + container.ready(); +} export async function makeDependencies (conf: ValidDependencyConfig) { @@ -118,7 +148,7 @@ export async function makeDependencies } if(included.includes('@sern/localizer')) { - await insertLocalizer(containerSubject); + insertLocalizer(containerSubject); } containerSubject.ready(); diff --git a/src/core/ioc/dependency-injection.ts b/src/core/ioc/dependency-injection.ts index 617d8023..bd08466a 100644 --- a/src/core/ioc/dependency-injection.ts +++ b/src/core/ioc/dependency-injection.ts @@ -1,7 +1,5 @@ -import type { CoreDependencies, DependencyConfiguration, IntoDependencies } from '../../types/ioc'; -import { requir } from '../module-loading'; -import { insertLogger, useContainerRaw } from './base'; -import { CoreContainer } from './container'; +import type { IntoDependencies } from '../../types/ioc'; +import { useContainerRaw } from './base'; /** * @__PURE__ @@ -47,33 +45,7 @@ export function Services(...keys: [...T] return keys.map(k => container.get(k)!) as IntoDependencies; } -/** - * Given the user's conf, check for any excluded/included dependency keys. - * Then, call conf.build to get the rest of the users' dependencies. - * Finally, update the containerSubject with the new container state - * @param conf - */ -export function composeRoot( - container: CoreContainer>, - conf: DependencyConfiguration, -) { - //container should have no client or logger yet. - const hasLogger = conf.exclude?.has('@sern/logger'); - if (!hasLogger) { - insertLogger(container); - } - if(conf.include?.includes('@sern/localizer')) { - container.add({ '@sern/localizer': requir('shrimple-locales') }); - } - //Build the container based on the callback provided by the user - conf.build(container as CoreContainer>); - - if (!hasLogger) { - container.get('@sern/logger')?.info({ message: 'All dependencies loaded successfully.' }); - } - container.ready(); -} export function useContainer() { return (...keys: [...V]) => diff --git a/src/core/structures/optional/localizer.ts b/src/core/structures/optional/localizer.ts deleted file mode 100644 index c248111c..00000000 --- a/src/core/structures/optional/localizer.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { Localizer, Init } from '../../contracts' -import { Localization } from 'shrimple-locales' -/** - * @internal - * @since 2.0.0 - * Version 4.0.0 will internalize this api. Please refrain from using ModuleStore! - */ -export class ShrimpleLocalizer implements Localizer, Init { - - __localization!: Localization; - translate(text: string): string { - return this.__localization.get(text); - } - - async init() { - //TODO - this.__localization = new Localization({ } as any); - } - -} diff --git a/src/optional/localizer.ts b/src/optional/localizer.ts new file mode 100644 index 00000000..4d85b7e3 --- /dev/null +++ b/src/optional/localizer.ts @@ -0,0 +1,35 @@ +import type { Localizer, Init } from '../core/contracts' +import { Localization } from 'shrimple-locales' +import fs from 'node:fs/promises' +import { join, resolve } from 'node:path'; +import { filename } from '../core/module-loading' +/** + * @internal + * @since 2.0.0 + * Version 4.0.0 will internalize this api. Please refrain from using ModuleStore! + */ +export class ShrimpleLocalizer implements Localizer, Init { + private __localization!: Localization; + constructor(){} + translate(text: string): string { + return this.__localization.get(text); + } + + async init() { + this.__localization = new Localization({ + defaultLocale: "en", + fallbackLocale: "en", + locales: await this.readLocalizationDirectory() + }); + } + + private async readLocalizationDirectory() { + const translationFiles = []; + const localPath = resolve('locals'); + for(const json of await fs.readdir(localPath)) { + translationFiles.push({ [filename(json)]: + JSON.parse(await fs.readFile(join(localPath, json), 'utf8')) }) + } + return translationFiles.reduce((acc, cur ) => ({ ...cur, ...acc }), {}); + } +} diff --git a/tsup.config.js b/tsup.config.js index 73a6edf4..0217257d 100644 --- a/tsup.config.js +++ b/tsup.config.js @@ -1,6 +1,6 @@ import { defineConfig } from 'tsup'; const shared = { - entry: ['src/index.ts', 'src/core/structures/optional/localizer.ts'], + entry: ['src/index.ts', 'src/optional/localizer.ts'], external: ['discord.js', 'iti', 'shrimple-locales'], platform: 'node', clean: true, diff --git a/yarn.lock b/yarn.lock index bcc54eb8..97585378 100644 --- a/yarn.lock +++ b/yarn.lock @@ -629,7 +629,6 @@ __metadata: "@typescript-eslint/parser": 5.59.1 callsites: ^3.1.0 discord.js: ^14.11.0 - esbuild: ^0.17.0 eslint: 8.39.0 iti: ^0.6.0 prettier: 2.8.8 @@ -639,9 +638,8 @@ __metadata: tsup: ^6.7.0 typescript: 5.0.2 vitest: latest - dependenciesMeta: - shrimple-locales: - optional: true + peerDependencies: + shrimple-locales: ^0.1.2 languageName: unknown linkType: soft @@ -1453,7 +1451,7 @@ __metadata: languageName: node linkType: hard -"esbuild@npm:^0.17.0, esbuild@npm:^0.17.6": +"esbuild@npm:^0.17.6": version: 0.17.19 resolution: "esbuild@npm:0.17.19" dependencies: From e83a011ebd01dea2ec2cf71b1406594c569123de Mon Sep 17 00:00:00 2001 From: Jacob Nguyen <76754747+jacoobes@users.noreply.github.com> Date: Wed, 24 Jan 2024 10:20:05 -0600 Subject: [PATCH 06/24] proposing api notation? --- TEST PLEASE DELETE.js | 20 -------------------- src/core/contracts/localizer.ts | 2 +- src/core/ioc/dependency-injection.ts | 11 ++++++++++- src/core/ioc/index.ts | 2 +- src/core/module-loading.ts | 1 + src/optional/localizer.ts | 7 ++++++- src/sern.ts | 2 +- src/types/core-modules.ts | 1 - src/types/ioc.ts | 4 ++-- 9 files changed, 22 insertions(+), 28 deletions(-) delete mode 100644 TEST PLEASE DELETE.js diff --git a/TEST PLEASE DELETE.js b/TEST PLEASE DELETE.js deleted file mode 100644 index 7fe3534f..00000000 --- a/TEST PLEASE DELETE.js +++ /dev/null @@ -1,20 +0,0 @@ -const { Localization } = require('shrimple-locales'); - -//ok so plan is, -/** - * - * await makeDependencies(({ include })=> { - * include('@sern/localizer') // preconfigure localizer, will expose the translate function - * }); - * - */ -const loc = new Localization({ - defaultLocale: 'en', - fallbackLocale: 'en', - locales: { - en: { somethingInside: { hey: 'hi' }, somethingOutside: 'hello' }, - es: { somethingInside: { hey: 'hola inside' }, somethingOutside: 'hola' } - } -}); - -console.log(loc.get('somethingOutside')); \ No newline at end of file diff --git a/src/core/contracts/localizer.ts b/src/core/contracts/localizer.ts index c7e76b27..364a0689 100644 --- a/src/core/contracts/localizer.ts +++ b/src/core/contracts/localizer.ts @@ -1,4 +1,4 @@ export interface Localizer { - translate(text: string) : string; + translate(text: string, local: string) : string; } diff --git a/src/core/ioc/dependency-injection.ts b/src/core/ioc/dependency-injection.ts index bd08466a..3fb996d1 100644 --- a/src/core/ioc/dependency-injection.ts +++ b/src/core/ioc/dependency-injection.ts @@ -1,3 +1,4 @@ +import assert from 'node:assert'; import type { IntoDependencies } from '../../types/ioc'; import { useContainerRaw } from './base'; @@ -33,7 +34,9 @@ export function transient(cb: () => () => T) { * */ export function Service(key: T) { - return useContainerRaw().get(key)!; + const dep = useContainerRaw().get(key)!; + assert(dep, "Requested key " + key + " returned undefined"); + return dep; } /** * @since 3.0.0 @@ -51,3 +54,9 @@ export function useContainer() { return (...keys: [...V]) => keys.map(key => useContainerRaw().get(key as keyof Dependencies)) as IntoDependencies; } + + +export function $local(i: string, local: string) { + return Service('@sern/localizer').translate(i, local) +} + diff --git a/src/core/ioc/index.ts b/src/core/ioc/index.ts index e89f8b6f..77cf4bbc 100644 --- a/src/core/ioc/index.ts +++ b/src/core/ioc/index.ts @@ -1,2 +1,2 @@ export { makeDependencies } from './base'; -export { Service, Services, single, transient } from './dependency-injection'; +export { Service, Services, single, transient, $local } from './dependency-injection'; diff --git a/src/core/module-loading.ts b/src/core/module-loading.ts index 91a10111..81146880 100644 --- a/src/core/module-loading.ts +++ b/src/core/module-loading.ts @@ -18,6 +18,7 @@ export const shouldHandle = (path: string, fpath: string) => { export type ModuleResult = Promise>; + /** * Import any module based on the absolute path. * This can accept four types of exported modules diff --git a/src/optional/localizer.ts b/src/optional/localizer.ts index 4d85b7e3..569becb9 100644 --- a/src/optional/localizer.ts +++ b/src/optional/localizer.ts @@ -1,8 +1,11 @@ import type { Localizer, Init } from '../core/contracts' import { Localization } from 'shrimple-locales' import fs from 'node:fs/promises' +import { existsSync } from 'node:fs' import { join, resolve } from 'node:path'; import { filename } from '../core/module-loading' +import assert from 'node:assert'; + /** * @internal * @since 2.0.0 @@ -11,7 +14,8 @@ import { filename } from '../core/module-loading' export class ShrimpleLocalizer implements Localizer, Init { private __localization!: Localization; constructor(){} - translate(text: string): string { + translate(text: string, local: string): string { + this.__localization.changeLanguage(local); return this.__localization.get(text); } @@ -26,6 +30,7 @@ export class ShrimpleLocalizer implements Localizer, Init { private async readLocalizationDirectory() { const translationFiles = []; const localPath = resolve('locals'); + assert(existsSync(localPath), "You need to create a directory called \"locals\" for the localizer") for(const json of await fs.readdir(localPath)) { translationFiles.push({ [filename(json)]: JSON.parse(await fs.readFile(join(localPath, json), 'utf8')) }) diff --git a/src/sern.ts b/src/sern.ts index 495e331c..289d3dc2 100644 --- a/src/sern.ts +++ b/src/sern.ts @@ -1,6 +1,6 @@ import { handleCrash } from './handlers/_internal'; import callsites from 'callsites'; -import { err, ok, Files } from './core/_internal'; +import { Files } from './core/_internal'; import { merge } from 'rxjs'; import { Services } from './core/ioc'; import { Wrapper } from './types/core'; diff --git a/src/types/core-modules.ts b/src/types/core-modules.ts index e53320a4..d0f98349 100644 --- a/src/types/core-modules.ts +++ b/src/types/core-modules.ts @@ -20,7 +20,6 @@ import { AnyCommandPlugin, AnyEventPlugin, ControlPlugin, InitPlugin } from './c import { Awaitable, Args, SlashOptions, SernEventsMapping } from './utility'; - export interface CommandMeta { fullPath: string; id: string; diff --git a/src/types/ioc.ts b/src/types/ioc.ts index 9b821fd0..042d83db 100644 --- a/src/types/ioc.ts +++ b/src/types/ioc.ts @@ -26,11 +26,12 @@ export type DependencyList = [ export interface CoreDependencies { '@sern/client': () => Contracts.Emitter; - '@sern/logger'?: () => Contracts.Logging; '@sern/emitter': () => Contracts.Emitter; '@sern/store': () => Contracts.CoreModuleStore; '@sern/modules': () => Contracts.ModuleManager; '@sern/errors': () => Contracts.ErrorHandling; + '@sern/logger'?: () => Contracts.Logging; + '@sern/localizer'?: () => Contracts.Localizer } export type DependencyFromKey = Dependencies[T]; @@ -45,7 +46,6 @@ export interface DependencyConfiguration { //Extra modules that are preconfigured and ready to use! @sern/localizer is an example include?: string[] - build: ( root: Container, {}>, ) => Container; From 262fa6af5cc4b5cb1299a644d11c7ad519bec197 Mon Sep 17 00:00:00 2001 From: Jacob Nguyen <76754747+jacoobes@users.noreply.github.com> Date: Wed, 24 Jan 2024 23:10:08 -0600 Subject: [PATCH 07/24] prepare for localization map --- src/core/contracts/localizer.ts | 1 + src/optional/localizer.ts | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/core/contracts/localizer.ts b/src/core/contracts/localizer.ts index 364a0689..0081c6a1 100644 --- a/src/core/contracts/localizer.ts +++ b/src/core/contracts/localizer.ts @@ -1,4 +1,5 @@ export interface Localizer { translate(text: string, local: string) : string; + // translationsFor(path: string): Record } diff --git a/src/optional/localizer.ts b/src/optional/localizer.ts index 569becb9..b31e6a02 100644 --- a/src/optional/localizer.ts +++ b/src/optional/localizer.ts @@ -13,18 +13,22 @@ import assert from 'node:assert'; */ export class ShrimpleLocalizer implements Localizer, Init { private __localization!: Localization; + private __localization_map!: Record constructor(){} + translate(text: string, local: string): string { this.__localization.changeLanguage(local); return this.__localization.get(text); } async init() { + const map = await this.readLocalizationDirectory(); this.__localization = new Localization({ defaultLocale: "en", fallbackLocale: "en", - locales: await this.readLocalizationDirectory() + locales: map }); + this.__localization_map = map } private async readLocalizationDirectory() { From 622f8a77af25b2acabb861264b9c78210c268ca9 Mon Sep 17 00:00:00 2001 From: jacob Date: Sat, 27 Jan 2024 14:56:13 -0600 Subject: [PATCH 08/24] add localsFor --- package.json | 2 +- src/core/contracts/localizer.ts | 2 +- src/core/ioc/dependency-injection.ts | 6 ++++-- src/core/ioc/index.ts | 2 +- src/optional/localizer.ts | 12 ++++++------ yarn.lock | 10 +++++----- 6 files changed, 18 insertions(+), 16 deletions(-) diff --git a/package.json b/package.json index 9dd90f30..21efa61b 100644 --- a/package.json +++ b/package.json @@ -50,7 +50,7 @@ "discord.js": "^14.11.0", "eslint": "8.39.0", "prettier": "2.8.8", - "shrimple-locales": "^0.1.2", + "shrimple-locales": "^0.2.0", "tsup": "^6.7.0", "typescript": "5.0.2", "vitest": "latest" diff --git a/src/core/contracts/localizer.ts b/src/core/contracts/localizer.ts index 0081c6a1..8fb12754 100644 --- a/src/core/contracts/localizer.ts +++ b/src/core/contracts/localizer.ts @@ -1,5 +1,5 @@ export interface Localizer { translate(text: string, local: string) : string; - // translationsFor(path: string): Record + translationsFor(path: string): Record } diff --git a/src/core/ioc/dependency-injection.ts b/src/core/ioc/dependency-injection.ts index 3fb996d1..8781f94a 100644 --- a/src/core/ioc/dependency-injection.ts +++ b/src/core/ioc/dependency-injection.ts @@ -49,14 +49,16 @@ export function Services(...keys: [...T] } - export function useContainer() { return (...keys: [...V]) => keys.map(key => useContainerRaw().get(key as keyof Dependencies)) as IntoDependencies; } -export function $local(i: string, local: string) { +export const local = (i: string, local: string) => { return Service('@sern/localizer').translate(i, local) } +export const localsFor = (path: string) => { + return Service('@sern/localizer').translationsFor(path) +} diff --git a/src/core/ioc/index.ts b/src/core/ioc/index.ts index 77cf4bbc..a4480d33 100644 --- a/src/core/ioc/index.ts +++ b/src/core/ioc/index.ts @@ -1,2 +1,2 @@ export { makeDependencies } from './base'; -export { Service, Services, single, transient, $local } from './dependency-injection'; +export { Service, Services, single, transient, local, localsFor } from './dependency-injection'; diff --git a/src/optional/localizer.ts b/src/optional/localizer.ts index b31e6a02..9118bf92 100644 --- a/src/optional/localizer.ts +++ b/src/optional/localizer.ts @@ -7,15 +7,16 @@ import { filename } from '../core/module-loading' import assert from 'node:assert'; /** - * @internal - * @since 2.0.0 - * Version 4.0.0 will internalize this api. Please refrain from using ModuleStore! + * @since 3.4.0 */ export class ShrimpleLocalizer implements Localizer, Init { private __localization!: Localization; - private __localization_map!: Record constructor(){} + translationsFor(path: string): Record { + return this.__localization.localizationFor(path); + } + translate(text: string, local: string): string { this.__localization.changeLanguage(local); return this.__localization.get(text); @@ -28,13 +29,12 @@ export class ShrimpleLocalizer implements Localizer, Init { fallbackLocale: "en", locales: map }); - this.__localization_map = map } private async readLocalizationDirectory() { const translationFiles = []; const localPath = resolve('locals'); - assert(existsSync(localPath), "You need to create a directory called \"locals\" for the localizer") + assert(existsSync(localPath), "No directory \"locals\" found for the localizer") for(const json of await fs.readdir(localPath)) { translationFiles.push({ [filename(json)]: JSON.parse(await fs.readFile(join(localPath, json), 'utf8')) }) diff --git a/yarn.lock b/yarn.lock index 97585378..691efb7c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -633,7 +633,7 @@ __metadata: iti: ^0.6.0 prettier: 2.8.8 rxjs: ^7.8.0 - shrimple-locales: ^0.1.2 + shrimple-locales: ^0.2.0 ts-results-es: ^4.0.0 tsup: ^6.7.0 typescript: 5.0.2 @@ -3116,10 +3116,10 @@ __metadata: languageName: node linkType: hard -"shrimple-locales@npm:^0.1.2": - version: 0.1.2 - resolution: "shrimple-locales@npm:0.1.2" - checksum: 3e30c4a6aff792e5ef51495f37e45704526a3b42d58fb21d5219fd7ae81007e7ca9b651d0551d2e89ab00c28457284d8f1fad2f2295095a22cd6b272172d55d1 +"shrimple-locales@npm:^0.2.0": + version: 0.2.0 + resolution: "shrimple-locales@npm:0.2.0" + checksum: 9b5360e6ca5b2e75fdbaaeee0286015294b64773950924088f6088184f010837a89e84101eddfedcda5dd660a97df84fee6e1e95345e01f7e1edfff6b4ff2341 languageName: node linkType: hard From 8c3f502ac1d8b24df23c3eed76b1f4253ea9fefa Mon Sep 17 00:00:00 2001 From: jacob Date: Sun, 28 Jan 2024 01:03:20 -0600 Subject: [PATCH 09/24] merge some internals --- src/core/_internal.ts | 1 - src/core/functions.ts | 36 ++++++++++++++++++++++++++++++++++++ src/core/predicates.ts | 34 ---------------------------------- 3 files changed, 36 insertions(+), 35 deletions(-) delete mode 100644 src/core/predicates.ts diff --git a/src/core/_internal.ts b/src/core/_internal.ts index 026d036f..b1683e06 100644 --- a/src/core/_internal.ts +++ b/src/core/_internal.ts @@ -1,6 +1,5 @@ export * as Id from './id'; export * from './operators'; -export * from './predicates'; export * as Files from './module-loading'; export * from './functions'; export type { VoidResult } from '../types/core-plugin'; diff --git a/src/core/functions.ts b/src/core/functions.ts index f45bf8a8..2783d155 100644 --- a/src/core/functions.ts +++ b/src/core/functions.ts @@ -2,6 +2,17 @@ import { Err, Ok } from 'ts-results-es'; import { ApplicationCommandOptionType, AutocompleteInteraction } from 'discord.js'; import type { SernAutocompleteData, SernOptionsData } from '../types/core-modules'; import type { AnyCommandPlugin, AnyEventPlugin, Plugin } from '../types/core-plugin'; +import type { + AnySelectMenuInteraction, + ButtonInteraction, + ChatInputCommandInteraction, + MessageContextMenuCommandInteraction, + ModalSubmitInteraction, + UserContextMenuCommandInteraction, +} from 'discord.js'; +import { InteractionType } from 'discord.js'; + + import { PluginType } from './structures'; import assert from 'assert'; @@ -81,3 +92,28 @@ export function treeSearch( } } } + + +interface InteractionTypable { + type: InteractionType; +} +//discord.js pls fix ur typings or i will >:( +type AnyMessageComponentInteraction = AnySelectMenuInteraction | ButtonInteraction; +type AnyCommandInteraction = + | ChatInputCommandInteraction + | MessageContextMenuCommandInteraction + | UserContextMenuCommandInteraction; + +export function isMessageComponent(i: InteractionTypable): i is AnyMessageComponentInteraction { + return i.type === InteractionType.MessageComponent; +} +export function isCommand(i: InteractionTypable): i is AnyCommandInteraction { + return i.type === InteractionType.ApplicationCommand; +} +export function isAutocomplete(i: InteractionTypable): i is AutocompleteInteraction { + return i.type === InteractionType.ApplicationCommandAutocomplete; +} + +export function isModal(i: InteractionTypable): i is ModalSubmitInteraction { + return i.type === InteractionType.ModalSubmit; +} diff --git a/src/core/predicates.ts b/src/core/predicates.ts deleted file mode 100644 index a325e7a3..00000000 --- a/src/core/predicates.ts +++ /dev/null @@ -1,34 +0,0 @@ -import type { - AnySelectMenuInteraction, - AutocompleteInteraction, - ButtonInteraction, - ChatInputCommandInteraction, - MessageContextMenuCommandInteraction, - ModalSubmitInteraction, - UserContextMenuCommandInteraction, -} from 'discord.js'; -import { InteractionType } from 'discord.js'; - -interface InteractionTypable { - type: InteractionType; -} -//discord.js pls fix ur typings or i will >:( -type AnyMessageComponentInteraction = AnySelectMenuInteraction | ButtonInteraction; -type AnyCommandInteraction = - | ChatInputCommandInteraction - | MessageContextMenuCommandInteraction - | UserContextMenuCommandInteraction; - -export function isMessageComponent(i: InteractionTypable): i is AnyMessageComponentInteraction { - return i.type === InteractionType.MessageComponent; -} -export function isCommand(i: InteractionTypable): i is AnyCommandInteraction { - return i.type === InteractionType.ApplicationCommand; -} -export function isAutocomplete(i: InteractionTypable): i is AutocompleteInteraction { - return i.type === InteractionType.ApplicationCommandAutocomplete; -} - -export function isModal(i: InteractionTypable): i is ModalSubmitInteraction { - return i.type === InteractionType.ModalSubmit; -} From f020e783b3c6caff61e0953ad67f37ada3568729 Mon Sep 17 00:00:00 2001 From: jacob Date: Sun, 28 Jan 2024 15:16:49 -0600 Subject: [PATCH 10/24] boss call --- package.json | 2 +- src/core/_internal.ts | 1 + src/core/functions.ts | 16 +++-- src/core/ioc/base.ts | 20 +------ src/core/ioc/container.ts | 5 +- src/core/ioc/dependency-injection.ts | 26 +++++++- src/core/ioc/index.ts | 2 +- src/core/structures/index.ts | 2 +- src/core/structures/sern-emitter.ts | 89 ---------------------------- src/handlers/event-utils.ts | 15 ++--- src/handlers/interaction-event.ts | 7 ++- src/handlers/message-event.ts | 9 +-- src/sern.ts | 1 - src/types/ioc.ts | 3 - src/types/utility.ts | 1 - 15 files changed, 60 insertions(+), 139 deletions(-) delete mode 100644 src/core/structures/sern-emitter.ts diff --git a/package.json b/package.json index 21efa61b..6971bdfd 100644 --- a/package.json +++ b/package.json @@ -97,6 +97,6 @@ }, "homepage": "https://sern.dev", "peerDependencies": { - "shrimple-locales": "^0.1.2" + "shrimple-locales": "^0.2.0" } } diff --git a/src/core/_internal.ts b/src/core/_internal.ts index b1683e06..513abaa2 100644 --- a/src/core/_internal.ts +++ b/src/core/_internal.ts @@ -7,3 +7,4 @@ export { SernError } from './structures/enums'; export { ModuleStore } from './structures/module-store'; export * as DefaultServices from './structures/services'; export { useContainerRaw } from './ioc/base' + diff --git a/src/core/functions.ts b/src/core/functions.ts index 2783d155..60d62e9b 100644 --- a/src/core/functions.ts +++ b/src/core/functions.ts @@ -1,6 +1,5 @@ import { Err, Ok } from 'ts-results-es'; -import { ApplicationCommandOptionType, AutocompleteInteraction } from 'discord.js'; -import type { SernAutocompleteData, SernOptionsData } from '../types/core-modules'; +import type { Module, SernAutocompleteData, SernOptionsData } from '../types/core-modules'; import type { AnyCommandPlugin, AnyEventPlugin, Plugin } from '../types/core-plugin'; import type { AnySelectMenuInteraction, @@ -9,12 +8,12 @@ import type { MessageContextMenuCommandInteraction, ModalSubmitInteraction, UserContextMenuCommandInteraction, + AutocompleteInteraction } from 'discord.js'; -import { InteractionType } from 'discord.js'; - - -import { PluginType } from './structures'; +import { ApplicationCommandOptionType, InteractionType } from 'discord.js' +import { PayloadType, PluginType } from './structures'; import assert from 'assert'; +import { Payload } from '../types/utility'; //function wrappers for empty ok / err export const ok = /* @__PURE__*/ () => Ok.EMPTY; @@ -117,3 +116,8 @@ export function isAutocomplete(i: InteractionTypable): i is AutocompleteInteract export function isModal(i: InteractionTypable): i is ModalSubmitInteraction { return i.type === InteractionType.ModalSubmit; } + +export function resultPayload +(type: T, module?: Module, reason?: unknown) { + return { type, module, reason } as Payload & { type : T }; +} diff --git a/src/core/ioc/base.ts b/src/core/ioc/base.ts index fdd0c6c6..08db7505 100644 --- a/src/core/ioc/base.ts +++ b/src/core/ioc/base.ts @@ -6,9 +6,6 @@ import { Result } from 'ts-results-es'; import { DefaultServices } from '../_internal'; import { AnyFunction } from '../../types/utility'; import type { Logging } from '../contracts/logging'; -import { requir } from '../module-loading'; -import { fileURLToPath } from 'node:url'; -import path from 'path'; //SIDE EFFECT: GLOBAL DI let containerSubject: CoreContainer>; @@ -95,13 +92,6 @@ export const insertLogger = (containerSubject: CoreContainer) => { .upsert({'@sern/logger': () => new DefaultServices.DefaultLogging}); } -const insertLocalizer = async (containerSubject: CoreContainer) => { - const packageDirectory = fileURLToPath(import.meta.url); - const pathToLocalizer= path.resolve(packageDirectory, "../", "optional", "localizer"); - const { ShrimpleLocalizer } = requir(pathToLocalizer); - containerSubject - .upsert({'@sern/localizer': new ShrimpleLocalizer() }); -} /** * Given the user's conf, check for any excluded/included dependency keys. @@ -118,9 +108,9 @@ function composeRoot( if (!hasLogger) { insertLogger(container); } - if(conf.include?.includes('@sern/localizer')) { - insertLocalizer(container); - } +// if(conf.include?.includes('@sern/localizer')) { +// insertLocalizer(container); +// } //Build the container based on the callback provided by the user conf.build(container as CoreContainer>); @@ -147,10 +137,6 @@ export async function makeDependencies insertLogger(containerSubject); } - if(included.includes('@sern/localizer')) { - insertLocalizer(containerSubject); - } - containerSubject.ready(); } else { composeRoot(containerSubject, conf); diff --git a/src/core/ioc/container.ts b/src/core/ioc/container.ts index 9f6b024c..5cacc44b 100644 --- a/src/core/ioc/container.ts +++ b/src/core/ioc/container.ts @@ -1,9 +1,10 @@ import { Container } from 'iti'; -import { Disposable, SernEmitter } from '../'; +import { Disposable } from '../'; import * as assert from 'node:assert'; import { Subject } from 'rxjs'; import { DefaultServices, ModuleStore } from '../_internal'; import * as Hooks from './hooks'; +import { EventEmitter } from 'node:events'; /** @@ -23,7 +24,7 @@ export class CoreContainer> extends Container) .add({ '@sern/errors': () => new DefaultServices.DefaultErrorHandling, - '@sern/emitter': () => new SernEmitter, + '@sern/emitter': () => new EventEmitter({ captureRejections: true }), '@sern/store': () => new ModuleStore }) .add(ctx => { return { '@sern/modules': () => diff --git a/src/core/ioc/dependency-injection.ts b/src/core/ioc/dependency-injection.ts index 8781f94a..a84d3100 100644 --- a/src/core/ioc/dependency-injection.ts +++ b/src/core/ioc/dependency-injection.ts @@ -1,6 +1,10 @@ import assert from 'node:assert'; import type { IntoDependencies } from '../../types/ioc'; import { useContainerRaw } from './base'; +import { fileURLToPath } from 'node:url'; +import path from 'node:path'; +import { requir } from '../module-loading'; +import type { Localizer } from '../contracts'; /** * @__PURE__ @@ -54,11 +58,31 @@ export function useContainer() { keys.map(key => useContainerRaw().get(key as keyof Dependencies)) as IntoDependencies; } - +/** + * Translates a string to its respective local + * @example + * ```ts + * assert.deepEqual(locals("salute.hello", "es"), "hola") + * ``` + */ export const local = (i: string, local: string) => { return Service('@sern/localizer').translate(i, local) } +/** + * Returns a record of locales to their respective translations. + * @example + * ```ts + * assert.deepEqual(localsFor("salute.hello"), { "en-US": "hello", "es": "hola" }) + * ``` + */ export const localsFor = (path: string) => { return Service('@sern/localizer').translationsFor(path) } + +export const Localization = () => { + const packageDirectory = fileURLToPath(import.meta.url); + const pathToLocalizer= path.resolve(packageDirectory, "../", "optional", "localizer"); + const { ShrimpleLocalizer } = requir(pathToLocalizer); + return new ShrimpleLocalizer() as Localizer; +} diff --git a/src/core/ioc/index.ts b/src/core/ioc/index.ts index a4480d33..8961acb2 100644 --- a/src/core/ioc/index.ts +++ b/src/core/ioc/index.ts @@ -1,2 +1,2 @@ export { makeDependencies } from './base'; -export { Service, Services, single, transient, local, localsFor } from './dependency-injection'; +export { Service, Services, single, transient, local, localsFor, Localization } from './dependency-injection'; diff --git a/src/core/structures/index.ts b/src/core/structures/index.ts index e3c08dcb..8eeb6f92 100644 --- a/src/core/structures/index.ts +++ b/src/core/structures/index.ts @@ -1,5 +1,5 @@ export { CommandType, PluginType, PayloadType, EventType } from './enums'; export * from './context'; -export * from './sern-emitter'; export * from './services'; export * from './module-store'; + diff --git a/src/core/structures/sern-emitter.ts b/src/core/structures/sern-emitter.ts deleted file mode 100644 index 0b4f188d..00000000 --- a/src/core/structures/sern-emitter.ts +++ /dev/null @@ -1,89 +0,0 @@ -import { EventEmitter } from 'node:events'; -import { PayloadType } from '../../core/structures'; -import { Module } from '../../types/core-modules'; -import { SernEventsMapping, Payload } from '../../types/utility'; - -/** - * @since 1.0.0 - */ -export class SernEmitter extends EventEmitter { - constructor() { - super({ captureRejections: true }); - } - /** - * Listening to sern events with on. This event stays on until a crash or a normal exit - * @param eventName - * @param listener what to do with the data - */ - public override on( - eventName: T, - listener: (...args: SernEventsMapping[T][]) => void, - ): this { - return super.on(eventName, listener); - } - /** - * Listening to sern events with on. This event stays on until a crash or a normal exit - * @param eventName - * @param listener what to do with the data - */ - public override once( - eventName: T, - listener: (...args: SernEventsMapping[T][]) => void, - ): this { - return super.once(eventName, listener); - } - /** - * Listening to sern events with on. This event stays on until a crash or a normal exit - * @param eventName - * @param args the arguments for emitting the eventName - */ - public override emit( - eventName: T, - ...args: SernEventsMapping[T] - ): boolean { - return super.emit(eventName, ...args); - } - private static payload( - type: PayloadType, - module?: Module, - reason?: unknown, - ) { - return { type, module, reason } as T; - } - - /** - * Creates a compliant SernEmitter failure payload - * @param module - * @param reason - */ - static failure(module?: Module, reason?: unknown) { - //The generic cast Payload & { type : PayloadType.* } coerces the type to be a failure payload - // same goes to the other methods below - return SernEmitter.payload( - PayloadType.Failure, - module, - reason, - ); - } - /** - * Creates a compliant SernEmitter module success payload - * @param module - */ - static success(module: Module) { - return SernEmitter.payload( - PayloadType.Success, - module, - ); - } - /** - * Creates a compliant SernEmitter module warning payload - * @param reason - */ - static warning(reason: unknown) { - return SernEmitter.payload( - PayloadType.Warning, - undefined, - reason, - ); - } -} diff --git a/src/handlers/event-utils.ts b/src/handlers/event-utils.ts index 6182aee3..fd079384 100644 --- a/src/handlers/event-utils.ts +++ b/src/handlers/event-utils.ts @@ -21,11 +21,11 @@ import { handleError, SernError, VoidResult, + resultPayload, } from '../core/_internal'; -import { Emitter, ErrorHandling, Logging, ModuleManager } from '../core'; +import { Emitter, ErrorHandling, Logging, ModuleManager, PayloadType } from '../core'; import { contextArgs, createDispatcher } from './dispatchers'; import { ObservableInput, pipe } from 'rxjs'; -import { SernEmitter } from '../core'; import { Err, Ok, Result } from 'ts-results-es'; import type { Awaitable } from '../types/utility'; import type { ControlPlugin } from '../types/core-plugin'; @@ -168,10 +168,10 @@ export function executeModule( concatMap(() => Result.wrapAsync(async () => task())), concatMap(result => { if (result.isOk()) { - emitter.emit('module.activate', SernEmitter.success(module)); + emitter.emit('module.activate', resultPayload(PayloadType.Success, module)); return EMPTY; } - return throwError(() => SernEmitter.failure(module, result.error)); + return throwError(() => resultPayload(PayloadType.Failure, module, result.error)); }), ); @@ -218,13 +218,10 @@ export function callInitPlugins>(sernEmitter: Emi createResultResolver({ createStream: args => from(args.module.plugins).pipe(callPlugin(args)), onStop: (module: T) => { - sernEmitter.emit( - 'module.register', - SernEmitter.failure(module, SernError.PluginFailure), - ); + sernEmitter.emit('module.register', resultPayload(PayloadType.Failure, module, SernError.PluginFailure)); }, onNext: ({ module }) => { - sernEmitter.emit('module.register', SernEmitter.success(module)); + sernEmitter.emit('module.register', resultPayload(PayloadType.Success, module)); return { module }; }, }), diff --git a/src/handlers/interaction-event.ts b/src/handlers/interaction-event.ts index f9b90e14..06523417 100644 --- a/src/handlers/interaction-event.ts +++ b/src/handlers/interaction-event.ts @@ -1,6 +1,6 @@ import { Interaction } from 'discord.js'; import { mergeMap, merge } from 'rxjs'; -import { SernEmitter } from '../core'; +import { PayloadType } from '../core'; import { isAutocomplete, isCommand, @@ -9,6 +9,7 @@ import { sharedEventStream, SernError, filterTap, + resultPayload, } from '../core/_internal'; import { createInteractionHandler, executeModule, makeModuleExecutor } from './_internal'; import type { DependencyList } from '../types/ioc'; @@ -25,8 +26,8 @@ export function interactionHandler([emitter, err, log, modules, client]: Depende ); return interactionHandler$ .pipe( - filterTap(e => emitter.emit('warning', SernEmitter.warning(e))), + filterTap(e => emitter.emit('warning', resultPayload(PayloadType.Warning, undefined, e))), makeModuleExecutor(module => - emitter.emit('module.activate', SernEmitter.failure(module, SernError.PluginFailure))), + emitter.emit('module.activate', resultPayload(PayloadType.Failure, module, SernError.PluginFailure))), mergeMap(payload => executeModule(emitter, log, err, payload))); } diff --git a/src/handlers/message-event.ts b/src/handlers/message-event.ts index d234ca70..bb84d48b 100644 --- a/src/handlers/message-event.ts +++ b/src/handlers/message-event.ts @@ -1,7 +1,7 @@ import { mergeMap, EMPTY } from 'rxjs'; import type { Message } from 'discord.js'; -import { SernEmitter } from '../core'; -import { sharedEventStream, SernError, filterTap } from '../core/_internal'; +import { PayloadType, SernEmitter } from '../core'; +import { sharedEventStream, SernError, filterTap, resultPayload } from '../core/_internal'; import { createMessageHandler, executeModule, makeModuleExecutor } from './_internal'; import type { DependencyList } from '../types/ioc'; @@ -38,9 +38,10 @@ export function messageHandler( const msgCommands$ = handle(isNonBot(defaultPrefix)); return msgCommands$.pipe( - filterTap((e) => emitter.emit('warning', SernEmitter.warning(e))), + filterTap((e) => emitter.emit('warning', resultPayload(PayloadType.Warning, undefined, e))), makeModuleExecutor(module => { - emitter.emit('module.activate', SernEmitter.failure(module, SernError.PluginFailure)); + const result = resultPayload(PayloadType.Failure, module, SernError.PluginFailure); + emitter.emit('module.activate', result); }), mergeMap(payload => executeModule(emitter, log, err, payload))); } diff --git a/src/sern.ts b/src/sern.ts index 289d3dc2..0d48c03d 100644 --- a/src/sern.ts +++ b/src/sern.ts @@ -23,7 +23,6 @@ import { Client } from 'discord.js'; * }) * ``` */ - export function init(maybeWrapper: Wrapper | 'file') { const startTime = performance.now(); const wrapper = Files.loadConfig(maybeWrapper); diff --git a/src/types/ioc.ts b/src/types/ioc.ts index 042d83db..9d2b1778 100644 --- a/src/types/ioc.ts +++ b/src/types/ioc.ts @@ -43,9 +43,6 @@ export type IntoDependencies = { export interface DependencyConfiguration { //@deprecated. Loggers will always be included in the future exclude?: Set<'@sern/logger'>; - - //Extra modules that are preconfigured and ready to use! @sern/localizer is an example - include?: string[] build: ( root: Container, {}>, ) => Container; diff --git a/src/types/utility.ts b/src/types/utility.ts index a2535875..65efc3d6 100644 --- a/src/types/utility.ts +++ b/src/types/utility.ts @@ -29,5 +29,4 @@ export type Payload = | { type: PayloadType.Warning; reason: string }; - export type ReplyOptions = string | Omit | MessageReplyOptions; From c32e79488f12100800dc02bf255e24a6b6603863 Mon Sep 17 00:00:00 2001 From: jacob Date: Sun, 28 Jan 2024 16:01:18 -0600 Subject: [PATCH 11/24] add test for init functionality --- test/core/ioc.test.ts | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/test/core/ioc.test.ts b/test/core/ioc.test.ts index 48f4d8ad..de8015c1 100644 --- a/test/core/ioc.test.ts +++ b/test/core/ioc.test.ts @@ -1,12 +1,13 @@ import { beforeEach, describe, expect, it, vi } from 'vitest'; import { CoreContainer } from '../../src/core/ioc/container'; import { EventEmitter } from 'events'; -import { DefaultLogging, Disposable, Init, Logging } from '../../src/core'; +import { DefaultLogging, Disposable, Emitter, Init, Logging } from '../../src/core'; import { CoreDependencies } from '../../src/types/ioc'; describe('ioc container', () => { let container: CoreContainer<{}> = new CoreContainer(); let dependency: Logging & Init & Disposable; + let dependency2: Emitter beforeEach(() => { dependency = { init: vi.fn(), @@ -16,6 +17,11 @@ describe('ioc container', () => { debug(): void {}, dispose: vi.fn() }; + dependency2 = { + addListener: vi.fn(), + removeListener: vi.fn(), + emit: vi.fn() + }; container = new CoreContainer(); }); const wait = (seconds: number) => new Promise((resolve) => setTimeout(resolve, seconds)); @@ -83,4 +89,13 @@ describe('ioc container', () => { container.ready(); expect(dependency.init).toHaveBeenCalledTimes(0); }); + + it('should init dependency depending on something else', () => { + container.add({ '@sern/client': dependency2 }); + container.upsert((cntr) => ({ + '@sern/logger': dependency + })); + container.ready(); + expect(dependency.init).toHaveBeenCalledTimes(1); + }) }); From fa0c4ce05900ccf8316e9bee949b37ff4f2c5142 Mon Sep 17 00:00:00 2001 From: Jacob Nguyen <76754747+jacoobes@users.noreply.github.com> Date: Wed, 31 Jan 2024 13:25:34 -0600 Subject: [PATCH 12/24] add documentation --- src/core/contracts/localizer.ts | 10 ++++++++-- src/core/ioc/dependency-injection.ts | 8 ++++++-- src/optional/localizer.ts | 6 ++++-- test/core/services.test.ts | 3 +++ yarn.lock | 2 +- 5 files changed, 22 insertions(+), 7 deletions(-) diff --git a/src/core/contracts/localizer.ts b/src/core/contracts/localizer.ts index 8fb12754..25663c32 100644 --- a/src/core/contracts/localizer.ts +++ b/src/core/contracts/localizer.ts @@ -1,5 +1,11 @@ - +/** + * @since 3.4.0 + * Represents a localizer which can translate text for you. + * The internal representation of localization may differ between Localizers, + * But we are insured that translate, translateFor, currentLocale are always available + */ export interface Localizer { translate(text: string, local: string) : string; - translationsFor(path: string): Record + translationsFor(path: string): Record + currentLocale: string } diff --git a/src/core/ioc/dependency-injection.ts b/src/core/ioc/dependency-injection.ts index a84d3100..531a6774 100644 --- a/src/core/ioc/dependency-injection.ts +++ b/src/core/ioc/dependency-injection.ts @@ -80,9 +80,13 @@ export const localsFor = (path: string) => { return Service('@sern/localizer').translationsFor(path) } -export const Localization = () => { +export const Localization = (defaultLocale?: string) => { const packageDirectory = fileURLToPath(import.meta.url); const pathToLocalizer= path.resolve(packageDirectory, "../", "optional", "localizer"); const { ShrimpleLocalizer } = requir(pathToLocalizer); - return new ShrimpleLocalizer() as Localizer; + const localizer = new ShrimpleLocalizer as Localizer; + if (defaultLocale) { + localizer.currentLocale = defaultLocale; + } + return localizer; } diff --git a/src/optional/localizer.ts b/src/optional/localizer.ts index 9118bf92..f2e7fda6 100644 --- a/src/optional/localizer.ts +++ b/src/optional/localizer.ts @@ -8,10 +8,12 @@ import assert from 'node:assert'; /** * @since 3.4.0 + * @internal */ export class ShrimpleLocalizer implements Localizer, Init { private __localization!: Localization; constructor(){} + currentLocale: string = "en-US"; translationsFor(path: string): Record { return this.__localization.localizationFor(path); @@ -25,8 +27,8 @@ export class ShrimpleLocalizer implements Localizer, Init { async init() { const map = await this.readLocalizationDirectory(); this.__localization = new Localization({ - defaultLocale: "en", - fallbackLocale: "en", + defaultLocale: this.currentLocale, + fallbackLocale: "en-US", locales: map }); } diff --git a/test/core/services.test.ts b/test/core/services.test.ts index fea60460..479adef1 100644 --- a/test/core/services.test.ts +++ b/test/core/services.test.ts @@ -74,4 +74,7 @@ describe('services', () => { expect(consoleMock).toHaveBeenCalledOnce(); expect(consoleMock).toHaveBeenLastCalledWith({ message: 'error' }); }); + + + }); diff --git a/yarn.lock b/yarn.lock index 691efb7c..16513d39 100644 --- a/yarn.lock +++ b/yarn.lock @@ -639,7 +639,7 @@ __metadata: typescript: 5.0.2 vitest: latest peerDependencies: - shrimple-locales: ^0.1.2 + shrimple-locales: ^0.2.0 languageName: unknown linkType: soft From ba06f970d33bf1ad5f257191fe72cfccde54de55 Mon Sep 17 00:00:00 2001 From: Jacob Nguyen <76754747+jacoobes@users.noreply.github.com> Date: Wed, 31 Jan 2024 14:27:14 -0600 Subject: [PATCH 13/24] inline and cleanup --- src/handlers/event-utils.ts | 2 +- src/handlers/message-event.ts | 2 +- src/handlers/ready-event.ts | 2 +- src/optional/localizer.ts | 2 +- src/sern.ts | 22 +++++++--------------- 5 files changed, 11 insertions(+), 19 deletions(-) diff --git a/src/handlers/event-utils.ts b/src/handlers/event-utils.ts index fd079384..f766bcb6 100644 --- a/src/handlers/event-utils.ts +++ b/src/handlers/event-utils.ts @@ -26,7 +26,7 @@ import { import { Emitter, ErrorHandling, Logging, ModuleManager, PayloadType } from '../core'; import { contextArgs, createDispatcher } from './dispatchers'; import { ObservableInput, pipe } from 'rxjs'; -import { Err, Ok, Result } from 'ts-results-es'; +import { Err, Ok, Result, Option } from 'ts-results-es'; import type { Awaitable } from '../types/utility'; import type { ControlPlugin } from '../types/core-plugin'; import type { AnyModule, CommandModule, Module, Processed } from '../types/core-modules'; diff --git a/src/handlers/message-event.ts b/src/handlers/message-event.ts index bb84d48b..86b14466 100644 --- a/src/handlers/message-event.ts +++ b/src/handlers/message-event.ts @@ -1,6 +1,6 @@ import { mergeMap, EMPTY } from 'rxjs'; import type { Message } from 'discord.js'; -import { PayloadType, SernEmitter } from '../core'; +import { PayloadType } from '../core'; import { sharedEventStream, SernError, filterTap, resultPayload } from '../core/_internal'; import { createMessageHandler, executeModule, makeModuleExecutor } from './_internal'; import type { DependencyList } from '../types/ioc'; diff --git a/src/handlers/ready-event.ts b/src/handlers/ready-event.ts index b4e811bd..80c6ad03 100644 --- a/src/handlers/ready-event.ts +++ b/src/handlers/ready-event.ts @@ -9,7 +9,7 @@ import * as util from 'node:util'; import type { DependencyList } from '../types/ioc'; import type { AnyModule, Processed } from '../types/core-modules'; -export function startReadyEvent( +export function readyHandler( [sEmitter, , , moduleManager, client]: DependencyList, allPaths: ObservableInput, ) { diff --git a/src/optional/localizer.ts b/src/optional/localizer.ts index f2e7fda6..c6c0654f 100644 --- a/src/optional/localizer.ts +++ b/src/optional/localizer.ts @@ -8,7 +8,7 @@ import assert from 'node:assert'; /** * @since 3.4.0 - * @internal + * @internal */ export class ShrimpleLocalizer implements Localizer, Init { private __localization!: Localization; diff --git a/src/sern.ts b/src/sern.ts index 0d48c03d..d294e7f3 100644 --- a/src/sern.ts +++ b/src/sern.ts @@ -5,7 +5,7 @@ import { merge } from 'rxjs'; import { Services } from './core/ioc'; import { Wrapper } from './types/core'; import { eventsHandler } from './handlers/user-defined-events'; -import { startReadyEvent } from './handlers/ready-event'; +import { readyHandler } from './handlers/ready-event'; import { messageHandler } from './handlers/message-event'; import { interactionHandler } from './handlers/interaction-event'; import { presenceHandler } from './handlers/presence'; @@ -26,7 +26,11 @@ import { Client } from 'discord.js'; export function init(maybeWrapper: Wrapper | 'file') { const startTime = performance.now(); const wrapper = Files.loadConfig(maybeWrapper); - const dependencies = useDependencies(); + const dependencies = Services('@sern/emitter', + '@sern/errors', + '@sern/logger', + '@sern/modules', + '@sern/client'); const logger = dependencies[2], errorHandler = dependencies[1]; @@ -37,7 +41,7 @@ export function init(maybeWrapper: Wrapper | 'file') { const initCallsite = callsites()[1].getFileName(); const presencePath = Files.shouldHandle(initCallsite!, "presence"); //Ready event: load all modules and when finished, time should be taken and logged - startReadyEvent(dependencies, Files.getFullPathTree(wrapper.commands)) + readyHandler(dependencies, Files.getFullPathTree(wrapper.commands)) .add(() => { const time = ((performance.now() - startTime) / 1000).toFixed(2); dependencies[0].emit('modulesLoaded'); @@ -55,15 +59,3 @@ export function init(maybeWrapper: Wrapper | 'file') { // listening to the message stream and interaction stream merge(messages$, interactions$).pipe(handleCrash(errorHandler, logger)).subscribe(); } - -function useDependencies() { - return Services( - '@sern/emitter', - '@sern/errors', - '@sern/logger', - '@sern/modules', - '@sern/client', - ); -} - - From 598241c7a3a9bf38681bc976228e1b90e6c5f2d2 Mon Sep 17 00:00:00 2001 From: Jacob Nguyen <76754747+jacoobes@users.noreply.github.com> Date: Wed, 31 Jan 2024 14:51:36 -0600 Subject: [PATCH 14/24] feat: logging for experimental json loading --- src/core/module-loading.ts | 11 ++++++----- src/sern.ts | 2 +- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/core/module-loading.ts b/src/core/module-loading.ts index 81146880..a5e89690 100644 --- a/src/core/module-loading.ts +++ b/src/core/module-loading.ts @@ -7,6 +7,7 @@ import { createRequire } from 'node:module'; import type { ImportPayload, Wrapper } from '../types/core'; import type { Module } from '../types/core-modules'; import { existsSync } from 'fs'; +import type { Logging } from './contracts/logging'; export const shouldHandle = (path: string, fpath: string) => { const file_name = fpath+extname(path); @@ -107,11 +108,11 @@ async function* readPaths(dir: string): AsyncGenerator { export const requir = createRequire(import.meta.url); -export function loadConfig(wrapper: Wrapper | 'file'): Wrapper { +export function loadConfig(wrapper: Wrapper | 'file', log: Logging | undefined): Wrapper { if (wrapper !== 'file') { return wrapper; } - console.log('Experimental loading of sern.config.json'); + log?.info({ message: 'Experimental loading of sern.config.json'}); const config = requir(resolve('sern.config.json')); const makePath = (dir: PropertyKey) => @@ -119,14 +120,14 @@ export function loadConfig(wrapper: Wrapper | 'file'): Wrapper { ? join('dist', config.paths[dir]!) : join(config.paths[dir]!); - console.log('Loading config: ', config); + log?.info({ message: 'Loading config: ' + JSON.stringify(config, null, 4) }); const commandsPath = makePath('commands'); - console.log('Commands path is set to', commandsPath); + log?.info({ message: `Commands path is set to ${commandsPath}` }); let eventsPath: string | undefined; if (config.paths.events) { eventsPath = makePath('events'); - console.log('Events path is set to', eventsPath); + log?.info({ message: `Events path is set to ${eventsPath} `}); } return { defaultPrefix: config.defaultPrefix, diff --git a/src/sern.ts b/src/sern.ts index d294e7f3..e633be01 100644 --- a/src/sern.ts +++ b/src/sern.ts @@ -25,7 +25,6 @@ import { Client } from 'discord.js'; */ export function init(maybeWrapper: Wrapper | 'file') { const startTime = performance.now(); - const wrapper = Files.loadConfig(maybeWrapper); const dependencies = Services('@sern/emitter', '@sern/errors', '@sern/logger', @@ -34,6 +33,7 @@ export function init(maybeWrapper: Wrapper | 'file') { const logger = dependencies[2], errorHandler = dependencies[1]; + const wrapper = Files.loadConfig(maybeWrapper, logger); if (wrapper.events !== undefined) { eventsHandler(dependencies, Files.getFullPathTree(wrapper.events)); } From 13e3fafa9b36e16cf0d68d085c3954177356fb05 Mon Sep 17 00:00:00 2001 From: Jacob Nguyen <76754747+jacoobes@users.noreply.github.com> Date: Sat, 3 Feb 2024 11:50:50 -0600 Subject: [PATCH 15/24] loosen typings --- src/core/ioc/base.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/ioc/base.ts b/src/core/ioc/base.ts index 08db7505..04836b63 100644 --- a/src/core/ioc/base.ts +++ b/src/core/ioc/base.ts @@ -33,7 +33,7 @@ export function disposeAll(logger: Logging|undefined) { const dependencyBuilder = (container: any, excluded: string[], included: string[]) => { type Insertable = | ((container: CoreContainer) => unknown ) - | Record + | object return { /** * Insert a dependency into your container. From d2054f25d7462f4d71087562731e579fe0b39629 Mon Sep 17 00:00:00 2001 From: jacob Date: Sun, 4 Feb 2024 15:34:00 -0600 Subject: [PATCH 16/24] dev workflow and cleaning up comments --- .github/workflows/npm-publish-dev.yml | 34 +++++++++++++++++++++++++++ src/handlers/dispatchers.ts | 5 +--- src/handlers/event-utils.ts | 2 +- src/handlers/presence.ts | 3 +-- 4 files changed, 37 insertions(+), 7 deletions(-) create mode 100644 .github/workflows/npm-publish-dev.yml diff --git a/.github/workflows/npm-publish-dev.yml b/.github/workflows/npm-publish-dev.yml new file mode 100644 index 00000000..27c1b03f --- /dev/null +++ b/.github/workflows/npm-publish-dev.yml @@ -0,0 +1,34 @@ +name: Continuous Delivery + +on: + push: + branches: + - main + paths: + - 'src/**' + - 'package.json' + +jobs: + Publish: + name: Publishing Dev + runs-on: ubuntu-latest + + steps: + - name: Check out Git repository + uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3 + + - name: Set up Node.js + uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3 + with: + node-version: 18 + registry-url: 'https://registry.npmjs.org' + + - name: Install Node.js dependencies + run: npm i && npm run build:dev + + - name: Publish to npm + run: | + npm version premajor --preid "dev.$(git rev-parse --verify --short HEAD)" --git-tag-version=false + npm publish --tag dev + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} diff --git a/src/handlers/dispatchers.ts b/src/handlers/dispatchers.ts index 5162e1ee..d52f7bee 100644 --- a/src/handlers/dispatchers.ts +++ b/src/handlers/dispatchers.ts @@ -85,10 +85,7 @@ export function createDispatcher(payload: { args: [payload.event], }; } - return { - module: payload.module, - args: contextArgs(payload.event), - }; + return { module: payload.module, args: contextArgs(payload.event) }; } default: return { module: payload.module, diff --git a/src/handlers/event-utils.ts b/src/handlers/event-utils.ts index f766bcb6..fd079384 100644 --- a/src/handlers/event-utils.ts +++ b/src/handlers/event-utils.ts @@ -26,7 +26,7 @@ import { import { Emitter, ErrorHandling, Logging, ModuleManager, PayloadType } from '../core'; import { contextArgs, createDispatcher } from './dispatchers'; import { ObservableInput, pipe } from 'rxjs'; -import { Err, Ok, Result, Option } from 'ts-results-es'; +import { Err, Ok, Result } from 'ts-results-es'; import type { Awaitable } from '../types/utility'; import type { ControlPlugin } from '../types/core-plugin'; import type { AnyModule, CommandModule, Module, Processed } from '../types/core-modules'; diff --git a/src/handlers/presence.ts b/src/handlers/presence.ts index 38afa6e0..761fbb12 100644 --- a/src/handlers/presence.ts +++ b/src/handlers/presence.ts @@ -19,7 +19,6 @@ const parseConfig = async (conf: Promise) => { .pipe(scan(onRepeat, s), startWith(s)); } - //take 1? return of(s).pipe(take(1)); }) }; @@ -37,7 +36,7 @@ export const presenceHandler = (path: string, setPresence: SetPresence) => { }) const module$ = from(presence); return module$.pipe( - //compose:. + //compose: //call the execute function, passing that result into parseConfig. //concatMap resolves the promise, and passes it to the next concatMap. concatMap(fn => parseConfig(fn())), From 99aa7bce78cd651c9506fccab23fdb22793d60ee Mon Sep 17 00:00:00 2001 From: jacob Date: Sun, 4 Feb 2024 15:52:53 -0600 Subject: [PATCH 17/24] cleaning up a bit more --- src/core/ioc/base.ts | 9 +++------ src/core/structures/context.ts | 2 +- src/types/ioc.ts | 4 +++- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/core/ioc/base.ts b/src/core/ioc/base.ts index 04836b63..d978ed93 100644 --- a/src/core/ioc/base.ts +++ b/src/core/ioc/base.ts @@ -30,7 +30,7 @@ export function disposeAll(logger: Logging|undefined) { .then(() => logger?.info({ message: 'Cleaning container and crashing' })); } -const dependencyBuilder = (container: any, excluded: string[], included: string[]) => { +const dependencyBuilder = (container: any, excluded: string[] ) => { type Insertable = | ((container: CoreContainer) => unknown ) | object @@ -51,9 +51,7 @@ const dependencyBuilder = (container: any, excluded: string[], included: string[ exclude(...keys: (keyof Dependencies)[]) { keys.forEach(key => excluded.push(key)); }, - include(...keys: string[]) { - included.push(...keys); - }, + /** * @param key the key of the dependency * @param v The dependency to swap out. @@ -126,8 +124,7 @@ export async function makeDependencies containerSubject = new CoreContainer(); if(typeof conf === 'function') { const excluded: string[] = []; - const included: string[] = []; - conf(dependencyBuilder(containerSubject, excluded, included)); + conf(dependencyBuilder(containerSubject, excluded)); const includeLogger = !excluded.includes('@sern/logger') diff --git a/src/core/structures/context.ts b/src/core/structures/context.ts index 6ceb7abc..fb37c05c 100644 --- a/src/core/structures/context.ts +++ b/src/core/structures/context.ts @@ -1,4 +1,4 @@ -import { +import type { BaseInteraction, ChatInputCommandInteraction, Client, diff --git a/src/types/ioc.ts b/src/types/ioc.ts index 9d2b1778..bcf4d53f 100644 --- a/src/types/ioc.ts +++ b/src/types/ioc.ts @@ -41,7 +41,9 @@ export type IntoDependencies = { } & { length: Tuple['length'] }; export interface DependencyConfiguration { - //@deprecated. Loggers will always be included in the future + /* + * @deprecated. Loggers will be opt-in the future + */ exclude?: Set<'@sern/logger'>; build: ( root: Container, {}>, From 6b3643caeb668ef7998bdd59cf0646c58e0a3d5c Mon Sep 17 00:00:00 2001 From: jacob Date: Sun, 4 Feb 2024 16:28:00 -0600 Subject: [PATCH 18/24] rename Localizer -> Localization --- src/core/contracts/index.ts | 2 +- .../contracts/{localizer.ts => localization.ts} | 4 ++-- src/core/ioc/base.ts | 3 --- src/core/ioc/container.ts | 1 + src/core/ioc/dependency-injection.ts | 16 ++++++++++++---- src/core/ioc/index.ts | 2 +- src/optional/localizer.ts | 10 +++++----- src/types/ioc.ts | 2 +- 8 files changed, 23 insertions(+), 17 deletions(-) rename src/core/contracts/{localizer.ts => localization.ts} (75%) diff --git a/src/core/contracts/index.ts b/src/core/contracts/index.ts index 5c336761..20910fbe 100644 --- a/src/core/contracts/index.ts +++ b/src/core/contracts/index.ts @@ -5,4 +5,4 @@ export * from './module-store'; export * from './init'; export * from './emitter'; export * from './disposable' -export * from './localizer' +export * from './localization' diff --git a/src/core/contracts/localizer.ts b/src/core/contracts/localization.ts similarity index 75% rename from src/core/contracts/localizer.ts rename to src/core/contracts/localization.ts index 25663c32..f1b40a82 100644 --- a/src/core/contracts/localizer.ts +++ b/src/core/contracts/localization.ts @@ -1,10 +1,10 @@ /** * @since 3.4.0 - * Represents a localizer which can translate text for you. + * Represents a localization service which can translate text for you. * The internal representation of localization may differ between Localizers, * But we are insured that translate, translateFor, currentLocale are always available */ -export interface Localizer { +export interface Localization { translate(text: string, local: string) : string; translationsFor(path: string): Record currentLocale: string diff --git a/src/core/ioc/base.ts b/src/core/ioc/base.ts index d978ed93..dbf363db 100644 --- a/src/core/ioc/base.ts +++ b/src/core/ioc/base.ts @@ -106,9 +106,6 @@ function composeRoot( if (!hasLogger) { insertLogger(container); } -// if(conf.include?.includes('@sern/localizer')) { -// insertLocalizer(container); -// } //Build the container based on the callback provided by the user conf.build(container as CoreContainer>); diff --git a/src/core/ioc/container.ts b/src/core/ioc/container.ts index 5cacc44b..d01b2fc0 100644 --- a/src/core/ioc/container.ts +++ b/src/core/ioc/container.ts @@ -48,6 +48,7 @@ export class CoreContainer> extends Container dep.dispose() } as never); } await super.disposeAll(); diff --git a/src/core/ioc/dependency-injection.ts b/src/core/ioc/dependency-injection.ts index 531a6774..7c7d67dd 100644 --- a/src/core/ioc/dependency-injection.ts +++ b/src/core/ioc/dependency-injection.ts @@ -4,7 +4,7 @@ import { useContainerRaw } from './base'; import { fileURLToPath } from 'node:url'; import path from 'node:path'; import { requir } from '../module-loading'; -import type { Localizer } from '../contracts'; +import type { Localization } from '../contracts'; /** * @__PURE__ @@ -79,12 +79,20 @@ export const local = (i: string, local: string) => { export const localsFor = (path: string) => { return Service('@sern/localizer').translationsFor(path) } - -export const Localization = (defaultLocale?: string) => { +/** + * A service which provides simple file based localization. Add this while making dependencies. + * @example + * ```ts + * await makeDependencies(({ add }) => { + * add('@sern/localizer', DefaultLocalization()); + * }); + * ``` + **/ +export const DefaultLocalization = (defaultLocale?: string) => { const packageDirectory = fileURLToPath(import.meta.url); const pathToLocalizer= path.resolve(packageDirectory, "../", "optional", "localizer"); const { ShrimpleLocalizer } = requir(pathToLocalizer); - const localizer = new ShrimpleLocalizer as Localizer; + const localizer = new ShrimpleLocalizer as Localization; if (defaultLocale) { localizer.currentLocale = defaultLocale; } diff --git a/src/core/ioc/index.ts b/src/core/ioc/index.ts index 8961acb2..90b296b9 100644 --- a/src/core/ioc/index.ts +++ b/src/core/ioc/index.ts @@ -1,2 +1,2 @@ export { makeDependencies } from './base'; -export { Service, Services, single, transient, local, localsFor, Localization } from './dependency-injection'; +export { Service, Services, single, transient, local, localsFor, DefaultLocalization } from './dependency-injection'; diff --git a/src/optional/localizer.ts b/src/optional/localizer.ts index c6c0654f..8d7bdf92 100644 --- a/src/optional/localizer.ts +++ b/src/optional/localizer.ts @@ -1,5 +1,5 @@ -import type { Localizer, Init } from '../core/contracts' -import { Localization } from 'shrimple-locales' +import type { Localization, Init } from '../core/contracts' +import { Localization as LocalsProvider } from 'shrimple-locales' import fs from 'node:fs/promises' import { existsSync } from 'node:fs' import { join, resolve } from 'node:path'; @@ -10,8 +10,8 @@ import assert from 'node:assert'; * @since 3.4.0 * @internal */ -export class ShrimpleLocalizer implements Localizer, Init { - private __localization!: Localization; +export class ShrimpleLocalizer implements Localization, Init { + private __localization!: LocalsProvider; constructor(){} currentLocale: string = "en-US"; @@ -26,7 +26,7 @@ export class ShrimpleLocalizer implements Localizer, Init { async init() { const map = await this.readLocalizationDirectory(); - this.__localization = new Localization({ + this.__localization = new LocalsProvider({ defaultLocale: this.currentLocale, fallbackLocale: "en-US", locales: map diff --git a/src/types/ioc.ts b/src/types/ioc.ts index bcf4d53f..4b05c319 100644 --- a/src/types/ioc.ts +++ b/src/types/ioc.ts @@ -31,7 +31,7 @@ export interface CoreDependencies { '@sern/modules': () => Contracts.ModuleManager; '@sern/errors': () => Contracts.ErrorHandling; '@sern/logger'?: () => Contracts.Logging; - '@sern/localizer'?: () => Contracts.Localizer + '@sern/localizer'?: () => Contracts.Localization } export type DependencyFromKey = Dependencies[T]; From a50fb97d29fa3c284b76dacfd8e14d701d1688f8 Mon Sep 17 00:00:00 2001 From: jacob Date: Sun, 4 Feb 2024 16:45:39 -0600 Subject: [PATCH 19/24] more documentation, change dir for default localizer --- src/core/ioc/dependency-injection.ts | 3 +++ src/optional/localizer.ts | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/core/ioc/dependency-injection.ts b/src/core/ioc/dependency-injection.ts index 7c7d67dd..b7068cb0 100644 --- a/src/core/ioc/dependency-injection.ts +++ b/src/core/ioc/dependency-injection.ts @@ -29,6 +29,7 @@ export function transient(cb: () => () => T) { * The new Service api, a cleaner alternative to useContainer * To obtain intellisense, ensure a .d.ts file exists in the root of compilation. * Usually our scaffolding tool takes care of this. + * Note: this method only works AFTER your container has been initiated * @since 3.0.0 * @example * ```ts @@ -60,6 +61,7 @@ export function useContainer() { /** * Translates a string to its respective local + * Note: this method only works AFTER your container has been initiated * @example * ```ts * assert.deepEqual(locals("salute.hello", "es"), "hola") @@ -71,6 +73,7 @@ export const local = (i: string, local: string) => { /** * Returns a record of locales to their respective translations. + * Note: this method only works AFTER your container has been initiated * @example * ```ts * assert.deepEqual(localsFor("salute.hello"), { "en-US": "hello", "es": "hola" }) diff --git a/src/optional/localizer.ts b/src/optional/localizer.ts index 8d7bdf92..e8a126ae 100644 --- a/src/optional/localizer.ts +++ b/src/optional/localizer.ts @@ -35,8 +35,8 @@ export class ShrimpleLocalizer implements Localization, Init { private async readLocalizationDirectory() { const translationFiles = []; - const localPath = resolve('locals'); - assert(existsSync(localPath), "No directory \"locals\" found for the localizer") + const localPath = resolve('resources', 'locals'); + assert(existsSync(localPath), "No directory \"resources/locals\" found for the localizer") for(const json of await fs.readdir(localPath)) { translationFiles.push({ [filename(json)]: JSON.parse(await fs.readFile(join(localPath, json), 'utf8')) }) From 3b4f9b9e81cdde1251945786d6e9a8b6efbf26aa Mon Sep 17 00:00:00 2001 From: Jacob Nguyen <76754747+jacoobes@users.noreply.github.com> Date: Sun, 4 Feb 2024 18:59:22 -0600 Subject: [PATCH 20/24] some tests --- test/core/id.test.ts | 64 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 test/core/id.test.ts diff --git a/test/core/id.test.ts b/test/core/id.test.ts new file mode 100644 index 00000000..9d130a01 --- /dev/null +++ b/test/core/id.test.ts @@ -0,0 +1,64 @@ +import { CommandType } from '../../src/core'; +import * as Id from '../../src/core/id' +import { expect, test } from 'vitest' + +test('id -> Text', () => { + const bothCmdId = Id.create("ping", CommandType.Text) + expect(bothCmdId).toBe("ping_T") +}) + +test('id -> Both', () => { + const bothCmdId = Id.create("ping", CommandType.Both) + expect(bothCmdId).toBe("ping_B") +}) + +test('id -> CtxMsg', () => { + const bothCmdId = Id.create("ping", CommandType.CtxMsg) + expect(bothCmdId).toBe("ping_A3") +}) +test('id -> CtxUsr', () => { + const bothCmdId = Id.create("ping", CommandType.CtxUser) + expect(bothCmdId).toBe("ping_A2") +}) +test('id -> Modal', () => { + const modal = Id.create("my-modal", CommandType.Modal) + expect(modal).toBe("my-modal_M"); +}) + +test('id -> Button', () => { + const modal = Id.create("my-button", CommandType.Button) + expect(modal).toBe("my-button_C2"); +}) + +test('id -> Slash', () => { + const modal = Id.create("myslash", CommandType.Slash) + expect(modal).toBe("myslash_A1"); +}) + +test('id -> StringSelect', () => { + const modal = Id.create("mystringselect", CommandType.StringSelect) + expect(modal).toBe("mystringselect_C3"); +}) + +test('id -> UserSelect', () => { + const modal = Id.create("myuserselect", CommandType.UserSelect) + expect(modal).toBe("myuserselect_C5"); +}) + +test('id -> RoleSelect', () => { + const modal = Id.create("myroleselect", CommandType.RoleSelect) + expect(modal).toBe("myroleselect_C6"); +}) + +test('id -> MentionSelect', () => { + const modal = Id.create("mymentionselect", CommandType.MentionableSelect) + expect(modal).toBe("mymentionselect_C7"); +}) + +test('id -> ChannelSelect', () => { + const modal = Id.create("mychannelselect", CommandType.ChannelSelect) + expect(modal).toBe("mychannelselect_C8"); +}) + + + From 2c0d34105ad84f9f03ae122f323d58304530c1f3 Mon Sep 17 00:00:00 2001 From: Jacob Nguyen <76754747+jacoobes@users.noreply.github.com> Date: Mon, 5 Feb 2024 10:56:12 -0600 Subject: [PATCH 21/24] " --- package.json | 6 +--- src/core/contracts/index.ts | 1 - src/core/contracts/localization.ts | 11 ------- src/core/ioc/dependency-injection.ts | 46 ---------------------------- src/core/ioc/index.ts | 2 +- src/optional/localizer.ts | 46 ---------------------------- src/types/core-plugin.ts | 6 ++-- src/types/ioc.ts | 4 ++- tsup.config.js | 4 +-- 9 files changed, 10 insertions(+), 116 deletions(-) delete mode 100644 src/core/contracts/localization.ts delete mode 100644 src/optional/localizer.ts diff --git a/package.json b/package.json index 6971bdfd..a636251e 100644 --- a/package.json +++ b/package.json @@ -50,7 +50,6 @@ "discord.js": "^14.11.0", "eslint": "8.39.0", "prettier": "2.8.8", - "shrimple-locales": "^0.2.0", "tsup": "^6.7.0", "typescript": "5.0.2", "vitest": "latest" @@ -95,8 +94,5 @@ "type": "git", "url": "git+https://github.com/sern-handler/handler.git" }, - "homepage": "https://sern.dev", - "peerDependencies": { - "shrimple-locales": "^0.2.0" - } + "homepage": "https://sern.dev" } diff --git a/src/core/contracts/index.ts b/src/core/contracts/index.ts index 20910fbe..7d123b1e 100644 --- a/src/core/contracts/index.ts +++ b/src/core/contracts/index.ts @@ -5,4 +5,3 @@ export * from './module-store'; export * from './init'; export * from './emitter'; export * from './disposable' -export * from './localization' diff --git a/src/core/contracts/localization.ts b/src/core/contracts/localization.ts deleted file mode 100644 index f1b40a82..00000000 --- a/src/core/contracts/localization.ts +++ /dev/null @@ -1,11 +0,0 @@ -/** - * @since 3.4.0 - * Represents a localization service which can translate text for you. - * The internal representation of localization may differ between Localizers, - * But we are insured that translate, translateFor, currentLocale are always available - */ -export interface Localization { - translate(text: string, local: string) : string; - translationsFor(path: string): Record - currentLocale: string -} diff --git a/src/core/ioc/dependency-injection.ts b/src/core/ioc/dependency-injection.ts index b7068cb0..f792b8ae 100644 --- a/src/core/ioc/dependency-injection.ts +++ b/src/core/ioc/dependency-injection.ts @@ -1,10 +1,6 @@ import assert from 'node:assert'; import type { IntoDependencies } from '../../types/ioc'; import { useContainerRaw } from './base'; -import { fileURLToPath } from 'node:url'; -import path from 'node:path'; -import { requir } from '../module-loading'; -import type { Localization } from '../contracts'; /** * @__PURE__ @@ -59,45 +55,3 @@ export function useContainer() { keys.map(key => useContainerRaw().get(key as keyof Dependencies)) as IntoDependencies; } -/** - * Translates a string to its respective local - * Note: this method only works AFTER your container has been initiated - * @example - * ```ts - * assert.deepEqual(locals("salute.hello", "es"), "hola") - * ``` - */ -export const local = (i: string, local: string) => { - return Service('@sern/localizer').translate(i, local) -} - -/** - * Returns a record of locales to their respective translations. - * Note: this method only works AFTER your container has been initiated - * @example - * ```ts - * assert.deepEqual(localsFor("salute.hello"), { "en-US": "hello", "es": "hola" }) - * ``` - */ -export const localsFor = (path: string) => { - return Service('@sern/localizer').translationsFor(path) -} -/** - * A service which provides simple file based localization. Add this while making dependencies. - * @example - * ```ts - * await makeDependencies(({ add }) => { - * add('@sern/localizer', DefaultLocalization()); - * }); - * ``` - **/ -export const DefaultLocalization = (defaultLocale?: string) => { - const packageDirectory = fileURLToPath(import.meta.url); - const pathToLocalizer= path.resolve(packageDirectory, "../", "optional", "localizer"); - const { ShrimpleLocalizer } = requir(pathToLocalizer); - const localizer = new ShrimpleLocalizer as Localization; - if (defaultLocale) { - localizer.currentLocale = defaultLocale; - } - return localizer; -} diff --git a/src/core/ioc/index.ts b/src/core/ioc/index.ts index 90b296b9..fcc32bda 100644 --- a/src/core/ioc/index.ts +++ b/src/core/ioc/index.ts @@ -1,2 +1,2 @@ export { makeDependencies } from './base'; -export { Service, Services, single, transient, local, localsFor, DefaultLocalization } from './dependency-injection'; +export { Service, Services, single, transient } from './dependency-injection'; diff --git a/src/optional/localizer.ts b/src/optional/localizer.ts deleted file mode 100644 index e8a126ae..00000000 --- a/src/optional/localizer.ts +++ /dev/null @@ -1,46 +0,0 @@ -import type { Localization, Init } from '../core/contracts' -import { Localization as LocalsProvider } from 'shrimple-locales' -import fs from 'node:fs/promises' -import { existsSync } from 'node:fs' -import { join, resolve } from 'node:path'; -import { filename } from '../core/module-loading' -import assert from 'node:assert'; - -/** - * @since 3.4.0 - * @internal - */ -export class ShrimpleLocalizer implements Localization, Init { - private __localization!: LocalsProvider; - constructor(){} - currentLocale: string = "en-US"; - - translationsFor(path: string): Record { - return this.__localization.localizationFor(path); - } - - translate(text: string, local: string): string { - this.__localization.changeLanguage(local); - return this.__localization.get(text); - } - - async init() { - const map = await this.readLocalizationDirectory(); - this.__localization = new LocalsProvider({ - defaultLocale: this.currentLocale, - fallbackLocale: "en-US", - locales: map - }); - } - - private async readLocalizationDirectory() { - const translationFiles = []; - const localPath = resolve('resources', 'locals'); - assert(existsSync(localPath), "No directory \"resources/locals\" found for the localizer") - for(const json of await fs.readdir(localPath)) { - translationFiles.push({ [filename(json)]: - JSON.parse(await fs.readFile(join(localPath, json), 'utf8')) }) - } - return translationFiles.reduce((acc, cur ) => ({ ...cur, ...acc }), {}); - } -} diff --git a/src/types/core-plugin.ts b/src/types/core-plugin.ts index fb626990..8ece7c3c 100644 --- a/src/types/core-plugin.ts +++ b/src/types/core-plugin.ts @@ -33,9 +33,9 @@ import type { TextCommand, UserSelectCommand, } from './core-modules'; -import { Args, Awaitable, Payload, SlashOptions } from './utility'; -import { CommandType, Context, EventType, PluginType } from '../core'; -import { +import type { Args, Awaitable, Payload, SlashOptions } from './utility'; +import type { CommandType, Context, EventType, PluginType } from '../core'; +import type { ButtonInteraction, ChannelSelectMenuInteraction, ClientEvents, diff --git a/src/types/ioc.ts b/src/types/ioc.ts index 4b05c319..11bf2b7d 100644 --- a/src/types/ioc.ts +++ b/src/types/ioc.ts @@ -31,7 +31,6 @@ export interface CoreDependencies { '@sern/modules': () => Contracts.ModuleManager; '@sern/errors': () => Contracts.ErrorHandling; '@sern/logger'?: () => Contracts.Logging; - '@sern/localizer'?: () => Contracts.Localization } export type DependencyFromKey = Dependencies[T]; @@ -40,6 +39,9 @@ export type IntoDependencies = { [Index in keyof Tuple]: UnpackFunction>>; //Unpack and make NonNullable } & { length: Tuple['length'] }; +/** + * @deprecated This old signature will be incompatible with future versions of sern. + */ export interface DependencyConfiguration { /* * @deprecated. Loggers will be opt-in the future diff --git a/tsup.config.js b/tsup.config.js index 0217257d..812c2a60 100644 --- a/tsup.config.js +++ b/tsup.config.js @@ -1,7 +1,7 @@ import { defineConfig } from 'tsup'; const shared = { - entry: ['src/index.ts', 'src/optional/localizer.ts'], - external: ['discord.js', 'iti', 'shrimple-locales'], + entry: ['src/index.ts'], + external: ['discord.js', 'iti'], platform: 'node', clean: true, sourcemap: true, From 945df8533028b2c388284fbbd4cc8613a5f1cddf Mon Sep 17 00:00:00 2001 From: Jacob Nguyen <76754747+jacoobes@users.noreply.github.com> Date: Wed, 7 Feb 2024 01:08:39 -0600 Subject: [PATCH 22/24] move stuff, refactor, deprecate --- package.json | 3 +++ src/core/contracts/disposable.ts | 9 --------- src/core/contracts/hooks.ts | 16 ++++++++++++++++ src/core/contracts/index.ts | 3 +-- src/core/contracts/init.ts | 8 -------- src/core/ioc/base.ts | 15 ++++++--------- src/core/ioc/container.ts | 6 ++---- src/core/operators.ts | 3 +-- src/core/structures/module-store.ts | 5 ++--- src/handlers/event-utils.ts | 3 +-- src/types/ioc.ts | 4 ++++ 11 files changed, 36 insertions(+), 39 deletions(-) delete mode 100644 src/core/contracts/disposable.ts create mode 100644 src/core/contracts/hooks.ts delete mode 100644 src/core/contracts/init.ts diff --git a/package.json b/package.json index a636251e..26f45aea 100644 --- a/package.json +++ b/package.json @@ -94,5 +94,8 @@ "type": "git", "url": "git+https://github.com/sern-handler/handler.git" }, + "engines": { + "node": ">= 18.16.x" + }, "homepage": "https://sern.dev" } diff --git a/src/core/contracts/disposable.ts b/src/core/contracts/disposable.ts deleted file mode 100644 index 42b0142c..00000000 --- a/src/core/contracts/disposable.ts +++ /dev/null @@ -1,9 +0,0 @@ -import type { Awaitable } from '../../types/utility'; - -/** - * Represents a Disposable contract. - * Let dependencies implement this to dispose and cleanup. - */ -export interface Disposable { - dispose(): Awaitable; -} diff --git a/src/core/contracts/hooks.ts b/src/core/contracts/hooks.ts new file mode 100644 index 00000000..ee329dde --- /dev/null +++ b/src/core/contracts/hooks.ts @@ -0,0 +1,16 @@ + +/** + * Represents an initialization contract. + * Let dependencies implement this to initiate some logic. + */ +export interface Init { + init(): unknown; +} + +/** + * Represents a Disposable contract. + * Let dependencies implement this to dispose and cleanup. + */ +export interface Disposable { + dispose(): unknown; +} diff --git a/src/core/contracts/index.ts b/src/core/contracts/index.ts index 7d123b1e..f0eb130a 100644 --- a/src/core/contracts/index.ts +++ b/src/core/contracts/index.ts @@ -2,6 +2,5 @@ export * from './error-handling'; export * from './logging'; export * from './module-manager'; export * from './module-store'; -export * from './init'; +export * from './hooks'; export * from './emitter'; -export * from './disposable' diff --git a/src/core/contracts/init.ts b/src/core/contracts/init.ts deleted file mode 100644 index 5769d239..00000000 --- a/src/core/contracts/init.ts +++ /dev/null @@ -1,8 +0,0 @@ - -/** - * Represents an initialization contract. - * Let dependencies implement this to initiate some logic. - */ -export interface Init { - init(): PromiseLike | unknown; -} diff --git a/src/core/ioc/base.ts b/src/core/ioc/base.ts index dbf363db..540204aa 100644 --- a/src/core/ioc/base.ts +++ b/src/core/ioc/base.ts @@ -40,9 +40,8 @@ const dependencyBuilder = (container: any, excluded: string[] ) => { * Supply the correct key and dependency */ add(key: keyof Dependencies, v: Insertable) { - Result - .wrap(() => container.add({ [key]: v})) - .expect("Failed to add " + key); + Result.wrap(() => container.add({ [key]: v})) + .expect("Failed to add " + key); }, /** * Exclude any dependencies from being added. @@ -58,9 +57,8 @@ const dependencyBuilder = (container: any, excluded: string[] ) => { * Swap out a preexisting dependency. */ swap(key: keyof Dependencies, v: Insertable) { - Result - .wrap(() => container.upsert({ [key]: v })) - .expect("Failed to update " + key); + Result.wrap(() => container.upsert({ [key]: v })) + .expect("Failed to update " + key); }, /** * @param key the key of the dependency @@ -72,9 +70,8 @@ const dependencyBuilder = (container: any, excluded: string[] ) => { * Swap out a preexisting dependency. */ addDisposer(key: keyof Dependencies, cleanup: AnyFunction) { - Result - .wrap(() => container.addDisposer({ [key] : cleanup })) - .expect("Failed to addDisposer for" + key); + Result.wrap(() => container.addDisposer({ [key] : cleanup })) + .expect("Failed to addDisposer for" + key); } }; }; diff --git a/src/core/ioc/container.ts b/src/core/ioc/container.ts index d01b2fc0..638eb8f4 100644 --- a/src/core/ioc/container.ts +++ b/src/core/ioc/container.ts @@ -41,16 +41,14 @@ export class CoreContainer> extends Container 'dispose' in value ? [key] : []); - - for(const key of otherDisposables) { + otherDisposables.forEach(key => { //possible source of bug: dispose is a property. this.addDisposer({ [key]: (dep: Disposable) => dep.dispose() } as never); - } + }) await super.disposeAll(); } diff --git a/src/core/operators.ts b/src/core/operators.ts index 12743ab9..d534c5b1 100644 --- a/src/core/operators.ts +++ b/src/core/operators.ts @@ -71,8 +71,7 @@ export function handleError(crashHandler: ErrorHandling, logging?: Logging) { } // Temporary until i get rxjs operators working on ts-results-es export const filterTap = (onErr: (e: R) => void): OperatorFunction, K> => - pipe( - concatMap(result => { + pipe(concatMap(result => { if(result.isOk()) { return of(result.value) } diff --git a/src/core/structures/module-store.ts b/src/core/structures/module-store.ts index 6e754e1a..44d9ca1c 100644 --- a/src/core/structures/module-store.ts +++ b/src/core/structures/module-store.ts @@ -1,12 +1,11 @@ import { CommandMeta, Module } from '../../types/core-modules'; -import { CoreModuleStore } from '../contracts'; /* - * @internal + * @deprecated * Version 4.0.0 will internalize this api. Please refrain from using ModuleStore! * For interacting with modules, use the ModuleManager instead. */ -export class ModuleStore implements CoreModuleStore { +export class ModuleStore { metadata = new WeakMap(); commands = new Map(); } diff --git a/src/handlers/event-utils.ts b/src/handlers/event-utils.ts index fd079384..a2e757b1 100644 --- a/src/handlers/event-utils.ts +++ b/src/handlers/event-utils.ts @@ -86,8 +86,7 @@ export function createInteractionHandler( module: payload.module, event, }))); - }, -); + }); } export function createMessageHandler( diff --git a/src/types/ioc.ts b/src/types/ioc.ts index 11bf2b7d..be5278a9 100644 --- a/src/types/ioc.ts +++ b/src/types/ioc.ts @@ -27,6 +27,10 @@ export type DependencyList = [ export interface CoreDependencies { '@sern/client': () => Contracts.Emitter; '@sern/emitter': () => Contracts.Emitter; + /** + * @deprecated + * Will be removed and turned internal + */ '@sern/store': () => Contracts.CoreModuleStore; '@sern/modules': () => Contracts.ModuleManager; '@sern/errors': () => Contracts.ErrorHandling; From a83e2436425c77fb8bc63703791e0a392d81ecb0 Mon Sep 17 00:00:00 2001 From: Jacob Nguyen <76754747+jacoobes@users.noreply.github.com> Date: Wed, 7 Feb 2024 01:27:57 -0600 Subject: [PATCH 23/24] yarnb --- yarn.lock | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/yarn.lock b/yarn.lock index 16513d39..afae7762 100644 --- a/yarn.lock +++ b/yarn.lock @@ -633,13 +633,10 @@ __metadata: iti: ^0.6.0 prettier: 2.8.8 rxjs: ^7.8.0 - shrimple-locales: ^0.2.0 ts-results-es: ^4.0.0 tsup: ^6.7.0 typescript: 5.0.2 vitest: latest - peerDependencies: - shrimple-locales: ^0.2.0 languageName: unknown linkType: soft @@ -3116,13 +3113,6 @@ __metadata: languageName: node linkType: hard -"shrimple-locales@npm:^0.2.0": - version: 0.2.0 - resolution: "shrimple-locales@npm:0.2.0" - checksum: 9b5360e6ca5b2e75fdbaaeee0286015294b64773950924088f6088184f010837a89e84101eddfedcda5dd660a97df84fee6e1e95345e01f7e1edfff6b4ff2341 - languageName: node - linkType: hard - "siginfo@npm:^2.0.0": version: 2.0.0 resolution: "siginfo@npm:2.0.0" From 3ac1c7e0ec65b0db9882a5456ff7f46a79ea05ff Mon Sep 17 00:00:00 2001 From: Jacob Nguyen <76754747+jacoobes@users.noreply.github.com> Date: Thu, 8 Feb 2024 16:32:38 -0600 Subject: [PATCH 24/24] Update index.ts --- src/core/ioc/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/ioc/index.ts b/src/core/ioc/index.ts index fcc32bda..e89f8b6f 100644 --- a/src/core/ioc/index.ts +++ b/src/core/ioc/index.ts @@ -1,2 +1,2 @@ export { makeDependencies } from './base'; -export { Service, Services, single, transient } from './dependency-injection'; +export { Service, Services, single, transient } from './dependency-injection';