├── .modularignore ├── .husky ├── .gitignore └── pre-commit ├── docs ├── CNAME ├── concepts │ ├── index.md │ └── versioning.md ├── releases │ ├── index.md │ ├── 3.6.x.md │ ├── 3.3.x.md │ └── 3.5.x.md ├── how-to │ ├── index.md │ └── rename-package.md ├── components │ └── index.md ├── commands │ ├── index.md │ ├── workspace.md │ ├── check.md │ └── serve.md ├── esm-views │ └── index.md └── img │ └── modular-hero.svg ├── packages ├── modular-types │ ├── .gitignore │ └── package.json ├── remote-view │ ├── .gitignore │ ├── src │ │ ├── utils │ │ │ ├── symbol.ts │ │ │ ├── remote-view-error.ts │ │ │ └── dynamically-import.tsx │ │ ├── components │ │ │ ├── index.ts │ │ │ ├── remote-view.tsx │ │ │ ├── default-remote-view-error-fallback.tsx │ │ │ └── default-unknown-error-fallback.tsx │ │ ├── index.ts │ │ ├── context.ts │ │ ├── types.ts │ │ ├── __tests__ │ │ │ ├── serve.js │ │ │ ├── default-unknown-error-fallback.test.tsx │ │ │ └── default-remote-view-error-fallback.test.tsx │ │ └── hooks │ │ │ └── useRemoteView.tsx │ ├── README.md │ ├── CONTRIBUTING.md │ ├── CHANGELOG.md │ └── package.json ├── modular-scripts │ ├── .npmignore │ ├── src │ │ ├── __tests__ │ │ │ ├── esbuild-scripts │ │ │ │ └── __fixtures__ │ │ │ │ │ ├── module-scope │ │ │ │ │ ├── src │ │ │ │ │ │ └── index.tsx │ │ │ │ │ └── foo.ts │ │ │ │ │ ├── svgr-dataurl │ │ │ │ │ ├── index.css │ │ │ │ │ ├── logo.svg │ │ │ │ │ └── index.tsx │ │ │ │ │ ├── worker-plugin │ │ │ │ │ ├── alive.worker.ts │ │ │ │ │ └── index.ts │ │ │ │ │ ├── svgr-url │ │ │ │ │ ├── logo.svg │ │ │ │ │ └── index.tsx │ │ │ │ │ └── svgr-component │ │ │ │ │ ├── logo.svg │ │ │ │ │ └── index.tsx │ │ │ ├── __fixtures__ │ │ │ │ ├── packages │ │ │ │ │ ├── sample-library-package │ │ │ │ │ │ └── index.ts │ │ │ │ │ ├── sample-async-package │ │ │ │ │ │ ├── index.ts │ │ │ │ │ │ └── runAsync.ts │ │ │ │ │ └── sample-depending-package │ │ │ │ │ │ └── index.ts │ │ │ │ ├── lint │ │ │ │ │ ├── InvalidJSX.jsx │ │ │ │ │ ├── InvalidJS.js │ │ │ │ │ ├── InvalidTS.ts │ │ │ │ │ └── InvalidTSX.tsx │ │ │ │ ├── test │ │ │ │ │ ├── ValidTest.test.ts │ │ │ │ │ └── InvalidTest.test.ts │ │ │ │ └── typecheck │ │ │ │ │ └── InvalidTyping.ts │ │ │ ├── TestView.test-tsx │ │ │ ├── TestEsmView.test-tsx │ │ │ ├── TestViewPackages.test-tsx │ │ │ ├── utils │ │ │ │ ├── getWorkspaceInfo.test.ts │ │ │ │ └── formatPath.test.ts │ │ │ ├── __snapshots__ │ │ │ │ ├── app.node-env.test.ts.snap │ │ │ │ └── build.test.ts.snap │ │ │ ├── memoize.test.ts │ │ │ ├── TestApp.test-tsx │ │ │ └── modularRoot.test.ts │ │ ├── build-scripts │ │ │ ├── webpack-scripts │ │ │ │ ├── utils │ │ │ │ │ ├── refreshOverlayInterop.ts │ │ │ │ │ ├── ignoredFiles.ts │ │ │ │ │ └── redirectServedPathMiddleware.ts │ │ │ │ └── plugins │ │ │ │ │ └── WatchMissingNodeModulesPlugin.js │ │ │ ├── esbuild-scripts │ │ │ │ ├── utils │ │ │ │ │ ├── formatPath.ts │ │ │ │ │ ├── formatError.ts │ │ │ │ │ └── absoluteSourceMapsMiddleware.ts │ │ │ │ └── start │ │ │ │ │ ├── plugins │ │ │ │ │ ├── metafileReporter.ts │ │ │ │ │ └── firstCompile.ts │ │ │ │ │ └── utils │ │ │ │ │ └── getHost.ts │ │ │ └── common-scripts │ │ │ │ └── errorOverlayMiddleware.ts │ │ ├── utils │ │ │ ├── isReactNewApi.ts │ │ │ ├── memoize.ts │ │ │ ├── getLocation.ts │ │ │ ├── execAsync.ts │ │ │ ├── getAllFiles.ts │ │ │ ├── getRelativeLocation.ts │ │ │ ├── checkBrowsers.ts │ │ │ ├── checkRequiredFiles.ts │ │ │ ├── getPrefixedLogger.ts │ │ │ ├── resolveAsBin.ts │ │ │ ├── reportTSDiagnostics.ts │ │ │ ├── actionPreflightCheck.ts │ │ │ ├── LineFilterOutStream.ts │ │ │ └── getAllWorkspaces.ts │ │ └── analyze.ts │ ├── types │ │ ├── package │ │ │ └── packagejson │ │ ├── view │ │ │ └── packagejson │ │ └── esm-view │ │ │ └── packagejson │ ├── tsconfig.build.json │ ├── jest-runner-eslint │ │ └── index.js │ └── tsconfig.json ├── create-modular-react-app │ ├── .npmignore │ ├── .gitignore │ ├── template │ │ ├── yarnrc │ │ ├── .prettierignore │ │ ├── modular │ │ │ ├── setupEnvironment.ts │ │ │ └── setupTests.ts │ │ ├── tsconfig.json │ │ ├── .vscode │ │ │ ├── extensions.json │ │ │ ├── settings.json │ │ │ └── launch.json │ │ ├── .editorconfig │ │ ├── gitignore │ │ ├── .eslintignore │ │ └── packages │ │ │ └── README.md │ ├── README.md │ └── package.json ├── modular-template-app │ ├── src │ │ ├── react-app-env.d.ts │ │ ├── index.tsx │ │ ├── __tests__ │ │ │ └── App.test.tsx │ │ ├── index.css │ │ ├── App.tsx │ │ └── App.css │ ├── public │ │ ├── robots.txt │ │ ├── favicon.ico │ │ ├── logo192.png │ │ ├── logo512.png │ │ └── manifest.json │ └── package.json ├── modular-template-node-env-app │ ├── src │ │ ├── index.tsx │ │ └── react-app-env.d.ts │ ├── package.json │ └── CHANGELOG.md ├── modular-template-esm-view │ ├── src │ │ ├── react-app-env.d.ts │ │ ├── __tests__ │ │ │ └── EsmView.test.tsx │ │ ├── index.tsx │ │ └── EsmView.css │ └── package.json ├── modular-template-package │ ├── src │ │ ├── index.ts │ │ └── __tests__ │ │ │ └── index.test.ts │ └── package.json ├── modular-template-source │ ├── src │ │ ├── index.ts │ │ └── __tests__ │ │ │ └── index.test.ts │ ├── package.json │ ├── CHANGELOG.md │ └── README.md ├── tree-view-for-tests │ ├── src │ │ ├── ascii-tree.d.ts │ │ └── __tests__ │ │ │ └── tree.test.ts │ ├── package.json │ ├── CHANGELOG.md │ └── README.md ├── workspace-resolver │ ├── src │ │ └── index.ts │ ├── tsconfig.json │ └── package.json ├── modular-template-view │ ├── src │ │ ├── index.tsx │ │ └── __tests__ │ │ │ └── index.test.tsx │ └── package.json ├── remote-view-demos │ ├── src │ │ └── examples │ │ │ ├── index.ts │ │ │ └── my-error-boundary.tsx │ ├── package.json │ └── README.md └── eslint-config-modular-app │ ├── README.md │ ├── base.js │ └── recommended.js ├── README.md ├── .yarnrc ├── __fixtures__ ├── ghost-testing │ ├── .gitignore │ ├── .yarnrc │ ├── README.md │ ├── packages │ │ ├── README.md │ │ ├── b │ │ │ ├── src │ │ │ │ ├── index.ts │ │ │ │ └── __tests__ │ │ │ │ │ ├── b-dummy.ts │ │ │ │ │ ├── b.test.ts │ │ │ │ │ └── utils │ │ │ │ │ └── b-nested.test.ts │ │ │ └── package.json │ │ ├── c │ │ │ ├── src │ │ │ │ ├── index.ts │ │ │ │ └── __tests__ │ │ │ │ │ ├── c.test.ts │ │ │ │ │ └── utils │ │ │ │ │ └── c-nested.test.ts │ │ │ ├── c-dummy.ts │ │ │ └── package.json │ │ ├── d │ │ │ ├── src │ │ │ │ ├── index.ts │ │ │ │ └── __tests__ │ │ │ │ │ ├── d-dummy.ts │ │ │ │ │ ├── d.test.ts │ │ │ │ │ └── utils │ │ │ │ │ └── d-nested.test.ts │ │ │ └── package.json │ │ ├── e │ │ │ ├── src │ │ │ │ ├── index.ts │ │ │ │ └── __tests__ │ │ │ │ │ ├── e-dummy.ts │ │ │ │ │ ├── e.test.ts │ │ │ │ │ └── utils │ │ │ │ │ └── e-nested.test.ts │ │ │ └── package.json │ │ └── a │ │ │ ├── src │ │ │ ├── index.ts │ │ │ └── __tests__ │ │ │ │ ├── a.test.ts │ │ │ │ └── utils │ │ │ │ └── a-nested.test.ts │ │ │ ├── a-dummy.ts │ │ │ └── package.json │ ├── tsconfig.json │ └── modular │ │ └── setupTests.ts ├── selective-lint │ ├── .gitignore │ ├── .yarnrc │ ├── README.md │ ├── packages │ │ ├── README.md │ │ ├── beta-lint │ │ │ ├── src │ │ │ │ └── index.ts │ │ │ └── package.json │ │ ├── delta-lint │ │ │ ├── src │ │ │ │ └── index.ts │ │ │ └── package.json │ │ ├── epsilon-lint │ │ │ ├── src │ │ │ │ └── index.ts │ │ │ └── package.json │ │ ├── gamma-lint │ │ │ ├── src │ │ │ │ └── index.ts │ │ │ └── package.json │ │ └── alpha-lint │ │ │ ├── src │ │ │ └── index.ts │ │ │ └── package.json │ ├── tsconfig.json │ └── modular │ │ └── setupTests.ts ├── source-type │ ├── .yarnrc │ ├── .prettierignore │ ├── README.md │ ├── modular │ │ ├── setupEnvironment.ts │ │ └── setupTests.ts │ ├── packages │ │ ├── a │ │ │ ├── src │ │ │ │ └── index.ts │ │ │ └── package.json │ │ ├── b │ │ │ ├── src │ │ │ │ └── index.ts │ │ │ └── package.json │ │ ├── c │ │ │ ├── src │ │ │ │ └── index.ts │ │ │ └── package.json │ │ ├── d │ │ │ ├── src │ │ │ │ └── index.ts │ │ │ └── package.json │ │ └── e │ │ │ ├── src │ │ │ └── index.ts │ │ │ └── package.json │ ├── tsconfig.json │ ├── .editorconfig │ ├── .gitignore │ └── .eslintignore ├── ghost-building │ ├── .yarnrc │ ├── .prettierignore │ ├── README.md │ ├── modular │ │ ├── setupEnvironment.ts │ │ └── setupTests.ts │ ├── packages │ │ ├── a │ │ │ ├── src │ │ │ │ └── index.ts │ │ │ └── package.json │ │ ├── b │ │ │ ├── src │ │ │ │ └── index.ts │ │ │ └── package.json │ │ ├── c │ │ │ ├── src │ │ │ │ └── index.ts │ │ │ └── package.json │ │ ├── d │ │ │ ├── src │ │ │ │ └── index.ts │ │ │ └── package.json │ │ ├── e │ │ │ ├── src │ │ │ │ └── index.ts │ │ │ └── package.json │ │ └── f │ │ │ ├── src │ │ │ └── index.ts │ │ │ └── package.json │ ├── tsconfig.json │ ├── .editorconfig │ ├── .gitignore │ └── .eslintignore ├── non-modular │ ├── packages │ │ ├── non-modular-buildable │ │ │ ├── .gitignore │ │ │ ├── src │ │ │ │ ├── index.ts │ │ │ │ └── __tests__ │ │ │ │ │ └── index.test.ts │ │ │ ├── tsconfig.json │ │ │ └── package.json │ │ ├── non-modular-lintable │ │ │ ├── .gitignore │ │ │ ├── src │ │ │ │ ├── index.ts │ │ │ │ └── __tests__ │ │ │ │ │ └── index.test.ts │ │ │ ├── package.json │ │ │ └── tsconfig.json │ │ ├── non-modular-testable │ │ │ ├── .gitignore │ │ │ ├── src │ │ │ │ ├── index.ts │ │ │ │ └── __tests__ │ │ │ │ │ └── index.test.ts │ │ │ ├── package.json │ │ │ └── tsconfig.json │ │ ├── non-modular-typecheckable │ │ │ ├── .gitignore │ │ │ ├── src │ │ │ │ ├── index.ts │ │ │ │ └── __tests__ │ │ │ │ │ └── index.test.ts │ │ │ ├── tsconfig.json │ │ │ └── package.json │ │ ├── non-modular-non-buildable-non-testable │ │ │ ├── .gitignore │ │ │ ├── src │ │ │ │ ├── index.ts │ │ │ │ └── __tests__ │ │ │ │ │ └── index.test.ts │ │ │ ├── package.json │ │ │ └── tsconfig.json │ │ ├── app │ │ │ ├── tsconfig.json │ │ │ ├── src │ │ │ │ ├── react-app-env.d.ts │ │ │ │ ├── index.tsx │ │ │ │ ├── __tests__ │ │ │ │ │ └── App.test.tsx │ │ │ │ ├── App.tsx │ │ │ │ └── index.css │ │ │ └── package.json │ │ └── README.md │ ├── modular │ │ ├── setupEnvironment.ts │ │ └── setupTests.ts │ └── tsconfig.json ├── remote-view │ └── packages │ │ ├── view1 │ │ ├── README.md │ │ ├── src │ │ │ ├── index.tsx │ │ │ ├── __tests__ │ │ │ │ └── index.test.tsx │ │ │ └── index.css │ │ └── package.json │ │ ├── view2 │ │ ├── README.md │ │ ├── src │ │ │ ├── index.tsx │ │ │ └── __tests__ │ │ │ │ └── index.test.tsx │ │ └── package.json │ │ ├── package.json │ │ ├── esm-view-card │ │ ├── package.json │ │ └── src │ │ │ └── index.tsx │ │ └── esm-view-list │ │ ├── package.json │ │ └── src │ │ └── index.tsx ├── templates │ ├── modular-template-app │ │ ├── CHANGELOG.md │ │ ├── README.md │ │ ├── package.json │ │ └── src │ │ │ ├── __tests__ │ │ │ └── App.test.tsx │ │ │ └── App.tsx │ ├── modular-template-filter │ │ ├── CHANGELOG.md │ │ ├── README.md │ │ ├── src │ │ │ ├── index.tsx │ │ │ └── __tests__ │ │ │ │ └── filter.test.ts │ │ └── package.json │ ├── modular-template-no-filter │ │ ├── CHANGELOG.md │ │ ├── README.md │ │ ├── public │ │ │ └── robots.txt │ │ ├── src │ │ │ ├── index.tsx │ │ │ └── __tests__ │ │ │ │ └── no-filter.test.ts │ │ └── package.json │ └── modular-template-non-modular │ │ ├── CHANGELOG.md │ │ ├── src │ │ └── index.ts │ │ ├── README.md │ │ └── package.json ├── custom-workspace-root │ ├── packages │ │ └── README.md │ ├── apps │ │ ├── app │ │ │ ├── tsconfig.json │ │ │ ├── src │ │ │ │ ├── react-app-env.d.ts │ │ │ │ ├── index.tsx │ │ │ │ ├── __tests__ │ │ │ │ │ └── App.test.tsx │ │ │ │ ├── index.css │ │ │ │ ├── App.tsx │ │ │ │ └── App.css │ │ │ ├── public │ │ │ │ ├── robots.txt │ │ │ │ ├── favicon.ico │ │ │ │ ├── logo192.png │ │ │ │ ├── logo512.png │ │ │ │ └── manifest.json │ │ │ └── package.json │ │ └── alpha │ │ │ ├── src │ │ │ ├── index.ts │ │ │ └── __tests__ │ │ │ │ └── index.test.ts │ │ │ └── package.json │ ├── modular │ │ ├── setupEnvironment.ts │ │ └── setupTests.ts │ └── tsconfig.json ├── test-config │ ├── esbuild-config.js │ └── webpack-config.js ├── selective-typecheck-example │ └── packages │ │ ├── esbuild-app │ │ ├── .modular.js │ │ ├── package.json │ │ └── src │ │ │ └── App.tsx │ │ ├── webpack-app │ │ ├── package.json │ │ └── src │ │ │ └── App.tsx │ │ └── common-module │ │ ├── package.json │ │ └── src │ │ └── index.ts ├── verifiable-project │ ├── packages │ │ ├── package-three │ │ │ └── package.json │ │ ├── package-one │ │ │ └── package.json │ │ ├── package-two │ │ │ └── package.json │ │ └── app-one │ │ │ └── package.json │ ├── other-packages │ │ └── package-four │ │ │ └── package.json │ └── package.json ├── resolve-workspace │ ├── non-modular-workspace-1 │ │ ├── packages │ │ │ ├── package-extraneous-1 │ │ │ │ └── package.json │ │ │ ├── package-one │ │ │ │ └── package.json │ │ │ ├── package-extraneous-3 │ │ │ │ └── package.json │ │ │ ├── package-extraneous-2 │ │ │ │ └── package.json │ │ │ └── app-one │ │ │ │ └── package.json │ │ └── package.json │ ├── clean-workspace-1 │ │ ├── packages │ │ │ ├── package-one │ │ │ │ └── package.json │ │ │ ├── package-two │ │ │ │ └── package.json │ │ │ └── app-one │ │ │ │ └── package.json │ │ └── package.json │ ├── clean-workspace-2 │ │ ├── packages │ │ │ ├── package-one │ │ │ │ └── package.json │ │ │ ├── package-two │ │ │ │ └── package.json │ │ │ └── app-one │ │ │ │ └── package.json │ │ └── package.json │ ├── clean-workspace-3 │ │ ├── packages │ │ │ ├── package-one │ │ │ │ └── package.json │ │ │ ├── package-two │ │ │ │ └── package.json │ │ │ ├── package-four │ │ │ │ └── package.json │ │ │ ├── package-three │ │ │ │ └── package.json │ │ │ └── app-one │ │ │ │ └── package.json │ │ └── package.json │ ├── invalid-workspace-1 │ │ ├── packages │ │ │ ├── package-one │ │ │ │ └── package.json │ │ │ ├── package-two │ │ │ │ └── package.json │ │ │ └── app-one │ │ │ │ └── package.json │ │ └── package.json │ ├── invalid-workspace-2 │ │ ├── packages │ │ │ ├── package-one │ │ │ │ └── package.json │ │ │ ├── package-two │ │ │ │ └── package.json │ │ │ └── app-one │ │ │ │ └── package.json │ │ └── package.json │ ├── invalid-workspace-3 │ │ ├── packages │ │ │ ├── package-one │ │ │ │ └── package.json │ │ │ ├── package-two │ │ │ │ └── package.json │ │ │ └── app-one │ │ │ │ └── package.json │ │ └── package.json │ ├── invalid-workspace-4 │ │ ├── packages │ │ │ ├── package-one │ │ │ │ └── package.json │ │ │ ├── package-two │ │ │ │ └── package.json │ │ │ └── app-one │ │ │ │ └── package.json │ │ └── package.json │ ├── invalid-workspace-5 │ │ ├── packages │ │ │ ├── package-one │ │ │ │ └── package.json │ │ │ ├── package-two │ │ │ │ └── package.json │ │ │ └── app-one │ │ │ │ └── package.json │ │ └── package.json │ └── mismatched-dependency │ │ ├── packages │ │ ├── package-one │ │ │ └── package.json │ │ ├── package-two │ │ │ └── package.json │ │ └── app-one │ │ │ └── package.json │ │ └── package.json └── remote-view-fake-cdn │ ├── index.html │ ├── view1 │ ├── index.html │ ├── static │ │ ├── css │ │ │ ├── main.1115b39e.css │ │ │ └── main.1115b39e.css.map │ │ └── js │ │ │ └── _trampoline.js │ ├── asset-manifest.json │ └── package.json │ ├── esm-view-card │ ├── index.html │ ├── static │ │ └── js │ │ │ ├── _trampoline.js │ │ │ └── main.5a34a408.js │ └── package.json │ ├── esm-view-list │ ├── index.html │ ├── static │ │ └── js │ │ │ └── _trampoline.js │ └── package.json │ ├── react@17.0.2.js │ ├── view2 │ ├── asset-manifest.json │ ├── index.html │ ├── static │ │ └── js │ │ │ └── _trampoline.js │ └── package.json │ ├── react-dom@17.0.2.js │ └── static │ └── js │ └── _trampoline.js ├── .vscode ├── settings.json ├── extensions.json └── launch.json ├── .prettierrc ├── integration-test-scripts ├── startVerdaccio.sh ├── setupVerdaccio.sh └── verdaccio-config.yaml ├── .prettierignore ├── modular └── setupTests.ts ├── tsconfig.json ├── .editorconfig ├── .changeset ├── config.json └── README.md ├── patches ├── detect-port-alt+1.1.6.patch └── react-error-overlay+6.0.9.patch ├── babel.config.js ├── .github ├── workflows │ ├── validate.yml │ ├── release.yml │ └── static.yml └── dependabot.yml ├── scripts ├── validate-lockfile.js ├── extend-publish-config.js └── remote-view-prepublish.js ├── .eslintignore └── .gitignore /.modularignore: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.husky/.gitignore: -------------------------------------------------------------------------------- 1 | _ 2 | -------------------------------------------------------------------------------- /docs/CNAME: -------------------------------------------------------------------------------- 1 | modular.js.org -------------------------------------------------------------------------------- /packages/modular-types/.gitignore: -------------------------------------------------------------------------------- 1 | dist -------------------------------------------------------------------------------- /packages/remote-view/.gitignore: -------------------------------------------------------------------------------- 1 | dist -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | packages/modular-scripts/README.md -------------------------------------------------------------------------------- /.yarnrc: -------------------------------------------------------------------------------- 1 | registry "https://registry.yarnpkg.com" -------------------------------------------------------------------------------- /packages/modular-scripts/.npmignore: -------------------------------------------------------------------------------- 1 | /src 2 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | yarn lint-staged -------------------------------------------------------------------------------- /__fixtures__/ghost-testing/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /__fixtures__/selective-lint/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /packages/create-modular-react-app/.npmignore: -------------------------------------------------------------------------------- 1 | src 2 | -------------------------------------------------------------------------------- /__fixtures__/source-type/.yarnrc: -------------------------------------------------------------------------------- 1 | disable-self-update-check true -------------------------------------------------------------------------------- /packages/create-modular-react-app/.gitignore: -------------------------------------------------------------------------------- 1 | new-modular-app -------------------------------------------------------------------------------- /__fixtures__/ghost-building/.yarnrc: -------------------------------------------------------------------------------- 1 | disable-self-update-check true -------------------------------------------------------------------------------- /__fixtures__/ghost-testing/.yarnrc: -------------------------------------------------------------------------------- 1 | disable-self-update-check true -------------------------------------------------------------------------------- /__fixtures__/selective-lint/.yarnrc: -------------------------------------------------------------------------------- 1 | disable-self-update-check true -------------------------------------------------------------------------------- /__fixtures__/non-modular/packages/non-modular-buildable/.gitignore: -------------------------------------------------------------------------------- 1 | dist -------------------------------------------------------------------------------- /__fixtures__/non-modular/packages/non-modular-lintable/.gitignore: -------------------------------------------------------------------------------- 1 | dist -------------------------------------------------------------------------------- /__fixtures__/non-modular/packages/non-modular-testable/.gitignore: -------------------------------------------------------------------------------- 1 | dist -------------------------------------------------------------------------------- /__fixtures__/remote-view/packages/view1/README.md: -------------------------------------------------------------------------------- 1 | This is a component 2 | -------------------------------------------------------------------------------- /__fixtures__/remote-view/packages/view2/README.md: -------------------------------------------------------------------------------- 1 | This is a component 2 | -------------------------------------------------------------------------------- /__fixtures__/templates/modular-template-app/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Test File 2 | -------------------------------------------------------------------------------- /__fixtures__/ghost-building/.prettierignore: -------------------------------------------------------------------------------- 1 | /dist 2 | /packages/**/public 3 | -------------------------------------------------------------------------------- /__fixtures__/non-modular/packages/non-modular-typecheckable/.gitignore: -------------------------------------------------------------------------------- 1 | dist -------------------------------------------------------------------------------- /__fixtures__/source-type/.prettierignore: -------------------------------------------------------------------------------- 1 | /dist 2 | /packages/**/public 3 | -------------------------------------------------------------------------------- /__fixtures__/templates/modular-template-filter/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Test File 2 | -------------------------------------------------------------------------------- /__fixtures__/templates/modular-template-no-filter/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Test File 2 | -------------------------------------------------------------------------------- /__fixtures__/templates/modular-template-non-modular/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Test File 2 | -------------------------------------------------------------------------------- /packages/create-modular-react-app/template/yarnrc: -------------------------------------------------------------------------------- 1 | disable-self-update-check true -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "typescript.tsdk": "node_modules/typescript/lib" 3 | } 4 | -------------------------------------------------------------------------------- /__fixtures__/ghost-testing/README.md: -------------------------------------------------------------------------------- 1 | This is the `README.md` for the whole monorepo. 2 | -------------------------------------------------------------------------------- /__fixtures__/non-modular/packages/non-modular-non-buildable-non-testable/.gitignore: -------------------------------------------------------------------------------- 1 | dist -------------------------------------------------------------------------------- /__fixtures__/source-type/README.md: -------------------------------------------------------------------------------- 1 | This is the `README.md` for the whole monorepo. 2 | -------------------------------------------------------------------------------- /packages/remote-view/src/utils/symbol.ts: -------------------------------------------------------------------------------- 1 | export const loading = Symbol('loading'); 2 | -------------------------------------------------------------------------------- /__fixtures__/ghost-building/README.md: -------------------------------------------------------------------------------- 1 | This is the `README.md` for the whole monorepo. 2 | -------------------------------------------------------------------------------- /__fixtures__/ghost-testing/packages/README.md: -------------------------------------------------------------------------------- 1 | This will be the readme inside /packages 2 | -------------------------------------------------------------------------------- /__fixtures__/selective-lint/README.md: -------------------------------------------------------------------------------- 1 | This is the `README.md` for the whole monorepo. 2 | -------------------------------------------------------------------------------- /__fixtures__/selective-lint/packages/README.md: -------------------------------------------------------------------------------- 1 | This will be the readme inside /packages 2 | -------------------------------------------------------------------------------- /packages/create-modular-react-app/template/.prettierignore: -------------------------------------------------------------------------------- 1 | /dist 2 | /packages/**/public 3 | -------------------------------------------------------------------------------- /__fixtures__/custom-workspace-root/packages/README.md: -------------------------------------------------------------------------------- 1 | This will be the readme inside /packages 2 | -------------------------------------------------------------------------------- /__fixtures__/non-modular/packages/app/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json" 3 | } 4 | -------------------------------------------------------------------------------- /__fixtures__/test-config/esbuild-config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | useModularEsbuild: true, 3 | }; 4 | -------------------------------------------------------------------------------- /docs/concepts/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | has_children: true 3 | nav_order: 250 4 | --- 5 | 6 | # Concepts 7 | -------------------------------------------------------------------------------- /__fixtures__/custom-workspace-root/apps/app/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json" 3 | } 4 | -------------------------------------------------------------------------------- /__fixtures__/test-config/webpack-config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | useModularEsbuild: false, 3 | }; 4 | -------------------------------------------------------------------------------- /docs/releases/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | has_children: true 3 | nav_order: 750 4 | title: Release Notes 5 | --- 6 | -------------------------------------------------------------------------------- /__fixtures__/templates/modular-template-non-modular/src/index.ts: -------------------------------------------------------------------------------- 1 | console.log('I am a non-modular template'); 2 | -------------------------------------------------------------------------------- /packages/modular-template-app/src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /packages/modular-template-node-env-app/src/index.tsx: -------------------------------------------------------------------------------- 1 | console.log(process.env.NODE_ENV); 2 | 3 | export {}; 4 | -------------------------------------------------------------------------------- /__fixtures__/templates/modular-template-app/README.md: -------------------------------------------------------------------------------- 1 | # This is a README placeholder for this template fixture 2 | -------------------------------------------------------------------------------- /__fixtures__/templates/modular-template-filter/README.md: -------------------------------------------------------------------------------- 1 | # This is a README placeholder for this template fixture 2 | -------------------------------------------------------------------------------- /docs/how-to/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | has_children: true 3 | title: How To 4 | nav_order: 300 5 | --- 6 | 7 | # How To 8 | -------------------------------------------------------------------------------- /packages/modular-template-esm-view/src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /__fixtures__/ghost-building/modular/setupEnvironment.ts: -------------------------------------------------------------------------------- 1 | // Allows for adding setup configuration to Jest 2 | export {}; 3 | -------------------------------------------------------------------------------- /__fixtures__/non-modular/modular/setupEnvironment.ts: -------------------------------------------------------------------------------- 1 | // Allows for adding setup configuration to Jest 2 | export {}; 3 | -------------------------------------------------------------------------------- /__fixtures__/non-modular/packages/app/src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /__fixtures__/source-type/modular/setupEnvironment.ts: -------------------------------------------------------------------------------- 1 | // Allows for adding setup configuration to Jest 2 | export {}; 3 | -------------------------------------------------------------------------------- /__fixtures__/templates/modular-template-no-filter/README.md: -------------------------------------------------------------------------------- 1 | # This is a README placeholder for this template fixture 2 | -------------------------------------------------------------------------------- /__fixtures__/templates/modular-template-non-modular/README.md: -------------------------------------------------------------------------------- 1 | # This is a README placeholder for this template fixture 2 | -------------------------------------------------------------------------------- /packages/create-modular-react-app/README.md: -------------------------------------------------------------------------------- 1 | ## create-modular-react-app 2 | 3 | `create-react-app`, but for `modular`. 4 | -------------------------------------------------------------------------------- /packages/modular-template-node-env-app/src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /__fixtures__/custom-workspace-root/apps/app/src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /packages/modular-template-app/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "trailingComma": "all", 4 | "printWidth": 80, 5 | "proseWrap": "always" 6 | } 7 | -------------------------------------------------------------------------------- /__fixtures__/custom-workspace-root/modular/setupEnvironment.ts: -------------------------------------------------------------------------------- 1 | // Allows for adding setup configuration to Jest 2 | export {}; 3 | -------------------------------------------------------------------------------- /__fixtures__/selective-typecheck-example/packages/esbuild-app/.modular.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | useModularEsbuild: true, 3 | }; 4 | -------------------------------------------------------------------------------- /__fixtures__/source-type/packages/a/src/index.ts: -------------------------------------------------------------------------------- 1 | export default function add(a: number, b: number): number { 2 | return a + b; 3 | } 4 | -------------------------------------------------------------------------------- /__fixtures__/source-type/packages/b/src/index.ts: -------------------------------------------------------------------------------- 1 | export default function add(a: number, b: number): number { 2 | return a + b; 3 | } 4 | -------------------------------------------------------------------------------- /__fixtures__/source-type/packages/c/src/index.ts: -------------------------------------------------------------------------------- 1 | export default function add(a: number, b: number): number { 2 | return a + b; 3 | } 4 | -------------------------------------------------------------------------------- /__fixtures__/source-type/packages/d/src/index.ts: -------------------------------------------------------------------------------- 1 | export default function add(a: number, b: number): number { 2 | return a + b; 3 | } 4 | -------------------------------------------------------------------------------- /__fixtures__/source-type/packages/e/src/index.ts: -------------------------------------------------------------------------------- 1 | export default function add(a: number, b: number): number { 2 | return a + b; 3 | } 4 | -------------------------------------------------------------------------------- /integration-test-scripts/startVerdaccio.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | verdaccio --config ./integration-test-scripts/verdaccio-config.yaml -------------------------------------------------------------------------------- /packages/create-modular-react-app/template/modular/setupEnvironment.ts: -------------------------------------------------------------------------------- 1 | // Allows for adding setup configuration to Jest 2 | export {}; 3 | -------------------------------------------------------------------------------- /packages/modular-template-package/src/index.ts: -------------------------------------------------------------------------------- 1 | export default function add(a: number, b: number): number { 2 | return a + b; 3 | } 4 | -------------------------------------------------------------------------------- /packages/modular-template-source/src/index.ts: -------------------------------------------------------------------------------- 1 | export default function add(a: number, b: number): number { 2 | return a + b; 3 | } 4 | -------------------------------------------------------------------------------- /__fixtures__/custom-workspace-root/apps/app/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /__fixtures__/ghost-building/packages/a/src/index.ts: -------------------------------------------------------------------------------- 1 | export default function add(a: number, b: number): number { 2 | return a + b; 3 | } 4 | -------------------------------------------------------------------------------- /__fixtures__/ghost-building/packages/b/src/index.ts: -------------------------------------------------------------------------------- 1 | export default function add(a: number, b: number): number { 2 | return a + b; 3 | } 4 | -------------------------------------------------------------------------------- /__fixtures__/ghost-building/packages/c/src/index.ts: -------------------------------------------------------------------------------- 1 | export default function add(a: number, b: number): number { 2 | return a + b; 3 | } 4 | -------------------------------------------------------------------------------- /__fixtures__/ghost-building/packages/d/src/index.ts: -------------------------------------------------------------------------------- 1 | export default function add(a: number, b: number): number { 2 | return a + b; 3 | } 4 | -------------------------------------------------------------------------------- /__fixtures__/ghost-building/packages/e/src/index.ts: -------------------------------------------------------------------------------- 1 | export default function add(a: number, b: number): number { 2 | return a + b; 3 | } 4 | -------------------------------------------------------------------------------- /__fixtures__/ghost-building/packages/f/src/index.ts: -------------------------------------------------------------------------------- 1 | export default function add(a: number, b: number): number { 2 | return a + b; 3 | } 4 | -------------------------------------------------------------------------------- /__fixtures__/ghost-testing/packages/b/src/index.ts: -------------------------------------------------------------------------------- 1 | export default function add(a: number, b: number): number { 2 | return a + b; 3 | } 4 | -------------------------------------------------------------------------------- /__fixtures__/ghost-testing/packages/c/src/index.ts: -------------------------------------------------------------------------------- 1 | export default function add(a: number, b: number): number { 2 | return a + b; 3 | } 4 | -------------------------------------------------------------------------------- /__fixtures__/ghost-testing/packages/d/src/index.ts: -------------------------------------------------------------------------------- 1 | export default function add(a: number, b: number): number { 2 | return a + b; 3 | } 4 | -------------------------------------------------------------------------------- /__fixtures__/ghost-testing/packages/e/src/index.ts: -------------------------------------------------------------------------------- 1 | export default function add(a: number, b: number): number { 2 | return a + b; 3 | } 4 | -------------------------------------------------------------------------------- /packages/tree-view-for-tests/src/ascii-tree.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'ascii-tree' { 2 | export function generate(input: string): string; 3 | } 4 | -------------------------------------------------------------------------------- /__fixtures__/custom-workspace-root/apps/alpha/src/index.ts: -------------------------------------------------------------------------------- 1 | export default function add(a: number, b: number): number { 2 | return a + b; 3 | } 4 | -------------------------------------------------------------------------------- /__fixtures__/non-modular/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "modular-scripts/tsconfig.json", 3 | "include": ["modular", "packages/**/src"] 4 | } 5 | -------------------------------------------------------------------------------- /__fixtures__/source-type/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "modular-scripts/tsconfig.json", 3 | "include": ["modular", "packages/**/src"] 4 | } 5 | -------------------------------------------------------------------------------- /__fixtures__/templates/modular-template-no-filter/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /packages/modular-scripts/src/__tests__/esbuild-scripts/__fixtures__/module-scope/src/index.tsx: -------------------------------------------------------------------------------- 1 | import { foo } from '../foo'; 2 | 3 | foo(); 4 | -------------------------------------------------------------------------------- /__fixtures__/ghost-building/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "modular-scripts/tsconfig.json", 3 | "include": ["modular", "packages/**/src"] 4 | } 5 | -------------------------------------------------------------------------------- /__fixtures__/ghost-testing/packages/a/src/index.ts: -------------------------------------------------------------------------------- 1 | export default function add(a: number, b: number): number { 2 | //test 3 | return a + b; 4 | } 5 | -------------------------------------------------------------------------------- /__fixtures__/ghost-testing/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "modular-scripts/tsconfig.json", 3 | "include": ["modular", "packages/**/src"] 4 | } 5 | -------------------------------------------------------------------------------- /__fixtures__/selective-lint/packages/beta-lint/src/index.ts: -------------------------------------------------------------------------------- 1 | export default function add(a: number, b: number): number { 2 | return a + b; 3 | } 4 | -------------------------------------------------------------------------------- /__fixtures__/selective-lint/packages/delta-lint/src/index.ts: -------------------------------------------------------------------------------- 1 | export default function add(a: number, b: number): number { 2 | return a + b; 3 | } 4 | -------------------------------------------------------------------------------- /__fixtures__/selective-lint/packages/epsilon-lint/src/index.ts: -------------------------------------------------------------------------------- 1 | export default function add(a: number, b: number): number { 2 | return a + b; 3 | } 4 | -------------------------------------------------------------------------------- /__fixtures__/selective-lint/packages/gamma-lint/src/index.ts: -------------------------------------------------------------------------------- 1 | export default function add(a: number, b: number): number { 2 | return a + b; 3 | } 4 | -------------------------------------------------------------------------------- /__fixtures__/selective-lint/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "modular-scripts/tsconfig.json", 3 | "include": ["modular", "packages/**/src"] 4 | } 5 | -------------------------------------------------------------------------------- /__fixtures__/templates/modular-template-filter/src/index.tsx: -------------------------------------------------------------------------------- 1 | export default function add(a: number, b: number): number { 2 | return a + b; 3 | } 4 | -------------------------------------------------------------------------------- /__fixtures__/templates/modular-template-no-filter/src/index.tsx: -------------------------------------------------------------------------------- 1 | export default function add(a: number, b: number): number { 2 | return a + b; 3 | } 4 | -------------------------------------------------------------------------------- /packages/modular-scripts/src/__tests__/esbuild-scripts/__fixtures__/module-scope/foo.ts: -------------------------------------------------------------------------------- 1 | export function foo(): void { 2 | console.log('foo'); 3 | } 4 | -------------------------------------------------------------------------------- /packages/modular-scripts/src/__tests__/esbuild-scripts/__fixtures__/svgr-dataurl/index.css: -------------------------------------------------------------------------------- 1 | .app { 2 | background-image: url('./logo.svg'); 3 | } 4 | -------------------------------------------------------------------------------- /packages/modular-template-app/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jpmorganchase/modular/HEAD/packages/modular-template-app/public/favicon.ico -------------------------------------------------------------------------------- /packages/modular-template-app/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jpmorganchase/modular/HEAD/packages/modular-template-app/public/logo192.png -------------------------------------------------------------------------------- /packages/modular-template-app/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jpmorganchase/modular/HEAD/packages/modular-template-app/public/logo512.png -------------------------------------------------------------------------------- /__fixtures__/non-modular/packages/non-modular-buildable/src/index.ts: -------------------------------------------------------------------------------- 1 | export default function add(a: number, b: number): number { 2 | return a + b; 3 | } 4 | -------------------------------------------------------------------------------- /__fixtures__/non-modular/packages/non-modular-lintable/src/index.ts: -------------------------------------------------------------------------------- 1 | export default function add(a: number, b: number): number { 2 | return a + b; 3 | } 4 | -------------------------------------------------------------------------------- /__fixtures__/non-modular/packages/non-modular-testable/src/index.ts: -------------------------------------------------------------------------------- 1 | export default function add(a: number, b: number): number { 2 | return a + b; 3 | } 4 | -------------------------------------------------------------------------------- /__fixtures__/non-modular/packages/non-modular-typecheckable/src/index.ts: -------------------------------------------------------------------------------- 1 | export default function add(a: number, b: number): number { 2 | return a + b; 3 | } 4 | -------------------------------------------------------------------------------- /__fixtures__/selective-lint/packages/alpha-lint/src/index.ts: -------------------------------------------------------------------------------- 1 | export default function add(a: number, b: number): number { 2 | //test 3 | return a + b; 4 | } 5 | -------------------------------------------------------------------------------- /packages/create-modular-react-app/template/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "modular-scripts/tsconfig.json", 3 | "include": ["modular", "packages/**/src"] 4 | } 5 | -------------------------------------------------------------------------------- /packages/modular-scripts/src/__tests__/esbuild-scripts/__fixtures__/worker-plugin/alive.worker.ts: -------------------------------------------------------------------------------- 1 | globalThis.self.postMessage("I'm alive!"); 2 | 3 | export {}; 4 | -------------------------------------------------------------------------------- /__fixtures__/custom-workspace-root/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "modular-scripts/tsconfig.json", 3 | "include": ["modular", "packages/**/src", "apps/**/src"] 4 | } 5 | -------------------------------------------------------------------------------- /__fixtures__/ghost-testing/packages/a/a-dummy.ts: -------------------------------------------------------------------------------- 1 | // This should never be executed when testing 2 | throw new Error('Dummy file executed for package a!'); 3 | export {}; 4 | -------------------------------------------------------------------------------- /__fixtures__/ghost-testing/packages/c/c-dummy.ts: -------------------------------------------------------------------------------- 1 | // This should never be executed when testing 2 | throw new Error('Dummy file executed for package c!'); 3 | export {}; 4 | -------------------------------------------------------------------------------- /packages/remote-view/src/components/index.ts: -------------------------------------------------------------------------------- 1 | export * from './remote-view'; 2 | export * from './remote-view-provider'; 3 | export * from './remote-view-error-boundary'; 4 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "dbaeumer.vscode-eslint", 4 | "esbenp.prettier-vscode", 5 | "wayou.vscode-todo-highlight" 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /__fixtures__/non-modular/packages/non-modular-non-buildable-non-testable/src/index.ts: -------------------------------------------------------------------------------- 1 | export default function add(a: number, b: number): number { 2 | return a + b; 3 | } 4 | -------------------------------------------------------------------------------- /__fixtures__/custom-workspace-root/apps/app/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jpmorganchase/modular/HEAD/__fixtures__/custom-workspace-root/apps/app/public/favicon.ico -------------------------------------------------------------------------------- /__fixtures__/custom-workspace-root/apps/app/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jpmorganchase/modular/HEAD/__fixtures__/custom-workspace-root/apps/app/public/logo192.png -------------------------------------------------------------------------------- /__fixtures__/custom-workspace-root/apps/app/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jpmorganchase/modular/HEAD/__fixtures__/custom-workspace-root/apps/app/public/logo512.png -------------------------------------------------------------------------------- /packages/modular-scripts/src/__tests__/__fixtures__/packages/sample-library-package/index.ts: -------------------------------------------------------------------------------- 1 | export default function add(a: number, b: number): number { 2 | return a + b; 3 | } 4 | -------------------------------------------------------------------------------- /packages/modular-scripts/types/package/packagejson: -------------------------------------------------------------------------------- 1 | { 2 | "name": "PackageName__", 3 | "version": "1.0.0", 4 | "main": "src/index.ts", 5 | "license": "UNLICENSED" 6 | } 7 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | .changeset 2 | /dist 3 | packages/*/dist 4 | packages/*/build 5 | packages/*/public 6 | packages/*/dist-cjs 7 | packages/*/dist-types 8 | __fixtures__/remote-view-fake-cdn -------------------------------------------------------------------------------- /__fixtures__/custom-workspace-root/apps/app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "app", 3 | "private": true, 4 | "modular": { 5 | "type": "app" 6 | }, 7 | "version": "1.0.0" 8 | } 9 | -------------------------------------------------------------------------------- /__fixtures__/ghost-testing/packages/b/src/__tests__/b-dummy.ts: -------------------------------------------------------------------------------- 1 | // This should never be executed when testing 2 | throw new Error('Dummy file executed for package b!'); 3 | export {}; 4 | -------------------------------------------------------------------------------- /__fixtures__/ghost-testing/packages/b/src/__tests__/b.test.ts: -------------------------------------------------------------------------------- 1 | import add from '../index'; 2 | 3 | test('it should add two numbers', () => { 4 | expect(add(1, 2)).toEqual(3); 5 | }); 6 | -------------------------------------------------------------------------------- /__fixtures__/ghost-testing/packages/c/src/__tests__/c.test.ts: -------------------------------------------------------------------------------- 1 | import add from '../index'; 2 | 3 | test('it should add two numbers', () => { 4 | expect(add(4, 4)).toEqual(8); 5 | }); 6 | -------------------------------------------------------------------------------- /__fixtures__/ghost-testing/packages/d/src/__tests__/d-dummy.ts: -------------------------------------------------------------------------------- 1 | // This should never be executed when testing 2 | throw new Error('Dummy file executed for package d!'); 3 | export {}; 4 | -------------------------------------------------------------------------------- /__fixtures__/ghost-testing/packages/e/src/__tests__/e-dummy.ts: -------------------------------------------------------------------------------- 1 | // This should never be executed when testing 2 | throw new Error('Dummy file executed for package e!'); 3 | export {}; 4 | -------------------------------------------------------------------------------- /__fixtures__/ghost-testing/packages/e/src/__tests__/e.test.ts: -------------------------------------------------------------------------------- 1 | import add from '../index'; 2 | 3 | test('it should add two numbers', () => { 4 | expect(add(3, 4)).toEqual(7); 5 | }); 6 | -------------------------------------------------------------------------------- /__fixtures__/verifiable-project/packages/package-three/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "package-three", 3 | "private": true, 4 | "main": "./src/index.ts", 5 | "version": "1.0.0" 6 | } 7 | -------------------------------------------------------------------------------- /__fixtures__/ghost-testing/packages/a/src/__tests__/a.test.ts: -------------------------------------------------------------------------------- 1 | import add from '../index'; 2 | 3 | test('it should add two numbers unique', () => { 4 | expect(add(5, 5)).toEqual(10); 5 | }); 6 | -------------------------------------------------------------------------------- /docs/components/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | has_children: true 3 | title: Components 4 | nav_order: 2 5 | --- 6 | 7 | # Components 8 | 9 | Components that are designed to work with Modular. 10 | -------------------------------------------------------------------------------- /packages/modular-scripts/src/__tests__/esbuild-scripts/__fixtures__/svgr-url/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /packages/workspace-resolver/src/index.ts: -------------------------------------------------------------------------------- 1 | export { 2 | resolveWorkspace, 3 | analyzeWorkspaceDependencies, 4 | } from './resolve-workspace'; 5 | 6 | export * from './resolve-dependencies'; 7 | -------------------------------------------------------------------------------- /__fixtures__/remote-view/packages/view1/src/index.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import App from './App'; 3 | 4 | export default function View1(): JSX.Element { 5 | return ; 6 | } 7 | -------------------------------------------------------------------------------- /__fixtures__/remote-view/packages/view2/src/index.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import App from './App'; 3 | 4 | export default function View1(): JSX.Element { 5 | return ; 6 | } 7 | -------------------------------------------------------------------------------- /__fixtures__/templates/modular-template-filter/src/__tests__/filter.test.ts: -------------------------------------------------------------------------------- 1 | import add from '../index'; 2 | 3 | test('it should add two numbers', () => { 4 | expect(add(1, 2)).toEqual(3); 5 | }); 6 | -------------------------------------------------------------------------------- /packages/modular-scripts/src/__tests__/esbuild-scripts/__fixtures__/svgr-component/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /packages/modular-scripts/src/__tests__/esbuild-scripts/__fixtures__/svgr-dataurl/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /packages/modular-template-view/src/index.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | 3 | export default function ComponentName__(): JSX.Element { 4 | return
This is ComponentName__
; 5 | } 6 | -------------------------------------------------------------------------------- /__fixtures__/ghost-testing/packages/a/src/__tests__/utils/a-nested.test.ts: -------------------------------------------------------------------------------- 1 | import add from '../../index'; 2 | 3 | test('it should add two numbers', () => { 4 | expect(add(3, 4)).toEqual(7); 5 | }); 6 | -------------------------------------------------------------------------------- /__fixtures__/ghost-testing/packages/b/src/__tests__/utils/b-nested.test.ts: -------------------------------------------------------------------------------- 1 | import add from '../../index'; 2 | 3 | test('it should add two numbers', () => { 4 | expect(add(7, 8)).toEqual(15); 5 | }); 6 | -------------------------------------------------------------------------------- /__fixtures__/ghost-testing/packages/c/src/__tests__/utils/c-nested.test.ts: -------------------------------------------------------------------------------- 1 | import add from '../../index'; 2 | 3 | test('it should add two numbers', () => { 4 | expect(add(7, 7)).toEqual(14); 5 | }); 6 | -------------------------------------------------------------------------------- /__fixtures__/ghost-testing/packages/e/src/__tests__/utils/e-nested.test.ts: -------------------------------------------------------------------------------- 1 | import add from '../../index'; 2 | 3 | test('it should add two numbers', () => { 4 | expect(add(15, 15)).toEqual(30); 5 | }); 6 | -------------------------------------------------------------------------------- /__fixtures__/non-modular/packages/non-modular-buildable/src/__tests__/index.test.ts: -------------------------------------------------------------------------------- 1 | import add from '../index'; 2 | 3 | test('it should add two numbers', () => { 4 | expect(add(1, 2)).toBe(3); 5 | }); 6 | -------------------------------------------------------------------------------- /__fixtures__/non-modular/packages/non-modular-lintable/src/__tests__/index.test.ts: -------------------------------------------------------------------------------- 1 | import add from '../index'; 2 | 3 | test('it should add two numbers', () => { 4 | expect(add(1, 2)).toBe(3); 5 | }); 6 | -------------------------------------------------------------------------------- /__fixtures__/non-modular/packages/non-modular-testable/src/__tests__/index.test.ts: -------------------------------------------------------------------------------- 1 | import add from '../index'; 2 | 3 | test('it should add two numbers', () => { 4 | expect(add(1, 2)).toBe(3); 5 | }); 6 | -------------------------------------------------------------------------------- /__fixtures__/templates/modular-template-no-filter/src/__tests__/no-filter.test.ts: -------------------------------------------------------------------------------- 1 | import add from '../index'; 2 | 3 | test('it should add two numbers', () => { 4 | expect(add(1, 2)).toEqual(3); 5 | }); 6 | -------------------------------------------------------------------------------- /packages/modular-template-package/src/__tests__/index.test.ts: -------------------------------------------------------------------------------- 1 | import add from '../index'; 2 | 3 | test('it should add two numbers', () => { 4 | expect(add(0.1, 0.2)).toBe(0.30000000000000004); 5 | }); 6 | -------------------------------------------------------------------------------- /packages/modular-template-source/src/__tests__/index.test.ts: -------------------------------------------------------------------------------- 1 | import add from '../index'; 2 | 3 | test('it should add two numbers', () => { 4 | expect(add(0.1, 0.2)).toBe(0.30000000000000004); 5 | }); 6 | -------------------------------------------------------------------------------- /__fixtures__/non-modular/packages/non-modular-typecheckable/src/__tests__/index.test.ts: -------------------------------------------------------------------------------- 1 | import add from '../index'; 2 | 3 | test('it should add two numbers', () => { 4 | expect(add(1, 2)).toBe(3); 5 | }); 6 | -------------------------------------------------------------------------------- /docs/commands/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | has_children: true 3 | title: Commands 4 | nav_order: 2 5 | --- 6 | 7 | # Commands 8 | 9 | The Modular CLI is the entrypoint for working with the modular ecosystem. 10 | -------------------------------------------------------------------------------- /packages/remote-view/src/index.ts: -------------------------------------------------------------------------------- 1 | export { 2 | RemoteViewProvider, 3 | RemoteView, 4 | RemoteViewErrorBoundary, 5 | } from './components'; 6 | 7 | export { RemoteViewError } from './utils/remote-view-error'; 8 | -------------------------------------------------------------------------------- /__fixtures__/custom-workspace-root/apps/alpha/src/__tests__/index.test.ts: -------------------------------------------------------------------------------- 1 | import add from '../index'; 2 | 3 | test('it should add two numbers', () => { 4 | expect(add(0.1, 0.2)).toEqual(0.30000000000000004); 5 | }); 6 | -------------------------------------------------------------------------------- /__fixtures__/source-type/packages/d/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "d", 3 | "private": false, 4 | "modular": { 5 | "type": "source" 6 | }, 7 | "main": "./src/index.ts", 8 | "version": "1.0.0" 9 | } 10 | -------------------------------------------------------------------------------- /packages/create-modular-react-app/template/.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "dbaeumer.vscode-eslint", 4 | "esbenp.prettier-vscode", 5 | "wayou.vscode-todo-highlight" 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /__fixtures__/ghost-building/packages/d/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "d", 3 | "private": false, 4 | "modular": { 5 | "type": "package" 6 | }, 7 | "main": "./src/index.ts", 8 | "version": "1.0.0" 9 | } 10 | -------------------------------------------------------------------------------- /__fixtures__/ghost-building/packages/f/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "f", 3 | "private": false, 4 | "modular": { 5 | "type": "package" 6 | }, 7 | "main": "./src/index.ts", 8 | "version": "1.0.0" 9 | } 10 | -------------------------------------------------------------------------------- /__fixtures__/ghost-testing/packages/d/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "d", 3 | "private": false, 4 | "modular": { 5 | "type": "package" 6 | }, 7 | "main": "./src/index.ts", 8 | "version": "1.0.0" 9 | } 10 | -------------------------------------------------------------------------------- /__fixtures__/non-modular/packages/non-modular-non-buildable-non-testable/src/__tests__/index.test.ts: -------------------------------------------------------------------------------- 1 | import add from '../index'; 2 | 3 | test('it should add two numbers', () => { 4 | expect(add(1, 2)).toBe(3); 5 | }); 6 | -------------------------------------------------------------------------------- /__fixtures__/resolve-workspace/non-modular-workspace-1/packages/package-extraneous-1/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "package-extraneous-1", 3 | "private": true, 4 | "main": "./src/index.ts", 5 | "version": "1.0.0" 6 | } 7 | -------------------------------------------------------------------------------- /packages/modular-scripts/src/__tests__/TestView.test-tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | 3 | export default function SampleView(): JSX.Element { 4 | return
this is a modular view
5 | } -------------------------------------------------------------------------------- /__fixtures__/custom-workspace-root/apps/alpha/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "alpha", 3 | "private": false, 4 | "modular": { 5 | "type": "package" 6 | }, 7 | "main": "./src/index.ts", 8 | "version": "1.0.0" 9 | } 10 | -------------------------------------------------------------------------------- /__fixtures__/ghost-testing/packages/d/src/__tests__/d.test.ts: -------------------------------------------------------------------------------- 1 | import add from '../index'; 2 | 3 | test('it should add two numbers', () => { 4 | console.log('testing d:index.test.ts'); 5 | expect(add(87, 1)).toEqual(88); 6 | }); 7 | -------------------------------------------------------------------------------- /__fixtures__/remote-view-fake-cdn/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 |
6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /packages/modular-scripts/src/__tests__/TestEsmView.test-tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | 3 | export default function SampleESMView(): JSX.Element { 4 | return
this is a modular esm-view
5 | } -------------------------------------------------------------------------------- /packages/modular-scripts/types/view/packagejson: -------------------------------------------------------------------------------- 1 | { 2 | "name": "PackageName__", 3 | "version": "1.0.0", 4 | "main": "src/index.tsx", 5 | "license": "UNLICENSED", 6 | "modular": { 7 | "type": "view" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /modular/setupTests.ts: -------------------------------------------------------------------------------- 1 | import '@testing-library/jest-dom'; 2 | 3 | // polyfill for node < 16 4 | import 'string.prototype.replaceall/auto'; 5 | 6 | // Certain tests perform installs that take a while 7 | jest.setTimeout(10 * 60 * 1000); 8 | -------------------------------------------------------------------------------- /packages/create-modular-react-app/template/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "typescript.tsdk": "node_modules/typescript/lib", 3 | "jest.jestCommandLine": "./node_modules/.bin/modular test --watchAll=false", 4 | "jest.autoRun": "off" 5 | } 6 | -------------------------------------------------------------------------------- /__fixtures__/remote-view-fake-cdn/view1/index.html: -------------------------------------------------------------------------------- 1 |
-------------------------------------------------------------------------------- /__fixtures__/selective-lint/packages/delta-lint/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "delta-lint", 3 | "private": false, 4 | "modular": { 5 | "type": "package" 6 | }, 7 | "main": "./src/index.ts", 8 | "version": "1.0.0" 9 | } 10 | -------------------------------------------------------------------------------- /packages/modular-scripts/src/__tests__/__fixtures__/packages/sample-async-package/index.ts: -------------------------------------------------------------------------------- 1 | export default async function runInAsync(): Promise { 2 | const { runAsync } = await import('./runAsync'); 3 | 4 | return runAsync(); 5 | } 6 | -------------------------------------------------------------------------------- /packages/modular-scripts/types/esm-view/packagejson: -------------------------------------------------------------------------------- 1 | { 2 | "name": "PackageName__", 3 | "version": "1.0.0", 4 | "main": "src/index.tsx", 5 | "license": "UNLICENSED", 6 | "modular": { 7 | "type": "esm-view" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /__fixtures__/remote-view-fake-cdn/esm-view-card/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 |
6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /__fixtures__/remote-view-fake-cdn/esm-view-list/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 |
6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /__fixtures__/remote-view-fake-cdn/react@17.0.2.js: -------------------------------------------------------------------------------- 1 | /* esm.sh - react@17.0.2 */ 2 | export * from 'http://localhost:8484/stable/react@17.0.2/es2022/react.js'; 3 | export { default } from 'http://localhost:8484/stable/react@17.0.2/es2022/react.js'; 4 | -------------------------------------------------------------------------------- /__fixtures__/verifiable-project/packages/package-one/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "package-one", 3 | "private": true, 4 | "modular": { 5 | "type": "package" 6 | }, 7 | "main": "./src/index.ts", 8 | "version": "1.0.0" 9 | } 10 | -------------------------------------------------------------------------------- /__fixtures__/verifiable-project/packages/package-two/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "package-two", 3 | "private": true, 4 | "modular": { 5 | "type": "package" 6 | }, 7 | "main": "./src/index.ts", 8 | "version": "1.0.0" 9 | } 10 | -------------------------------------------------------------------------------- /packages/modular-scripts/src/__tests__/esbuild-scripts/__fixtures__/svgr-dataurl/index.tsx: -------------------------------------------------------------------------------- 1 | import './index.css'; 2 | import React from 'react'; 3 | import ReactDOM from 'react-dom'; 4 | 5 | ReactDOM.render(
, document.body); 6 | -------------------------------------------------------------------------------- /__fixtures__/ghost-testing/packages/d/src/__tests__/utils/d-nested.test.ts: -------------------------------------------------------------------------------- 1 | import add from '../../index'; 2 | 3 | test('it should add two numbers', () => { 4 | console.log('testing d:/utils/utils.test.ts'); 5 | expect(add(3, 2)).toEqual(5); 6 | }); 7 | -------------------------------------------------------------------------------- /__fixtures__/verifiable-project/other-packages/package-four/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "package-four", 3 | "private": true, 4 | "modular": { 5 | "type": "esm-view" 6 | }, 7 | "main": "./src/index.ts", 8 | "version": "1.0.0" 9 | } 10 | -------------------------------------------------------------------------------- /packages/modular-scripts/src/__tests__/esbuild-scripts/__fixtures__/svgr-url/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import logo from './logo.svg'; 4 | 5 | ReactDOM.render(logo, document.body); 6 | -------------------------------------------------------------------------------- /__fixtures__/remote-view-fake-cdn/view2/asset-manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "files": { 3 | "main.js": "/static/js/main.95dbf0ef.js", 4 | "main.95dbf0ef.js.map": "/static/js/main.95dbf0ef.js.map" 5 | }, 6 | "entrypoints": ["static/js/main.95dbf0ef.js"] 7 | } 8 | -------------------------------------------------------------------------------- /__fixtures__/resolve-workspace/clean-workspace-1/packages/package-one/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "package-one", 3 | "private": true, 4 | "modular": { 5 | "type": "package" 6 | }, 7 | "main": "./src/index.ts", 8 | "version": "1.0.0" 9 | } 10 | -------------------------------------------------------------------------------- /__fixtures__/resolve-workspace/clean-workspace-1/packages/package-two/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "package-two", 3 | "private": true, 4 | "modular": { 5 | "type": "package" 6 | }, 7 | "main": "./src/index.ts", 8 | "version": "1.0.0" 9 | } 10 | -------------------------------------------------------------------------------- /__fixtures__/resolve-workspace/clean-workspace-2/packages/package-one/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "package-one", 3 | "private": true, 4 | "modular": { 5 | "type": "package" 6 | }, 7 | "main": "./src/index.ts", 8 | "version": "1.0.0" 9 | } 10 | -------------------------------------------------------------------------------- /__fixtures__/resolve-workspace/clean-workspace-2/packages/package-two/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "package-two", 3 | "private": true, 4 | "modular": { 5 | "type": "package" 6 | }, 7 | "main": "./src/index.ts", 8 | "version": "1.0.0" 9 | } 10 | -------------------------------------------------------------------------------- /__fixtures__/resolve-workspace/clean-workspace-3/packages/package-one/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "package-one", 3 | "private": true, 4 | "modular": { 5 | "type": "package" 6 | }, 7 | "main": "./src/index.ts", 8 | "version": "1.0.0" 9 | } 10 | -------------------------------------------------------------------------------- /__fixtures__/resolve-workspace/clean-workspace-3/packages/package-two/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "package-two", 3 | "private": true, 4 | "modular": { 5 | "type": "package" 6 | }, 7 | "main": "./src/index.ts", 8 | "version": "1.0.0" 9 | } 10 | -------------------------------------------------------------------------------- /packages/modular-scripts/src/__tests__/__fixtures__/lint/InvalidJSX.jsx: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | 3 | import { useEffect } from 'react'; 4 | 5 | export function BadComponent(props) { 6 | if (props.name) { 7 | useEffect(() => {}); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /__fixtures__/remote-view-fake-cdn/react-dom@17.0.2.js: -------------------------------------------------------------------------------- 1 | /* esm.sh - react-dom@17.0.2 */ 2 | export * from 'http://localhost:8484/v106/react-dom@17.0.2/es2022/react-dom.js'; 3 | export { default } from 'http://localhost:8484/v106/react-dom@17.0.2/es2022/react-dom.js'; 4 | -------------------------------------------------------------------------------- /__fixtures__/remote-view-fake-cdn/view2/index.html: -------------------------------------------------------------------------------- 1 |
-------------------------------------------------------------------------------- /__fixtures__/resolve-workspace/clean-workspace-3/packages/package-four/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "package-four", 3 | "private": true, 4 | "modular": { 5 | "type": "package" 6 | }, 7 | "main": "./src/index.ts", 8 | "version": "1.0.0" 9 | } 10 | -------------------------------------------------------------------------------- /__fixtures__/resolve-workspace/clean-workspace-3/packages/package-three/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "package-three", 3 | "private": true, 4 | "modular": { 5 | "type": "package" 6 | }, 7 | "main": "./src/index.ts", 8 | "version": "1.0.0" 9 | } 10 | -------------------------------------------------------------------------------- /__fixtures__/resolve-workspace/invalid-workspace-1/packages/package-one/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "package-one", 3 | "private": true, 4 | "modular": { 5 | "type": "package" 6 | }, 7 | "main": "./src/index.ts", 8 | "version": "1.0.0" 9 | } 10 | -------------------------------------------------------------------------------- /__fixtures__/resolve-workspace/invalid-workspace-1/packages/package-two/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "package-two", 3 | "private": true, 4 | "modular": { 5 | "type": "package" 6 | }, 7 | "main": "./src/index.ts", 8 | "version": "1.0.0" 9 | } 10 | -------------------------------------------------------------------------------- /__fixtures__/resolve-workspace/invalid-workspace-2/packages/package-one/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "package-one", 3 | "private": true, 4 | "modular": { 5 | "type": "package" 6 | }, 7 | "main": "./src/index.ts", 8 | "version": "1.0.0" 9 | } 10 | -------------------------------------------------------------------------------- /__fixtures__/resolve-workspace/invalid-workspace-2/packages/package-two/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "package-two", 3 | "private": true, 4 | "modular": { 5 | "type": "package" 6 | }, 7 | "main": "./src/index.ts", 8 | "version": "1.0.0" 9 | } 10 | -------------------------------------------------------------------------------- /__fixtures__/resolve-workspace/invalid-workspace-3/packages/package-one/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "package-one", 3 | "private": true, 4 | "modular": { 5 | "type": "package" 6 | }, 7 | "main": "./src/index.ts", 8 | "version": "1.0.0" 9 | } 10 | -------------------------------------------------------------------------------- /__fixtures__/resolve-workspace/invalid-workspace-3/packages/package-two/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "package-two", 3 | "private": true, 4 | "modular": { 5 | "type": "package" 6 | }, 7 | "main": "./src/index.ts", 8 | "version": "1.0.0" 9 | } 10 | -------------------------------------------------------------------------------- /__fixtures__/resolve-workspace/invalid-workspace-4/packages/package-one/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "package-one", 3 | "private": true, 4 | "modular": { 5 | "type": "package" 6 | }, 7 | "main": "./src/index.ts", 8 | "version": "1.0.0" 9 | } 10 | -------------------------------------------------------------------------------- /__fixtures__/resolve-workspace/invalid-workspace-4/packages/package-two/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "package-two", 3 | "private": true, 4 | "modular": { 5 | "type": "package" 6 | }, 7 | "main": "./src/index.ts", 8 | "version": "1.0.0" 9 | } 10 | -------------------------------------------------------------------------------- /__fixtures__/resolve-workspace/invalid-workspace-5/packages/package-one/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "package-one", 3 | "private": true, 4 | "modular": { 5 | "type": "package" 6 | }, 7 | "main": "./src/index.ts", 8 | "version": "1.0.0" 9 | } 10 | -------------------------------------------------------------------------------- /__fixtures__/resolve-workspace/invalid-workspace-5/packages/package-two/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "package-two", 3 | "private": true, 4 | "modular": { 5 | "type": "package" 6 | }, 7 | "main": "./src/index.ts", 8 | "version": "1.0.0" 9 | } 10 | -------------------------------------------------------------------------------- /__fixtures__/resolve-workspace/mismatched-dependency/packages/package-one/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "package-one", 3 | "private": true, 4 | "modular": { 5 | "type": "package" 6 | }, 7 | "main": "./src/index.ts", 8 | "version": "0.0.9" 9 | } 10 | -------------------------------------------------------------------------------- /__fixtures__/resolve-workspace/mismatched-dependency/packages/package-two/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "package-two", 3 | "private": true, 4 | "modular": { 5 | "type": "package" 6 | }, 7 | "main": "./src/index.ts", 8 | "version": "1.0.0" 9 | } 10 | -------------------------------------------------------------------------------- /__fixtures__/resolve-workspace/non-modular-workspace-1/packages/package-one/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "package-one", 3 | "private": true, 4 | "modular": { 5 | "type": "package" 6 | }, 7 | "main": "./src/index.ts", 8 | "version": "1.0.0" 9 | } 10 | -------------------------------------------------------------------------------- /__fixtures__/ghost-testing/packages/b/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "b", 3 | "private": false, 4 | "modular": { 5 | "type": "package" 6 | }, 7 | "main": "./src/index.ts", 8 | "version": "1.0.0", 9 | "dependencies": { 10 | "c": "1.0.0" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /__fixtures__/ghost-testing/packages/c/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "c", 3 | "private": false, 4 | "modular": { 5 | "type": "package" 6 | }, 7 | "main": "./src/index.ts", 8 | "version": "1.0.0", 9 | "dependencies": { 10 | "d": "1.0.0" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /__fixtures__/ghost-testing/packages/e/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "e", 3 | "private": false, 4 | "modular": { 5 | "type": "package" 6 | }, 7 | "main": "./src/index.ts", 8 | "version": "1.0.0", 9 | "dependencies": { 10 | "a": "1.0.0" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /__fixtures__/source-type/packages/a/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "a", 3 | "private": false, 4 | "modular": { 5 | "type": "package" 6 | }, 7 | "main": "./src/index.ts", 8 | "version": "1.0.0", 9 | "dependencies": { 10 | "e": "1.0.0" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /__fixtures__/source-type/packages/b/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "b", 3 | "private": false, 4 | "modular": { 5 | "type": "package" 6 | }, 7 | "main": "./src/index.ts", 8 | "version": "1.0.0", 9 | "dependencies": { 10 | "c": "1.0.0" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /__fixtures__/source-type/packages/e/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "e", 3 | "private": false, 4 | "modular": { 5 | "type": "package" 6 | }, 7 | "main": "./src/index.ts", 8 | "version": "1.0.0", 9 | "dependencies": { 10 | "a": "1.0.0" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /__fixtures__/ghost-building/packages/b/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "b", 3 | "private": false, 4 | "modular": { 5 | "type": "package" 6 | }, 7 | "main": "./src/index.ts", 8 | "version": "1.0.0", 9 | "dependencies": { 10 | "c": "1.0.0" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /__fixtures__/ghost-building/packages/c/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "c", 3 | "private": false, 4 | "modular": { 5 | "type": "package" 6 | }, 7 | "main": "./src/index.ts", 8 | "version": "1.0.0", 9 | "dependencies": { 10 | "d": "1.0.0" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /__fixtures__/ghost-building/packages/e/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "e", 3 | "private": false, 4 | "modular": { 5 | "type": "package" 6 | }, 7 | "main": "./src/index.ts", 8 | "version": "1.0.0", 9 | "dependencies": { 10 | "a": "1.0.0" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /__fixtures__/remote-view-fake-cdn/view1/static/css/main.1115b39e.css: -------------------------------------------------------------------------------- 1 | .card-component{margin:auto;width:480px}.card-component .card{background-color:#f9f9f9}.card-component .group{margin-bottom:5px}.card-component .button{margin-top:14px} 2 | /*# sourceMappingURL=main.1115b39e.css.map*/ -------------------------------------------------------------------------------- /__fixtures__/resolve-workspace/non-modular-workspace-1/packages/package-extraneous-3/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "package-extraneous-3", 3 | "private": true, 4 | "modular": { 5 | "type": "" 6 | }, 7 | "main": "./src/index.ts", 8 | "version": "1.0.0" 9 | } 10 | -------------------------------------------------------------------------------- /docs/commands/workspace.md: -------------------------------------------------------------------------------- 1 | --- 2 | parent: Commands 3 | title: modular workspace 4 | --- 5 | 6 | # `modular workspace` 7 | 8 | Prints an extension of `yarn workspaces info` to the console. Extended with 9 | modular metadata about package type and public/private status. 10 | -------------------------------------------------------------------------------- /packages/modular-scripts/src/__tests__/esbuild-scripts/__fixtures__/svgr-component/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import { ReactComponent } from './logo.svg'; 4 | 5 | ReactDOM.render(, document.body); 6 | -------------------------------------------------------------------------------- /__fixtures__/resolve-workspace/invalid-workspace-4/packages/app-one/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "modular": { 4 | "type": "app" 5 | }, 6 | "dependencies": { 7 | "package-one": "1.0.0", 8 | "package-two": "1.0.0" 9 | }, 10 | "version": "1.0.0" 11 | } 12 | -------------------------------------------------------------------------------- /__fixtures__/resolve-workspace/invalid-workspace-5/packages/app-one/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "app-one", 3 | "private": true, 4 | "modular": { 5 | "type": "app" 6 | }, 7 | "dependencies": { 8 | "package-one": "1.0.0", 9 | "package-two": "1.0.0" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /packages/modular-scripts/src/__tests__/__fixtures__/lint/InvalidJS.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | 3 | const path = require('path'); 4 | 5 | function funcHasNoType(props) { 6 | let type; 7 | 8 | if (type) { 9 | } else { 10 | } 11 | 12 | const emptyFunc = () => {}; 13 | } 14 | -------------------------------------------------------------------------------- /packages/modular-scripts/src/__tests__/__fixtures__/packages/sample-async-package/runAsync.ts: -------------------------------------------------------------------------------- 1 | export function runAsync(): Promise { 2 | return new Promise((resolve) => { 3 | setTimeout(() => { 4 | console.log('done'); 5 | resolve(); 6 | }, 1000); 7 | }); 8 | } 9 | -------------------------------------------------------------------------------- /packages/remote-view-demos/src/examples/index.ts: -------------------------------------------------------------------------------- 1 | export * from './happy-path'; 2 | export * from './fallback-iframes'; 3 | export * from './default-error-boundary'; 4 | export * from './custom-error-content'; 5 | export * from './custom-error-boundary'; 6 | export * from './error-recovery'; 7 | -------------------------------------------------------------------------------- /__fixtures__/resolve-workspace/non-modular-workspace-1/packages/package-extraneous-2/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "package-extraneous-2", 3 | "private": true, 4 | "modular": { 5 | "anotherProperty": "value" 6 | }, 7 | "main": "./src/index.ts", 8 | "version": "1.0.0" 9 | } 10 | -------------------------------------------------------------------------------- /__fixtures__/selective-typecheck-example/packages/esbuild-app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "app", 3 | "private": true, 4 | "modular": { 5 | "type": "app" 6 | }, 7 | "version": "1.0.0", 8 | "dependencies": { 9 | "selective-typecheck-common-module": "*" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /__fixtures__/source-type/packages/c/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "c", 3 | "private": false, 4 | "modular": { 5 | "type": "source" 6 | }, 7 | "main": "./src/index.ts", 8 | "version": "1.0.0", 9 | "dependencies": { 10 | "b": "1.0.0", 11 | "d": "1.0.0" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /packages/modular-scripts/src/build-scripts/webpack-scripts/utils/refreshOverlayInterop.ts: -------------------------------------------------------------------------------- 1 | import { dismissRuntimeErrors, reportRuntimeError } from 'react-error-overlay'; 2 | 3 | module.exports = { 4 | clearRuntimeErrors: dismissRuntimeErrors, 5 | handleRuntimeError: reportRuntimeError, 6 | }; 7 | -------------------------------------------------------------------------------- /__fixtures__/ghost-building/packages/a/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "a", 3 | "private": false, 4 | "modular": { 5 | "type": "package" 6 | }, 7 | "main": "./src/index.ts", 8 | "version": "1.0.0", 9 | "dependencies": { 10 | "b": "1.0.0", 11 | "c": "1.0.0" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /__fixtures__/ghost-testing/packages/a/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "a", 3 | "private": false, 4 | "modular": { 5 | "type": "package" 6 | }, 7 | "main": "./src/index.ts", 8 | "version": "1.0.0", 9 | "dependencies": { 10 | "b": "1.0.0", 11 | "c": "1.0.0" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /__fixtures__/selective-typecheck-example/packages/webpack-app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "webpack-app", 3 | "private": true, 4 | "modular": { 5 | "type": "app" 6 | }, 7 | "version": "1.0.0", 8 | "dependencies": { 9 | "selective-typecheck-common-module": "*" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /packages/tree-view-for-tests/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "tree-view-for-tests", 3 | "version": "2.0.1", 4 | "main": "src/index.ts", 5 | "license": "Apache-2.0", 6 | "private": true, 7 | "dependencies": { 8 | "@emotion/hash": "0.9.0", 9 | "ascii-tree": "0.3.0" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /__fixtures__/selective-lint/packages/beta-lint/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "beta-lint", 3 | "private": false, 4 | "modular": { 5 | "type": "package" 6 | }, 7 | "main": "./src/index.ts", 8 | "version": "1.0.0", 9 | "dependencies": { 10 | "gamma-lint": "1.0.0" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /__fixtures__/selective-lint/packages/gamma-lint/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "gamma-lint", 3 | "private": false, 4 | "modular": { 5 | "type": "package" 6 | }, 7 | "main": "./src/index.ts", 8 | "version": "1.0.0", 9 | "dependencies": { 10 | "delta-lint": "1.0.0" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /__fixtures__/remote-view/packages/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "remote-view", 3 | "version": "1.0.0", 4 | "author": "App Frameworks team", 5 | "license": "MIT", 6 | "private": true, 7 | "workspaces": [ 8 | "packages/**" 9 | ], 10 | "modular": { 11 | "type": "root" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /__fixtures__/selective-lint/packages/epsilon-lint/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "epsilon-lint", 3 | "private": false, 4 | "modular": { 5 | "type": "package" 6 | }, 7 | "main": "./src/index.ts", 8 | "version": "1.0.0", 9 | "dependencies": { 10 | "alpha-lint": "1.0.0" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /__fixtures__/selective-typecheck-example/packages/common-module/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "selective-typecheck-common-module", 3 | "private": false, 4 | "modular": { 5 | "type": "source" 6 | }, 7 | "main": "./src/index.ts", 8 | "types": "./src/index.ts", 9 | "version": "1.0.0" 10 | } 11 | -------------------------------------------------------------------------------- /packages/modular-scripts/src/build-scripts/esbuild-scripts/utils/formatPath.ts: -------------------------------------------------------------------------------- 1 | import path from 'path'; 2 | 3 | export function normalizeToPosix(pathName: T): T { 4 | return ( 5 | pathName ? pathName.split(path.win32.sep).join(path.posix.sep) : pathName 6 | ) as T; 7 | } 8 | -------------------------------------------------------------------------------- /packages/remote-view/README.md: -------------------------------------------------------------------------------- 1 | # `` 2 | 3 | `` is a Modular React component that enables the micro-frontend 4 | pattern using Modular [ESM views](https://modular.js.org/esm-views/). 5 | 6 | ## Docs 7 | 8 | View the [documentation](https://modular.js.org/components/remote-view/). 9 | -------------------------------------------------------------------------------- /packages/remote-view/src/context.ts: -------------------------------------------------------------------------------- 1 | import { createContext } from 'react'; 2 | import type { RemoteViewErrorsContext, RemoteViewsContext } from './types'; 3 | 4 | export const ViewsContext = createContext({}); 5 | 6 | export const ErrorContext = createContext({}); 7 | -------------------------------------------------------------------------------- /__fixtures__/ghost-testing/modular/setupTests.ts: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom/extend-expect'; 6 | -------------------------------------------------------------------------------- /__fixtures__/non-modular/modular/setupTests.ts: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom/extend-expect'; 6 | -------------------------------------------------------------------------------- /__fixtures__/resolve-workspace/clean-workspace-1/packages/app-one/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "app-one", 3 | "private": true, 4 | "modular": { 5 | "type": "app" 6 | }, 7 | "dependencies": { 8 | "package-one": "1.0.0", 9 | "package-two": "1.0.0" 10 | }, 11 | "version": "1.0.0" 12 | } 13 | -------------------------------------------------------------------------------- /__fixtures__/resolve-workspace/clean-workspace-2/packages/app-one/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "app-one", 3 | "private": true, 4 | "modular": { 5 | "type": "app" 6 | }, 7 | "dependencies": { 8 | "package-one": "1.0.0", 9 | "package-two": "1.0.0" 10 | }, 11 | "version": "1.0.0" 12 | } 13 | -------------------------------------------------------------------------------- /__fixtures__/source-type/modular/setupTests.ts: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom/extend-expect'; 6 | -------------------------------------------------------------------------------- /__fixtures__/ghost-building/modular/setupTests.ts: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom/extend-expect'; 6 | -------------------------------------------------------------------------------- /__fixtures__/resolve-workspace/invalid-workspace-1/packages/app-one/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "app-one", 3 | "private": true, 4 | "modular": { 5 | "type": "root" 6 | }, 7 | "dependencies": { 8 | "package-one": "1.0.0", 9 | "package-two": "1.0.0" 10 | }, 11 | "version": "1.0.0" 12 | } 13 | -------------------------------------------------------------------------------- /__fixtures__/resolve-workspace/mismatched-dependency/packages/app-one/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "app-one", 3 | "private": true, 4 | "modular": { 5 | "type": "app" 6 | }, 7 | "dependencies": { 8 | "package-one": "1.0.0", 9 | "package-two": "1.0.0" 10 | }, 11 | "version": "1.0.0" 12 | } 13 | -------------------------------------------------------------------------------- /__fixtures__/resolve-workspace/non-modular-workspace-1/packages/app-one/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "app-one", 3 | "private": true, 4 | "modular": { 5 | "type": "app" 6 | }, 7 | "dependencies": { 8 | "package-one": "1.0.0", 9 | "package-two": "1.0.0" 10 | }, 11 | "version": "1.0.0" 12 | } 13 | -------------------------------------------------------------------------------- /__fixtures__/selective-lint/modular/setupTests.ts: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom/extend-expect'; 6 | -------------------------------------------------------------------------------- /packages/create-modular-react-app/template/modular/setupTests.ts: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom'; 6 | -------------------------------------------------------------------------------- /__fixtures__/custom-workspace-root/modular/setupTests.ts: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom/extend-expect'; 6 | -------------------------------------------------------------------------------- /__fixtures__/remote-view/packages/view1/src/__tests__/index.test.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import { render } from 'react-dom'; 3 | import View1 from '../index'; 4 | 5 | test('it should render', () => { 6 | const el = document.createElement('div'); 7 | expect(() => render(, el)).not.toThrow(); 8 | }); 9 | -------------------------------------------------------------------------------- /__fixtures__/remote-view/packages/view2/src/__tests__/index.test.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import { render } from 'react-dom'; 3 | import View2 from '../index'; 4 | 5 | test('it should render', () => { 6 | const el = document.createElement('div'); 7 | expect(() => render(, el)).not.toThrow(); 8 | }); 9 | -------------------------------------------------------------------------------- /packages/modular-scripts/src/__tests__/__fixtures__/lint/InvalidTS.ts: -------------------------------------------------------------------------------- 1 | //@ts-nocheck 2 | /* eslint-disable */ 3 | 4 | interface Props {} 5 | 6 | export function funcHasNoType(props: Props) { 7 | const type: any = ''; 8 | 9 | if (type) { 10 | } else { 11 | } 12 | 13 | const emptyFunc = () => {}; 14 | } 15 | -------------------------------------------------------------------------------- /packages/modular-scripts/src/__tests__/__fixtures__/test/ValidTest.test.ts: -------------------------------------------------------------------------------- 1 | // eslint-disable-next-line jest/no-disabled-tests 2 | describe.skip('A passing test', () => { 3 | it('should pass', () => { 4 | expect(true).toBe(true); 5 | }); 6 | }); 7 | 8 | // eslint-disable-next-line jest/no-export 9 | export {}; 10 | -------------------------------------------------------------------------------- /packages/modular-scripts/src/__tests__/esbuild-scripts/__fixtures__/worker-plugin/index.ts: -------------------------------------------------------------------------------- 1 | import WorkerCls from './alive.worker.ts'; 2 | 3 | const worker = new WorkerCls(); 4 | 5 | worker.addEventListener('message', (event: MessageEvent) => { 6 | console.log(`Received message from worker: ${event.data}`); 7 | }); 8 | -------------------------------------------------------------------------------- /packages/modular-template-app/src/index.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import * as ReactDOM from 'react-dom'; 3 | import App from './App'; 4 | import './index.css'; 5 | 6 | ReactDOM.render( 7 | 8 | 9 | , 10 | document.getElementById('root'), 11 | ); 12 | -------------------------------------------------------------------------------- /packages/modular-types/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@modular-scripts/modular-types", 3 | "version": "1.2.1", 4 | "license": "Apache-2.0", 5 | "types": "src/types.ts", 6 | "publishConfig": { 7 | "access": "public" 8 | }, 9 | "dependencies": { 10 | "@schemastore/package": "0.0.6" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /__fixtures__/non-modular/packages/non-modular-non-buildable-non-testable/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "non-modular-non-buildable-non-testable", 3 | "private": false, 4 | "files": [ 5 | "dist", 6 | "src" 7 | ], 8 | "license": "UNLICENSED", 9 | "main": "./dist/index.js", 10 | "version": "1.0.0" 11 | } 12 | -------------------------------------------------------------------------------- /packages/modular-scripts/src/__tests__/__fixtures__/lint/InvalidTSX.tsx: -------------------------------------------------------------------------------- 1 | //@ts-nocheck 2 | /* eslint-disable */ 3 | 4 | import { useEffect } from 'react'; 5 | 6 | export function BadComponent(props) { 7 | if (props.name) { 8 | useEffect(function logMe() { 9 | console.log('Me!'); 10 | }); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /packages/modular-scripts/src/__tests__/__fixtures__/test/InvalidTest.test.ts: -------------------------------------------------------------------------------- 1 | // eslint-disable-next-line jest/no-disabled-tests 2 | describe.skip('A failing test', () => { 3 | it('should fail', () => { 4 | expect(true).toBe(false); 5 | }); 6 | }); 7 | 8 | // eslint-disable-next-line jest/no-export 9 | export {}; 10 | -------------------------------------------------------------------------------- /__fixtures__/non-modular/packages/app/src/index.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import * as ReactDOM from 'react-dom'; 3 | 4 | import App from './App'; 5 | import './index.css'; 6 | 7 | ReactDOM.render( 8 | 9 | 10 | , 11 | document.getElementById('root'), 12 | ); 13 | -------------------------------------------------------------------------------- /__fixtures__/remote-view/packages/view1/src/index.css: -------------------------------------------------------------------------------- 1 | .card-component { 2 | width: 480px; 3 | margin: auto; 4 | } 5 | 6 | .card-component .card { 7 | background-color: #f9f9f9; 8 | } 9 | 10 | .card-component .group { 11 | margin-bottom: 5px; 12 | } 13 | 14 | .card-component .button { 15 | margin-top: 14px; 16 | } 17 | -------------------------------------------------------------------------------- /__fixtures__/selective-lint/packages/alpha-lint/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "alpha-lint", 3 | "private": false, 4 | "modular": { 5 | "type": "package" 6 | }, 7 | "main": "./src/index.ts", 8 | "version": "1.0.0", 9 | "dependencies": { 10 | "beta-lint": "1.0.0", 11 | "gamma-lint": "1.0.0" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /__fixtures__/templates/modular-template-no-filter/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "modular-template-no-filter", 3 | "version": "0.0.1", 4 | "exports": { 5 | "./package.json": "./package.json" 6 | }, 7 | "modular": { 8 | "type": "template", 9 | "templateType": "app" 10 | }, 11 | "license": "Apache-2.0" 12 | } 13 | -------------------------------------------------------------------------------- /__fixtures__/custom-workspace-root/apps/app/src/index.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import * as ReactDOM from 'react-dom'; 3 | 4 | import App from './App'; 5 | import './index.css'; 6 | 7 | ReactDOM.render( 8 | 9 | 10 | , 11 | document.getElementById('root'), 12 | ); 13 | -------------------------------------------------------------------------------- /packages/workspace-resolver/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../modular-scripts/tsconfig.json", 3 | "compilerOptions": { 4 | "noEmit": false, 5 | "declaration": true, 6 | "emitDeclarationOnly": true, 7 | "outDir": "dist-cjs" 8 | }, 9 | "include": ["src/*"], 10 | "exclude": ["__tests__", "node_modules"] 11 | } 12 | -------------------------------------------------------------------------------- /__fixtures__/remote-view-fake-cdn/static/js/_trampoline.js: -------------------------------------------------------------------------------- 1 | import ReactDOM from 'http://localhost:8484/react-dom@17.0.2.js'; 2 | import React from 'http://localhost:8484/react@17.0.2.js'; 3 | import Component from './main.d2345139.js'; 4 | var DOMRoot = document.getElementById('root'); 5 | ReactDOM.render(React.createElement(Component, null), DOMRoot); 6 | -------------------------------------------------------------------------------- /__fixtures__/non-modular/packages/app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "app", 3 | "private": true, 4 | "modular": { 5 | "type": "app" 6 | }, 7 | "version": "1.0.0", 8 | "dependencies": { 9 | "non-modular-buildable": "1.0.0" 10 | }, 11 | "scripts": { 12 | "build": "echo 'I should never be executed' && exit -1" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /__fixtures__/templates/modular-template-non-modular/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "modular-template-non-modular", 3 | "version": "1.1.0", 4 | "exports": { 5 | "./package.json": "./package.json" 6 | }, 7 | "modular": { 8 | "type": "template" 9 | }, 10 | "license": "Apache-2.0", 11 | "files": [ 12 | "src" 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /packages/modular-scripts/src/__tests__/__fixtures__/packages/sample-depending-package/index.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/no-unsafe-call */ 2 | /* eslint-disable @typescript-eslint/no-unsafe-return */ 3 | // @ts-ignore 4 | import add from 'sample-library-package'; 5 | 6 | export function double(x: number): number { 7 | return add(x, x); 8 | } 9 | -------------------------------------------------------------------------------- /packages/modular-scripts/src/__tests__/__fixtures__/typecheck/InvalidTyping.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | //@ts-nocheck @ts-nocheck 3 | 4 | import foo from 'foo'; 5 | 6 | function convertToCelcius(temp: number): number { 7 | const result = (temp - 32) * (5 / 9); 8 | } 9 | 10 | window.__invalid__ = foo.bar; 11 | 12 | convertToCelcius('75'); 13 | -------------------------------------------------------------------------------- /__fixtures__/remote-view-fake-cdn/esm-view-card/static/js/_trampoline.js: -------------------------------------------------------------------------------- 1 | import ReactDOM from 'http://localhost:8484/react-dom@17.0.2.js'; 2 | import React from 'http://localhost:8484/react@17.0.2.js'; 3 | import Component from './main.5a34a408.js'; 4 | var DOMRoot = document.getElementById('root'); 5 | ReactDOM.render(React.createElement(Component, null), DOMRoot); 6 | -------------------------------------------------------------------------------- /__fixtures__/remote-view-fake-cdn/esm-view-list/static/js/_trampoline.js: -------------------------------------------------------------------------------- 1 | import ReactDOM from 'http://localhost:8484/react-dom@17.0.2.js'; 2 | import React from 'http://localhost:8484/react@17.0.2.js'; 3 | import Component from './main.874f720c.js'; 4 | var DOMRoot = document.getElementById('root'); 5 | ReactDOM.render(React.createElement(Component, null), DOMRoot); 6 | -------------------------------------------------------------------------------- /__fixtures__/selective-typecheck-example/packages/common-module/src/index.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | 3 | // The following TS nocheck flag gets removed in test 4 | // @ts-nocheck 5 | 6 | export default function add(a: number, b: number): number { 7 | return a + b + 'c'; 8 | } 9 | 10 | export function otherThing(input) { 11 | return typeof input; 12 | } 13 | -------------------------------------------------------------------------------- /__fixtures__/templates/modular-template-app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "modular-template-app", 3 | "version": "1.1.0", 4 | "exports": { 5 | "./package.json": "./package.json" 6 | }, 7 | "modular": { 8 | "type": "template", 9 | "templateType": "app" 10 | }, 11 | "license": "Apache-2.0", 12 | "files": [ 13 | "src" 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /__fixtures__/templates/modular-template-filter/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "modular-template-filter", 3 | "version": "0.0.1", 4 | "exports": { 5 | "./package.json": "./package.json" 6 | }, 7 | "modular": { 8 | "type": "template", 9 | "templateType": "app" 10 | }, 11 | "files": [ 12 | "src" 13 | ], 14 | "license": "Apache-2.0" 15 | } 16 | -------------------------------------------------------------------------------- /__fixtures__/non-modular/packages/non-modular-lintable/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "non-modular-lintable", 3 | "private": false, 4 | "scripts": { 5 | "lint": "echo 'non-modular-lintable was linted'" 6 | }, 7 | "files": [ 8 | "dist", 9 | "src" 10 | ], 11 | "license": "UNLICENSED", 12 | "main": "./dist/index.js", 13 | "version": "1.0.0" 14 | } 15 | -------------------------------------------------------------------------------- /__fixtures__/non-modular/packages/non-modular-testable/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "non-modular-testable", 3 | "private": false, 4 | "scripts": { 5 | "test": "echo 'non-modular-testable was tested'" 6 | }, 7 | "files": [ 8 | "dist", 9 | "src" 10 | ], 11 | "license": "UNLICENSED", 12 | "main": "./dist/index.js", 13 | "version": "1.0.0" 14 | } 15 | -------------------------------------------------------------------------------- /__fixtures__/remote-view-fake-cdn/view1/static/js/_trampoline.js: -------------------------------------------------------------------------------- 1 | import { createRoot } from 'https://esm.sh/react-dom@18.2.0/client'; 2 | import React from 'https://esm.sh/react@18.2.0'; 3 | import Component from './main.8285d3ce.js'; 4 | var container = document.getElementById('root'); 5 | var root = createRoot(container); 6 | root.render(React.createElement(Component, null)); 7 | -------------------------------------------------------------------------------- /__fixtures__/remote-view-fake-cdn/view2/static/js/_trampoline.js: -------------------------------------------------------------------------------- 1 | import { createRoot } from 'https://esm.sh/react-dom@18.2.0/client'; 2 | import React from 'https://esm.sh/react@18.2.0'; 3 | import Component from './main.95dbf0ef.js'; 4 | var container = document.getElementById('root'); 5 | var root = createRoot(container); 6 | root.render(React.createElement(Component, null)); 7 | -------------------------------------------------------------------------------- /__fixtures__/resolve-workspace/invalid-workspace-2/packages/app-one/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "app-one", 3 | "private": true, 4 | "modular": { 5 | "type": "app" 6 | }, 7 | "workspaces": [ 8 | "foo", 9 | "bar" 10 | ], 11 | "dependencies": { 12 | "package-one": "1.0.0", 13 | "package-two": "1.0.0" 14 | }, 15 | "version": "1.0.0" 16 | } 17 | -------------------------------------------------------------------------------- /__fixtures__/non-modular/packages/non-modular-buildable/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": ["src"], 3 | "compilerOptions": { 4 | "target": "es2018", 5 | "outDir": "dist", 6 | "lib": ["dom", "esnext"], 7 | "declaration": true, 8 | "moduleResolution": "node", 9 | "sourceMap": true, 10 | "strict": true, 11 | "esModuleInterop": true 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /__fixtures__/non-modular/packages/non-modular-lintable/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": ["src"], 3 | "compilerOptions": { 4 | "target": "es2018", 5 | "outDir": "dist", 6 | "lib": ["dom", "esnext"], 7 | "declaration": true, 8 | "moduleResolution": "node", 9 | "sourceMap": true, 10 | "strict": true, 11 | "esModuleInterop": true 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /__fixtures__/non-modular/packages/non-modular-testable/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": ["src"], 3 | "compilerOptions": { 4 | "target": "es2018", 5 | "outDir": "dist", 6 | "lib": ["dom", "esnext"], 7 | "declaration": true, 8 | "moduleResolution": "node", 9 | "sourceMap": true, 10 | "strict": true, 11 | "esModuleInterop": true 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /__fixtures__/remote-view/packages/esm-view-card/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "esm-view-card", 3 | "private": false, 4 | "modular": { 5 | "type": "esm-view", 6 | "externalCdnTemplate": "http://localhost:8484/[name]@[version]" 7 | }, 8 | "dependencies": {}, 9 | "version": "1.0.0", 10 | "devDependencies": {}, 11 | "files": [ 12 | "src" 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /__fixtures__/remote-view/packages/esm-view-list/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "esm-view-list", 3 | "private": false, 4 | "modular": { 5 | "type": "esm-view", 6 | "externalCdnTemplate": "http://localhost:8484/[name]@[version]" 7 | }, 8 | "dependencies": {}, 9 | "version": "1.0.0", 10 | "devDependencies": {}, 11 | "files": [ 12 | "src" 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /__fixtures__/custom-workspace-root/apps/app/src/__tests__/App.test.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import { render, screen } from '@testing-library/react'; 3 | import App from '../App'; 4 | 5 | test('renders learn react link', () => { 6 | render(); 7 | const linkElement = screen.getByText(/learn react/i); 8 | expect(linkElement).toBeInTheDocument(); 9 | }); 10 | -------------------------------------------------------------------------------- /__fixtures__/non-modular/packages/app/src/__tests__/App.test.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import { render, screen } from '@testing-library/react'; 3 | import App from '../App'; 4 | 5 | test('renders learn react link', () => { 6 | render(); 7 | const linkElement = screen.getByText(/The result is 14/i); 8 | expect(linkElement).toBeInTheDocument(); 9 | }); 10 | -------------------------------------------------------------------------------- /__fixtures__/non-modular/packages/non-modular-typecheckable/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": ["src"], 3 | "compilerOptions": { 4 | "target": "es2018", 5 | "outDir": "dist", 6 | "lib": ["dom", "esnext"], 7 | "declaration": true, 8 | "moduleResolution": "node", 9 | "sourceMap": true, 10 | "strict": true, 11 | "esModuleInterop": true 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /__fixtures__/templates/modular-template-app/src/__tests__/App.test.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import { render, screen } from '@testing-library/react'; 3 | import App from '../App'; 4 | 5 | test('renders learn react link', () => { 6 | render(); 7 | const linkElement = screen.getByText(/learn react/i); 8 | expect(linkElement).toBeInTheDocument(); 9 | }); 10 | -------------------------------------------------------------------------------- /__fixtures__/verifiable-project/packages/app-one/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "app-one", 3 | "private": true, 4 | "modular": { 5 | "type": "app" 6 | }, 7 | "dependencies": { 8 | "package-one": "workspace:*", 9 | "package-two": "workspace:*", 10 | "package-three": "workspace:*", 11 | "package-four": "workspace:*" 12 | }, 13 | "version": "1.0.0" 14 | } 15 | -------------------------------------------------------------------------------- /packages/modular-scripts/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "baseUrl": ".", 5 | "rootDir": "src", 6 | "noEmit": false, 7 | "declaration": true, 8 | "declarationDir": "dist-types", 9 | "emitDeclarationOnly": true 10 | }, 11 | "include": ["src/*"], 12 | "exclude": ["__tests__", "node_modules"] 13 | } 14 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "modular-scripts/tsconfig.json", 3 | "include": [ 4 | "modular", 5 | "packages/**/src", 6 | "packages/create-modular-react-app/template/" 7 | ], 8 | "compilerOptions": { 9 | "paths": { 10 | "@modular-scripts/workspace-resolver": [ 11 | "./packages/workspace-resolver/src" 12 | ] 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /__fixtures__/resolve-workspace/clean-workspace-1/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "clean-workspace-1", 3 | "version": "1.0.0", 4 | "author": "App Frameworks team", 5 | "license": "MIT", 6 | "private": true, 7 | "workspaces": [ 8 | "packages/**" 9 | ], 10 | "modular": { 11 | "type": "root" 12 | }, 13 | "dependencies": { 14 | "lodash": "^4.17.21" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /__fixtures__/resolve-workspace/clean-workspace-3/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "clean-workspace-3", 3 | "version": "1.0.0", 4 | "author": "App Frameworks team", 5 | "license": "MIT", 6 | "private": true, 7 | "workspaces": [ 8 | "packages/**" 9 | ], 10 | "modular": { 11 | "type": "root" 12 | }, 13 | "dependencies": { 14 | "lodash": "^4.17.21" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /packages/modular-scripts/src/build-scripts/webpack-scripts/utils/ignoredFiles.ts: -------------------------------------------------------------------------------- 1 | import path from 'path'; 2 | import escape from 'escape-string-regexp'; 3 | 4 | export default function ignoredFiles(appSrc: string) { 5 | return new RegExp( 6 | `^(?!${escape( 7 | path.normalize(appSrc + '/').replace(/[\\]+/g, '/'), 8 | )}).+/node_modules/`, 9 | 'g', 10 | ); 11 | } 12 | -------------------------------------------------------------------------------- /packages/modular-template-view/src/__tests__/index.test.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @jest-environment jsdom 3 | */ 4 | import * as React from 'react'; 5 | import { render } from 'react-dom'; 6 | import ComponentName from '../index'; 7 | 8 | test('it should render', () => { 9 | const el = document.createElement('div'); 10 | expect(() => render(, el)).not.toThrow(); 11 | }); 12 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # https://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | end_of_line = lf 7 | indent_size = 2 8 | indent_style = space 9 | insert_final_newline = true 10 | max_line_length = 80 11 | trim_trailing_whitespace = true 12 | 13 | [*.{md,mdx}] 14 | max_line_length = 0 15 | trim_trailing_whitespace = false 16 | 17 | [COMMIT_EDITMSG] 18 | max_line_length = 0 19 | -------------------------------------------------------------------------------- /__fixtures__/non-modular/packages/app/src/App.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import sum from 'non-modular-buildable'; 3 | 4 | function App(): JSX.Element { 5 | return ( 6 |
7 |

This is the sum:

8 |

9 | {`The result is ${sum(7, 7)}`} 10 |

11 |
12 | ); 13 | } 14 | 15 | export default App; 16 | -------------------------------------------------------------------------------- /__fixtures__/resolve-workspace/invalid-workspace-1/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "invalid-workspace-1", 3 | "version": "1.0.0", 4 | "author": "App Frameworks team", 5 | "license": "MIT", 6 | "private": true, 7 | "workspaces": [ 8 | "packages/**" 9 | ], 10 | "modular": { 11 | "type": "root" 12 | }, 13 | "dependencies": { 14 | "lodash": "^4.17.21" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /__fixtures__/resolve-workspace/invalid-workspace-2/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "invalid-workspace-2", 3 | "version": "1.0.0", 4 | "author": "App Frameworks team", 5 | "license": "MIT", 6 | "private": true, 7 | "workspaces": [ 8 | "packages/**" 9 | ], 10 | "modular": { 11 | "type": "root" 12 | }, 13 | "dependencies": { 14 | "lodash": "^4.17.21" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /__fixtures__/resolve-workspace/invalid-workspace-3/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "invalid-workspace-3", 3 | "version": "1.0.0", 4 | "author": "App Frameworks team", 5 | "license": "MIT", 6 | "private": true, 7 | "workspaces": [ 8 | "packages/**" 9 | ], 10 | "modular": { 11 | "type": "root" 12 | }, 13 | "dependencies": { 14 | "lodash": "^4.17.21" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /__fixtures__/resolve-workspace/invalid-workspace-4/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "invalid-workspace-3", 3 | "version": "1.0.0", 4 | "author": "App Frameworks team", 5 | "license": "MIT", 6 | "private": true, 7 | "workspaces": [ 8 | "packages/**" 9 | ], 10 | "modular": { 11 | "type": "root" 12 | }, 13 | "dependencies": { 14 | "lodash": "^4.17.21" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /__fixtures__/resolve-workspace/invalid-workspace-5/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "invalid-workspace-3", 3 | "version": "1.0.0", 4 | "author": "App Frameworks team", 5 | "license": "MIT", 6 | "private": true, 7 | "workspaces": [ 8 | "packages/**" 9 | ], 10 | "modular": { 11 | "type": "root" 12 | }, 13 | "dependencies": { 14 | "lodash": "^4.17.21" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /__fixtures__/non-modular/packages/non-modular-buildable/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "non-modular-buildable", 3 | "private": false, 4 | "scripts": { 5 | "build": "tsc --skipLibCheck && echo 'non-modular-buildable was built'" 6 | }, 7 | "files": [ 8 | "dist", 9 | "src" 10 | ], 11 | "license": "UNLICENSED", 12 | "main": "./dist/index.js", 13 | "version": "1.0.0" 14 | } 15 | -------------------------------------------------------------------------------- /__fixtures__/non-modular/packages/non-modular-non-buildable-non-testable/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": ["src"], 3 | "compilerOptions": { 4 | "target": "es2018", 5 | "outDir": "dist", 6 | "lib": ["dom", "esnext"], 7 | "declaration": true, 8 | "moduleResolution": "node", 9 | "sourceMap": true, 10 | "strict": true, 11 | "esModuleInterop": true 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /__fixtures__/non-modular/packages/non-modular-typecheckable/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "non-modular-typecheckable", 3 | "private": false, 4 | "scripts": { 5 | "typecheck": "echo 'non-modular-typecheckable was typechecked'" 6 | }, 7 | "files": [ 8 | "dist", 9 | "src" 10 | ], 11 | "license": "UNLICENSED", 12 | "main": "./dist/index.js", 13 | "version": "1.0.0" 14 | } 15 | -------------------------------------------------------------------------------- /__fixtures__/remote-view-fake-cdn/esm-view-card/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "esm-view-card", 3 | "version": "1.0.0", 4 | "modular": { 5 | "type": "esm-view", 6 | "externalCdnTemplate": "http://localhost:8484/[name]@[version]" 7 | }, 8 | "dependencies": { 9 | "react": "17.0.2" 10 | }, 11 | "bundledDependencies": [], 12 | "module": "/static/js/main.5a34a408.js" 13 | } 14 | -------------------------------------------------------------------------------- /__fixtures__/remote-view-fake-cdn/esm-view-list/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "esm-view-list", 3 | "version": "1.0.0", 4 | "modular": { 5 | "type": "esm-view", 6 | "externalCdnTemplate": "http://localhost:8484/[name]@[version]" 7 | }, 8 | "dependencies": { 9 | "react": "17.0.2" 10 | }, 11 | "bundledDependencies": [], 12 | "module": "/static/js/main.874f720c.js" 13 | } 14 | -------------------------------------------------------------------------------- /__fixtures__/resolve-workspace/mismatched-dependency/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mismatched-dependency", 3 | "version": "1.0.0", 4 | "author": "App Frameworks team", 5 | "license": "MIT", 6 | "private": true, 7 | "workspaces": [ 8 | "packages/**" 9 | ], 10 | "modular": { 11 | "type": "root" 12 | }, 13 | "dependencies": { 14 | "lodash": "^4.17.21" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /__fixtures__/resolve-workspace/non-modular-workspace-1/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "non-modular-workspace-1", 3 | "version": "1.0.0", 4 | "author": "App Frameworks team", 5 | "license": "MIT", 6 | "private": true, 7 | "workspaces": [ 8 | "packages/**" 9 | ], 10 | "modular": { 11 | "type": "root" 12 | }, 13 | "dependencies": { 14 | "lodash": "^4.17.21" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /__fixtures__/verifiable-project/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "verifiable-project", 3 | "version": "1.0.0", 4 | "author": "App Frameworks team", 5 | "license": "MIT", 6 | "private": true, 7 | "workspaces": [ 8 | "packages/**", 9 | "other-packages/**" 10 | ], 11 | "modular": { 12 | "type": "root" 13 | }, 14 | "dependencies": { 15 | "lodash": "^4.17.21" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /__fixtures__/resolve-workspace/clean-workspace-3/packages/app-one/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "app-one", 3 | "private": true, 4 | "modular": { 5 | "type": "app" 6 | }, 7 | "dependencies": { 8 | "package-one": "workspace:*", 9 | "package-two": "workspace:^", 10 | "package-three": "workspace:~", 11 | "package-four": "workspace:^1.0.0" 12 | }, 13 | "version": "1.0.0" 14 | } 15 | -------------------------------------------------------------------------------- /packages/remote-view/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | Refer to the 4 | [main Modular contributing guidelines](https://github.com/jpmorganchase/modular/blob/main/CONTRIBUTING.md) 5 | for a summary of contributing to Modular. 6 | 7 | ## Build 8 | 9 | To [build](https://modular.js.org/commands/build) this package, run: 10 | 11 | ```bash 12 | yarn modular build @modular-scripts/remote-view 13 | ``` 14 | -------------------------------------------------------------------------------- /__fixtures__/resolve-workspace/invalid-workspace-3/packages/app-one/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "app-one", 3 | "private": true, 4 | "modular": { 5 | "type": "app" 6 | }, 7 | "workspaces": { 8 | "packages": [ 9 | "foo", 10 | "bar" 11 | ] 12 | }, 13 | "dependencies": { 14 | "package-one": "1.0.0", 15 | "package-two": "1.0.0" 16 | }, 17 | "version": "1.0.0" 18 | } 19 | -------------------------------------------------------------------------------- /__fixtures__/ghost-building/.editorconfig: -------------------------------------------------------------------------------- 1 | # https://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | end_of_line = lf 7 | indent_size = 2 8 | indent_style = space 9 | insert_final_newline = true 10 | max_line_length = 80 11 | trim_trailing_whitespace = true 12 | 13 | [*.{md,mdx}] 14 | max_line_length = 0 15 | trim_trailing_whitespace = false 16 | 17 | [COMMIT_EDITMSG] 18 | max_line_length = 0 19 | -------------------------------------------------------------------------------- /__fixtures__/remote-view-fake-cdn/view1/asset-manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "files": { 3 | "main.css": "/static/css/main.1115b39e.css", 4 | "main.js": "/static/js/main.8285d3ce.js", 5 | "main.1115b39e.css.map": "/static/css/main.1115b39e.css.map", 6 | "main.8285d3ce.js.map": "/static/js/main.8285d3ce.js.map" 7 | }, 8 | "entrypoints": ["static/css/main.1115b39e.css", "static/js/main.8285d3ce.js"] 9 | } 10 | -------------------------------------------------------------------------------- /__fixtures__/source-type/.editorconfig: -------------------------------------------------------------------------------- 1 | # https://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | end_of_line = lf 7 | indent_size = 2 8 | indent_style = space 9 | insert_final_newline = true 10 | max_line_length = 80 11 | trim_trailing_whitespace = true 12 | 13 | [*.{md,mdx}] 14 | max_line_length = 0 15 | trim_trailing_whitespace = false 16 | 17 | [COMMIT_EDITMSG] 18 | max_line_length = 0 19 | -------------------------------------------------------------------------------- /packages/modular-template-app/src/__tests__/App.test.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @jest-environment jsdom 3 | */ 4 | import * as React from 'react'; 5 | import { render, screen } from '@testing-library/react'; 6 | import App from '../App'; 7 | 8 | test('renders learn react link', () => { 9 | render(); 10 | const linkElement = screen.getByText(/learn react/i); 11 | expect(linkElement).toBeInTheDocument(); 12 | }); 13 | -------------------------------------------------------------------------------- /.changeset/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://unpkg.com/@changesets/config@1.3.0/schema.json", 3 | "changelog": ["@changesets/changelog-github", { "repo": "jpmorganchase/modular" }], 4 | "commit": false, 5 | "linked": [], 6 | "access": "public", 7 | "baseBranch": "main", 8 | "updateInternalDependencies": "patch", 9 | "ignore": ["remote-view-demos"], 10 | "updateInternalDependents": "always" 11 | } 12 | -------------------------------------------------------------------------------- /docs/commands/check.md: -------------------------------------------------------------------------------- 1 | --- 2 | parent: Commands 3 | title: modular check 4 | --- 5 | 6 | # `modular check [options]` 7 | 8 | Checks the modular root repo has yarn workspaces and modular packages are set up 9 | properly and checks your package tree for issues with your dependencies. 10 | 11 | ## Options: 12 | 13 | `--fix`: Run autofix over applications 14 | 15 | `--verbose`: Run yarn commands with the --verbose flag set 16 | -------------------------------------------------------------------------------- /packages/create-modular-react-app/template/.editorconfig: -------------------------------------------------------------------------------- 1 | # https://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | end_of_line = lf 7 | indent_size = 2 8 | indent_style = space 9 | insert_final_newline = true 10 | max_line_length = 80 11 | trim_trailing_whitespace = true 12 | 13 | [*.{md,mdx}] 14 | max_line_length = 0 15 | trim_trailing_whitespace = false 16 | 17 | [COMMIT_EDITMSG] 18 | max_line_length = 0 19 | -------------------------------------------------------------------------------- /packages/modular-template-esm-view/src/__tests__/EsmView.test.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @jest-environment jsdom 3 | */ 4 | import * as React from 'react'; 5 | import { render, screen } from '@testing-library/react'; 6 | import EsmView from '..'; 7 | 8 | test('renders learn react link', () => { 9 | render(); 10 | const linkElement = screen.getByText(/learn react/i); 11 | expect(linkElement).toBeInTheDocument(); 12 | }); 13 | -------------------------------------------------------------------------------- /packages/modular-scripts/src/utils/isReactNewApi.ts: -------------------------------------------------------------------------------- 1 | import semver from 'semver'; 2 | import type { Dependency } from '@schemastore/package'; 3 | 4 | export function isReactNewApi(manifest: Dependency): boolean { 5 | // React >= 18 needs a different way of instantiating rendering. Find out if the project needs it. 6 | const reactVersion = manifest?.['react']; 7 | return Boolean(reactVersion && semver.gte(reactVersion, '18.0.0')); 8 | } 9 | -------------------------------------------------------------------------------- /packages/create-modular-react-app/template/gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # misc 12 | .DS_Store 13 | .env.local 14 | .env.development.local 15 | .env.test.local 16 | .env.production.local 17 | 18 | npm-debug.log* 19 | yarn-debug.log* 20 | yarn-error.log* 21 | 22 | /dist 23 | -------------------------------------------------------------------------------- /packages/modular-scripts/src/__tests__/TestViewPackages.test-tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import get from 'lodash/get'; 3 | import merge from 'lodash.merge'; 4 | import { difference } from 'lodash'; 5 | import 'regular-table/dist/css/material.css'; 6 | 7 | export default function SampleView(): JSX.Element { 8 | return ( 9 |
10 |
{JSON.stringify({ get, merge, difference })}
11 |
12 | ); 13 | } -------------------------------------------------------------------------------- /packages/modular-template-esm-view/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "modular-template-esm-view", 3 | "version": "2.0.0", 4 | "exports": { 5 | "./package.json": "./package.json" 6 | }, 7 | "modular": { 8 | "type": "template", 9 | "templateType": "esm-view" 10 | }, 11 | "eslintConfig": { 12 | "extends": "modular-app/recommended" 13 | }, 14 | "license": "Apache-2.0", 15 | "files": [ 16 | "src" 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /__fixtures__/ghost-building/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # misc 12 | .DS_Store 13 | .env.local 14 | .env.development.local 15 | .env.test.local 16 | .env.production.local 17 | 18 | npm-debug.log* 19 | yarn-debug.log* 20 | yarn-error.log* 21 | 22 | /dist 23 | 24 | .vscode 25 | -------------------------------------------------------------------------------- /__fixtures__/source-type/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # misc 12 | .DS_Store 13 | .env.local 14 | .env.development.local 15 | .env.test.local 16 | .env.production.local 17 | 18 | npm-debug.log* 19 | yarn-debug.log* 20 | yarn-error.log* 21 | 22 | /dist 23 | 24 | .vscode 25 | -------------------------------------------------------------------------------- /packages/modular-template-app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "modular-template-app", 3 | "version": "2.0.0", 4 | "exports": { 5 | "./package.json": "./package.json" 6 | }, 7 | "modular": { 8 | "type": "template", 9 | "templateType": "app" 10 | }, 11 | "eslintConfig": { 12 | "extends": "modular-app/recommended" 13 | }, 14 | "license": "Apache-2.0", 15 | "files": [ 16 | "public", 17 | "src" 18 | ] 19 | } 20 | -------------------------------------------------------------------------------- /__fixtures__/remote-view/packages/view2/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "view2", 3 | "version": "1.0.0", 4 | "main": "src/index.tsx", 5 | "license": "UNLICENSED", 6 | "modular": { 7 | "type": "esm-view", 8 | "externalCdnTemplate": "https://esm.sh/[name]@[version]" 9 | }, 10 | "dependencies": { 11 | "react": "18.2.0", 12 | "react-dom": "18.2.0", 13 | "minifaker": "1.34.1", 14 | "regular-table": "0.5.6" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /__fixtures__/source-type/.eslintignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # misc 12 | .DS_Store 13 | .env.local 14 | .env.development.local 15 | .env.test.local 16 | .env.production.local 17 | 18 | npm-debug.log* 19 | yarn-debug.log* 20 | yarn-error.log* 21 | 22 | packages/**/public 23 | /dist 24 | -------------------------------------------------------------------------------- /__fixtures__/ghost-building/.eslintignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # misc 12 | .DS_Store 13 | .env.local 14 | .env.development.local 15 | .env.test.local 16 | .env.production.local 17 | 18 | npm-debug.log* 19 | yarn-debug.log* 20 | yarn-error.log* 21 | 22 | packages/**/public 23 | /dist 24 | -------------------------------------------------------------------------------- /packages/modular-template-app/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 12 | monospace; 13 | } 14 | -------------------------------------------------------------------------------- /__fixtures__/non-modular/packages/app/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 12 | monospace; 13 | } 14 | -------------------------------------------------------------------------------- /packages/modular-scripts/src/utils/memoize.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/no-explicit-any */ 2 | 3 | export default function memoize R>(f: T): T { 4 | const memory = new Map(); 5 | 6 | const g = (...args: unknown[]) => { 7 | if (!memory.has(args.join())) { 8 | memory.set(args.join(), f(...args)); 9 | } 10 | 11 | return memory.get(args.join()); 12 | }; 13 | 14 | return g as T; 15 | } 16 | -------------------------------------------------------------------------------- /packages/modular-template-view/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "modular-template-view", 3 | "version": "2.0.0", 4 | "exports": { 5 | "./package.json": "./package.json" 6 | }, 7 | "main": "./src/index.tsx", 8 | "license": "Apache-2.0", 9 | "modular": { 10 | "type": "template", 11 | "templateType": "view" 12 | }, 13 | "eslintConfig": { 14 | "extends": "modular-app/recommended" 15 | }, 16 | "files": [ 17 | "src" 18 | ] 19 | } 20 | -------------------------------------------------------------------------------- /packages/create-modular-react-app/template/.eslintignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # misc 12 | .DS_Store 13 | .env.local 14 | .env.development.local 15 | .env.test.local 16 | .env.production.local 17 | 18 | npm-debug.log* 19 | yarn-debug.log* 20 | yarn-error.log* 21 | 22 | packages/**/public 23 | /dist 24 | -------------------------------------------------------------------------------- /packages/modular-template-package/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "modular-template-package", 3 | "version": "2.0.0", 4 | "exports": { 5 | "./package.json": "./package.json" 6 | }, 7 | "main": "./src/index.ts", 8 | "modular": { 9 | "type": "template", 10 | "templateType": "package" 11 | }, 12 | "eslintConfig": { 13 | "extends": "modular-app/recommended" 14 | }, 15 | "license": "Apache-2.0", 16 | "files": [ 17 | "src" 18 | ] 19 | } 20 | -------------------------------------------------------------------------------- /__fixtures__/custom-workspace-root/apps/app/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 12 | monospace; 13 | } 14 | -------------------------------------------------------------------------------- /__fixtures__/resolve-workspace/clean-workspace-2/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "clean-workspace-2", 3 | "version": "1.0.0", 4 | "author": "App Frameworks team", 5 | "license": "MIT", 6 | "private": true, 7 | "workspaces": { 8 | "packages": [ 9 | "packages/**" 10 | ], 11 | "nohoist": [ 12 | "foo" 13 | ] 14 | }, 15 | "modular": { 16 | "type": "root" 17 | }, 18 | "dependencies": { 19 | "lodash": "^4.17.21" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /packages/modular-scripts/src/analyze.ts: -------------------------------------------------------------------------------- 1 | import stripAnsi from 'strip-ansi'; 2 | import actionPreflightCheck from './utils/actionPreflightCheck'; 3 | import { getPackageDependencies } from './utils/getPackageDependencies'; 4 | 5 | async function analyze({ target }: { target: string }): Promise { 6 | console.log( 7 | stripAnsi(JSON.stringify(await getPackageDependencies(target), null, 2)), 8 | ); 9 | } 10 | 11 | export default actionPreflightCheck(analyze); 12 | -------------------------------------------------------------------------------- /docs/how-to/rename-package.md: -------------------------------------------------------------------------------- 1 | --- 2 | parent: How To 3 | nav_order: 2 4 | title: Rename Modular Package 5 | --- 6 | 7 | # Rename a Modular Package 8 | 9 | To rename a Modular package, find and replace the package name in the following 10 | places: 11 | 12 | - The `name` field in the package's package.json 13 | - All places where the package is imported/referenced 14 | 15 | Feel free to rename the package directory, although this will not have an impact 16 | on the package. 17 | -------------------------------------------------------------------------------- /packages/remote-view/src/utils/remote-view-error.ts: -------------------------------------------------------------------------------- 1 | import type { RemoteViewErrorInterface } from '../types'; 2 | 3 | export class RemoteViewError extends Error implements RemoteViewErrorInterface { 4 | remoteViewUrl: string; 5 | 6 | constructor(message: string, remoteViewUrl: string) { 7 | super(message); 8 | Object.setPrototypeOf(this, RemoteViewError.prototype); 9 | 10 | this.name = 'RemoteViewError'; 11 | this.remoteViewUrl = remoteViewUrl; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /__fixtures__/remote-view-fake-cdn/view1/static/css/main.1115b39e.css.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"static/css/main.1115b39e.css","mappings":"AAAA,gBAEE,WAAY,CADZ,WAEF,CAEA,sBACE,wBACF,CAEA,uBACE,iBACF,CAEA,wBACE,eACF","sources":["index.css"],"sourcesContent":[".card-component {\n width: 480px;\n margin: auto;\n}\n\n.card-component .card {\n background-color: #f9f9f9;\n}\n\n.card-component .group {\n margin-bottom: 5px;\n}\n\n.card-component .button {\n margin-top: 14px;\n}\n"],"names":[],"sourceRoot":""} -------------------------------------------------------------------------------- /__fixtures__/remote-view/packages/view1/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "view1", 3 | "version": "1.0.0", 4 | "main": "src/index.tsx", 5 | "license": "UNLICENSED", 6 | "modular": { 7 | "type": "esm-view", 8 | "externalCdnTemplate": "https://esm.sh/[name]@[version]" 9 | }, 10 | "dependencies": { 11 | "react": "18.2.0", 12 | "react-dom": "18.2.0", 13 | "@mantine/core": "5.10.4", 14 | "@mantine/hooks": "5.10.4", 15 | "minifaker": "1.34.1" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /packages/modular-template-source/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "modular-template-source", 3 | "version": "2.0.0", 4 | "exports": { 5 | "./package.json": "./package.json" 6 | }, 7 | "main": "./src/index.ts", 8 | "modular": { 9 | "type": "template", 10 | "templateType": "source" 11 | }, 12 | "eslintConfig": { 13 | "extends": "modular-app/recommended" 14 | }, 15 | "license": "Apache-2.0", 16 | "files": [ 17 | "README.md", 18 | "src" 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /integration-test-scripts/setupVerdaccio.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Install `verdaccio`, plus `forever`, which we use to run Verdaccio as a daemon i.e. in the background 4 | yarn global add verdaccio@5.15.4 5 | yarn global add forever 6 | 7 | # Start Verdaccio, via `forever` 8 | # This effectively daemonizes the running of verdaccio (i.e. makes it run in the background) 9 | forever start -c "sh" ./integration-test-scripts/startVerdaccio.sh 10 | 11 | npm ping --registry http://localhost:4873/ 12 | -------------------------------------------------------------------------------- /packages/remote-view-demos/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "remote-view-demos", 3 | "private": true, 4 | "modular": { 5 | "type": "esm-view", 6 | "externalCdnTemplate": "https://esm.sh/[name]@[version]" 7 | }, 8 | "version": "0.0.0", 9 | "dependencies": { 10 | "@modular-scripts/remote-view": "*", 11 | "@salt-ds/core": "1.1.0", 12 | "@salt-ds/lab": "1.0.0-alpha.1", 13 | "@salt-ds/theme": "1.0.0", 14 | "react": "17.0.2", 15 | "react-dom": "17.0.2" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /packages/create-modular-react-app/template/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "name": "Debug Tests", 6 | "type": "node", 7 | "request": "launch", 8 | "args": ["${relativeFile}"], 9 | "runtimeExecutable": "${workspaceRoot}/node_modules/.bin/modular", 10 | "runtimeArgs": ["test", "--watchAll=false"], 11 | "sourceMaps": true, 12 | "cwd": "${workspaceRoot}", 13 | "protocol": "inspector" 14 | } 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /__fixtures__/remote-view-fake-cdn/view1/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "view1", 3 | "version": "1.0.0", 4 | "license": "UNLICENSED", 5 | "modular": { 6 | "type": "esm-view", 7 | "externalCdnTemplate": "https://esm.sh/[name]@[version]" 8 | }, 9 | "dependencies": { 10 | "react": "18.2.0", 11 | "@mantine/core": "5.10.4", 12 | "minifaker": "1.34.1" 13 | }, 14 | "bundledDependencies": [], 15 | "module": "/static/js/main.8285d3ce.js", 16 | "style": "/static/css/main.1115b39e.css" 17 | } 18 | -------------------------------------------------------------------------------- /packages/remote-view/src/utils/dynamically-import.tsx: -------------------------------------------------------------------------------- 1 | import type { View } from '../types'; 2 | 3 | /** 4 | * Performs a dynamic (i.e. runtime) import of a remote ESM View 5 | * 6 | * Note that we cast to `View`, i.e. assume a React component is returned, but this is not guaranteed. 7 | */ 8 | export async function dynamicallyImport(remoteModuleUrl: string) { 9 | const { default: LoadedView } = (await import( 10 | /* webpackIgnore: true */ remoteModuleUrl 11 | )) as View; 12 | 13 | return LoadedView; 14 | } 15 | -------------------------------------------------------------------------------- /packages/tree-view-for-tests/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # tree-view-for-tests 2 | 3 | ## 2.0.1 4 | 5 | ### Patch Changes 6 | 7 | - [#1989](https://github.com/jpmorganchase/modular/pull/1989) 8 | [`e002b87`](https://github.com/jpmorganchase/modular/commit/e002b878597b8f08befaef78b91cfa4b4b78652a) 9 | Thanks [@dependabot](https://github.com/apps/dependabot)! - Bump @emotion/hash 10 | from 0.8.0 to 0.9.0 11 | 12 | ## 2.0.0 13 | 14 | ### Major Changes 15 | 16 | - af8f49f: Remove react-scripts as a dependency and release major change. 17 | -------------------------------------------------------------------------------- /__fixtures__/non-modular/packages/README.md: -------------------------------------------------------------------------------- 1 | # Workspaces 2 | 3 | This is the default 4 | [workspaces](https://classic.yarnpkg.com/lang/en/docs/workspaces/) root created 5 | by Create Modular React App. Packages added by the 6 | [`modular add`](https://modular.js.org/commands/add/) command will be located 7 | here by default, unless a different directory (included in the root 8 | package.json's 9 | [`workspaces` field](https://classic.yarnpkg.com/lang/en/docs/workspaces/#toc-how-to-use-it)) 10 | is specified using the `--path` option. 11 | -------------------------------------------------------------------------------- /packages/modular-scripts/jest-runner-eslint/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const { createJestRunner } = require('create-jest-runner'); 4 | 5 | const runner = createJestRunner( 6 | require.resolve('jest-runner-eslint/build/runner/runESLint'), 7 | { 8 | getExtraOptions: () => ({ 9 | cache: true, 10 | maxWarnings: 0, 11 | fix: process.env.MODULAR_LINT_FIX 12 | ? process.env.MODULAR_LINT_FIX.toLowerCase() === 'true' 13 | : false, 14 | }), 15 | }, 16 | ); 17 | 18 | module.exports = runner; 19 | -------------------------------------------------------------------------------- /patches/detect-port-alt+1.1.6.patch: -------------------------------------------------------------------------------- 1 | diff --git a/node_modules/detect-port-alt/index.d.ts b/node_modules/detect-port-alt/index.d.ts 2 | new file mode 100644 3 | index 0000000..982cba2 4 | --- /dev/null 5 | +++ b/node_modules/detect-port-alt/index.d.ts 6 | @@ -0,0 +1,4 @@ 7 | +declare function detectPort(defaultPort: number, host: string, ): Promise; 8 | +declare function detectPort(defaultPort: number, host: string, callback: (err: any, newPort: number) => any): void; 9 | + 10 | +export = detectPort; 11 | \ No newline at end of file 12 | -------------------------------------------------------------------------------- /__fixtures__/remote-view/packages/esm-view-card/src/index.tsx: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react'; 2 | 3 | export default function EsmCardView(): JSX.Element { 4 | const [contents, setContents] = useState('Some card contents'); 5 | 6 | return ( 7 |
8 |

My Card

9 | {contents} 10 | 17 |
18 | ); 19 | } 20 | -------------------------------------------------------------------------------- /packages/modular-template-node-env-app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "modular-template-node-env-app", 3 | "version": "0.2.1", 4 | "exports": { 5 | "./package.json": "./package.json" 6 | }, 7 | "private": true, 8 | "modular": { 9 | "type": "template", 10 | "templateType": "app" 11 | }, 12 | "eslintConfig": { 13 | "extends": "modular-app/recommended" 14 | }, 15 | "dependencies": { 16 | "lodash": "^4.17.21" 17 | }, 18 | "license": "Apache-2.0", 19 | "files": [ 20 | "public", 21 | "src" 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /packages/create-modular-react-app/template/packages/README.md: -------------------------------------------------------------------------------- 1 | # Workspaces 2 | 3 | This is the default 4 | [workspaces](https://classic.yarnpkg.com/lang/en/docs/workspaces/) root created 5 | by Create Modular React App. Packages added by the 6 | [`modular add`](https://modular.js.org/commands/add/) command will be located 7 | here by default, unless a different directory (included in the root 8 | package.json's 9 | [`workspaces` field](https://classic.yarnpkg.com/lang/en/docs/workspaces/#toc-how-to-use-it)) 10 | is specified using the `--path` option. 11 | -------------------------------------------------------------------------------- /packages/remote-view/src/components/remote-view.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { useRemoteView } from '../hooks/useRemoteView'; 3 | 4 | interface Props { 5 | url: string; 6 | loading?: JSX.Element; 7 | } 8 | 9 | function DefaultLoading() { 10 | return
Loading
; 11 | } 12 | 13 | export function RemoteView({ url, loading }: Props) { 14 | const ViewComponent = useRemoteView(url); 15 | const loadingOutput = loading ? loading : ; 16 | 17 | return (ViewComponent && ) || loadingOutput; 18 | } 19 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "configurations": [ 3 | { 4 | "name": "Debug Test", 5 | "type": "node", 6 | "request": "launch", 7 | "args": ["${relativeFile}"], 8 | "runtimeArgs": [ 9 | "--nolazy", 10 | "-r", 11 | "ts-node/register", 12 | "packages/modular-scripts/src/cli.ts", 13 | "test", 14 | "--watchAll=false", 15 | "--runInBand" 16 | ], 17 | "sourceMaps": true, 18 | "cwd": "${workspaceRoot}", 19 | "protocol": "inspector" 20 | } 21 | ] 22 | } 23 | -------------------------------------------------------------------------------- /packages/modular-scripts/src/utils/getLocation.ts: -------------------------------------------------------------------------------- 1 | import * as path from 'path'; 2 | import getModularRoot from './getModularRoot'; 3 | import getRelativeWorkspaceLocation from './getRelativeLocation'; 4 | 5 | /** 6 | * Get absolute workspace path for a given workspace/package name 7 | * @param name Name of the workspace 8 | * @returns 9 | */ 10 | export async function getWorkspaceLocation(name: string): Promise { 11 | return path.join(getModularRoot(), await getRelativeWorkspaceLocation(name)); 12 | } 13 | 14 | export default getWorkspaceLocation; 15 | -------------------------------------------------------------------------------- /.changeset/README.md: -------------------------------------------------------------------------------- 1 | # Changesets 2 | 3 | Hello and welcome! This folder has been automatically generated by 4 | `@changesets/cli`, a build tool that works with multi-package repos, or 5 | single-package repos to help you version and publish your code. You can find the 6 | full documentation for it 7 | [in our repository](https://github.com/changesets/changesets) 8 | 9 | We have a quick list of common questions to get you started engaging with this 10 | project in 11 | [our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md) 12 | -------------------------------------------------------------------------------- /__fixtures__/remote-view-fake-cdn/view2/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "view2", 3 | "version": "1.0.0", 4 | "license": "UNLICENSED", 5 | "modular": { 6 | "type": "esm-view", 7 | "externalCdnTemplate": "https://esm.sh/[name]@[version]" 8 | }, 9 | "dependencies": { 10 | "regular-table": "0.5.6", 11 | "react": "18.2.0", 12 | "minifaker": "1.34.1" 13 | }, 14 | "bundledDependencies": [], 15 | "module": "/static/js/main.95dbf0ef.js", 16 | "styleImports": [ 17 | "https://esm.sh/regular-table@0.5.6/dist/css/material.css" 18 | ] 19 | } 20 | -------------------------------------------------------------------------------- /packages/remote-view/src/components/default-remote-view-error-fallback.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { RemoteViewError } from '../utils/remote-view-error'; 3 | 4 | export function DefaultRemoteViewErrorFallback({ 5 | error, 6 | }: { 7 | error: RemoteViewError; 8 | }) { 9 | const { message, remoteViewUrl } = error; 10 | const formattedMsg = `Something went wrong for module at URL "${remoteViewUrl}".`; 11 | 12 | return ( 13 |
14 | {formattedMsg} 15 | {message &&
{message}
} 16 |
17 | ); 18 | } 19 | -------------------------------------------------------------------------------- /packages/remote-view/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @modular-scripts/remote-view 2 | 3 | ## 0.1.0 4 | 5 | ### Minor Changes 6 | 7 | - [#2284](https://github.com/jpmorganchase/modular/pull/2284) 8 | [`a4e2f21`](https://github.com/jpmorganchase/modular/commit/a4e2f21449e8f3c97665062d3bb997e28f410ec8) 9 | Thanks [@sgb-io](https://github.com/sgb-io)! - Implement RemoteView 10 | 11 | ### Patch Changes 12 | 13 | - Updated dependencies 14 | [[`a4e2f21`](https://github.com/jpmorganchase/modular/commit/a4e2f21449e8f3c97665062d3bb997e28f410ec8)]: 15 | - @modular-scripts/modular-types@1.2.0 16 | -------------------------------------------------------------------------------- /docs/concepts/versioning.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Versioning Packages 3 | parent: Concepts 4 | nav_order: 400 5 | --- 6 | 7 | # Version Control in a Modular Repository 8 | 9 | Modular's primary objective is to provide frictionless 10 | [build](../commands/build.md) and [test](../commands/test.md) functionality for 11 | your micro-frontend monorepo. 12 | 13 | How you version the built artifacts and run your CI pipelines is up to you, but 14 | we recommend [`changesets`](https://github.com/atlassian/changesets), a tool 15 | written by Atlassian which uses changeset files to generate new versions of 16 | packages. 17 | -------------------------------------------------------------------------------- /packages/modular-scripts/src/build-scripts/esbuild-scripts/start/plugins/metafileReporter.ts: -------------------------------------------------------------------------------- 1 | import { Plugin } from 'esbuild'; 2 | import type * as esbuild from 'esbuild'; 3 | 4 | type MetafileCallback = (metafile: esbuild.Metafile) => void; 5 | 6 | function createPlugin(callback: MetafileCallback): Plugin { 7 | const plugin: Plugin = { 8 | name: 'incremental-errors', 9 | setup(build) { 10 | build.onEnd((result) => { 11 | callback(result.metafile as esbuild.Metafile); 12 | }); 13 | }, 14 | }; 15 | 16 | return plugin; 17 | } 18 | 19 | export default createPlugin; 20 | -------------------------------------------------------------------------------- /packages/remote-view/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@modular-scripts/remote-view", 3 | "private": false, 4 | "modular": { 5 | "type": "package" 6 | }, 7 | "main": "./src/index.ts", 8 | "version": "0.1.2", 9 | "peerDependencies": { 10 | "react": ">=16.8.0", 11 | "react-dom": ">=16.8.0" 12 | }, 13 | "devDependencies": { 14 | "finalhandler": "^1.2.0", 15 | "serve-static": "^1.15.0" 16 | }, 17 | "dependencies": { 18 | "isomorphic-fetch": "^3.0.0", 19 | "@modular-scripts/modular-types": "^1.2.0" 20 | }, 21 | "publishConfig": { 22 | "directory": "dist" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /__fixtures__/remote-view/packages/esm-view-list/src/index.tsx: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react'; 2 | 3 | export default function EsmListView(): JSX.Element { 4 | const [contents, setContents] = useState(['foo', 'bar', 'baz']); 5 | 6 | return ( 7 |
8 |

My List

9 |
    10 | {contents.map((item) => ( 11 |
  • {item}
  • 12 | ))} 13 |
14 | 21 |
22 | ); 23 | } 24 | -------------------------------------------------------------------------------- /integration-test-scripts/verdaccio-config.yaml: -------------------------------------------------------------------------------- 1 | # Modular Verdaccio Config for CI 2 | 3 | storage: ./storage 4 | plugins: ./plugins 5 | 6 | web: 7 | title: Verdaccio 8 | 9 | auth: 10 | htpasswd: 11 | file: ./htpasswd 12 | 13 | uplinks: 14 | npmjs: 15 | url: https://registry.yarnpkg.com 16 | 17 | packages: 18 | '**': 19 | access: $all 20 | publish: $all 21 | unpublish: $all 22 | proxy: npmjs 23 | 24 | server: 25 | keepAliveTimeout: 60 26 | 27 | middlewares: 28 | audit: 29 | enabled: false 30 | 31 | logs: { type: stdout, format: pretty, level: http } 32 | 33 | i18n: 34 | web: en-US 35 | -------------------------------------------------------------------------------- /packages/remote-view/src/components/default-unknown-error-fallback.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | interface Props { 4 | error: Error; 5 | } 6 | 7 | /** 8 | * Used to catch unknown errors, i.e. errors that are not RemoteViewErrors. 9 | * This handles errors of any type within a tree, assuming the user is using the 10 | */ 11 | export function DefaultUnknownErrorFallback({ error }: Props) { 12 | const { message } = error; 13 | 14 | return ( 15 |
16 | Something went wrong 17 | {message &&
{message}
} 18 |
19 | ); 20 | } 21 | -------------------------------------------------------------------------------- /packages/modular-template-app/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /docs/commands/serve.md: -------------------------------------------------------------------------------- 1 | --- 2 | parent: Commands 3 | title: modular serve 4 | --- 5 | 6 | # `modular serve [options] ` 7 | 8 | Start a local HTTP server to serve an already-[built](./build.md) 9 | [application](../package-types/app.md) or 10 | [ESM View](../package-types/esm-view.md). This is different from 11 | [start](./start.md) in that it statically serves an already-built `app` or 12 | `esm-view` directly from `dist/` without injecting any run-time script. 13 | Use it to preview the result of a build with optimized bundles and minification. 14 | 15 | ## Options 16 | 17 | `--port`: Select the port to serve on (default: '3000') 18 | -------------------------------------------------------------------------------- /__fixtures__/selective-typecheck-example/packages/webpack-app/src/App.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import './App.css'; 3 | 4 | function App(): JSX.Element { 5 | return ( 6 |
7 |
8 |

9 | Edit src/App.tsx and save to reload. 10 |

11 | 17 | Learn React 18 | 19 |
20 |
21 | ); 22 | } 23 | 24 | export default App; 25 | -------------------------------------------------------------------------------- /packages/modular-scripts/src/utils/execAsync.ts: -------------------------------------------------------------------------------- 1 | import execa from 'execa'; 2 | import chalk from 'chalk'; 3 | import * as logger from './logger'; 4 | 5 | export default function execSync( 6 | file: string, 7 | args: string[], 8 | options: { log?: boolean } & execa.SyncOptions = { log: true }, 9 | ): execa.ExecaChildProcess { 10 | const { log, ...opts } = options; 11 | if (log) { 12 | logger.log(chalk.grey(`$ ${file} ${args.join(' ')}`)); 13 | } 14 | return execa(file, args, { 15 | stdin: process.stdin, 16 | stderr: process.stderr, 17 | stdout: process.stdout, 18 | cleanup: true, 19 | ...opts, 20 | }); 21 | } 22 | -------------------------------------------------------------------------------- /__fixtures__/custom-workspace-root/apps/app/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /__fixtures__/selective-typecheck-example/packages/esbuild-app/src/App.tsx: -------------------------------------------------------------------------------- 1 | import React, { useEffect } from 'react'; 2 | import './App.css'; 3 | 4 | function App(): JSX.Element { 5 | return ( 6 |
7 |
8 |

9 | Edit src/App.tsx and save to reload. 10 |

11 | 17 | Learn React 18 | 19 |
20 |
21 | ); 22 | } 23 | 24 | export default App; 25 | -------------------------------------------------------------------------------- /packages/modular-scripts/src/utils/getAllFiles.ts: -------------------------------------------------------------------------------- 1 | import * as path from 'path'; 2 | import * as fs from 'fs-extra'; 3 | 4 | // recursively get all files in a folder 5 | export default function getAllFiles( 6 | dirPath: string, 7 | arrayOfFiles: string[] = [], 8 | ): string[] { 9 | const files = fs.readdirSync(dirPath); 10 | 11 | files.forEach(function (file) { 12 | const pathToCheck = path.join(dirPath, file); 13 | if (fs.statSync(pathToCheck).isDirectory()) { 14 | arrayOfFiles = getAllFiles(pathToCheck, arrayOfFiles); 15 | } else { 16 | arrayOfFiles.push(pathToCheck); 17 | } 18 | }); 19 | 20 | return arrayOfFiles; 21 | } 22 | -------------------------------------------------------------------------------- /docs/releases/3.6.x.md: -------------------------------------------------------------------------------- 1 | --- 2 | parent: Release Notes 3 | title: 3.6.x 4 | --- 5 | 6 | # Modular 3.6.0 7 | 8 | - Selective builds (support for `--changed`, `--compareBranch`, `--ancestors`, 9 | `--descendants` flags in `modular build`). 10 | 11 | # Merged Changes 12 | 13 | - `modular-scripts` @ 3.6.0 - See 14 | [the GitHub release](https://github.com/jpmorganchase/modular/releases/tag/modular-scripts%403.6.0) 15 | for full details 16 | 17 | # Patch Versions 18 | 19 | Patch versions of this release do not have a dedicated summary. For details of 20 | patch releases, please visit 21 | [the GitHub releases page](https://github.com/jpmorganchase/modular/releases). 22 | -------------------------------------------------------------------------------- /packages/modular-scripts/src/utils/getRelativeLocation.ts: -------------------------------------------------------------------------------- 1 | import getWorkspaceInfo from './getWorkspaceInfo'; 2 | 3 | export async function getRelativeWorkspaceLocation( 4 | name: string, 5 | ): Promise { 6 | const workspaceInfo = await getWorkspaceInfo(); 7 | const workspace = workspaceInfo[name]; 8 | if (workspace) { 9 | return workspace.location; 10 | } else { 11 | const available = Object.keys(workspaceInfo); 12 | throw new Error( 13 | `Could not find ${name} in current workspace. Available packages are \n\t${available.join( 14 | '\n\t', 15 | )}`, 16 | ); 17 | } 18 | } 19 | 20 | export default getRelativeWorkspaceLocation; 21 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | // We're only using this file for builds right now. 2 | // It'll go away once we self host builds as well. 3 | 4 | 'use strict'; 5 | 6 | module.exports = (api) => { 7 | api.cache(true); 8 | 9 | return { 10 | presets: [ 11 | [ 12 | '@babel/preset-env', 13 | { 14 | targets: { 15 | // TODO: can we get this to read from package.json somehow..? 16 | node: '16', 17 | }, 18 | }, 19 | ], 20 | '@babel/preset-react', 21 | ], 22 | overrides: [ 23 | { 24 | test: /\.tsx?$/, 25 | presets: ['@babel/preset-typescript'], 26 | }, 27 | ], 28 | }; 29 | }; 30 | -------------------------------------------------------------------------------- /.github/workflows/validate.yml: -------------------------------------------------------------------------------- 1 | name: 'Validate' 2 | on: 3 | push: 4 | branches: [main, 'release/**', 'feature/**'] 5 | pull_request: 6 | branches: [main, 'release/**', 'feature/**'] 7 | 8 | jobs: 9 | check-yarn-lock-registry: 10 | name: 'Validate yarn.lock' 11 | runs-on: ubuntu-latest 12 | steps: 13 | - name: Checkout 14 | uses: actions/checkout@v3 15 | - name: Use Node.js 18 16 | uses: actions/setup-node@v3.3.0 17 | with: 18 | node-version: 18 19 | cache: 'yarn' 20 | - name: Install Dependencies 21 | run: yarn --frozen-lockfile 22 | - name: Check yarn.lock registry url 23 | run: yarn validate-lockfile 24 | -------------------------------------------------------------------------------- /docs/releases/3.3.x.md: -------------------------------------------------------------------------------- 1 | --- 2 | parent: Release Notes 3 | title: 3.3.x 4 | --- 5 | 6 | # Modular 3.3.0 7 | 8 | - Add support for selective testing (`--ancestors`, `--changed`, 9 | `--compareBranch` new flags in `modular test`) 10 | - Add support for linting staged files (`--staged` flag) 11 | 12 | # Merged Changes 13 | 14 | - `modular-scripts` @ 3.3.0 - See 15 | [the GitHub release](https://github.com/jpmorganchase/modular/releases/tag/modular-scripts%403.3.0) 16 | for full details 17 | 18 | # Patch Versions 19 | 20 | Patch versions of this release do not have a dedicated summary. For details of 21 | patch releases, please visit 22 | [the GitHub releases page](https://github.com/jpmorganchase/modular/releases). 23 | -------------------------------------------------------------------------------- /packages/modular-scripts/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2017", 4 | "downlevelIteration": true, 5 | "lib": ["dom", "dom.iterable", "esnext", "WebWorker"], 6 | "allowJs": true, 7 | "skipLibCheck": true, 8 | "esModuleInterop": true, 9 | "allowSyntheticDefaultImports": true, 10 | "strict": true, 11 | "forceConsistentCasingInFileNames": true, 12 | "noFallthroughCasesInSwitch": true, 13 | "module": "commonjs", 14 | "moduleResolution": "node", 15 | "resolveJsonModule": true, 16 | "isolatedModules": true, 17 | "noEmit": true, 18 | "jsx": "react", 19 | "sourceMap": true 20 | }, 21 | "ts-node": { 22 | "swc": true 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /packages/modular-template-app/src/App.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import logo from './logo.svg'; 3 | import './App.css'; 4 | 5 | function App(): JSX.Element { 6 | return ( 7 |
8 |
9 | logo 10 |

