@nexia/sdk 0.8.8 → 0.8.10
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/README.md +56 -0
- package/changelog/0.8.9/en.md +17 -0
- package/changelog/0.8.9/ko.md +17 -0
- package/dist/platform.d.ts +12 -0
- package/dist/testing.d.ts +1 -1
- package/dist/testing.js +2 -2
- package/dist/vite.mjs +31 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -8,8 +8,64 @@ Report SDK, setup, CLI, Docker, AI-tool and sandbox problems in the [central dev
|
|
|
8
8
|
|
|
9
9
|
SDK·개발환경·CLI·Docker·AI 도구·샌드박스 문제는 [통합 이슈 창구](https://github.com/nexia-cloud-os/developer-support/issues)에 신고하세요. 기존 이슈를 먼저 검색하고 패키지 버전과 최소 재현 단계를 포함하세요. 인증 정보, 비공개 Core 소스와 고객 데이터는 첨부하지 마세요.
|
|
10
10
|
|
|
11
|
+
## Standalone App frontend tests
|
|
12
|
+
|
|
13
|
+
Run Vitest in the App repository with `environment: 'jsdom'`, its own setup file,
|
|
14
|
+
and the App's React dependencies. Install `@testing-library/react`,
|
|
15
|
+
`@testing-library/jest-dom`, `jsdom`, `i18next`, `msw`, and `vitest` as App test
|
|
16
|
+
dependencies. No Core checkout or Core test setup is required.
|
|
17
|
+
|
|
18
|
+
The existing `configureNexiaAppFrontendHost` API accepts a complete explicit host
|
|
19
|
+
fixture. `configureNexiaAppFrontendTestHost` connects the suite's i18n and MSW
|
|
20
|
+
instances to `appTestI18n` and `appTestServer`.
|
|
21
|
+
|
|
22
|
+
Configure explicit host capabilities through the existing public API in the
|
|
23
|
+
suite's setup file. Supply a real axios instance and explicit public component,
|
|
24
|
+
hook, runtime, and registry fixtures for the capabilities exercised by that suite.
|
|
25
|
+
Missing capabilities should throw instead of supplying automatic UI or permission
|
|
26
|
+
substitutes. No new SDK API or SDK release is needed.
|
|
27
|
+
|
|
28
|
+
Connect the suite's own i18n and MSW instances with
|
|
29
|
+
`configureNexiaAppFrontendTestHost({ i18n, server })`. Register
|
|
30
|
+
`server.listen({ onUnhandledRequest: 'error' })` in Vitest `beforeAll`, run React
|
|
31
|
+
Testing Library `cleanup()` and `server.resetHandlers()` in `afterEach`, and call
|
|
32
|
+
`server.close()` in `afterAll`. Use one installed SDK instance throughout the
|
|
33
|
+
suite so its main and `/testing` exports share the same configured host.
|
|
34
|
+
|
|
35
|
+
App fixtures can verify App branching, validation, and request payloads. A DOM
|
|
36
|
+
substitute for a host component does not verify that component's accessibility,
|
|
37
|
+
keyboard behavior, or production rendering; those checks belong to its host.
|
|
38
|
+
Reconfigure mutable fixtures per test to avoid state leaking between cases.
|
|
39
|
+
|
|
11
40
|
## Standalone App styles
|
|
12
41
|
|
|
13
42
|
`nexiaAppConfig(import.meta.url)` generates Tailwind utilities from the App resources, including lazy screens, and records emitted CSS in `nexia-host.json`. The build references the shared `@nexia/sdk/theme.css` token aliases; Core supplies token values and resets. Keep those aliases aligned with the Core theme contract. Do not bundle a second preflight or global theme.
|
|
14
43
|
|
|
15
44
|
After adopting the SDK release containing this fix, rebuild and resubmit each standalone App. Existing deployed bundles are unchanged until replaced. Custom builds must declare every emitted stylesheet in `nexia-host.json`.
|
|
45
|
+
|
|
46
|
+
### App API and Core host capabilities
|
|
47
|
+
|
|
48
|
+
`api` from `@nexia/sdk/host` is bound to the calling App. It is not an
|
|
49
|
+
unrestricted HTTP client for Core. Development frames and installed App surfaces
|
|
50
|
+
use the same host transport policy; a mocked Axios response or direct HTTP test
|
|
51
|
+
does not exercise that boundary.
|
|
52
|
+
|
|
53
|
+
Use `useOrganizationTargetsQuery`, `useAffiliatedOperatingUnits` and Resource
|
|
54
|
+
Reference options for scoped business choices. Tenant-wide administration is a
|
|
55
|
+
different authority. Core's explicit host routes preserve their tenant-wide
|
|
56
|
+
permissions: legal-entity/operating-unit reads, operating-unit creation,
|
|
57
|
+
party duplicate lookup, user creation/invitation/credential sending, and the
|
|
58
|
+
actor's self-service profile. Unsupported methods and arbitrary Core routes
|
|
59
|
+
remain unavailable. A host refusal reports `APP_HOST_ROUTE_UNAVAILABLE` rather
|
|
60
|
+
than proving that the actor lacks a business permission.
|
|
61
|
+
|
|
62
|
+
`sendUserInvitation` and `useDataMigrationBackgroundOperation` retain the calling
|
|
63
|
+
App's client. Do not replace it with a global client to bypass a refusal.
|
|
64
|
+
Background operation status is accessible only to the originating App and actor;
|
|
65
|
+
Core returns 404 for another App's ticket even when the actor is the same.
|
|
66
|
+
The Core host-capability fix must be deployed before relying on these paths;
|
|
67
|
+
an SDK-only update does not install server routes.
|
|
68
|
+
|
|
69
|
+
Test both a successful call and a denied call through an actual development
|
|
70
|
+
frame or installed App transport. For invitations, use a test mail sink; for
|
|
71
|
+
imports, verify the terminal result as well as the initial 202 response.
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
---
|
|
2
|
+
status: published
|
|
3
|
+
version: 0.8.9
|
|
4
|
+
date: 2026-10-16
|
|
5
|
+
title: App frontend compatibility metadata
|
|
6
|
+
description: App frontend compatibility metadata
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# App frontend compatibility metadata
|
|
10
|
+
|
|
11
|
+
The standalone App build records its declared `@nexia/sdk` range, the SDK used to build it, and the shared host exports imported by the generated JavaScript. Platforms supporting this metadata can check compatibility before changing the host or opening a new App bundle. SDK version ranges do not replace behavioral compatibility tests.
|
|
12
|
+
|
|
13
|
+
Keep the supported SDK range in the App's `package.json` `peerDependencies` or `dependencies` and retain the dependency lock. Peer requirements take precedence when both are present. Rebuild with this SDK to include the metadata; the metadata alone does not require a new App version or change existing published bundles.
|
|
14
|
+
|
|
15
|
+
Apps without an explicit SDK requirement still build with their existing frontend manifest. Their host compatibility remains unknown and must be verified before a platform update. No automatic App upgrade is introduced.
|
|
16
|
+
|
|
17
|
+
Standalone builds warn when emitted JavaScript uses the deprecated `allowsManualAppFallback` or `isRetryableHandoffFailure` aliases. Replace them with `permitsManualFallback` or `isRetryableFailure`, respectively. No removal version is scheduled. This import check does not inspect erased TypeScript types or PHP annotations.
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
---
|
|
2
|
+
status: published
|
|
3
|
+
version: 0.8.9
|
|
4
|
+
date: 2026-10-16
|
|
5
|
+
title: 앱 프런트엔드 호환성 메타데이터
|
|
6
|
+
description: 앱 프런트엔드 호환성 메타데이터
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# 앱 프런트엔드 호환성 정보
|
|
10
|
+
|
|
11
|
+
독립 앱 빌드에 선언된 `@nexia/sdk` 지원 범위, 빌드에 사용한 SDK 버전, 생성된 JavaScript가 가져오는 공용 호스트 export 목록이 기록됩니다. 이 정보를 지원하는 플랫폼은 호스트를 바꾸거나 새 앱 번들을 열기 전에 호환성을 확인할 수 있습니다. SDK 버전 범위만으로 실제 동작의 호환성 검증을 대신할 수는 없습니다.
|
|
12
|
+
|
|
13
|
+
앱 `package.json`의 `peerDependencies` 또는 `dependencies`에 지원 SDK 범위를 유지하고 의존성 잠금 파일을 보관하세요. 두 곳에 모두 있으면 peer 요구사항을 우선합니다. 이번 SDK로 다시 빌드하면 정보가 포함되며, 정보 추가만으로 앱 버전을 올릴 필요는 없습니다. 이미 게시된 번들은 바뀌지 않습니다.
|
|
14
|
+
|
|
15
|
+
명시적인 SDK 요구사항이 없는 앱도 기존 프런트엔드 manifest 형식으로 빌드됩니다. 다만 호스트 호환성이 확인된 것은 아니므로 플랫폼 업데이트 전에 별도 검증이 필요합니다. 앱을 자동으로 업그레이드하지 않습니다.
|
|
16
|
+
|
|
17
|
+
독립 빌드의 JavaScript에서 deprecated 별칭인 `allowsManualAppFallback` 또는 `isRetryableHandoffFailure`를 사용하면 경고합니다. 각각 `permitsManualFallback`, `isRetryableFailure`로 바꾸세요. 제거 버전은 정해지지 않았습니다. 이 import 검사는 컴파일 후 사라지는 TypeScript 타입이나 PHP 주석을 검사하지 않습니다.
|
package/dist/platform.d.ts
CHANGED
|
@@ -302,6 +302,18 @@ export interface ProfileSlotPropsV2 {
|
|
|
302
302
|
familyKey: string;
|
|
303
303
|
workContext: SelfWorkContext | null;
|
|
304
304
|
}
|
|
305
|
+
/** App-owned workforce view in the Core organization surface. No access memberships are implied. */
|
|
306
|
+
export interface OrganizationWorkforceSlotPropsV1 {
|
|
307
|
+
slot: 'organization.workforce';
|
|
308
|
+
slotApiVersion: 1;
|
|
309
|
+
tenant: Pick<TenantContext, 'id' | 'name'>;
|
|
310
|
+
legalEntity: Pick<LegalEntityContext, 'name' | 'code' | 'public_id'>;
|
|
311
|
+
descriptorKey: string;
|
|
312
|
+
appKey: string;
|
|
313
|
+
familyKey: string;
|
|
314
|
+
view: 'chart' | 'table';
|
|
315
|
+
search: string;
|
|
316
|
+
}
|
|
305
317
|
export interface OperatingUnitScopeReference {
|
|
306
318
|
public_id: string;
|
|
307
319
|
code: string;
|
package/dist/testing.d.ts
CHANGED
|
@@ -6,7 +6,7 @@ export interface NexiaAppFrontendTestHostBindings {
|
|
|
6
6
|
use: (...handlers: unknown[]) => void;
|
|
7
7
|
};
|
|
8
8
|
}
|
|
9
|
-
/**
|
|
9
|
+
/** App or host test setup installs its own i18n and request-interception harness here. */
|
|
10
10
|
export declare function configureNexiaAppFrontendTestHost(bindings: NexiaAppFrontendTestHostBindings): void;
|
|
11
11
|
export declare const appTestI18n: {
|
|
12
12
|
changeLanguage: (language: string) => unknown;
|
package/dist/testing.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
let activeTestHost = null;
|
|
2
|
-
/**
|
|
2
|
+
/** App or host test setup installs its own i18n and request-interception harness here. */
|
|
3
3
|
export function configureNexiaAppFrontendTestHost(bindings) {
|
|
4
4
|
activeTestHost = bindings;
|
|
5
5
|
}
|
|
6
6
|
function testHost() {
|
|
7
7
|
if (activeTestHost === null) {
|
|
8
|
-
throw new Error('Nexia App frontend test host is not configured.
|
|
8
|
+
throw new Error('Nexia App frontend test host is not configured. Configure it with the test suite’s own i18n and request-interception fixtures before App specs run.');
|
|
9
9
|
}
|
|
10
10
|
return activeTestHost;
|
|
11
11
|
}
|
package/dist/vite.mjs
CHANGED
|
@@ -76,10 +76,39 @@ export const { api, openFile, sendUserInvitation, useDataMigrationBackgroundOper
|
|
|
76
76
|
},
|
|
77
77
|
generateBundle: { order: 'post', handler(_options, bundle) {
|
|
78
78
|
// Standalone App builds expose compatibility before executing their entry.
|
|
79
|
-
if (owners.length
|
|
79
|
+
if (owners.length !== 1) return;
|
|
80
|
+
let appPackage = {};
|
|
81
|
+
try { appPackage = JSON.parse(readFileSync(path.join(owners[0].root, 'package.json'), 'utf8')); }
|
|
82
|
+
catch (error) { if (error.code !== 'ENOENT') throw error; }
|
|
83
|
+
const required = appPackage.peerDependencies?.['@nexia/sdk'] ?? appPackage.dependencies?.['@nexia/sdk'];
|
|
84
|
+
const sdk = JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf8'));
|
|
85
|
+
const imports = {};
|
|
86
|
+
for (const chunk of Object.values(bundle)) {
|
|
87
|
+
if (chunk.type !== 'chunk') continue;
|
|
88
|
+
for (const [specifier, bindings] of Object.entries(chunk.importedBindings)) {
|
|
89
|
+
if (!nexiaHostPeers.includes(specifier)) continue;
|
|
90
|
+
imports[specifier] = [...new Set([...(imports[specifier] ?? []), ...bindings])].sort();
|
|
91
|
+
}
|
|
92
|
+
for (const specifier of chunk.dynamicImports) {
|
|
93
|
+
if (nexiaHostPeers.includes(specifier)) imports[specifier] = ['*'];
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
// These aliases are explicitly deprecated in index.ts; no removal release is declared.
|
|
97
|
+
const deprecated = { allowsManualAppFallback: 'permitsManualFallback', isRetryableHandoffFailure: 'isRetryableFailure' };
|
|
98
|
+
for (const [name, replacement] of Object.entries(deprecated)) {
|
|
99
|
+
if (imports['@nexia/sdk']?.includes(name)) {
|
|
100
|
+
this.warn(`[NEXIA_SDK_DEPRECATED] ${name}: use ${replacement}. Removal version is not scheduled.`);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
this.emitFile({
|
|
80
104
|
type: 'asset', fileName: 'nexia-host.json',
|
|
81
105
|
source: JSON.stringify({ version: 1, development_updates: 1, app_key: owners[0].appKey,
|
|
82
|
-
styles: Object.keys(bundle).filter(file => file.endsWith('.css'))
|
|
106
|
+
styles: Object.keys(bundle).filter(file => file.endsWith('.css')),
|
|
107
|
+
// Preserve builds that predate explicit host requirements. Their compatibility
|
|
108
|
+
// remains unknown; operators must not infer permission to change the host.
|
|
109
|
+
...(typeof required === 'string' && required.trim() && required.length <= 256
|
|
110
|
+
? { compatibility: { schema_version: 1, host_contract: 1,
|
|
111
|
+
sdk: { package: '@nexia/sdk', required, built_with: sdk.version }, imports } } : {}) }),
|
|
83
112
|
});
|
|
84
113
|
} },
|
|
85
114
|
};
|