본문으로 건너뛰기

예제

Descriptor 만들고 수정하기

Workshop Note의 typed 전자결재 binding과 문서 schema를 게시하고 도메인 양식에 나타난 결과를 확인합니다.

예제 유형 레시피

개요

Descriptor 만들고 수정하기 예제

이 예제는 같은 Workshop Note를 전자결재에 연결할 수 있도록 ApprovalFormBindingDescriptor와 ApprovalDocumentSchema를 추가합니다. 앞의 Contributor 만들기에서 workshop.note.publish 권한을 추가했다고 가정합니다.

이 예제가 다루는 범위

Descriptor는 여러 Core 런타임에 App 기능을 공개하는 공통 방식이지만, 이 예제는 그중 전자결재에 필요한 binding과 문서 schema만 다룹니다. 테넌트가 작성한 BPMN의 Service Task에서 App 업무 동작을 실행하려면 전자결재 descriptor를 재사용하지 않고 ProcessWorkActionDescriptor를 별도로 게시해야 합니다.

ProcessWorkActionDescriptor로 BPMN 선택기에 동작 공개
  → 서비스 프로바이더가 ProcessWorkActionRegistrar에 handler factory 등록
  → ProcessWorkActionHandler::handle()이 복원된 실행 문맥과 입력을 받음
  → ProcessWorkActionResult로 출력을 반환

Descriptor 선언은 catalog와 실행 계약을 공개할 뿐 App 업무 로직을 실행하지 않습니다. 실제 처리는 App 소유 handler가 담당합니다. Process 시작 binding, 사용자 태스크 폼, 가져올 수 있는 Process template도 각각 ProcessStartBindingDescriptor, ProcessUserTaskFormDescriptor, ProcessTemplateDescriptor라는 별도 계약을 사용합니다. 실제 descriptor, handler, 서비스 프로바이더 등록은 다음 업무 프로세스 기여하기에서 이어집니다. BPMN 연동의 전체 선택 기준과 런타임 시그니처는 업무 프로세스와 업무 프로세스 계약을 보세요.

이 작업이 끝나면

생기는 것확인 위치
workshop.note.submit binding전자결재 → 양식 관리 → 새 전자결재 양식 → 업무 양식 → 도메인 양식
이름·상태 snapshot schema양식 미리 보기와 결재 상세가 사용할 공개 문서 구조
새 메뉴없음. 전자결재 메뉴는 Core가 소유함

Workshop 노트 제출 Descriptor

위 화면이 작업 완료 후 실제로 추가되는 정보입니다. 도메인 양식 dialog에서 Workshop을 검색하면 노트 제출이 기타 앱 → Workshop 아래에 나타납니다. 이 단계는 관리자가 연결할 수 있는 선택지를 만든 것이며, 사용자용 작성 Widget은 다음 전자 결재에 기여하기에서 연결합니다.

어떤 계약을 구현하고 Core가 어떻게 받는가

WorkshopApprovalDescriptors도 Core 클래스를 상속하지 않습니다. App SDK의 AppDescriptorContribution을 구현하고 appDescriptors()에서 AppDescriptorSet을 반환합니다. ApprovalFormBindingDescriptor와 ApprovalDocumentSchema는 개발자가 상속하는 base class가 아니라, SDK가 제공하는 final descriptor 값 객체입니다.

WorkshopApprovalDescriptors implements AppDescriptorContribution
  → NexiaContributionRegistry가 구현 클래스를 발견
  → AppDescriptorCatalog가 appDescriptors()를 호출
  → descriptor type + key 중복을 검사하고 Workshop 소유권을 기록
  ├─ ApprovalBindingRegistry가 ApprovalFormBindingDescriptor를 소비
  └─ ApprovalDocumentSchemaRegistry가 ApprovalDocumentSchema를 소비
     (두 Registry 모두 현재 tenant의 App 설치 상태와 lifecycle을 다시 검사)

따라서 appDescriptors()에 객체를 넣는 행위는 UI를 직접 그리는 코드가 아닙니다. Core의 전자결재 Registry가 이 정적 계약을 읽어 연결 가능한 도메인 양식과 동결할 문서 값의 구조로 해석합니다. ContributionOwner는 클래스가 발견된 Workshop namespace에서 정해지므로 App이 다른 App 소유인 것처럼 descriptor를 게시할 수도 없습니다.

1. Descriptor 추가

코드 예시
Shell
cp docs/developers/examples/descriptor/WorkshopApprovalDescriptors.php \
  packages/workshop/src/Descriptors/WorkshopApprovalDescriptors.php

binding의 핵심은 다음과 같습니다.

코드 예시
PHP
new ApprovalFormBindingDescriptor(
    appKey: 'workshop',
    resourceKey: 'note',
    actionKey: 'submit',
    labelKey: 'workshop.approval.note.submit.label',
    entryModes: ['link'],
    formWidgetKey: 'workshop.note.submit',
    documentSchemaKey: 'workshop.note',
    descriptionKey: 'workshop.approval.note.submit.description',
    submitPermissionKey: 'workshop.note.publish',
)

link는 이미 존재하는 Note를 연결한다는 뜻입니다. submit permission은 catalog 가시성을 제한하지만, 레코드별 backend Policy를 대신하지 않습니다.

같은 set에 binding이 참조하는 schema도 게시합니다.

