@neuxnet/neux-cli 0.2.3 → 0.2.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@neuxnet/neux-cli",
3
- "version": "0.2.3",
3
+ "version": "0.2.4",
4
4
  "description": "Standalone CLI and Node API for Neux mini program build, pack, preview, and CI automation.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -24,6 +24,8 @@
24
24
  "sync:compiler": "node ./scripts/sync-compiler.js",
25
25
  "prepare:publish": "npm run sync:compiler && npm run sync:container",
26
26
  "generate:init-types": "node ./scripts/generate-init-types.js",
27
+ "smoke:init-types": "node ./scripts/smoke-init-types.mjs",
28
+ "smoke:init-types:registry": "node ./scripts/smoke-init-types.mjs --registry",
27
29
  "test": "node --test",
28
30
  "smoke:help": "node ./src/bin/cli.js --help",
29
31
  "pack:dry": "npm pack --dry-run"
@@ -58,6 +60,12 @@
58
60
  "preview"
59
61
  ],
60
62
  "license": "Apache-2.0",
63
+ "neux": {
64
+ "typesPackage": {
65
+ "name": "@neuxnet/neux-miniapp-types",
66
+ "versionRange": "^0.1.7"
67
+ }
68
+ },
61
69
  "publishConfig": {
62
70
  "access": "public"
63
71
  },
@@ -0,0 +1,114 @@
1
+ import fs from 'node:fs/promises'
2
+ import os from 'node:os'
3
+ import path from 'node:path'
4
+ import { execFile } from 'node:child_process'
5
+ import { promisify } from 'node:util'
6
+ import { initProject } from '../src/core/init.js'
7
+
8
+ const execFileAsync = promisify(execFile)
9
+ const cliRoot = path.resolve(import.meta.dirname, '..')
10
+ const repoRoot = path.resolve(cliRoot, '..')
11
+ const typesRoot = path.join(repoRoot, 'neux-miniapp-types')
12
+ const tscPath = path.join(repoRoot, 'fe', 'node_modules', '.bin', 'tsc')
13
+ const tempRoot = await fs.mkdtemp(path.join(os.tmpdir(), 'neux-cli-types-smoke-'))
14
+ const registryMode = process.argv.includes('--registry')
15
+
16
+ async function pack(directory, destination) {
17
+ const { stdout } = await execFileAsync('npm', [
18
+ 'pack',
19
+ '--pack-destination',
20
+ destination,
21
+ '--json',
22
+ ], { cwd: directory })
23
+ const result = JSON.parse(stdout)
24
+ return path.join(destination, result[0].filename)
25
+ }
26
+
27
+ try {
28
+ const project = path.join(tempRoot, 'starter-app')
29
+ await initProject({
30
+ _: [project],
31
+ appId: 'wxlocaltypes123',
32
+ name: 'Local Types Smoke',
33
+ })
34
+
35
+ const packageJsonPath = path.join(project, 'package.json')
36
+ const packageJson = JSON.parse(await fs.readFile(packageJsonPath, 'utf8'))
37
+ const typesPackage = packageJson.devDependencies['@neuxnet/neux-miniapp-types']
38
+ const cliPackage = JSON.parse(await fs.readFile(
39
+ path.join(cliRoot, 'package.json'),
40
+ 'utf8',
41
+ ))
42
+ const expectedTypesRange = cliPackage.neux?.typesPackage?.versionRange
43
+ if (typesPackage !== expectedTypesRange) {
44
+ throw new Error(
45
+ `Unexpected generated types dependency: ${typesPackage}; ` +
46
+ `expected ${expectedTypesRange}`,
47
+ )
48
+ }
49
+
50
+ if (!registryMode) {
51
+ const typesTarball = await pack(typesRoot, tempRoot)
52
+ const cliTarball = await pack(cliRoot, tempRoot)
53
+ packageJson.devDependencies['@neuxnet/neux-cli'] = `file:${cliTarball}`
54
+ packageJson.devDependencies['@neuxnet/neux-miniapp-types'] = `file:${typesTarball}`
55
+ }
56
+ await fs.writeFile(packageJsonPath, `${JSON.stringify(packageJson, null, 2)}\n`, 'utf8')
57
+
58
+ await fs.writeFile(path.join(project, 'types', 'consumer.ts'), [
59
+ 'Page({',
60
+ ' data: { count: 0 },',
61
+ ' onLoad(query) {',
62
+ ' const id: string | undefined = query.id',
63
+ ' this.setData({ count: this.data.count + 1, dynamicallyAdded: true })',
64
+ ' void id',
65
+ ' },',
66
+ '})',
67
+ '',
68
+ 'wx.request({',
69
+ " url: '/api/profile',",
70
+ " method: 'GET',",
71
+ ' success(result) { result }',
72
+ '})',
73
+ '',
74
+ "Component({ properties: { title: String }, methods: { emitChange() {",
75
+ " this.triggerEvent<{ value: string }>('change', { value: this.properties.title })",
76
+ '} } })',
77
+ '',
78
+ ].join('\n'), 'utf8')
79
+
80
+ const installArgs = [
81
+ 'install',
82
+ '--ignore-scripts',
83
+ '--no-package-lock',
84
+ ]
85
+ if (registryMode) {
86
+ installArgs.push('--registry=https://registry.npmjs.org/')
87
+ }
88
+ await execFileAsync('npm', installArgs, {
89
+ cwd: project,
90
+ maxBuffer: 1024 * 1024,
91
+ })
92
+
93
+ await execFileAsync(tscPath, [
94
+ '-p',
95
+ path.join(project, 'jsconfig.json'),
96
+ '--noEmit',
97
+ ], { cwd: project, maxBuffer: 1024 * 1024 })
98
+
99
+ const installedTypesPackage = JSON.parse(await fs.readFile(
100
+ path.join(project, 'node_modules', '@neuxnet', 'neux-miniapp-types', 'package.json'),
101
+ 'utf8',
102
+ ))
103
+ if (installedTypesPackage.name !== '@neuxnet/neux-miniapp-types') {
104
+ throw new Error('Installed types package has an unexpected name')
105
+ }
106
+ if (installedTypesPackage.types !== './index.d.ts') {
107
+ throw new Error('Installed types package does not expose index.d.ts')
108
+ }
109
+
110
+ console.log(`Passed: neux init -> ${registryMode ? 'registry' : 'local'} npm install -> TypeScript consumer check.`)
111
+ }
112
+ finally {
113
+ await fs.rm(tempRoot, { recursive: true, force: true })
114
+ }
package/src/core/init.js CHANGED
@@ -3,7 +3,7 @@ import path from 'node:path'
3
3
  import { fileURLToPath } from 'node:url'
