@majordigital/create-acorn 1.5.2 → 1.5.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/create-acorn.mjs +77 -75
- package/package.json +1 -1
package/bin/create-acorn.mjs
CHANGED
|
@@ -335,11 +335,21 @@ async function setupStoryblok(projectName) {
|
|
|
335
335
|
console.log('');
|
|
336
336
|
}
|
|
337
337
|
|
|
338
|
-
async function setupDato(
|
|
338
|
+
async function setupDato() {
|
|
339
339
|
console.log('Setting up DatoCMS...');
|
|
340
340
|
console.log('');
|
|
341
|
+
console.log('NOTE: DatoCMS does not support creating projects via CLI or API.');
|
|
342
|
+
console.log('You must create your DatoCMS project in the dashboard before continuing:');
|
|
343
|
+
console.log(' https://www.datocms.com/dashboard');
|
|
344
|
+
console.log('');
|
|
345
|
+
console.log('Once your project is ready, provide the Full-access API token below');
|
|
346
|
+
console.log('and we will automatically scaffold all models (Page, Hero, Button, Layout, etc.).');
|
|
347
|
+
console.log('');
|
|
348
|
+
console.log('Token location: Settings > API Tokens > Full-access API token');
|
|
349
|
+
console.log('Make sure "Access the Content Management API" is enabled and the role is Admin.');
|
|
350
|
+
console.log('');
|
|
341
351
|
|
|
342
|
-
const
|
|
352
|
+
const apiToken = await ask('Paste your Full-access API token (or press Enter to skip)');
|
|
343
353
|
console.log('');
|
|
344
354
|
|
|
345
355
|
// Install DatoCMS dependencies
|
|
@@ -356,33 +366,6 @@ async function setupDato(projectName) {
|
|
|
356
366
|
]);
|
|
357
367
|
console.log('');
|
|
358
368
|
|
|
359
|
-
// --- DatoCMS Project Connection & Model Scaffolding ---
|
|
360
|
-
const hasExisting = await ask('Do you already have a DatoCMS project? (y/n)', 'n');
|
|
361
|
-
const isExisting = hasExisting.toLowerCase() === 'y' || hasExisting.toLowerCase() === 'yes';
|
|
362
|
-
|
|
363
|
-
if (!isExisting) {
|
|
364
|
-
console.log('');
|
|
365
|
-
console.log('NOTE: DatoCMS does not support creating projects via CLI or API.');
|
|
366
|
-
console.log('You need to create the project manually first:');
|
|
367
|
-
console.log('');
|
|
368
|
-
console.log(' 1. Go to https://www.datocms.com/dashboard');
|
|
369
|
-
console.log(' 2. Click "New Project" and create your project');
|
|
370
|
-
console.log(' 3. Go to Settings > API Tokens > Full-access API token');
|
|
371
|
-
console.log(' 4. Copy the token and paste it below');
|
|
372
|
-
console.log('');
|
|
373
|
-
console.log('If you provide the token, we will automatically scaffold all models');
|
|
374
|
-
console.log('(Page, Hero, Button, Layout, etc.) in your DatoCMS project.');
|
|
375
|
-
console.log('');
|
|
376
|
-
} else {
|
|
377
|
-
console.log('');
|
|
378
|
-
console.log('Great! We can automatically scaffold all models in your project.');
|
|
379
|
-
console.log('Grab your Full-access API token from:');
|
|
380
|
-
console.log(' Settings > API Tokens > Full-access API token');
|
|
381
|
-
console.log('');
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
const apiToken = await ask('Paste your Full-access API token (or press Enter to skip)');
|
|
385
|
-
|
|
386
369
|
if (apiToken) {
|
|
387
370
|
console.log('');
|
|
388
371
|
console.log('Scaffolding DatoCMS models...');
|
|
@@ -571,22 +554,41 @@ async function scaffoldDatoModels(apiToken) {
|
|
|
571
554
|
const { buildClient } = await import('@datocms/cma-client-node');
|
|
572
555
|
const client = buildClient({ apiToken });
|
|
573
556
|
|
|
557
|
+
// Fetch existing models so we can skip duplicates (handles re-runs)
|
|
558
|
+
const existingTypes = await client.itemTypes.list();
|
|
559
|
+
const existingKeys = new Set(existingTypes.map(t => t.api_key));
|
|
560
|
+
|
|
561
|
+
async function findOrCreateItemType(config) {
|
|
562
|
+
if (existingKeys.has(config.api_key)) {
|
|
563
|
+
console.log(` Skipping ${config.name} (already exists)...`);
|
|
564
|
+
return existingTypes.find(t => t.api_key === config.api_key);
|
|
565
|
+
}
|
|
566
|
+
return client.itemTypes.create(config);
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
async function findOrCreateField(modelId, config) {
|
|
570
|
+
const existingFields = await client.fields.list(modelId);
|
|
571
|
+
const existing = existingFields.find(f => f.api_key === config.api_key);
|
|
572
|
+
if (existing) return existing;
|
|
573
|
+
return client.fields.create(modelId, config);
|
|
574
|
+
}
|
|
575
|
+
|
|
574
576
|
// --- Block models (must be created first so we can reference them) ---
|
|
575
577
|
|
|
576
578
|
// Button block
|
|
577
579
|
console.log(' Creating Button block...');
|
|
578
|
-
const buttonBlock = await
|
|
580
|
+
const buttonBlock = await findOrCreateItemType({
|
|
579
581
|
name: 'Button',
|
|
580
582
|
api_key: 'button',
|
|
581
583
|
modular_block: true,
|
|
582
584
|
});
|
|
583
|
-
await
|
|
585
|
+
await findOrCreateField(buttonBlock.id, {
|
|
584
586
|
label: 'Text',
|
|
585
587
|
field_type: 'string',
|
|
586
588
|
api_key: 'text',
|
|
587
589
|
validators: { required: {} },
|
|
588
590
|
});
|
|
589
|
-
await
|
|
591
|
+
await findOrCreateField(buttonBlock.id, {
|
|
590
592
|
label: 'Variant',
|
|
591
593
|
field_type: 'string',
|
|
592
594
|
api_key: 'variant',
|
|
@@ -601,7 +603,7 @@ async function scaffoldDatoModels(apiToken) {
|
|
|
601
603
|
]},
|
|
602
604
|
},
|
|
603
605
|
});
|
|
604
|
-
await
|
|
606
|
+
await findOrCreateField(buttonBlock.id, {
|
|
605
607
|
label: 'Link',
|
|
606
608
|
field_type: 'json',
|
|
607
609
|
api_key: 'link',
|
|
@@ -609,23 +611,23 @@ async function scaffoldDatoModels(apiToken) {
|
|
|
609
611
|
|
|
610
612
|
// Hero block
|
|
611
613
|
console.log(' Creating Hero block...');
|
|
612
|
-
const heroBlock = await
|
|
614
|
+
const heroBlock = await findOrCreateItemType({
|
|
613
615
|
name: 'Hero',
|
|
614
616
|
api_key: 'hero',
|
|
615
617
|
modular_block: true,
|
|
616
618
|
});
|
|
617
|
-
await
|
|
619
|
+
await findOrCreateField(heroBlock.id, {
|
|
618
620
|
label: 'Heading',
|
|
619
621
|
field_type: 'string',
|
|
620
622
|
api_key: 'heading',
|
|
621
623
|
validators: { required: {} },
|
|
622
624
|
});
|
|
623
|
-
await
|
|
625
|
+
await findOrCreateField(heroBlock.id, {
|
|
624
626
|
label: 'Eyebrow',
|
|
625
627
|
field_type: 'string',
|
|
626
628
|
api_key: 'eyebrow',
|
|
627
629
|
});
|
|
628
|
-
await
|
|
630
|
+
await findOrCreateField(heroBlock.id, {
|
|
629
631
|
label: 'Content',
|
|
630
632
|
field_type: 'text',
|
|
631
633
|
api_key: 'content',
|
|
@@ -635,7 +637,7 @@ async function scaffoldDatoModels(apiToken) {
|
|
|
635
637
|
parameters: {},
|
|
636
638
|
},
|
|
637
639
|
});
|
|
638
|
-
await
|
|
640
|
+
await findOrCreateField(heroBlock.id, {
|
|
639
641
|
label: 'Layout',
|
|
640
642
|
field_type: 'string',
|
|
641
643
|
api_key: 'layout',
|
|
@@ -650,7 +652,7 @@ async function scaffoldDatoModels(apiToken) {
|
|
|
650
652
|
]},
|
|
651
653
|
},
|
|
652
654
|
});
|
|
653
|
-
await
|
|
655
|
+
await findOrCreateField(heroBlock.id, {
|
|
654
656
|
label: 'Theme',
|
|
655
657
|
field_type: 'string',
|
|
656
658
|
api_key: 'theme',
|
|
@@ -664,12 +666,12 @@ async function scaffoldDatoModels(apiToken) {
|
|
|
664
666
|
]},
|
|
665
667
|
},
|
|
666
668
|
});
|
|
667
|
-
await
|
|
669
|
+
await findOrCreateField(heroBlock.id, {
|
|
668
670
|
label: 'Image',
|
|
669
671
|
field_type: 'file',
|
|
670
672
|
api_key: 'image',
|
|
671
673
|
});
|
|
672
|
-
await
|
|
674
|
+
await findOrCreateField(heroBlock.id, {
|
|
673
675
|
label: 'Actions',
|
|
674
676
|
field_type: 'rich_text',
|
|
675
677
|
api_key: 'actions',
|
|
@@ -680,12 +682,12 @@ async function scaffoldDatoModels(apiToken) {
|
|
|
680
682
|
|
|
681
683
|
// MenuItem block
|
|
682
684
|
console.log(' Creating MenuItem block...');
|
|
683
|
-
const menuItemBlock = await
|
|
685
|
+
const menuItemBlock = await findOrCreateItemType({
|
|
684
686
|
name: 'Menu Item',
|
|
685
687
|
api_key: 'menu_item',
|
|
686
688
|
modular_block: true,
|
|
687
689
|
});
|
|
688
|
-
await
|
|
690
|
+
await findOrCreateField(menuItemBlock.id, {
|
|
689
691
|
label: 'Heading',
|
|
690
692
|
field_type: 'string',
|
|
691
693
|
api_key: 'heading',
|
|
@@ -696,40 +698,40 @@ async function scaffoldDatoModels(apiToken) {
|
|
|
696
698
|
|
|
697
699
|
// Page model
|
|
698
700
|
console.log(' Creating Page model...');
|
|
699
|
-
const pageModel = await
|
|
701
|
+
const pageModel = await findOrCreateItemType({
|
|
700
702
|
name: 'Page',
|
|
701
703
|
api_key: 'page',
|
|
702
704
|
draft_mode_active: true,
|
|
703
705
|
});
|
|
704
|
-
await
|
|
706
|
+
const pageHeadingField = await findOrCreateField(pageModel.id, {
|
|
705
707
|
label: 'Heading',
|
|
706
708
|
field_type: 'string',
|
|
707
709
|
api_key: 'heading',
|
|
708
710
|
validators: { required: {} },
|
|
709
711
|
});
|
|
710
|
-
await
|
|
712
|
+
await findOrCreateField(pageModel.id, {
|
|
711
713
|
label: 'Description',
|
|
712
714
|
field_type: 'text',
|
|
713
715
|
api_key: 'description',
|
|
714
716
|
});
|
|
715
|
-
await
|
|
717
|
+
await findOrCreateField(pageModel.id, {
|
|
716
718
|
label: 'Slug',
|
|
717
719
|
field_type: 'slug',
|
|
718
720
|
api_key: 'slug',
|
|
719
721
|
validators: {
|
|
720
722
|
required: {},
|
|
721
|
-
slug_title_field: { title_field_id:
|
|
723
|
+
slug_title_field: { title_field_id: pageHeadingField.id },
|
|
722
724
|
},
|
|
723
725
|
});
|
|
724
|
-
await
|
|
726
|
+
await findOrCreateField(pageModel.id, {
|
|
725
727
|
label: 'Parent Page',
|
|
726
728
|
field_type: 'link',
|
|
727
729
|
api_key: 'parent_page',
|
|
728
730
|
validators: {
|
|
729
|
-
item_item_type: {
|
|
731
|
+
item_item_type: { item_types: [pageModel.id] },
|
|
730
732
|
},
|
|
731
733
|
});
|
|
732
|
-
await
|
|
734
|
+
await findOrCreateField(pageModel.id, {
|
|
733
735
|
label: 'Body',
|
|
734
736
|
field_type: 'rich_text',
|
|
735
737
|
api_key: 'body',
|
|
@@ -739,61 +741,61 @@ async function scaffoldDatoModels(apiToken) {
|
|
|
739
741
|
});
|
|
740
742
|
|
|
741
743
|
// Add target link to MenuItem (now that Page exists)
|
|
742
|
-
await
|
|
744
|
+
await findOrCreateField(menuItemBlock.id, {
|
|
743
745
|
label: 'Target',
|
|
744
746
|
field_type: 'link',
|
|
745
747
|
api_key: 'target',
|
|
746
748
|
validators: {
|
|
747
|
-
item_item_type: {
|
|
749
|
+
item_item_type: { item_types: [pageModel.id] },
|
|
748
750
|
},
|
|
749
751
|
});
|
|
750
752
|
|
|
751
753
|
// Case Study model
|
|
752
754
|
console.log(' Creating Case Study model...');
|
|
753
|
-
const caseStudyModel = await
|
|
755
|
+
const caseStudyModel = await findOrCreateItemType({
|
|
754
756
|
name: 'Case Study',
|
|
755
757
|
api_key: 'case_study',
|
|
756
758
|
draft_mode_active: true,
|
|
757
759
|
});
|
|
758
|
-
await
|
|
760
|
+
const caseStudyTitleField = await findOrCreateField(caseStudyModel.id, {
|
|
759
761
|
label: 'Title',
|
|
760
762
|
field_type: 'string',
|
|
761
763
|
api_key: 'title',
|
|
762
764
|
validators: { required: {} },
|
|
763
765
|
});
|
|
764
|
-
await
|
|
766
|
+
await findOrCreateField(caseStudyModel.id, {
|
|
765
767
|
label: 'Slug',
|
|
766
768
|
field_type: 'slug',
|
|
767
769
|
api_key: 'slug',
|
|
768
770
|
validators: {
|
|
769
771
|
required: {},
|
|
770
|
-
slug_title_field: { title_field_id:
|
|
772
|
+
slug_title_field: { title_field_id: caseStudyTitleField.id },
|
|
771
773
|
},
|
|
772
774
|
});
|
|
773
775
|
|
|
774
776
|
// Legal Page model
|
|
775
777
|
console.log(' Creating Legal Page model...');
|
|
776
|
-
const legalPageModel = await
|
|
778
|
+
const legalPageModel = await findOrCreateItemType({
|
|
777
779
|
name: 'Legal Page',
|
|
778
780
|
api_key: 'legal_page',
|
|
779
781
|
draft_mode_active: true,
|
|
780
782
|
});
|
|
781
|
-
await
|
|
783
|
+
const legalTitleField = await findOrCreateField(legalPageModel.id, {
|
|
782
784
|
label: 'Title',
|
|
783
785
|
field_type: 'string',
|
|
784
786
|
api_key: 'title',
|
|
785
787
|
validators: { required: {} },
|
|
786
788
|
});
|
|
787
|
-
await
|
|
789
|
+
await findOrCreateField(legalPageModel.id, {
|
|
788
790
|
label: 'Slug',
|
|
789
791
|
field_type: 'slug',
|
|
790
792
|
api_key: 'slug',
|
|
791
793
|
validators: {
|
|
792
794
|
required: {},
|
|
793
|
-
slug_title_field: { title_field_id:
|
|
795
|
+
slug_title_field: { title_field_id: legalTitleField.id },
|
|
794
796
|
},
|
|
795
797
|
});
|
|
796
|
-
await
|
|
798
|
+
await findOrCreateField(legalPageModel.id, {
|
|
797
799
|
label: 'Download',
|
|
798
800
|
field_type: 'file',
|
|
799
801
|
api_key: 'download',
|
|
@@ -801,35 +803,35 @@ async function scaffoldDatoModels(apiToken) {
|
|
|
801
803
|
|
|
802
804
|
// Post model
|
|
803
805
|
console.log(' Creating Post model...');
|
|
804
|
-
const postModel = await
|
|
806
|
+
const postModel = await findOrCreateItemType({
|
|
805
807
|
name: 'Post',
|
|
806
808
|
api_key: 'post',
|
|
807
809
|
draft_mode_active: true,
|
|
808
810
|
});
|
|
809
|
-
await
|
|
811
|
+
const postTitleField = await findOrCreateField(postModel.id, {
|
|
810
812
|
label: 'Title',
|
|
811
813
|
field_type: 'string',
|
|
812
814
|
api_key: 'title',
|
|
813
815
|
validators: { required: {} },
|
|
814
816
|
});
|
|
815
|
-
await
|
|
817
|
+
await findOrCreateField(postModel.id, {
|
|
816
818
|
label: 'Slug',
|
|
817
819
|
field_type: 'slug',
|
|
818
820
|
api_key: 'slug',
|
|
819
821
|
validators: {
|
|
820
822
|
required: {},
|
|
821
|
-
slug_title_field: { title_field_id:
|
|
823
|
+
slug_title_field: { title_field_id: postTitleField.id },
|
|
822
824
|
},
|
|
823
825
|
});
|
|
824
826
|
|
|
825
827
|
// Case Studies Listing (singleton)
|
|
826
828
|
console.log(' Creating Case Studies Listing singleton...');
|
|
827
|
-
const caseStudiesListing = await
|
|
829
|
+
const caseStudiesListing = await findOrCreateItemType({
|
|
828
830
|
name: 'Case Studies Listing',
|
|
829
831
|
api_key: 'case_studies_listing',
|
|
830
832
|
singleton: true,
|
|
831
833
|
});
|
|
832
|
-
await
|
|
834
|
+
await findOrCreateField(caseStudiesListing.id, {
|
|
833
835
|
label: 'Slug',
|
|
834
836
|
field_type: 'string',
|
|
835
837
|
api_key: 'slug',
|
|
@@ -838,12 +840,12 @@ async function scaffoldDatoModels(apiToken) {
|
|
|
838
840
|
|
|
839
841
|
// Post Listing (singleton)
|
|
840
842
|
console.log(' Creating Post Listing singleton...');
|
|
841
|
-
const postListing = await
|
|
843
|
+
const postListing = await findOrCreateItemType({
|
|
842
844
|
name: 'Post Listing',
|
|
843
845
|
api_key: 'post_listing',
|
|
844
846
|
singleton: true,
|
|
845
847
|
});
|
|
846
|
-
await
|
|
848
|
+
await findOrCreateField(postListing.id, {
|
|
847
849
|
label: 'Slug',
|
|
848
850
|
field_type: 'string',
|
|
849
851
|
api_key: 'slug',
|
|
@@ -852,12 +854,12 @@ async function scaffoldDatoModels(apiToken) {
|
|
|
852
854
|
|
|
853
855
|
// Layout (singleton)
|
|
854
856
|
console.log(' Creating Layout singleton...');
|
|
855
|
-
const layoutModel = await
|
|
857
|
+
const layoutModel = await findOrCreateItemType({
|
|
856
858
|
name: 'Layout',
|
|
857
859
|
api_key: 'layout',
|
|
858
860
|
singleton: true,
|
|
859
861
|
});
|
|
860
|
-
await
|
|
862
|
+
await findOrCreateField(layoutModel.id, {
|
|
861
863
|
label: 'Navigation',
|
|
862
864
|
field_type: 'rich_text',
|
|
863
865
|
api_key: 'navigation',
|
|
@@ -865,7 +867,7 @@ async function scaffoldDatoModels(apiToken) {
|
|
|
865
867
|
rich_text_blocks: { item_types: [menuItemBlock.id] },
|
|
866
868
|
},
|
|
867
869
|
});
|
|
868
|
-
await
|
|
870
|
+
await findOrCreateField(layoutModel.id, {
|
|
869
871
|
label: 'Footer Navigation',
|
|
870
872
|
field_type: 'rich_text',
|
|
871
873
|
api_key: 'footer_navigation',
|
|
@@ -873,7 +875,7 @@ async function scaffoldDatoModels(apiToken) {
|
|
|
873
875
|
rich_text_blocks: { item_types: [menuItemBlock.id] },
|
|
874
876
|
},
|
|
875
877
|
});
|
|
876
|
-
await
|
|
878
|
+
await findOrCreateField(layoutModel.id, {
|
|
877
879
|
label: 'Copyright',
|
|
878
880
|
field_type: 'string',
|
|
879
881
|
api_key: 'copyright',
|
|
@@ -1125,7 +1127,7 @@ NEXT_PUBLIC_SITE_URL=
|
|
|
1125
1127
|
} else if (selection.key === 'storyblok') {
|
|
1126
1128
|
await setupStoryblok(projectDir);
|
|
1127
1129
|
} else if (selection.key === 'dato') {
|
|
1128
|
-
await setupDato(
|
|
1130
|
+
await setupDato();
|
|
1129
1131
|
}
|
|
1130
1132
|
}
|
|
1131
1133
|
|
package/package.json
CHANGED