코드 예시
PHP
new ApprovalDocumentSchema(
    appKey: 'workshop',
    resourceKey: 'note',
    titleKey: 'workshop.approval.note.document.title',
    sections: [[
        'title_key' => 'workshop.approval.note.document.summary',
        'fields' => [
            ['key' => 'name', 'label_key' => 'workshop.note.name.label', 'type' => 'string'],
            ['key' => 'status', 'label_key' => 'workshop.note.status.label', 'type' => 'string'],
        ],
    ]],
)

Schema는 모델 column을 자동 반사하지 않습니다. App이 제출 시 동결할 documentValues의 공개 shape만 선언합니다.

2. locale 추가

Workshop이 지원하는 모든 locale에 같은 dotted key를 추가합니다.

코드 예시
JSON
{
  "workshop.approval.note.submit.label": "노트 제출",
  "workshop.approval.note.submit.description": "기존 노트를 전자결재에 연결합니다.",
  "workshop.approval.note.document.title": "노트",
  "workshop.approval.note.document.summary": "노트 내용"
}

3. 발견과 화면 확인

코드 예시
Shell
sh docs/developers/examples/descriptor/verify.sh

성공한 뒤 위 캡처의 경로에서 Workshop을 검색합니다. App 설치 상태, submitPermissionKey, lifecycle, locale가 모두 맞아야 항목이 보입니다.

4. Descriptor 수정

표시 문구만 바꿀 때는 locale 값만 수정하고 identity와 version을 유지합니다. 호환 가능한 optional 계약을 추가한다면 consumer 호환성을 확인하고 version을 올립니다.

코드 예시
PHP
version: '1.1',

action key, field type, requiredness처럼 기존 의미를 깨는 변경은 새 descriptor를 Active로 추가하고 기존 버전을 Deprecated로 전환합니다. 저장된 양식과 consumer가 이동한 뒤에만 Removed로 바꿉니다.

자주 발생하는 오류

증상원인해결다시 확인
validator는 성공하지만 도메인 양식 목록에 없음Workshop이 tenant에 설치되지 않았거나 사용자에게 submit 권한이 없거나 descriptor가 Active가 아님설치 상태, workshop.note.publish 배정과 lifecycle을 확인같은 tenant와 Legal Entity에서 Workshop 검색 시 노트 제출이 표시됨
raw locale key가 보임Workshop이 지원하는 locale 중 하나에 동일한 dotted key가 없음모든 resources/lang/{locale}.json에 네 key를 추가하고 runtime cache 갱신선택기에 번역된 노트 제출과 설명이 표시됨
목록에는 있지만 작성 화면이 열리지 않음Descriptor는 정적 catalog만 게시했고 Slot Widget과 frontend registry가 아직 없음다음 전자결재 contribution 레시피에서 네 workshop.note.submit identity를 연결작성 화면이 Workshop Widget을 로드함
schema를 찾지 못함binding의 documentSchemaKey와 schema의 appKey.resourceKey identity가 다름둘을 정규 workshop.note identity로 맞춤verify.sh가 Descriptor contracts are valid.를 출력

포함된 파일

전자결재 Descriptor

docs/developers/examples/descriptor/WorkshopApprovalDescriptors.php
코드 예시
PHP
<?php

declare(strict_types=1);

namespace Amuzcorp\Nexia\Workshop\Descriptors;

use Nexia\AppDescriptors\AppDescriptorSet;
use Nexia\AppDescriptors\ApprovalDocumentSchema;
use Nexia\AppDescriptors\ApprovalFormBindingDescriptor;
use Nexia\AppDescriptors\Contracts\AppDescriptorContribution;

final class WorkshopApprovalDescriptors implements AppDescriptorContribution
{
    public static function appDescriptors(): AppDescriptorSet
    {
        return AppDescriptorSet::of(
            new ApprovalFormBindingDescriptor(
                appKey: 'workshop',
                resourceKey: 'note',
                actionKey: 'submit',
                labelKey: 'workshop.approval.note.submit.label',
                entryModes: ['link'],
                formWidgetKey: 'workshop.note.submit',
                documentSchemaKey: 'workshop.note',
                descriptionKey: 'workshop.approval.note.submit.description',
                submitPermissionKey: 'workshop.note.publish',
            ),
            new ApprovalDocumentSchema(
                appKey: 'workshop',
                resourceKey: 'note',
                titleKey: 'workshop.approval.note.document.title',
                sections: [[
                    'title_key' => 'workshop.approval.note.document.summary',
                    'fields' => [
                        [
                            'key' => 'name',
                            'label_key' => 'workshop.note.name.label',
                            'type' => 'string',
                        ],
                        [
                            'key' => 'status',
                            'label_key' => 'workshop.note.status.label',
                            'type' => 'string',
                        ],
                    ],
                ]],
            ),
        );
    }
}

Descriptor 갱신과 검증

docs/developers/examples/descriptor/verify.sh
코드 예시
Shell
#!/usr/bin/env sh
set -eu

test -f packages/workshop/src/Descriptors/WorkshopApprovalDescriptors.php

task artisan -- nexia-runtime:refresh-runtime-caches --if-route-cached --no-ansi
task artisan -- nexia-apps:validate-app-descriptors workshop --no-ansi
task artisan -- nexia-apps:doctor-package-app workshop --no-ansi

printf '%s\n' 'Descriptor contracts are valid. Confirm the new binding in the Electronic Approval domain-form catalog.'