diff --git a/packages/app-shell/src/views/metadata-admin/i18n.ts b/packages/app-shell/src/views/metadata-admin/i18n.ts index 477f24dbb..76bffbfe6 100644 --- a/packages/app-shell/src/views/metadata-admin/i18n.ts +++ b/packages/app-shell/src/views/metadata-admin/i18n.ts @@ -632,10 +632,7 @@ const ENGINE_STRINGS_EN: Record = { 'engine.packages.create.title': 'New Package', 'engine.packages.create.description': 'Create a project-scoped package to author and publish your own metadata. The id should be reverse-domain (e.g. {example}).', 'engine.packages.create.id': 'Package ID', - 'engine.packages.create.idInvalid': 'Use letters, numbers, dot, dash or underscore (2–255 chars).', 'engine.packages.create.namespace': 'Object namespace', - 'engine.packages.create.namespaceHint': 'All object names will start with `{ns}_` (e.g. leave_request).', - 'engine.packages.create.namespaceInvalid': 'Use 2–20 chars: a lowercase letter, then letters, digits or underscore.', 'engine.packages.create.name': 'Display name', 'engine.packages.create.version': 'Version', 'engine.packages.create.versionInvalid': 'Use semantic version, e.g. 0.1.0', @@ -1045,7 +1042,6 @@ const ENGINE_STRINGS_EN: Record = { 'engine.studio.landing.dupIdPlaceholder': 'Copy package ID', 'engine.studio.landing.dupGo': 'Duplicate and open the builder', 'engine.studio.landing.dupCreated': 'Duplicated into writable package “{name}”', - 'engine.studio.landing.createGo': 'Create and start building', 'engine.studio.landing.installedHeading': 'Installed (read-only · browsable)', 'engine.studio.designer.search': 'Search…', 'engine.studio.designer.select': 'Select…', @@ -1167,14 +1163,8 @@ const ENGINE_STRINGS_EN: Record = { 'engine.studio.pkg.writable': 'Writable', 'engine.studio.pkg.heading': 'Packages (apps)', 'engine.studio.pkg.none': 'No app packages yet', - 'engine.studio.pkg.namePlaceholder': 'Name (e.g. Repair Center)', - 'engine.studio.pkg.idPlaceholder': 'Package ID (e.g. com.example.repairs)', - 'engine.studio.pkg.namespacePlaceholder': 'Namespace (e.g. repairs)', - 'engine.studio.pkg.namespaceHint': 'All object names will start with `{ns}_` (e.g. leave_request).', - 'engine.studio.pkg.namespaceInvalid': 'Use 2–20 chars: a lowercase letter, then letters, digits or underscore.', 'engine.studio.pkg.idStrippedNotice': 'Unsupported characters were removed — allowed: lowercase letters, digits, dots, hyphens, underscores', 'engine.studio.pkg.idFormatHint': 'Use a reverse-domain identifier with at least one dot, e.g. com.example.myapp', - 'engine.studio.pkg.idFromNameUnavailable': 'No identifier could be suggested from this name — type one below (e.g. com.example.myapp)', 'engine.studio.pkg.createWritable': 'Create writable package', 'engine.studio.pkg.new': 'New package (writable base)', 'engine.studio.pkg.created': 'Package {name} created (writable)', @@ -1938,10 +1928,7 @@ const ENGINE_STRINGS_ZH: Record = { 'engine.packages.create.title': '新建软件包', 'engine.packages.create.description': '创建项目范围的软件包,用来编写并发布自己的元数据。ID 建议使用反向域名格式(例如 {example})。', 'engine.packages.create.id': '软件包 ID', - 'engine.packages.create.idInvalid': '只能使用字母、数字、点、短横线或下划线(2–255 个字符)。', 'engine.packages.create.namespace': '对象命名空间', - 'engine.packages.create.namespaceHint': '所有对象名将以 `{ns}_` 开头(如 leave_request)。', - 'engine.packages.create.namespaceInvalid': '请使用 2–20 个字符:以小写字母开头,其后为字母、数字或下划线。', 'engine.packages.create.name': '显示名称', 'engine.packages.create.version': '版本', 'engine.packages.create.versionInvalid': '请使用语义化版本号,例如 0.1.0', @@ -2347,7 +2334,6 @@ const ENGINE_STRINGS_ZH: Record = { 'engine.studio.landing.dupIdPlaceholder': '副本包 ID', 'engine.studio.landing.dupGo': '复制并进入构建器', 'engine.studio.landing.dupCreated': '已复制为可写软件包「{name}」', - 'engine.studio.landing.createGo': '创建并开始构建', 'engine.studio.landing.installedHeading': '已安装(只读 · 可浏览)', 'engine.studio.designer.search': '搜索…', 'engine.studio.designer.select': '请选择…', @@ -2469,14 +2455,8 @@ const ENGINE_STRINGS_ZH: Record = { 'engine.studio.pkg.writable': '可写', 'engine.studio.pkg.heading': '软件包(应用)', 'engine.studio.pkg.none': '暂无应用软件包', - 'engine.studio.pkg.namePlaceholder': '名称(如:维修中心)', - 'engine.studio.pkg.idPlaceholder': '包 ID(如:com.example.repairs)', - 'engine.studio.pkg.namespacePlaceholder': '命名空间(如:repairs)', - 'engine.studio.pkg.namespaceHint': '所有对象名将以 `{ns}_` 开头(如 leave_request)。', - 'engine.studio.pkg.namespaceInvalid': '请使用 2–20 个字符:以小写字母开头,其后为字母、数字或下划线。', 'engine.studio.pkg.idStrippedNotice': '已移除不支持的字符——仅允许小写字母、数字、点、连字符和下划线', 'engine.studio.pkg.idFormatHint': '请使用带至少一个点的反向域名标识,如 com.example.myapp', - 'engine.studio.pkg.idFromNameUnavailable': '无法从该名称生成标识,请在下方手动输入(如 com.example.myapp)', 'engine.studio.pkg.createWritable': '创建可写软件包', 'engine.studio.pkg.new': '新建软件包(可写 base)', 'engine.studio.pkg.created': '软件包 {name} 已创建(可写)', diff --git a/packages/app-shell/src/views/studio-design/PackageIdInput.test.tsx b/packages/app-shell/src/views/studio-design/PackageIdInput.test.tsx index 13567a1fe..1e32c4649 100644 --- a/packages/app-shell/src/views/studio-design/PackageIdInput.test.tsx +++ b/packages/app-shell/src/views/studio-design/PackageIdInput.test.tsx @@ -5,7 +5,7 @@ import * as React from 'react'; import { afterEach, describe, expect, it, vi } from 'vitest'; import { render, screen, fireEvent, cleanup } from '@testing-library/react'; import { sanitizePackageId, PACKAGE_ID_RE } from './packages-io'; -import { PackageIdInput, PackageIdSuggestionHint } from './PackageIdInput'; +import { PackageIdInput } from './PackageIdInput'; afterEach(cleanup); @@ -66,12 +66,3 @@ describe('PackageIdInput', () => { expect(screen.queryByTestId('pkg-id-stripped')).not.toBeInTheDocument(); }); }); - -describe('PackageIdSuggestionHint', () => { - it('renders only when shown (CJK name yielded no suggestion)', () => { - const { rerender } = render(); - expect(screen.queryByTestId('pkg-id-manual-hint')).not.toBeInTheDocument(); - rerender(); - expect(screen.getByTestId('pkg-id-manual-hint')).toBeInTheDocument(); - }); -}); diff --git a/packages/app-shell/src/views/studio-design/PackageIdInput.tsx b/packages/app-shell/src/views/studio-design/PackageIdInput.tsx index c96b356ad..f3b1bde71 100644 --- a/packages/app-shell/src/views/studio-design/PackageIdInput.tsx +++ b/packages/app-shell/src/views/studio-design/PackageIdInput.tsx @@ -1,9 +1,10 @@ // Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license. /** - * Package-identifier input shared by the three package wizards (switcher - * create, landing create, landing duplicate). Fixes the dogfood wizard - * findings (framework#2615 P2): illegal characters are still normalized + * Package-identifier input used by the landing "duplicate package" form. + * (Package create/edit now runs through the spec-driven PackageFormDialog.) + * Fixes the dogfood wizard findings (framework#2615 P2): illegal characters + * are still normalized * away, but no longer silently — a notice says so — and while the value * doesn't parse as a package id yet, an inline hint spells out the * reverse-domain format instead of leaving the user staring at a disabled @@ -72,23 +73,3 @@ export function PackageIdInput({ ); } - -/** - * Hint under the display-name input when the name yields no identifier - * suggestion (CJK-only names slug to nothing) — say the id must be typed - * manually instead of leaving the id box silently empty. - */ -export function PackageIdSuggestionHint({ - show, - locale, -}: { - show: boolean; - locale?: string; -}): React.ReactElement | null { - if (!show) return null; - return ( -

- {t('engine.studio.pkg.idFromNameUnavailable', locale)} -

- ); -} diff --git a/packages/app-shell/src/views/studio-design/packages-io.ts b/packages/app-shell/src/views/studio-design/packages-io.ts index 06c46af42..4f70bbf46 100644 --- a/packages/app-shell/src/views/studio-design/packages-io.ts +++ b/packages/app-shell/src/views/studio-design/packages-io.ts @@ -54,28 +54,6 @@ export async function fetchPackages(): Promise { return parsePackages(await res.json()); } -/** - * Create a writable base package (POST /packages {id, name, namespace?}). - * - * `namespace` is the object-name prefix (framework#2694). The framework - * back-derives it from the id when omitted, but sending it explicitly keeps the - * authored value (which the user may have edited) authoritative. - */ -export async function createBasePackage(id: string, name: string, namespace?: string): Promise { - const res = await fetch('/api/v1/packages', { - method: 'POST', - credentials: 'include', - headers: { 'Content-Type': 'application/json', Accept: 'application/json' }, - body: JSON.stringify({ id, name, ...(namespace ? { namespace } : {}) }), - }); - const payload = (await res.json().catch(() => null)) as - | { success?: boolean; error?: { message?: string } } - | null; - if (!res.ok || payload?.success === false) { - throw new Error(payload?.error?.message || `HTTP ${res.status}`); - } -} - /** * Duplicate a package into a NEW writable base (ADR-0070 D4 — the Airtable * "duplicate base" gesture; POST /packages/:id/duplicate). This is how a