11 | Edit src/App.tsx and save to reload. 12 |

13 | 19 | Learn React 20 | 21 |
22 |
23 | ); 24 | } 25 | 26 | export default App; 27 | -------------------------------------------------------------------------------- /__fixtures__/custom-workspace-root/apps/app/src/App.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import logo from './logo.svg'; 3 | import './App.css'; 4 | 5 | function App(): JSX.Element { 6 | return ( 7 |
8 |
9 | logo 10 |

11 | Edit src/App.tsx and save to reload. 12 |

13 | 19 | Learn React 20 | 21 |
22 |
23 | ); 24 | } 25 | 26 | export default App; 27 | -------------------------------------------------------------------------------- /__fixtures__/templates/modular-template-app/src/App.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import logo from './logo.svg'; 3 | import './App.css'; 4 | 5 | function App(): JSX.Element { 6 | return ( 7 |
8 |
9 | logo 10 |

11 | Edit src/App.tsx and save to reload. 12 |

13 | 19 | Learn React 20 | 21 |
22 |
23 | ); 24 | } 25 | 26 | export default App; 27 | -------------------------------------------------------------------------------- /packages/modular-template-esm-view/src/index.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import logo from './logo.svg'; 3 | import './EsmView.css'; 4 | 5 | export default function EsmView(): JSX.Element { 6 | return ( 7 |
8 |
9 | logo 10 |

11 | Edit src/index.tsx and save to reload. 12 |

13 | 19 | Learn React 20 | 21 |
22 |
23 | ); 24 | } 25 | -------------------------------------------------------------------------------- /packages/modular-template-app/src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | height: 40vmin; 7 | pointer-events: none; 8 | } 9 | 10 | @media (prefers-reduced-motion: no-preference) { 11 | .App-logo { 12 | animation: App-logo-spin infinite 20s linear; 13 | } 14 | } 15 | 16 | .App-header { 17 | background-color: #282c34; 18 | min-height: 100vh; 19 | display: flex; 20 | flex-direction: column; 21 | align-items: center; 22 | justify-content: center; 23 | font-size: calc(10px + 2vmin); 24 | color: white; 25 | } 26 | 27 | .App-link { 28 | color: #61dafb; 29 | } 30 | 31 | @keyframes App-logo-spin { 32 | from { 33 | transform: rotate(0deg); 34 | } 35 | to { 36 | transform: rotate(360deg); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /packages/modular-template-node-env-app/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # modular-template-node-env-app 2 | 3 | ## 0.2.1 4 | 5 | ### Patch Changes 6 | 7 | - [#2050](https://github.com/jpmorganchase/modular/pull/2050) 8 | [`2241c2b`](https://github.com/jpmorganchase/modular/commit/2241c2b2c900e21fd1cc29f1d3e6d75c6f6ec372) 9 | Thanks [@joshwooding](https://github.com/joshwooding)! - Remove explicit 10 | package.json and license entry in files array 11 | 12 | ## 0.2.0 13 | 14 | ### Minor Changes 15 | 16 | - [#1636](https://github.com/jpmorganchase/modular/pull/1636) 17 | [`0201846`](https://github.com/jpmorganchase/modular/commit/0201846b39a67610f9b5f653421f0c3ed86f078b) 18 | Thanks [@steveukx](https://github.com/steveukx)! - Include template contents 19 | in published packages 20 | -------------------------------------------------------------------------------- /scripts/validate-lockfile.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const lockfile = require('@yarnpkg/lockfile'); 4 | const fs = require('fs'); 5 | const path = require('path'); 6 | 7 | const lockfilePath = path.join(__dirname, '..', 'yarn.lock'); 8 | 9 | let file = fs.readFileSync(lockfilePath, 'utf8'); 10 | let json = lockfile.parse(file); 11 | 12 | let failed = false; 13 | for (const entry of Object.entries(json.object)) { 14 | const [dependency, resolution] = entry; 15 | const { resolved, version } = resolution; 16 | if (/jpmchase\.net/.test(resolved)) { 17 | failed = true; 18 | console.error(`${dependency}@${version}: ${resolved}`); 19 | } 20 | } 21 | 22 | if (failed) { 23 | console.log('FAILED'); 24 | process.exit(1); 25 | } else { 26 | process.exit(0); 27 | } 28 | -------------------------------------------------------------------------------- /__fixtures__/custom-workspace-root/apps/app/src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | height: 40vmin; 7 | pointer-events: none; 8 | } 9 | 10 | @media (prefers-reduced-motion: no-preference) { 11 | .App-logo { 12 | animation: App-logo-spin infinite 20s linear; 13 | } 14 | } 15 | 16 | .App-header { 17 | background-color: #282c34; 18 | min-height: 100vh; 19 | display: flex; 20 | flex-direction: column; 21 | align-items: center; 22 | justify-content: center; 23 | font-size: calc(10px + 2vmin); 24 | color: white; 25 | } 26 | 27 | .App-link { 28 | color: #61dafb; 29 | } 30 | 31 | @keyframes App-logo-spin { 32 | from { 33 | transform: rotate(0deg); 34 | } 35 | to { 36 | transform: rotate(360deg); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /packages/modular-scripts/src/__tests__/utils/getWorkspaceInfo.test.ts: -------------------------------------------------------------------------------- 1 | import { getWorkspaceInfo } from '../../utils/getWorkspaceInfo'; 2 | import type { WorkspaceInfo } from '../../utils/getWorkspaceInfo'; 3 | 4 | test('getWorkspaceInfo', async () => { 5 | const collected: WorkspaceInfo = {}; 6 | const workspace = await getWorkspaceInfo(); 7 | 8 | // Check that a version string exists but, exclude the version 9 | // from the snapshot comparison, to avoid intefering when version bumping happens 10 | Object.entries(workspace).forEach(([key, workspaceRecord]) => { 11 | const { version, ...record } = workspaceRecord; 12 | expect(typeof version).toBe('string'); 13 | collected[key] = { ...record }; 14 | }); 15 | 16 | expect(collected).toMatchSnapshot(); 17 | }); 18 | -------------------------------------------------------------------------------- /packages/eslint-config-modular-app/README.md: -------------------------------------------------------------------------------- 1 | ## eslint-config-modular-app 2 | 3 | An ESLint config, made for `create-modular-react-app`/`modular-scripts`. It's 4 | simply 5 | [`eslint-config-react-app`](https://www.npmjs.com/package/eslint-config-react-app) 6 | with dependencies bundled in. 7 | 8 | If you want to extend the ESLint configuration in a modular repo, add the 9 | following configuration in your project's root folder `package.json` with the 10 | following content: 11 | 12 | "eslintConfig": { 13 | "extends": "modular-app" 14 | } 15 | 16 | That's it! Add your additional config to this file. Read more about 17 | [extending sharable configuration packages here](https://eslint.org/docs/user-guide/configuring/configuration-files#using-a-shareable-configuration-package). 18 | -------------------------------------------------------------------------------- /packages/modular-scripts/src/__tests__/__snapshots__/app.node-env.test.ts.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`when working with a NODE_ENV app WHEN building with esbuild can generate a js/index-L2US6VEL.js 1`] = ` 4 | "console.log("production"); 5 | //# sourceMappingURL=/static/js/index-L2US6VEL.js.map 6 | " 7 | `; 8 | 9 | exports[`when working with a NODE_ENV app WHEN building with webpack can generate a js/main.a482480b.js 1`] = ` 10 | ""use strict"; 11 | (self.webpackChunknode_env_app = self.webpackChunknode_env_app || []).push([ 12 | [179], 13 | { 14 | 908: () => { 15 | console.log("production"); 16 | }, 17 | }, 18 | (e) => { 19 | var n; 20 | (n = 908), e((e.s = n)); 21 | }, 22 | ]); 23 | //# sourceMappingURL=main.a482480b.js.map 24 | " 25 | `; 26 | -------------------------------------------------------------------------------- /packages/modular-scripts/src/build-scripts/esbuild-scripts/start/plugins/firstCompile.ts: -------------------------------------------------------------------------------- 1 | import type { BuildResult, Plugin } from 'esbuild'; 2 | 3 | type ResolveCallback = () => void; 4 | type ResultCallback = (result: BuildResult) => void; 5 | 6 | function createPlugin( 7 | firstCompileCallback: ResolveCallback, 8 | rebuildCallback: ResultCallback, 9 | ): Plugin { 10 | const plugin: Plugin = { 11 | name: 'first-compile-reporter', 12 | setup(build) { 13 | let isFirstCompile = true; 14 | 15 | build.onEnd((result) => { 16 | rebuildCallback(result); 17 | if (isFirstCompile) { 18 | isFirstCompile = false; 19 | firstCompileCallback(); 20 | } 21 | }); 22 | }, 23 | }; 24 | 25 | return plugin; 26 | } 27 | 28 | export default createPlugin; 29 | -------------------------------------------------------------------------------- /docs/esm-views/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | has_children: true 3 | title: ESM Views 4 | nav_order: 700 5 | --- 6 | 7 | # ESM Views 8 | 9 | Modular builds packages of `"type": "esm-view"` as 10 | [ES Modules](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules), 11 | rewriting all of a subset of their imports to make use of a configurable ESM CDN 12 | (e.g. [Skypack](https://www.skypack.dev) or [esm.sh](https://esm.sh/)). This 13 | allows users to implement the 14 | [microfrontend pattern](../concepts/microfrontends.md), by creating an artifact 15 | that can be 16 | [`import`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import#dynamic_imports)ed 17 | at runtime by a host application, or loaded stand-alone thanks to the automatic 18 | generation of the `index.html` and trampoline file. 19 | -------------------------------------------------------------------------------- /packages/remote-view/src/types.ts: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import { loading } from './utils/symbol'; 3 | import { RemoteViewError } from './utils/remote-view-error'; 4 | import type { MicrofrontendManifest } from '@modular-scripts/modular-types'; 5 | 6 | export type AppRegView = { 7 | name: string; 8 | root: string; 9 | manifest: string; 10 | }; 11 | 12 | export interface View { 13 | default: React.ComponentType; 14 | } 15 | 16 | export type RemoteViewsContext = Record< 17 | string, 18 | React.ComponentType | typeof loading 19 | >; 20 | 21 | export type RemoteViewErrorsContext = Record; 22 | 23 | export type ManifestCheck = (manifest: MicrofrontendManifest) => boolean; 24 | 25 | export interface RemoteViewErrorInterface extends Error { 26 | remoteViewUrl: string; 27 | } 28 | -------------------------------------------------------------------------------- /packages/modular-scripts/src/build-scripts/webpack-scripts/utils/redirectServedPathMiddleware.ts: -------------------------------------------------------------------------------- 1 | import path from 'path'; 2 | import { NextFunction, Request, Response } from 'express'; 3 | 4 | export default function createRedirectServedPathMiddleware(servedPath: string) { 5 | // remove end slash so user can land on `/test` instead of `/test/` 6 | servedPath = servedPath.slice(0, -1); 7 | return function redirectServedPathMiddleware( 8 | req: Request, 9 | res: Response, 10 | next: NextFunction, 11 | ) { 12 | if ( 13 | servedPath === '' || 14 | req.url === servedPath || 15 | req.url.startsWith(servedPath) 16 | ) { 17 | next(); 18 | } else { 19 | const newPath = path.join(servedPath, req.path !== '/' ? req.path : ''); 20 | res.redirect(newPath); 21 | } 22 | }; 23 | } 24 | -------------------------------------------------------------------------------- /docs/releases/3.5.x.md: -------------------------------------------------------------------------------- 1 | --- 2 | parent: Release Notes 3 | title: 3.5.x 4 | --- 5 | 6 | # Modular 3.5.0 7 | 8 | - External (CDN) CSS in esm-views will be exported in `styleImports` array field 9 | - Fixed `modular add` from template not copying all template files when no 10 | "files" field is specified in the package.json 11 | - Caniuse db updated in browserlist 12 | - Add `repository` field to the output manifest 13 | 14 | # Merged Changes 15 | 16 | - `modular-scripts` @ 3.5.0 - See 17 | [the GitHub release](https://github.com/jpmorganchase/modular/releases/tag/modular-scripts%403.5.0) 18 | for full details 19 | 20 | # Patch Versions 21 | 22 | Patch versions of this release do not have a dedicated summary. For details of 23 | patch releases, please visit 24 | [the GitHub releases page](https://github.com/jpmorganchase/modular/releases). 25 | -------------------------------------------------------------------------------- /packages/modular-scripts/src/build-scripts/esbuild-scripts/start/utils/getHost.ts: -------------------------------------------------------------------------------- 1 | import chalk from 'chalk'; 2 | import memoize from '../../../../utils/memoize'; 3 | import * as logger from '../../../../utils/logger'; 4 | 5 | const getHost = memoize(() => { 6 | if (process.env.HOST) { 7 | logger.log( 8 | chalk.cyan( 9 | `Attempting to bind to HOST environment variable: ${chalk.yellow( 10 | chalk.bold(process.env.HOST), 11 | )}`, 12 | ), 13 | ); 14 | logger.log( 15 | `If this was unintentional, check that you haven't mistakenly set it in your shell.`, 16 | ); 17 | logger.log( 18 | `Learn more here: ${chalk.yellow('https://cra.link/advanced-config')}`, 19 | ); 20 | logger.log(); 21 | } 22 | return process.env.HOST || '0.0.0.0'; 23 | }); 24 | 25 | export default getHost; 26 | -------------------------------------------------------------------------------- /packages/remote-view/src/__tests__/serve.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const path = require('path'); 4 | const http = require('http'); 5 | const serveStatic = require('serve-static'); 6 | const finalhandler = require('finalhandler'); 7 | 8 | // Serve the 2 ESM views (the build output of both) 9 | const esmViewsPath = path.resolve( 10 | __dirname, 11 | '..', 12 | '..', 13 | '..', 14 | '..', 15 | '__fixtures__', 16 | 'remote-view-fake-cdn', 17 | ); 18 | 19 | const serve = serveStatic(esmViewsPath); 20 | 21 | // Create server 22 | const server = http.createServer(function onRequest(req, res) { 23 | res.setHeader('Access-Control-Allow-Origin', '*'); 24 | serve(req, res, finalhandler(req, res)); 25 | }); 26 | 27 | // Listen 28 | const port = 8484; 29 | console.log(`Static server (remote-view) launched on port ${port}`); 30 | server.listen(port); 31 | -------------------------------------------------------------------------------- /packages/modular-template-source/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # modular-template-source 2 | 3 | ## 2.0.0 4 | 5 | ### Major Changes 6 | 7 | - [#2369](https://github.com/jpmorganchase/modular/pull/2369) 8 | [`3141f92`](https://github.com/jpmorganchase/modular/commit/3141f9259afccff4fbac9d5428d4d4b7714b9911) 9 | Thanks [@AlbertoBrusa](https://github.com/AlbertoBrusa)! - Added new 10 | recommended eslint configuration that includes import sorting - 11 | "modular-app/recommended" 12 | 13 | ## 1.1.0 14 | 15 | ### Minor Changes 16 | 17 | - [#2264](https://github.com/jpmorganchase/modular/pull/2264) 18 | [`75718c4`](https://github.com/jpmorganchase/modular/commit/75718c4feaa19216683523e0ec10165b40b2b059) 19 | Thanks [@AlbertoBrusa](https://github.com/AlbertoBrusa)! - Generate README 20 | inside newly created packages Improve root and default workspaces container 21 | README 22 | -------------------------------------------------------------------------------- /packages/modular-scripts/src/utils/checkBrowsers.ts: -------------------------------------------------------------------------------- 1 | import * as os from 'os'; 2 | import browserslist from 'browserslist'; 3 | import chalk from 'chalk'; 4 | 5 | export const defaultBrowsers = { 6 | production: ['>0.2%', 'not dead', 'not op_mini all'], 7 | development: [ 8 | 'last 1 chrome version', 9 | 'last 1 firefox version', 10 | 'last 1 safari version', 11 | ], 12 | }; 13 | 14 | export function checkBrowsers(dir: string): Promise { 15 | const current = browserslist.loadConfig({ path: dir }); 16 | if (current != null) { 17 | return Promise.resolve(); 18 | } else { 19 | return Promise.reject( 20 | new Error( 21 | chalk.red('Modular requires that you specify targeted browsers.') + 22 | os.EOL + 23 | `Run ${chalk.blue('modular check --fix')} to autofix this.`, 24 | ), 25 | ); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /packages/modular-scripts/src/__tests__/memoize.test.ts: -------------------------------------------------------------------------------- 1 | import memoize from '../utils/memoize'; 2 | 3 | describe('memoize', () => { 4 | function createSymbol(description?: string) { 5 | return Symbol(description); 6 | } 7 | 8 | it('Memoize memoizes a function with non-empty arguments', () => { 9 | const getMemoizedSymbol = memoize(createSymbol); 10 | 11 | expect(getMemoizedSymbol('my-symbol')).toEqual( 12 | getMemoizedSymbol('my-symbol'), 13 | ); 14 | expect(createSymbol('my-other-symbol')).not.toEqual( 15 | createSymbol('my-other-symbol'), 16 | ); 17 | }); 18 | 19 | it('Memoize memoizes a function with empty arguments', () => { 20 | const getMemoizedSymbol = memoize(createSymbol); 21 | 22 | expect(getMemoizedSymbol()).toEqual(getMemoizedSymbol()); 23 | expect(createSymbol()).not.toEqual(createSymbol()); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /packages/remote-view/src/__tests__/default-unknown-error-fallback.test.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @jest-environment jsdom 3 | */ 4 | 5 | import React from 'react'; 6 | import { render, screen, waitFor } from '@testing-library/react'; 7 | import { DefaultUnknownErrorFallback } from '../components/default-unknown-error-fallback'; 8 | 9 | describe('RemoteView DefaultUnknownErrorFallback', () => { 10 | beforeEach(() => { 11 | jest.spyOn(console, 'error').mockImplementation(() => undefined); 12 | }); 13 | 14 | it('should render an error as expected', async () => { 15 | const thrownError = new TypeError('Fake TypeError'); 16 | render(); 17 | const failText = 'Something went wrong'; 18 | 19 | await waitFor(() => screen.findByText(failText)); 20 | expect(screen.getByText(failText)).toBeInTheDocument(); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # Dependencies 4 | node_modules 5 | 6 | # created by tests in modular-scripts 7 | packages/sample-app 8 | packages/sample-esbuild-app 9 | packages/sample-view 10 | packages/sample-package 11 | 12 | # Build output 13 | /packages/**/build/ 14 | /packages/**/dist-cjs/ 15 | /packages/**/dist-types/ 16 | 17 | # Testing 18 | /coverage 19 | 20 | # Misc 21 | .DS_Store 22 | .eslintcache 23 | 24 | # Editors 25 | .idea 26 | 27 | # Logs 28 | npm-debug.log* 29 | yarn-debug.log* 30 | yarn-error.log* 31 | 32 | /dist 33 | /packages/**/dist-cjs/ 34 | /packages/**/dist-types/ 35 | 36 | # Used by typescript for incremental builds 37 | .tsbuildinfo 38 | *.tsbuildinfo 39 | 40 | # Top level test fixtures 41 | /__fixtures__ 42 | 43 | # Only used in RemoteView tests 44 | __fixtures__/remote-view-fake-cdn -------------------------------------------------------------------------------- /packages/modular-scripts/src/utils/checkRequiredFiles.ts: -------------------------------------------------------------------------------- 1 | import * as path from 'path'; 2 | import * as fs from 'fs-extra'; 3 | import chalk from 'chalk'; 4 | import * as logger from './logger'; 5 | 6 | export default async function checkRequiredFiles( 7 | files: string[], 8 | ): Promise { 9 | let currentFilePath: string = files[0]; 10 | try { 11 | for (const filePath of files) { 12 | currentFilePath = filePath; 13 | await fs.access(filePath, fs.constants.F_OK); 14 | } 15 | } catch (err) { 16 | const dirName = path.dirname(currentFilePath); 17 | const fileName = path.basename(currentFilePath); 18 | logger.log(chalk.red('Could not find a required file.')); 19 | logger.log(chalk.red(' Name: ') + chalk.cyan(fileName)); 20 | logger.log(chalk.red(' Searched in: ') + chalk.cyan(dirName)); 21 | throw new Error(`Could not find ${fileName}`); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /packages/modular-scripts/src/build-scripts/common-scripts/errorOverlayMiddleware.ts: -------------------------------------------------------------------------------- 1 | import * as express from 'express'; 2 | import launchEditor from './launchEditor'; 3 | 4 | export default function createLaunchEditorMiddleware() { 5 | return function launchEditorMiddleware( 6 | req: express.Request, 7 | res: express.Response, 8 | next: express.NextFunction, 9 | ) { 10 | if ( 11 | req.url.startsWith('/__open-stack-frame-in-editor') && 12 | typeof req.query.lineNumber === 'string' && 13 | typeof req.query.colNumber === 'string' && 14 | typeof req.query.fileName === 'string' 15 | ) { 16 | const lineNumber = parseInt(req.query.lineNumber, 10) || 1; 17 | const colNumber = parseInt(req.query.colNumber, 10) || 1; 18 | launchEditor(req.query.fileName, lineNumber, colNumber); 19 | res.end(); 20 | } else { 21 | next(); 22 | } 23 | }; 24 | } 25 | -------------------------------------------------------------------------------- /packages/modular-scripts/src/utils/getPrefixedLogger.ts: -------------------------------------------------------------------------------- 1 | import * as logger from './logger'; 2 | import memoize from './memoize'; 3 | 4 | export type Logger = typeof logger; 5 | 6 | function _getPrefixedLogger(target: string): Logger { 7 | const prefix = '$ ' + target + ':'; 8 | 9 | return { 10 | clear: () => { 11 | logger.clear(); 12 | }, 13 | debug: (...args: Parameters) => { 14 | logger.debug(prefix, ...args); 15 | }, 16 | log: (...args: Parameters) => { 17 | return logger.log(prefix, ...args); 18 | }, 19 | error: (...args: Parameters) => { 20 | return logger.error(prefix, ...args); 21 | }, 22 | warn: (...args: Parameters) => { 23 | return logger.error(prefix, ...args); 24 | }, 25 | }; 26 | } 27 | 28 | export default memoize Logger>(_getPrefixedLogger); 29 | -------------------------------------------------------------------------------- /docs/img/modular-hero.svg: -------------------------------------------------------------------------------- 1 | modular-hero -------------------------------------------------------------------------------- /packages/remote-view/src/hooks/useRemoteView.tsx: -------------------------------------------------------------------------------- 1 | import React, { useContext } from 'react'; 2 | import { ErrorContext, ViewsContext } from '../context'; 3 | import { loading } from '../utils/symbol'; 4 | import { RemoteViewError } from '../utils/remote-view-error'; 5 | import 'isomorphic-fetch'; 6 | 7 | export const useRemoteView = (baseUrl: string): React.ComponentType | null => { 8 | const views = useContext(ViewsContext); 9 | const errors = useContext(ErrorContext); 10 | const remoteViewError = errors[baseUrl]; 11 | const currentView = views[baseUrl]; 12 | 13 | if (remoteViewError) { 14 | throw new RemoteViewError(remoteViewError.message, baseUrl); 15 | } 16 | 17 | // Initial render (loading has not yet started) 18 | if (currentView === undefined) { 19 | return null; 20 | } 21 | 22 | // Loading render 23 | if (currentView === loading) { 24 | return null; 25 | } 26 | 27 | return currentView; 28 | }; 29 | -------------------------------------------------------------------------------- /packages/tree-view-for-tests/src/__tests__/tree.test.ts: -------------------------------------------------------------------------------- 1 | import * as path from 'path'; 2 | import * as fs from 'fs-extra'; 3 | import rimraf from 'rimraf'; 4 | import tree from '../index'; 5 | 6 | const testDir = 'tree-test'; 7 | 8 | beforeEach(() => { 9 | fs.mkdirSync(path.join(__dirname, testDir)); 10 | const files = ['foo.js', 'bar.js']; 11 | files.forEach((file: string) => 12 | fs.createFileSync(path.join(__dirname, testDir, file)), 13 | ); 14 | }); 15 | 16 | afterEach(() => { 17 | rimraf.sync(path.join(__dirname, testDir)); 18 | }); 19 | 20 | test('it can serialise a folder', () => { 21 | // this needs to be a folder that doesn't change during tests, 22 | // so can't include any .test.ts files that actually use this. 23 | // I picked one of our packages instead. 24 | expect(tree(path.join(__dirname, testDir))).toMatchInlineSnapshot(` 25 | "tree-test 26 | ├─ bar.js #0 27 | └─ foo.js #0" 28 | `); 29 | }); 30 | -------------------------------------------------------------------------------- /packages/modular-scripts/src/build-scripts/esbuild-scripts/utils/formatError.ts: -------------------------------------------------------------------------------- 1 | import * as path from 'path'; 2 | import { Message } from 'esbuild'; 3 | import chalk from 'chalk'; 4 | import * as fs from 'fs-extra'; 5 | import { codeFrameColumns } from '@babel/code-frame'; 6 | 7 | export async function formatError( 8 | error: Message, 9 | baseDir: string = process.cwd(), 10 | ): Promise { 11 | if (error.location?.file) { 12 | const pathToFile = path.join(baseDir, error.location?.file); 13 | const source = await fs.readFile(pathToFile, { 14 | encoding: 'utf-8', 15 | }); 16 | return `${chalk.red('Error:')}[${error.location.file}] ${error.text} 17 | 18 | ${codeFrameColumns( 19 | source, 20 | { start: { line: error.location.line, column: error.location.column } }, 21 | { 22 | highlightCode: true, 23 | }, 24 | )} 25 | `; 26 | } else { 27 | return `${chalk.red('Error:')} ${error.text}\n`; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /packages/modular-scripts/src/utils/resolveAsBin.ts: -------------------------------------------------------------------------------- 1 | import * as path from 'path'; 2 | import * as fs from 'fs-extra'; 3 | import type { ModularPackageJson } from '@modular-scripts/modular-types'; 4 | 5 | async function getBin(packageDir: string) { 6 | const packageJson = (await fs.readJson( 7 | path.join(packageDir, 'package.json'), 8 | )) as ModularPackageJson; 9 | if (!packageJson.bin) { 10 | throw Error(`No bins found.`); 11 | } else { 12 | if (typeof packageJson.bin === 'string') { 13 | return packageJson.bin; 14 | } else { 15 | const bins = Object.values(packageJson.bin); 16 | return bins[0] as string; 17 | } 18 | } 19 | } 20 | 21 | export async function resolveAsBin(packageName: string): Promise { 22 | const packageDir = path.dirname( 23 | require.resolve(`${packageName}/package.json`), 24 | ); 25 | const bin = await getBin(packageDir); 26 | return path.join(packageDir, bin); 27 | } 28 | -------------------------------------------------------------------------------- /packages/workspace-resolver/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@modular-scripts/workspace-resolver", 3 | "version": "2.0.0", 4 | "license": "Apache-2.0", 5 | "main": "src/index.ts", 6 | "dependencies": { 7 | "@esm2cjs/globby": "13.1.4", 8 | "fs-extra": "^10.1.0", 9 | "semver": "7.3.7" 10 | }, 11 | "devDependencies": { 12 | "@modular-scripts/modular-types": "1.2.1", 13 | "@types/fs-extra": "^9.0.13" 14 | }, 15 | "scripts": { 16 | "build": "tsc && babel --source-maps --root-mode upward src --out-dir dist-cjs --extensions .ts --ignore **/__tests__", 17 | "clean": "rimraf dist-cjs", 18 | "prepublishOnly": "node ../../scripts/extend-publish-config.js" 19 | }, 20 | "files": [ 21 | "dist-cjs" 22 | ], 23 | "types": "src/index.ts", 24 | "publishConfig": { 25 | "access": "public" 26 | }, 27 | "extendedPublishConfig": { 28 | "main": "dist-cjs/index.js", 29 | "types": "dist-cjs/index.d.ts" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /packages/modular-scripts/src/utils/reportTSDiagnostics.ts: -------------------------------------------------------------------------------- 1 | import * as ts from 'typescript'; 2 | import getPrefixedLogger from './getPrefixedLogger'; 3 | 4 | // from https://github.com/Microsoft/TypeScript/issues/6387 5 | // a helper to output a readable message from a ts diagnostics object 6 | export function reportTSDiagnostics( 7 | packagePath: string, 8 | diagnostics: ts.Diagnostic[], 9 | ): void { 10 | const logger = getPrefixedLogger(packagePath); 11 | 12 | diagnostics.forEach((diagnostic) => { 13 | let message = `Error`; 14 | if (diagnostic.file) { 15 | const where = diagnostic.file.getLineAndCharacterOfPosition( 16 | diagnostic.start as number, 17 | ); 18 | message += ` ${diagnostic.file.fileName} ${where.line}, ${ 19 | where.character + 1 20 | }`; 21 | } 22 | message += 23 | ': ' + ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n'); 24 | logger.error(message); 25 | }); 26 | } 27 | -------------------------------------------------------------------------------- /packages/modular-scripts/src/utils/actionPreflightCheck.ts: -------------------------------------------------------------------------------- 1 | import * as logger from './logger'; 2 | import getModularRoot from './getModularRoot'; 3 | 4 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 5 | type ModularAction = (...args: any[]) => Promise; 6 | 7 | function actionPreflightCheck(fn: ModularAction): ModularAction { 8 | const wrappedFn: ModularAction = async (...args) => { 9 | // Bail out if there is no modular root 10 | getModularRoot(); 11 | if (process.env.SKIP_PREFLIGHT_CHECK !== 'true') { 12 | const { check } = await import('../check'); 13 | await check({ fix: false }); 14 | } else { 15 | logger.warn( 16 | 'Preflight check is skipped. Modular repository may be invalid.', 17 | ); 18 | } 19 | 20 | // eslint-disable-next-line @typescript-eslint/no-unsafe-argument 21 | return fn(...args); 22 | }; 23 | 24 | return wrappedFn; 25 | } 26 | 27 | export default actionPreflightCheck; 28 | -------------------------------------------------------------------------------- /packages/modular-template-source/README.md: -------------------------------------------------------------------------------- 1 | # `PackageName__` 2 | 3 | This is a [Modular Source package](https://modular.js.org/package-types/source) 4 | 5 | # Build 6 | 7 | Source packages cannot be built; the 8 | [`build`](https://modular.js.org/commands/build.md) command will ignore them 9 | without throwing an error, to allow for selective builds to still succeed if 10 | their dependency graph contains one or more `source` packages. 11 | 12 | ## Start 13 | 14 | Source package cannot be started; attempting to do so will cause Modular to 15 | throw an error. 16 | 17 | ## Entry-point 18 | 19 | Source packages are imported from their source files directly, so they don't 20 | have the concept of "entry-point". 21 | 22 | ## Template 23 | 24 | Sources are generated by `modular add` using the 25 | [`modular-template-source`](https://github.com/jpmorganchase/modular/tree/main/packages/modular-template-source) 26 | [template](https://modular.js.org/package-types/template.md). 27 | -------------------------------------------------------------------------------- /packages/tree-view-for-tests/README.md: -------------------------------------------------------------------------------- 1 | ## tree-view-for-tests 2 | 3 | This is used for generating a tree view of a folder structure, with hashes of 4 | files contents. Useful for tests, particularly when used with inline snapshots. 5 | Example usage: 6 | 7 | ```jsx 8 | import tree from 'tree-view-for-tests'; 9 | 10 | // ... 11 | expect(tree('path/to/folder/')).toMatchInlineSnapshot(); 12 | ``` 13 | 14 | Example output: 15 | 16 | ``` 17 | create-modular-react-app 18 | ├─ .npmignore #1rstiru 19 | ├─ CHANGELOG.md #1qszd4f 20 | ├─ package.json 21 | ├─ src 22 | │ ├─ __tests__ 23 | │ │ └─ index.test.ts #1lutspt 24 | │ ├─ cli.ts #1m487e6 25 | │ └─ index.ts #govck 26 | └─ template 27 | ├─ README.md #1nksyzj 28 | ├─ gitignore #1ugsijf 29 | ├─ modular 30 | │ └─ setupTests.ts #bnjknz 31 | ├─ packages 32 | │ └─ README.md #14bthrh 33 | ├─ shared 34 | │ └─ README.md #1aqc5yw 35 | └─ tsconfig.json #1y19cv2 36 | ``` 37 | -------------------------------------------------------------------------------- /packages/create-modular-react-app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "create-modular-react-app", 3 | "version": "6.0.0", 4 | "license": "Apache-2.0", 5 | "bin": { 6 | "create-modular-react-app": "build/cli.js" 7 | }, 8 | "main": "./build/index.js", 9 | "exports": { 10 | ".": "./build/index.js", 11 | "./package.json": "./package.json" 12 | }, 13 | "engines": { 14 | "node": ">=16.10.0 || >=18.0.0 || >=20.0.0" 15 | }, 16 | "scripts": { 17 | "create-modular-react-app": "ts-node src/cli.ts", 18 | "clean": "rimraf build", 19 | "prebuild": "yarn clean", 20 | "build": "babel --root-mode upward src --out-dir build --extensions .ts --ignore 'src/**/*.test.ts'" 21 | }, 22 | "dependencies": { 23 | "chalk": "4.1.2", 24 | "commander": "9.4.0", 25 | "execa": "5.1.1", 26 | "fs-extra": "10.1.0", 27 | "semver": "7.3.7" 28 | }, 29 | "devDependencies": { 30 | "@schemastore/package": "0.0.6", 31 | "rimraf": "3.0.2" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /packages/modular-scripts/src/__tests__/__snapshots__/build.test.ts.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`WHEN building with preserve modules SHOULD create the correct index.js 1`] = ` 4 | "export { default } from './index2.js'; 5 | //# sourceMappingURL=index.js.map 6 | " 7 | `; 8 | 9 | exports[`WHEN building with preserve modules SHOULD create the correct index2.js 1`] = ` 10 | "async function runInAsync() { 11 | const { runAsync } = await import('./runAsync.js'); 12 | return runAsync(); 13 | } 14 | 15 | export { runInAsync as default }; 16 | //# sourceMappingURL=index2.js.map 17 | " 18 | `; 19 | 20 | exports[`WHEN building with preserve modules SHOULD create the correct runAsync.js 1`] = ` 21 | "function runAsync() { 22 | return new Promise((resolve) => { 23 | setTimeout(() => { 24 | console.log("done"); 25 | resolve(); 26 | }, 1e3); 27 | }); 28 | } 29 | 30 | export { runAsync }; 31 | //# sourceMappingURL=runAsync.js.map 32 | " 33 | `; 34 | -------------------------------------------------------------------------------- /packages/modular-scripts/src/build-scripts/esbuild-scripts/utils/absoluteSourceMapsMiddleware.ts: -------------------------------------------------------------------------------- 1 | import * as path from 'path'; 2 | import * as fs from 'fs-extra'; 3 | import type { Request, Response } from 'express'; 4 | 5 | type SourceMap = { sources: string[] }; 6 | 7 | /* This middleware remedies this issue - https://github.com/evanw/esbuild/pull/1234, 8 | where paths in sources that are relative to outDir break react-error-overlay. 9 | This is to be used before static. 10 | */ 11 | 12 | export function createAbsoluteSourceMapMiddleware(outDir: string) { 13 | return function sourceMapMiddleware(req: Request, res: Response): void { 14 | const filePath = path.join(outDir, req.path); 15 | void fs.readJson(filePath).then((sourceMapObject: SourceMap) => { 16 | // Make all paths absolute 17 | sourceMapObject.sources = sourceMapObject.sources.map((sourcePath) => 18 | path.join(outDir, sourcePath), 19 | ); 20 | res.json(sourceMapObject); 21 | }); 22 | }; 23 | } 24 | -------------------------------------------------------------------------------- /scripts/extend-publish-config.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const { writeFileSync } = require('fs'); 4 | const { resolve } = require('path'); 5 | 6 | // This script applies the contents of any `extendedPublishConfig` blocks 7 | // to the root package.json of affected packages in PACKAGES_TO_EXTEND. 8 | // 9 | // It also removes `scripts` on the assumption none are needed when installing npm libraries. 10 | 11 | const PACKAGES_TO_EXTEND = ['workspace-resolver']; 12 | 13 | function writeNewPackageJson(src, content) { 14 | writeFileSync(src, JSON.stringify(content, null, 2)); 15 | } 16 | 17 | function updatePackageJson(src) { 18 | const { extendedPublishConfig, scripts, ...pkg } = require(src); 19 | 20 | return { 21 | ...pkg, 22 | ...extendedPublishConfig, 23 | }; 24 | } 25 | 26 | PACKAGES_TO_EXTEND.forEach((dirName) => { 27 | const src = resolve(__dirname, `../packages/${dirName}`, 'package.json'); 28 | const content = updatePackageJson(src); 29 | writeNewPackageJson(src, content); 30 | }); 31 | -------------------------------------------------------------------------------- /packages/modular-scripts/src/utils/LineFilterOutStream.ts: -------------------------------------------------------------------------------- 1 | import { Transform } from 'stream'; 2 | 3 | export default class LineFilterOutStream extends Transform { 4 | // A stream transform to filter out lines that pass the regexp test 5 | buffer = ''; 6 | pattern: RegExp; 7 | 8 | constructor(pattern: RegExp) { 9 | super(); 10 | this.pattern = pattern; 11 | } 12 | 13 | _transform( 14 | chunk: unknown, 15 | encoding: BufferEncoding, 16 | callback: (error?: Error | null, data?: string) => void, 17 | ): void { 18 | const data = String(chunk); 19 | const lines = data.split('\n'); 20 | 21 | // Handle last line which is probably incomplete 22 | lines[0] = this.buffer + lines[0]; 23 | this.buffer = lines.pop() ?? ''; 24 | 25 | const output = lines.reduce((acc, line) => { 26 | if (!this.pattern.test(line)) { 27 | acc += `${line}\n`; 28 | } 29 | return acc; 30 | }, ''); 31 | 32 | this.push(output); 33 | callback(); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /packages/remote-view-demos/src/examples/my-error-boundary.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { RemoteViewError } from '@modular-scripts/remote-view'; 3 | 4 | interface BoundaryState { 5 | error: RemoteViewError | undefined; 6 | } 7 | 8 | interface BoundaryProps { 9 | content?: React.ComponentType; 10 | children?: React.ReactNode; 11 | } 12 | 13 | export class MyErrorBoundary extends React.Component< 14 | BoundaryProps, 15 | BoundaryState 16 | > { 17 | constructor(props: BoundaryProps) { 18 | super(props); 19 | this.state = { error: undefined }; 20 | } 21 | 22 | componentDidCatch(error: RemoteViewError, errorInfo: React.ErrorInfo): void { 23 | const { message } = error; 24 | console.error(message); 25 | console.error(errorInfo.componentStack); 26 | this.setState({ error }); 27 | } 28 | 29 | render() { 30 | if (this.state.error) { 31 | return
The error was: {this.state.error.message}
; 32 | } 33 | 34 | return this.props.children; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # To get started with Dependabot version updates, you'll need to specify which 2 | # package ecosystems to update and where the package manifests are located. 3 | # Please see the documentation for all configuration options: 4 | # https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates 5 | 6 | version: 2 7 | updates: 8 | - package-ecosystem: 'npm' # See documentation for possible values 9 | directory: '/' # Location of package manifests 10 | schedule: 11 | interval: 'weekly' 12 | # Allow up to 10 open pull requests for NPM dependencies 13 | open-pull-requests-limit: 10 14 | # Ignore major version bumps for all dependencies 15 | ignore: 16 | - dependency-name: '*' 17 | update-types: ['version-update:semver-major'] 18 | - package-ecosystem: 'github-actions' 19 | directory: '/' 20 | schedule: 21 | interval: 'weekly' 22 | # Allow up to 10 open pull requests for actions 23 | open-pull-requests-limit: 10 24 | -------------------------------------------------------------------------------- /patches/react-error-overlay+6.0.9.patch: -------------------------------------------------------------------------------- 1 | diff --git a/node_modules/react-error-overlay/index.d.ts b/node_modules/react-error-overlay/index.d.ts 2 | new file mode 100644 3 | index 0000000..04929fb 4 | --- /dev/null 5 | +++ b/node_modules/react-error-overlay/index.d.ts 6 | @@ -0,0 +1,20 @@ 7 | +export type ErrorLocation = { 8 | + fileName: string; 9 | + lineNumber: number; 10 | + colNumber?: number; 11 | +}; 12 | + 13 | +type RuntimeReportingOptions = { 14 | + onError?: () => void; 15 | + filename?: string; 16 | +}; 17 | + 18 | +type EditorHandler = (errorLoc: ErrorLocation) => void; 19 | + 20 | +export const setEditorHandler: (handler: EditorHandler | null) => void; 21 | +export const reportBuildError: (error: string) => void; 22 | +export const reportRuntimeError: (error: Error, options: RuntimeReportingOptions) => void; 23 | +export const dismissBuildError: () => void; 24 | +export const startReportingRuntimeErrors: (options: RuntimeReportingOptions) => void; 25 | +export const dismissRuntimeErrors: () => void; 26 | +export const stopReportingRuntimeErrors: () => void; 27 | -------------------------------------------------------------------------------- /scripts/remote-view-prepublish.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const { writeFileSync } = require('fs'); 4 | const { resolve } = require('path'); 5 | 6 | /** 7 | * Removes the `publishConfig` block from a built Modular package. 8 | * This expects the build output to have been copied to `packages//dist`. 9 | * 10 | * Mainly used by RemoteView. 11 | */ 12 | 13 | const DIRS_TO_PREPARE = ['remote-view']; 14 | 15 | function writeNewPackageJson(src, content) { 16 | writeFileSync(src, JSON.stringify(content, null, 2)); 17 | } 18 | 19 | function removePublishConfig(src) { 20 | const { publishConfig, ...pkg } = require(src); 21 | 22 | return { 23 | ...pkg, 24 | }; 25 | } 26 | 27 | DIRS_TO_PREPARE.forEach((dirName) => { 28 | const src = resolve( 29 | __dirname, 30 | `../packages/${dirName}`, 31 | 'dist', 32 | 'package.json', 33 | ); 34 | const content = removePublishConfig(src); 35 | writeNewPackageJson(src, content); 36 | console.log( 37 | `Package at dir packages/${dirName}/dist was updated to remove publishConfig`, 38 | ); 39 | }); 40 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | - 'release/**' 8 | 9 | permissions: 10 | contents: write 11 | pull-requests: write 12 | 13 | jobs: 14 | release: 15 | name: Release 16 | runs-on: ubuntu-latest 17 | 18 | steps: 19 | - uses: actions/checkout@v3 20 | - name: Use Node.js 21 | uses: actions/setup-node@v3.3.0 22 | with: 23 | node-version: '18.x' 24 | registry-url: https://registry.npmjs.org/ 25 | cache: 'yarn' 26 | 27 | - name: Install Dependencies 28 | run: yarn --frozen-lockfile 29 | 30 | - name: Build 31 | run: yarn build 32 | 33 | - name: Create Release Pull Request or Publish to npm 34 | id: changesets 35 | uses: changesets/action@v1 36 | with: 37 | publish: yarn changeset publish 38 | env: 39 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 40 | NPM_TOKEN: ${{ secrets.NPM_TOKEN }} 41 | NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} 42 | -------------------------------------------------------------------------------- /packages/modular-scripts/src/utils/getAllWorkspaces.ts: -------------------------------------------------------------------------------- 1 | import { 2 | analyzeWorkspaceDependencies, 3 | resolveWorkspace, 4 | } from '@modular-scripts/workspace-resolver'; 5 | import memoize from './memoize'; 6 | import getModularRoot from './getModularRoot'; 7 | import type { 8 | WorkspaceContent, 9 | WorkspaceMap, 10 | } from '@modular-scripts/modular-types'; 11 | export interface PackageManagerInfo { 12 | getWorkspaceCommand: string; 13 | formatWorkspaceCommandOutput: (stdout: string) => WorkspaceMap; 14 | } 15 | 16 | export async function getWorkspacePackages( 17 | modularRoot: string, 18 | target: string = modularRoot, 19 | ): Promise { 20 | const [allPackages] = await resolveWorkspace(modularRoot, target); 21 | 22 | return [allPackages, analyzeWorkspaceDependencies(allPackages)]; 23 | } 24 | 25 | function _getAllWorkspaces(target?: string): Promise { 26 | const modularRoot = getModularRoot(); 27 | 28 | return getWorkspacePackages(modularRoot, target); 29 | } 30 | 31 | export const getAllWorkspaces = memoize(_getAllWorkspaces); 32 | -------------------------------------------------------------------------------- /packages/remote-view-demos/README.md: -------------------------------------------------------------------------------- 1 | # RemoteView Demos 2 | 3 | This package contains demos of ``. 4 | 5 | The examples are a reference for users, but this package is also useful for 6 | developing `` components themselves. 7 | 8 | ## Setup 9 | 10 | For demos using `` to work, we need some `esm-view`s that our 11 | RemoteView will render. 12 | 13 | To this end, `view1` and `view2` have been pre-built and are exposed in the fake 14 | ESM cdn that is also used in integration tests 15 | (`__fixtures/remote-view-fake-cdn`). These two views have been built pointing at 16 | esm.sh, which means that this demo only works with connectivity through to 17 | esm.sh. Note that the other packages in that directory are designed for use in 18 | integration tests. 19 | 20 | To run the demos, from the root of the monorepo: 21 | 22 | 1. `node packages/remote-view/src/__tests__/serve.js` (boots a local static 23 | content server on port 8484, exposing the pre-built views) 24 | 2. `yarn modular start remote-view-demos` - launches the demos on 25 | `localhost:3000` 26 | -------------------------------------------------------------------------------- /packages/modular-scripts/src/build-scripts/webpack-scripts/plugins/WatchMissingNodeModulesPlugin.js: -------------------------------------------------------------------------------- 1 | // This webpack plugin ensures `npm install ` forces a project rebuild. 2 | // We’re not sure why this isn't webpack's default behavior. 3 | // See https://github.com/facebook/create-react-app/issues/186. 4 | 5 | 'use strict'; 6 | 7 | class WatchMissingNodeModulesPlugin { 8 | constructor(nodeModulesPath) { 9 | this.nodeModulesPath = nodeModulesPath; 10 | } 11 | 12 | apply(compiler) { 13 | compiler.hooks.emit.tap('WatchMissingNodeModulesPlugin', (compilation) => { 14 | var missingDeps = Array.from(compilation.missingDependencies); 15 | var nodeModulesPath = this.nodeModulesPath; 16 | 17 | // If any missing files are expected to appear in node_modules... 18 | if (missingDeps.some((file) => file.includes(nodeModulesPath))) { 19 | // ...tell webpack to watch node_modules recursively until they appear. 20 | compilation.contextDependencies.add(nodeModulesPath); 21 | } 22 | }); 23 | } 24 | } 25 | 26 | module.exports = WatchMissingNodeModulesPlugin; 27 | -------------------------------------------------------------------------------- /packages/modular-scripts/src/__tests__/utils/formatPath.test.ts: -------------------------------------------------------------------------------- 1 | import { normalizeToPosix } from '../../build-scripts/esbuild-scripts/utils/formatPath'; 2 | 3 | describe('Normalize path to Posix', () => { 4 | it('should convert a Win32 path into a Posix path', () => { 5 | expect(normalizeToPosix('\\this\\is\\my\\win32\\path')).toBe( 6 | '/this/is/my/win32/path', 7 | ); 8 | }); 9 | it('should convert a mixed path into a Posix path', () => { 10 | expect(normalizeToPosix('/this/is\\my/mixed\\path')).toBe( 11 | '/this/is/my/mixed/path', 12 | ); 13 | }); 14 | it('should leave a Posix path untouched', () => { 15 | expect(normalizeToPosix('/this/is/my/posix/path')).toBe( 16 | '/this/is/my/posix/path', 17 | ); 18 | }); 19 | it('should return undefined if undefined is passed', () => { 20 | expect(normalizeToPosix(undefined)).toBeUndefined(); 21 | }); 22 | it('should convert a relative path to a relative Posix path', () => { 23 | expect(normalizeToPosix('this\\is/my/relative\\mixed/path')).toBe( 24 | 'this/is/my/relative/mixed/path', 25 | ); 26 | }); 27 | }); 28 | -------------------------------------------------------------------------------- /packages/remote-view/src/__tests__/default-remote-view-error-fallback.test.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @jest-environment jsdom 3 | */ 4 | 5 | import React from 'react'; 6 | import { render, screen, waitFor } from '@testing-library/react'; 7 | import { DefaultRemoteViewErrorFallback } from '../components/default-remote-view-error-fallback'; 8 | import { RemoteViewError } from '../utils/remote-view-error'; 9 | 10 | const mockRemoteViewError = new RemoteViewError( 11 | 'Some example error', 12 | 'http://cdn.example.com/fake-module-url', 13 | ); 14 | 15 | describe('RemoteView DefaultRemoteViewErrorFallback', () => { 16 | beforeEach(() => { 17 | jest.spyOn(console, 'error').mockImplementation(() => undefined); 18 | }); 19 | 20 | it('should render an error as expected', async () => { 21 | render(); 22 | const failText = 23 | 'Something went wrong for module at URL "http://cdn.example.com/fake-module-url".'; 24 | 25 | await waitFor(() => screen.findByText(failText)); 26 | expect(screen.getByText(failText)).toBeInTheDocument(); 27 | }); 28 | }); 29 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # Dependencies 4 | node_modules 5 | 6 | # created by tests in modular-scripts 7 | packages/sample-app 8 | packages/sample-esbuild-app 9 | packages/sample-view 10 | packages/sample-esm-view 11 | packages/sample-package 12 | packages/nested 13 | packages/custom 14 | packages/sample-library-package 15 | packages/sample-renamable-library-package 16 | packages/sample-renamed-library-package 17 | packages/sample-depending-package 18 | packages/sample-renamable-depending-package 19 | 20 | # example app 21 | packages/esbuild-app 22 | 23 | # Build output 24 | /packages/*/build/ 25 | /packages/*/dist-cjs/ 26 | /packages/*/dist-types/ 27 | 28 | # Testing 29 | /coverage 30 | 31 | # Misc 32 | .DS_Store 33 | .eslintcache 34 | 35 | # Editors 36 | .idea 37 | 38 | # Logs 39 | npm-debug.log* 40 | yarn-debug.log* 41 | yarn-error.log* 42 | 43 | /dist 44 | 45 | # Used by typescript for incremental builds 46 | .tsbuildinfo 47 | *.tsbuildinfo 48 | 49 | # Local Jekyll preview of docs 50 | docs/_site 51 | docs/.bundle 52 | docs/vendor 53 | docs/Gemfile* -------------------------------------------------------------------------------- /packages/modular-scripts/src/__tests__/TestApp.test-tsx: -------------------------------------------------------------------------------- 1 | // We need to ensure that the `app/src/App.tsx` used by `yarn start` renders views 2 | // in order that we can test that an application can render views. 3 | // Therefore, this is a copy of `App.tsx` which renders all of the views. 4 | // I've changed the extension, because I don't want it to be picked up by TypeScript or ESLint. 5 | import * as React from 'react'; 6 | import logo from './logo.svg'; 7 | import './App.css'; 8 | 9 | function App(): JSX.Element { 10 | return ( 11 |
12 |
13 | logo 14 |

