diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 74b6d314..60814034 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -6,7 +6,7 @@ repos: args: ["--maxkb=1024"] exclude: | (?x)^( - bundler/esbuild_v0.19.11.wasm + bundler/esbuild_v0.20.0.wasm )$ - id: check-case-conflict - id: check-executables-have-shebangs @@ -64,7 +64,7 @@ repos: .git/COMMIT_EDITMSG| appserver/README.md| bundler/README.md| - bundler/esbuild_v0.19.11.wasm| + bundler/esbuild_v0.20.0.wasm| collector/README.md| di/README.md| directives/README.md| diff --git a/_etc/tasks/deps.ts b/_etc/tasks/deps.ts index c2286591..c73e2faa 100644 --- a/_etc/tasks/deps.ts +++ b/_etc/tasks/deps.ts @@ -1,3 +1,3 @@ // Copyright 2023-present Eser Ozvataf and other contributors. All rights reserved. Apache-2.0 license. -export * as walk from "https://deno.land/std@0.212.0/fs/walk.ts"; +export * as walk from "https://deno.land/std@0.213.0/fs/walk.ts"; diff --git a/appserver/appserver.ts b/appserver/appserver.ts index 5eb5f3f2..4131e3c7 100644 --- a/appserver/appserver.ts +++ b/appserver/appserver.ts @@ -19,7 +19,7 @@ export class AppServer { awaits: Array> = []; constructor() { - this.runMode = runModes.RunMode.NotSet; + this.runMode = runModes.RunModes.NotSet; this.events = events; this.di = di; this.channels = new Map(); diff --git a/appserver/deps.ts b/appserver/deps.ts index c6269bf3..75778ff9 100644 --- a/appserver/deps.ts +++ b/appserver/deps.ts @@ -1,3 +1,3 @@ // Copyright 2023-present Eser Ozvataf and other contributors. All rights reserved. Apache-2.0 license. -export * as semver from "https://deno.land/std@0.212.0/semver/mod.ts"; +export * as semver from "https://deno.land/std@0.213.0/semver/mod.ts"; diff --git a/bundler/deps.ts b/bundler/deps.ts index 9cfb3f6b..477e5b83 100644 --- a/bundler/deps.ts +++ b/bundler/deps.ts @@ -1,8 +1,8 @@ // Copyright 2023-present Eser Ozvataf and other contributors. All rights reserved. Apache-2.0 license. -export * as colors from "https://deno.land/std@0.212.0/fmt/colors.ts"; -export * as hex from "https://deno.land/std@0.212.0/encoding/hex.ts"; -export * as path from "https://deno.land/std@0.212.0/path/mod.ts"; -export * as regexpEscape from "https://deno.land/std@0.212.0/regexp/escape.ts"; +export * as colors from "https://deno.land/std@0.213.0/fmt/colors.ts"; +export * as hex from "https://deno.land/std@0.213.0/encoding/hex.ts"; +export * as path from "https://deno.land/std@0.213.0/path/mod.ts"; +export * as regexpEscape from "https://deno.land/std@0.213.0/regexp/escape.ts"; -export * as esbuild from "https://deno.land/x/esbuild_deno_loader@0.8.3/mod.ts"; +export * as esbuild from "https://deno.land/x/esbuild_deno_loader@0.8.5/mod.ts"; diff --git a/bundler/esbuild.ts b/bundler/esbuild.ts index 3700368e..eeaecf31 100644 --- a/bundler/esbuild.ts +++ b/bundler/esbuild.ts @@ -4,7 +4,7 @@ import { type BuildOptions, type OnLoadOptions, type Plugin, -} from "https://deno.land/x/esbuild@v0.19.11/mod.js"; +} from "https://deno.land/x/esbuild@v0.20.0/mod.js"; import * as runtime from "../standards/runtime.ts"; import { esbuild, path, regexpEscape } from "./deps.ts"; import { Builder, BuildSnapshot } from "./mod.ts"; @@ -43,12 +43,12 @@ export class EsbuildBuilder implements Builder { const portableBuilder = env["LIME_ESBUILD_LOADER"] === "portable"; // Lazily initialize esbuild - // @deno-types="https://deno.land/x/esbuild@v0.19.11/mod.d.ts" + // @deno-types="https://deno.land/x/esbuild@v0.20.0/mod.d.ts" const esbuildInstance = isOnDenoDeploy || portableBuilder - ? await import("https://deno.land/x/esbuild@v0.19.11/wasm.js") - : await import("https://deno.land/x/esbuild@v0.19.11/mod.js"); + ? await import("https://deno.land/x/esbuild@v0.20.0/wasm.js") + : await import("https://deno.land/x/esbuild@v0.20.0/mod.js"); const esbuildWasmURL = - new URL("./esbuild_v0.19.11.wasm", import.meta.url).href; + new URL("./esbuild_v0.20.0.wasm", import.meta.url).href; if (isOnDenoDeploy) { await esbuildInstance.initialize({ diff --git a/bundler/esbuild_v0.19.11.wasm b/bundler/esbuild_v0.20.0.wasm similarity index 76% rename from bundler/esbuild_v0.19.11.wasm rename to bundler/esbuild_v0.20.0.wasm index 6b208de4..8b4bb2b1 100644 Binary files a/bundler/esbuild_v0.19.11.wasm and b/bundler/esbuild_v0.20.0.wasm differ diff --git a/collector/collector.ts b/collector/collector.ts index 9c780241..b27b8b88 100644 --- a/collector/collector.ts +++ b/collector/collector.ts @@ -8,6 +8,7 @@ import { path, walk } from "./deps.ts"; import * as patterns from "../standards/patterns.ts"; +// import { runtime } from "$cool/standards/mod.ts"; export async function* walkFiles( baseDir: string, @@ -35,11 +36,12 @@ export async function* walkFiles( export interface CollectExportsOptions { baseDir: string; globFilter?: string; - exportFilter?: (entries: [string, unknown][]) => [string, unknown][]; + exportFilter?: (entries: [string, unknown][]) => Promise<[string, unknown][]>; ignoreFilePattern?: RegExp; } export const collectExports = async (options: CollectExportsOptions) => { + // const mainModule = runtime.current.getMainModule(); const ignoreFilePattern = options.ignoreFilePattern ?? patterns.JS_TEST_FILE_PATTERN; @@ -55,6 +57,10 @@ export const collectExports = async (options: CollectExportsOptions) => { const entryUri = `${options.baseDir}/${entry}`; try { + // if (`file://${entryUri}` === mainModule) { + // continue; + // } + const entryModule = await import(entryUri); const moduleExports = Object.entries(entryModule); @@ -63,7 +69,7 @@ export const collectExports = async (options: CollectExportsOptions) => { continue; } - const selectedExports = options.exportFilter(moduleExports); + const selectedExports = await options.exportFilter(moduleExports); if (selectedExports.length === 0) { continue; diff --git a/collector/deps-dev.ts b/collector/deps-dev.ts index 9c9ddf22..f10dec70 100644 --- a/collector/deps-dev.ts +++ b/collector/deps-dev.ts @@ -1,4 +1,4 @@ // Copyright 2023-present Eser Ozvataf and other contributors. All rights reserved. Apache-2.0 license. -export * as assert from "https://deno.land/std@0.212.0/assert/mod.ts"; -export * as bdd from "https://deno.land/std@0.212.0/testing/bdd.ts"; +export * as assert from "https://deno.land/std@0.213.0/assert/mod.ts"; +export * as bdd from "https://deno.land/std@0.213.0/testing/bdd.ts"; diff --git a/collector/deps.ts b/collector/deps.ts index 89c33f15..b83883ed 100644 --- a/collector/deps.ts +++ b/collector/deps.ts @@ -1,5 +1,5 @@ // Copyright 2023-present Eser Ozvataf and other contributors. All rights reserved. Apache-2.0 license. -export * as path from "https://deno.land/std@0.212.0/path/mod.ts"; -export * as posix from "https://deno.land/std@0.212.0/path/posix/mod.ts"; -export * as walk from "https://deno.land/std@0.212.0/fs/walk.ts"; +export * as path from "https://deno.land/std@0.213.0/path/mod.ts"; +export * as posix from "https://deno.land/std@0.213.0/path/posix/mod.ts"; +export * as walk from "https://deno.land/std@0.213.0/fs/walk.ts"; diff --git a/collector/manifest.ts b/collector/manifest.ts index 8143b878..3de76db4 100644 --- a/collector/manifest.ts +++ b/collector/manifest.ts @@ -8,6 +8,7 @@ import { path, posix } from "./deps.ts"; import * as runtime from "../standards/runtime.ts"; +import * as logger from "../logging/logger.ts"; import * as validatorIdentifier from "./validator-identifier/mod.ts"; import * as collector from "./collector.ts"; import * as formatter from "./formatter.ts"; @@ -138,14 +139,20 @@ export const manifest = ${manifestSerialized}; }; export const buildManifest = async ( + target: WritableStream, options: collector.CollectExportsOptions, ) => { const collection = await collector.collectExports(options); const manifestStr = await writeManifestToString(collection); - const manifestPath = path.join(options.baseDir, "./manifest.gen.ts"); - await runtime.current.writeTextFile(manifestPath, manifestStr); + const outputWriter = target.getWriter(); + await outputWriter.ready; + + const encoded = new TextEncoder().encode(manifestStr); + await outputWriter.write(encoded); + + outputWriter.releaseLock(); const exportModules = Object.values(collection); const exportCount = exportModules.reduce((acc, [, moduleFns]) => { @@ -153,8 +160,21 @@ export const buildManifest = async ( return acc; }, 0); - console.log( - `%cThe manifest file has been generated for ${exportCount} exports in ${exportModules.length} modules.`, - "color: blue", + logger.current.info( + `The manifest file has been generated for ${exportCount} exports in ${exportModules.length} modules.`, ); }; + +export const buildManifestFile = async ( + filepath: string, + options: collector.CollectExportsOptions, +) => { + const target = await runtime.current.open(filepath, { + create: true, + write: true, + }); + + await buildManifest(target.writable, options); + + target.close(); +}; diff --git a/cool.ts b/cool.ts index f3acc671..24e14cc5 100755 --- a/cool.ts +++ b/cool.ts @@ -20,7 +20,9 @@ export const repl = async (_args: Array, _options: ExecuteOptions) => { { args: [ "repl", - "--unstable", + "--unstable-cron", + "--unstable-kv", + "--unstable-temporal", "--allow-all", "--eval-file=https://deno.land/x/cool@0.7.13/repl-init.ts", ], diff --git a/deno.jsonc b/deno.jsonc index 7fe43c61..9c5615ab 100644 --- a/deno.jsonc +++ b/deno.jsonc @@ -45,7 +45,7 @@ ] }, "tasks": { - "cleanup": "rm -rf ./_etc/coverage/ ./_etc/coverage.lcov ./deno.lock && deno cache --unstable --reload ./mod.ts", + "cleanup": "rm -rf ./_etc/coverage/ ./_etc/coverage.lcov ./deno.lock && deno cache --unstable-cron --unstable-kv --unstable-temporal --reload ./mod.ts", "check:license": "deno run --allow-read --allow-write ./_etc/tasks/check-license.ts", "check:mod": "deno run --check --reload ./mod.ts", "doc:lint": "deno doc --lint ./mod.ts", @@ -55,7 +55,7 @@ "test:coverage": "deno coverage ./_etc/coverage/ --exclude='\\.(j|t)sx$'", "test:coverage-gen": "deno coverage ./_etc/coverage --exclude='\\.(j|t)sx$' --lcov --output=./_etc/coverage.lcov", "ok": "deno fmt --check && deno lint && deno task check:license --check && deno task check:mod && deno task test:run", - "repl": "deno repl --unstable --allow-all --eval-file=./repl-init.ts", + "repl": "deno repl --unstable-cron --unstable-kv --unstable-temporal --allow-all --eval-file=./repl-init.ts", "container:build": "docker build -t cool .", "container:run": "docker run --interactive --tty --rm cool" } diff --git a/deps.ts b/deps.ts index 98e3ed6f..c2a44960 100644 --- a/deps.ts +++ b/deps.ts @@ -1,3 +1,3 @@ // Copyright 2023-present Eser Ozvataf and other contributors. All rights reserved. Apache-2.0 license. -export * as posix from "https://deno.land/std@0.212.0/path/posix/mod.ts"; +export * as posix from "https://deno.land/std@0.213.0/path/posix/mod.ts"; diff --git a/di/container.ts b/di/container.ts index 5e449216..3f1cbad1 100644 --- a/di/container.ts +++ b/di/container.ts @@ -1,7 +1,7 @@ // Copyright 2023-present Eser Ozvataf and other contributors. All rights reserved. Apache-2.0 license. import { type Promisable } from "../standards/promises.ts"; -import { type AnonymousFunction } from "../standards/functions.ts"; +import { type GenericFunction } from "../standards/functions.ts"; import { type PromisableBuilder, type ServiceDescriptor, @@ -9,7 +9,7 @@ import { type ServiceRegistry, type ServiceResolution, type ServiceScope, - ServiceType, + ServiceTypes, type ServiceValue, } from "./primitives.ts"; import { invoke } from "./invoker.ts"; @@ -19,25 +19,25 @@ export class Registry descriptors = new Map>(); set(token: K, value: Promisable) { - this.descriptors.set(token, [ServiceType.Singleton, value]); + this.descriptors.set(token, [ServiceTypes.Singleton, value]); return this; } setLazy(token: K, value: PromisableBuilder) { - this.descriptors.set(token, [ServiceType.Lazy, value]); + this.descriptors.set(token, [ServiceTypes.Lazy, value]); return this; } setScoped(token: K, value: PromisableBuilder) { - this.descriptors.set(token, [ServiceType.Scoped, value]); + this.descriptors.set(token, [ServiceTypes.Scoped, value]); return this; } setTransient(token: K, value: PromisableBuilder) { - this.descriptors.set(token, [ServiceType.Transient, value]); + this.descriptors.set(token, [ServiceTypes.Transient, value]); return this; } @@ -68,14 +68,15 @@ export class Scope return defaultValue; } - if (descriptor[0] === ServiceType.Singleton) { + if (descriptor[0] === ServiceTypes.Singleton) { return descriptor[1] as Promisable; } if ( - descriptor[0] === ServiceType.Lazy || descriptor[0] === ServiceType.Scoped + descriptor[0] === ServiceTypes.Lazy || + descriptor[0] === ServiceTypes.Scoped ) { - const targetScope = (descriptor[0] === ServiceType.Scoped) + const targetScope = (descriptor[0] === ServiceTypes.Scoped) ? this : this.rootScope; const stored = targetScope.items.get(token); @@ -100,7 +101,7 @@ export class Scope return result as ServiceResolution; } - // if (descriptor[0] === ServiceType.Transient) { + // if (descriptor[0] === ServiceTypes.Transient) { const value = descriptor[1] as PromisableBuilder; const result = value(this); @@ -112,7 +113,7 @@ export class Scope return tokens.map((token) => this.get(token)); } - invoke(fn: T): ReturnType { + invoke(fn: T): ReturnType { return invoke(this, fn); } diff --git a/di/deps-dev.ts b/di/deps-dev.ts index 09e2c5af..fe0a1ba2 100644 --- a/di/deps-dev.ts +++ b/di/deps-dev.ts @@ -1,5 +1,5 @@ // Copyright 2023-present Eser Ozvataf and other contributors. All rights reserved. Apache-2.0 license. -export * as assert from "https://deno.land/std@0.212.0/assert/mod.ts"; -export * as bdd from "https://deno.land/std@0.212.0/testing/bdd.ts"; -export * as mock from "https://deno.land/std@0.212.0/testing/mock.ts"; +export * as assert from "https://deno.land/std@0.213.0/assert/mod.ts"; +export * as bdd from "https://deno.land/std@0.213.0/testing/bdd.ts"; +export * as mock from "https://deno.land/std@0.213.0/testing/mock.ts"; diff --git a/di/fluent-api-factory.ts b/di/fluent-api-factory.ts index 7a8961a8..adb8fdcc 100644 --- a/di/fluent-api-factory.ts +++ b/di/fluent-api-factory.ts @@ -1,7 +1,7 @@ // Copyright 2023-present Eser Ozvataf and other contributors. All rights reserved. Apache-2.0 license. import { type Promisable } from "../standards/promises.ts"; -import { type AnonymousFunction } from "../standards/functions.ts"; +import { type GenericFunction } from "../standards/functions.ts"; import { type PromisableBuilder, type ServiceKey, @@ -37,7 +37,7 @@ export const factory = ( di.many = (...tokens: ReadonlyArray) => services.getMany(...tokens); - di.invoke = (fn: T): ReturnType => + di.invoke = (fn: T): ReturnType => services.invoke(fn); di.scope = () => services.createScope(); diff --git a/di/invoker.ts b/di/invoker.ts index a9876cc0..caed3aea 100644 --- a/di/invoker.ts +++ b/di/invoker.ts @@ -1,6 +1,6 @@ // Copyright 2023-present Eser Ozvataf and other contributors. All rights reserved. Apache-2.0 license. -import { type AnonymousFunction } from "../standards/functions.ts"; +import { type GenericFunction } from "../standards/functions.ts"; import { type ServiceKey, type ServiceScope, @@ -17,7 +17,7 @@ const getFunctionParametersFromString = (fnSerialized: string) => { return []; }; -const getFunctionParameters = (fn: AnonymousFunction) => { +const getFunctionParameters = (fn: GenericFunction) => { return getFunctionParametersFromString(fn.toString()); }; @@ -56,7 +56,7 @@ const getFunctionParameters = (fn: AnonymousFunction) => { // }; export const invoke = < - T extends AnonymousFunction, + T extends GenericFunction, K = ServiceKey, V = ServiceValue, >( diff --git a/di/primitives.ts b/di/primitives.ts index 398e4c61..24d54228 100644 --- a/di/primitives.ts +++ b/di/primitives.ts @@ -2,21 +2,24 @@ import { type Promisable } from "../standards/promises.ts"; import { - type AnonymousClass, - type AnonymousFunction, + type GenericClass, + type GenericFunction, } from "../standards/functions.ts"; -export enum ServiceType { - Singleton = 0, - Lazy = 1, - Scoped = 2, - Transient = 3, -} +export const ServiceTypes = { + Singleton: 0, + Lazy: 1, + Scoped: 2, + Transient: 3, +} as const; + +export type ServiceTypeKey = Exclude; +export type ServiceType = typeof ServiceTypes[ServiceTypeKey]; // deno-lint-ignore no-explicit-any export type Value = any; -export type ClassService = AnonymousClass; -export type FunctionService = AnonymousFunction; +export type ClassService = GenericClass; +export type FunctionService = GenericFunction; export type ServiceKey = ClassService | FunctionService | symbol | string; export type ServiceValue = ClassService | FunctionService | Value; @@ -48,7 +51,7 @@ export interface ServiceScope { get(token: K, defaultValue?: V2): ServiceResolution; getMany(...tokens: ReadonlyArray): ReadonlyArray>; - invoke(fn: T): ReturnType; + invoke(fn: T): ReturnType; createScope(): ServiceScope; } diff --git a/dotenv/deps.ts b/dotenv/deps.ts index ae6093ad..9a499257 100644 --- a/dotenv/deps.ts +++ b/dotenv/deps.ts @@ -1,3 +1,3 @@ // Copyright 2023-present Eser Ozvataf and other contributors. All rights reserved. Apache-2.0 license. -export * as dotenv from "https://deno.land/std@0.212.0/dotenv/mod.ts"; +export * as dotenv from "https://deno.land/std@0.213.0/dotenv/mod.ts"; diff --git a/events/deps-dev.ts b/events/deps-dev.ts index 09e2c5af..fe0a1ba2 100644 --- a/events/deps-dev.ts +++ b/events/deps-dev.ts @@ -1,5 +1,5 @@ // Copyright 2023-present Eser Ozvataf and other contributors. All rights reserved. Apache-2.0 license. -export * as assert from "https://deno.land/std@0.212.0/assert/mod.ts"; -export * as bdd from "https://deno.land/std@0.212.0/testing/bdd.ts"; -export * as mock from "https://deno.land/std@0.212.0/testing/mock.ts"; +export * as assert from "https://deno.land/std@0.213.0/assert/mod.ts"; +export * as bdd from "https://deno.land/std@0.213.0/testing/bdd.ts"; +export * as mock from "https://deno.land/std@0.213.0/testing/mock.ts"; diff --git a/file-loader/deps.ts b/file-loader/deps.ts index bae6e943..bbe19de1 100644 --- a/file-loader/deps.ts +++ b/file-loader/deps.ts @@ -1,7 +1,7 @@ // Copyright 2023-present Eser Ozvataf and other contributors. All rights reserved. Apache-2.0 license. -export * as JSONC from "https://deno.land/std@0.212.0/jsonc/mod.ts"; -export * as TOML from "https://deno.land/std@0.212.0/toml/mod.ts"; -export * as YAML from "https://deno.land/std@0.212.0/yaml/mod.ts"; -export * as path from "https://deno.land/std@0.212.0/path/mod.ts"; -export * as fs from "https://deno.land/std@0.212.0/fs/mod.ts"; +export * as JSONC from "https://deno.land/std@0.213.0/jsonc/mod.ts"; +export * as TOML from "https://deno.land/std@0.213.0/toml/mod.ts"; +export * as YAML from "https://deno.land/std@0.213.0/yaml/mod.ts"; +export * as path from "https://deno.land/std@0.213.0/path/mod.ts"; +export * as fs from "https://deno.land/std@0.213.0/fs/mod.ts"; diff --git a/fp/compose.ts b/fp/compose.ts index f2c87f20..f9b1e9e6 100644 --- a/fp/compose.ts +++ b/fp/compose.ts @@ -1,11 +1,8 @@ // Copyright 2023-present Eser Ozvataf and other contributors. All rights reserved. Apache-2.0 license. -import { - type AnonymousFunction, - type ArgList, -} from "../standards/functions.ts"; +import { type ArgList, type GenericFunction } from "../standards/functions.ts"; -type ComposableFunction = AnonymousFunction; +type ComposableFunction = GenericFunction; export const compose = ( ...funcs: ReadonlyArray diff --git a/fp/deps-dev.ts b/fp/deps-dev.ts index 9c9ddf22..f10dec70 100644 --- a/fp/deps-dev.ts +++ b/fp/deps-dev.ts @@ -1,4 +1,4 @@ // Copyright 2023-present Eser Ozvataf and other contributors. All rights reserved. Apache-2.0 license. -export * as assert from "https://deno.land/std@0.212.0/assert/mod.ts"; -export * as bdd from "https://deno.land/std@0.212.0/testing/bdd.ts"; +export * as assert from "https://deno.land/std@0.213.0/assert/mod.ts"; +export * as bdd from "https://deno.land/std@0.213.0/testing/bdd.ts"; diff --git a/fp/pipe.ts b/fp/pipe.ts index 0eefa595..34f315cf 100644 --- a/fp/pipe.ts +++ b/fp/pipe.ts @@ -1,11 +1,8 @@ // Copyright 2023-present Eser Ozvataf and other contributors. All rights reserved. Apache-2.0 license. -import { - type AnonymousFunction, - type ArgList, -} from "../standards/functions.ts"; +import { type ArgList, type GenericFunction } from "../standards/functions.ts"; -type ComposableFunction = AnonymousFunction; +type ComposableFunction = GenericFunction; export const pipe = ( ...funcs: ReadonlyArray diff --git a/functions/deps-dev.ts b/functions/deps-dev.ts index 09e2c5af..fe0a1ba2 100644 --- a/functions/deps-dev.ts +++ b/functions/deps-dev.ts @@ -1,5 +1,5 @@ // Copyright 2023-present Eser Ozvataf and other contributors. All rights reserved. Apache-2.0 license. -export * as assert from "https://deno.land/std@0.212.0/assert/mod.ts"; -export * as bdd from "https://deno.land/std@0.212.0/testing/bdd.ts"; -export * as mock from "https://deno.land/std@0.212.0/testing/mock.ts"; +export * as assert from "https://deno.land/std@0.213.0/assert/mod.ts"; +export * as bdd from "https://deno.land/std@0.213.0/testing/bdd.ts"; +export * as mock from "https://deno.land/std@0.213.0/testing/mock.ts"; diff --git a/jsx-runtime.test/deps-dev.ts b/jsx-runtime.test/deps-dev.ts index 09e2c5af..fe0a1ba2 100644 --- a/jsx-runtime.test/deps-dev.ts +++ b/jsx-runtime.test/deps-dev.ts @@ -1,5 +1,5 @@ // Copyright 2023-present Eser Ozvataf and other contributors. All rights reserved. Apache-2.0 license. -export * as assert from "https://deno.land/std@0.212.0/assert/mod.ts"; -export * as bdd from "https://deno.land/std@0.212.0/testing/bdd.ts"; -export * as mock from "https://deno.land/std@0.212.0/testing/mock.ts"; +export * as assert from "https://deno.land/std@0.213.0/assert/mod.ts"; +export * as bdd from "https://deno.land/std@0.213.0/testing/bdd.ts"; +export * as mock from "https://deno.land/std@0.213.0/testing/mock.ts"; diff --git a/lime.test/build.ts b/lime.test/build.ts new file mode 100644 index 00000000..1317ada7 --- /dev/null +++ b/lime.test/build.ts @@ -0,0 +1,11 @@ +// Copyright 2023-present Eser Ozvataf and other contributors. All rights reserved. Apache-2.0 license. + +import * as collector from "../collector/mod.ts"; + +await collector.buildManifest( + Deno.stdout.writable, + { + baseDir: import.meta.dirname ?? ".", + globFilter: "pkg/**/*", + }, +); diff --git a/lime.test/main.ts b/lime.test/main.ts index 461d3a49..7253b917 100644 --- a/lime.test/main.ts +++ b/lime.test/main.ts @@ -14,14 +14,14 @@ import * as lime from "../lime/mod.ts"; // ... // } -export const instance = lime.lime() +export const instance = lime.builder() .setBaseUrl(import.meta.url) .loadManifest(); -// .setOptions(options) +// .setOptions(options) // (set defaults ... or load from file?) +// .loadEnvironment() // (deserialize options from env, dev mode vs) if (import.meta.main) { - await instance.dev() // { + const [state] = useState({ + title: "", + description: "", + keywords: "", + styles: [], + scripts: [], + }); + + return ( + + + + {state.title} + + + {state.styles.map((style) => )} + + + {props.children} + {state.scripts.map((script) => )} + + + ); +}; + +export const indexPage = (props) => { + return ( + +

