@ronin/compiler 0.17.5 → 0.17.6-leo-ron-1099-experimental-390
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/dist/index.js +456 -451
- package/package.json +1 -1
package/dist/index.js
CHANGED
@@ -23,12 +23,6 @@ var RAW_FIELD_TYPES = ["string", "number", "boolean"];
|
|
23
23
|
var CURRENT_TIME_EXPRESSION = {
|
24
24
|
[QUERY_SYMBOLS.EXPRESSION]: `strftime('%Y-%m-%dT%H:%M:%f', 'now') || 'Z'`
|
25
25
|
};
|
26
|
-
var ID_EXPRESSION = (idPrefix) => ({
|
27
|
-
// Since default values in SQLite cannot rely on other columns, we unfortunately
|
28
|
-
// cannot rely on the `idPrefix` column here. Instead, we need to inject it directly
|
29
|
-
// into the expression as a static string.
|
30
|
-
[QUERY_SYMBOLS.EXPRESSION]: `'${idPrefix}_' || lower(substr(hex(randomblob(12)), 1, 16))`
|
31
|
-
});
|
32
26
|
var MOUNTING_PATH_SUFFIX = /(.*?)(\{(\d+)\})?$/;
|
33
27
|
var composeMountingPath = (single, key, mountingPath) => {
|
34
28
|
if (key === "ronin_root") {
|
@@ -465,72 +459,457 @@ var handleSelecting = (models, model, statementParams, single, instructions, opt
|
|
465
459
|
return { columns: columns.join(", "), isJoining, selectedFields };
|
466
460
|
};
|
467
461
|
|
468
|
-
//
|
469
|
-
var
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
462
|
+
// node_modules/title/dist/esm/lower-case.js
|
463
|
+
var conjunctions = [
|
464
|
+
"for",
|
465
|
+
"and",
|
466
|
+
"nor",
|
467
|
+
"but",
|
468
|
+
"or",
|
469
|
+
"yet",
|
470
|
+
"so"
|
471
|
+
];
|
472
|
+
var articles = [
|
473
|
+
"a",
|
474
|
+
"an",
|
475
|
+
"the"
|
476
|
+
];
|
477
|
+
var prepositions = [
|
478
|
+
"aboard",
|
479
|
+
"about",
|
480
|
+
"above",
|
481
|
+
"across",
|
482
|
+
"after",
|
483
|
+
"against",
|
484
|
+
"along",
|
485
|
+
"amid",
|
486
|
+
"among",
|
487
|
+
"anti",
|
488
|
+
"around",
|
489
|
+
"as",
|
490
|
+
"at",
|
491
|
+
"before",
|
492
|
+
"behind",
|
493
|
+
"below",
|
494
|
+
"beneath",
|
495
|
+
"beside",
|
496
|
+
"besides",
|
497
|
+
"between",
|
498
|
+
"beyond",
|
499
|
+
"but",
|
500
|
+
"by",
|
501
|
+
"concerning",
|
502
|
+
"considering",
|
503
|
+
"despite",
|
504
|
+
"down",
|
505
|
+
"during",
|
506
|
+
"except",
|
507
|
+
"excepting",
|
508
|
+
"excluding",
|
509
|
+
"following",
|
510
|
+
"for",
|
511
|
+
"from",
|
512
|
+
"in",
|
513
|
+
"inside",
|
514
|
+
"into",
|
515
|
+
"like",
|
516
|
+
"minus",
|
517
|
+
"near",
|
518
|
+
"of",
|
519
|
+
"off",
|
520
|
+
"on",
|
521
|
+
"onto",
|
522
|
+
"opposite",
|
523
|
+
"over",
|
524
|
+
"past",
|
525
|
+
"per",
|
526
|
+
"plus",
|
527
|
+
"regarding",
|
528
|
+
"round",
|
529
|
+
"save",
|
530
|
+
"since",
|
531
|
+
"than",
|
532
|
+
"through",
|
533
|
+
"to",
|
534
|
+
"toward",
|
535
|
+
"towards",
|
536
|
+
"under",
|
537
|
+
"underneath",
|
538
|
+
"unlike",
|
539
|
+
"until",
|
540
|
+
"up",
|
541
|
+
"upon",
|
542
|
+
"versus",
|
543
|
+
"via",
|
544
|
+
"with",
|
545
|
+
"within",
|
546
|
+
"without"
|
547
|
+
];
|
548
|
+
var lowerCase = /* @__PURE__ */ new Set([
|
549
|
+
...conjunctions,
|
550
|
+
...articles,
|
551
|
+
...prepositions
|
552
|
+
]);
|
553
|
+
|
554
|
+
// node_modules/title/dist/esm/specials.js
|
555
|
+
var specials = [
|
556
|
+
"ZEIT",
|
557
|
+
"ZEIT Inc.",
|
558
|
+
"Vercel",
|
559
|
+
"Vercel Inc.",
|
560
|
+
"CLI",
|
561
|
+
"API",
|
562
|
+
"HTTP",
|
563
|
+
"HTTPS",
|
564
|
+
"JSX",
|
565
|
+
"DNS",
|
566
|
+
"URL",
|
567
|
+
"now.sh",
|
568
|
+
"now.json",
|
569
|
+
"vercel.app",
|
570
|
+
"vercel.json",
|
571
|
+
"CI",
|
572
|
+
"CD",
|
573
|
+
"CDN",
|
574
|
+
"package.json",
|
575
|
+
"package.lock",
|
576
|
+
"yarn.lock",
|
577
|
+
"GitHub",
|
578
|
+
"GitLab",
|
579
|
+
"CSS",
|
580
|
+
"Sass",
|
581
|
+
"JS",
|
582
|
+
"JavaScript",
|
583
|
+
"TypeScript",
|
584
|
+
"HTML",
|
585
|
+
"WordPress",
|
586
|
+
"Next.js",
|
587
|
+
"Node.js",
|
588
|
+
"Webpack",
|
589
|
+
"Docker",
|
590
|
+
"Bash",
|
591
|
+
"Kubernetes",
|
592
|
+
"SWR",
|
593
|
+
"TinaCMS",
|
594
|
+
"UI",
|
595
|
+
"UX",
|
596
|
+
"TS",
|
597
|
+
"TSX",
|
598
|
+
"iPhone",
|
599
|
+
"iPad",
|
600
|
+
"watchOS",
|
601
|
+
"iOS",
|
602
|
+
"iPadOS",
|
603
|
+
"macOS",
|
604
|
+
"PHP",
|
605
|
+
"composer.json",
|
606
|
+
"composer.lock",
|
607
|
+
"CMS",
|
608
|
+
"SQL",
|
609
|
+
"C",
|
610
|
+
"C#",
|
611
|
+
"GraphQL",
|
612
|
+
"GraphiQL",
|
613
|
+
"JWT",
|
614
|
+
"JWTs"
|
615
|
+
];
|
616
|
+
|
617
|
+
// node_modules/title/dist/esm/index.js
|
618
|
+
var word = `[^\\s'\u2019\\(\\)!?;:"-]`;
|
619
|
+
var regex = new RegExp(`(?:(?:(\\s?(?:^|[.\\(\\)!?;:"-])\\s*)(${word}))|(${word}))(${word}*[\u2019']*${word}*)`, "g");
|
620
|
+
var convertToRegExp = (specials2) => specials2.map((s) => [new RegExp(`\\b${s}\\b`, "gi"), s]);
|
621
|
+
function parseMatch(match) {
|
622
|
+
const firstCharacter = match[0];
|
623
|
+
if (/\s/.test(firstCharacter)) {
|
624
|
+
return match.slice(1);
|
475
625
|
}
|
476
|
-
if (
|
477
|
-
|
478
|
-
// If records are being created, set their creation time.
|
479
|
-
...inlineDefaultInsertionFields ? { createdAt: CURRENT_TIME_EXPRESSION } : {},
|
480
|
-
// If records are being updated, bump their update time.
|
481
|
-
...queryType === "set" || inlineDefaultInsertionFields ? { updatedAt: CURRENT_TIME_EXPRESSION } : {},
|
482
|
-
// Allow for overwriting the default values provided above.
|
483
|
-
...toInstruction.ronin
|
484
|
-
};
|
485
|
-
if (Object.keys(defaults).length > 0) defaultFields.ronin = defaults;
|
626
|
+
if (/[\(\)]/.test(firstCharacter)) {
|
627
|
+
return null;
|
486
628
|
}
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
const
|
492
|
-
const
|
493
|
-
|
494
|
-
|
495
|
-
(field) => field.slug
|
496
|
-
),
|
497
|
-
...subQueryIncludedFields ? Object.keys(
|
498
|
-
flatten(subQueryIncludedFields || {})
|
499
|
-
) : []
|
500
|
-
];
|
501
|
-
for (const field of subQueryFields || []) {
|
502
|
-
getFieldFromModel(model, field, { instructionName: "to" });
|
629
|
+
return match;
|
630
|
+
}
|
631
|
+
var src_default = (str, options = {}) => {
|
632
|
+
str = str.toLowerCase().replace(regex, (m, lead = "", forced, lower, rest, offset, string) => {
|
633
|
+
const isLastWord = m.length + offset >= string.length;
|
634
|
+
const parsedMatch = parseMatch(m);
|
635
|
+
if (!parsedMatch) {
|
636
|
+
return m;
|
503
637
|
}
|
504
|
-
|
505
|
-
|
506
|
-
|
507
|
-
return
|
508
|
-
}
|
509
|
-
statement2 = `(${columns.join(", ")}) `;
|
638
|
+
if (!forced) {
|
639
|
+
const fullLower = lower + rest;
|
640
|
+
if (lowerCase.has(fullLower) && !isLastWord) {
|
641
|
+
return parsedMatch;
|
642
|
+
}
|
510
643
|
}
|
511
|
-
|
512
|
-
|
513
|
-
|
514
|
-
|
515
|
-
|
644
|
+
return lead + (lower || forced).toUpperCase() + rest;
|
645
|
+
});
|
646
|
+
const customSpecials = options.special || [];
|
647
|
+
const replace = [...specials, ...customSpecials];
|
648
|
+
const replaceRegExp = convertToRegExp(replace);
|
649
|
+
replaceRegExp.forEach(([pattern, s]) => {
|
650
|
+
str = str.replace(pattern, s);
|
651
|
+
});
|
652
|
+
return str;
|
653
|
+
};
|
654
|
+
|
655
|
+
// src/model/defaults.ts
|
656
|
+
var slugToName = (slug) => {
|
657
|
+
const name = slug.replace(/([a-z])([A-Z])/g, "$1 $2");
|
658
|
+
return src_default(name);
|
659
|
+
};
|
660
|
+
var VOWELS = ["a", "e", "i", "o", "u"];
|
661
|
+
var pluralize = (word2) => {
|
662
|
+
const lastLetter = word2.slice(-1).toLowerCase();
|
663
|
+
const secondLastLetter = word2.slice(-2, -1).toLowerCase();
|
664
|
+
if (lastLetter === "y" && !VOWELS.includes(secondLastLetter)) {
|
665
|
+
return `${word2.slice(0, -1)}ies`;
|
516
666
|
}
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
|
525
|
-
|
526
|
-
|
527
|
-
|
528
|
-
|
529
|
-
|
530
|
-
|
531
|
-
|
532
|
-
|
533
|
-
|
667
|
+
if (lastLetter === "s" || word2.slice(-2).toLowerCase() === "ch" || word2.slice(-2).toLowerCase() === "sh" || word2.slice(-2).toLowerCase() === "ex") {
|
668
|
+
return `${word2}es`;
|
669
|
+
}
|
670
|
+
return `${word2}s`;
|
671
|
+
};
|
672
|
+
var modelAttributes = [
|
673
|
+
["pluralSlug", "slug", pluralize, true],
|
674
|
+
["name", "slug", slugToName, false],
|
675
|
+
["pluralName", "pluralSlug", slugToName, false],
|
676
|
+
["idPrefix", "slug", (slug) => slug.slice(0, 3).toLowerCase(), false],
|
677
|
+
["table", "pluralSlug", convertToSnakeCase, true]
|
678
|
+
];
|
679
|
+
var getRecordIdentifier = (prefix) => {
|
680
|
+
return `${prefix}_${Array.from(crypto.getRandomValues(new Uint8Array(12))).map((b) => b.toString(16).padStart(2, "0")).join("").slice(0, 16).toLowerCase()}`;
|
681
|
+
};
|
682
|
+
var addDefaultModelAttributes = (model, isNew) => {
|
683
|
+
const copiedModel = { ...model };
|
684
|
+
if (isNew && !copiedModel.id) copiedModel.id = getRecordIdentifier("mod");
|
685
|
+
for (const [setting, base, generator, mustRegenerate] of modelAttributes) {
|
686
|
+
if (!(isNew || mustRegenerate)) continue;
|
687
|
+
if (copiedModel[setting] || !copiedModel[base]) continue;
|
688
|
+
copiedModel[setting] = generator(copiedModel[base]);
|
689
|
+
}
|
690
|
+
const newFields = copiedModel.fields || [];
|
691
|
+
if (isNew || Object.keys(newFields).length > 0) {
|
692
|
+
if (!copiedModel.identifiers) copiedModel.identifiers = {};
|
693
|
+
if (!copiedModel.identifiers.name) {
|
694
|
+
const suitableField = Object.entries(newFields).find(
|
695
|
+
([fieldSlug, field]) => field.type === "string" && field.required === true && ["name"].includes(fieldSlug)
|
696
|
+
);
|
697
|
+
copiedModel.identifiers.name = suitableField?.[0] || "id";
|
698
|
+
}
|
699
|
+
if (!copiedModel.identifiers.slug) {
|
700
|
+
const suitableField = Object.entries(newFields).find(
|
701
|
+
([fieldSlug, field]) => field.type === "string" && field.unique === true && field.required === true && ["slug", "handle"].includes(fieldSlug)
|
702
|
+
);
|
703
|
+
copiedModel.identifiers.slug = suitableField?.[0] || "id";
|
704
|
+
}
|
705
|
+
}
|
706
|
+
return copiedModel;
|
707
|
+
};
|
708
|
+
var addDefaultModelFields = (model, isNew) => {
|
709
|
+
const copiedModel = { ...model };
|
710
|
+
const existingFields = copiedModel.fields || [];
|
711
|
+
if (isNew || Object.keys(existingFields).length > 0) {
|
712
|
+
const additionalFields = Object.fromEntries(
|
713
|
+
Object.entries(getSystemFields(copiedModel.idPrefix)).filter(([newFieldSlug]) => {
|
714
|
+
return !Object.hasOwn(existingFields, newFieldSlug);
|
715
|
+
})
|
716
|
+
);
|
717
|
+
copiedModel.fields = { ...additionalFields, ...existingFields };
|
718
|
+
}
|
719
|
+
return copiedModel;
|
720
|
+
};
|
721
|
+
var addDefaultModelPresets = (list, model) => {
|
722
|
+
const defaultPresets = {};
|
723
|
+
for (const [fieldSlug, rest] of Object.entries(model.fields || {})) {
|
724
|
+
const field = { slug: fieldSlug, ...rest };
|
725
|
+
if (field.type === "link" && !fieldSlug.startsWith("ronin.")) {
|
726
|
+
const targetModel = getModelBySlug(list, field.target);
|
727
|
+
if (field.kind === "many") {
|
728
|
+
const systemModel = list.find(({ system }) => {
|
729
|
+
return system?.model === model.id && system?.associationSlug === field.slug;
|
730
|
+
});
|
731
|
+
if (!systemModel) continue;
|
732
|
+
const preset2 = {
|
733
|
+
instructions: {
|
734
|
+
// Perform a LEFT JOIN that adds the associative table.
|
735
|
+
including: {
|
736
|
+
[fieldSlug]: {
|
737
|
+
[QUERY_SYMBOLS.QUERY]: {
|
738
|
+
get: {
|
739
|
+
[systemModel.pluralSlug]: {
|
740
|
+
// ON associative_table.source = origin_model.id
|
741
|
+
with: {
|
742
|
+
source: {
|
743
|
+
[QUERY_SYMBOLS.EXPRESSION]: `${QUERY_SYMBOLS.FIELD_PARENT}id`
|
744
|
+
}
|
745
|
+
},
|
746
|
+
// Perform a LEFT JOIN that adds the target model table.
|
747
|
+
including: {
|
748
|
+
[QUERY_SYMBOLS.QUERY]: {
|
749
|
+
get: {
|
750
|
+
[targetModel.slug]: {
|
751
|
+
// ON target_model.id = associative_table.target
|
752
|
+
with: {
|
753
|
+
id: {
|
754
|
+
[QUERY_SYMBOLS.EXPRESSION]: `${QUERY_SYMBOLS.FIELD_PARENT}target`
|
755
|
+
}
|
756
|
+
}
|
757
|
+
}
|
758
|
+
}
|
759
|
+
}
|
760
|
+
},
|
761
|
+
selecting: ["**", "!source", "!target"]
|
762
|
+
}
|
763
|
+
}
|
764
|
+
}
|
765
|
+
}
|
766
|
+
}
|
767
|
+
}
|
768
|
+
};
|
769
|
+
defaultPresets[fieldSlug] = preset2;
|
770
|
+
continue;
|
771
|
+
}
|
772
|
+
const preset = {
|
773
|
+
instructions: {
|
774
|
+
including: {
|
775
|
+
[fieldSlug]: {
|
776
|
+
[QUERY_SYMBOLS.QUERY]: {
|
777
|
+
get: {
|
778
|
+
[targetModel.slug]: {
|
779
|
+
with: {
|
780
|
+
// Compare the `id` field of the related model to the link field on
|
781
|
+
// the root model (`field.slug`).
|
782
|
+
id: {
|
783
|
+
[QUERY_SYMBOLS.EXPRESSION]: `${QUERY_SYMBOLS.FIELD_PARENT}${field.slug}`
|
784
|
+
}
|
785
|
+
}
|
786
|
+
}
|
787
|
+
}
|
788
|
+
}
|
789
|
+
}
|
790
|
+
}
|
791
|
+
}
|
792
|
+
};
|
793
|
+
defaultPresets[fieldSlug] = preset;
|
794
|
+
}
|
795
|
+
}
|
796
|
+
const childModels = list.map((subModel) => {
|
797
|
+
if (subModel.system?.associationSlug) return null;
|
798
|
+
const field = Object.entries(subModel.fields).find(([fieldSlug, rest]) => {
|
799
|
+
const field2 = { slug: fieldSlug, ...rest };
|
800
|
+
return field2.type === "link" && field2.target === model.slug;
|
801
|
+
});
|
802
|
+
if (!field) return null;
|
803
|
+
return { model: subModel, field: { slug: field[0], ...field[1] } };
|
804
|
+
}).filter((match) => match !== null);
|
805
|
+
for (const childMatch of childModels) {
|
806
|
+
const { model: childModel, field: childField } = childMatch;
|
807
|
+
const pluralSlug = childModel.pluralSlug;
|
808
|
+
const presetSlug = childModel.system?.associationSlug || pluralSlug;
|
809
|
+
const preset = {
|
810
|
+
instructions: {
|
811
|
+
including: {
|
812
|
+
[presetSlug]: {
|
813
|
+
[QUERY_SYMBOLS.QUERY]: {
|
814
|
+
get: {
|
815
|
+
[pluralSlug]: {
|
816
|
+
with: {
|
817
|
+
[childField.slug]: {
|
818
|
+
[QUERY_SYMBOLS.EXPRESSION]: `${QUERY_SYMBOLS.FIELD_PARENT}id`
|
819
|
+
}
|
820
|
+
}
|
821
|
+
}
|
822
|
+
}
|
823
|
+
}
|
824
|
+
}
|
825
|
+
}
|
826
|
+
}
|
827
|
+
};
|
828
|
+
defaultPresets[presetSlug] = preset;
|
829
|
+
}
|
830
|
+
if (Object.keys(defaultPresets).length > 0) {
|
831
|
+
const existingPresets = model.presets;
|
832
|
+
const additionalPresets = Object.fromEntries(
|
833
|
+
Object.entries(defaultPresets).filter(([newPresetSlug]) => {
|
834
|
+
return !existingPresets?.[newPresetSlug];
|
835
|
+
})
|
836
|
+
);
|
837
|
+
model.presets = { ...additionalPresets, ...existingPresets };
|
838
|
+
}
|
839
|
+
return model;
|
840
|
+
};
|
841
|
+
|
842
|
+
// src/instructions/to.ts
|
843
|
+
var handleTo = (models, model, statementParams, queryType, dependencyStatements, instructions, options) => {
|
844
|
+
const { with: withInstruction, to: toInstruction } = instructions;
|
845
|
+
const defaultFields = {};
|
846
|
+
const currentTime = (/* @__PURE__ */ new Date()).toISOString();
|
847
|
+
if (queryType === "add" && options?.inlineDefaults) {
|
848
|
+
defaultFields.id = toInstruction.id || getRecordIdentifier(model.idPrefix);
|
849
|
+
}
|
850
|
+
if (queryType === "add" || queryType === "set" || toInstruction.ronin) {
|
851
|
+
const defaults = options?.inlineDefaults ? {
|
852
|
+
// If records are being created, set their creation time.
|
853
|
+
...queryType === "add" && { createdAt: currentTime },
|
854
|
+
// If records are being updated or craeted, bump their update time.
|
855
|
+
updatedAt: currentTime,
|
856
|
+
// Allow for overwriting the default values provided above.
|
857
|
+
...toInstruction.ronin
|
858
|
+
} : {
|
859
|
+
// If records are being updated, bump their update time.
|
860
|
+
...queryType === "set" ? { updatedAt: CURRENT_TIME_EXPRESSION } : {},
|
861
|
+
// Allow for overwriting the default values provided above.
|
862
|
+
...toInstruction.ronin
|
863
|
+
};
|
864
|
+
if (Object.keys(defaults).length > 0) defaultFields.ronin = defaults;
|
865
|
+
}
|
866
|
+
const symbol = getQuerySymbol(toInstruction);
|
867
|
+
if (symbol?.type === "query") {
|
868
|
+
const { queryModel: subQueryModelSlug, queryInstructions: subQueryInstructions } = splitQuery(symbol.value);
|
869
|
+
const subQueryModel = getModelBySlug(models, subQueryModelSlug);
|
870
|
+
const subQuerySelectedFields = subQueryInstructions?.selecting;
|
871
|
+
const subQueryIncludedFields = subQueryInstructions?.including;
|
872
|
+
const subQueryFields = [
|
873
|
+
...filterSelectedFields(subQueryModel, subQuerySelectedFields).map(
|
874
|
+
(field) => field.slug
|
875
|
+
),
|
876
|
+
...subQueryIncludedFields ? Object.keys(
|
877
|
+
flatten(subQueryIncludedFields || {})
|
878
|
+
) : []
|
879
|
+
];
|
880
|
+
for (const field of subQueryFields || []) {
|
881
|
+
getFieldFromModel(model, field, { instructionName: "to" });
|
882
|
+
}
|
883
|
+
let statement2 = "";
|
884
|
+
if (subQuerySelectedFields) {
|
885
|
+
const columns = subQueryFields.map((field) => {
|
886
|
+
return getFieldFromModel(model, field, { instructionName: "to" }).fieldSelector;
|
887
|
+
});
|
888
|
+
statement2 = `(${columns.join(", ")}) `;
|
889
|
+
}
|
890
|
+
statement2 += compileQueryInput(symbol.value, models, statementParams, {
|
891
|
+
// biome-ignore lint/complexity/useSimplifiedLogicExpression: This is needed.
|
892
|
+
inlineDefaults: options?.inlineDefaults || false
|
893
|
+
}).main.statement;
|
894
|
+
return statement2;
|
895
|
+
}
|
896
|
+
Object.assign(toInstruction, defaultFields);
|
897
|
+
for (const fieldSlug in toInstruction) {
|
898
|
+
if (!Object.hasOwn(toInstruction, fieldSlug)) continue;
|
899
|
+
const fieldValue = toInstruction[fieldSlug];
|
900
|
+
const fieldDetails = getFieldFromModel(
|
901
|
+
model,
|
902
|
+
fieldSlug,
|
903
|
+
{ instructionName: "to" },
|
904
|
+
false
|
905
|
+
);
|
906
|
+
if (fieldDetails?.field.type === "link" && fieldDetails.field.kind === "many") {
|
907
|
+
delete toInstruction[fieldSlug];
|
908
|
+
const associativeModelSlug = composeAssociationModelSlug(model, fieldDetails.field);
|
909
|
+
const composeStatement = (subQueryType, value) => {
|
910
|
+
const source = queryType === "add" ? toInstruction : withInstruction;
|
911
|
+
const recordDetails = { source };
|
912
|
+
if (value) recordDetails.target = value;
|
534
913
|
const query = compileQueryInput(
|
535
914
|
{
|
536
915
|
[subQueryType]: {
|
@@ -1060,386 +1439,6 @@ var handleWith = (models, model, statementParams, instruction, parentModel) => {
|
|
1060
1439
|
);
|
1061
1440
|
};
|
1062
1441
|
|
1063
|
-
// node_modules/title/dist/esm/lower-case.js
|
1064
|
-
var conjunctions = [
|
1065
|
-
"for",
|
1066
|
-
"and",
|
1067
|
-
"nor",
|
1068
|
-
"but",
|
1069
|
-
"or",
|
1070
|
-
"yet",
|
1071
|
-
"so"
|
1072
|
-
];
|
1073
|
-
var articles = [
|
1074
|
-
"a",
|
1075
|
-
"an",
|
1076
|
-
"the"
|
1077
|
-
];
|
1078
|
-
var prepositions = [
|
1079
|
-
"aboard",
|
1080
|
-
"about",
|
1081
|
-
"above",
|
1082
|
-
"across",
|
1083
|
-
"after",
|
1084
|
-
"against",
|
1085
|
-
"along",
|
1086
|
-
"amid",
|
1087
|
-
"among",
|
1088
|
-
"anti",
|
1089
|
-
"around",
|
1090
|
-
"as",
|
1091
|
-
"at",
|
1092
|
-
"before",
|
1093
|
-
"behind",
|
1094
|
-
"below",
|
1095
|
-
"beneath",
|
1096
|
-
"beside",
|
1097
|
-
"besides",
|
1098
|
-
"between",
|
1099
|
-
"beyond",
|
1100
|
-
"but",
|
1101
|
-
"by",
|
1102
|
-
"concerning",
|
1103
|
-
"considering",
|
1104
|
-
"despite",
|
1105
|
-
"down",
|
1106
|
-
"during",
|
1107
|
-
"except",
|
1108
|
-
"excepting",
|
1109
|
-
"excluding",
|
1110
|
-
"following",
|
1111
|
-
"for",
|
1112
|
-
"from",
|
1113
|
-
"in",
|
1114
|
-
"inside",
|
1115
|
-
"into",
|
1116
|
-
"like",
|
1117
|
-
"minus",
|
1118
|
-
"near",
|
1119
|
-
"of",
|
1120
|
-
"off",
|
1121
|
-
"on",
|
1122
|
-
"onto",
|
1123
|
-
"opposite",
|
1124
|
-
"over",
|
1125
|
-
"past",
|
1126
|
-
"per",
|
1127
|
-
"plus",
|
1128
|
-
"regarding",
|
1129
|
-
"round",
|
1130
|
-
"save",
|
1131
|
-
"since",
|
1132
|
-
"than",
|
1133
|
-
"through",
|
1134
|
-
"to",
|
1135
|
-
"toward",
|
1136
|
-
"towards",
|
1137
|
-
"under",
|
1138
|
-
"underneath",
|
1139
|
-
"unlike",
|
1140
|
-
"until",
|
1141
|
-
"up",
|
1142
|
-
"upon",
|
1143
|
-
"versus",
|
1144
|
-
"via",
|
1145
|
-
"with",
|
1146
|
-
"within",
|
1147
|
-
"without"
|
1148
|
-
];
|
1149
|
-
var lowerCase = /* @__PURE__ */ new Set([
|
1150
|
-
...conjunctions,
|
1151
|
-
...articles,
|
1152
|
-
...prepositions
|
1153
|
-
]);
|
1154
|
-
|
1155
|
-
// node_modules/title/dist/esm/specials.js
|
1156
|
-
var specials = [
|
1157
|
-
"ZEIT",
|
1158
|
-
"ZEIT Inc.",
|
1159
|
-
"Vercel",
|
1160
|
-
"Vercel Inc.",
|
1161
|
-
"CLI",
|
1162
|
-
"API",
|
1163
|
-
"HTTP",
|
1164
|
-
"HTTPS",
|
1165
|
-
"JSX",
|
1166
|
-
"DNS",
|
1167
|
-
"URL",
|
1168
|
-
"now.sh",
|
1169
|
-
"now.json",
|
1170
|
-
"vercel.app",
|
1171
|
-
"vercel.json",
|
1172
|
-
"CI",
|
1173
|
-
"CD",
|
1174
|
-
"CDN",
|
1175
|
-
"package.json",
|
1176
|
-
"package.lock",
|
1177
|
-
"yarn.lock",
|
1178
|
-
"GitHub",
|
1179
|
-
"GitLab",
|
1180
|
-
"CSS",
|
1181
|
-
"Sass",
|
1182
|
-
"JS",
|
1183
|
-
"JavaScript",
|
1184
|
-
"TypeScript",
|
1185
|
-
"HTML",
|
1186
|
-
"WordPress",
|
1187
|
-
"Next.js",
|
1188
|
-
"Node.js",
|
1189
|
-
"Webpack",
|
1190
|
-
"Docker",
|
1191
|
-
"Bash",
|
1192
|
-
"Kubernetes",
|
1193
|
-
"SWR",
|
1194
|
-
"TinaCMS",
|
1195
|
-
"UI",
|
1196
|
-
"UX",
|
1197
|
-
"TS",
|
1198
|
-
"TSX",
|
1199
|
-
"iPhone",
|
1200
|
-
"iPad",
|
1201
|
-
"watchOS",
|
1202
|
-
"iOS",
|
1203
|
-
"iPadOS",
|
1204
|
-
"macOS",
|
1205
|
-
"PHP",
|
1206
|
-
"composer.json",
|
1207
|
-
"composer.lock",
|
1208
|
-
"CMS",
|
1209
|
-
"SQL",
|
1210
|
-
"C",
|
1211
|
-
"C#",
|
1212
|
-
"GraphQL",
|
1213
|
-
"GraphiQL",
|
1214
|
-
"JWT",
|
1215
|
-
"JWTs"
|
1216
|
-
];
|
1217
|
-
|
1218
|
-
// node_modules/title/dist/esm/index.js
|
1219
|
-
var word = `[^\\s'\u2019\\(\\)!?;:"-]`;
|
1220
|
-
var regex = new RegExp(`(?:(?:(\\s?(?:^|[.\\(\\)!?;:"-])\\s*)(${word}))|(${word}))(${word}*[\u2019']*${word}*)`, "g");
|
1221
|
-
var convertToRegExp = (specials2) => specials2.map((s) => [new RegExp(`\\b${s}\\b`, "gi"), s]);
|
1222
|
-
function parseMatch(match) {
|
1223
|
-
const firstCharacter = match[0];
|
1224
|
-
if (/\s/.test(firstCharacter)) {
|
1225
|
-
return match.slice(1);
|
1226
|
-
}
|
1227
|
-
if (/[\(\)]/.test(firstCharacter)) {
|
1228
|
-
return null;
|
1229
|
-
}
|
1230
|
-
return match;
|
1231
|
-
}
|
1232
|
-
var src_default = (str, options = {}) => {
|
1233
|
-
str = str.toLowerCase().replace(regex, (m, lead = "", forced, lower, rest, offset, string) => {
|
1234
|
-
const isLastWord = m.length + offset >= string.length;
|
1235
|
-
const parsedMatch = parseMatch(m);
|
1236
|
-
if (!parsedMatch) {
|
1237
|
-
return m;
|
1238
|
-
}
|
1239
|
-
if (!forced) {
|
1240
|
-
const fullLower = lower + rest;
|
1241
|
-
if (lowerCase.has(fullLower) && !isLastWord) {
|
1242
|
-
return parsedMatch;
|
1243
|
-
}
|
1244
|
-
}
|
1245
|
-
return lead + (lower || forced).toUpperCase() + rest;
|
1246
|
-
});
|
1247
|
-
const customSpecials = options.special || [];
|
1248
|
-
const replace = [...specials, ...customSpecials];
|
1249
|
-
const replaceRegExp = convertToRegExp(replace);
|
1250
|
-
replaceRegExp.forEach(([pattern, s]) => {
|
1251
|
-
str = str.replace(pattern, s);
|
1252
|
-
});
|
1253
|
-
return str;
|
1254
|
-
};
|
1255
|
-
|
1256
|
-
// src/model/defaults.ts
|
1257
|
-
var slugToName = (slug) => {
|
1258
|
-
const name = slug.replace(/([a-z])([A-Z])/g, "$1 $2");
|
1259
|
-
return src_default(name);
|
1260
|
-
};
|
1261
|
-
var VOWELS = ["a", "e", "i", "o", "u"];
|
1262
|
-
var pluralize = (word2) => {
|
1263
|
-
const lastLetter = word2.slice(-1).toLowerCase();
|
1264
|
-
const secondLastLetter = word2.slice(-2, -1).toLowerCase();
|
1265
|
-
if (lastLetter === "y" && !VOWELS.includes(secondLastLetter)) {
|
1266
|
-
return `${word2.slice(0, -1)}ies`;
|
1267
|
-
}
|
1268
|
-
if (lastLetter === "s" || word2.slice(-2).toLowerCase() === "ch" || word2.slice(-2).toLowerCase() === "sh" || word2.slice(-2).toLowerCase() === "ex") {
|
1269
|
-
return `${word2}es`;
|
1270
|
-
}
|
1271
|
-
return `${word2}s`;
|
1272
|
-
};
|
1273
|
-
var modelAttributes = [
|
1274
|
-
["pluralSlug", "slug", pluralize, true],
|
1275
|
-
["name", "slug", slugToName, false],
|
1276
|
-
["pluralName", "pluralSlug", slugToName, false],
|
1277
|
-
["idPrefix", "slug", (slug) => slug.slice(0, 3).toLowerCase(), false],
|
1278
|
-
["table", "pluralSlug", convertToSnakeCase, true]
|
1279
|
-
];
|
1280
|
-
var getModelIdentifier = () => {
|
1281
|
-
return `mod_${Array.from(crypto.getRandomValues(new Uint8Array(12))).map((b) => b.toString(16).padStart(2, "0")).join("").slice(0, 16).toLowerCase()}`;
|
1282
|
-
};
|
1283
|
-
var addDefaultModelAttributes = (model, isNew) => {
|
1284
|
-
const copiedModel = { ...model };
|
1285
|
-
if (isNew && !copiedModel.id) copiedModel.id = getModelIdentifier();
|
1286
|
-
for (const [setting, base, generator, mustRegenerate] of modelAttributes) {
|
1287
|
-
if (!(isNew || mustRegenerate)) continue;
|
1288
|
-
if (copiedModel[setting] || !copiedModel[base]) continue;
|
1289
|
-
copiedModel[setting] = generator(copiedModel[base]);
|
1290
|
-
}
|
1291
|
-
const newFields = copiedModel.fields || [];
|
1292
|
-
if (isNew || Object.keys(newFields).length > 0) {
|
1293
|
-
if (!copiedModel.identifiers) copiedModel.identifiers = {};
|
1294
|
-
if (!copiedModel.identifiers.name) {
|
1295
|
-
const suitableField = Object.entries(newFields).find(
|
1296
|
-
([fieldSlug, field]) => field.type === "string" && field.required === true && ["name"].includes(fieldSlug)
|
1297
|
-
);
|
1298
|
-
copiedModel.identifiers.name = suitableField?.[0] || "id";
|
1299
|
-
}
|
1300
|
-
if (!copiedModel.identifiers.slug) {
|
1301
|
-
const suitableField = Object.entries(newFields).find(
|
1302
|
-
([fieldSlug, field]) => field.type === "string" && field.unique === true && field.required === true && ["slug", "handle"].includes(fieldSlug)
|
1303
|
-
);
|
1304
|
-
copiedModel.identifiers.slug = suitableField?.[0] || "id";
|
1305
|
-
}
|
1306
|
-
}
|
1307
|
-
return copiedModel;
|
1308
|
-
};
|
1309
|
-
var addDefaultModelFields = (model, isNew) => {
|
1310
|
-
const copiedModel = { ...model };
|
1311
|
-
const existingFields = copiedModel.fields || [];
|
1312
|
-
if (isNew || Object.keys(existingFields).length > 0) {
|
1313
|
-
const additionalFields = Object.fromEntries(
|
1314
|
-
Object.entries(getSystemFields(copiedModel.idPrefix)).filter(([newFieldSlug]) => {
|
1315
|
-
return !Object.hasOwn(existingFields, newFieldSlug);
|
1316
|
-
})
|
1317
|
-
);
|
1318
|
-
copiedModel.fields = { ...additionalFields, ...existingFields };
|
1319
|
-
}
|
1320
|
-
return copiedModel;
|
1321
|
-
};
|
1322
|
-
var addDefaultModelPresets = (list, model) => {
|
1323
|
-
const defaultPresets = {};
|
1324
|
-
for (const [fieldSlug, rest] of Object.entries(model.fields || {})) {
|
1325
|
-
const field = { slug: fieldSlug, ...rest };
|
1326
|
-
if (field.type === "link" && !fieldSlug.startsWith("ronin.")) {
|
1327
|
-
const targetModel = getModelBySlug(list, field.target);
|
1328
|
-
if (field.kind === "many") {
|
1329
|
-
const systemModel = list.find(({ system }) => {
|
1330
|
-
return system?.model === model.id && system?.associationSlug === field.slug;
|
1331
|
-
});
|
1332
|
-
if (!systemModel) continue;
|
1333
|
-
const preset2 = {
|
1334
|
-
instructions: {
|
1335
|
-
// Perform a LEFT JOIN that adds the associative table.
|
1336
|
-
including: {
|
1337
|
-
[fieldSlug]: {
|
1338
|
-
[QUERY_SYMBOLS.QUERY]: {
|
1339
|
-
get: {
|
1340
|
-
[systemModel.pluralSlug]: {
|
1341
|
-
// ON associative_table.source = origin_model.id
|
1342
|
-
with: {
|
1343
|
-
source: {
|
1344
|
-
[QUERY_SYMBOLS.EXPRESSION]: `${QUERY_SYMBOLS.FIELD_PARENT}id`
|
1345
|
-
}
|
1346
|
-
},
|
1347
|
-
// Perform a LEFT JOIN that adds the target model table.
|
1348
|
-
including: {
|
1349
|
-
[QUERY_SYMBOLS.QUERY]: {
|
1350
|
-
get: {
|
1351
|
-
[targetModel.slug]: {
|
1352
|
-
// ON target_model.id = associative_table.target
|
1353
|
-
with: {
|
1354
|
-
id: {
|
1355
|
-
[QUERY_SYMBOLS.EXPRESSION]: `${QUERY_SYMBOLS.FIELD_PARENT}target`
|
1356
|
-
}
|
1357
|
-
}
|
1358
|
-
}
|
1359
|
-
}
|
1360
|
-
}
|
1361
|
-
},
|
1362
|
-
selecting: ["**", "!source", "!target"]
|
1363
|
-
}
|
1364
|
-
}
|
1365
|
-
}
|
1366
|
-
}
|
1367
|
-
}
|
1368
|
-
}
|
1369
|
-
};
|
1370
|
-
defaultPresets[fieldSlug] = preset2;
|
1371
|
-
continue;
|
1372
|
-
}
|
1373
|
-
const preset = {
|
1374
|
-
instructions: {
|
1375
|
-
including: {
|
1376
|
-
[fieldSlug]: {
|
1377
|
-
[QUERY_SYMBOLS.QUERY]: {
|
1378
|
-
get: {
|
1379
|
-
[targetModel.slug]: {
|
1380
|
-
with: {
|
1381
|
-
// Compare the `id` field of the related model to the link field on
|
1382
|
-
// the root model (`field.slug`).
|
1383
|
-
id: {
|
1384
|
-
[QUERY_SYMBOLS.EXPRESSION]: `${QUERY_SYMBOLS.FIELD_PARENT}${field.slug}`
|
1385
|
-
}
|
1386
|
-
}
|
1387
|
-
}
|
1388
|
-
}
|
1389
|
-
}
|
1390
|
-
}
|
1391
|
-
}
|
1392
|
-
}
|
1393
|
-
};
|
1394
|
-
defaultPresets[fieldSlug] = preset;
|
1395
|
-
}
|
1396
|
-
}
|
1397
|
-
const childModels = list.map((subModel) => {
|
1398
|
-
if (subModel.system?.associationSlug) return null;
|
1399
|
-
const field = Object.entries(subModel.fields).find(([fieldSlug, rest]) => {
|
1400
|
-
const field2 = { slug: fieldSlug, ...rest };
|
1401
|
-
return field2.type === "link" && field2.target === model.slug;
|
1402
|
-
});
|
1403
|
-
if (!field) return null;
|
1404
|
-
return { model: subModel, field: { slug: field[0], ...field[1] } };
|
1405
|
-
}).filter((match) => match !== null);
|
1406
|
-
for (const childMatch of childModels) {
|
1407
|
-
const { model: childModel, field: childField } = childMatch;
|
1408
|
-
const pluralSlug = childModel.pluralSlug;
|
1409
|
-
const presetSlug = childModel.system?.associationSlug || pluralSlug;
|
1410
|
-
const preset = {
|
1411
|
-
instructions: {
|
1412
|
-
including: {
|
1413
|
-
[presetSlug]: {
|
1414
|
-
[QUERY_SYMBOLS.QUERY]: {
|
1415
|
-
get: {
|
1416
|
-
[pluralSlug]: {
|
1417
|
-
with: {
|
1418
|
-
[childField.slug]: {
|
1419
|
-
[QUERY_SYMBOLS.EXPRESSION]: `${QUERY_SYMBOLS.FIELD_PARENT}id`
|
1420
|
-
}
|
1421
|
-
}
|
1422
|
-
}
|
1423
|
-
}
|
1424
|
-
}
|
1425
|
-
}
|
1426
|
-
}
|
1427
|
-
}
|
1428
|
-
};
|
1429
|
-
defaultPresets[presetSlug] = preset;
|
1430
|
-
}
|
1431
|
-
if (Object.keys(defaultPresets).length > 0) {
|
1432
|
-
const existingPresets = model.presets;
|
1433
|
-
const additionalPresets = Object.fromEntries(
|
1434
|
-
Object.entries(defaultPresets).filter(([newPresetSlug]) => {
|
1435
|
-
return !existingPresets?.[newPresetSlug];
|
1436
|
-
})
|
1437
|
-
);
|
1438
|
-
model.presets = { ...additionalPresets, ...existingPresets };
|
1439
|
-
}
|
1440
|
-
return model;
|
1441
|
-
};
|
1442
|
-
|
1443
1442
|
// src/model/index.ts
|
1444
1443
|
var getModelBySlug = (models, slug) => {
|
1445
1444
|
const model = models.find((model2) => {
|
@@ -1500,7 +1499,12 @@ var getSystemFields = (idPrefix) => ({
|
|
1500
1499
|
id: {
|
1501
1500
|
name: "ID",
|
1502
1501
|
type: "string",
|
1503
|
-
defaultValue:
|
1502
|
+
defaultValue: {
|
1503
|
+
// Since default values in SQLite cannot rely on other columns, we unfortunately
|
1504
|
+
// cannot rely on the `idPrefix` column here. Instead, we need to inject it
|
1505
|
+
// directly into the expression as a static string.
|
1506
|
+
[QUERY_SYMBOLS.EXPRESSION]: `'${idPrefix}_' || lower(substr(hex(randomblob(12)), 1, 16))`
|
1507
|
+
}
|
1504
1508
|
},
|
1505
1509
|
"ronin.createdAt": {
|
1506
1510
|
name: "RONIN - Created At",
|
@@ -2004,10 +2008,11 @@ var transformMetaQuery = (models, dependencyStatements, statementParams, query,
|
|
2004
2008
|
let json;
|
2005
2009
|
switch (action) {
|
2006
2010
|
case "create": {
|
2007
|
-
const
|
2008
|
-
|
2011
|
+
const { slug: slug2, ...entityValue } = jsonValue;
|
2012
|
+
const value = prepareStatementValue(statementParams, entityValue);
|
2013
|
+
json = `json_insert(${field}, '$.${slug2}', ${value})`;
|
2009
2014
|
if (!existingModel[pluralType]) existingModel[pluralType] = {};
|
2010
|
-
existingModel[pluralType][
|
2015
|
+
existingModel[pluralType][slug2] = jsonValue;
|
2011
2016
|
break;
|
2012
2017
|
}
|
2013
2018
|
case "alter": {
|