@tsmodule/tsmodule 8.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) C. Lewis <ctj.lewis@icloud.com> (ctjlewis.com)
4
+ Copyright (c) Luke Edwards <luke.edwards05@gmail.com> (lukeed.com)
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
7
+ this software and associated documentation files (the "Software"), to deal in
8
+ the Software without restriction, including without limitation the rights to
9
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
10
+ the Software, and to permit persons to whom the Software is furnished to do so,
11
+ subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in all
14
+ copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
18
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
19
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
20
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,136 @@
1
+ <div align="center">
2
+ <h1><code>tsmodule</code></h1>
3
+ <h3>TypeScript Module Toolkit</h3>
4
+ </div>
5
+
6
+ ## Features
7
+
8
+ ### Quickly create TypeScript projects with **`tsmodule create`**
9
+
10
+ Supports React via TSX/JSX. Ready with zero config:
11
+
12
+ - package.json scripts: `yarn build`, `yarn test`, `yarn lint`
13
+ - ESLint, `typescript-eslint`, TypeScript configs
14
+ - CI/CD with GitHub Actions
15
+
16
+ ### Build TypeScript to pure ESM with **`tsmodule build`**
17
+
18
+ - No more polyfilling to CJS or older featuresets
19
+ - Use latest syntax in source, leave backporting to downstream consumers
20
+
21
+ ### Run TypeScript directly with **`tsmodule <file>`**
22
+
23
+ - Uses Node module loader to resolve TS at runtime
24
+ - Executable TypeScript files with `#!/usr/bin/env tsm`
25
+
26
+ ## Use Cases
27
+
28
+ Below are some example use cases of TS modules in practice.
29
+
30
+ ### Generic TypeScript library
31
+
32
+ The most common type of library will be a TS module with generic TypeScript
33
+ exports in `src/**/index.ts`, e.g.
34
+ [`await-shell`](https://github.com/ctjlewis/await-shell), a Promise wrapper
35
+ around `child_process.spawn` that's used in tsmodule itself.
36
+
37
+ This library contains only one export at `src/index.ts`, a function called
38
+ `shell`. It has one test at `test/errors.test.ts`.
39
+
40
+ ### Next.js component library
41
+
42
+ It's often necessary to compile libraries of TSX components to valid JS that can
43
+ be consumed by a bundler downstream. This is handled by tsmodule out of the
44
+ box.
45
+
46
+ The following configuration can be used to export a library of TSX components in
47
+ `src/components/**/index.tsx` that is also consumed in a Next.js demo from pages
48
+ in `src/pages`:
49
+
50
+ - In `next.config.js`, allow for ESM externals (our exported components will be
51
+ ESM):
52
+
53
+ ```js
54
+ {
55
+ experiments: {
56
+ esmExternals: true
57
+ }
58
+ }
59
+ ```
60
+
61
+ - In package.json, configure the package to export from `dist/components`:
62
+
63
+ ```json
64
+ {
65
+ "exports": {
66
+ ".": "./dist/index.js",
67
+ "./*": "./dist/components/*/index.js",
68
+ "./styles": "./dist/styles/index.css",
69
+ "./styles/*": "./dist/styles/*/index.css",
70
+ "./package.json": "./package.json"
71
+ },
72
+ }
73
+ ```
74
+
75
+ ## Requirements
76
+
77
+ Because tsmodule packages are pure ESM environments, only **Node 16+** is
78
+ supported.
79
+
80
+ ## Installation
81
+
82
+ Install tsmodule in your project (or globally) to run or build your module:
83
+
84
+ ```shell
85
+ yarn add @tsmodule/tsmodule
86
+ ```
87
+
88
+
89
+ You can build your TypeScript module to ESM with the `build` CLI command:
90
+
91
+ ```shell
92
+ tsmodule build
93
+ ```
94
+
95
+ Source will be compiled from `src/` to `dist/` and will contain only
96
+ ESM-compliant import specifiers as resolved by the tsmodule loader. It can then
97
+ be executed with Node, e.g. `node dist/index.js`.
98
+
99
+ ## Footnotes
100
+
101
+ ### Module configuration
102
+
103
+ All packages built with `tsmodule build` are ES modules. `{ "type": "module" }`
104
+ is forced to minimize ambiguity.
105
+
106
+ `tsmodule build` also forces the following tsconfig.json values during the
107
+ type-check and declaration emit:
108
+
109
+ ```json
110
+ {
111
+ "rootDir": "src/",
112
+ "outDir": "dist/",
113
+ }
114
+ ```
115
+
116
+ And conditional exports in package.json will be configured like so, such that
117
+ "index modules" at e.g. `src/test/index.ts` will be available at
118
+ `my-package/test`:
119
+
120
+ ```json
121
+ {
122
+ "files": ["dist/"],
123
+ "exports": {
124
+ "./package.json": "./package.json",
125
+ "./": "./dist/index.js",
126
+ "./*": "./dist/*/index.js"
127
+ },
128
+ }
129
+ ```
130
+
131
+ This has no restriction on internal imports between files, only the default
132
+ configuration for how downstream consumers can import from module subpaths.
133
+
134
+ ## License
135
+
136
+ MIT © [C. Lewis](https://ctjlewis.com)
@@ -0,0 +1,7 @@
1
+ export declare const bannerLog: (msg: string) => void;
2
+ /**
3
+ * Build TS to JS. This will contain incomplete specifiers like `./foo` which
4
+ * could mean many things, all of which is handled by the loader which will
5
+ * resolve them for us.
6
+ */
7
+ export declare const build: (dev?: boolean) => Promise<void>;
@@ -0,0 +1,3 @@
1
+ import{build as d}from"esbuild";import{existsSync as h,readFileSync as k,writeFileSync as T}from"fs";import{extname as w,resolve as l}from"path";import{readFile as x,rm as F}from"fs/promises";import a from"chalk";import O from"fast-glob";import{createDebugLogger as B,log as c}from"create-debug-logger";import{isTs as N,isTsxOrJsx as g}from"../../utils/index.js";import{emitTsDeclarations as j}from"./lib/emitTsDeclarations.js";import{normalizeImportSpecifiers as E}from"../normalize/index.js";import i from"ora";const y=t=>{c(a.bgBlue(a.white(` ${t} `)))},J=async(t=!1)=>{const n=B(J);t||y("Building for production.");const s=process.cwd(),S=l(s,"package.json"),b=await x(S,"utf-8"),m={absWorkingDir:s,outbase:"src",outdir:"dist",assetNames:"[name].js",logLevel:t?"debug":"error",charset:"utf8",format:"esm",target:"esnext",minify:!t,define:{PACKAGE_JSON:b}},f=l(s,"dist");n.log("Cleaning old output:",{distDir:f}),await F(f,{force:!0,recursive:!0});const r=O.sync("src/**/*",{cwd:s}).filter(e=>w(e)!==".d.ts").map(e=>l(e)),p=r.filter(e=>N.test(e)).filter(e=>!g.test(e));n.log("Compiling TS files:",{tsFiles:p}),await d({...m,entryPoints:p.filter(e=>!e.endsWith(".d.ts"))}),i("Built TS files.").succeed();const u=r.filter(e=>g.test(e));if(n.log("Compiling TSX files:",{tsxFiles:u}),await d({...m,entryPoints:u.filter(e=>!e.endsWith(".d.ts")),jsxFactory:"createElement",banner:{js:`import { createElement } from 'react';
2
+ `}}),i("Built TSX files.").succeed(),process.env.NO_REWRITES||(await E(),i("Normalized import specifiers.").succeed(),t)||process.env.NO_DECLARATIONS)return;y("Running post-build setup."),c(`Generating type declarations.
3
+ This might take a moment.`),j(r),i(`Generated delcarations for ${r.length} files.`).succeed();let o;h("dist/package.json")?o=JSON.parse(k("dist/package.json","utf-8")):o={},o.type="module",T("dist/package.json",JSON.stringify(o,null,2)),i('Forced "type": "module" in output.').succeed(),c(a.green("Build complete."))};export{y as bannerLog,J as build};
@@ -0,0 +1 @@
1
+ export declare const emitTsDeclarations: (files: string[]) => void;
@@ -0,0 +1,3 @@
1
+ import{TS_CONFIG as m}from"../../normalize/lib/typescriptApi.js";import a from"chalk";import{createDebugLogger as g}from"create-debug-logger";import t from"typescript";const f=o=>{const r=g(f),s=t.createProgram(o,{...m,declaration:!0,noEmit:!1,emitDeclarationOnly:!0}),i=s.emit();t.getPreEmitDiagnostics(s).concat(i.diagnostics).forEach(e=>{if(e.file){const{line:n,character:l}=t.getLineAndCharacterOfPosition(e.file,e.start??0),c=t.flattenDiagnosticMessageText(e.messageText,`
2
+ `);r.log(a.red(`${e.file.fileName} (${n+1},${l+1}): ${c}`))}else r.log(a.red(t.flattenDiagnosticMessageText(e.messageText,`
3
+ `)))})};export{f as emitTsDeclarations};
@@ -0,0 +1 @@
1
+ export declare const create: (name: string) => Promise<void>;
@@ -0,0 +1 @@
1
+ import{cp as p,readFile as d,writeFile as g}from"fs/promises";import{fileURLToPath as m,URL as u}from"url";import w from"chalk";import f from"ora";import{resolve as a}from"path";import{shell as n}from"await-shell";const S=async e=>{const i=process.cwd(),t=f(`Creating new module ${w.blueBright(e)}.`).start(),o=new u("../../../template",import.meta.url);await p(m(o),a(i,e),{recursive:!0});const s=a(i,e,"package.json"),c=await d(s,"utf-8"),r=JSON.parse(c);r.name=e,await g(s,JSON.stringify(r,null,2)),t.succeed("Project created."),t.start("Installing dependencies."),process.chdir(e);const l=["@tsmodule/tsmodule","typescript","ava","eslint","@typescript-eslint/eslint-plugin","@typescript-eslint/parser"];globalThis.SHELL_OPTIONS={stdio:["ignore","ignore","inherit"]},await n(`yarn add -D ${l.join(" ")}`),t.succeed("Dependencies installed."),t.start("Initializing git."),await n("git init"),t.succeed("Git initialized.")};export{S as create};
@@ -0,0 +1 @@
1
+ export declare const execute: () => void;
@@ -0,0 +1 @@
1
+ import{URL as s}from"url";import{spawn as n}from"child_process";const a=()=>{process.env.NODE_OPTIONS="--no-warnings";const e=import.meta.url,o=new s("../../../dist/loader/index.js",e),r=["--loader",o.href,...process.argv.slice(2)];n("node",r,{stdio:"inherit"}).on("exit",process.exit)};export{a as execute};
@@ -0,0 +1,19 @@
1
+ /**
2
+ * @fileoverview
3
+ * This module contains the logic for normalizing import specifiers. It must use
4
+ * fully-specified filepaths here, since the bootstrap script will compile it
5
+ * with esbuild and then use it to normalize emitted output.
6
+ */
7
+ /**
8
+ * Matches a complete import statement, including the import keyword, as well as
9
+ * dynamic imports, requires, and export statements.
10
+ */
11
+ export declare const generateImportPattern: (importSource: string) => RegExp;
12
+ /**
13
+ * Rewrite an import/export/require statement.
14
+ */
15
+ export declare const rewriteImportStatement: (importStatement: string, specifierToReplace: string, specifierReplacement: string) => string;
16
+ /**
17
+ * Rewrite imports in the emitted JS to ESM-compliant paths.
18
+ */
19
+ export declare const normalizeImportSpecifiers: (files?: string) => Promise<any>;
@@ -0,0 +1,2 @@
1
+ import{readFile as w,writeFile as $}from"fs/promises";import x from"fast-glob";import{pathToFileURL as E}from"url";import{resolve as y}from"path";import{createDebugLogger as g}from"create-debug-logger";import{getRewrittenSpecifiers as I}from"./lib/typescriptApi.js";const P=e=>{const r=`[^
2
+ \r;]*`,o=e.replace(".","\\.").replace("/","\\/"),s=`${r}["']${o}["']${r}`,t=`(import${r}from)`,i=`(import|require)${r}\\(`,n=`(export${r}from)`;return new RegExp(`(${t}|${i}|${n})${s}`,"g")},d=(e,r,o)=>{g(d).log("Rewriting import",{importStatement:e,specifierToReplace:r,specifierReplacement:o});const[,t]=e.split(/from|\(/),i=t.replace(r,o).trim();return e.replace(t,i)},R=async(e="dist/**/*.js")=>{const r=g(R),o=await x(e,{cwd:process.cwd()});r.log("Normalizing import/require specifiers:",{filesToNormalize:o});for(const s of o){const t=y(s),i=E(t).href,n=I(t);if(!n)return null;r.log("TypeScript API yielded specifiers to rewrite:",{rewrites:n});let p=await w(t,"utf8");r.group();for(const{specifierToReplace:c,specifierReplacement:a}of n){const u=P(c),l=p.match(u)??[];r.log("Replacing import statements.",{entryPointURL:i,specifierToReplace:c,specifierReplacement:a,importStatements:l});for(const m of l){r.group();const f=d(m,c,a);r.log("Performing specifier rewrite.",{entryPointURL:i,importStatement:m,rewrittenImportStatement:f}),p=p.replace(m,f),await $(t,p),r.log("Wrote output file.",{resolvedEntryPoint:t}),r.groupEnd()}}r.groupEnd()}};export{P as generateImportPattern,R as normalizeImportSpecifiers,d as rewriteImportStatement};
@@ -0,0 +1,13 @@
1
+ import ts from "typescript";
2
+ export declare const TS_CONFIG: ts.CompilerOptions;
3
+ export declare const compilerHost: ts.CompilerHost;
4
+ interface SpecifierReplacement {
5
+ specifierToReplace: string;
6
+ specifierReplacement: string;
7
+ }
8
+ /**
9
+ * Get the rewritten specifiers for a given module. Import/export specifiers
10
+ * will be resolved ahead-of-time by the TypeScript compiler and returned.
11
+ */
12
+ export declare const getRewrittenSpecifiers: (modulePath: string) => SpecifierReplacement[];
13
+ export {};
@@ -0,0 +1 @@
1
+ import{dirname as E,extname as v,relative as w}from"path/posix";import{createDebugLogger as N}from"create-debug-logger";import e from"typescript";const l={moduleResolution:e.ModuleResolutionKind.NodeJs,module:e.ModuleKind.ESNext,target:e.ScriptTarget.ESNext,esModuleInterop:!0,incremental:!1,noEmit:!0,rootDir:"src",outDir:"dist"},p=e.createCompilerHost(l),R=(t,o=process.cwd())=>{const{resolvedModule:r}=e.resolveModuleName(t,o,l,p);if(!r){const s=JSON.stringify({specifier:t,entryPoint:o},null,2);throw new Error(`Could not resolve module: ${s}`)}return r},x=(t,o)=>{const r=w(E(t),o);return r.startsWith(".")?r:`./${r}`},h=t=>{const o=N(h);o.log("Getting rewritten specifiers:",{modulePath:t});const{resolvedFileName:r}=R(t),s=p.getSourceFile(r,e.ScriptTarget.ESNext);if(!s)throw new Error(`Could not read source file: ${r}`);const{statements:d,fileName:u}=s,a=[];return d.forEach(n=>{const f=e.isExportDeclaration(n);if(!(e.isImportDeclaration(n)&&!n?.importClause?.isTypeOnly)&&!f)return;const{moduleSpecifier:c}=n;if(!c){if(f)return;throw new Error(`Could not find module specifier in: ${JSON.stringify(n)}`)}if(e.isStringLiteral(c)){const{text:i}=c;if(!i.startsWith(".")||v(i))return;o.log("Using TypeScript API to resolve specifier",{specifier:i});const{resolvedModule:m}=e.resolveModuleName(i,u,{...l,allowJs:!0,checkJs:!0},p);if(!m)throw new Error(`Could not resolve module: ${i}`);const{resolvedFileName:g}=m,S=x(u,g);a.push({specifierToReplace:i,specifierReplacement:S})}}),a};export{l as TS_CONFIG,p as compilerHost,h as getRewrittenSpecifiers};
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/index.js ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ var t="@tsmodule/tsmodule",r="module",a="8.1.0",s="tsmodule/tsmodule",d="TypeScript Module loader and compiler",m="MIT",c={tsmodule:"dist/index.js"},p={".":"./dist/loader/index.js","./*":"./dist/*/index.js","./package.json":"./package.json"},l="dist/types/index.d.ts",f=[{name:"C. Lewis",email:"ctj.lewis@icloud.com",url:"https://ctjlewis.com"}],u=["dist/","template/"],v={node:">=14"},g={bootstrap:"node bootstrap.js",prebuild:"yarn bootstrap",build:"node --no-warnings --loader ./dist/loader/index.js src/index.ts build",lint:"eslint --fix src",prepare:"yarn build",test:"ava --no-worker-threads"},S={"await-shell":"^2.7.0",chalk:"^5.0.0",commander:"^8.3.0","create-debug-logger":"^1.10.1",esbuild:"^0.14.0","fast-glob":"^3.2.10",ora:"^6.0.1",react:"^17.0.2",rollup:"^2.63.0","rollup-plugin-preserve-shebang":"^1.0.1",typescript:"^4.5.5"},w={"@types/node":"17.0.8","@types/react":"17.0.38","@typescript-eslint/eslint-plugin":"^5.9.1","@typescript-eslint/parser":"^5.9.1",ava:"^4.0.1",eslint:"^8.6.0"},C=["esm","loader","typescript","loader hook","require hook","experimental-loader"],b={files:["test/**/*.test.ts"],extensions:{ts:"module"},nodeArguments:["--no-warnings","--loader=@tsmodule/tsmodule"]},n={name:t,type:r,version:a,repository:s,description:d,license:m,bin:c,exports:p,types:l,contributors:f,files:u,engines:v,scripts:g,dependencies:S,devDependencies:w,keywords:C,ava:b};import{Command as A}from"commander";import{build as E}from"./commands/build/index.js";import{create as h}from"./commands/create/index.js";import{execute as x}from"./commands/execute/index.js";import{normalizeImportSpecifiers as y}from"./commands/normalize/index.js";const o=new A;o.command("execute <file>",{isDefault:!0}).option("--d, --dev","Enable development mode").description("Run the given TS program, analogous to `node <file>`.").action(x),o.command("build").option("-d, --dev","Build development version (default: production)").description("Builds TS files to output in dist/. (default: src/**/*.{ts,tsx})").action(async({dev:i})=>await E(i)),o.command("create <name>").description("Create a new project.").action(h),o.command("normalize [files]").description(`Rewrites import specifiers in files to ESM-compliant paths.
3
+ (default: dist/**/*.js)`).action(async({files:i})=>{await y(i)}),o.command("version").description("Print the current version.").action(()=>{console.log(typeof n=="undefined"?"Cannot read version in development mode.":`v${n.version}`)}),o.parse(process.argv);
@@ -0,0 +1,11 @@
1
+ import type { GetFormatHook as ModuleGetFormatHook, LoadHook as ModuleLoadHook, ResolveHook as ModuleResolveHook, TransformHook as ModuleTransformSourceHook } from "./types";
2
+ export declare const resolve: ModuleResolveHook;
3
+ export declare const load: ModuleLoadHook;
4
+ /**
5
+ * @deprecated As of Node 17.
6
+ */
7
+ export declare const getFormat: ModuleGetFormatHook;
8
+ /**
9
+ * @deprecated As of Node 17.
10
+ */
11
+ export declare const transformSource: ModuleTransformSourceHook;
@@ -0,0 +1 @@
1
+ import{extname as m,isAbsolute as U,join as F,normalize as E,resolve as S}from"path";import{fileURLToPath as w,pathToFileURL as v,URL as L}from"url";import{promises as H}from"fs";import{transform as h}from"esbuild";import{sep as M}from"path/posix";import{sep as T}from"path/win32";import{checkExtensions as k,checkTsExtensions as D,fileExists as b,isJs as G,isTs as y,MODULE_LOADERS as R}from"../utils/index.js";import{createDebugLogger as d}from"create-debug-logger";const N=async(o,r,t)=>{const{parentURL:s}=r,e=d(N);if(e.log("Resolving specifier:",{importedFromURL:s,specifier:o}),!o.startsWith(".")&&!U(o))return e.log("Using defaultResolve for named module:",{specifier:o}),t(o,r,t);const{href:l}=v(process.cwd()),{href:i}=new L(s||l);e.log("Finding import URL for",{specifier:o,baseURL:i});let n=o;o.startsWith("file://")||(U(o)?(e.log("Setting import URL to absolute specifier."),n=v(S(E(o))).href):(e.log("Setting import URL relative to baseURL."),n=new L(o,i).href),e.log("Resolved import URL:",{importedFileURL:n,importedFromURL:s}));const f=m(s??"").toLowerCase(),u=m(n).toLowerCase();if(e.log("Rewriting file extension:",{parentExtension:f,specifierExtension:u}),u){const a=n.substring(0,n.lastIndexOf(u));if(e.log("Re-resolving specifier:",{unresolvedSpecifier:a}),G.test(u)&&y.test(f)){const p=D(a);if(p)return e.log("Found JS import in TS:",{unresolvedSpecifier:a,resolvedTsSourceFile:p}),{url:p}}return b(a)?(e.log("Found file at unresolved specifier:",{unresolvedSpecifier:a}),{url:a}):t(o,r,t)}e.log("Resolving incomplete URL import to file:",{specifier:o});const c=k(n);if(c)return e.log("Resolved import URL to file:",{resolvedFile:c}),{url:c};const x=new L(F(n,"index")).href,g=k(x);return g?(e.log("Resolved import URL to index file:",{resolvedIndexFile:g}),{url:g}):t(o,r,t)},B=async(o,r,t)=>{const s=d(B);if(s.log("Loading source file:",{url:o}),!o.includes(T)&&!o.includes(M))return s.log("Using defaultLoad for named module:",{url:o}),t(o,r,t);const e=m(o),l=R[e];if(!l)return s.log("No loader found, using defaultLoad:",{url:o}),t(o,r,t);const i=w(o),n=await H.readFile(i),f=await h(n.toString(),{...l,sourcefile:i,format:"esm"});return{format:"module",source:f.code}},O=async(o,r,t)=>{const s=d(O);s.log("Getting format for source file:",{url:o});const e=m(o);return R[e]?{format:"module"}:(s.log("No loader found, using default format:",{url:o}),t(o,r,t))},j=async(o,r,t)=>{const s=d(j);s.log("Transforming source from context:",{context:r});const{url:e}=r,l=m(e),i=R[l];return i?{source:(await h(o.toString(),{...i,logLevel:"info",charset:"utf8",target:"esnext",sourcefile:r.url,format:r.format==="module"?"esm":"cjs"})).code}:(s.log("No loader found, using default transformer:",{url:e}),t(o,r,t))};export{O as getFormat,B as load,N as resolve,j as transformSource};
@@ -0,0 +1,22 @@
1
+ export declare type Promisable<T> = Promise<T> | T;
2
+ export declare type ModuleSource = string | SharedArrayBuffer | Uint8Array;
3
+ export declare type ModuleFormat = "builtin" | "commonjs" | "json" | "module" | "wasm";
4
+ export declare type ResolveHook = (specifier: string, context: {
5
+ conditions: string[];
6
+ parentURL?: string;
7
+ }, fallback: ResolveHook) => Promisable<{
8
+ url: string;
9
+ format?: ModuleFormat;
10
+ }>;
11
+ export declare type GetFormatHook = (url: string, context: object, fallback: GetFormatHook) => Promisable<{
12
+ format: ModuleFormat;
13
+ }>;
14
+ export declare type TransformHook = (source: ModuleSource, context: Record<"url" | "format", string>, fallback: TransformHook) => Promisable<{
15
+ source: ModuleSource;
16
+ }>;
17
+ export declare type LoadHook = (url: string, context: {
18
+ format?: ModuleFormat;
19
+ }, fallback: LoadHook) => Promisable<{
20
+ format: ModuleFormat;
21
+ source: ModuleSource;
22
+ }>;
File without changes
@@ -0,0 +1,3 @@
1
+ {
2
+ "type": "module"
3
+ }
@@ -0,0 +1,4 @@
1
+ declare global {
2
+ const PACKAGE_JSON: Record<string, unknown>;
3
+ }
4
+ export * from "../loader/types";
@@ -0,0 +1 @@
1
+ export*from"../loader/types.js";
@@ -0,0 +1,27 @@
1
+ export declare const DEVELOPMENT_MODE: boolean;
2
+ export declare const isTs: RegExp;
3
+ export declare const isJs: RegExp;
4
+ export declare const isTsxOrJsx: RegExp;
5
+ export declare const BASE_CONFIG: {
6
+ format: string;
7
+ charset: string;
8
+ sourcemap: string;
9
+ target: string;
10
+ minify: boolean;
11
+ };
12
+ export declare type ModuleLoaders = {
13
+ [extension: string]: {
14
+ [configKey: string]: unknown;
15
+ };
16
+ };
17
+ export declare const MODULE_LOADERS: ModuleLoaders;
18
+ export declare const POSSIBLE_EXTENSIONS: string[];
19
+ /**
20
+ * Force a Unix-like path.
21
+ */
22
+ export declare const normalizeSpecifier: (path: string) => string;
23
+ export declare const fileExists: (fileUrl: string) => string | void;
24
+ export declare const fileExistsAny: (fileUrls: string[]) => string | void;
25
+ export declare const checkTsExtensions: (specifier: string) => string | void;
26
+ export declare const checkJsExtension: (specifier: string) => string | void;
27
+ export declare const checkExtensions: (specifier: string) => string;
@@ -0,0 +1 @@
1
+ import{existsSync as i}from"fs";import{fileURLToPath as c}from"url";import{sep as p}from"path/posix";import{sep as x}from"path";const O=!1,S=/\.[mc]?tsx?(?=\?|$)/,h=/\.([mc])?js$/,L=/\.([mc])?[tj]sx$/,e={format:"esm",charset:"utf8",sourcemap:"inline",target:"node16",minify:!1},a={".mts":{...e,loader:"ts"},".jsx":{...e,loader:"jsx"},".tsx":{...e,loader:"tsx"},".cts":{...e,loader:"ts"},".ts":{...e,loader:"ts"},".json":{...e,loader:"json"}},n=Object.keys(a),M=s=>s.split(x).join(p),l=s=>{const t=c(s);if(i(t))return s},r=s=>{for(const t of s)if(l(t))return t},m=s=>{const t=n.filter(o=>o.includes("ts")).concat([".js"]);return r(t.map(o=>s+o))},f=s=>{const t=n.filter(o=>o.includes("js")).concat([".js"]);return r(t.map(o=>s+o))},y=s=>{const t=f(s);if(t)return t;const o=m(s);if(o)return o};export{e as BASE_CONFIG,O as DEVELOPMENT_MODE,a as MODULE_LOADERS,n as POSSIBLE_EXTENSIONS,y as checkExtensions,f as checkJsExtension,m as checkTsExtensions,l as fileExists,r as fileExistsAny,h as isJs,S as isTs,L as isTsxOrJsx,M as normalizeSpecifier};
package/package.json ADDED
@@ -0,0 +1,80 @@
1
+ {
2
+ "name": "@tsmodule/tsmodule",
3
+ "type": "module",
4
+ "version": "8.1.0",
5
+ "repository": "tsmodule/tsmodule",
6
+ "description": "TypeScript Module loader and compiler",
7
+ "license": "MIT",
8
+ "bin": {
9
+ "tsmodule": "dist/index.js"
10
+ },
11
+ "exports": {
12
+ ".": "./dist/loader/index.js",
13
+ "./*": "./dist/*/index.js",
14
+ "./package.json": "./package.json"
15
+ },
16
+ "types": "dist/types/index.d.ts",
17
+ "contributors": [
18
+ {
19
+ "name": "C. Lewis",
20
+ "email": "ctj.lewis@icloud.com",
21
+ "url": "https://ctjlewis.com"
22
+ }
23
+ ],
24
+ "files": [
25
+ "dist/",
26
+ "template/"
27
+ ],
28
+ "engines": {
29
+ "node": ">=14"
30
+ },
31
+ "scripts": {
32
+ "bootstrap": "node bootstrap.js",
33
+ "prebuild": "yarn bootstrap",
34
+ "build": "node --no-warnings --loader ./dist/loader/index.js src/index.ts build",
35
+ "lint": "eslint --fix src",
36
+ "prepare": "yarn build",
37
+ "test": "ava --no-worker-threads"
38
+ },
39
+ "dependencies": {
40
+ "await-shell": "^2.7.0",
41
+ "chalk": "^5.0.0",
42
+ "commander": "^8.3.0",
43
+ "create-debug-logger": "^1.10.1",
44
+ "esbuild": "^0.14.0",
45
+ "fast-glob": "^3.2.10",
46
+ "ora": "^6.0.1",
47
+ "react": "^17.0.2",
48
+ "rollup": "^2.63.0",
49
+ "rollup-plugin-preserve-shebang": "^1.0.1",
50
+ "typescript": "^4.5.5"
51
+ },
52
+ "devDependencies": {
53
+ "@types/node": "17.0.8",
54
+ "@types/react": "17.0.38",
55
+ "@typescript-eslint/eslint-plugin": "^5.9.1",
56
+ "@typescript-eslint/parser": "^5.9.1",
57
+ "ava": "^4.0.1",
58
+ "eslint": "^8.6.0"
59
+ },
60
+ "keywords": [
61
+ "esm",
62
+ "loader",
63
+ "typescript",
64
+ "loader hook",
65
+ "require hook",
66
+ "experimental-loader"
67
+ ],
68
+ "ava": {
69
+ "files": [
70
+ "test/**/*.test.ts"
71
+ ],
72
+ "extensions": {
73
+ "ts": "module"
74
+ },
75
+ "nodeArguments": [
76
+ "--no-warnings",
77
+ "--loader=@tsmodule/tsmodule"
78
+ ]
79
+ }
80
+ }
@@ -0,0 +1,52 @@
1
+ {
2
+ "extends": [
3
+ "plugin:@typescript-eslint/recommended"
4
+ ],
5
+ "parser": "@typescript-eslint/parser",
6
+ "plugins": ["@typescript-eslint"],
7
+ "rules": {
8
+
9
+ "no-console": "error",
10
+ "no-trailing-spaces": "error",
11
+ "max-len": [1, 80, 2, {
12
+ "ignorePattern": "^import\\s.+\\sfrom\\s.+;$",
13
+ "ignoreUrls": true,
14
+ "ignoreStrings": true,
15
+ "ignoreTemplateLiterals": true,
16
+ "ignoreRegExpLiterals": true
17
+ }],
18
+
19
+ "@typescript-eslint/type-annotation-spacing": ["error"],
20
+
21
+ "@typescript-eslint/ban-ts-comment": [
22
+ "error",
23
+ {
24
+ "ts-nocheck": "allow-with-description",
25
+ "ts-ignore": "allow-with-description"
26
+ }
27
+ ],
28
+
29
+ "indent": "off",
30
+ "@typescript-eslint/indent": ["error", 2],
31
+
32
+ "semi": "off",
33
+ "@typescript-eslint/semi": ["error", "always"],
34
+
35
+ "quotes": "off",
36
+ "@typescript-eslint/quotes": ["error", "double"],
37
+
38
+ "object-curly-spacing": "off",
39
+ "@typescript-eslint/object-curly-spacing": ["error", "always"],
40
+
41
+ "sort-imports": [
42
+ "warn",
43
+ {
44
+ "ignoreCase": false,
45
+ "ignoreDeclarationSort": false,
46
+ "ignoreMemberSort": true,
47
+ "memberSyntaxSortOrder": ["none", "all", "multiple", "single"],
48
+ "allowSeparatedGroups": true
49
+ }
50
+ ]
51
+ }
52
+ }
@@ -0,0 +1,30 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - '**'
7
+ pull_request:
8
+ branches:
9
+ - '**'
10
+
11
+ jobs:
12
+ test:
13
+ name: Node.js v${{ matrix.nodejs }} (${{ matrix.os }})
14
+ runs-on: ${{ matrix.os }}
15
+ timeout-minutes: 5
16
+ strategy:
17
+ matrix:
18
+ nodejs: [16]
19
+ os: [ubuntu-latest, windows-latest, macos-latest]
20
+ steps:
21
+ - uses: actions/checkout@v2
22
+ - uses: actions/setup-node@v2
23
+ with:
24
+ node-version: ${{ matrix.nodejs }}
25
+
26
+ - name: Install and link
27
+ run: yarn install --frozen-lockfile && yarn build
28
+
29
+ - name: Test
30
+ run: yarn test
@@ -0,0 +1,10 @@
1
+ node_modules
2
+
3
+ # Potential Firebase / GCP credentials.
4
+ service-account.json
5
+
6
+ # Emitted output.
7
+ dist/
8
+
9
+ # Incremental TS build info.
10
+ *.tsbuildinfo
@@ -0,0 +1,5 @@
1
+ This is a TS module. Build it with tsmodule via:
2
+
3
+ ```shell
4
+ yarn build
5
+ ```
@@ -0,0 +1,32 @@
1
+ {
2
+ "name": "template",
3
+ "type": "module",
4
+ "version": "0.0.1",
5
+ "license": "MIT",
6
+ "types": "dist/index.d.ts",
7
+ "files": [
8
+ "dist"
9
+ ],
10
+ "exports": {
11
+ "./package.json": "./package.json",
12
+ ".": "./dist/index.js",
13
+ "./*": "./dist/*/index.js"
14
+ },
15
+ "scripts": {
16
+ "build": "tsmodule build",
17
+ "test": "ava",
18
+ "lint": "eslint src --fix"
19
+ },
20
+ "ava": {
21
+ "files": [
22
+ "test/**/*.test.ts"
23
+ ],
24
+ "extensions": {
25
+ "ts": "module"
26
+ },
27
+ "nodeArguments": [
28
+ "--no-warnings",
29
+ "--loader=@tsmodule/tsmodule"
30
+ ]
31
+ }
32
+ }
@@ -0,0 +1,4 @@
1
+ export const helloWorld = () => {
2
+ // eslint-disable-next-line no-console
3
+ console.log("Hello World!");
4
+ };
@@ -0,0 +1,7 @@
1
+ import test from "ava";
2
+
3
+ test("two plus two should equal four", (t) => {
4
+ if (2 + 2 === 4) {
5
+ t.pass();
6
+ }
7
+ });
@@ -0,0 +1,41 @@
1
+ {
2
+ "include": [
3
+ "*env.d.ts",
4
+ "src/**/*"
5
+ ],
6
+ "exclude": [
7
+ "node_modules",
8
+ "test/**"
9
+ ],
10
+ "compilerOptions": {
11
+ "moduleResolution": "Node",
12
+ "target": "ESNext",
13
+ "module": "ESNext",
14
+ "lib": [
15
+ "DOM",
16
+ "DOM.Iterable",
17
+ "ESNext"
18
+ ],
19
+ "jsx": "preserve",
20
+ "rootDir": "src",
21
+ "outDir": "dist",
22
+ "allowJs": true,
23
+ "importHelpers": true,
24
+ "esModuleInterop": true,
25
+ "allowSyntheticDefaultImports": true,
26
+ "strict": true,
27
+ "noUnusedLocals": true,
28
+ "noUnusedParameters": true,
29
+ "noImplicitReturns": true,
30
+ "noFallthroughCasesInSwitch": true,
31
+ "skipLibCheck": true,
32
+ "resolveJsonModule": true,
33
+ "declaration": true,
34
+ "sourceMap": true,
35
+ "checkJs": true,
36
+ "noEmit": false,
37
+ "forceConsistentCasingInFileNames": true,
38
+ "isolatedModules": true,
39
+ "incremental": false
40
+ }
41
+ }