diff --git a/AUTHORING_LIBRARIES.md b/AUTHORING_LIBRARIES.md index a011ab40..b7eb6517 100644 --- a/AUTHORING_LIBRARIES.md +++ b/AUTHORING_LIBRARIES.md @@ -39,10 +39,21 @@ If you've done ESM in node, this should feel familiar, and we can be be consiste import { AnotherThing } from './path/to/file.js'; ``` +Generally, import: +- gjs with `./path/to/file.gjs` +- gts with `./path/to/file.gts` +- js with `./path/to/file.js` +- ts with `./path/to/file.ts` +- hbs with `./path/to/file.js` or `./path/to/file` + A couple caveats with older, co-located components, - - for `.hbs` / template-only components, the import path is still `.js`, because we transform it. + - for `.hbs` / template-only components, no extension is needed, but the js extension can be used. - for co-located components, where the template is in a separate `.hbs` file, you may not import that `.hbs` file directly, because it is merged in with the associated `.js` or `.ts` file. +For consumers of your library, they will not need to worry about the extensions, because: +- rollup compiles away the implementation details (non-js modules) +- package.json#exports declares what is importable under what path, and maps non-extension imports to files with extensions + ## CSS diff --git a/files/__addonLocation__/package.json b/files/__addonLocation__/package.json index 9e0e206b..1464265e 100644 --- a/files/__addonLocation__/package.json +++ b/files/__addonLocation__/package.json @@ -43,9 +43,10 @@ "@babel/plugin-transform-class-static-block": "^7.20.0", "@babel/runtime": "^7.17.0", "@embroider/addon-dev": "^4.1.0",<% if (typescript) { %> - "@glint/core": "^1.0.2", - "@glint/environment-ember-loose": "^1.0.2", - "@glint/template": "^1.0.2", + "@glint/core": "^1.2.0", + "@glint/environment-ember-loose": "^1.2.0", + "@glint/environment-ember-template-imports": "^1.2.0", + "@glint/template": "^1.2.0", "@tsconfig/ember": "^2.0.0", "@types/ember": "^4.0.4", "@types/ember__object": "^4.0.6", @@ -64,6 +65,8 @@ "@types/ember__array": "^4.0.4", "@types/ember__error": "^4.0.3", "@types/ember__component": "^4.0.14", + "@types/ember__modifier": "^4.0.6", + "@types/ember__helper": "^4.0.3", "@types/ember__routing": "^4.0.13", "@typescript-eslint/eslint-plugin": "^6.7.2", "@typescript-eslint/parser": "^6.7.2",<% } %> diff --git a/files/__addonLocation__/tsconfig.json b/files/__addonLocation__/tsconfig.json index df7aca23..782c56ed 100644 --- a/files/__addonLocation__/tsconfig.json +++ b/files/__addonLocation__/tsconfig.json @@ -5,7 +5,7 @@ "unpublished-development-types/**/*" ], "glint": { - "environment": "ember-loose" + "environment": ["ember-loose", "ember-template-imports"] }, "compilerOptions": { "allowJs": true, diff --git a/tests/fixtures/typescript/my-addon/src/components/template-only.ts b/tests/fixtures/typescript/my-addon/src/components/template-only.ts new file mode 100644 index 00000000..fa850535 --- /dev/null +++ b/tests/fixtures/typescript/my-addon/src/components/template-only.ts @@ -0,0 +1,3 @@ +import templateOnly from '@ember/component/template-only'; + +export default templateOnly(); diff --git a/tests/helpers/utils.ts b/tests/helpers/utils.ts index 1dfbfc50..3216c12a 100644 --- a/tests/helpers/utils.ts +++ b/tests/helpers/utils.ts @@ -22,6 +22,46 @@ export async function createTmp() { return tmpDirPath; } +const ROLLUP_HASH = /[a-f0-9]{8}/ + +/** +* Filters out rollup-hashes from a list of files. +* +* When there are private files, rollup will add some +* hash to the emitted file path, +* such as: +* template-only-ab2e7769.js.map +* +* These hashes have predictable length, so we can have +* a fairly narrow matcher to remove them. +*/ +export function withoutHashes(names: string[]) { + return names.filter(name => !ROLLUP_HASH.test(name)); +} + +/** +* Filters out a list of files, keeping only the rollup-emitted hashed files +* +* When there are private files, rollup will add some +* hash to the emitted file path, +* such as: +* template-only-ab2e7769.js.map +* +* These hashes have predictable length, so we can have +* a fairly narrow matcher to remove them. +* This a +*/ +export function hashesOnly(names: string[]) { + return names.filter(name => ROLLUP_HASH.test(name)); +} + +export function splitHashedFiles(names: string[]) { + return { + hashed: hashesOnly(names), + unhashed: withoutHashes(names), + }; +} + /** * Abstraction for install, as the blueprint supports multiple package managers */ diff --git a/tests/smoke-tests/--typescript.test.ts b/tests/smoke-tests/--typescript.test.ts index 553f7bb5..1909eb42 100644 --- a/tests/smoke-tests/--typescript.test.ts +++ b/tests/smoke-tests/--typescript.test.ts @@ -7,6 +7,7 @@ import { AddonHelper, assertGeneratedCorrectly, dirContents, + splitHashedFiles, SUPPORTED_PACKAGE_MANAGERS, } from '../helpers.js'; @@ -71,13 +72,12 @@ for (let packageManager of SUPPORTED_PACKAGE_MANAGERS) { expect(buildResult.exitCode).toEqual(0); - let distContents = (await dirContents(distDir)).filter( - // these files have a hash that changes based on file contents - (distFile) => !distFile.startsWith('_rollupPluginBabelHelpers') - ); + let distContents = splitHashedFiles(await dirContents(distDir)); let declarationsContents = await dirContents(declarationsDir); - expect(distContents).to.deep.equal([ + + + expect(distContents.unhashed).to.deep.equal([ '_app_', 'components', 'index.js', @@ -86,6 +86,18 @@ for (let packageManager of SUPPORTED_PACKAGE_MANAGERS) { 'template-registry.js.map', ]); + expect(distContents.hashed.length).toBe(4); + expect( + distContents.hashed + .filter(file => file.includes('_rollup')) + .map(file => file.split('.js')[1]) + ).to.deep.equal(["", '.map'], 'the rollup helpers are emitted with a source map'); + expect( + distContents.hashed + .filter(file => file.includes('template-only')) + .map(file => file.split('.js')[1]) + ).to.deep.equal(["", '.map'], 'the template-only component is emitted with a source map'); + expect(declarationsContents).to.deep.equal([ 'components', 'index.d.ts',