1+ import type { CSpellUserSettings } from "cspell-lib" ;
2+ import { spellCheckDocument } from "cspell-lib" ;
3+ import * as jsonc from "jsonc-parser" ;
14import semver from "semver" ;
25
3- import { fillTemplate } from "../../formatting.js" ;
6+ import { fillTemplate , stringify } from "../../formatting.js" ;
47import { getNodeLtsVersions } from "../../versions/node.js" ;
58import { getNpmPackageDistTags } from "../../versions/npm.js" ;
69import { getOciArtifactMaxMajorVersion , getOciArtifactTags } from "../../versions/oci.js" ;
710import { loadTemplates } from "../templates.js" ;
11+ import type { BaseDotConfigs } from "./dotConfig.js" ;
812
913export interface BaseDevcontainerConfigs {
1014 ".devcontainer/.env" : string ;
@@ -29,37 +33,64 @@ const getPnpmLatestDistTag = async () => {
2933
3034export const createBaseDevcontainerConfigs = async (
3135 projectName : string ,
32- remoteUser = "dev" ,
36+ remoteUser : string ,
3337) : Promise < BaseDevcontainerConfigs > => {
34- const userInitRepoName = "ghcr.io/devcontainer-config/features/user-init" ;
35- const dotConfigRepoName = "ghcr.io/devcontainer-config/features/dot-config" ;
36- const userInitVersion = await getOciArtifactMaxMajorVersion ( userInitRepoName ) ;
37- const dotConfigVersion = await getOciArtifactMaxMajorVersion ( dotConfigRepoName ) ;
38-
39- const nodeDevcontainerRepoName = "mcr.microsoft.com/devcontainers/javascript-node" ;
40- const nodeLtsVersions = await getNodeLtsVersions ( ) ;
41- const nodeDevcontainerTags = new Set ( await getOciArtifactTags ( nodeDevcontainerRepoName ) ) ;
42- const nodeVersion = nodeLtsVersions . find ( ( v ) => nodeDevcontainerTags . has ( v . toString ( ) ) ) ?. toString ( ) ?? "latest" ;
43-
44- const templates = await loadTemplates ( "base" , [
38+ const templatePaths = [
4539 ".devcontainer/.env" ,
4640 ".devcontainer/devcontainer.json" ,
4741 ".devcontainer/docker-compose.yml" ,
4842 ".devcontainer/Dockerfile" ,
4943 ".devcontainer/dot-config.json" ,
50- ] satisfies ( keyof BaseDevcontainerConfigs ) [ ] ) ;
44+ ] satisfies ( keyof BaseDevcontainerConfigs ) [ ] ;
45+ const templates = await loadTemplates ( "base" , [
46+ ...templatePaths ,
47+ ".config/cspell/cspell.json" satisfies keyof BaseDotConfigs ,
48+ ] ) ;
49+
50+ const devContainerConfig = await ( async ( ) => {
51+ const devContainerConfigPath = ".devcontainer/devcontainer.json" satisfies keyof BaseDevcontainerConfigs ;
52+ const devContainerConfig = jsonc . parse (
53+ fillTemplate ( templates [ devContainerConfigPath ] , { projectName, remoteUser } ) ,
54+ ) as {
55+ features : object ;
56+ } ;
57+
58+ const userInitRepoName = "ghcr.io/devcontainer-config/features/user-init" ;
59+ const dotConfigRepoName = "ghcr.io/devcontainer-config/features/dot-config" ;
60+ const userInitVersion = await getOciArtifactMaxMajorVersion ( userInitRepoName ) ;
61+ const dotConfigVersion = await getOciArtifactMaxMajorVersion ( dotConfigRepoName ) ;
62+ devContainerConfig . features = {
63+ [ `${ userInitRepoName } :${ userInitVersion } ` ] : { } ,
64+ [ `${ dotConfigRepoName } :${ dotConfigVersion } ` ] : { } ,
65+ } ;
66+
67+ const content = stringify ( devContainerConfig ) ;
68+ const spellCheckResult = await spellCheckDocument (
69+ { uri : devContainerConfigPath , text : content } ,
70+ { noConfigSearch : true } ,
71+ jsonc . parse ( templates [ ".config/cspell/cspell.json" ] ) as CSpellUserSettings ,
72+ ) ;
73+ return [
74+ `// spell-checker:ignore ${ [ ...new Set ( spellCheckResult . issues . map ( ( issue ) => issue . text ) ) ] . join ( " " ) } ` ,
75+ content ,
76+ ] . join ( "\n" ) ;
77+ } ) ( ) ;
78+
79+ const dockerFile = await ( async ( ) => {
80+ const nodeDevcontainerRepoName = "mcr.microsoft.com/devcontainers/javascript-node" ;
81+ const nodeLtsVersions = await getNodeLtsVersions ( ) ;
82+ const nodeDevcontainerTags = new Set ( await getOciArtifactTags ( nodeDevcontainerRepoName ) ) ;
83+ const nodeVersion = nodeLtsVersions . find ( ( v ) => nodeDevcontainerTags . has ( v . toString ( ) ) ) ?. toString ( ) ?? "latest" ;
84+ const pnpmVersion = await getPnpmLatestDistTag ( ) ;
85+
86+ return fillTemplate ( templates [ ".devcontainer/Dockerfile" ] , { nodeVersion, pnpmVersion } ) ;
87+ } ) ( ) ;
5188
52- const pnpmVersion = await getPnpmLatestDistTag ( ) ;
5389 return {
5490 ".devcontainer/.env" : fillTemplate ( templates [ ".devcontainer/.env" ] , { projectName, remoteUser } ) ,
55- ".devcontainer/devcontainer.json" : fillTemplate ( templates [ ".devcontainer/devcontainer.json" ] , {
56- projectName,
57- remoteUser,
58- } )
59- . replaceAll ( userInitRepoName , `${ userInitRepoName } :${ userInitVersion } ` )
60- . replaceAll ( dotConfigRepoName , `${ dotConfigRepoName } :${ dotConfigVersion } ` ) ,
91+ ".devcontainer/devcontainer.json" : devContainerConfig ,
6192 ".devcontainer/docker-compose.yml" : templates [ ".devcontainer/docker-compose.yml" ] ,
62- ".devcontainer/Dockerfile" : fillTemplate ( templates [ ".devcontainer/Dockerfile" ] , { nodeVersion , pnpmVersion } ) ,
93+ ".devcontainer/Dockerfile" : dockerFile ,
6394 ".devcontainer/dot-config.json" : fillTemplate ( templates [ ".devcontainer/dot-config.json" ] , { remoteUser } ) ,
6495 } ;
6596} ;
0 commit comments