Hello World

+
+ ); +}; + +export const anyFnc = (a, b, c) => { + return a + b + c; +}; + +export const limeModule = (r) => { + r.register(baseLayout); + // = r.register(baseLayout, { type: "layout", name: "base", loc: "$/pkg/app/mod.tsx" }); + r.register(indexPage); + // = r.register(indexPage, { type: "page", name: "index", path: "/", loc: "$/pkg/app/mod.tsx" }); + r.register(anyFnc); +}; diff --git a/lime/deps.ts b/lime/deps.ts index 98e3ed6f..c2a44960 100644 --- a/lime/deps.ts +++ b/lime/deps.ts @@ -1,3 +1,3 @@ // Copyright 2023-present Eser Ozvataf and other contributors. All rights reserved. Apache-2.0 license. -export * as posix from "https://deno.land/std@0.212.0/path/posix/mod.ts"; +export * as posix from "https://deno.land/std@0.213.0/path/posix/mod.ts"; diff --git a/lime/mod.ts b/lime/mod.ts index 11251428..e4c9483b 100644 --- a/lime/mod.ts +++ b/lime/mod.ts @@ -8,7 +8,7 @@ export * from "./primitives.ts"; * * @returns {Lime} */ -export const lime = () => { +export const builder = () => { const instance = new primitives.Lime(); instance.setAsDefaultAppServer(); diff --git a/lime/primitives.ts b/lime/primitives.ts index 101bf457..27d6d292 100644 --- a/lime/primitives.ts +++ b/lime/primitives.ts @@ -67,13 +67,17 @@ export class Lime extends appserver.AppServer { } dev(): Lime { - this.runMode |= runModes.RunMode.Development; + this.runMode |= runModes.RunModes.Development; return this; } async start(): Promise { await this.awaitAll(); - // this.execute(_options); + // this.executeOpts(_options); + } + + execute(): Promise { + return this.start(); } } diff --git a/logging/formatters.ts b/logging/formatters.ts new file mode 100644 index 00000000..756c54ed --- /dev/null +++ b/logging/formatters.ts @@ -0,0 +1,32 @@ +// Copyright 2023-present Eser Ozvataf and other contributors. All rights reserved. Apache-2.0 license. + +// This file contains code from deno std lib (https://github.com/denoland/deno_std), +// which is a standard library, licensed under the MIT license. + +// Copyright (c) 2023-2024 Eser Ozvataf and other contributors +// Copyright (c) 2021-2023 the Deno authors + +import * as logging from "../standards/logging.ts"; +import * as functions from "../standards/functions.ts"; +import * as logger from "./logger.ts"; + +export type FormatterFn = (logRecord: logger.LogRecord) => string; + +const flattenArgs = (args: functions.ArgList): unknown => { + if (args.length > 1) { + return args; + } + + return args[0]; +}; + +export const jsonFormatter: FormatterFn = ( + logRecord: logger.LogRecord, +): string => { + return JSON.stringify({ + level: logging.SeverityNames[logRecord.severity], + datetime: logRecord.datetime.getTime(), + message: logRecord.message, + args: flattenArgs(logRecord.args), + }); +}; diff --git a/logging/logger.ts b/logging/logger.ts new file mode 100644 index 00000000..9a7a7ea1 --- /dev/null +++ b/logging/logger.ts @@ -0,0 +1,198 @@ +// Copyright 2023-present Eser Ozvataf and other contributors. All rights reserved. Apache-2.0 license. + +// This file contains code from deno std lib (https://github.com/denoland/deno_std), +// which is a standard library, licensed under the MIT license. + +// Copyright (c) 2023-2024 Eser Ozvataf and other contributors +// Copyright (c) 2021-2023 the Deno authors + +import * as runtime from "../standards/runtime.ts"; +import * as logging from "../standards/logging.ts"; +import * as functions from "../standards/functions.ts"; +import * as formatters from "./formatters.ts"; + +export const DEFAULT_LEVEL = logging.Severities.Info; + +export interface LogRecord { + message: string; + args: functions.ArgList; + datetime: Date; + severity: logging.Severity; + loggerName: string; +} + +export const Logger = class implements logging.Logger { + readonly loggerName: string; + readonly targetStream: WritableStream; + loglevel: logging.Severity; + readonly formatter: formatters.FormatterFn; + encoder: TextEncoder; + + constructor( + loggerName: string, + targetStream: WritableStream, + loglevel: logging.Severity = DEFAULT_LEVEL, + formatter: formatters.FormatterFn = formatters.jsonFormatter, + ) { + this.loggerName = loggerName; + this.targetStream = targetStream; + this.loglevel = loglevel; + this.formatter = formatter; + this.encoder = new TextEncoder(); + } + + /** + * If the level of the logger is greater than the level to log, then nothing + * is logged, otherwise a log record is passed to each log handler. `message` data + * passed in is returned. If a function is passed in, it is only evaluated + * if the message will be logged and the return value will be the result of the + * function, not the function itself, unless the function isn't called, in which + * case undefined is returned. All types are coerced to strings for logging. + */ + async log( + severity: logging.Severity, + message: (T extends functions.GenericFunction ? never : T) | (() => T), + ...args: functions.ArgList + ): Promise { + if (this.loglevel > severity) { + return message instanceof Function ? undefined : message; + } + + let fnResult: T | undefined; + let logMessage: string; + if (message instanceof Function) { + fnResult = message(); + logMessage = this.asString(fnResult); + } else { + logMessage = this.asString(message); + } + const record: LogRecord = { + message: logMessage, + args: args, + datetime: new Date(), + severity: severity, + loggerName: this.loggerName, + }; + + const outputWriter = this.targetStream.getWriter(); + await outputWriter.ready; + + const formatted = this.formatter(record); + const encoded = this.encoder.encode(formatted); + await outputWriter.write(encoded); + + outputWriter.releaseLock(); + + return message instanceof Function ? fnResult : message; + } + + asString(data: unknown, isProperty = false): string { + if (typeof data === "string") { + if (isProperty) { + return `"${data}"`; + } + + return data; + } + + if ( + data === null || + typeof data === "number" || + typeof data === "bigint" || + typeof data === "boolean" || + typeof data === "undefined" || + typeof data === "symbol" + ) { + return String(data); + } + + if (data instanceof Error) { + return data.stack!; + } + + if (typeof data === "object") { + return `{${ + Object.entries(data) + .map(([k, v]) => `"${k}":${this.asString(v, true)}`) + .join(",") + }}`; + } + + return "undefined"; + } + + debug( + message: () => T, + ...args: functions.ArgList + ): Promise; + debug( + message: T extends functions.GenericFunction ? never : T, + ...args: functions.ArgList + ): Promise; + debug( + message: (T extends functions.GenericFunction ? never : T) | (() => T), + ...args: functions.ArgList + ): Promise { + return this.log(logging.Severities.Debug, message, ...args); + } + + info(message: () => T, ...args: functions.ArgList): Promise; + info( + message: T extends functions.GenericFunction ? never : T, + ...args: functions.ArgList + ): Promise; + info( + message: (T extends functions.GenericFunction ? never : T) | (() => T), + ...args: functions.ArgList + ): Promise { + return this.log(logging.Severities.Info, message, ...args); + } + + warn(message: () => T, ...args: functions.ArgList): Promise; + warn( + message: T extends functions.GenericFunction ? never : T, + ...args: functions.ArgList + ): Promise; + warn( + message: (T extends functions.GenericFunction ? never : T) | (() => T), + ...args: functions.ArgList + ): Promise { + return this.log(logging.Severities.Warning, message, ...args); + } + + error( + message: () => T, + ...args: functions.ArgList + ): Promise; + error( + message: T extends functions.GenericFunction ? never : T, + ...args: functions.ArgList + ): Promise; + error( + message: (T extends functions.GenericFunction ? never : T) | (() => T), + ...args: functions.ArgList + ): Promise { + return this.log(logging.Severities.Error, message, ...args); + } + + critical( + message: () => T, + ...args: functions.ArgList + ): Promise; + critical( + message: T extends functions.GenericFunction ? never : T, + ...args: functions.ArgList + ): Promise; + critical( + message: (T extends functions.GenericFunction ? never : T) | (() => T), + ...args: functions.ArgList + ): Promise { + return this.log(logging.Severities.Critical, message, ...args); + } +}; + +export const current = new Logger( + "default", + runtime.current.getStdout(), + DEFAULT_LEVEL, +); diff --git a/logging/mod.ts b/logging/mod.ts new file mode 100644 index 00000000..6ce54299 --- /dev/null +++ b/logging/mod.ts @@ -0,0 +1,4 @@ +// Copyright 2023-present Eser Ozvataf and other contributors. All rights reserved. Apache-2.0 license. + +export * from "./logger.ts"; +export * from "./formatters.ts"; diff --git a/parsing/deps-dev.ts b/parsing/deps-dev.ts index 9c9ddf22..f10dec70 100644 --- a/parsing/deps-dev.ts +++ b/parsing/deps-dev.ts @@ -1,4 +1,4 @@ // Copyright 2023-present Eser Ozvataf and other contributors. All rights reserved. Apache-2.0 license. -export * as assert from "https://deno.land/std@0.212.0/assert/mod.ts"; -export * as bdd from "https://deno.land/std@0.212.0/testing/bdd.ts"; +export * as assert from "https://deno.land/std@0.213.0/assert/mod.ts"; +export * as bdd from "https://deno.land/std@0.213.0/testing/bdd.ts"; diff --git a/standards/functions.ts b/standards/functions.ts index 24395108..3f0ee7a5 100644 --- a/standards/functions.ts +++ b/standards/functions.ts @@ -3,9 +3,9 @@ // deno-lint-ignore no-explicit-any export type ArgList = ReadonlyArray; // deno-lint-ignore no-explicit-any -export type AnonymousFunction = (...args: ArgList) => T; +export type GenericFunction = (...args: ArgList) => T; // deno-lint-ignore no-explicit-any -export type AnonymousClass = new (...args: ArgList) => T; +export type GenericClass = new (...args: ArgList) => T; export const nullAsyncGeneratorFn = async function* (): AsyncGenerator< TR diff --git a/standards/logging.ts b/standards/logging.ts index d3dfb0bb..e83d2f26 100644 --- a/standards/logging.ts +++ b/standards/logging.ts @@ -1,21 +1,37 @@ // Copyright 2023-present Eser Ozvataf and other contributors. All rights reserved. Apache-2.0 license. -import { type ArgList } from "./functions.ts"; +import * as functions from "./functions.ts"; // taken from RFC5424 (see: https://datatracker.ietf.org/doc/html/rfc5424#section-6.2.1) -export enum Severity { - Emergency = 0, // system is unusable - Alert = 1, // action must be taken immediately - Critical = 2, // critical conditions - Error = 3, // error conditions - Warning = 4, // warning conditions - Notice = 5, // normal but significant condition - Info = 6, // informational messages - Debug = 7, // debug-level messages -} +export const Severities = { + Emergency: 0, // system is unusable + Alert: 1, // action must be taken immediately + Critical: 2, // critical conditions + Error: 3, // error conditions + Warning: 4, // warning conditions + Notice: 5, // normal but significant condition + Info: 6, // informational messages + Debug: 7, // debug-level messages +} as const; + +export type SeverityKey = Exclude; +export type Severity = typeof Severities[SeverityKey]; + +export const SeverityNames = { + [Severities.Emergency]: "Emergency", + [Severities.Alert]: "Alert", + [Severities.Critical]: "Critical", + [Severities.Error]: "Error", + [Severities.Warning]: "Warning", + [Severities.Notice]: "Notice", + [Severities.Info]: "Info", + [Severities.Debug]: "Debug", +} as const; export interface Logger { - log(severity: Severity, message: string, ...args: ArgList): void; + log( + severity: Severity, + message: (T extends functions.GenericFunction ? never : T) | (() => T), + ...args: functions.ArgList + ): Promise; } - -export { type Logger as default }; diff --git a/standards/run-modes.ts b/standards/run-modes.ts index e3d3fdab..e67c40ab 100644 --- a/standards/run-modes.ts +++ b/standards/run-modes.ts @@ -1,19 +1,22 @@ // Copyright 2023-present Eser Ozvataf and other contributors. All rights reserved. Apache-2.0 license. -export enum RunMode { - NotSet = 0, - Development = 1, - Test = 2, -} +export const RunModes = { + NotSet: 0, + Development: 1, + Test: 2, +} as const; + +export type RunModeKey = Exclude; +export type RunMode = typeof RunModes[RunModeKey]; export const inProductionMode = (mode: RunMode) => { - return (mode & RunMode.Development) !== RunMode.Development; + return (mode & RunModes.Development) !== RunModes.Development; }; export const inDevelopmentMode = (mode: RunMode) => { - return (mode & RunMode.Development) === RunMode.Development; + return (mode & RunModes.Development) === RunModes.Development; }; export const inTestMode = (mode: RunMode) => { - return (mode & RunMode.Test) === RunMode.Test; + return (mode & RunModes.Test) === RunModes.Test; }; diff --git a/standards/runtime.ts b/standards/runtime.ts index bc5eeb26..49b32523 100644 --- a/standards/runtime.ts +++ b/standards/runtime.ts @@ -3,10 +3,16 @@ /// /// -export enum SupportedRuntimes { - Unknown = 0, - Deno = 1, -} +export const SupportedRuntimes = { + Unknown: 0, + Deno: 1, +} as const; + +export type SupportedRuntimeKey = Exclude< + keyof typeof SupportedRuntimes, + number +>; +export type SupportedRuntime = typeof SupportedRuntimes[SupportedRuntimeKey]; export const notImplemented = (name: string) => { return () => { @@ -21,7 +27,7 @@ export const notSupportedRuntime = (name: string) => { }; export interface Runtime { - runtime: SupportedRuntimes; + runtime: SupportedRuntime; errors: { // deno-lint-ignore no-explicit-any @@ -31,6 +37,11 @@ export interface Runtime { execPath(): string; getArgs(): Array; getEnv(): { [index: string]: string }; + getMainModule(): string | undefined; + + getStdin(): ReadableStream; + getStdout(): WritableStream; + getStderr(): WritableStream; open(path: string | URL, options?: Deno.OpenOptions): Promise; stat(path: string | URL): Promise; @@ -71,6 +82,11 @@ export const createDenoRuntime = (): Runtime => { execPath: denoObjRef.execPath, getArgs: () => denoObjRef.args, getEnv: () => denoObjRef.env.toObject(), + getMainModule: () => denoObjRef.mainModule, + + getStdin: () => denoObjRef.stdin.readable, + getStdout: () => denoObjRef.stdout.writable, + getStderr: () => denoObjRef.stderr.writable, open: denoObjRef.open, stat: denoObjRef.stat, @@ -98,6 +114,11 @@ export const createGenericRuntime = (): Runtime => { execPath: notImplemented("execPath"), getArgs: notImplemented("getArgs"), getEnv: notImplemented("getEnv"), + getMainModule: notImplemented("getMainModule"), + + getStdin: notImplemented("getStdin"), + getStdout: notImplemented("getStdout"), + getStderr: notImplemented("getStderr"), open: notImplemented("open"), stat: notImplemented("stat"),