@xfilecom/xframe 0.1.20 → 0.1.22

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/bin/xframe.js CHANGED
@@ -30,12 +30,52 @@ function shouldProcess(filePath) {
30
30
  return false;
31
31
  }
32
32
 
33
+ /** 모노레포 sibling 패키지 또는 배포 tarball 의 defaults.json → ^semver */
34
+ let defaultCoreSpecsCache;
35
+ function getDefaultCoreSpecs() {
36
+ if (defaultCoreSpecsCache) return defaultCoreSpecsCache;
37
+ const hardcoded = { backendCore: '^1.0.1', frontCore: '^0.2.6' };
38
+ const readCaret = (pkgPath, expectedName) => {
39
+ try {
40
+ if (!fs.existsSync(pkgPath)) return null;
41
+ const j = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
42
+ if (j.name !== expectedName || !j.version) return null;
43
+ return `^${j.version}`;
44
+ } catch {
45
+ return null;
46
+ }
47
+ };
48
+ const binDir = __dirname;
49
+ const monoBackend = path.join(binDir, '..', '..', 'backend-core', 'package.json');
50
+ const monoFront = path.join(binDir, '..', '..', 'front-core', 'package.json');
51
+ let backendCore = readCaret(monoBackend, '@xfilecom/backend-core');
52
+ let frontCore = readCaret(monoFront, '@xfilecom/front-core');
53
+ if (!backendCore || !frontCore) {
54
+ try {
55
+ const defPath = path.join(binDir, '..', 'defaults.json');
56
+ if (fs.existsSync(defPath)) {
57
+ const d = JSON.parse(fs.readFileSync(defPath, 'utf8'));
58
+ if (d.backendCore) backendCore = backendCore || d.backendCore;
59
+ if (d.frontCore) frontCore = frontCore || d.frontCore;
60
+ }
61
+ } catch {
62
+ /* ignore */
63
+ }
64
+ }
65
+ defaultCoreSpecsCache = {
66
+ backendCore: backendCore || hardcoded.backendCore,
67
+ frontCore: frontCore || hardcoded.frontCore,
68
+ };
69
+ return defaultCoreSpecsCache;
70
+ }
71
+
33
72
  function usage() {
73
+ const { backendCore: defB, frontCore: defF } = getDefaultCoreSpecs();
34
74
  console.log(`Usage: xframe <project-directory> [options]
35
75
 
36
76
  Options:
37
- --backend-core <spec> @xfilecom/backend-core (default: ^1.0.0)
38
- --front-core <spec> @xfilecom/front-core (default: ^0.2.1)
77
+ --backend-core <spec> @xfilecom/backend-core (default: ${defB})
78
+ --front-core <spec> @xfilecom/front-core (default: ${defF}, npm 공개 레지스트리)
39
79
  --no-install 스캐폴드만 하고 yarn/npm install 생략
40
80
 
41
81
  MySQL (shared/config/api/application.yml 의 database.*)
@@ -57,10 +97,11 @@ Examples:
57
97
  }
58
98
 
59
99
  function parseArgs(argv) {
100
+ const defs = getDefaultCoreSpecs();
60
101
  const rest = argv.slice(2);
61
102
  let projectDir = null;
62
- let backendCore = '^1.0.0';
63
- let frontCore = '^0.2.1';
103
+ let backendCore = defs.backendCore;
104
+ let frontCore = defs.frontCore;
64
105
  let skipInstall = false;
65
106
  let skipDbPrompt = false;
66
107
  let dbPull = false;
package/defaults.json ADDED
@@ -0,0 +1,4 @@
1
+ {
2
+ "backendCore": "^1.0.3",
3
+ "frontCore": "^0.2.8"
4
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xfilecom/xframe",
3
- "version": "0.1.20",
3
+ "version": "0.1.22",
4
4
  "description": "Scaffold full-stack app: Nest + @xfilecom/backend-core, Vite/React + @xfilecom/front-core",
5
5
  "license": "UNLICENSED",
6
6
  "bin": {
@@ -8,8 +8,14 @@
8
8
  },
9
9
  "files": [
10
10
  "bin",
11
+ "defaults.json",
11
12
  "template"
12
13
  ],
14
+ "scripts": {
15
+ "sync-defaults": "node scripts/sync-defaults.js",
16
+ "sync-template-front-core": "node scripts/sync-template-front-core.js",
17
+ "prepublishOnly": "npm run sync-defaults && npm run sync-template-front-core"
18
+ },
13
19
  "engines": {
14
20
  "node": ">=18"
15
21
  },
@@ -20,6 +20,8 @@ Nest API (`@xfilecom/backend-core`) + Vite/React client·admin (`@xfilecom/front
20
20
  - Client: `http://localhost:3001` — `CommonResponse` 형태로 `/health` 표시
21
21
  - Admin: `http://localhost:3002`
22
22
 
23
+ `@xfilecom/front-core` / `@xfilecom/backend-core` 는 **`package.json`에서 npm 버전 범위**(예: `^0.2.6`, `^1.0.1`)로 두는 것을 권장합니다. `file:../../../packages/...` 는 폴더 구조에 따라 깨지기 쉽습니다. 스캐폴드 시 `npx @xfilecom/xframe` 이 넣는 기본 범위는 **배포 시점의 코어 패키지 버전**과 맞춰지며(`defaults.json`, `npm publish` 전 동기화), 필요하면 `--backend-core` / `--front-core` 로 덮어쓸 수 있습니다.
24
+
23
25
  ## `shared/` (설정·스키마·SQL·endpoint)
24
26
 
25
27
  - **`shared/config/api`**, **`shared/config/web/client`**, **`shared/config/web/admin`**: YAML (`application.yml` + `application-<env>.yml`)
@@ -32,6 +34,20 @@ Nest API (`@xfilecom/backend-core`) + Vite/React client·admin (`@xfilecom/front
32
34
 
33
35
  설정 흐름, `DatabaseService` / `DatabaseQuery` 주입, Drizzle Kit 스크립트는 **[docs/DATABASE.md](./docs/DATABASE.md)** 를 보면 됩니다.
34
36
 
37
+ ## 브라우저 콘솔: `content.js`, `chrome-extension://invalid`, `locales.getpip.com`
38
+
39
+ Client/Admin을 Chrome으로 열었을 때 아래 같은 메시지가 **앱 코드와 무관**하게 뜰 수 있습니다.
40
+
41
+ | 증상 | 원인 |
42
+ |------|------|
43
+ | `content.js:…` 스택 | Chrome **확장 프로그램**이 페이지에 주입한 스크립트 |
44
+ | `GET chrome-extension://invalid/ … ERR_FAILED` | 지갑·Web3 등 확장이 잘못된 확장 URL로 리소스를 요청할 때 |
45
+ | `GET https://locales.getpip.com/… … ERR_NAME_NOT_RESOLVED` | 일부 확장이 원격 번역/로케일을 가져오다 DNS·네트워크로 실패할 때 |
46
+
47
+ **대응:** 앱 버그가 아니므로 무시해도 됩니다. 콘솔을 깨끗이 보고 싶으면 **시크릿 창**(확장 기본 비활성)에서 `localhost`를 열거나, 개발용 Chrome 프로필에서 확장을 끄면 됩니다.
48
+
49
+ 자세한 설명은 **[docs/WEB_DEV_CONSOLE.md](./docs/WEB_DEV_CONSOLE.md)** 참고.
50
+
35
51
  ## GitLab `~/.npmrc` 와 충돌 시
36
52
 
37
53
  프로젝트 루트 `.npmrc`의 `@xfilecom:registry`가 npm 공개 레지스트리를 가리키므로, `@xfilecom/*` 설치는 여기서 우선합니다.
@@ -3,9 +3,9 @@
3
3
  "version": "0.0.1",
4
4
  "private": true,
5
5
  "scripts": {
6
- "build": "nest build",
7
- "start": "nest build && node --enable-source-maps dist/apps/api/src/main.js",
8
- "start:dev": "tsc-watch -p tsconfig.build.json --onSuccess \"node --enable-source-maps dist/apps/api/src/main.js\" --noClear",
6
+ "build": "nest build && tsc-alias -p tsconfig.build.json",
7
+ "start": "npm run build && node --enable-source-maps dist/apps/api/src/main.js",
8
+ "start:dev": "tsc-watch -p tsconfig.build.json --onSuccess \"tsc-alias -p tsconfig.build.json && node --enable-source-maps dist/apps/api/src/main.js\" --noClear",
9
9
  "start:prod": "node --enable-source-maps dist/apps/api/src/main.js"
10
10
  },
11
11
  "dependencies": {
@@ -20,6 +20,7 @@
20
20
  "@nestjs/cli": "^10.0.0",
21
21
  "@types/express": "^4.17.21",
22
22
  "@types/node": "^20.0.0",
23
+ "tsc-alias": "^1.8.10",
23
24
  "tsc-watch": "^6.2.1",
24
25
  "typescript": "^5.0.0"
25
26
  }
@@ -5,7 +5,7 @@ import { AppController } from './app.controller';
5
5
  import { AppService } from './app.service';
6
6
  import { SqlQueryController } from './sql-query/sql-query.controller';
7
7
  import { SqlQueryService } from './sql-query/sql-query.service';
8
- import { schema } from '../../../shared/schema';
8
+ import { schema } from '@shared/schema';
9
9
 
10
10
  function coreOptionsFromYaml(): CoreModuleOptions {
11
11
  const c = appConfig.core;
@@ -8,7 +8,7 @@ import {
8
8
  } from '@nestjs/common';
9
9
  import { ControllerHelpers, Public } from '@xfilecom/backend-core';
10
10
  import { appConfig } from '../config.loader';
11
- import type { SqlDatabaseListPostBody, SqlListPostBody } from '../../../../shared/sql/sql';
11
+ import type { SqlDatabaseListPostBody, SqlListPostBody } from '@shared/sql/sql';
12
12
  import { SqlQueryService } from './sql-query.service';
13
13
 
14
14
  /**
@@ -11,13 +11,13 @@ import {
11
11
  listPageableColumnNames,
12
12
  pageableFromClause,
13
13
  pickDefaultSortColumn,
14
- } from '../../../../shared/sql/pageable-drizzle';
14
+ } from '@shared/sql/pageable-drizzle';
15
15
  import {
16
16
  getPageableResourceKeyByMysqlTableName,
17
17
  getPageableTable,
18
18
  getPageableTableByMysqlTableName,
19
19
  PAGEABLE_RESOURCE_OPTIONS,
20
- } from '../../../../shared/sql/pageable-tables';
20
+ } from '@shared/sql/pageable-tables';
21
21
  import {
22
22
  escapeLikePattern,
23
23
  isSafeSqlIdentifier,
@@ -25,7 +25,7 @@ import {
25
25
  resolveEndpointSqlQuery,
26
26
  type SqlDatabaseListPostBody,
27
27
  type SqlListPostBody,
28
- } from '../../../../shared/sql/sql';
28
+ } from '@shared/sql/sql';
29
29
 
30
30
  @Injectable()
31
31
  export class SqlQueryService {
@@ -10,6 +10,9 @@
10
10
  "sourceMap": true,
11
11
  "outDir": "./dist",
12
12
  "baseUrl": "./",
13
+ "paths": {
14
+ "@shared/*": ["../../shared/*"]
15
+ },
13
16
  "incremental": true,
14
17
  "skipLibCheck": true,
15
18
  "strictNullChecks": false,
@@ -0,0 +1,20 @@
1
+ # 웹 Client/Admin — 브라우저 콘솔 노이즈
2
+
3
+ Chrome에서 `http://localhost:3001` 등을 열었을 때 DevTools 콘솔에 아래가 보일 수 있습니다. **이 프로젝트(Vite/React) 소스와는 무관**합니다.
4
+
5
+ ## `content.js` / `chrome-extension://invalid/`
6
+
7
+ - Chrome **확장 프로그램**이 모든 탭에 주입하는 **content script**가 `content.js`처럼 보이는 스택을 남깁니다.
8
+ - `chrome-extension://invalid/` 요청은 지갑·Web3·기타 확장이 내부 리소스 URL을 잘못 잡았을 때 발생합니다.
9
+ - 스택에 `getProvider`, `autoConnect` 등이 보이면 **지갑 확장** 쪽일 가능성이 큽니다.
10
+
11
+ ## `locales.getpip.com` / `ERR_NAME_NOT_RESOLVED`
12
+
13
+ - 일부 확장이 원격 번역 JSON을 받아오다 DNS 실패·차단으로 네트워크 오류를 냅니다.
14
+ - 앱의 `fetch` / 라우팅과는 별개입니다.
15
+
16
+ ## 권장 대응
17
+
18
+ 1. **무시** — 앱 동작·배포와 무관하면 그대로 두어도 됩니다.
19
+ 2. **시크릿 창**에서 로컬 호스트를 열면 확장이 기본 꺼져 콘솔이 조용해집니다.
20
+ 3. 개발 전용 Chrome 프로필에서 확장을 끄거나, 해당 확장만 비활성화합니다.
@@ -10,6 +10,8 @@
10
10
  | **`sql/`** | 마이그레이션·시드·원시 SQL; **`sql/sql.ts`** (`databaseSqlManifest`) 로 경로·절차 메타 정리 |
11
11
  | **`endpoint/`** | HTTP 계약(OpenAPI yaml, 공유 DTO 타입, 라우트 메타) — 제품에 맞게 확장 |
12
12
 
13
+ 프론트 전용 공유 패키지(**`web/shared`**)는 이 루트 `shared/`와 **별도**입니다. 설명은 **[`web/shared/README.md`](../web/shared/README.md)** 를 참고하세요.
14
+
13
15
  `apps/api/src/config.loader.ts`는 **`shared/config/api`** 를 읽습니다.
14
16
  `web/client/vite.config.ts` / `web/admin/vite.config.ts`는 각각 **`shared/config/web/client`**, **`shared/config/web/admin`** 을 읽습니다.
15
17
 
@@ -1,9 +1,9 @@
1
1
  import React from 'react';
2
2
  import ReactDOM from 'react-dom/client';
3
3
  import '@xfilecom/front-core/tokens.css';
4
- import '../../shared/src/styles/xfc-theme.css';
4
+ import '__WEB_SHARED_WORKSPACE__/styles/xfc-theme.css';
5
5
  import '@xfilecom/front-core/base.css';
6
- import '../../shared/src/styles/app.css';
6
+ import '__WEB_SHARED_WORKSPACE__/styles/app.css';
7
7
  import { App } from './App';
8
8
 
9
9
  ReactDOM.createRoot(document.getElementById('root')!).render(
@@ -1,9 +1,9 @@
1
1
  import React from 'react';
2
2
  import ReactDOM from 'react-dom/client';
3
3
  import '@xfilecom/front-core/tokens.css';
4
- import '../../shared/src/styles/xfc-theme.css';
4
+ import '__WEB_SHARED_WORKSPACE__/styles/xfc-theme.css';
5
5
  import '@xfilecom/front-core/base.css';
6
- import '../../shared/src/styles/app.css';
6
+ import '__WEB_SHARED_WORKSPACE__/styles/app.css';
7
7
  import { App } from './App';
8
8
 
9
9
  ReactDOM.createRoot(document.getElementById('root')!).render(
@@ -0,0 +1,25 @@
1
+ # `web/shared` — 클라이언트·어드민 공유 패키지
2
+
3
+ Vite 앱(`web/client`, `web/admin`)이 함께 쓰는 **React 컴포넌트, 스타일, 훅, 타입**을 두는 워크스페이스 패키지입니다.
4
+ 프로젝트 루트의 **`shared/`**(Drizzle 스키마, `sql/`, API `config/` 등)와 **별도**입니다.
5
+
6
+ ## 백엔드 `@shared/*`와 겹치나요?
7
+
8
+ **겹치지 않습니다.** Nest(`apps/api`)는 `@shared/*`를 루트 `shared/`로만 쓰고, 프론트는 이 패키지의 **npm 이름**(`__WEB_SHARED_WORKSPACE__` → 스캐폴드 시 실제 이름)과 **`exports`** 서브패스로만 연결합니다.
9
+
10
+ ## 스타일 (`main.tsx`)
11
+
12
+ ```ts
13
+ import '@xfilecom/front-core/tokens.css';
14
+ import '__WEB_SHARED_WORKSPACE__/styles/xfc-theme.css';
15
+ import '@xfilecom/front-core/base.css';
16
+ import '__WEB_SHARED_WORKSPACE__/styles/app.css';
17
+ ```
18
+
19
+ ## TS/컴포넌트
20
+
21
+ ```ts
22
+ import { Shell } from '__WEB_SHARED_WORKSPACE__';
23
+ ```
24
+
25
+ 새 파일을 앱에서 가져오려면 `package.json`의 **`exports`**에 서브패스를 추가하세요.