15 | Edit src/App.tsx and save to reload. 16 |

17 | 23 | Learn React 24 | 25 |
26 |
27 | this is a modular app 28 |
29 |
30 | ); 31 | } 32 | 33 | export default App; 34 | -------------------------------------------------------------------------------- /__fixtures__/remote-view-fake-cdn/esm-view-card/static/js/main.5a34a408.js: -------------------------------------------------------------------------------- 1 | import * as e from 'http://localhost:8484/react@17.0.2.js'; 2 | var t = { 3 | d: (e, a) => { 4 | for (var n in a) 5 | t.o(a, n) && 6 | !t.o(e, n) && 7 | Object.defineProperty(e, n, { enumerable: !0, get: a[n] }); 8 | }, 9 | o: (e, t) => Object.prototype.hasOwnProperty.call(e, t), 10 | }, 11 | a = {}; 12 | t.d(a, { Z: () => r }); 13 | const n = ((e) => { 14 | var a = {}; 15 | return t.d(a, e), a; 16 | })({ default: () => e.default, useState: () => e.useState }); 17 | function r() { 18 | const [e, t] = (0, n.useState)('Some card contents'); 19 | return n.default.createElement( 20 | 'div', 21 | null, 22 | n.default.createElement('h1', null, 'My Card'), 23 | n.default.createElement('span', null, e), 24 | n.default.createElement( 25 | 'button', 26 | { 27 | onClick: () => { 28 | t('Some mutated card contents'); 29 | }, 30 | }, 31 | 'Change card content', 32 | ), 33 | ); 34 | } 35 | var l = a.Z; 36 | export { l as default }; 37 | //# sourceMappingURL=main.5a34a408.js.map 38 | -------------------------------------------------------------------------------- /.github/workflows/static.yml: -------------------------------------------------------------------------------- 1 | name: Lint 2 | 3 | on: 4 | push: 5 | branches: [main, 'release/**', 'feature/**'] 6 | pull_request: 7 | branches: [main, 'release/**', 'feature/**'] 8 | 9 | jobs: 10 | Static: 11 | name: ${{ matrix.name }} 12 | runs-on: ubuntu-latest 13 | env: 14 | MODULAR_LOGGER_DEBUG: true 15 | strategy: 16 | fail-fast: false 17 | matrix: 18 | include: 19 | - name: Prettier 20 | command: 'prettier --check .' 21 | - name: Typecheck 22 | command: typecheck 23 | - name: Lint 24 | command: lint 25 | - name: Build 26 | command: build 27 | steps: 28 | - uses: actions/checkout@v3 29 | - name: Use Node.js 30 | uses: actions/setup-node@v3.3.0 31 | with: 32 | node-version: '18.x' 33 | cache: 'yarn' 34 | 35 | - name: 'Install Dependencies' 36 | run: yarn --frozen-lockfile 37 | - name: 'Build internal prerequisites' 38 | run: yarn workspace @modular-scripts/workspace-resolver build 39 | - name: ${{ matrix.name }} 40 | run: yarn ${{ matrix.command }} 41 | -------------------------------------------------------------------------------- /packages/modular-scripts/src/__tests__/modularRoot.test.ts: -------------------------------------------------------------------------------- 1 | import { promisify } from 'util'; 2 | import * as fs from 'fs-extra'; 3 | import * as tmp from 'tmp'; 4 | import getModularRoot, { findModularRoot } from '../utils/getModularRoot'; 5 | const mktempd = promisify(tmp.dir); 6 | 7 | describe('findModularRoot and getModularRoot', () => { 8 | const cwd = process.cwd(); 9 | let folder: string; 10 | beforeEach(async () => { 11 | folder = await mktempd(); 12 | process.chdir(folder); 13 | }); 14 | 15 | afterEach(async () => { 16 | process.chdir(cwd); 17 | await fs.remove(folder); 18 | }); 19 | 20 | it("When findModularRoot doesn't find a root in a temp directory it returns undefined and doesn't except", () => { 21 | let modularRoot: string | undefined = 'truthy'; 22 | 23 | function findWrapper() { 24 | modularRoot = findModularRoot(); 25 | } 26 | 27 | expect(findWrapper).not.toThrow(); 28 | expect(modularRoot).toBeUndefined(); 29 | }); 30 | 31 | it("When getModularRoot doesn't find a root in a temp directory, it excepts", () => { 32 | function findWrapper() { 33 | getModularRoot(); 34 | } 35 | 36 | expect(findWrapper).toThrow(); 37 | }); 38 | }); 39 | -------------------------------------------------------------------------------- /packages/modular-template-esm-view/src/EsmView.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 12 | monospace; 13 | } 14 | 15 | .EsmView { 16 | text-align: center; 17 | } 18 | 19 | .EsmView-logo { 20 | height: 40vmin; 21 | pointer-events: none; 22 | } 23 | 24 | @media (prefers-reduced-motion: no-preference) { 25 | .EsmView-logo { 26 | animation: EsmView-logo-spin infinite 20s linear; 27 | } 28 | } 29 | 30 | .EsmView-header { 31 | background-color: #282c34; 32 | min-height: 100vh; 33 | display: flex; 34 | flex-direction: column; 35 | align-items: center; 36 | justify-content: center; 37 | font-size: calc(10px + 2vmin); 38 | color: white; 39 | } 40 | 41 | .EsmView-link { 42 | color: #61dafb; 43 | } 44 | 45 | @keyframes EsmView-logo-spin { 46 | from { 47 | transform: rotate(0deg); 48 | } 49 | to { 50 | transform: rotate(360deg); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /packages/eslint-config-modular-app/base.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | // This file is based on https://github.com/facebook/create-react-app/tree/main/packages/eslint-config-react-app 4 | 5 | // Fix eslint shareable config (https://github.com/eslint/eslint/issues/3458) 6 | require('@rushstack/eslint-patch/modern-module-resolution'); 7 | 8 | // This file contains the minimum ESLint configuration required for Create 9 | // React App support, and is used as the `baseConfig` for `eslint-loader` 10 | // to ensure that user-provided configs don't need this boilerplate. 11 | 12 | module.exports = { 13 | root: true, 14 | 15 | parser: '@babel/eslint-parser', 16 | 17 | plugins: ['react'], 18 | 19 | env: { 20 | browser: true, 21 | commonjs: true, 22 | es6: true, 23 | jest: true, 24 | node: true, 25 | }, 26 | 27 | parserOptions: { 28 | sourceType: 'module', 29 | requireConfigFile: false, 30 | babelOptions: { 31 | presets: [require.resolve('babel-preset-react-app/prod')], 32 | }, 33 | }, 34 | 35 | settings: { 36 | react: { 37 | version: 'detect', 38 | }, 39 | }, 40 | 41 | rules: { 42 | 'react/jsx-uses-vars': 'warn', 43 | 'react/jsx-uses-react': 'warn', 44 | }, 45 | }; 46 | -------------------------------------------------------------------------------- /packages/eslint-config-modular-app/recommended.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | /** 3 | * Stricter variant of the default index.js configuration 4 | * * Adds import sorting rules 5 | */ 6 | 7 | module.exports = { 8 | extends: [require.resolve('./index')], 9 | overrides: [ 10 | { 11 | files: ['**/*.ts?(x)', '**/*.js?(x)'], 12 | rules: { 13 | 'no-multiple-empty-lines': 1, 14 | 'sort-imports': [ 15 | 1, 16 | { 17 | ignoreDeclarationSort: true, 18 | ignoreCase: true, 19 | }, 20 | ], 21 | 'import/order': [ 22 | 1, 23 | { 24 | groups: [ 25 | 'builtin', 26 | 'external', 27 | 'internal', 28 | ['parent', 'sibling'], 29 | 'type', 30 | ], 31 | pathGroups: [ 32 | { 33 | pattern: 'react+(|-native)', 34 | group: 'external', 35 | position: 'before', 36 | }, 37 | ], 38 | pathGroupsExcludedImportTypes: ['react+(|-native'], 39 | 'newlines-between': 'never', 40 | }, 41 | ], 42 | }, 43 | }, 44 | ], 45 | }; 46 | --------------------------------------------------------------------------------