From 69fbae6f010a00c9bbaacc3a0d5104036f6b2add Mon Sep 17 00:00:00 2001 From: Rishi Kunnath <82925475+rishikunnath2747@users.noreply.github.com> Date: Tue, 30 Sep 2025 09:29:40 +0530 Subject: [PATCH 1/8] changes for multi level entity UI --- .../demoapp/app/_i18n/i18n.properties | 24 ++ .../demoapp/app/admin-books/fiori-service.cds | 125 +++++++++- .../app/admin-books/webapp/manifest.json | 29 ++- cap-notebook/demoapp/app/common.cds | 228 ++++++++++-------- cap-notebook/demoapp/db/schema.cds | 94 +++++--- cap-notebook/demoapp/srv/admin-service.cds | 68 ++---- .../demoapp/srv/attachment-extension.cds | 87 +++---- cap-notebook/demoapp/srv/user-service.cds | 18 +- 8 files changed, 404 insertions(+), 269 deletions(-) diff --git a/cap-notebook/demoapp/app/_i18n/i18n.properties b/cap-notebook/demoapp/app/_i18n/i18n.properties index fd0c6145a..b6e53f774 100644 --- a/cap-notebook/demoapp/app/_i18n/i18n.properties +++ b/cap-notebook/demoapp/app/_i18n/i18n.properties @@ -21,3 +21,27 @@ attachment_status = Status attachment_note = Note attachment = Attachment attachments = Attachments + +#XFLD,50: Label for a section +Chapters=Chapters + +#XFLD,120: Label for entity +Chapter=Chapter + +#XFLD,120: Label for a field +ChapterTitle=Chapter Title + +#XFLD,120: Label for a field +ChapterType=Chapter Type + +#XFLD,120: Label for a field +Description=Description + +#XFLD,120: Label for a field +URL=URL + +#XFLD,50: Label for a section +GeneralInformation=General Information + +#XFLD,50: Label for a section +Attachments=Attachments diff --git a/cap-notebook/demoapp/app/admin-books/fiori-service.cds b/cap-notebook/demoapp/app/admin-books/fiori-service.cds index d8cd8382b..84aed7136 100644 --- a/cap-notebook/demoapp/app/admin-books/fiori-service.cds +++ b/cap-notebook/demoapp/app/admin-books/fiori-service.cds @@ -27,12 +27,6 @@ annotate AdminService.Books with @(UI: { Label : '{i18n>attachments}', Target: 'attachments/@UI.LineItem' }, - { - $Type : 'UI.ReferenceFacet', - ID : 'ReferencesFacet', - Label : 'References', - Target: 'references/@UI.LineItem' - }, { $Type : 'UI.ReferenceFacet', ID : 'FootnotesFacet', @@ -43,7 +37,13 @@ annotate AdminService.Books with @(UI: { $Type : 'UI.ReferenceFacet', Label : '{i18n>Admin}', Target: '@UI.FieldGroup#Admin' - } + }, + { + $Type : 'UI.ReferenceFacet', + Label : '{i18n>Chapters}', + ID : 'i18nChapters', + Target : 'chapters/@UI.LineItem#i18nChapters', + }, ], FieldGroup #General: {Data: [ {Value: title}, @@ -67,6 +67,110 @@ annotate AdminService.Books with @(UI: { ]} }); +////////// + +// Chapters annotations +annotate AdminService.Chapters with @title : '{i18n>Chapter}'; + +annotate AdminService.Books.chapters with @( + title : '{i18n>Chapters}' +); + +annotate AdminService.Chapters with @( + UI.LineItem : [ + { + $Type : 'UI.DataField', + Value : title, + Label : '{i18n>ChapterTitle}', + }, + { + $Type : 'UI.DataField', + Value : chapterType, + Label : '{i18n>ChapterType}', + }, + { + $Type : 'UI.DataField', + Value : description, + Label : '{i18n>Description}', + }, + ], + UI.LineItem #i18nChapters : [ + { + $Type : 'UI.DataField', + Value : title, + Label : '{i18n>ChapterTitle}', + }, + { + $Type : 'UI.DataField', + Value : chapterType, + Label : '{i18n>ChapterType}', + }, + { + $Type : 'UI.DataField', + Value : description, + Label : '{i18n>Description}', + }, + ] +); + +annotate AdminService.Chapters with @( + UI.HeaderInfo : { + Title : { + $Type : 'UI.DataField', + Value : title, + }, + TypeName : '{i18n>Chapter}', + TypeNamePlural : '{i18n>Chapters}', + Description : { + $Type : 'UI.DataField', + Value : description, + }, + } +); + +annotate AdminService.Chapters with @( + UI.FieldGroup #GeneratedGroup1 : { + $Type : 'UI.FieldGroupType', + Data : [ + { + $Type : 'UI.DataField', + Value : title, + Label : '{i18n>ChapterTitle}', + }, + { + $Type : 'UI.DataField', + Value : chapterType, + Label : '{i18n>ChapterType}', + }, + { + $Type : 'UI.DataField', + Value : description, + Label : '{i18n>Description}', + }, + { + $Type : 'UI.DataField', + Value : url, + Label : '{i18n>URL}', + }, + ], + }, + UI.Facets : [ + { + $Type : 'UI.ChapterFacet', + ID : 'GeneratedFacet1', + Label : '{i18n>GeneralInformation}', + Target : '@UI.FieldGroup#GeneratedGroup1', + }, + { + $Type : 'UI.ReferenceFacet', + ID : 'AttachmentsFacet', + Label : '{i18n>attachments}', + Target : 'attachments/@UI.LineItem' + } + ] +); + + //////////////////////////////////////////////////////////// // @@ -128,6 +232,7 @@ annotate AdminService.Books with { genre @Common.ValueListWithFixedValues; } -annotate AdminService.Books.attachments with { - customProperty1 @Common.ValueListWithFixedValues; -} +// annotate AdminService.Books.attachments with { +// customProperty1 @Common.ValueListWithFixedValues; +// } + diff --git a/cap-notebook/demoapp/app/admin-books/webapp/manifest.json b/cap-notebook/demoapp/app/admin-books/webapp/manifest.json index 3d92bc9bb..02b7b118f 100644 --- a/cap-notebook/demoapp/app/admin-books/webapp/manifest.json +++ b/cap-notebook/demoapp/app/admin-books/webapp/manifest.json @@ -83,6 +83,11 @@ "pattern": "Books({key}/author({key2}):?query:", "name": "AuthorsDetails", "target": "AuthorsDetails" + }, + { + "pattern": "Books({key})/chapters({key2}):?query:", + "name": "chaptersObjectPage", + "target": "ChaptersObjectPage" } ], "targets": { @@ -112,9 +117,9 @@ "settings": { "entitySet": "Books", "navigation": { - "Authors": { + "Chapters": { "detail": { - "route": "AuthorsDetails" + "route": "ChaptersObjectPage" } } }, @@ -126,24 +131,34 @@ "rowPress": ".extension.books.controller.custom.onRowPress" } }, - "references/@com.sap.vocabularies.UI.v1.LineItem": { + "footnotes/@com.sap.vocabularies.UI.v1.LineItem": { "tableSettings": { "type": "ResponsiveTable", "selectionMode": "Auto", "rowPress": ".extension.books.controller.custom.onRowPress" } }, - "footnotes/@com.sap.vocabularies.UI.v1.LineItem": { + "chapters/@com.sap.vocabularies.UI.v1.LineItem#i18nChapters": { "tableSettings": { - "type": "ResponsiveTable", - "selectionMode": "Auto", - "rowPress": ".extension.books.controller.custom.onRowPress" + "type": "ResponsiveTable" } } } } } }, + "ChaptersObjectPage": { + "type": "Component", + "id": "ChaptersObjectPage", + "name": "sap.fe.templates.ObjectPage", + "options": { + "settings": { + "editableHeaderContent": false, + "entitySet": "Chapters", + "navigation": {} + } + } + }, "AuthorsDetails": { "type": "Component", "id": "AuthorsDetailsList", diff --git a/cap-notebook/demoapp/app/common.cds b/cap-notebook/demoapp/app/common.cds index 515445386..cc60aff2d 100644 --- a/cap-notebook/demoapp/app/common.cds +++ b/cap-notebook/demoapp/app/common.cds @@ -79,7 +79,7 @@ annotate my.Books.attachments with @UI: { $Type : 'UI.DataFieldForActionGroup', ID : 'TableActionGroup', Label : 'Create', - ![@UI.Hidden]: {$edmJson: {$Eq: [ {$Path: 'IsActiveEntity'}, true ]}}, + ![@UI.Hidden]: {$edmJson: {$Eq: [ {$Path: 'IsActiveEntity'}, 'true' ]}}, Actions: [ { $Type : 'UI.DataFieldForAction', @@ -89,26 +89,35 @@ annotate my.Books.attachments with @UI: { ] }, { - @UI.Hidden: {$edmJson: { - $If: [ - { $Eq: [ { $Path: 'IsActiveEntity' }, true ] }, - true, - { - $If: [ - { $Ne: [ { $Path: 'mimeType' }, 'application/internet-shortcut' ] }, - true, - false - ] - } - ] - } - }, + @UI.Disabled: {$edmJson: { + $If: [ + { $Eq: [ { $Path: 'IsActiveEntity' }, true ] }, + true, + { + $If: [ + { $Ne: [ { $Path: 'mimeType' }, 'application/internet-shortcut' ] }, + true, + false + ] + } + ] + } +}, $Type : 'UI.DataFieldForAction', Label : 'Edit Link', Action: 'AdminService.editLink', Inline: true, IconUrl: 'sap-icon://edit', - @HTML5.CssDefaults: {width: '4%'} + @HTML5.CssDefaults: {width: '4%'}, + @UI.ButtonType : #Tertiary + }, + { + $Type : 'UI.DataFieldForAction', + Label : 'Changelog', + Action: 'AdminService.createLink', + Inline: true, + IconUrl: 'sap-icon://activities', + @HTML5.CssDefaults: {width: '4%'} } ], } @@ -131,7 +140,84 @@ annotate Attachments with @Common: {SideEffects #ContentChanged: { TargetEntities : [Books.attachments] }}{}; -annotate my.Books.references with @UI: { +// annotate my.Books.references with @UI: { +// HeaderInfo: { +// $Type : 'UI.HeaderInfoType', +// TypeName : '{i18n>Attachment}', +// TypeNamePlural: '{i18n>Attachments}', +// }, +// LineItem : [ +// {Value: type, @HTML5.CssDefaults: {width: '10%'}}, +// {Value: fileName, @HTML5.CssDefaults: {width: '25%'}}, +// {Value: content, @HTML5.CssDefaults: {width: '0%'}}, +// {Value: createdAt, @HTML5.CssDefaults: {width: '20%'}}, +// {Value: createdBy, @HTML5.CssDefaults: {width: '20%'}}, +// {Value: note, @HTML5.CssDefaults: {width: '25%'}}, +// { +// $Type : 'UI.DataFieldForAction', +// Label : 'Copy Attachments', +// Action: 'AdminService.copyAttachments', +// }, +// { +// $Type : 'UI.DataFieldForActionGroup', +// ID : 'TableActionGroup', +// Label : 'Create', +// ![@UI.Hidden]: {$edmJson: {$Eq: [ {$Path: 'IsActiveEntity'}, 'true' ]}}, +// Actions: [ +// { +// $Type : 'UI.DataFieldForAction', +// Label : 'Link', +// Action: 'AdminService.createLink' +// } +// ] +// }, +// { +// @UI.Disabled: {$edmJson: { +// $If: [ +// { $Eq: [ { $Path: 'IsActiveEntity' }, true ] }, +// true, +// { +// $If: [ +// { $Ne: [ { $Path: 'mimeType' }, 'application/internet-shortcut' ] }, +// true, +// false +// ] +// } +// ] +// } +// }, +// $Type : 'UI.DataFieldForAction', +// Label : 'Edit Link', +// Action: 'AdminService.editLink', +// Inline: true, +// IconUrl: 'sap-icon://edit', +// @HTML5.CssDefaults: {width: '4%'} +// }, +// { +// $Type : 'UI.DataFieldForAction', +// Label : 'Changelog', +// Action: 'AdminService.createLink', +// Inline: true, +// IconUrl: 'sap-icon://activities', +// @HTML5.CssDefaults: {width: '4%'} +// } +// ], +// } +// { +// note @(title: '{i18n>Note}'); +// fileName @(title: '{i18n>Filename}'); +// modifiedAt @(odata.etag: null); +// content +// @Core.ContentDisposition: { Filename: fileName } +// @(title: '{i18n>Attachment}'); +// folderId @UI.Hidden; +// repositoryId @UI.Hidden ; +// objectId @UI.Hidden ; +// mimeType @UI.Hidden; +// status @UI.Hidden; +// } + +annotate my.Books.footnotes with @UI: { HeaderInfo: { $Type : 'UI.HeaderInfoType', TypeName : '{i18n>Attachment}', @@ -153,7 +239,7 @@ annotate my.Books.references with @UI: { $Type : 'UI.DataFieldForActionGroup', ID : 'TableActionGroup', Label : 'Create', - ![@UI.Hidden]: {$edmJson: {$Eq: [ {$Path: 'IsActiveEntity'}, true ]}}, + ![@UI.Hidden]: {$edmJson: {$Eq: [ {$Path: 'IsActiveEntity'}, 'true' ]}}, Actions: [ { $Type : 'UI.DataFieldForAction', @@ -163,26 +249,34 @@ annotate my.Books.references with @UI: { ] }, { - @UI.Hidden: {$edmJson: { - $If: [ - { $Eq: [ { $Path: 'IsActiveEntity' }, true ] }, - true, - { - $If: [ - { $Ne: [ { $Path: 'mimeType' }, 'application/internet-shortcut' ] }, - true, - false - ] - } - ] - } - }, + @UI.Disabled: {$edmJson: { + $If: [ + { $Eq: [ { $Path: 'IsActiveEntity' }, true ] }, + true, + { + $If: [ + { $Ne: [ { $Path: 'mimeType' }, 'application/internet-shortcut' ] }, + true, + false + ] + } + ] + } +}, $Type : 'UI.DataFieldForAction', Label : 'Edit Link', Action: 'AdminService.editLink', Inline: true, IconUrl: 'sap-icon://edit', - @HTML5.CssDefaults: {width: '4%'} + @HTML5.CssDefaults: {width: '4%'} + }, + { + $Type : 'UI.DataFieldForAction', + Label : 'Changelog', + Action: 'AdminService.createLink', + Inline: true, + IconUrl: 'sap-icon://activities', + @HTML5.CssDefaults: {width: '4%'} } ], } @@ -200,74 +294,6 @@ annotate my.Books.references with @UI: { status @UI.Hidden; } -annotate my.Books.footnotes with @UI: { - HeaderInfo: { - $Type : 'UI.HeaderInfoType', - TypeName : '{i18n>Attachment}', - TypeNamePlural: '{i18n>Attachments}', - }, - LineItem : [ - {Value: type, @HTML5.CssDefaults: {width: '10%'}}, - {Value: fileName, @HTML5.CssDefaults: {width: '25%'}}, - {Value: content, @HTML5.CssDefaults: {width: '0%'}}, - {Value: createdAt, @HTML5.CssDefaults: {width: '20%'}}, - {Value: createdBy, @HTML5.CssDefaults: {width: '20%'}}, - {Value: note, @HTML5.CssDefaults: {width: '25%'}}, - { - $Type : 'UI.DataFieldForAction', - Label : 'Copy Attachments', - Action: 'AdminService.copyAttachments', - }, - { - $Type : 'UI.DataFieldForActionGroup', - ID : 'TableActionGroup', - Label : 'Create', - ![@UI.Hidden]: {$edmJson: {$Eq: [ {$Path: 'IsActiveEntity'}, true ]}}, - Actions: [ - { - $Type : 'UI.DataFieldForAction', - Label : 'Link', - Action: 'AdminService.createLink' - } - ] - }, - { - @UI.Hidden: {$edmJson: { - $If: [ - { $Eq: [ { $Path: 'IsActiveEntity' }, true ] }, - true, - { - $If: [ - { $Ne: [ { $Path: 'mimeType' }, 'application/internet-shortcut' ] }, - true, - false - ] - } - ] - } - }, - $Type : 'UI.DataFieldForAction', - Label : 'Edit Link', - Action: 'AdminService.editLink', - Inline: true, - IconUrl: 'sap-icon://edit', - @HTML5.CssDefaults: {width: '4%'} - } - ], -} { - note @(title: '{i18n>Note}'); - fileName @(title: '{i18n>Filename}'); - modifiedAt @(odata.etag: null); - content - @Core.ContentDisposition: { Filename: fileName } - @(title: '{i18n>Attachment}'); - folderId @UI.Hidden; - repositoryId @UI.Hidden ; - objectId @UI.Hidden ; - mimeType @UI.Hidden; - status @UI.Hidden; -} - //////////////////////////////////////////////////////////////////////////// // // Books Elements diff --git a/cap-notebook/demoapp/db/schema.cds b/cap-notebook/demoapp/db/schema.cds index aed7d8725..fb0f5953b 100644 --- a/cap-notebook/demoapp/db/schema.cds +++ b/cap-notebook/demoapp/db/schema.cds @@ -1,58 +1,72 @@ using { - Currency, - managed, - cuid, - sap.common.CodeList +Currency, +managed, +cuid, +sap.common.CodeList } from '@sap/cds/common'; namespace sap.capire.bookshop; entity Books : managed, cuid { - @mandatory title : localized String(111); - descr : localized String(1111); - @mandatory author : Association to Authors; - genre : Association to Genres; - stock : Integer; - price : Decimal; - currency : Currency; - image : LargeBinary @Core.MediaType: 'image/png'; +@mandatory title : localized String(111); +descr : localized String(1111); +@mandatory author : Association to Authors; +genre : Association to Genres; +stock : Integer; +price : Decimal; +currency : Currency; +image : LargeBinary @Core.MediaType: 'image/png'; + +// top-level chapters composition (root of the nested hierarchy) +chapters : Composition of many Chapters on chapters.book = $self; + +// keep any other fields as before } entity Authors : managed, cuid { - @mandatory name : String(111); - dateOfBirth : Date; - dateOfDeath : Date; - placeOfBirth : String; - placeOfDeath : String; - books : Association to many Books - on books.author = $self; +@mandatory name : String(111); +dateOfBirth : Date; +dateOfDeath : Date; +placeOfBirth : String; +placeOfDeath : String; +books : Association to many Books +on books.author = $self; } /** Hierarchically organized Code List for Genres */ entity Genres : CodeList { - key ID : Integer; - parent : Association to Genres; - children : Composition of many Genres - on children.parent = $self; +key ID : Integer; +parent : Association to Genres; +children : Composition of many Genres +on children.parent = $self; } -/** Adding {Notebooks,Writers} for user service */ -entity Notebooks : managed, cuid { - @mandatory title : localized String(111); - descr : localized String(1111); - @mandatory writer : Association to Writers; - stock : Integer; - price : Decimal; - currency : Currency; - image : LargeBinary @Core.MediaType: 'image/png'; +// --- Nested composition entities to emulate deep structure --- + +// entity Chapters : cuid, managed { +// title : String(255); + +// // backlink to parent Book +// book : Association to Books; + +// // each chapter has many sections +// sections : Composition of many Sections on sections.chapter = $self; +// } + +entity Sections : cuid, managed { +title : String(255); + +// backlink to parent chapter +chapter : Association to Chapters; + +// attachments will be added via attachments-extension.cds so we don't create a hard dependency on SDM in the core schema +// attachments : Composition of many sap.attachments.Attachments; // added by extension } -entity Writers : managed, cuid { - @mandatory name : String(111); - dateOfBirth : Date; - dateOfDeath : Date; - placeOfBirth : String; - placeOfDeath : String; - notebooks : Association to many Notebooks - on notebooks.writer = $self; +entity Chapters : cuid, managed { + book : Association to Books; + title : String @title: 'Chapter Title'; + description : String; + url : String; + chapterType : String @title: 'Chapter Type'; } \ No newline at end of file diff --git a/cap-notebook/demoapp/srv/admin-service.cds b/cap-notebook/demoapp/srv/admin-service.cds index eaa6b25b0..04ff97792 100644 --- a/cap-notebook/demoapp/srv/admin-service.cds +++ b/cap-notebook/demoapp/srv/admin-service.cds @@ -1,60 +1,26 @@ -using {sap.capire.bookshop as my} from '../db/schema'; +using { sap.capire.bookshop as my } from '../db/schema'; + +service AdminService @(requires: 'admin') { -service AdminService @(requires: ['admin','system-user']) { entity Books as projection on my.Books; entity Authors as projection on my.Authors; - entity Books.attachments as projection on my.Books.attachments - actions { - @(Common.SideEffects : {TargetEntities: ['']},) - action copyAttachments(in:many $self, up__ID:String, objectIds:String); - - @(Common.SideEffects : {TargetEntities: ['']},) - action createLink( - in:many $self, - @mandatory @Common.Label:'Name' name: String @UI.Placeholder: 'Enter a name for the link', - @mandatory @assert.format:'^(https?:\/\/)(([a-zA-Z0-9\-]+\.)+[a-zA-Z]{2,}|localhost)(:\d{2,5})?(\/[^\s]*)?$' @Common.Label:'URL' url: String @UI.Placeholder: 'Example: https://www.example.com' - ); - - action editLink( - @mandatory @assert.format:'^(https?:\/\/)(([a-zA-Z0-9\-]+\.)+[a-zA-Z]{2,}|localhost)(:\d{2,5})?(\/[^\s]*)?$' @Common.Label:'URL' url: String @UI.Placeholder: 'Example: https://www.example.com' - ); - action openAttachment() returns String; - } + entity Chapters as projection on my.Chapters; - entity Books.references as projection on my.Books.references - actions { - @(Common.SideEffects : {TargetEntities: ['']},) - action copyAttachments(in:many $self, up__ID:String, objectIds:String); + entity Books.attachments as projection on my.Books.attachments + actions { + // Table-level actions + @(Common.SideEffects : { TargetEntities: [''] }) + action copyAttachments(in: many $self, up__ID: String, objectIds: String); - @(Common.SideEffects : {TargetEntities: ['']},) + @(Common.SideEffects : { TargetEntities: [''] }) action createLink( - in:many $self, - @mandatory @Common.Label:'Name' name: String @UI.Placeholder: 'Enter a name for the link', - @mandatory @assert.format:'^(https?:\/\/)(([a-zA-Z0-9\-]+\.)+[a-zA-Z]{2,}|localhost)(:\d{2,5})?(\/[^\s]*)?$' @Common.Label:'URL' url: String @UI.Placeholder: 'Example: https://www.example.com' - ); - - action editLink( - @mandatory @assert.format:'^(https?:\/\/)(([a-zA-Z0-9\-]+\.)+[a-zA-Z]{2,}|localhost)(:\d{2,5})?(\/[^\s]*)?$' @Common.Label:'URL' url: String @UI.Placeholder: 'Example: https://www.example.com' - ); - action openAttachment() returns String; - } - - entity Books.footnotes as projection on my.Books.footnotes - actions { - @(Common.SideEffects : {TargetEntities: ['']},) - action copyAttachments(in:many $self, up__ID:String, objectIds:String); + in: many $self, + @mandatory @assert.unique @placeholder: 'Enter name' name: String, + @mandatory @placeholder: 'Enter URL' url: String + ); - @(Common.SideEffects : {TargetEntities: ['']},) - action createLink( - in:many $self, - @mandatory @Common.Label:'Name' name: String @UI.Placeholder: 'Enter a name for the link', - @mandatory @assert.format:'^(https?:\/\/)(([a-zA-Z0-9\-]+\.)+[a-zA-Z]{2,}|localhost)(:\d{2,5})?(\/[^\s]*)?$' @Common.Label:'URL' url: String @UI.Placeholder: 'Example: https://www.example.com' - ); - - action editLink( - @mandatory @assert.format:'^(https?:\/\/)(([a-zA-Z0-9\-]+\.)+[a-zA-Z]{2,}|localhost)(:\d{2,5})?(\/[^\s]*)?$' @Common.Label:'URL' url: String @UI.Placeholder: 'Example: https://www.example.com' - ); + // Row-level actions + action editLink(in: $self, url: String); action openAttachment() returns String; - } + }; } - diff --git a/cap-notebook/demoapp/srv/attachment-extension.cds b/cap-notebook/demoapp/srv/attachment-extension.cds index b0ad504e6..ea1cce275 100644 --- a/cap-notebook/demoapp/srv/attachment-extension.cds +++ b/cap-notebook/demoapp/srv/attachment-extension.cds @@ -1,65 +1,50 @@ -using {sap.capire.bookshop.Books, sap.capire.bookshop.Notebooks} from '../db/schema'; +using {sap.capire.bookshop.Books, sap.capire.bookshop.Chapters} from '../db/schema'; using {sap.attachments.Attachments, sap.attachments.StatusCode} from`com.sap.cds/sdm`; using {sap,managed,sap.common.CodeList} from '@sap/cds/common'; +// keep the original shallow attachments on Books extend entity Books with { - attachments : Composition of many Attachments @SDM.Attachments:{maxCount: 4, maxCountError:'Only 4 attachments allowed.'}; - references : Composition of many Attachments @SDM.Attachments:{maxCount: 5, maxCountError:'Only 5 attachments allowed.'}; - footnotes : Composition of many Attachments; + attachments : Composition of many Attachments; + //references: Composition of many Attachments; + footnotes: Composition of many Attachments; } -extend entity Notebooks with { - attachments : Composition of many Attachments @SDM.Attachments:{maxCount: 4, maxCountError:'Only 4 attachments allowed.'}; + +// Add attachments to Sections +extend entity sap.capire.bookshop.Sections with { + attachments : Composition of many Attachments; + //references: Composition of many Attachments; + footnotes: Composition of many Attachments; } + +extend entity Chapters with { attachments: Composition of many Attachments } + entity Statuses @cds.autoexpose @readonly { - key code : StatusCode; - text : localized String(255); + key code : StatusCode; + text : localized String(255); } extend Attachments with { - statusText : Association to Statuses on statusText.code = $self.status; - customProperty1 : WDIRS_CodeList_TYPE - @SDM.Attachments.AdditionalProperty: { - name: 'Working:DocumentInfoRecordString' - } - @(title: 'DocumentInfoRecordString'); - customProperty2 : Integer - @SDM.Attachments.AdditionalProperty: { - name: 'Working:DocumentInfoRecordInt' - }; - customProperty3 : String - @SDM.Attachments.AdditionalProperty: { - name: 'abc:myId1' - } - @(title: 'id1'); - customProperty4 : String - @SDM.Attachments.AdditionalProperty: { - name: 'abc:myId2' - } - @(title: 'id2'); - customProperty5 : DateTime - @SDM.Attachments.AdditionalProperty: { - name: 'Working:DocumentInfoRecordDate' - } - @(title: 'DocumentInfoRecordDate'); - customProperty6 : Boolean - @SDM.Attachments.AdditionalProperty: { - name: 'Working:DocumentInfoRecordBoolean' - } - @(title: 'DocumentInfoRecordBoolean'); + statusText : Association to Statuses on statusText.code = $self.status; } -entity WDIRSCodeList : CodeList { - key code : String(30) @Common.Text : name @Common.TextArrangement: #TextFirst; -}; - -type WDIRS_CodeList_TYPE : Association to one WDIRSCodeList; - annotate Books.attachments with { - status @( - Common.Text: { - $value: ![statusText.text], - ![@UI.TextArrangement]: #TextOnly - }, - ValueList: {entity:'Statuses'} - ); + status @( + Common.Text: { + $value: ![statusText.text], + ![@UI.TextArrangement]: #TextOnly + }, + ValueList: { entity: 'Statuses' }, + sap.value.list: 'fixed-values' + ); +} + +annotate sap.capire.bookshop.Sections.attachments with { + status @( + Common.Text: { + $value: ![statusText.text], + ![@UI.TextArrangement]: #TextOnly + }, + ValueList: { entity: 'Statuses' }, + sap.value.list: 'fixed-values' + ); } diff --git a/cap-notebook/demoapp/srv/user-service.cds b/cap-notebook/demoapp/srv/user-service.cds index de6444756..b9052b611 100644 --- a/cap-notebook/demoapp/srv/user-service.cds +++ b/cap-notebook/demoapp/srv/user-service.cds @@ -1,10 +1,10 @@ -using {sap.capire.bookshop as my} from '../db/schema'; +// using {sap.capire.bookshop as my} from '../db/schema'; -service UserService @(requires: [ - 'admin', - 'system-user' -]) { - @odata.draft.enabled - entity Notebooks as projection on my.Notebooks; - entity Writers as projection on my.Writers; -} +// service UserService @(requires: [ +// 'admin', +// 'system-user' +// ]) { +// @odata.draft.enabled +// entity Notebooks as projection on my.Notebooks; +// entity Writers as projection on my.Writers; +// } From 60757c53bd0baff8a873b213cd0e3d5820265bc8 Mon Sep 17 00:00:00 2001 From: Rishi Kunnath <82925475+rishikunnath2747@users.noreply.github.com> Date: Tue, 7 Oct 2025 13:00:32 +0530 Subject: [PATCH 2/8] init --- .../demoapp/app/_i18n/i18n.properties | 17 + .../demoapp/app/_i18n/i18n_de.properties | 38 +- .../demoapp/app/admin-books/fiori-service.cds | 194 +- .../app/admin-books/webapp/manifest.json | 42 +- cap-notebook/demoapp/app/common.cds | 231 ++ cap-notebook/demoapp/app/package-lock.json | 2414 +++++++++++++++++ cap-notebook/demoapp/db/schema.cds | 24 +- cap-notebook/demoapp/srv/admin-service.cds | 121 + .../demoapp/srv/attachment-extension.cds | 179 +- 9 files changed, 3230 insertions(+), 30 deletions(-) create mode 100644 cap-notebook/demoapp/app/package-lock.json diff --git a/cap-notebook/demoapp/app/_i18n/i18n.properties b/cap-notebook/demoapp/app/_i18n/i18n.properties index b6e53f774..1191e2e0d 100644 --- a/cap-notebook/demoapp/app/_i18n/i18n.properties +++ b/cap-notebook/demoapp/app/_i18n/i18n.properties @@ -21,6 +21,8 @@ attachment_status = Status attachment_note = Note attachment = Attachment attachments = Attachments +reference = Reference +references = References #XFLD,50: Label for a section Chapters=Chapters @@ -33,6 +35,21 @@ ChapterTitle=Chapter Title #XFLD,120: Label for a field ChapterType=Chapter Type + +#XFLD,50: Label for a section +Pages=Pages + +#XFLD,120: Label for entity +Page=Page + +#XFLD,120: Label for a field +PageTitle=Page Title + +#XFLD,120: Label for a field +PageType=Page Type + +#XFLD,50: Label for a section +Footnotes=Footnotes #XFLD,120: Label for a field Description=Description diff --git a/cap-notebook/demoapp/app/_i18n/i18n_de.properties b/cap-notebook/demoapp/app/_i18n/i18n_de.properties index cb712c12c..7046fa3e8 100644 --- a/cap-notebook/demoapp/app/_i18n/i18n_de.properties +++ b/cap-notebook/demoapp/app/_i18n/i18n_de.properties @@ -12,4 +12,40 @@ Stock = Bestand Order = Bestellung Orders = Bestellungen Price = Preis -Genre = Genre \ No newline at end of file +Genre = Genre + +#XFLD,50: Label for a section +Chapters=Kapitel + +#XFLD,120: Label for entity +Chapter=Kapitel + +#XFLD,120: Label for a field +ChapterTitle=Kapitel Titel + +#XFLD,120: Label for a field +ChapterType=Kapitel Typ + +#XFLD,50: Label for a section +Pages=Seiten + +#XFLD,120: Label for entity +Page=Seite + +#XFLD,120: Label for a field +PageTitle=Seiten Titel + +#XFLD,120: Label for a field +PageType=Seiten Typ + +#XFLD,50: Label for a section +Footnotes=Fußnoten + +#XFLD,120: Label for a field +Description=Beschreibung + +#XFLD,120: Label for a field +URL=URL + +#XFLD,50: Label for a section +GeneralInformation=Allgemeine Informationen \ No newline at end of file diff --git a/cap-notebook/demoapp/app/admin-books/fiori-service.cds b/cap-notebook/demoapp/app/admin-books/fiori-service.cds index 84aed7136..4f98f4cc0 100644 --- a/cap-notebook/demoapp/app/admin-books/fiori-service.cds +++ b/cap-notebook/demoapp/app/admin-books/fiori-service.cds @@ -27,6 +27,12 @@ annotate AdminService.Books with @(UI: { Label : '{i18n>attachments}', Target: 'attachments/@UI.LineItem' }, + { + $Type : 'UI.ReferenceFacet', + ID : 'ReferencesFacet', + Label : '{i18n>references}', + Target: 'references/@UI.LineItem' + }, { $Type : 'UI.ReferenceFacet', ID : 'FootnotesFacet', @@ -44,6 +50,12 @@ annotate AdminService.Books with @(UI: { ID : 'i18nChapters', Target : 'chapters/@UI.LineItem#i18nChapters', }, + { + $Type : 'UI.ReferenceFacet', + Label : '{i18n>Pages}', + ID : 'i18nPages', + Target : 'pages/@UI.LineItem#i18nPages', + }, ], FieldGroup #General: {Data: [ {Value: title}, @@ -156,7 +168,7 @@ annotate AdminService.Chapters with @( }, UI.Facets : [ { - $Type : 'UI.ChapterFacet', + $Type : 'UI.ReferenceFacet', ID : 'GeneratedFacet1', Label : '{i18n>GeneralInformation}', Target : '@UI.FieldGroup#GeneratedGroup1', @@ -166,10 +178,136 @@ annotate AdminService.Chapters with @( ID : 'AttachmentsFacet', Label : '{i18n>attachments}', Target : 'attachments/@UI.LineItem' + }, + { + $Type : 'UI.ReferenceFacet', + ID : 'ReferencesFacet', + Label : '{i18n>references}', + Target : 'references/@UI.LineItem' + }, + { + $Type : 'UI.ReferenceFacet', + ID : 'FootnotesFacet', + Label : '{i18n>Footnotes}', + Target : 'footnotes/@UI.LineItem' } ] ); +////////// + +// Pages annotations +annotate AdminService.Pages with @title : '{i18n>Page}'; + +annotate AdminService.Books.pages with @( + title : '{i18n>Pages}' +); + +annotate AdminService.Pages with @( + UI.LineItem : [ + { + $Type : 'UI.DataField', + Value : title, + Label : '{i18n>PageTitle}', + }, + { + $Type : 'UI.DataField', + Value : pageType, + Label : '{i18n>PageType}', + }, + { + $Type : 'UI.DataField', + Value : description, + Label : '{i18n>Description}', + }, + ], + UI.LineItem #i18nPages : [ + { + $Type : 'UI.DataField', + Value : title, + Label : '{i18n>PageTitle}', + }, + { + $Type : 'UI.DataField', + Value : pageType, + Label : '{i18n>PageType}', + }, + { + $Type : 'UI.DataField', + Value : description, + Label : '{i18n>Description}', + }, + ] +); + +annotate AdminService.Pages with @( + UI.HeaderInfo : { + Title : { + $Type : 'UI.DataField', + Value : title, + }, + TypeName : '{i18n>Page}', + TypeNamePlural : '{i18n>Pages}', + Description : { + $Type : 'UI.DataField', + Value : description, + }, + } +); + +annotate AdminService.Pages with @( + UI.FieldGroup #GeneratedGroup1 : { + $Type : 'UI.FieldGroupType', + Data : [ + { + $Type : 'UI.DataField', + Value : title, + Label : '{i18n>PageTitle}', + }, + { + $Type : 'UI.DataField', + Value : pageType, + Label : '{i18n>PageType}', + }, + { + $Type : 'UI.DataField', + Value : description, + Label : '{i18n>Description}', + }, + { + $Type : 'UI.DataField', + Value : url, + Label : '{i18n>URL}', + }, + ], + }, + UI.Facets : [ + { + $Type : 'UI.ReferenceFacet', + ID : 'GeneratedFacet1', + Label : '{i18n>GeneralInformation}', + Target : '@UI.FieldGroup#GeneratedGroup1', + }, + { + $Type : 'UI.ReferenceFacet', + ID : 'AttachmentsFacet', + Label : '{i18n>attachments}', + Target : 'attachments/@UI.LineItem' + }, + { + $Type : 'UI.ReferenceFacet', + ID : 'ReferencesFacet', + Label : '{i18n>references}', + Target : 'references/@UI.LineItem' + }, + { + $Type : 'UI.ReferenceFacet', + ID : 'FootnotesFacet', + Label : '{i18n>Footnotes}', + Target : 'footnotes/@UI.LineItem' + } + ] +); //////////////////////////////////////////////////////////// @@ -214,14 +352,51 @@ annotate AdminService.Books.texts { ) }; -// In addition we need to expose Languages through AdminService as a target for ValueList -using {sap} from '@sap/cds/common'; +// Workaround for Fiori popup for asking user to enter a new UUID on Create +annotate AdminService.Books with { + ID @Core.Computed; +} -extend service AdminService { - @readonly - entity Languages as projection on sap.common.Languages; +// Show Genre as drop down, not a dialog +annotate AdminService.Books with { + genre @Common.ValueListWithFixedValues; } +annotate AdminService.Books.texts with @(UI: { + Identification : [{Value: title}], + SelectionFields: [ + locale, + title + ], + LineItem : [ + { + Value: locale, + Label: 'Locale' + }, + { + Value: title, + Label: 'Title' + }, + { + Value: descr, + Label: 'Description' + }, + ] +}); + +annotate AdminService.Books.texts with { + ID @UI.Hidden; + ID_texts @UI.Hidden; +}; + +// Add Value Help for Locales +annotate AdminService.Books.texts { + locale @( + ValueList.entity: 'Languages', + Common.ValueListWithFixedValues, //show as drop down, not a dialog + ) +}; + // Workaround for Fiori popup for asking user to enter a new UUID on Create annotate AdminService.Books with { ID @Core.Computed; @@ -232,7 +407,6 @@ annotate AdminService.Books with { genre @Common.ValueListWithFixedValues; } -// annotate AdminService.Books.attachments with { -// customProperty1 @Common.ValueListWithFixedValues; -// } - +annotate AdminService.Books.attachments with { + customProperty1 @Common.ValueListWithFixedValues; +} diff --git a/cap-notebook/demoapp/app/admin-books/webapp/manifest.json b/cap-notebook/demoapp/app/admin-books/webapp/manifest.json index 02b7b118f..d4251ba12 100644 --- a/cap-notebook/demoapp/app/admin-books/webapp/manifest.json +++ b/cap-notebook/demoapp/app/admin-books/webapp/manifest.json @@ -88,6 +88,11 @@ "pattern": "Books({key})/chapters({key2}):?query:", "name": "chaptersObjectPage", "target": "ChaptersObjectPage" + }, + { + "pattern": "Books({key})/pages({key2}):?query:", + "name": "pagesObjectPage", + "target": "PagesObjectPage" } ], "targets": { @@ -121,6 +126,11 @@ "detail": { "route": "ChaptersObjectPage" } + }, + "Pages": { + "detail": { + "route": "PagesObjectPage" + } } }, "controlConfiguration": { @@ -142,7 +152,13 @@ "tableSettings": { "type": "ResponsiveTable" } + }, + "pages/@com.sap.vocabularies.UI.v1.LineItem#i18nPages": { + "tableSettings": { + "type": "ResponsiveTable" + } } + } } } @@ -154,7 +170,31 @@ "options": { "settings": { "editableHeaderContent": false, - "entitySet": "Chapters", + "entitySet": "Chapters" + + } + } + }, + "PagesObjectPage": { + "type": "Component", + "id": "PagesObjectPage", + "name": "sap.fe.templates.ObjectPage", + "options": { + "settings": { + "editableHeaderContent": false, + "entitySet": "Pages", + "navigation": {} + } + } + }, + "SectionsObjectPage": { + "type": "Component", + "id": "SectionsObjectPage", + "name": "sap.fe.templates.ObjectPage", + "options": { + "settings": { + "editableHeaderContent": false, + "entitySet": "Sections", "navigation": {} } } diff --git a/cap-notebook/demoapp/app/common.cds b/cap-notebook/demoapp/app/common.cds index cc60aff2d..11adfde3c 100644 --- a/cap-notebook/demoapp/app/common.cds +++ b/cap-notebook/demoapp/app/common.cds @@ -294,6 +294,237 @@ annotate my.Books.footnotes with @UI: { status @UI.Hidden; } +annotate my.Books.references with @UI: { + HeaderInfo: { + $Type : 'UI.HeaderInfoType', + TypeName : '{i18n>Reference}', + TypeNamePlural: '{i18n>References}', + }, + LineItem : [ + {Value: type, @HTML5.CssDefaults: {width: '10%'}}, + {Value: fileName, @HTML5.CssDefaults: {width: '25%'}}, + {Value: content, @HTML5.CssDefaults: {width: '0%'}}, + {Value: createdAt, @HTML5.CssDefaults: {width: '20%'}}, + {Value: createdBy, @HTML5.CssDefaults: {width: '20%'}}, + {Value: note, @HTML5.CssDefaults: {width: '25%'}}, + { + $Type : 'UI.DataFieldForAction', + Label : 'Copy References', + Action: 'AdminService.copyAttachments', + }, + { + $Type : 'UI.DataFieldForActionGroup', + ID : 'TableActionGroup', + Label : 'Create', + ![@UI.Hidden]: {$edmJson: {$Eq: [ {$Path: 'IsActiveEntity'}, 'true' ]}}, + Actions: [ + { + $Type : 'UI.DataFieldForAction', + Label : 'Link', + Action: 'AdminService.createLink' + } + ] + }, + { + @UI.Disabled: {$edmJson: { + $If: [ + { $Eq: [ { $Path: 'IsActiveEntity' }, true ] }, + true, + { + $If: [ + { $Ne: [ { $Path: 'mimeType' }, 'application/internet-shortcut' ] }, + true, + false + ] + } + ] + } +}, + $Type : 'UI.DataFieldForAction', + Label : 'Edit Link', + Action: 'AdminService.editLink', + Inline: true, + IconUrl: 'sap-icon://edit', + @HTML5.CssDefaults: {width: '4%'} + }, + { + $Type : 'UI.DataFieldForAction', + Label : 'Changelog', + Action: 'AdminService.createLink', + Inline: true, + IconUrl: 'sap-icon://activities', + @HTML5.CssDefaults: {width: '4%'} + } + ], +} +{ + note @(title: '{i18n>Note}'); + fileName @(title: '{i18n>Filename}'); + modifiedAt @(odata.etag: null); + content + @Core.ContentDisposition: { Filename: fileName } + @(title: '{i18n>Attachment}'); + folderId @UI.Hidden; + repositoryId @UI.Hidden ; + objectId @UI.Hidden ; + mimeType @UI.Hidden; + status @UI.Hidden; +} + +annotate my.Chapters.attachments with @UI: { + HeaderInfo: { + $Type : 'UI.HeaderInfoType', + TypeName : '{i18n>Attachment}', + TypeNamePlural: '{i18n>Attachments}', + }, + LineItem : [ + {Value: type, @HTML5.CssDefaults: {width: '10%'}}, + {Value: fileName, @HTML5.CssDefaults: {width: '25%'}}, + {Value: content, @HTML5.CssDefaults: {width: '0%'}}, + {Value: createdAt, @HTML5.CssDefaults: {width: '20%'}}, + {Value: createdBy, @HTML5.CssDefaults: {width: '20%'}}, + {Value: note, @HTML5.CssDefaults: {width: '25%'}}, + { + $Type : 'UI.DataFieldForAction', + Label : 'Copy Attachments', + Action: 'AdminService.copyAttachments', + }, + { + $Type : 'UI.DataFieldForActionGroup', + ID : 'TableActionGroup', + Label : 'Create', + ![@UI.Hidden]: {$edmJson: {$Eq: [ {$Path: 'IsActiveEntity'}, 'true' ]}}, + Actions: [ + { + $Type : 'UI.DataFieldForAction', + Label : 'Link', + Action: 'AdminService.createLink' + } + ] + }, + { + @UI.Disabled: {$edmJson: { + $If: [ + { $Eq: [ { $Path: 'IsActiveEntity' }, true ] }, + true, + { + $If: [ + { $Ne: [ { $Path: 'mimeType' }, 'application/internet-shortcut' ] }, + true, + false + ] + } + ] + } +}, + $Type : 'UI.DataFieldForAction', + Label : 'Edit Link', + Action: 'AdminService.editLink', + Inline: true, + IconUrl: 'sap-icon://edit', + @HTML5.CssDefaults: {width: '4%'} + }, + { + $Type : 'UI.DataFieldForAction', + Label : 'Changelog', + Action: 'AdminService.createLink', + Inline: true, + IconUrl: 'sap-icon://activities', + @HTML5.CssDefaults: {width: '4%'} + } + ], +} +{ + note @(title: '{i18n>Note}'); + fileName @(title: '{i18n>Filename}'); + modifiedAt @(odata.etag: null); + content + @Core.ContentDisposition: { Filename: fileName } + @(title: '{i18n>Attachment}'); + folderId @UI.Hidden; + repositoryId @UI.Hidden ; + objectId @UI.Hidden ; + mimeType @UI.Hidden; + status @UI.Hidden; +} + +annotate my.Chapters.references with @UI: { + HeaderInfo: { + $Type : 'UI.HeaderInfoType', + TypeName : '{i18n>Reference}', + TypeNamePlural: '{i18n>References}', + }, + LineItem : [ + {Value: type, @HTML5.CssDefaults: {width: '10%'}}, + {Value: fileName, @HTML5.CssDefaults: {width: '25%'}}, + {Value: content, @HTML5.CssDefaults: {width: '0%'}}, + {Value: createdAt, @HTML5.CssDefaults: {width: '20%'}}, + {Value: createdBy, @HTML5.CssDefaults: {width: '20%'}}, + {Value: note, @HTML5.CssDefaults: {width: '25%'}}, + { + $Type : 'UI.DataFieldForAction', + Label : 'Copy References', + Action: 'AdminService.copyAttachments', + }, + { + $Type : 'UI.DataFieldForActionGroup', + ID : 'TableActionGroup', + Label : 'Create', + ![@UI.Hidden]: {$edmJson: {$Eq: [ {$Path: 'IsActiveEntity'}, 'true' ]}}, + Actions: [ + { + $Type : 'UI.DataFieldForAction', + Label : 'Link', + Action: 'AdminService.createLink' + } + ] + }, + { + @UI.Disabled: {$edmJson: { + $If: [ + { $Eq: [ { $Path: 'IsActiveEntity' }, true ] }, + true, + { + $If: [ + { $Ne: [ { $Path: 'mimeType' }, 'application/internet-shortcut' ] }, + true, + false + ] + } + ] + } +}, + $Type : 'UI.DataFieldForAction', + Label : 'Edit Link', + Action: 'AdminService.editLink', + Inline: true, + IconUrl: 'sap-icon://edit', + @HTML5.CssDefaults: {width: '4%'} + }, + { + $Type : 'UI.DataFieldForAction', + Label : 'Changelog', + Action: 'AdminService.createLink', + Inline: true, + IconUrl: 'sap-icon://activities', + @HTML5.CssDefaults: {width: '4%'} + } + ], +} +{ + note @(title: '{i18n>Note}'); + fileName @(title: '{i18n>Filename}'); + modifiedAt @(odata.etag: null); + content + @Core.ContentDisposition: { Filename: fileName } + @(title: '{i18n>Attachment}'); + folderId @UI.Hidden; + repositoryId @UI.Hidden ; + objectId @UI.Hidden ; + mimeType @UI.Hidden; + status @UI.Hidden; +} + //////////////////////////////////////////////////////////////////////////// // // Books Elements diff --git a/cap-notebook/demoapp/app/package-lock.json b/cap-notebook/demoapp/app/package-lock.json new file mode 100644 index 000000000..d8b2ef349 --- /dev/null +++ b/cap-notebook/demoapp/app/package-lock.json @@ -0,0 +1,2414 @@ +{ + "name": "approuter", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "approuter", + "dependencies": { + "@sap/approuter": "16.8.2" + } + }, + "node_modules/@colors/colors": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.6.0.tgz", + "integrity": "sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==", + "license": "MIT", + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/@sap/approuter": { + "version": "16.8.2", + "resolved": "https://registry.npmjs.org/@sap/approuter/-/approuter-16.8.2.tgz", + "integrity": "sha512-jIj0b5EzrDnaPpYKJ/dFYSK22oZTJRafHeRk2YFEVxIKwr4kjAlDnKEn8PCwE/9pit0Ky8lXisBjale05Y3p3g==", + "license": "SEE LICENSE IN LICENSE", + "dependencies": { + "@sap/audit-logging": "6.1.0", + "@sap/e2e-trace": "4.1.0", + "@sap/logging": "^7.1.0", + "@sap/xsenv": "^4.0.0", + "@sap/xssec": "3.6.1", + "agentkeepalive": "2.0.5", + "axios": "1.7.4", + "axios-cookiejar-support": "2.0.3", + "base64-url": "2.3.3", + "basic-auth": "1.0.3", + "body-parser": "1.20.3", + "cf-nodejs-logging-support": "^7.2.0", + "commander": "2.9.0", + "compressible": "2.0.18", + "compression": "1.7.4", + "connect": "3.6.5", + "cookie": "0.2.2", + "cookie-parser": "1.4.6", + "cookie-signature": "1.1.0", + "debug": "4.3.2", + "deepmerge": "2.1.1", + "encodeurl": "1.0.2", + "express-session": "1.17.0", + "http-proxy-agent": "4.0.1", + "https-proxy-agent": "5.0.0", + "ioredis": "4.28.5", + "jwt-decode": "2.0.1", + "lodash": "4.17.21", + "lru-cache": "4.0.0", + "mime": "1.4.1", + "ms": "2.1.1", + "mustache": "2.2.1", + "node-cache": "4.1.1", + "node-forge": "^1.3.0", + "passport": "^0.6.0", + "query-string": "7.1.2", + "request-stats": "2.0.1", + "safe-regex": "1.1.0", + "send": "0.19.0", + "serve-static": "1.16.2", + "tough-cookie": "4.1.3", + "tv4": "1.2.7", + "uid-safe": "2.1.5", + "urijs": "^1.19.11", + "uuid": "8.3.2", + "validator": "13.7.0", + "verror": "1.10.0", + "ws": "7.5.10", + "wtfnode": "0.9.1" + }, + "engines": { + "node": "^18.0.0 || ^20.0.0" + } + }, + "node_modules/@sap/audit-logging": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@sap/audit-logging/-/audit-logging-6.1.0.tgz", + "integrity": "sha512-NmKBjWTawJW0GjUnt0SNnQ9h+yj15fYrZ66SI1lE5lwR0ard8AgzbMwTnoq6jHrTSKvTHeOEhPYeUHAdb8llYA==", + "license": "SEE LICENSE IN LICENSE file", + "dependencies": { + "@sap/xssec": "^3.6.1", + "debug": "4.3.4", + "fetch-retry": "4.1.0", + "lodash": "4.17.21", + "node-cache": "5.1.2", + "node-fetch": "2.7.0" + }, + "engines": { + "node": "^18.0.0 || ^20.0.0" + } + }, + "node_modules/@sap/audit-logging/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "license": "MIT", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@sap/audit-logging/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "license": "MIT" + }, + "node_modules/@sap/audit-logging/node_modules/node-cache": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/node-cache/-/node-cache-5.1.2.tgz", + "integrity": "sha512-t1QzWwnk4sjLWaQAS8CHgOJ+RAfmHpxFWmc36IWTiWHQfs0w5JDMBS1b1ZxQteo0vVVuWJvIUKHDkkeK7vIGCg==", + "license": "MIT", + "dependencies": { + "clone": "2.x" + }, + "engines": { + "node": ">= 8.0.0" + } + }, + "node_modules/@sap/e2e-trace": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@sap/e2e-trace/-/e2e-trace-4.1.0.tgz", + "integrity": "sha512-HSOIPHQjdC2coWFVxB04DztApRUgYiMIV781FfyYpmvnJy7/BUCv5fdLyJjisoIUqBpDE3KbkJ/Ko1GdoryHlw==", + "hasShrinkwrap": true, + "license": "SEE LICENSE IN LICENSE file", + "dependencies": { + "request-stats": "3.0.0" + }, + "engines": { + "node": "^12.0.0 || ^14.0.0 || ^16.0.0 || ^18.0.0 || ^20.0.0" + } + }, + "node_modules/@sap/e2e-trace/node_modules/http-headers": { + "version": "3.0.2", + "dependencies": { + "next-line": "^1.1.0" + } + }, + "node_modules/@sap/e2e-trace/node_modules/next-line": { + "version": "1.1.0" + }, + "node_modules/@sap/e2e-trace/node_modules/once": { + "version": "1.4.0", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/@sap/e2e-trace/node_modules/request-stats": { + "version": "3.0.0", + "dependencies": { + "http-headers": "^3.0.1", + "once": "^1.4.0" + } + }, + "node_modules/@sap/e2e-trace/node_modules/wrappy": { + "version": "1.0.2" + }, + "node_modules/@sap/logging": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@sap/logging/-/logging-7.1.0.tgz", + "integrity": "sha512-pMYHJg23099j/nW90md0X8Ach0mfkdFy8235LOWXBlcH7eNPuIb5ES6slisqinQ6PHsj1Cip5C2emyGlkd/liw==", + "hasShrinkwrap": true, + "license": "SEE LICENSE IN LICENSE file", + "dependencies": { + "@sap/e2e-trace": "^4.1.0", + "lodash": "4.17.21", + "moment": "2.29.4" + }, + "engines": { + "node": "^12.0.0 || ^14.0.0 || ^16.0.0 || ^18.0.0 || ^20.0.0" + } + }, + "node_modules/@sap/logging/node_modules/@sap/e2e-trace": { + "version": "4.1.0", + "dependencies": { + "request-stats": "3.0.0" + } + }, + "node_modules/@sap/logging/node_modules/@sap/e2e-trace/node_modules/http-headers": { + "version": "3.0.2", + "dependencies": { + "next-line": "^1.1.0" + } + }, + "node_modules/@sap/logging/node_modules/@sap/e2e-trace/node_modules/next-line": { + "version": "1.1.0" + }, + "node_modules/@sap/logging/node_modules/@sap/e2e-trace/node_modules/once": { + "version": "1.4.0", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/@sap/logging/node_modules/@sap/e2e-trace/node_modules/request-stats": { + "version": "3.0.0", + "dependencies": { + "http-headers": "^3.0.1", + "once": "^1.4.0" + } + }, + "node_modules/@sap/logging/node_modules/@sap/e2e-trace/node_modules/wrappy": { + "version": "1.0.2" + }, + "node_modules/@sap/logging/node_modules/lodash": { + "version": "4.17.21" + }, + "node_modules/@sap/logging/node_modules/moment": { + "version": "2.29.4" + }, + "node_modules/@sap/xsenv": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@sap/xsenv/-/xsenv-4.2.0.tgz", + "integrity": "sha512-Hu74ezPEKVgzz1XLi4/Ttlv+n2w9CTuLBlR6Vw4y9FK7btLm1wnCViDPufTG7yxniEADw8EQbqRv+krmcFmGLA==", + "hasShrinkwrap": true, + "license": "SEE LICENSE IN LICENSE file", + "dependencies": { + "debug": "4.3.3", + "node-cache": "^5.1.0", + "verror": "1.10.0" + }, + "engines": { + "node": "^12.0.0 || ^14.0.0 || ^16.0.0 || ^18.0.0 || ^20.0.0" + } + }, + "node_modules/@sap/xsenv/node_modules/assert-plus": { + "version": "1.0.0" + }, + "node_modules/@sap/xsenv/node_modules/clone": { + "version": "2.1.2" + }, + "node_modules/@sap/xsenv/node_modules/core-util-is": { + "version": "1.0.2" + }, + "node_modules/@sap/xsenv/node_modules/debug": { + "version": "4.3.3", + "dependencies": { + "ms": "2.1.2" + } + }, + "node_modules/@sap/xsenv/node_modules/extsprintf": { + "version": "1.4.1" + }, + "node_modules/@sap/xsenv/node_modules/ms": { + "version": "2.1.2" + }, + "node_modules/@sap/xsenv/node_modules/node-cache": { + "version": "5.1.2", + "dependencies": { + "clone": "2.x" + } + }, + "node_modules/@sap/xsenv/node_modules/verror": { + "version": "1.10.0", + "dependencies": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "node_modules/@sap/xssec": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/@sap/xssec/-/xssec-3.6.1.tgz", + "integrity": "sha512-OJouwIWClefpsJ8rVCziEydeDHDNOMA4hjsjw9OqolbbObaiYMMDRU0YJbPe7XL5JkLgrtt+CLCBCsNERxcCZg==", + "license": "SAP DEVELOPER LICENSE AGREEMENT", + "dependencies": { + "axios": "^1.6", + "debug": "^4.3.4", + "jsonwebtoken": "^9.0.2", + "node-rsa": "^1.1.1" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@sap/xssec/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@sap/xssec/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/@tootallnate/once": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", + "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/@types/triple-beam": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/triple-beam/-/triple-beam-1.3.5.tgz", + "integrity": "sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw==", + "license": "MIT" + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "license": "MIT", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "license": "MIT", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/agentkeepalive": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-2.0.5.tgz", + "integrity": "sha512-dlXxjfkCrcEPmvJju6ypP6/eq1q0l+cu0u10IhKfiwMoy4yH73n0TQ2jMO2H39xbcC3Q4cWUFPkNk1b3GLEklg==", + "license": "MIT", + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/ajv": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/asn1": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", + "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", + "license": "MIT", + "dependencies": { + "safer-buffer": "~2.1.0" + } + }, + "node_modules/assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", + "license": "MIT", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" + }, + "node_modules/axios": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.4.tgz", + "integrity": "sha512-DukmaFRnY6AzAALSH4J2M3k6PkaC+MfaAGdEERRWcC9q3/TWQwLpHR8ZRLKTdQ3aBDL64EdluRDjJqKw+BPZEw==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/axios-cookiejar-support": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/axios-cookiejar-support/-/axios-cookiejar-support-2.0.3.tgz", + "integrity": "sha512-tvMB+0JhxXLjjvePsXzqXhBI4DMlW4ImR4pKKNl+xclwF0IviNV+CkuhubQCCFjPzOXv7PIzOq3z7WFiF9pMpw==", + "license": "MIT", + "dependencies": { + "http-cookie-agent": "^1.0.2" + }, + "engines": { + "node": ">=12.19.0 <13.0.0 || >=14.5.0" + }, + "peerDependencies": { + "axios": ">=0.20.0", + "tough-cookie": ">=4.0.0" + } + }, + "node_modules/base64-url": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/base64-url/-/base64-url-2.3.3.tgz", + "integrity": "sha512-dLMhIsK7OplcDauDH/tZLvK7JmUZK3A7KiQpjNzsBrM6Etw7hzNI1tLEywqJk9NnwkgWuFKSlx/IUO7vF6Mo8Q==", + "license": "ISC", + "engines": { + "node": ">=6" + } + }, + "node_modules/basic-auth": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-1.0.3.tgz", + "integrity": "sha512-fkXSqXkCTgBy5HVNQ2wP1Fnc/JZjnREwM3hfU8h5RyUN8X9WMQBJem6ZmlsSs7Y4f3fQ7z09vcARgOa0iaPaZA==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/body-parser": { + "version": "1.20.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", + "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.13.0", + "raw-body": "2.5.2", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/body-parser/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/body-parser/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==", + "license": "BSD-3-Clause" + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/cf-nodejs-logging-support": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/cf-nodejs-logging-support/-/cf-nodejs-logging-support-7.4.0.tgz", + "integrity": "sha512-s4rf4+JFUEumraAI842TBor6K/n5w3bmmZkpmROK5Fl7XJmx27M6XrjYxw8VAzRHVWdQmK9AVKfBBzt2wUtxZg==", + "license": "Apache-2.0", + "dependencies": { + "ajv": "^8.11.0", + "json-stringify-safe": "^5.0.1", + "jsonwebtoken": "^9.0.0", + "triple-beam": "^1.3.0", + "uuid": "^9.0.0", + "winston-transport": "^4.5.0" + }, + "engines": { + "node": ">=14.14" + } + }, + "node_modules/cf-nodejs-logging-support/node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==", + "license": "MIT", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/cluster-key-slot": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz", + "integrity": "sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==", + "license": "Apache-2.0", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commander": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz", + "integrity": "sha512-bmkUukX8wAOjHdN26xj5c4ctEV22TQ7dQYhSmuckKhToXrkUn0iIaolHdIxYYqD55nhpSPA9zPQ1yP57GdXP2A==", + "license": "MIT", + "dependencies": { + "graceful-readlink": ">= 1.0.0" + }, + "engines": { + "node": ">= 0.6.x" + } + }, + "node_modules/compressible": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "license": "MIT", + "dependencies": { + "mime-db": ">= 1.43.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/compression": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", + "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", + "license": "MIT", + "dependencies": { + "accepts": "~1.3.5", + "bytes": "3.0.0", + "compressible": "~2.0.16", + "debug": "2.6.9", + "on-headers": "~1.0.2", + "safe-buffer": "5.1.2", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/compression/node_modules/bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/compression/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/compression/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/connect": { + "version": "3.6.5", + "resolved": "https://registry.npmjs.org/connect/-/connect-3.6.5.tgz", + "integrity": "sha512-B+WTJ0bDgjQugnbNF7fWGvwEgTj9Isdk3Y7yTZlgCuVe+hpl/do8frEMeimx7sRMPW3oZA+EsC9uDZL8MaaAwQ==", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "finalhandler": "1.0.6", + "parseurl": "~1.3.2", + "utils-merge": "1.0.1" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/connect/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/connect/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.2.2.tgz", + "integrity": "sha512-QT1/SH6oF6jrC9K4rlWpa/5FgqUZuh/Ohl4NvGAgSm67DsieBdTz/XsiVQwBKEJMnw7Tui5uBuC7k1yUAmPO2g==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-parser": { + "version": "1.4.6", + "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.6.tgz", + "integrity": "sha512-z3IzaNjdwUC2olLIB5/ITd0/setiaFMLYiZJle7xg5Fe9KWAceil7xszYfHHBtDFYLSgJduS2Ty0P1uJdPDJeA==", + "license": "MIT", + "dependencies": { + "cookie": "0.4.1", + "cookie-signature": "1.0.6" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/cookie-parser/node_modules/cookie": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", + "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-parser/node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", + "license": "MIT" + }, + "node_modules/cookie-signature": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.1.0.tgz", + "integrity": "sha512-Alvs19Vgq07eunykd3Xy2jF0/qSNv2u7KDbAek9H5liV1UMijbqFs5cycZvv5dVsvseT/U4H8/7/w8Koh35C4A==", + "license": "MIT", + "engines": { + "node": ">=6.6.0" + } + }, + "node_modules/core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==", + "license": "MIT" + }, + "node_modules/debug": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "license": "MIT", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/debug/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "license": "MIT" + }, + "node_modules/decode-uri-component": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz", + "integrity": "sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==", + "license": "MIT", + "engines": { + "node": ">=0.10" + } + }, + "node_modules/deepmerge": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-2.1.1.tgz", + "integrity": "sha512-urQxA1smbLZ2cBbXbaYObM1dJ82aJ2H57A1C/Kklfh/ZN1bgH4G/n5KWhdNfOK11W98gqZfyYj7W4frJJRwA2w==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/denque": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/denque/-/denque-1.5.1.tgz", + "integrity": "sha512-XwE+iZ4D6ZUB7mfYRMb5wByE8L74HCn30FBN7sWnXksWc1LO1bPDl67pBR9o/kC4z/xSNAwkMYcGgqDV3BE3Hw==", + "license": "Apache-2.0", + "engines": { + "node": ">=0.10" + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "license": "MIT", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "license": "Apache-2.0", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "license": "MIT" + }, + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "license": "MIT" + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express-session": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.17.0.tgz", + "integrity": "sha512-t4oX2z7uoSqATbMfsxWMbNjAL0T5zpvcJCk3Z9wnPPN7ibddhnmDZXHfEcoBMG2ojKXZoCyPMc5FbtK+G7SoDg==", + "license": "MIT", + "dependencies": { + "cookie": "0.4.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~2.0.0", + "on-headers": "~1.0.2", + "parseurl": "~1.3.3", + "safe-buffer": "5.2.0", + "uid-safe": "~2.1.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/express-session/node_modules/cookie": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", + "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express-session/node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", + "license": "MIT" + }, + "node_modules/express-session/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/express-session/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/express-session/node_modules/safe-buffer": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz", + "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==", + "license": "MIT" + }, + "node_modules/extsprintf": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.4.1.tgz", + "integrity": "sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA==", + "engines": [ + "node >=0.6.0" + ], + "license": "MIT" + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "license": "MIT" + }, + "node_modules/fast-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz", + "integrity": "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/fecha": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.3.tgz", + "integrity": "sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==", + "license": "MIT" + }, + "node_modules/fetch-retry": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/fetch-retry/-/fetch-retry-4.1.0.tgz", + "integrity": "sha512-FUc9XZuhyE3ka3m53lec29PXVhdRf59QG01nE+OZdfl0M/R0E7Pk6k6qeWzHhX1pHl/f2JPA97sjjbHRgSg/9A==", + "license": "MIT" + }, + "node_modules/filter-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/filter-obj/-/filter-obj-1.1.0.tgz", + "integrity": "sha512-8rXg1ZnX7xzy2NGDVkBVaAy+lSlPNwad13BtgSlLuxfIslyt5Vg64U7tFcCt4WS1R0hvtnQybT/IyCkGZ3DpXQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/finalhandler": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.0.6.tgz", + "integrity": "sha512-immlyyYCPWG2tajlYBhZ6cjLAv1QAclU8tKS0d27ZtPqm/+iddy16GT3xLExg+V4lIETLpPwaYQAlZHNE//dPA==", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.1", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.2", + "statuses": "~1.3.1", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/finalhandler/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/finalhandler/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/finalhandler/node_modules/on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==", + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/follow-redirects": { + "version": "1.15.11", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz", + "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/form-data": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz", + "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-readlink": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", + "integrity": "sha512-8tLu60LgxF6XpdbK8OW3FA+IfTNBn1ZHGHKF4KQbEeSkajYw5PlYJcKluntgegDPTg8UkHjpet1T82vk6TQ68w==", + "license": "MIT" + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/http-cookie-agent": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/http-cookie-agent/-/http-cookie-agent-1.0.6.tgz", + "integrity": "sha512-Ei0BDjMfy6MSXATmCZ5nWr935NLYl6eD/BTxVGOIrKAlg4xDtMdk+8a+caq6Qwa4FACn+vACj89pFKlXmHOnkQ==", + "license": "MIT", + "dependencies": { + "agent-base": "^6.0.2" + }, + "engines": { + "node": ">=12.19.0 <13.0.0 || >=14.5.0" + }, + "peerDependencies": { + "tough-cookie": "^4.0.0" + } + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "license": "MIT", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/http-errors/node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/http-headers": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/http-headers/-/http-headers-3.0.2.tgz", + "integrity": "sha512-87E1I+2Wg4dxxz4rcxElo3dxO/w1ZtgL1yA0Sb6vH3qU16vRKq1NjWQv9SCY3ly2OQROcoxHZOUpmelS+k6wOw==", + "license": "MIT", + "dependencies": { + "next-line": "^1.1.0" + } + }, + "node_modules/http-proxy-agent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", + "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", + "license": "MIT", + "dependencies": { + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/https-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", + "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", + "license": "MIT", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, + "node_modules/ioredis": { + "version": "4.28.5", + "resolved": "https://registry.npmjs.org/ioredis/-/ioredis-4.28.5.tgz", + "integrity": "sha512-3GYo0GJtLqgNXj4YhrisLaNNvWSNwSS2wS4OELGfGxH8I69+XfNdnmV1AyN+ZqMh0i7eX+SWjrwFKDBDgfBC1A==", + "license": "MIT", + "dependencies": { + "cluster-key-slot": "^1.1.0", + "debug": "^4.3.1", + "denque": "^1.1.0", + "lodash.defaults": "^4.2.0", + "lodash.flatten": "^4.4.0", + "lodash.isarguments": "^3.1.0", + "p-map": "^2.1.0", + "redis-commands": "1.7.0", + "redis-errors": "^1.2.0", + "redis-parser": "^3.0.0", + "standard-as-callback": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/ioredis" + } + }, + "node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "license": "MIT" + }, + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", + "license": "ISC" + }, + "node_modules/jsonwebtoken": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", + "integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==", + "license": "MIT", + "dependencies": { + "jws": "^3.2.2", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=12", + "npm": ">=6" + } + }, + "node_modules/jwa": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.2.tgz", + "integrity": "sha512-eeH5JO+21J78qMvTIDdBXidBd6nG2kZjg5Ohz/1fpa28Z4CcsWUzJ1ZZyFq/3z3N17aZy+ZuBoHljASbL1WfOw==", + "license": "MIT", + "dependencies": { + "buffer-equal-constant-time": "^1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jws": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", + "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", + "license": "MIT", + "dependencies": { + "jwa": "^1.4.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jwt-decode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-2.0.1.tgz", + "integrity": "sha512-/KEXk2wGfWoSM2SHQk8mq9n/Rd6ahB0XIZt0jEcNy4tQXeDHU4oNOGK1shSVstIQm97qowy6dFgUAHB3zbOD8g==", + "license": "MIT" + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "license": "MIT" + }, + "node_modules/lodash.defaults": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", + "integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==", + "license": "MIT" + }, + "node_modules/lodash.flatten": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", + "integrity": "sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g==", + "license": "MIT" + }, + "node_modules/lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==", + "license": "MIT" + }, + "node_modules/lodash.isarguments": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", + "integrity": "sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg==", + "license": "MIT" + }, + "node_modules/lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==", + "license": "MIT" + }, + "node_modules/lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==", + "license": "MIT" + }, + "node_modules/lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==", + "license": "MIT" + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", + "license": "MIT" + }, + "node_modules/lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==", + "license": "MIT" + }, + "node_modules/lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==", + "license": "MIT" + }, + "node_modules/logform": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/logform/-/logform-2.7.0.tgz", + "integrity": "sha512-TFYA4jnP7PVbmlBIfhlSe+WKxs9dklXMTEGcBCIvLhE/Tn3H6Gk1norupVW7m5Cnd4bLcr08AytbyV/xj7f/kQ==", + "license": "MIT", + "dependencies": { + "@colors/colors": "1.6.0", + "@types/triple-beam": "^1.3.2", + "fecha": "^4.2.0", + "ms": "^2.1.1", + "safe-stable-stringify": "^2.3.1", + "triple-beam": "^1.3.0" + }, + "engines": { + "node": ">= 12.0.0" + } + }, + "node_modules/lru-cache": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.0.0.tgz", + "integrity": "sha512-WKhDkjlLwzE8jAQdQlsxLUQTPXLCKX/4cJk6s5AlRtJkDBk0IKH5O51bVDH61K9N4bhbbyvLM6EiOuE8ovApPA==", + "license": "ISC", + "dependencies": { + "pseudomap": "^1.0.1", + "yallist": "^2.0.0" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", + "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==", + "license": "MIT", + "bin": { + "mime": "cli.js" + } + }, + "node_modules/mime-db": { + "version": "1.54.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", + "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types/node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "license": "MIT" + }, + "node_modules/mustache": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/mustache/-/mustache-2.2.1.tgz", + "integrity": "sha512-azYRexmi9y6h2lk2JqfBLh1htlDMjKYyEYOkxoGKa0FRdr5aY4f5q8bH4JIecM181DtUEYLSz8PcRO46mgzMNQ==", + "license": "MIT", + "bin": { + "mustache": "bin/mustache" + }, + "engines": { + "npm": ">=1.4.0" + } + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/next-line": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/next-line/-/next-line-1.1.0.tgz", + "integrity": "sha512-+I10J3wKNoKddNxn0CNpoZ3eTZuqxjNM3b1GImVx22+ePI+Y15P8g/j3WsbP0fhzzrFzrtjOAoq5NCCucswXOQ==", + "license": "MIT" + }, + "node_modules/node-cache": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/node-cache/-/node-cache-4.1.1.tgz", + "integrity": "sha512-1IdglJ3+6RO7j2jGVSbWG7CD/H7axG770BbuopZNDqKpQu1ol89xC4Qc+hd6uBEewjsoCZ6xRIY8BRa5PkHgTQ==", + "license": "MIT", + "dependencies": { + "clone": "2.x", + "lodash": "4.x" + }, + "engines": { + "node": ">= 0.4.6" + } + }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "license": "MIT", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/node-forge": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", + "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", + "license": "(BSD-3-Clause OR GPL-2.0)", + "engines": { + "node": ">= 6.13.0" + } + }, + "node_modules/node-rsa": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/node-rsa/-/node-rsa-1.1.1.tgz", + "integrity": "sha512-Jd4cvbJMryN21r5HgxQOpMEqv+ooke/korixNNK3mGqfGJmy0M77WDDzo/05969+OkMy3XW1UuZsSmW9KQm7Fw==", + "license": "MIT", + "dependencies": { + "asn1": "^0.2.4" + } + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/p-map": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", + "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/passport": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/passport/-/passport-0.6.0.tgz", + "integrity": "sha512-0fe+p3ZnrWRW74fe8+SvCyf4a3Pb2/h7gFkQ8yTJpAO50gDzlfjZUZTO1k5Eg9kUct22OxHLqDZoKUWRHOh9ug==", + "license": "MIT", + "dependencies": { + "passport-strategy": "1.x.x", + "pause": "0.0.1", + "utils-merge": "^1.0.1" + }, + "engines": { + "node": ">= 0.4.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/jaredhanson" + } + }, + "node_modules/passport-strategy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz", + "integrity": "sha512-CB97UUvDKJde2V0KDWWB3lyf6PC3FaZP7YxZ2G8OAtn9p4HI9j9JLP9qjOGZFvyl8uwNT8qM+hGnz/n16NI7oA==", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/pause": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz", + "integrity": "sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg==" + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "license": "MIT" + }, + "node_modules/pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==", + "license": "ISC" + }, + "node_modules/psl": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.15.0.tgz", + "integrity": "sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w==", + "license": "MIT", + "dependencies": { + "punycode": "^2.3.1" + }, + "funding": { + "url": "https://github.com/sponsors/lupomontero" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/qs": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.0.6" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/query-string": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-7.1.2.tgz", + "integrity": "sha512-KPbFzz/8pmtYOMH6zlYZgqTYJKQ18FxwfW3RLHIBwHWQ0iQG18X16XtIOk68ddfaM6j3grjYSnMPMrqQEjwR4w==", + "license": "MIT", + "dependencies": { + "decode-uri-component": "^0.2.1", + "filter-obj": "^1.1.0", + "split-on-first": "^1.0.0", + "strict-uri-encode": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/querystringify": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", + "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", + "license": "MIT" + }, + "node_modules/random-bytes": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", + "integrity": "sha512-iv7LhNVO047HzYR3InF6pUcUsPQiHTM1Qal51DcGSuZFBil1aBBWG5eHPNek7bvILMaYJ/8RU1e8w1AMdHmLQQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/redis-commands": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/redis-commands/-/redis-commands-1.7.0.tgz", + "integrity": "sha512-nJWqw3bTFy21hX/CPKHth6sfhZbdiHP6bTawSgQBlKOVRG7EZkfHbbHwQJnrE4vsQf0CMNE+3gJ4Fmm16vdVlQ==", + "license": "MIT" + }, + "node_modules/redis-errors": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz", + "integrity": "sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/redis-parser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-3.0.0.tgz", + "integrity": "sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A==", + "license": "MIT", + "dependencies": { + "redis-errors": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/request-stats": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/request-stats/-/request-stats-2.0.1.tgz", + "integrity": "sha512-GZQvTZqbUx9gXrRfj1c9pMcFzyLeJEpV2P5qXxGwf1I2ZRswRsCNYPsuwnFLNRZQamlsrinzKQnExXBGgFzFCw==", + "license": "MIT", + "dependencies": { + "http-headers": "^3.0.1", + "once": "^1.4.0" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", + "license": "MIT" + }, + "node_modules/ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", + "license": "MIT", + "engines": { + "node": ">=0.12" + } + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "license": "MIT" + }, + "node_modules/safe-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "integrity": "sha512-aJXcif4xnaNUzvUuC5gcb46oTS7zvg4jpMTnuqtrEPlR3vFr4pxtdTwaF1Qs3Enjn9HK+ZlwQui+a7z0SywIzg==", + "license": "MIT", + "dependencies": { + "ret": "~0.1.10" + } + }, + "node_modules/safe-stable-stringify": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz", + "integrity": "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" + }, + "node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/send": { + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", + "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/send/node_modules/debug/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/send/node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/send/node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/serve-static": { + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", + "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", + "license": "MIT", + "dependencies": { + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.19.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/serve-static/node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "license": "ISC" + }, + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/split-on-first": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/split-on-first/-/split-on-first-1.1.0.tgz", + "integrity": "sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/standard-as-callback": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/standard-as-callback/-/standard-as-callback-2.1.0.tgz", + "integrity": "sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A==", + "license": "MIT" + }, + "node_modules/statuses": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz", + "integrity": "sha512-wuTCPGlJONk/a1kqZ4fQM2+908lC7fa7nPYpTC1EhnvqLX/IICbeP1OZGDtA374trpSq68YubKUMo8oRhN46yg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/strict-uri-encode": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz", + "integrity": "sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string_decoder/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "license": "MIT", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/tough-cookie": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.3.tgz", + "integrity": "sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw==", + "license": "BSD-3-Clause", + "dependencies": { + "psl": "^1.1.33", + "punycode": "^2.1.1", + "universalify": "^0.2.0", + "url-parse": "^1.5.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "license": "MIT" + }, + "node_modules/triple-beam": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.4.1.tgz", + "integrity": "sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg==", + "license": "MIT", + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/tv4": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/tv4/-/tv4-1.2.7.tgz", + "integrity": "sha512-7W00xKKK9ccSXbN8E1FUKe+PJKlQc3HcPRM1y9WnplFVucoWFBpTNCGJNMHG04+yf5lQKUKx71yt0mluqnbCzw==", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "license": "MIT", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/uid-safe": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz", + "integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==", + "license": "MIT", + "dependencies": { + "random-bytes": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/universalify": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", + "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", + "license": "MIT", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/urijs": { + "version": "1.19.11", + "resolved": "https://registry.npmjs.org/urijs/-/urijs-1.19.11.tgz", + "integrity": "sha512-HXgFDgDommxn5/bIv0cnQZsPhHDA90NPHD6+c/v21U5+Sx5hoP8+dP9IZXBU1gIfvdRfhG8cel9QNPeionfcCQ==", + "license": "MIT" + }, + "node_modules/url-parse": { + "version": "1.5.10", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", + "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", + "license": "MIT", + "dependencies": { + "querystringify": "^2.1.1", + "requires-port": "^1.0.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "license": "MIT" + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "license": "MIT", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/validator": { + "version": "13.7.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-13.7.0.tgz", + "integrity": "sha512-nYXQLCBkpJ8X6ltALua9dRrZDHVYxjJ1wgskNt1lH9fzGjs3tgojGSCBjmEPwkWS1y29+DrizMTW19Pr9uB2nw==", + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", + "engines": [ + "node >=0.6.0" + ], + "license": "MIT", + "dependencies": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "license": "BSD-2-Clause" + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "license": "MIT", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/winston-transport": { + "version": "4.9.0", + "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.9.0.tgz", + "integrity": "sha512-8drMJ4rkgaPo1Me4zD/3WLfI/zPdA9o2IipKODunnGDcuqbHwjsbB79ylv04LCGGzU0xQ6vTznOMpQGaLhhm6A==", + "license": "MIT", + "dependencies": { + "logform": "^2.7.0", + "readable-stream": "^3.6.2", + "triple-beam": "^1.3.0" + }, + "engines": { + "node": ">= 12.0.0" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "license": "ISC" + }, + "node_modules/ws": { + "version": "7.5.10", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", + "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", + "license": "MIT", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/wtfnode": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/wtfnode/-/wtfnode-0.9.1.tgz", + "integrity": "sha512-Ip6C2KeQPl/F3aP1EfOnPoQk14Udd9lffpoqWDNH3Xt78svxPbv53ngtmtfI0q2Te3oTq79XKTnRNXVIn/GsPA==", + "license": "ISC", + "bin": { + "wtfnode": "proxy.js" + } + }, + "node_modules/yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==", + "license": "ISC" + } + } +} diff --git a/cap-notebook/demoapp/db/schema.cds b/cap-notebook/demoapp/db/schema.cds index fb0f5953b..e2d61ef16 100644 --- a/cap-notebook/demoapp/db/schema.cds +++ b/cap-notebook/demoapp/db/schema.cds @@ -20,6 +20,9 @@ image : LargeBinary @Core.MediaType: 'image/png'; // top-level chapters composition (root of the nested hierarchy) chapters : Composition of many Chapters on chapters.book = $self; +// top-level pages composition (same pattern as chapters) +pages : Composition of many Pages on pages.book = $self; + // keep any other fields as before } @@ -53,20 +56,19 @@ on children.parent = $self; // sections : Composition of many Sections on sections.chapter = $self; // } -entity Sections : cuid, managed { -title : String(255); - -// backlink to parent chapter -chapter : Association to Chapters; - -// attachments will be added via attachments-extension.cds so we don't create a hard dependency on SDM in the core schema -// attachments : Composition of many sap.attachments.Attachments; // added by extension -} - entity Chapters : cuid, managed { book : Association to Books; title : String @title: 'Chapter Title'; description : String; url : String; chapterType : String @title: 'Chapter Type'; -} \ No newline at end of file +} + +entity Pages : cuid, managed { + book : Association to Books; + title : String @title: 'Page Title'; + description : String; + url : String; + pageType : String @title: 'Page Type'; +} + diff --git a/cap-notebook/demoapp/srv/admin-service.cds b/cap-notebook/demoapp/srv/admin-service.cds index 04ff97792..220b6fab8 100644 --- a/cap-notebook/demoapp/srv/admin-service.cds +++ b/cap-notebook/demoapp/srv/admin-service.cds @@ -5,6 +5,7 @@ service AdminService @(requires: 'admin') { entity Books as projection on my.Books; entity Authors as projection on my.Authors; entity Chapters as projection on my.Chapters; + entity Pages as projection on my.Pages; entity Books.attachments as projection on my.Books.attachments actions { @@ -23,4 +24,124 @@ service AdminService @(requires: 'admin') { action editLink(in: $self, url: String); action openAttachment() returns String; }; + + entity Books.references as projection on my.Books.references + actions { + // Table-level actions + @(Common.SideEffects : { TargetEntities: [''] }) + action copyAttachments(in: many $self, up__ID: String, objectIds: String); + + @(Common.SideEffects : { TargetEntities: [''] }) + action createLink( + in: many $self, + @mandatory @assert.unique @placeholder: 'Enter name' name: String, + @mandatory @placeholder: 'Enter URL' url: String + ); + + // Row-level actions + action editLink(in: $self, url: String); + action openAttachment() returns String; + }; + + entity Pages.attachments as projection on my.Pages.attachments + actions { + // Table-level actions + @(Common.SideEffects : { TargetEntities: [''] }) + action copyAttachments(in: many $self, up__ID: String, objectIds: String); + + @(Common.SideEffects : { TargetEntities: [''] }) + action createLink( + in: many $self, + @mandatory @assert.unique @placeholder: 'Enter name' name: String, + @mandatory @placeholder: 'Enter URL' url: String + ); + + // Row-level actions + action editLink(in: $self, url: String); + action openAttachment() returns String; + }; + + entity Pages.references as projection on my.Pages.references + actions { + // Table-level actions + @(Common.SideEffects : { TargetEntities: [''] }) + action copyAttachments(in: many $self, up__ID: String, objectIds: String); + + @(Common.SideEffects : { TargetEntities: [''] }) + action createLink( + in: many $self, + @mandatory @assert.unique @placeholder: 'Enter name' name: String, + @mandatory @placeholder: 'Enter URL' url: String + ); + + // Row-level actions + action editLink(in: $self, url: String); + action openAttachment() returns String; + }; + + // Chapters projections + entity Chapters.attachments as projection on my.Chapters.attachments + actions { + @(Common.SideEffects : { TargetEntities: [''] }) + action copyAttachments(in: many $self, up__ID: String, objectIds: String); + + @(Common.SideEffects : { TargetEntities: [''] }) + action createLink( + in: many $self, + @mandatory @assert.unique @placeholder: 'Enter name' name: String, + @mandatory @placeholder: 'Enter URL' url: String + ); + + action editLink(in: $self, url: String); + action openAttachment() returns String; + }; + + entity Chapters.references as projection on my.Chapters.references + actions { + @(Common.SideEffects : { TargetEntities: [''] }) + action copyAttachments(in: many $self, up__ID: String, objectIds: String); + + @(Common.SideEffects : { TargetEntities: [''] }) + action createLink( + in: many $self, + @mandatory @assert.unique @placeholder: 'Enter name' name: String, + @mandatory @placeholder: 'Enter URL' url: String + ); + + action editLink(in: $self, url: String); + action openAttachment() returns String; + }; + + entity Chapters.footnotes as projection on my.Chapters.footnotes + actions { + @(Common.SideEffects : { TargetEntities: [''] }) + action copyAttachments(in: many $self, up__ID: String, objectIds: String); + + @(Common.SideEffects : { TargetEntities: [''] }) + action createLink( + in: many $self, + @mandatory @assert.unique @placeholder: 'Enter name' name: String, + @mandatory @placeholder: 'Enter URL' url: String + ); + + action editLink(in: $self, url: String); + action openAttachment() returns String; + }; + + // Pages footnotes projection + entity Pages.footnotes as projection on my.Pages.footnotes + actions { + @(Common.SideEffects : { TargetEntities: [''] }) + action copyAttachments(in: many $self, up__ID: String, objectIds: String); + + @(Common.SideEffects : { TargetEntities: [''] }) + action createLink( + in: many $self, + @mandatory @assert.unique @placeholder: 'Enter name' name: String, + @mandatory @placeholder: 'Enter URL' url: String + ); + + action editLink(in: $self, url: String); + action openAttachment() returns String; + }; } diff --git a/cap-notebook/demoapp/srv/attachment-extension.cds b/cap-notebook/demoapp/srv/attachment-extension.cds index ea1cce275..af72748f1 100644 --- a/cap-notebook/demoapp/srv/attachment-extension.cds +++ b/cap-notebook/demoapp/srv/attachment-extension.cds @@ -1,22 +1,29 @@ -using {sap.capire.bookshop.Books, sap.capire.bookshop.Chapters} from '../db/schema'; +using {sap.capire.bookshop.Books, sap.capire.bookshop.Chapters, sap.capire.bookshop.Pages} from '../db/schema'; using {sap.attachments.Attachments, sap.attachments.StatusCode} from`com.sap.cds/sdm`; using {sap,managed,sap.common.CodeList} from '@sap/cds/common'; // keep the original shallow attachments on Books extend entity Books with { attachments : Composition of many Attachments; - //references: Composition of many Attachments; + references: Composition of many Attachments; footnotes: Composition of many Attachments; } -// Add attachments to Sections -extend entity sap.capire.bookshop.Sections with { - attachments : Composition of many Attachments; - //references: Composition of many Attachments; + + +extend entity Chapters with { + attachments: Composition of many Attachments; + references: Composition of many Attachments; + footnotes: Composition of many Attachments; +} + +extend entity Pages with { + attachments: Composition of many Attachments; + references: Composition of many Attachments; footnotes: Composition of many Attachments; } -extend entity Chapters with { attachments: Composition of many Attachments } + entity Statuses @cds.autoexpose @readonly { key code : StatusCode; @@ -48,3 +55,161 @@ annotate sap.capire.bookshop.Sections.attachments with { sap.value.list: 'fixed-values' ); } + +annotate Books.references with { + status @( + Common.Text: { + $value: ![statusText.text], + ![@UI.TextArrangement]: #TextOnly + }, + ValueList: { entity: 'Statuses' }, + sap.value.list: 'fixed-values' + ); +} + +annotate Chapters.attachments with { + status @( + Common.Text: { + $value: ![statusText.text], + ![@UI.TextArrangement]: #TextOnly + }, + ValueList: { entity: 'Statuses' }, + sap.value.list: 'fixed-values' + ); +} + +annotate Chapters.references with { + status @( + Common.Text: { + $value: ![statusText.text], + ![@UI.TextArrangement]: #TextOnly + }, + ValueList: { entity: 'Statuses' }, + sap.value.list: 'fixed-values' + ); +} + +annotate Pages.attachments with { + status @( + Common.Text: { + $value: ![statusText.text], + ![@UI.TextArrangement]: #TextOnly + }, + ValueList: { entity: 'Statuses' }, + sap.value.list: 'fixed-values' + ); +} + +annotate Pages.references with { + status @( + Common.Text: { + $value: ![statusText.text], + ![@UI.TextArrangement]: #TextOnly + }, + ValueList: { entity: 'Statuses' }, + sap.value.list: 'fixed-values' + ); +} + +annotate Chapters.footnotes with { + status @( + Common.Text: { + $value: ![statusText.text], + ![@UI.TextArrangement]: #TextOnly + }, + ValueList: { entity: 'Statuses' }, + sap.value.list: 'fixed-values' + ); +} + +annotate Pages.footnotes with { + status @( + Common.Text: { + $value: ![statusText.text], + ![@UI.TextArrangement]: #TextOnly + }, + ValueList: { entity: 'Statuses' }, + sap.value.list: 'fixed-values' + ); +} + +annotate Sections.attachments with { + status @( + Common.Text: { + $value: ![statusText.text], + ![@UI.TextArrangement]: #TextOnly + }, + ValueList: { entity: 'Statuses' }, + sap.value.list: 'fixed-values' + ); +} + +annotate Sections.references with { + status @( + Common.Text: { + $value: ![statusText.text], + ![@UI.TextArrangement]: #TextOnly + }, + ValueList: { entity: 'Statuses' }, + sap.value.list: 'fixed-values' + ); +} + +annotate Sections.footnotes with { + status @( + Common.Text: { + $value: ![statusText.text], + ![@UI.TextArrangement]: #TextOnly + }, + ValueList: { entity: 'Statuses' }, + sap.value.list: 'fixed-values' + ); +} + +extend Attachments with { + customProperty1 : WDIRS_CodeList_TYPE + @SDM.Attachments.AdditionalProperty: { + name: 'Working:DocumentInfoRecordString' + } + @(title: 'DocumentInfoRecordString'); + customProperty2 : Integer + @SDM.Attachments.AdditionalProperty: { + name: 'Working:DocumentInfoRecordInt' + }; + customProperty3 : String + @SDM.Attachments.AdditionalProperty: { + name: 'abc:myId1' + } + @(title: 'id1'); + customProperty4 : String + @SDM.Attachments.AdditionalProperty: { + name: 'abc:myId2' + } + @(title: 'id2'); + customProperty5 : DateTime + @SDM.Attachments.AdditionalProperty: { + name: 'Working:DocumentInfoRecordDate' + } + @(title: 'DocumentInfoRecordDate'); + customProperty6 : Boolean + @SDM.Attachments.AdditionalProperty: { + name: 'Working:DocumentInfoRecordBoolean' + } + @(title: 'DocumentInfoRecordBoolean'); +} + +entity WDIRSCodeList : CodeList { + key code : String(30) @Common.Text : name @Common.TextArrangement: #TextFirst; +}; + +type WDIRS_CodeList_TYPE : Association to one WDIRSCodeList; + +annotate Books.attachments with { + status @( + Common.Text: { + $value: ![statusText.text], + ![@UI.TextArrangement]: #TextOnly + }, + ValueList: {entity:'Statuses'} + ); +} From 88177dc68a3046b4afb66547e5c4016ef76a868d Mon Sep 17 00:00:00 2001 From: Rishi Kunnath <82925475+rishikunnath2747@users.noreply.github.com> Date: Fri, 10 Oct 2025 14:59:05 +0530 Subject: [PATCH 3/8] ui changes --- cap-notebook/demoapp/app/common.cds | 332 +++++++++++------- cap-notebook/demoapp/db/pom.xml | 2 +- .../demoapp/srv/attachment-extension.cds | 44 +-- cap-notebook/demoapp/srv/pom.xml | 2 +- 4 files changed, 214 insertions(+), 166 deletions(-) diff --git a/cap-notebook/demoapp/app/common.cds b/cap-notebook/demoapp/app/common.cds index 11adfde3c..3b928465e 100644 --- a/cap-notebook/demoapp/app/common.cds +++ b/cap-notebook/demoapp/app/common.cds @@ -79,7 +79,7 @@ annotate my.Books.attachments with @UI: { $Type : 'UI.DataFieldForActionGroup', ID : 'TableActionGroup', Label : 'Create', - ![@UI.Hidden]: {$edmJson: {$Eq: [ {$Path: 'IsActiveEntity'}, 'true' ]}}, + ![@UI.Hidden]: {$edmJson: {$Eq: [ {$Path: 'IsActiveEntity'}, true ]}}, Actions: [ { $Type : 'UI.DataFieldForAction', @@ -89,7 +89,7 @@ annotate my.Books.attachments with @UI: { ] }, { - @UI.Disabled: {$edmJson: { + @UI.Hidden: {$edmJson: { $If: [ { $Eq: [ { $Path: 'IsActiveEntity' }, true ] }, true, @@ -110,14 +110,6 @@ annotate my.Books.attachments with @UI: { IconUrl: 'sap-icon://edit', @HTML5.CssDefaults: {width: '4%'}, @UI.ButtonType : #Tertiary - }, - { - $Type : 'UI.DataFieldForAction', - Label : 'Changelog', - Action: 'AdminService.createLink', - Inline: true, - IconUrl: 'sap-icon://activities', - @HTML5.CssDefaults: {width: '4%'} } ], } @@ -140,82 +132,74 @@ annotate Attachments with @Common: {SideEffects #ContentChanged: { TargetEntities : [Books.attachments] }}{}; -// annotate my.Books.references with @UI: { -// HeaderInfo: { -// $Type : 'UI.HeaderInfoType', -// TypeName : '{i18n>Attachment}', -// TypeNamePlural: '{i18n>Attachments}', -// }, -// LineItem : [ -// {Value: type, @HTML5.CssDefaults: {width: '10%'}}, -// {Value: fileName, @HTML5.CssDefaults: {width: '25%'}}, -// {Value: content, @HTML5.CssDefaults: {width: '0%'}}, -// {Value: createdAt, @HTML5.CssDefaults: {width: '20%'}}, -// {Value: createdBy, @HTML5.CssDefaults: {width: '20%'}}, -// {Value: note, @HTML5.CssDefaults: {width: '25%'}}, -// { -// $Type : 'UI.DataFieldForAction', -// Label : 'Copy Attachments', -// Action: 'AdminService.copyAttachments', -// }, -// { -// $Type : 'UI.DataFieldForActionGroup', -// ID : 'TableActionGroup', -// Label : 'Create', -// ![@UI.Hidden]: {$edmJson: {$Eq: [ {$Path: 'IsActiveEntity'}, 'true' ]}}, -// Actions: [ -// { -// $Type : 'UI.DataFieldForAction', -// Label : 'Link', -// Action: 'AdminService.createLink' -// } -// ] -// }, -// { -// @UI.Disabled: {$edmJson: { -// $If: [ -// { $Eq: [ { $Path: 'IsActiveEntity' }, true ] }, -// true, -// { -// $If: [ -// { $Ne: [ { $Path: 'mimeType' }, 'application/internet-shortcut' ] }, -// true, -// false -// ] -// } -// ] -// } -// }, -// $Type : 'UI.DataFieldForAction', -// Label : 'Edit Link', -// Action: 'AdminService.editLink', -// Inline: true, -// IconUrl: 'sap-icon://edit', -// @HTML5.CssDefaults: {width: '4%'} -// }, -// { -// $Type : 'UI.DataFieldForAction', -// Label : 'Changelog', -// Action: 'AdminService.createLink', -// Inline: true, -// IconUrl: 'sap-icon://activities', -// @HTML5.CssDefaults: {width: '4%'} -// } -// ], -// } -// { -// note @(title: '{i18n>Note}'); -// fileName @(title: '{i18n>Filename}'); -// modifiedAt @(odata.etag: null); -// content -// @Core.ContentDisposition: { Filename: fileName } -// @(title: '{i18n>Attachment}'); -// folderId @UI.Hidden; -// repositoryId @UI.Hidden ; -// objectId @UI.Hidden ; -// mimeType @UI.Hidden; -// status @UI.Hidden; -// } +annotate my.Books.references with @UI: { + HeaderInfo: { + $Type : 'UI.HeaderInfoType', + TypeName : '{i18n>Attachment}', + TypeNamePlural: '{i18n>Attachments}', + }, + LineItem : [ + {Value: type, @HTML5.CssDefaults: {width: '10%'}}, + {Value: fileName, @HTML5.CssDefaults: {width: '25%'}}, + {Value: content, @HTML5.CssDefaults: {width: '0%'}}, + {Value: createdAt, @HTML5.CssDefaults: {width: '20%'}}, + {Value: createdBy, @HTML5.CssDefaults: {width: '20%'}}, + {Value: note, @HTML5.CssDefaults: {width: '25%'}}, + { + $Type : 'UI.DataFieldForAction', + Label : 'Copy Attachments', + Action: 'AdminService.copyAttachments', + }, + { + $Type : 'UI.DataFieldForActionGroup', + ID : 'TableActionGroup', + Label : 'Create', + ![@UI.Hidden]: {$edmJson: {$Eq: [ {$Path: 'IsActiveEntity'}, true ]}}, + Actions: [ + { + $Type : 'UI.DataFieldForAction', + Label : 'Link', + Action: 'AdminService.createLink' + } + ] + }, + { + @UI.Hidden: {$edmJson: { + $If: [ + { $Eq: [ { $Path: 'IsActiveEntity' }, true ] }, + true, + { + $If: [ + { $Ne: [ { $Path: 'mimeType' }, 'application/internet-shortcut' ] }, + true, + false + ] + } + ] + } +}, + $Type : 'UI.DataFieldForAction', + Label : 'Edit Link', + Action: 'AdminService.editLink', + Inline: true, + IconUrl: 'sap-icon://edit', + @HTML5.CssDefaults: {width: '4%'} + } + ], +} +{ + note @(title: '{i18n>Note}'); + fileName @(title: '{i18n>Filename}'); + modifiedAt @(odata.etag: null); + content + @Core.ContentDisposition: { Filename: fileName } + @(title: '{i18n>Attachment}'); + folderId @UI.Hidden; + repositoryId @UI.Hidden ; + objectId @UI.Hidden ; + mimeType @UI.Hidden; + status @UI.Hidden; +} annotate my.Books.footnotes with @UI: { HeaderInfo: { @@ -239,7 +223,7 @@ annotate my.Books.footnotes with @UI: { $Type : 'UI.DataFieldForActionGroup', ID : 'TableActionGroup', Label : 'Create', - ![@UI.Hidden]: {$edmJson: {$Eq: [ {$Path: 'IsActiveEntity'}, 'true' ]}}, + ![@UI.Hidden]: {$edmJson: {$Eq: [ {$Path: 'IsActiveEntity'}, true ]}}, Actions: [ { $Type : 'UI.DataFieldForAction', @@ -249,7 +233,7 @@ annotate my.Books.footnotes with @UI: { ] }, { - @UI.Disabled: {$edmJson: { + @UI.Hidden: {$edmJson: { $If: [ { $Eq: [ { $Path: 'IsActiveEntity' }, true ] }, true, @@ -269,14 +253,75 @@ annotate my.Books.footnotes with @UI: { Inline: true, IconUrl: 'sap-icon://edit', @HTML5.CssDefaults: {width: '4%'} + } + ], +} +{ + note @(title: '{i18n>Note}'); + fileName @(title: '{i18n>Filename}'); + modifiedAt @(odata.etag: null); + content + @Core.ContentDisposition: { Filename: fileName } + @(title: '{i18n>Attachment}'); + folderId @UI.Hidden; + repositoryId @UI.Hidden ; + objectId @UI.Hidden ; + mimeType @UI.Hidden; + status @UI.Hidden; +} + +annotate my.Chapters.attachments with @UI: { + HeaderInfo: { + $Type : 'UI.HeaderInfoType', + TypeName : '{i18n>Attachment}', + TypeNamePlural: '{i18n>Attachments}', + }, + LineItem : [ + {Value: type, @HTML5.CssDefaults: {width: '10%'}}, + {Value: fileName, @HTML5.CssDefaults: {width: '25%'}}, + {Value: content, @HTML5.CssDefaults: {width: '0%'}}, + {Value: createdAt, @HTML5.CssDefaults: {width: '20%'}}, + {Value: createdBy, @HTML5.CssDefaults: {width: '20%'}}, + {Value: note, @HTML5.CssDefaults: {width: '25%'}}, + { + $Type : 'UI.DataFieldForAction', + Label : 'Copy Attachments', + Action: 'AdminService.copyAttachments', + }, + { + $Type : 'UI.DataFieldForActionGroup', + ID : 'TableActionGroup', + Label : 'Create', + ![@UI.Hidden]: {$edmJson: {$Eq: [ {$Path: 'IsActiveEntity'}, true ]}}, + Actions: [ + { + $Type : 'UI.DataFieldForAction', + Label : 'Link', + Action: 'AdminService.createLink' + } + ] }, { + @UI.Hidden: {$edmJson: { + $If: [ + { $Eq: [ { $Path: 'IsActiveEntity' }, true ] }, + true, + { + $If: [ + { $Ne: [ { $Path: 'mimeType' }, 'application/internet-shortcut' ] }, + true, + false + ] + } + ] + } +}, $Type : 'UI.DataFieldForAction', - Label : 'Changelog', - Action: 'AdminService.createLink', + Label : 'Edit Link', + Action: 'AdminService.editLink', Inline: true, - IconUrl: 'sap-icon://activities', - @HTML5.CssDefaults: {width: '4%'} + IconUrl: 'sap-icon://edit', + @HTML5.CssDefaults: {width: '4%'} } ], } @@ -294,7 +339,7 @@ annotate my.Books.footnotes with @UI: { status @UI.Hidden; } -annotate my.Books.references with @UI: { +annotate my.Chapters.references with @UI: { HeaderInfo: { $Type : 'UI.HeaderInfoType', TypeName : '{i18n>Reference}', @@ -316,7 +361,7 @@ annotate my.Books.references with @UI: { $Type : 'UI.DataFieldForActionGroup', ID : 'TableActionGroup', Label : 'Create', - ![@UI.Hidden]: {$edmJson: {$Eq: [ {$Path: 'IsActiveEntity'}, 'true' ]}}, + ![@UI.Hidden]: {$edmJson: {$Eq: [ {$Path: 'IsActiveEntity'}, true ]}}, Actions: [ { $Type : 'UI.DataFieldForAction', @@ -326,7 +371,7 @@ annotate my.Books.references with @UI: { ] }, { - @UI.Disabled: {$edmJson: { + @UI.Hidden: {$edmJson: { $If: [ { $Eq: [ { $Path: 'IsActiveEntity' }, true ] }, true, @@ -346,14 +391,6 @@ annotate my.Books.references with @UI: { Inline: true, IconUrl: 'sap-icon://edit', @HTML5.CssDefaults: {width: '4%'} - }, - { - $Type : 'UI.DataFieldForAction', - Label : 'Changelog', - Action: 'AdminService.createLink', - Inline: true, - IconUrl: 'sap-icon://activities', - @HTML5.CssDefaults: {width: '4%'} } ], } @@ -371,7 +408,7 @@ annotate my.Books.references with @UI: { status @UI.Hidden; } -annotate my.Chapters.attachments with @UI: { +annotate my.Pages.attachments with @UI: { HeaderInfo: { $Type : 'UI.HeaderInfoType', TypeName : '{i18n>Attachment}', @@ -393,7 +430,7 @@ annotate my.Chapters.attachments with @UI: { $Type : 'UI.DataFieldForActionGroup', ID : 'TableActionGroup', Label : 'Create', - ![@UI.Hidden]: {$edmJson: {$Eq: [ {$Path: 'IsActiveEntity'}, 'true' ]}}, + ![@UI.Hidden]: {$edmJson: {$Eq: [ {$Path: 'IsActiveEntity'}, true ]}}, Actions: [ { $Type : 'UI.DataFieldForAction', @@ -403,7 +440,7 @@ annotate my.Chapters.attachments with @UI: { ] }, { - @UI.Disabled: {$edmJson: { + @UI.Hidden: {$edmJson: { $If: [ { $Eq: [ { $Path: 'IsActiveEntity' }, true ] }, true, @@ -423,14 +460,6 @@ annotate my.Chapters.attachments with @UI: { Inline: true, IconUrl: 'sap-icon://edit', @HTML5.CssDefaults: {width: '4%'} - }, - { - $Type : 'UI.DataFieldForAction', - Label : 'Changelog', - Action: 'AdminService.createLink', - Inline: true, - IconUrl: 'sap-icon://activities', - @HTML5.CssDefaults: {width: '4%'} } ], } @@ -448,7 +477,7 @@ annotate my.Chapters.attachments with @UI: { status @UI.Hidden; } -annotate my.Chapters.references with @UI: { +annotate my.Pages.references with @UI: { HeaderInfo: { $Type : 'UI.HeaderInfoType', TypeName : '{i18n>Reference}', @@ -470,7 +499,7 @@ annotate my.Chapters.references with @UI: { $Type : 'UI.DataFieldForActionGroup', ID : 'TableActionGroup', Label : 'Create', - ![@UI.Hidden]: {$edmJson: {$Eq: [ {$Path: 'IsActiveEntity'}, 'true' ]}}, + ![@UI.Hidden]: {$edmJson: {$Eq: [ {$Path: 'IsActiveEntity'}, true ]}}, Actions: [ { $Type : 'UI.DataFieldForAction', @@ -480,7 +509,7 @@ annotate my.Chapters.references with @UI: { ] }, { - @UI.Disabled: {$edmJson: { + @UI.Hidden: {$edmJson: { $If: [ { $Eq: [ { $Path: 'IsActiveEntity' }, true ] }, true, @@ -500,14 +529,75 @@ annotate my.Chapters.references with @UI: { Inline: true, IconUrl: 'sap-icon://edit', @HTML5.CssDefaults: {width: '4%'} + } + ], +} +{ + note @(title: '{i18n>Note}'); + fileName @(title: '{i18n>Filename}'); + modifiedAt @(odata.etag: null); + content + @Core.ContentDisposition: { Filename: fileName } + @(title: '{i18n>Attachment}'); + folderId @UI.Hidden; + repositoryId @UI.Hidden ; + objectId @UI.Hidden ; + mimeType @UI.Hidden; + status @UI.Hidden; +} + +annotate my.Pages.footnotes with @UI: { + HeaderInfo: { + $Type : 'UI.HeaderInfoType', + TypeName : '{i18n>Footnote}', + TypeNamePlural: '{i18n>Footnotes}', + }, + LineItem : [ + {Value: type, @HTML5.CssDefaults: {width: '10%'}}, + {Value: fileName, @HTML5.CssDefaults: {width: '25%'}}, + {Value: content, @HTML5.CssDefaults: {width: '0%'}}, + {Value: createdAt, @HTML5.CssDefaults: {width: '20%'}}, + {Value: createdBy, @HTML5.CssDefaults: {width: '20%'}}, + {Value: note, @HTML5.CssDefaults: {width: '25%'}}, + { + $Type : 'UI.DataFieldForAction', + Label : 'Copy Footnotes', + Action: 'AdminService.copyAttachments', }, { + $Type : 'UI.DataFieldForActionGroup', + ID : 'TableActionGroup', + Label : 'Create', + ![@UI.Hidden]: {$edmJson: {$Eq: [ {$Path: 'IsActiveEntity'}, true ]}}, + Actions: [ + { + $Type : 'UI.DataFieldForAction', + Label : 'Link', + Action: 'AdminService.createLink' + } + ] + }, + { + @UI.Hidden: {$edmJson: { + $If: [ + { $Eq: [ { $Path: 'IsActiveEntity' }, true ] }, + true, + { + $If: [ + { $Ne: [ { $Path: 'mimeType' }, 'application/internet-shortcut' ] }, + true, + false + ] + } + ] + } +}, $Type : 'UI.DataFieldForAction', - Label : 'Changelog', - Action: 'AdminService.createLink', + Label : 'Edit Link', + Action: 'AdminService.editLink', Inline: true, - IconUrl: 'sap-icon://activities', - @HTML5.CssDefaults: {width: '4%'} + IconUrl: 'sap-icon://edit', + @HTML5.CssDefaults: {width: '4%'} } ], } diff --git a/cap-notebook/demoapp/db/pom.xml b/cap-notebook/demoapp/db/pom.xml index 190a05f6b..7a74659e1 100644 --- a/cap-notebook/demoapp/db/pom.xml +++ b/cap-notebook/demoapp/db/pom.xml @@ -16,7 +16,7 @@ com.sap.cds sdm - 1.5.1-SNAPSHOT + 1.0.0-RC1 diff --git a/cap-notebook/demoapp/srv/attachment-extension.cds b/cap-notebook/demoapp/srv/attachment-extension.cds index af72748f1..ef6b548c7 100644 --- a/cap-notebook/demoapp/srv/attachment-extension.cds +++ b/cap-notebook/demoapp/srv/attachment-extension.cds @@ -9,8 +9,6 @@ extend entity Books with { footnotes: Composition of many Attachments; } - - extend entity Chapters with { attachments: Composition of many Attachments; references: Composition of many Attachments; @@ -45,16 +43,7 @@ annotate Books.attachments with { ); } -annotate sap.capire.bookshop.Sections.attachments with { - status @( - Common.Text: { - $value: ![statusText.text], - ![@UI.TextArrangement]: #TextOnly - }, - ValueList: { entity: 'Statuses' }, - sap.value.list: 'fixed-values' - ); -} + annotate Books.references with { status @( @@ -133,38 +122,7 @@ annotate Pages.footnotes with { ); } -annotate Sections.attachments with { - status @( - Common.Text: { - $value: ![statusText.text], - ![@UI.TextArrangement]: #TextOnly - }, - ValueList: { entity: 'Statuses' }, - sap.value.list: 'fixed-values' - ); -} - -annotate Sections.references with { - status @( - Common.Text: { - $value: ![statusText.text], - ![@UI.TextArrangement]: #TextOnly - }, - ValueList: { entity: 'Statuses' }, - sap.value.list: 'fixed-values' - ); -} -annotate Sections.footnotes with { - status @( - Common.Text: { - $value: ![statusText.text], - ![@UI.TextArrangement]: #TextOnly - }, - ValueList: { entity: 'Statuses' }, - sap.value.list: 'fixed-values' - ); -} extend Attachments with { customProperty1 : WDIRS_CodeList_TYPE diff --git a/cap-notebook/demoapp/srv/pom.xml b/cap-notebook/demoapp/srv/pom.xml index af82f4eb6..1a18bebd8 100644 --- a/cap-notebook/demoapp/srv/pom.xml +++ b/cap-notebook/demoapp/srv/pom.xml @@ -18,7 +18,7 @@ com.sap.cds sdm - 1.5.1-SNAPSHOT + 1.0.0-RC1 From e4ee9e06ab2508ee6334b32de20f28e021ce0c80 Mon Sep 17 00:00:00 2001 From: Rishi Kunnath <82925475+rishikunnath2747@users.noreply.github.com> Date: Mon, 13 Oct 2025 14:25:44 +0530 Subject: [PATCH 4/8] Update attachment-extension.cds --- cap-notebook/demoapp/srv/attachment-extension.cds | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cap-notebook/demoapp/srv/attachment-extension.cds b/cap-notebook/demoapp/srv/attachment-extension.cds index ef6b548c7..1cafb45db 100644 --- a/cap-notebook/demoapp/srv/attachment-extension.cds +++ b/cap-notebook/demoapp/srv/attachment-extension.cds @@ -4,9 +4,9 @@ using {sap,managed,sap.common.CodeList} from '@sap/cds/common'; // keep the original shallow attachments on Books extend entity Books with { - attachments : Composition of many Attachments; - references: Composition of many Attachments; - footnotes: Composition of many Attachments; + attachments : Composition of many Attachments @SDM.Attachments:{maxCount: 4, maxCountError:'Only 4 attachments allowed.'}; + references : Composition of many Attachments @SDM.Attachments:{maxCount: 5, maxCountError:'Only 5 attachments allowed.'}; + footnotes : Composition of many Attachments; } extend entity Chapters with { From 384a49ec4302cc78e3d0a89822e38a0c7c18a86b Mon Sep 17 00:00:00 2001 From: Rishi Kunnath <82925475+rishikunnath2747@users.noreply.github.com> Date: Mon, 13 Oct 2025 19:00:55 +0530 Subject: [PATCH 5/8] changes --- .../webapp/controller/custom.controller.js | 33 -- .../app/admin-books/webapp/manifest.json | 32 +- cap-notebook/demoapp/app/common.cds | 337 ++---------------- cap-notebook/demoapp/srv/admin-service.cds | 84 ----- 4 files changed, 25 insertions(+), 461 deletions(-) delete mode 100644 cap-notebook/demoapp/app/admin-books/webapp/controller/custom.controller.js diff --git a/cap-notebook/demoapp/app/admin-books/webapp/controller/custom.controller.js b/cap-notebook/demoapp/app/admin-books/webapp/controller/custom.controller.js deleted file mode 100644 index a7fd5a2a7..000000000 --- a/cap-notebook/demoapp/app/admin-books/webapp/controller/custom.controller.js +++ /dev/null @@ -1,33 +0,0 @@ -sap.ui.define( - [ - "sap/ui/core/mvc/ControllerExtension", - "sap/m/library" - ], - function (ControllerExtension,library) { - "use strict"; - - return ControllerExtension.extend("books.controller.custom", { - onRowPress: function(oContext) { - this.base.editFlow - .invokeAction("AdminService.openAttachment", { - contexts: oContext.getParameter("bindingContext") - }) - .then(function (res) { - let odataurl = ""; - if(res.getObject().value == "None") { - const lastSlashIndex = res.oModel.getServiceUrl().lastIndexOf('/'); - let str = res.oModel.getServiceUrl(); - if (lastSlashIndex !== -1) { - str = str.substring(0, lastSlashIndex) + str.substring(lastSlashIndex + 1); - } - odataurl = str+res.oBinding.oContext.sPath+"/content"; - } else { - odataurl = res.getObject().value; - } - library.URLHelper.redirect(odataurl, true); - - }); - } - }); - } -); \ No newline at end of file diff --git a/cap-notebook/demoapp/app/admin-books/webapp/manifest.json b/cap-notebook/demoapp/app/admin-books/webapp/manifest.json index d4251ba12..cfd4285c9 100644 --- a/cap-notebook/demoapp/app/admin-books/webapp/manifest.json +++ b/cap-notebook/demoapp/app/admin-books/webapp/manifest.json @@ -132,33 +132,6 @@ "route": "PagesObjectPage" } } - }, - "controlConfiguration": { - "attachments/@com.sap.vocabularies.UI.v1.LineItem": { - "tableSettings": { - "type": "ResponsiveTable", - "selectionMode": "Auto", - "rowPress": ".extension.books.controller.custom.onRowPress" - } - }, - "footnotes/@com.sap.vocabularies.UI.v1.LineItem": { - "tableSettings": { - "type": "ResponsiveTable", - "selectionMode": "Auto", - "rowPress": ".extension.books.controller.custom.onRowPress" - } - }, - "chapters/@com.sap.vocabularies.UI.v1.LineItem#i18nChapters": { - "tableSettings": { - "type": "ResponsiveTable" - } - }, - "pages/@com.sap.vocabularies.UI.v1.LineItem#i18nPages": { - "tableSettings": { - "type": "ResponsiveTable" - } - } - } } } @@ -213,10 +186,7 @@ }, "extends": { "extensions": { - "sap.ui.controllerExtensions": { - "sap.fe.templates.ObjectPage.ObjectPageController#books::BooksDetailsList": { - "controllerName": "books.controller.custom" - } + "sap.ui.controllerExtensions": { } } }, diff --git a/cap-notebook/demoapp/app/common.cds b/cap-notebook/demoapp/app/common.cds index 3b928465e..db4d58be6 100644 --- a/cap-notebook/demoapp/app/common.cds +++ b/cap-notebook/demoapp/app/common.cds @@ -64,52 +64,15 @@ annotate my.Books.attachments with @UI: { TypeNamePlural: '{i18n>Attachments}', }, LineItem : [ - {Value: type, @HTML5.CssDefaults: {width: '10%'}}, - {Value: fileName, @HTML5.CssDefaults: {width: '25%'}}, - {Value: content, @HTML5.CssDefaults: {width: '0%'}}, + {Value: fileName, @HTML5.CssDefaults: {width: '20%'}}, + {Value: content, @HTML5.CssDefaults: {width: '20%'}}, {Value: createdAt, @HTML5.CssDefaults: {width: '20%'}}, {Value: createdBy, @HTML5.CssDefaults: {width: '20%'}}, - {Value: note, @HTML5.CssDefaults: {width: '25%'}}, + {Value: note, @HTML5.CssDefaults: {width: '20%'}}, { $Type : 'UI.DataFieldForAction', Label : 'Copy Attachments', Action: 'AdminService.copyAttachments', - }, - { - $Type : 'UI.DataFieldForActionGroup', - ID : 'TableActionGroup', - Label : 'Create', - ![@UI.Hidden]: {$edmJson: {$Eq: [ {$Path: 'IsActiveEntity'}, true ]}}, - Actions: [ - { - $Type : 'UI.DataFieldForAction', - Label : 'Link', - Action: 'AdminService.createLink' - } - ] - }, - { - @UI.Hidden: {$edmJson: { - $If: [ - { $Eq: [ { $Path: 'IsActiveEntity' }, true ] }, - true, - { - $If: [ - { $Ne: [ { $Path: 'mimeType' }, 'application/internet-shortcut' ] }, - true, - false - ] - } - ] - } -}, - $Type : 'UI.DataFieldForAction', - Label : 'Edit Link', - Action: 'AdminService.editLink', - Inline: true, - IconUrl: 'sap-icon://edit', - @HTML5.CssDefaults: {width: '4%'}, - @UI.ButtonType : #Tertiary } ], } @@ -139,51 +102,15 @@ annotate my.Books.references with @UI: { TypeNamePlural: '{i18n>Attachments}', }, LineItem : [ - {Value: type, @HTML5.CssDefaults: {width: '10%'}}, - {Value: fileName, @HTML5.CssDefaults: {width: '25%'}}, - {Value: content, @HTML5.CssDefaults: {width: '0%'}}, + {Value: fileName, @HTML5.CssDefaults: {width: '20%'}}, + {Value: content, @HTML5.CssDefaults: {width: '20%'}}, {Value: createdAt, @HTML5.CssDefaults: {width: '20%'}}, {Value: createdBy, @HTML5.CssDefaults: {width: '20%'}}, - {Value: note, @HTML5.CssDefaults: {width: '25%'}}, + {Value: note, @HTML5.CssDefaults: {width: '20%'}}, { $Type : 'UI.DataFieldForAction', Label : 'Copy Attachments', Action: 'AdminService.copyAttachments', - }, - { - $Type : 'UI.DataFieldForActionGroup', - ID : 'TableActionGroup', - Label : 'Create', - ![@UI.Hidden]: {$edmJson: {$Eq: [ {$Path: 'IsActiveEntity'}, true ]}}, - Actions: [ - { - $Type : 'UI.DataFieldForAction', - Label : 'Link', - Action: 'AdminService.createLink' - } - ] - }, - { - @UI.Hidden: {$edmJson: { - $If: [ - { $Eq: [ { $Path: 'IsActiveEntity' }, true ] }, - true, - { - $If: [ - { $Ne: [ { $Path: 'mimeType' }, 'application/internet-shortcut' ] }, - true, - false - ] - } - ] - } -}, - $Type : 'UI.DataFieldForAction', - Label : 'Edit Link', - Action: 'AdminService.editLink', - Inline: true, - IconUrl: 'sap-icon://edit', - @HTML5.CssDefaults: {width: '4%'} } ], } @@ -208,51 +135,15 @@ annotate my.Books.footnotes with @UI: { TypeNamePlural: '{i18n>Attachments}', }, LineItem : [ - {Value: type, @HTML5.CssDefaults: {width: '10%'}}, - {Value: fileName, @HTML5.CssDefaults: {width: '25%'}}, - {Value: content, @HTML5.CssDefaults: {width: '0%'}}, + {Value: fileName, @HTML5.CssDefaults: {width: '20%'}}, + {Value: content, @HTML5.CssDefaults: {width: '20%'}}, {Value: createdAt, @HTML5.CssDefaults: {width: '20%'}}, {Value: createdBy, @HTML5.CssDefaults: {width: '20%'}}, - {Value: note, @HTML5.CssDefaults: {width: '25%'}}, + {Value: note, @HTML5.CssDefaults: {width: '20%'}}, { $Type : 'UI.DataFieldForAction', Label : 'Copy Attachments', Action: 'AdminService.copyAttachments', - }, - { - $Type : 'UI.DataFieldForActionGroup', - ID : 'TableActionGroup', - Label : 'Create', - ![@UI.Hidden]: {$edmJson: {$Eq: [ {$Path: 'IsActiveEntity'}, true ]}}, - Actions: [ - { - $Type : 'UI.DataFieldForAction', - Label : 'Link', - Action: 'AdminService.createLink' - } - ] - }, - { - @UI.Hidden: {$edmJson: { - $If: [ - { $Eq: [ { $Path: 'IsActiveEntity' }, true ] }, - true, - { - $If: [ - { $Ne: [ { $Path: 'mimeType' }, 'application/internet-shortcut' ] }, - true, - false - ] - } - ] - } -}, - $Type : 'UI.DataFieldForAction', - Label : 'Edit Link', - Action: 'AdminService.editLink', - Inline: true, - IconUrl: 'sap-icon://edit', - @HTML5.CssDefaults: {width: '4%'} } ], } @@ -277,51 +168,15 @@ annotate my.Chapters.attachments with @UI: { TypeNamePlural: '{i18n>Attachments}', }, LineItem : [ - {Value: type, @HTML5.CssDefaults: {width: '10%'}}, - {Value: fileName, @HTML5.CssDefaults: {width: '25%'}}, - {Value: content, @HTML5.CssDefaults: {width: '0%'}}, + {Value: fileName, @HTML5.CssDefaults: {width: '20%'}}, + {Value: content, @HTML5.CssDefaults: {width: '20%'}}, {Value: createdAt, @HTML5.CssDefaults: {width: '20%'}}, {Value: createdBy, @HTML5.CssDefaults: {width: '20%'}}, - {Value: note, @HTML5.CssDefaults: {width: '25%'}}, + {Value: note, @HTML5.CssDefaults: {width: '20%'}}, { $Type : 'UI.DataFieldForAction', Label : 'Copy Attachments', Action: 'AdminService.copyAttachments', - }, - { - $Type : 'UI.DataFieldForActionGroup', - ID : 'TableActionGroup', - Label : 'Create', - ![@UI.Hidden]: {$edmJson: {$Eq: [ {$Path: 'IsActiveEntity'}, true ]}}, - Actions: [ - { - $Type : 'UI.DataFieldForAction', - Label : 'Link', - Action: 'AdminService.createLink' - } - ] - }, - { - @UI.Hidden: {$edmJson: { - $If: [ - { $Eq: [ { $Path: 'IsActiveEntity' }, true ] }, - true, - { - $If: [ - { $Ne: [ { $Path: 'mimeType' }, 'application/internet-shortcut' ] }, - true, - false - ] - } - ] - } -}, - $Type : 'UI.DataFieldForAction', - Label : 'Edit Link', - Action: 'AdminService.editLink', - Inline: true, - IconUrl: 'sap-icon://edit', - @HTML5.CssDefaults: {width: '4%'} } ], } @@ -346,51 +201,15 @@ annotate my.Chapters.references with @UI: { TypeNamePlural: '{i18n>References}', }, LineItem : [ - {Value: type, @HTML5.CssDefaults: {width: '10%'}}, - {Value: fileName, @HTML5.CssDefaults: {width: '25%'}}, - {Value: content, @HTML5.CssDefaults: {width: '0%'}}, + {Value: fileName, @HTML5.CssDefaults: {width: '20%'}}, + {Value: content, @HTML5.CssDefaults: {width: '20%'}}, {Value: createdAt, @HTML5.CssDefaults: {width: '20%'}}, {Value: createdBy, @HTML5.CssDefaults: {width: '20%'}}, - {Value: note, @HTML5.CssDefaults: {width: '25%'}}, + {Value: note, @HTML5.CssDefaults: {width: '20%'}}, { $Type : 'UI.DataFieldForAction', Label : 'Copy References', Action: 'AdminService.copyAttachments', - }, - { - $Type : 'UI.DataFieldForActionGroup', - ID : 'TableActionGroup', - Label : 'Create', - ![@UI.Hidden]: {$edmJson: {$Eq: [ {$Path: 'IsActiveEntity'}, true ]}}, - Actions: [ - { - $Type : 'UI.DataFieldForAction', - Label : 'Link', - Action: 'AdminService.createLink' - } - ] - }, - { - @UI.Hidden: {$edmJson: { - $If: [ - { $Eq: [ { $Path: 'IsActiveEntity' }, true ] }, - true, - { - $If: [ - { $Ne: [ { $Path: 'mimeType' }, 'application/internet-shortcut' ] }, - true, - false - ] - } - ] - } -}, - $Type : 'UI.DataFieldForAction', - Label : 'Edit Link', - Action: 'AdminService.editLink', - Inline: true, - IconUrl: 'sap-icon://edit', - @HTML5.CssDefaults: {width: '4%'} } ], } @@ -415,51 +234,15 @@ annotate my.Pages.attachments with @UI: { TypeNamePlural: '{i18n>Attachments}', }, LineItem : [ - {Value: type, @HTML5.CssDefaults: {width: '10%'}}, - {Value: fileName, @HTML5.CssDefaults: {width: '25%'}}, - {Value: content, @HTML5.CssDefaults: {width: '0%'}}, + {Value: fileName, @HTML5.CssDefaults: {width: '20%'}}, + {Value: content, @HTML5.CssDefaults: {width: '20%'}}, {Value: createdAt, @HTML5.CssDefaults: {width: '20%'}}, {Value: createdBy, @HTML5.CssDefaults: {width: '20%'}}, - {Value: note, @HTML5.CssDefaults: {width: '25%'}}, + {Value: note, @HTML5.CssDefaults: {width: '20%'}}, { $Type : 'UI.DataFieldForAction', Label : 'Copy Attachments', Action: 'AdminService.copyAttachments', - }, - { - $Type : 'UI.DataFieldForActionGroup', - ID : 'TableActionGroup', - Label : 'Create', - ![@UI.Hidden]: {$edmJson: {$Eq: [ {$Path: 'IsActiveEntity'}, true ]}}, - Actions: [ - { - $Type : 'UI.DataFieldForAction', - Label : 'Link', - Action: 'AdminService.createLink' - } - ] - }, - { - @UI.Hidden: {$edmJson: { - $If: [ - { $Eq: [ { $Path: 'IsActiveEntity' }, true ] }, - true, - { - $If: [ - { $Ne: [ { $Path: 'mimeType' }, 'application/internet-shortcut' ] }, - true, - false - ] - } - ] - } -}, - $Type : 'UI.DataFieldForAction', - Label : 'Edit Link', - Action: 'AdminService.editLink', - Inline: true, - IconUrl: 'sap-icon://edit', - @HTML5.CssDefaults: {width: '4%'} } ], } @@ -484,51 +267,15 @@ annotate my.Pages.references with @UI: { TypeNamePlural: '{i18n>References}', }, LineItem : [ - {Value: type, @HTML5.CssDefaults: {width: '10%'}}, - {Value: fileName, @HTML5.CssDefaults: {width: '25%'}}, - {Value: content, @HTML5.CssDefaults: {width: '0%'}}, + {Value: fileName, @HTML5.CssDefaults: {width: '20%'}}, + {Value: content, @HTML5.CssDefaults: {width: '20%'}}, {Value: createdAt, @HTML5.CssDefaults: {width: '20%'}}, {Value: createdBy, @HTML5.CssDefaults: {width: '20%'}}, - {Value: note, @HTML5.CssDefaults: {width: '25%'}}, + {Value: note, @HTML5.CssDefaults: {width: '20%'}}, { $Type : 'UI.DataFieldForAction', Label : 'Copy References', Action: 'AdminService.copyAttachments', - }, - { - $Type : 'UI.DataFieldForActionGroup', - ID : 'TableActionGroup', - Label : 'Create', - ![@UI.Hidden]: {$edmJson: {$Eq: [ {$Path: 'IsActiveEntity'}, true ]}}, - Actions: [ - { - $Type : 'UI.DataFieldForAction', - Label : 'Link', - Action: 'AdminService.createLink' - } - ] - }, - { - @UI.Hidden: {$edmJson: { - $If: [ - { $Eq: [ { $Path: 'IsActiveEntity' }, true ] }, - true, - { - $If: [ - { $Ne: [ { $Path: 'mimeType' }, 'application/internet-shortcut' ] }, - true, - false - ] - } - ] - } -}, - $Type : 'UI.DataFieldForAction', - Label : 'Edit Link', - Action: 'AdminService.editLink', - Inline: true, - IconUrl: 'sap-icon://edit', - @HTML5.CssDefaults: {width: '4%'} } ], } @@ -553,51 +300,15 @@ annotate my.Pages.footnotes with @UI: { TypeNamePlural: '{i18n>Footnotes}', }, LineItem : [ - {Value: type, @HTML5.CssDefaults: {width: '10%'}}, - {Value: fileName, @HTML5.CssDefaults: {width: '25%'}}, - {Value: content, @HTML5.CssDefaults: {width: '0%'}}, + {Value: fileName, @HTML5.CssDefaults: {width: '20%'}}, + {Value: content, @HTML5.CssDefaults: {width: '20%'}}, {Value: createdAt, @HTML5.CssDefaults: {width: '20%'}}, {Value: createdBy, @HTML5.CssDefaults: {width: '20%'}}, - {Value: note, @HTML5.CssDefaults: {width: '25%'}}, + {Value: note, @HTML5.CssDefaults: {width: '20%'}}, { $Type : 'UI.DataFieldForAction', Label : 'Copy Footnotes', Action: 'AdminService.copyAttachments', - }, - { - $Type : 'UI.DataFieldForActionGroup', - ID : 'TableActionGroup', - Label : 'Create', - ![@UI.Hidden]: {$edmJson: {$Eq: [ {$Path: 'IsActiveEntity'}, true ]}}, - Actions: [ - { - $Type : 'UI.DataFieldForAction', - Label : 'Link', - Action: 'AdminService.createLink' - } - ] - }, - { - @UI.Hidden: {$edmJson: { - $If: [ - { $Eq: [ { $Path: 'IsActiveEntity' }, true ] }, - true, - { - $If: [ - { $Ne: [ { $Path: 'mimeType' }, 'application/internet-shortcut' ] }, - true, - false - ] - } - ] - } -}, - $Type : 'UI.DataFieldForAction', - Label : 'Edit Link', - Action: 'AdminService.editLink', - Inline: true, - IconUrl: 'sap-icon://edit', - @HTML5.CssDefaults: {width: '4%'} } ], } diff --git a/cap-notebook/demoapp/srv/admin-service.cds b/cap-notebook/demoapp/srv/admin-service.cds index 220b6fab8..8d0a288ed 100644 --- a/cap-notebook/demoapp/srv/admin-service.cds +++ b/cap-notebook/demoapp/srv/admin-service.cds @@ -12,17 +12,6 @@ service AdminService @(requires: 'admin') { // Table-level actions @(Common.SideEffects : { TargetEntities: [''] }) action copyAttachments(in: many $self, up__ID: String, objectIds: String); - - @(Common.SideEffects : { TargetEntities: [''] }) - action createLink( - in: many $self, - @mandatory @assert.unique @placeholder: 'Enter name' name: String, - @mandatory @placeholder: 'Enter URL' url: String - ); - - // Row-level actions - action editLink(in: $self, url: String); - action openAttachment() returns String; }; entity Books.references as projection on my.Books.references @@ -30,17 +19,6 @@ service AdminService @(requires: 'admin') { // Table-level actions @(Common.SideEffects : { TargetEntities: [''] }) action copyAttachments(in: many $self, up__ID: String, objectIds: String); - - @(Common.SideEffects : { TargetEntities: [''] }) - action createLink( - in: many $self, - @mandatory @assert.unique @placeholder: 'Enter name' name: String, - @mandatory @placeholder: 'Enter URL' url: String - ); - - // Row-level actions - action editLink(in: $self, url: String); - action openAttachment() returns String; }; entity Pages.attachments as projection on my.Pages.attachments @@ -48,17 +26,6 @@ service AdminService @(requires: 'admin') { // Table-level actions @(Common.SideEffects : { TargetEntities: [''] }) action copyAttachments(in: many $self, up__ID: String, objectIds: String); - - @(Common.SideEffects : { TargetEntities: [''] }) - action createLink( - in: many $self, - @mandatory @assert.unique @placeholder: 'Enter name' name: String, - @mandatory @placeholder: 'Enter URL' url: String - ); - - // Row-level actions - action editLink(in: $self, url: String); - action openAttachment() returns String; }; entity Pages.references as projection on my.Pages.references @@ -66,17 +33,6 @@ service AdminService @(requires: 'admin') { // Table-level actions @(Common.SideEffects : { TargetEntities: [''] }) action copyAttachments(in: many $self, up__ID: String, objectIds: String); - - @(Common.SideEffects : { TargetEntities: [''] }) - action createLink( - in: many $self, - @mandatory @assert.unique @placeholder: 'Enter name' name: String, - @mandatory @placeholder: 'Enter URL' url: String - ); - - // Row-level actions - action editLink(in: $self, url: String); - action openAttachment() returns String; }; // Chapters projections @@ -84,48 +40,18 @@ service AdminService @(requires: 'admin') { actions { @(Common.SideEffects : { TargetEntities: [''] }) action copyAttachments(in: many $self, up__ID: String, objectIds: String); - - @(Common.SideEffects : { TargetEntities: [''] }) - action createLink( - in: many $self, - @mandatory @assert.unique @placeholder: 'Enter name' name: String, - @mandatory @placeholder: 'Enter URL' url: String - ); - - action editLink(in: $self, url: String); - action openAttachment() returns String; }; entity Chapters.references as projection on my.Chapters.references actions { @(Common.SideEffects : { TargetEntities: [''] }) action copyAttachments(in: many $self, up__ID: String, objectIds: String); - - @(Common.SideEffects : { TargetEntities: [''] }) - action createLink( - in: many $self, - @mandatory @assert.unique @placeholder: 'Enter name' name: String, - @mandatory @placeholder: 'Enter URL' url: String - ); - - action editLink(in: $self, url: String); - action openAttachment() returns String; }; entity Chapters.footnotes as projection on my.Chapters.footnotes actions { @(Common.SideEffects : { TargetEntities: [''] }) action copyAttachments(in: many $self, up__ID: String, objectIds: String); - - @(Common.SideEffects : { TargetEntities: [''] }) - action createLink( - in: many $self, - @mandatory @assert.unique @placeholder: 'Enter name' name: String, - @mandatory @placeholder: 'Enter URL' url: String - ); - - action editLink(in: $self, url: String); - action openAttachment() returns String; }; // Pages footnotes projection @@ -133,15 +59,5 @@ service AdminService @(requires: 'admin') { actions { @(Common.SideEffects : { TargetEntities: [''] }) action copyAttachments(in: many $self, up__ID: String, objectIds: String); - - @(Common.SideEffects : { TargetEntities: [''] }) - action createLink( - in: many $self, - @mandatory @assert.unique @placeholder: 'Enter name' name: String, - @mandatory @placeholder: 'Enter URL' url: String - ); - - action editLink(in: $self, url: String); - action openAttachment() returns String; }; } From 324d68790aded8726155f682ddab680dfaa329c3 Mon Sep 17 00:00:00 2001 From: Rishi Kunnath <82925475+rishikunnath2747@users.noreply.github.com> Date: Tue, 21 Oct 2025 10:20:16 +0530 Subject: [PATCH 6/8] Changes to add link to all facets --- .../demoapp/app/admin-books/fiori-service.cds | 47 +- .../webapp/controller/custom.controller.js | 33 ++ .../app/admin-books/webapp/manifest.json | 85 +++- cap-notebook/demoapp/app/common.cds | 405 ++++++++++++++++-- cap-notebook/demoapp/srv/admin-service.cds | 151 ++++++- .../demoapp/srv/attachment-extension.cds | 2 +- 6 files changed, 632 insertions(+), 91 deletions(-) create mode 100644 cap-notebook/demoapp/app/admin-books/webapp/controller/custom.controller.js diff --git a/cap-notebook/demoapp/app/admin-books/fiori-service.cds b/cap-notebook/demoapp/app/admin-books/fiori-service.cds index 4f98f4cc0..de8e3171d 100644 --- a/cap-notebook/demoapp/app/admin-books/fiori-service.cds +++ b/cap-notebook/demoapp/app/admin-books/fiori-service.cds @@ -352,51 +352,14 @@ annotate AdminService.Books.texts { ) }; -// Workaround for Fiori popup for asking user to enter a new UUID on Create -annotate AdminService.Books with { - ID @Core.Computed; -} +// In addition we need to expose Languages through AdminService as a target for ValueList +using {sap} from '@sap/cds/common'; -// Show Genre as drop down, not a dialog -annotate AdminService.Books with { - genre @Common.ValueListWithFixedValues; +extend service AdminService { + @readonly + entity Languages as projection on sap.common.Languages; } -annotate AdminService.Books.texts with @(UI: { - Identification : [{Value: title}], - SelectionFields: [ - locale, - title - ], - LineItem : [ - { - Value: locale, - Label: 'Locale' - }, - { - Value: title, - Label: 'Title' - }, - { - Value: descr, - Label: 'Description' - }, - ] -}); - -annotate AdminService.Books.texts with { - ID @UI.Hidden; - ID_texts @UI.Hidden; -}; - -// Add Value Help for Locales -annotate AdminService.Books.texts { - locale @( - ValueList.entity: 'Languages', - Common.ValueListWithFixedValues, //show as drop down, not a dialog - ) -}; - // Workaround for Fiori popup for asking user to enter a new UUID on Create annotate AdminService.Books with { ID @Core.Computed; diff --git a/cap-notebook/demoapp/app/admin-books/webapp/controller/custom.controller.js b/cap-notebook/demoapp/app/admin-books/webapp/controller/custom.controller.js new file mode 100644 index 000000000..a7fd5a2a7 --- /dev/null +++ b/cap-notebook/demoapp/app/admin-books/webapp/controller/custom.controller.js @@ -0,0 +1,33 @@ +sap.ui.define( + [ + "sap/ui/core/mvc/ControllerExtension", + "sap/m/library" + ], + function (ControllerExtension,library) { + "use strict"; + + return ControllerExtension.extend("books.controller.custom", { + onRowPress: function(oContext) { + this.base.editFlow + .invokeAction("AdminService.openAttachment", { + contexts: oContext.getParameter("bindingContext") + }) + .then(function (res) { + let odataurl = ""; + if(res.getObject().value == "None") { + const lastSlashIndex = res.oModel.getServiceUrl().lastIndexOf('/'); + let str = res.oModel.getServiceUrl(); + if (lastSlashIndex !== -1) { + str = str.substring(0, lastSlashIndex) + str.substring(lastSlashIndex + 1); + } + odataurl = str+res.oBinding.oContext.sPath+"/content"; + } else { + odataurl = res.getObject().value; + } + library.URLHelper.redirect(odataurl, true); + + }); + } + }); + } +); \ No newline at end of file diff --git a/cap-notebook/demoapp/app/admin-books/webapp/manifest.json b/cap-notebook/demoapp/app/admin-books/webapp/manifest.json index cfd4285c9..24cc3f714 100644 --- a/cap-notebook/demoapp/app/admin-books/webapp/manifest.json +++ b/cap-notebook/demoapp/app/admin-books/webapp/manifest.json @@ -132,6 +132,29 @@ "route": "PagesObjectPage" } } + }, + "controlConfiguration": { + "attachments/@com.sap.vocabularies.UI.v1.LineItem": { + "tableSettings": { + "type": "ResponsiveTable", + "selectionMode": "Auto", + "rowPress": ".extension.books.controller.custom.onRowPress" + } + }, + "references/@com.sap.vocabularies.UI.v1.LineItem": { + "tableSettings": { + "type": "ResponsiveTable", + "selectionMode": "Auto", + "rowPress": ".extension.books.controller.custom.onRowPress" + } + }, + "footnotes/@com.sap.vocabularies.UI.v1.LineItem": { + "tableSettings": { + "type": "ResponsiveTable", + "selectionMode": "Auto", + "rowPress": ".extension.books.controller.custom.onRowPress" + } + } } } } @@ -143,8 +166,30 @@ "options": { "settings": { "editableHeaderContent": false, - "entitySet": "Chapters" - + "entitySet": "Chapters", + "controlConfiguration": { + "attachments/@com.sap.vocabularies.UI.v1.LineItem": { + "tableSettings": { + "type": "ResponsiveTable", + "selectionMode": "Auto", + "rowPress": ".extension.books.controller.custom.onRowPress" + } + }, + "references/@com.sap.vocabularies.UI.v1.LineItem": { + "tableSettings": { + "type": "ResponsiveTable", + "selectionMode": "Auto", + "rowPress": ".extension.books.controller.custom.onRowPress" + } + }, + "footnotes/@com.sap.vocabularies.UI.v1.LineItem": { + "tableSettings": { + "type": "ResponsiveTable", + "selectionMode": "Auto", + "rowPress": ".extension.books.controller.custom.onRowPress" + } + } + } } } }, @@ -156,7 +201,30 @@ "settings": { "editableHeaderContent": false, "entitySet": "Pages", - "navigation": {} + "navigation": {}, + "controlConfiguration": { + "attachments/@com.sap.vocabularies.UI.v1.LineItem": { + "tableSettings": { + "type": "ResponsiveTable", + "selectionMode": "Auto", + "rowPress": ".extension.books.controller.custom.onRowPress" + } + }, + "references/@com.sap.vocabularies.UI.v1.LineItem": { + "tableSettings": { + "type": "ResponsiveTable", + "selectionMode": "Auto", + "rowPress": ".extension.books.controller.custom.onRowPress" + } + }, + "footnotes/@com.sap.vocabularies.UI.v1.LineItem": { + "tableSettings": { + "type": "ResponsiveTable", + "selectionMode": "Auto", + "rowPress": ".extension.books.controller.custom.onRowPress" + } + } + } } } }, @@ -186,7 +254,16 @@ }, "extends": { "extensions": { - "sap.ui.controllerExtensions": { + "sap.ui.controllerExtensions": { + "sap.fe.templates.ObjectPage.ObjectPageController#books::BooksDetailsList": { + "controllerName": "books.controller.custom" + }, + "sap.fe.templates.ObjectPage.ObjectPageController#books::ChaptersObjectPage": { + "controllerName": "books.controller.custom" + }, + "sap.fe.templates.ObjectPage.ObjectPageController#books::PagesObjectPage": { + "controllerName": "books.controller.custom" + } } } }, diff --git a/cap-notebook/demoapp/app/common.cds b/cap-notebook/demoapp/app/common.cds index db4d58be6..bf73758fd 100644 --- a/cap-notebook/demoapp/app/common.cds +++ b/cap-notebook/demoapp/app/common.cds @@ -64,15 +64,51 @@ annotate my.Books.attachments with @UI: { TypeNamePlural: '{i18n>Attachments}', }, LineItem : [ - {Value: fileName, @HTML5.CssDefaults: {width: '20%'}}, - {Value: content, @HTML5.CssDefaults: {width: '20%'}}, + {Value: type, @HTML5.CssDefaults: {width: '10%'}}, + {Value: fileName, @HTML5.CssDefaults: {width: '25%'}}, + {Value: content, @HTML5.CssDefaults: {width: '0%'}}, {Value: createdAt, @HTML5.CssDefaults: {width: '20%'}}, {Value: createdBy, @HTML5.CssDefaults: {width: '20%'}}, - {Value: note, @HTML5.CssDefaults: {width: '20%'}}, + {Value: note, @HTML5.CssDefaults: {width: '25%'}}, { $Type : 'UI.DataFieldForAction', Label : 'Copy Attachments', Action: 'AdminService.copyAttachments', + }, + { + $Type : 'UI.DataFieldForActionGroup', + ID : 'TableActionGroup', + Label : 'Create', + ![@UI.Hidden]: {$edmJson: {$Eq: [ {$Path: 'IsActiveEntity'}, true ]}}, + Actions: [ + { + $Type : 'UI.DataFieldForAction', + Label : 'Link', + Action: 'AdminService.createLink' + } + ] + }, + { + @UI.Hidden: {$edmJson: { + $If: [ + { $Eq: [ { $Path: 'IsActiveEntity' }, true ] }, + true, + { + $If: [ + { $Ne: [ { $Path: 'mimeType' }, 'application/internet-shortcut' ] }, + true, + false + ] + } + ] + } + }, + $Type : 'UI.DataFieldForAction', + Label : 'Edit Link', + Action: 'AdminService.editLink', + Inline: true, + IconUrl: 'sap-icon://edit', + @HTML5.CssDefaults: {width: '4%'} } ], } @@ -102,15 +138,51 @@ annotate my.Books.references with @UI: { TypeNamePlural: '{i18n>Attachments}', }, LineItem : [ - {Value: fileName, @HTML5.CssDefaults: {width: '20%'}}, - {Value: content, @HTML5.CssDefaults: {width: '20%'}}, + {Value: type, @HTML5.CssDefaults: {width: '10%'}}, + {Value: fileName, @HTML5.CssDefaults: {width: '25%'}}, + {Value: content, @HTML5.CssDefaults: {width: '0%'}}, {Value: createdAt, @HTML5.CssDefaults: {width: '20%'}}, {Value: createdBy, @HTML5.CssDefaults: {width: '20%'}}, - {Value: note, @HTML5.CssDefaults: {width: '20%'}}, + {Value: note, @HTML5.CssDefaults: {width: '25%'}}, { $Type : 'UI.DataFieldForAction', Label : 'Copy Attachments', Action: 'AdminService.copyAttachments', + }, + { + $Type : 'UI.DataFieldForActionGroup', + ID : 'TableActionGroup', + Label : 'Create', + ![@UI.Hidden]: {$edmJson: {$Eq: [ {$Path: 'IsActiveEntity'}, true ]}}, + Actions: [ + { + $Type : 'UI.DataFieldForAction', + Label : 'Link', + Action: 'AdminService.createLink' + } + ] + }, + { + @UI.Hidden: {$edmJson: { + $If: [ + { $Eq: [ { $Path: 'IsActiveEntity' }, true ] }, + true, + { + $If: [ + { $Ne: [ { $Path: 'mimeType' }, 'application/internet-shortcut' ] }, + true, + false + ] + } + ] + } + }, + $Type : 'UI.DataFieldForAction', + Label : 'Edit Link', + Action: 'AdminService.editLink', + Inline: true, + IconUrl: 'sap-icon://edit', + @HTML5.CssDefaults: {width: '4%'} } ], } @@ -135,15 +207,51 @@ annotate my.Books.footnotes with @UI: { TypeNamePlural: '{i18n>Attachments}', }, LineItem : [ - {Value: fileName, @HTML5.CssDefaults: {width: '20%'}}, - {Value: content, @HTML5.CssDefaults: {width: '20%'}}, + {Value: type, @HTML5.CssDefaults: {width: '10%'}}, + {Value: fileName, @HTML5.CssDefaults: {width: '25%'}}, + {Value: content, @HTML5.CssDefaults: {width: '0%'}}, {Value: createdAt, @HTML5.CssDefaults: {width: '20%'}}, {Value: createdBy, @HTML5.CssDefaults: {width: '20%'}}, - {Value: note, @HTML5.CssDefaults: {width: '20%'}}, + {Value: note, @HTML5.CssDefaults: {width: '25%'}}, { $Type : 'UI.DataFieldForAction', Label : 'Copy Attachments', Action: 'AdminService.copyAttachments', + }, + { + $Type : 'UI.DataFieldForActionGroup', + ID : 'TableActionGroup', + Label : 'Create', + ![@UI.Hidden]: {$edmJson: {$Eq: [ {$Path: 'IsActiveEntity'}, true ]}}, + Actions: [ + { + $Type : 'UI.DataFieldForAction', + Label : 'Link', + Action: 'AdminService.createLink' + } + ] + }, + { + @UI.Hidden: {$edmJson: { + $If: [ + { $Eq: [ { $Path: 'IsActiveEntity' }, true ] }, + true, + { + $If: [ + { $Ne: [ { $Path: 'mimeType' }, 'application/internet-shortcut' ] }, + true, + false + ] + } + ] + } + }, + $Type : 'UI.DataFieldForAction', + Label : 'Edit Link', + Action: 'AdminService.editLink', + Inline: true, + IconUrl: 'sap-icon://edit', + @HTML5.CssDefaults: {width: '4%'} } ], } @@ -168,15 +276,51 @@ annotate my.Chapters.attachments with @UI: { TypeNamePlural: '{i18n>Attachments}', }, LineItem : [ - {Value: fileName, @HTML5.CssDefaults: {width: '20%'}}, - {Value: content, @HTML5.CssDefaults: {width: '20%'}}, + {Value: type, @HTML5.CssDefaults: {width: '10%'}}, + {Value: fileName, @HTML5.CssDefaults: {width: '25%'}}, + {Value: content, @HTML5.CssDefaults: {width: '0%'}}, {Value: createdAt, @HTML5.CssDefaults: {width: '20%'}}, {Value: createdBy, @HTML5.CssDefaults: {width: '20%'}}, - {Value: note, @HTML5.CssDefaults: {width: '20%'}}, + {Value: note, @HTML5.CssDefaults: {width: '25%'}}, { $Type : 'UI.DataFieldForAction', Label : 'Copy Attachments', Action: 'AdminService.copyAttachments', + }, + { + $Type : 'UI.DataFieldForActionGroup', + ID : 'TableActionGroup', + Label : 'Create', + ![@UI.Hidden]: {$edmJson: {$Eq: [ {$Path: 'IsActiveEntity'}, true ]}}, + Actions: [ + { + $Type : 'UI.DataFieldForAction', + Label : 'Link', + Action: 'AdminService.createLink' + } + ] + }, + { + @UI.Hidden: {$edmJson: { + $If: [ + { $Eq: [ { $Path: 'IsActiveEntity' }, true ] }, + true, + { + $If: [ + { $Ne: [ { $Path: 'mimeType' }, 'application/internet-shortcut' ] }, + true, + false + ] + } + ] + } + }, + $Type : 'UI.DataFieldForAction', + Label : 'Edit Link', + Action: 'AdminService.editLink', + Inline: true, + IconUrl: 'sap-icon://edit', + @HTML5.CssDefaults: {width: '4%'} } ], } @@ -201,15 +345,120 @@ annotate my.Chapters.references with @UI: { TypeNamePlural: '{i18n>References}', }, LineItem : [ - {Value: fileName, @HTML5.CssDefaults: {width: '20%'}}, - {Value: content, @HTML5.CssDefaults: {width: '20%'}}, + {Value: type, @HTML5.CssDefaults: {width: '10%'}}, + {Value: fileName, @HTML5.CssDefaults: {width: '25%'}}, + {Value: content, @HTML5.CssDefaults: {width: '0%'}}, {Value: createdAt, @HTML5.CssDefaults: {width: '20%'}}, {Value: createdBy, @HTML5.CssDefaults: {width: '20%'}}, - {Value: note, @HTML5.CssDefaults: {width: '20%'}}, + {Value: note, @HTML5.CssDefaults: {width: '25%'}}, { $Type : 'UI.DataFieldForAction', Label : 'Copy References', Action: 'AdminService.copyAttachments', + }, + { + $Type : 'UI.DataFieldForActionGroup', + ID : 'TableActionGroup', + Label : 'Create', + ![@UI.Hidden]: {$edmJson: {$Eq: [ {$Path: 'IsActiveEntity'}, true ]}}, + Actions: [ + { + $Type : 'UI.DataFieldForAction', + Label : 'Link', + Action: 'AdminService.createLink' + } + ] + }, + { + @UI.Hidden: {$edmJson: { + $If: [ + { $Eq: [ { $Path: 'IsActiveEntity' }, true ] }, + true, + { + $If: [ + { $Ne: [ { $Path: 'mimeType' }, 'application/internet-shortcut' ] }, + true, + false + ] + } + ] + } + }, + $Type : 'UI.DataFieldForAction', + Label : 'Edit Link', + Action: 'AdminService.editLink', + Inline: true, + IconUrl: 'sap-icon://edit', + @HTML5.CssDefaults: {width: '4%'} + } + ], +} +{ + note @(title: '{i18n>Note}'); + fileName @(title: '{i18n>Filename}'); + modifiedAt @(odata.etag: null); + content + @Core.ContentDisposition: { Filename: fileName } + @(title: '{i18n>Attachment}'); + folderId @UI.Hidden; + repositoryId @UI.Hidden ; + objectId @UI.Hidden ; + mimeType @UI.Hidden; + status @UI.Hidden; +} + +annotate my.Chapters.footnotes with @UI: { + HeaderInfo: { + $Type : 'UI.HeaderInfoType', + TypeName : '{i18n>Footnote}', + TypeNamePlural: '{i18n>Footnotes}', + }, + LineItem : [ + {Value: type, @HTML5.CssDefaults: {width: '10%'}}, + {Value: fileName, @HTML5.CssDefaults: {width: '25%'}}, + {Value: content, @HTML5.CssDefaults: {width: '0%'}}, + {Value: createdAt, @HTML5.CssDefaults: {width: '20%'}}, + {Value: createdBy, @HTML5.CssDefaults: {width: '20%'}}, + {Value: note, @HTML5.CssDefaults: {width: '25%'}}, + { + $Type : 'UI.DataFieldForAction', + Label : 'Copy Footnotes', + Action: 'AdminService.copyAttachments', + }, + { + $Type : 'UI.DataFieldForActionGroup', + ID : 'TableActionGroup', + Label : 'Create', + ![@UI.Hidden]: {$edmJson: {$Eq: [ {$Path: 'IsActiveEntity'}, true ]}}, + Actions: [ + { + $Type : 'UI.DataFieldForAction', + Label : 'Link', + Action: 'AdminService.createLink' + } + ] + }, + { + @UI.Hidden: {$edmJson: { + $If: [ + { $Eq: [ { $Path: 'IsActiveEntity' }, true ] }, + true, + { + $If: [ + { $Ne: [ { $Path: 'mimeType' }, 'application/internet-shortcut' ] }, + true, + false + ] + } + ] + } + }, + $Type : 'UI.DataFieldForAction', + Label : 'Edit Link', + Action: 'AdminService.editLink', + Inline: true, + IconUrl: 'sap-icon://edit', + @HTML5.CssDefaults: {width: '4%'} } ], } @@ -234,15 +483,51 @@ annotate my.Pages.attachments with @UI: { TypeNamePlural: '{i18n>Attachments}', }, LineItem : [ - {Value: fileName, @HTML5.CssDefaults: {width: '20%'}}, - {Value: content, @HTML5.CssDefaults: {width: '20%'}}, + {Value: type, @HTML5.CssDefaults: {width: '10%'}}, + {Value: fileName, @HTML5.CssDefaults: {width: '25%'}}, + {Value: content, @HTML5.CssDefaults: {width: '0%'}}, {Value: createdAt, @HTML5.CssDefaults: {width: '20%'}}, {Value: createdBy, @HTML5.CssDefaults: {width: '20%'}}, - {Value: note, @HTML5.CssDefaults: {width: '20%'}}, + {Value: note, @HTML5.CssDefaults: {width: '25%'}}, { $Type : 'UI.DataFieldForAction', Label : 'Copy Attachments', Action: 'AdminService.copyAttachments', + }, + { + $Type : 'UI.DataFieldForActionGroup', + ID : 'TableActionGroup', + Label : 'Create', + ![@UI.Hidden]: {$edmJson: {$Eq: [ {$Path: 'IsActiveEntity'}, true ]}}, + Actions: [ + { + $Type : 'UI.DataFieldForAction', + Label : 'Link', + Action: 'AdminService.createLink' + } + ] + }, + { + @UI.Hidden: {$edmJson: { + $If: [ + { $Eq: [ { $Path: 'IsActiveEntity' }, true ] }, + true, + { + $If: [ + { $Ne: [ { $Path: 'mimeType' }, 'application/internet-shortcut' ] }, + true, + false + ] + } + ] + } + }, + $Type : 'UI.DataFieldForAction', + Label : 'Edit Link', + Action: 'AdminService.editLink', + Inline: true, + IconUrl: 'sap-icon://edit', + @HTML5.CssDefaults: {width: '4%'} } ], } @@ -267,15 +552,51 @@ annotate my.Pages.references with @UI: { TypeNamePlural: '{i18n>References}', }, LineItem : [ - {Value: fileName, @HTML5.CssDefaults: {width: '20%'}}, - {Value: content, @HTML5.CssDefaults: {width: '20%'}}, + {Value: type, @HTML5.CssDefaults: {width: '10%'}}, + {Value: fileName, @HTML5.CssDefaults: {width: '25%'}}, + {Value: content, @HTML5.CssDefaults: {width: '0%'}}, {Value: createdAt, @HTML5.CssDefaults: {width: '20%'}}, {Value: createdBy, @HTML5.CssDefaults: {width: '20%'}}, - {Value: note, @HTML5.CssDefaults: {width: '20%'}}, + {Value: note, @HTML5.CssDefaults: {width: '25%'}}, { $Type : 'UI.DataFieldForAction', Label : 'Copy References', Action: 'AdminService.copyAttachments', + }, + { + $Type : 'UI.DataFieldForActionGroup', + ID : 'TableActionGroup', + Label : 'Create', + ![@UI.Hidden]: {$edmJson: {$Eq: [ {$Path: 'IsActiveEntity'}, true ]}}, + Actions: [ + { + $Type : 'UI.DataFieldForAction', + Label : 'Link', + Action: 'AdminService.createLink' + } + ] + }, + { + @UI.Hidden: {$edmJson: { + $If: [ + { $Eq: [ { $Path: 'IsActiveEntity' }, true ] }, + true, + { + $If: [ + { $Ne: [ { $Path: 'mimeType' }, 'application/internet-shortcut' ] }, + true, + false + ] + } + ] + } + }, + $Type : 'UI.DataFieldForAction', + Label : 'Edit Link', + Action: 'AdminService.editLink', + Inline: true, + IconUrl: 'sap-icon://edit', + @HTML5.CssDefaults: {width: '4%'} } ], } @@ -300,15 +621,51 @@ annotate my.Pages.footnotes with @UI: { TypeNamePlural: '{i18n>Footnotes}', }, LineItem : [ - {Value: fileName, @HTML5.CssDefaults: {width: '20%'}}, - {Value: content, @HTML5.CssDefaults: {width: '20%'}}, + {Value: type, @HTML5.CssDefaults: {width: '10%'}}, + {Value: fileName, @HTML5.CssDefaults: {width: '25%'}}, + {Value: content, @HTML5.CssDefaults: {width: '0%'}}, {Value: createdAt, @HTML5.CssDefaults: {width: '20%'}}, {Value: createdBy, @HTML5.CssDefaults: {width: '20%'}}, - {Value: note, @HTML5.CssDefaults: {width: '20%'}}, + {Value: note, @HTML5.CssDefaults: {width: '25%'}}, { $Type : 'UI.DataFieldForAction', Label : 'Copy Footnotes', Action: 'AdminService.copyAttachments', + }, + { + $Type : 'UI.DataFieldForActionGroup', + ID : 'TableActionGroup', + Label : 'Create', + ![@UI.Hidden]: {$edmJson: {$Eq: [ {$Path: 'IsActiveEntity'}, true ]}}, + Actions: [ + { + $Type : 'UI.DataFieldForAction', + Label : 'Link', + Action: 'AdminService.createLink' + } + ] + }, + { + @UI.Hidden: {$edmJson: { + $If: [ + { $Eq: [ { $Path: 'IsActiveEntity' }, true ] }, + true, + { + $If: [ + { $Ne: [ { $Path: 'mimeType' }, 'application/internet-shortcut' ] }, + true, + false + ] + } + ] + } + }, + $Type : 'UI.DataFieldForAction', + Label : 'Edit Link', + Action: 'AdminService.editLink', + Inline: true, + IconUrl: 'sap-icon://edit', + @HTML5.CssDefaults: {width: '4%'} } ], } diff --git a/cap-notebook/demoapp/srv/admin-service.cds b/cap-notebook/demoapp/srv/admin-service.cds index 8d0a288ed..6e3ca0994 100644 --- a/cap-notebook/demoapp/srv/admin-service.cds +++ b/cap-notebook/demoapp/srv/admin-service.cds @@ -1,4 +1,5 @@ using { sap.capire.bookshop as my } from '../db/schema'; +using './attachment-extension'; service AdminService @(requires: 'admin') { @@ -9,55 +10,165 @@ service AdminService @(requires: 'admin') { entity Books.attachments as projection on my.Books.attachments actions { - // Table-level actions - @(Common.SideEffects : { TargetEntities: [''] }) - action copyAttachments(in: many $self, up__ID: String, objectIds: String); + @(Common.SideEffects : {TargetEntities: ['']},) + action copyAttachments(in:many $self, up__ID:String, objectIds:String); + + @(Common.SideEffects : {TargetEntities: ['']},) + action createLink( + in:many $self, + @mandatory @Common.Label:'Name' name: String @UI.Placeholder: 'Enter a name for the link', + @mandatory @assert.format:'^(https?:\/\/)(([a-zA-Z0-9\-]+\.)+[a-zA-Z]{2,}|localhost)(:\d{2,5})?(\/[^\s]*)?$' @Common.Label:'URL' url: String @UI.Placeholder: 'Example: https://www.example.com' + ); + + action editLink( + @mandatory @assert.format:'^(https?:\/\/)(([a-zA-Z0-9\-]+\.)+[a-zA-Z]{2,}|localhost)(:\d{2,5})?(\/[^\s]*)?$' @Common.Label:'URL' url: String @UI.Placeholder: 'Example: https://www.example.com' + ); + action openAttachment() returns String; }; entity Books.references as projection on my.Books.references actions { - // Table-level actions - @(Common.SideEffects : { TargetEntities: [''] }) - action copyAttachments(in: many $self, up__ID: String, objectIds: String); + @(Common.SideEffects : {TargetEntities: ['']},) + action copyAttachments(in:many $self, up__ID:String, objectIds:String); + + @(Common.SideEffects : {TargetEntities: ['']},) + action createLink( + in:many $self, + @mandatory @Common.Label:'Name' name: String @UI.Placeholder: 'Enter a name for the link', + @mandatory @assert.format:'^(https?:\/\/)(([a-zA-Z0-9\-]+\.)+[a-zA-Z]{2,}|localhost)(:\d{2,5})?(\/[^\s]*)?$' @Common.Label:'URL' url: String @UI.Placeholder: 'Example: https://www.example.com' + ); + + action editLink( + @mandatory @assert.format:'^(https?:\/\/)(([a-zA-Z0-9\-]+\.)+[a-zA-Z]{2,}|localhost)(:\d{2,5})?(\/[^\s]*)?$' @Common.Label:'URL' url: String @UI.Placeholder: 'Example: https://www.example.com' + ); + action openAttachment() returns String; + }; + + entity Books.footnotes as projection on my.Books.footnotes + actions { + @(Common.SideEffects : {TargetEntities: ['']},) + action copyAttachments(in:many $self, up__ID:String, objectIds:String); + + @(Common.SideEffects : {TargetEntities: ['']},) + action createLink( + in:many $self, + @mandatory @Common.Label:'Name' name: String @UI.Placeholder: 'Enter a name for the link', + @mandatory @assert.format:'^(https?:\/\/)(([a-zA-Z0-9\-]+\.)+[a-zA-Z]{2,}|localhost)(:\d{2,5})?(\/[^\s]*)?$' @Common.Label:'URL' url: String @UI.Placeholder: 'Example: https://www.example.com' + ); + + action editLink( + @mandatory @assert.format:'^(https?:\/\/)(([a-zA-Z0-9\-]+\.)+[a-zA-Z]{2,}|localhost)(:\d{2,5})?(\/[^\s]*)?$' @Common.Label:'URL' url: String @UI.Placeholder: 'Example: https://www.example.com' + ); + action openAttachment() returns String; }; entity Pages.attachments as projection on my.Pages.attachments actions { - // Table-level actions - @(Common.SideEffects : { TargetEntities: [''] }) - action copyAttachments(in: many $self, up__ID: String, objectIds: String); + @(Common.SideEffects : {TargetEntities: ['']},) + action copyAttachments(in:many $self, up__ID:String, objectIds:String); + + @(Common.SideEffects : {TargetEntities: ['']},) + action createLink( + in:many $self, + @mandatory @Common.Label:'Name' name: String @UI.Placeholder: 'Enter a name for the link', + @mandatory @assert.format:'^(https?:\/\/)(([a-zA-Z0-9\-]+\.)+[a-zA-Z]{2,}|localhost)(:\d{2,5})?(\/[^\s]*)?$' @Common.Label:'URL' url: String @UI.Placeholder: 'Example: https://www.example.com' + ); + + action editLink( + @mandatory @assert.format:'^(https?:\/\/)(([a-zA-Z0-9\-]+\.)+[a-zA-Z]{2,}|localhost)(:\d{2,5})?(\/[^\s]*)?$' @Common.Label:'URL' url: String @UI.Placeholder: 'Example: https://www.example.com' + ); + action openAttachment() returns String; }; entity Pages.references as projection on my.Pages.references actions { - // Table-level actions - @(Common.SideEffects : { TargetEntities: [''] }) - action copyAttachments(in: many $self, up__ID: String, objectIds: String); + @(Common.SideEffects : {TargetEntities: ['']},) + action copyAttachments(in:many $self, up__ID:String, objectIds:String); + + @(Common.SideEffects : {TargetEntities: ['']},) + action createLink( + in:many $self, + @mandatory @Common.Label:'Name' name: String @UI.Placeholder: 'Enter a name for the link', + @mandatory @assert.format:'^(https?:\/\/)(([a-zA-Z0-9\-]+\.)+[a-zA-Z]{2,}|localhost)(:\d{2,5})?(\/[^\s]*)?$' @Common.Label:'URL' url: String @UI.Placeholder: 'Example: https://www.example.com' + ); + + action editLink( + @mandatory @assert.format:'^(https?:\/\/)(([a-zA-Z0-9\-]+\.)+[a-zA-Z]{2,}|localhost)(:\d{2,5})?(\/[^\s]*)?$' @Common.Label:'URL' url: String @UI.Placeholder: 'Example: https://www.example.com' + ); + action openAttachment() returns String; }; // Chapters projections entity Chapters.attachments as projection on my.Chapters.attachments actions { - @(Common.SideEffects : { TargetEntities: [''] }) - action copyAttachments(in: many $self, up__ID: String, objectIds: String); + @(Common.SideEffects : {TargetEntities: ['']},) + action copyAttachments(in:many $self, up__ID:String, objectIds:String); + + @(Common.SideEffects : {TargetEntities: ['']},) + action createLink( + in:many $self, + @mandatory @Common.Label:'Name' name: String @UI.Placeholder: 'Enter a name for the link', + @mandatory @assert.format:'^(https?:\/\/)(([a-zA-Z0-9\-]+\.)+[a-zA-Z]{2,}|localhost)(:\d{2,5})?(\/[^\s]*)?$' @Common.Label:'URL' url: String @UI.Placeholder: 'Example: https://www.example.com' + ); + + action editLink( + @mandatory @assert.format:'^(https?:\/\/)(([a-zA-Z0-9\-]+\.)+[a-zA-Z]{2,}|localhost)(:\d{2,5})?(\/[^\s]*)?$' @Common.Label:'URL' url: String @UI.Placeholder: 'Example: https://www.example.com' + ); + action openAttachment() returns String; }; entity Chapters.references as projection on my.Chapters.references actions { - @(Common.SideEffects : { TargetEntities: [''] }) - action copyAttachments(in: many $self, up__ID: String, objectIds: String); + @(Common.SideEffects : {TargetEntities: ['']},) + action copyAttachments(in:many $self, up__ID:String, objectIds:String); + + @(Common.SideEffects : {TargetEntities: ['']},) + action createLink( + in:many $self, + @mandatory @Common.Label:'Name' name: String @UI.Placeholder: 'Enter a name for the link', + @mandatory @assert.format:'^(https?:\/\/)(([a-zA-Z0-9\-]+\.)+[a-zA-Z]{2,}|localhost)(:\d{2,5})?(\/[^\s]*)?$' @Common.Label:'URL' url: String @UI.Placeholder: 'Example: https://www.example.com' + ); + + action editLink( + @mandatory @assert.format:'^(https?:\/\/)(([a-zA-Z0-9\-]+\.)+[a-zA-Z]{2,}|localhost)(:\d{2,5})?(\/[^\s]*)?$' @Common.Label:'URL' url: String @UI.Placeholder: 'Example: https://www.example.com' + ); + action openAttachment() returns String; }; entity Chapters.footnotes as projection on my.Chapters.footnotes actions { - @(Common.SideEffects : { TargetEntities: [''] }) - action copyAttachments(in: many $self, up__ID: String, objectIds: String); + @(Common.SideEffects : {TargetEntities: ['']},) + action copyAttachments(in:many $self, up__ID:String, objectIds:String); + + @(Common.SideEffects : {TargetEntities: ['']},) + action createLink( + in:many $self, + @mandatory @Common.Label:'Name' name: String @UI.Placeholder: 'Enter a name for the link', + @mandatory @assert.format:'^(https?:\/\/)(([a-zA-Z0-9\-]+\.)+[a-zA-Z]{2,}|localhost)(:\d{2,5})?(\/[^\s]*)?$' @Common.Label:'URL' url: String @UI.Placeholder: 'Example: https://www.example.com' + ); + + action editLink( + @mandatory @assert.format:'^(https?:\/\/)(([a-zA-Z0-9\-]+\.)+[a-zA-Z]{2,}|localhost)(:\d{2,5})?(\/[^\s]*)?$' @Common.Label:'URL' url: String @UI.Placeholder: 'Example: https://www.example.com' + ); + action openAttachment() returns String; }; // Pages footnotes projection entity Pages.footnotes as projection on my.Pages.footnotes actions { - @(Common.SideEffects : { TargetEntities: [''] }) - action copyAttachments(in: many $self, up__ID: String, objectIds: String); + @(Common.SideEffects : {TargetEntities: ['']},) + action copyAttachments(in:many $self, up__ID:String, objectIds:String); + + @(Common.SideEffects : {TargetEntities: ['']},) + action createLink( + in:many $self, + @mandatory @Common.Label:'Name' name: String @UI.Placeholder: 'Enter a name for the link', + @mandatory @assert.format:'^(https?:\/\/)(([a-zA-Z0-9\-]+\.)+[a-zA-Z]{2,}|localhost)(:\d{2,5})?(\/[^\s]*)?$' @Common.Label:'URL' url: String @UI.Placeholder: 'Example: https://www.example.com' + ); + + action editLink( + @mandatory @assert.format:'^(https?:\/\/)(([a-zA-Z0-9\-]+\.)+[a-zA-Z]{2,}|localhost)(:\d{2,5})?(\/[^\s]*)?$' @Common.Label:'URL' url: String @UI.Placeholder: 'Example: https://www.example.com' + ); + action openAttachment() returns String; }; } diff --git a/cap-notebook/demoapp/srv/attachment-extension.cds b/cap-notebook/demoapp/srv/attachment-extension.cds index 1cafb45db..87e2dedaa 100644 --- a/cap-notebook/demoapp/srv/attachment-extension.cds +++ b/cap-notebook/demoapp/srv/attachment-extension.cds @@ -1,5 +1,5 @@ using {sap.capire.bookshop.Books, sap.capire.bookshop.Chapters, sap.capire.bookshop.Pages} from '../db/schema'; -using {sap.attachments.Attachments, sap.attachments.StatusCode} from`com.sap.cds/sdm`; +using {sap.attachments.Attachments, sap.attachments.StatusCode} from 'com.sap.cds/sdm'; using {sap,managed,sap.common.CodeList} from '@sap/cds/common'; // keep the original shallow attachments on Books From 7648e816d3d8ccdb4e31de13c3be1c259103a6e4 Mon Sep 17 00:00:00 2001 From: Rishi Kunnath <82925475+rishikunnath2747@users.noreply.github.com> Date: Tue, 21 Oct 2025 10:34:06 +0530 Subject: [PATCH 7/8] fix --- cap-notebook/demoapp/srv/admin-service.cds | 2 -- 1 file changed, 2 deletions(-) diff --git a/cap-notebook/demoapp/srv/admin-service.cds b/cap-notebook/demoapp/srv/admin-service.cds index 6e3ca0994..287bebbc7 100644 --- a/cap-notebook/demoapp/srv/admin-service.cds +++ b/cap-notebook/demoapp/srv/admin-service.cds @@ -1,6 +1,4 @@ using { sap.capire.bookshop as my } from '../db/schema'; -using './attachment-extension'; - service AdminService @(requires: 'admin') { entity Books as projection on my.Books; From b44879ad5522b34b38a740e77e2be1db26d04f0d Mon Sep 17 00:00:00 2001 From: Rishi Kunnath <82925475+rishikunnath2747@users.noreply.github.com> Date: Thu, 23 Oct 2025 14:10:38 +0530 Subject: [PATCH 8/8] Update AdminService to require 'system-user' role --- cap-notebook/demoapp/srv/admin-service.cds | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cap-notebook/demoapp/srv/admin-service.cds b/cap-notebook/demoapp/srv/admin-service.cds index 287bebbc7..a2afc28c9 100644 --- a/cap-notebook/demoapp/srv/admin-service.cds +++ b/cap-notebook/demoapp/srv/admin-service.cds @@ -1,5 +1,5 @@ using { sap.capire.bookshop as my } from '../db/schema'; -service AdminService @(requires: 'admin') { +service AdminService @(requires: ['admin','system-user']) { entity Books as projection on my.Books; entity Authors as projection on my.Authors;