4
4
  import { DiminaCliError } from './errors.js'
5
5
  import { pathExists, resolvePath, writeJson } from './fs.js'
6
- import { getCliVersion } from './package-info.js'
6
+ import { getCliPackageInfo } from './package-info.js'
7
7
  import { saveCliKey } from '../providers/service-config.js'
8
8
  import { promptLines, shouldPrompt } from './prompts.js'
9
9
 
@@ -12,7 +12,6 @@ const DEFAULT_LIB_VERSION = '3.3.3'
12
12
  export const DEFAULT_SERVER_URL = 'https://demo-c.paas.superapp.neuvision.cn'
13
13
  const CLI_PACKAGE_NAME = '@neuxnet/neux-cli'
14
14
  const TEMPLATE_ASSET_DIR = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '../../assets/init')
15
- const DEFAULT_DOCS_BASE_URL = `${DEFAULT_SERVER_URL}/miniappdoc`
16
15
 
17
16
  export async function initProject(options = {}) {
18
17
  const targetArg = options._?.[0] || options.project || '.'
@@ -25,8 +24,14 @@ export async function initProject(options = {}) {
25
24
  const appId = options.appId || prompts.appId || DEFAULT_APP_ID
26
25
  const serverUrl = options.serverUrl || prompts.serverUrl || DEFAULT_SERVER_URL
27
26
  const cliKey = options.key || prompts.cliKey
28
- const cliVersion = await getCliVersion()
29
- const files = createTemplateFiles({ appId, projectName, serverUrl, cliVersion })
27
+ const cliPackage = await getCliPackageInfo()
28
+ const files = createTemplateFiles({
29
+ appId,
30
+ projectName,
31
+ serverUrl,
32
+ cliVersion: cliPackage.version,
33
+ typesPackage: cliPackage.typesPackage,
34
+ })
30
35
 
31
36
  for (const file of files) {
32
37
  const filePath = path.join(projectPath, file.path)
@@ -36,9 +41,7 @@ export async function initProject(options = {}) {
36
41
  await fs.mkdir(path.dirname(filePath), { recursive: true })
37
42
  const sourcePath = path.join(TEMPLATE_ASSET_DIR, file.source)
38
43
  if (file.source === 'types/neux-api.d.ts') {
39
- const docsBaseUrl = `${String(serverUrl || DEFAULT_SERVER_URL).replace(/\/+$/, '')}/miniappdoc`
40
- const content = await fs.readFile(sourcePath, 'utf8')
41
- await fs.writeFile(filePath, content.replaceAll(DEFAULT_DOCS_BASE_URL, docsBaseUrl), 'utf8')
44
+ await fs.writeFile(filePath, `/// <reference types="${file.typesPackage.name}" />\n`, 'utf8')
42
45
  }
43
46
  else await fs.copyFile(sourcePath, filePath)
44
47
  }
@@ -142,7 +145,20 @@ async function mergeJsonFile(filePath, generated) {
142
145
  await writeJson(filePath, merged)
143
146
  }
144
147
 
145
- function createTemplateFiles({ appId, projectName, serverUrl = DEFAULT_SERVER_URL, cliVersion }) {
148
+ function createTemplateFiles({
149
+ appId,
150
+ projectName,
151
+ serverUrl = DEFAULT_SERVER_URL,
152
+ cliVersion,
153
+ typesPackage,
154
+ }) {
155
+ if (!typesPackage?.name || !typesPackage?.versionRange) {
156
+ throw new DiminaCliError(
157
+ 'NEUX_CLI_TYPES_PACKAGE_METADATA_MISSING',
158
+ 'The CLI package does not declare a compatible miniapp types package.',
159
+ )
160
+ }
161
+
146
162
  return [
147
163
  {
148
164
  path: 'project.config.json',
@@ -198,6 +214,7 @@ function createTemplateFiles({ appId, projectName, serverUrl = DEFAULT_SERVER_UR
198
214
  },
199
215
  devDependencies: {
200
216
  [CLI_PACKAGE_NAME]: `^${cliVersion}`,
217
+ [typesPackage.name]: typesPackage.versionRange,
201
218
  },
202
219
  },
203
220
  },
@@ -276,11 +293,17 @@ function createTemplateFiles({ appId, projectName, serverUrl = DEFAULT_SERVER_UR
276
293
  checkJs: false,
277
294
  noEmit: true,
278
295
  target: 'ES2020',
296
+ types: [typesPackage.name],
279
297
  },
280
298
  include: ['**/*.js', '**/*.ts', 'types/**/*.d.ts'],
281
299
  },
282
300
  },
283
- { path: 'types/neux-api.d.ts', kind: 'asset', source: 'types/neux-api.d.ts' },
301
+ {
302
+ path: 'types/neux-api.d.ts',
303
+ kind: 'asset',
304
+ source: 'types/neux-api.d.ts',
305
+ typesPackage,
306
+ },
284
307
  { path: 'assets/tabbar/home.png', kind: 'asset', source: 'tabbar/home.png' },
285
308
  { path: 'assets/tabbar/home-active.png', kind: 'asset', source: 'tabbar/home-active.png' },
286
309
  { path: 'assets/tabbar/list.png', kind: 'asset', source: 'tabbar/list.png' },
@@ -15,6 +15,7 @@ export async function getCliPackageInfo() {
15
15
  packageName: packageJson.name || brand.packageName,
16
16
  version: packageJson.version,
17
17
  packageRoot,
18
+ typesPackage: packageJson.neux?.typesPackage || null,
18
19
  }
19
20
  }
20
21