srcpack 0.2.0 → 0.3.0

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/cli.js CHANGED
@@ -5547,6 +5547,334 @@ var require_out4 = __commonJS((exports, module) => {
5547
5547
  module.exports = FastGlob;
5548
5548
  });
5549
5549
 
5550
+ // node_modules/ignore/index.js
5551
+ var require_ignore = __commonJS((exports, module) => {
5552
+ function makeArray(subject) {
5553
+ return Array.isArray(subject) ? subject : [subject];
5554
+ }
5555
+ var UNDEFINED = undefined;
5556
+ var EMPTY = "";
5557
+ var SPACE = " ";
5558
+ var ESCAPE = "\\";
5559
+ var REGEX_TEST_BLANK_LINE = /^\s+$/;
5560
+ var REGEX_INVALID_TRAILING_BACKSLASH = /(?:[^\\]|^)\\$/;
5561
+ var REGEX_REPLACE_LEADING_EXCAPED_EXCLAMATION = /^\\!/;
5562
+ var REGEX_REPLACE_LEADING_EXCAPED_HASH = /^\\#/;
5563
+ var REGEX_SPLITALL_CRLF = /\r?\n/g;
5564
+ var REGEX_TEST_INVALID_PATH = /^\.{0,2}\/|^\.{1,2}$/;
5565
+ var REGEX_TEST_TRAILING_SLASH = /\/$/;
5566
+ var SLASH = "/";
5567
+ var TMP_KEY_IGNORE = "node-ignore";
5568
+ if (typeof Symbol !== "undefined") {
5569
+ TMP_KEY_IGNORE = Symbol.for("node-ignore");
5570
+ }
5571
+ var KEY_IGNORE = TMP_KEY_IGNORE;
5572
+ var define2 = (object, key, value) => {
5573
+ Object.defineProperty(object, key, { value });
5574
+ return value;
5575
+ };
5576
+ var REGEX_REGEXP_RANGE = /([0-z])-([0-z])/g;
5577
+ var RETURN_FALSE = () => false;
5578
+ var sanitizeRange = (range) => range.replace(REGEX_REGEXP_RANGE, (match, from, to) => from.charCodeAt(0) <= to.charCodeAt(0) ? match : EMPTY);
5579
+ var negateRange = (range) => range.startsWith("!") || range.startsWith("\\^") ? `^${range.slice(range[0] === "!" ? 1 : 2)}` : range;
5580
+ var cleanRangeBackSlash = (slashes) => {
5581
+ const { length } = slashes;
5582
+ return slashes.slice(0, length - length % 2);
5583
+ };
5584
+ var REPLACERS = [
5585
+ [
5586
+ /^\uFEFF/,
5587
+ () => EMPTY
5588
+ ],
5589
+ [
5590
+ /((?:\\\\)*?)(\\?\s+)$/,
5591
+ (_, m1, m2) => m1 + (m2.indexOf("\\") === 0 ? SPACE : EMPTY)
5592
+ ],
5593
+ [
5594
+ /(\\+?)\s/g,
5595
+ (_, m1) => {
5596
+ const { length } = m1;
5597
+ return m1.slice(0, length - length % 2) + SPACE;
5598
+ }
5599
+ ],
5600
+ [
5601
+ /[\\$.|*+(){^]/g,
5602
+ (match) => `\\${match}`
5603
+ ],
5604
+ [
5605
+ /(?!\\)\?/g,
5606
+ () => "[^/]"
5607
+ ],
5608
+ [
5609
+ /^\//,
5610
+ () => "^"
5611
+ ],
5612
+ [
5613
+ /\//g,
5614
+ () => "\\/"
5615
+ ],
5616
+ [
5617
+ /^\^*(?:\\\*\\\*\\\/)+/,
5618
+ () => "^(?:.*\\/)?"
5619
+ ],
5620
+ [
5621
+ /^(?=[^^])/,
5622
+ function startingReplacer() {
5623
+ return !/\/(?!$)/.test(this) ? "(?:^|\\/)" : "^";
5624
+ }
5625
+ ],
5626
+ [
5627
+ /\\\/\\\*\\\*(?=\\\/|$)/g,
5628
+ (_, index, str) => index + 6 < str.length ? "(?:\\/[^\\/]+)*" : "\\/.+"
5629
+ ],
5630
+ [
5631
+ /(^|[^\\]+)(\\\*)+(?=.+)/g,
5632
+ (_, p1, p2) => {
5633
+ const unescaped = p2.replace(/\\\*/g, "[^\\/]*");
5634
+ return p1 + unescaped;
5635
+ }
5636
+ ],
5637
+ [
5638
+ /\\\\\\(?=[$.|*+(){^])/g,
5639
+ () => ESCAPE
5640
+ ],
5641
+ [
5642
+ /\\\\/g,
5643
+ () => ESCAPE
5644
+ ],
5645
+ [
5646
+ /(\\)?\[([^\]/]*?)(\\*)($|\])/g,
5647
+ (match, leadEscape, range, endEscape, close) => leadEscape === ESCAPE ? `\\[${range}${cleanRangeBackSlash(endEscape)}${close}` : close === "]" ? endEscape.length % 2 === 0 ? `[${negateRange(sanitizeRange(range))}${endEscape}]` : "[]" : "[]"
5648
+ ],
5649
+ [
5650
+ /(?:[^*])$/,
5651
+ (match) => /\/$/.test(match) ? `${match}$` : `${match}(?=$|\\/$)`
5652
+ ]
5653
+ ];
5654
+ var REGEX_REPLACE_TRAILING_WILDCARD = /(^|\\\/)?\\\*$/;
5655
+ var MODE_IGNORE = "regex";
5656
+ var MODE_CHECK_IGNORE = "checkRegex";
5657
+ var UNDERSCORE = "_";
5658
+ var TRAILING_WILD_CARD_REPLACERS = {
5659
+ [MODE_IGNORE](_, p1) {
5660
+ const prefix = p1 ? `${p1}[^/]+` : "[^/]*";
5661
+ return `${prefix}(?=$|\\/$)`;
5662
+ },
5663
+ [MODE_CHECK_IGNORE](_, p1) {
5664
+ const prefix = p1 ? `${p1}[^/]*` : "[^/]*";
5665
+ return `${prefix}(?=$|\\/$)`;
5666
+ }
5667
+ };
5668
+ var makeRegexPrefix = (pattern) => REPLACERS.reduce((prev, [matcher, replacer]) => prev.replace(matcher, replacer.bind(pattern)), pattern);
5669
+ var isString = (subject) => typeof subject === "string";
5670
+ var checkPattern = (pattern) => pattern && isString(pattern) && !REGEX_TEST_BLANK_LINE.test(pattern) && !REGEX_INVALID_TRAILING_BACKSLASH.test(pattern) && pattern.indexOf("#") !== 0;
5671
+ var splitPattern = (pattern) => pattern.split(REGEX_SPLITALL_CRLF).filter(Boolean);
5672
+
5673
+ class IgnoreRule {
5674
+ constructor(pattern, mark, body, ignoreCase, negative, prefix) {
5675
+ this.pattern = pattern;
5676
+ this.mark = mark;
5677
+ this.negative = negative;
5678
+ define2(this, "body", body);
5679
+ define2(this, "ignoreCase", ignoreCase);
5680
+ define2(this, "regexPrefix", prefix);
5681
+ }
5682
+ get regex() {
5683
+ const key = UNDERSCORE + MODE_IGNORE;
5684
+ if (this[key]) {
5685
+ return this[key];
5686
+ }
5687
+ return this._make(MODE_IGNORE, key);
5688
+ }
5689
+ get checkRegex() {
5690
+ const key = UNDERSCORE + MODE_CHECK_IGNORE;
5691
+ if (this[key]) {
5692
+ return this[key];
5693
+ }
5694
+ return this._make(MODE_CHECK_IGNORE, key);
5695
+ }
5696
+ _make(mode, key) {
5697
+ const str = this.regexPrefix.replace(REGEX_REPLACE_TRAILING_WILDCARD, TRAILING_WILD_CARD_REPLACERS[mode]);
5698
+ const regex2 = this.ignoreCase ? new RegExp(str, "i") : new RegExp(str);
5699
+ return define2(this, key, regex2);
5700
+ }
5701
+ }
5702
+ var createRule = ({
5703
+ pattern,
5704
+ mark
5705
+ }, ignoreCase) => {
5706
+ let negative = false;
5707
+ let body = pattern;
5708
+ if (body.indexOf("!") === 0) {
5709
+ negative = true;
5710
+ body = body.substr(1);
5711
+ }
5712
+ body = body.replace(REGEX_REPLACE_LEADING_EXCAPED_EXCLAMATION, "!").replace(REGEX_REPLACE_LEADING_EXCAPED_HASH, "#");
5713
+ const regexPrefix = makeRegexPrefix(body);
5714
+ return new IgnoreRule(pattern, mark, body, ignoreCase, negative, regexPrefix);
5715
+ };
5716
+
5717
+ class RuleManager {
5718
+ constructor(ignoreCase) {
5719
+ this._ignoreCase = ignoreCase;
5720
+ this._rules = [];
5721
+ }
5722
+ _add(pattern) {
5723
+ if (pattern && pattern[KEY_IGNORE]) {
5724
+ this._rules = this._rules.concat(pattern._rules._rules);
5725
+ this._added = true;
5726
+ return;
5727
+ }
5728
+ if (isString(pattern)) {
5729
+ pattern = {
5730
+ pattern
5731
+ };
5732
+ }
5733
+ if (checkPattern(pattern.pattern)) {
5734
+ const rule = createRule(pattern, this._ignoreCase);
5735
+ this._added = true;
5736
+ this._rules.push(rule);
5737
+ }
5738
+ }
5739
+ add(pattern) {
5740
+ this._added = false;
5741
+ makeArray(isString(pattern) ? splitPattern(pattern) : pattern).forEach(this._add, this);
5742
+ return this._added;
5743
+ }
5744
+ test(path, checkUnignored, mode) {
5745
+ let ignored = false;
5746
+ let unignored = false;
5747
+ let matchedRule;
5748
+ this._rules.forEach((rule) => {
5749
+ const { negative } = rule;
5750
+ if (unignored === negative && ignored !== unignored || negative && !ignored && !unignored && !checkUnignored) {
5751
+ return;
5752
+ }
5753
+ const matched = rule[mode].test(path);
5754
+ if (!matched) {
5755
+ return;
5756
+ }
5757
+ ignored = !negative;
5758
+ unignored = negative;
5759
+ matchedRule = negative ? UNDEFINED : rule;
5760
+ });
5761
+ const ret = {
5762
+ ignored,
5763
+ unignored
5764
+ };
5765
+ if (matchedRule) {
5766
+ ret.rule = matchedRule;
5767
+ }
5768
+ return ret;
5769
+ }
5770
+ }
5771
+ var throwError = (message, Ctor) => {
5772
+ throw new Ctor(message);
5773
+ };
5774
+ var checkPath = (path, originalPath, doThrow) => {
5775
+ if (!isString(path)) {
5776
+ return doThrow(`path must be a string, but got \`${originalPath}\``, TypeError);
5777
+ }
5778
+ if (!path) {
5779
+ return doThrow(`path must not be empty`, TypeError);
5780
+ }
5781
+ if (checkPath.isNotRelative(path)) {
5782
+ const r = "`path.relative()`d";
5783
+ return doThrow(`path should be a ${r} string, but got "${originalPath}"`, RangeError);
5784
+ }
5785
+ return true;
5786
+ };
5787
+ var isNotRelative = (path) => REGEX_TEST_INVALID_PATH.test(path);
5788
+ checkPath.isNotRelative = isNotRelative;
5789
+ checkPath.convert = (p) => p;
5790
+
5791
+ class Ignore {
5792
+ constructor({
5793
+ ignorecase = true,
5794
+ ignoreCase = ignorecase,
5795
+ allowRelativePaths = false
5796
+ } = {}) {
5797
+ define2(this, KEY_IGNORE, true);
5798
+ this._rules = new RuleManager(ignoreCase);
5799
+ this._strictPathCheck = !allowRelativePaths;
5800
+ this._initCache();
5801
+ }
5802
+ _initCache() {
5803
+ this._ignoreCache = Object.create(null);
5804
+ this._testCache = Object.create(null);
5805
+ }
5806
+ add(pattern) {
5807
+ if (this._rules.add(pattern)) {
5808
+ this._initCache();
5809
+ }
5810
+ return this;
5811
+ }
5812
+ addPattern(pattern) {
5813
+ return this.add(pattern);
5814
+ }
5815
+ _test(originalPath, cache, checkUnignored, slices) {
5816
+ const path = originalPath && checkPath.convert(originalPath);
5817
+ checkPath(path, originalPath, this._strictPathCheck ? throwError : RETURN_FALSE);
5818
+ return this._t(path, cache, checkUnignored, slices);
5819
+ }
5820
+ checkIgnore(path) {
5821
+ if (!REGEX_TEST_TRAILING_SLASH.test(path)) {
5822
+ return this.test(path);
5823
+ }
5824
+ const slices = path.split(SLASH).filter(Boolean);
5825
+ slices.pop();
5826
+ if (slices.length) {
5827
+ const parent = this._t(slices.join(SLASH) + SLASH, this._testCache, true, slices);
5828
+ if (parent.ignored) {
5829
+ return parent;
5830
+ }
5831
+ }
5832
+ return this._rules.test(path, false, MODE_CHECK_IGNORE);
5833
+ }
5834
+ _t(path, cache, checkUnignored, slices) {
5835
+ if (path in cache) {
5836
+ return cache[path];
5837
+ }
5838
+ if (!slices) {
5839
+ slices = path.split(SLASH).filter(Boolean);
5840
+ }
5841
+ slices.pop();
5842
+ if (!slices.length) {
5843
+ return cache[path] = this._rules.test(path, checkUnignored, MODE_IGNORE);
5844
+ }
5845
+ const parent = this._t(slices.join(SLASH) + SLASH, cache, checkUnignored, slices);
5846
+ return cache[path] = parent.ignored ? parent : this._rules.test(path, checkUnignored, MODE_IGNORE);
5847
+ }
5848
+ ignores(path) {
5849
+ return this._test(path, this._ignoreCache, false).ignored;
5850
+ }
5851
+ createFilter() {
5852
+ return (path) => !this.ignores(path);
5853
+ }
5854
+ filter(paths) {
5855
+ return makeArray(paths).filter(this.createFilter());
5856
+ }
5857
+ test(path) {
5858
+ return this._test(path, this._testCache, true);
5859
+ }
5860
+ }
5861
+ var factory = (options) => new Ignore(options);
5862
+ var isPathValid = (path) => checkPath(path && checkPath.convert(path), path, RETURN_FALSE);
5863
+ var setupWindows = () => {
5864
+ const makePosix = (str) => /^\\\\\?\\/.test(str) || /["<>|\u0000-\u001F]+/u.test(str) ? str : str.replace(/\\/g, "/");
5865
+ checkPath.convert = makePosix;
5866
+ const REGEX_TEST_WINDOWS_PATH_ABSOLUTE = /^[a-z]:\//i;
5867
+ checkPath.isNotRelative = (path) => REGEX_TEST_WINDOWS_PATH_ABSOLUTE.test(path) || isNotRelative(path);
5868
+ };
5869
+ if (typeof process !== "undefined" && process.platform === "win32") {
5870
+ setupWindows();
5871
+ }
5872
+ module.exports = factory;
5873
+ factory.default = factory;
5874
+ module.exports.isPathValid = isPathValid;
5875
+ define2(module.exports, Symbol.for("setupWindows"), setupWindows);
5876
+ });
5877
+
5550
5878
  // node_modules/picomatch/lib/constants.js
5551
5879
  var require_constants4 = __commonJS((exports, module) => {
5552
5880
  var WIN_SLASH = "\\\\/";
@@ -7243,334 +7571,6 @@ var require_picomatch3 = __commonJS((exports, module) => {
7243
7571
  module.exports = picomatch;
7244
7572
  });
7245
7573
 
7246
- // node_modules/ignore/index.js
7247
- var require_ignore = __commonJS((exports, module) => {
7248
- function makeArray(subject) {
7249
- return Array.isArray(subject) ? subject : [subject];
7250
- }
7251
- var UNDEFINED = undefined;
7252
- var EMPTY = "";
7253
- var SPACE = " ";
7254
- var ESCAPE = "\\";
7255
- var REGEX_TEST_BLANK_LINE = /^\s+$/;
7256
- var REGEX_INVALID_TRAILING_BACKSLASH = /(?:[^\\]|^)\\$/;
7257
- var REGEX_REPLACE_LEADING_EXCAPED_EXCLAMATION = /^\\!/;
7258
- var REGEX_REPLACE_LEADING_EXCAPED_HASH = /^\\#/;
7259
- var REGEX_SPLITALL_CRLF = /\r?\n/g;
7260
- var REGEX_TEST_INVALID_PATH = /^\.{0,2}\/|^\.{1,2}$/;
7261
- var REGEX_TEST_TRAILING_SLASH = /\/$/;
7262
- var SLASH = "/";
7263
- var TMP_KEY_IGNORE = "node-ignore";
7264
- if (typeof Symbol !== "undefined") {
7265
- TMP_KEY_IGNORE = Symbol.for("node-ignore");
7266
- }
7267
- var KEY_IGNORE = TMP_KEY_IGNORE;
7268
- var define2 = (object, key, value) => {
7269
- Object.defineProperty(object, key, { value });
7270
- return value;
7271
- };
7272
- var REGEX_REGEXP_RANGE = /([0-z])-([0-z])/g;
7273
- var RETURN_FALSE = () => false;
7274
- var sanitizeRange = (range) => range.replace(REGEX_REGEXP_RANGE, (match, from, to) => from.charCodeAt(0) <= to.charCodeAt(0) ? match : EMPTY);
7275
- var negateRange = (range) => range.startsWith("!") || range.startsWith("\\^") ? `^${range.slice(range[0] === "!" ? 1 : 2)}` : range;
7276
- var cleanRangeBackSlash = (slashes) => {
7277
- const { length } = slashes;
7278
- return slashes.slice(0, length - length % 2);
7279
- };
7280
- var REPLACERS = [
7281
- [
7282
- /^\uFEFF/,
7283
- () => EMPTY
7284
- ],
7285
- [
7286
- /((?:\\\\)*?)(\\?\s+)$/,
7287
- (_, m1, m2) => m1 + (m2.indexOf("\\") === 0 ? SPACE : EMPTY)
7288
- ],
7289
- [
7290
- /(\\+?)\s/g,
7291
- (_, m1) => {
7292
- const { length } = m1;
7293
- return m1.slice(0, length - length % 2) + SPACE;
7294
- }
7295
- ],
7296
- [
7297
- /[\\$.|*+(){^]/g,
7298
- (match) => `\\${match}`
7299
- ],
7300
- [
7301
- /(?!\\)\?/g,
7302
- () => "[^/]"
7303
- ],
7304
- [
7305
- /^\//,
7306
- () => "^"
7307
- ],
7308
- [
7309
- /\//g,
7310
- () => "\\/"
7311
- ],
7312
- [
7313
- /^\^*(?:\\\*\\\*\\\/)+/,
7314
- () => "^(?:.*\\/)?"
7315
- ],
7316
- [
7317
- /^(?=[^^])/,
7318
- function startingReplacer() {
7319
- return !/\/(?!$)/.test(this) ? "(?:^|\\/)" : "^";
7320
- }
7321
- ],
7322
- [
7323
- /\\\/\\\*\\\*(?=\\\/|$)/g,
7324
- (_, index, str) => index + 6 < str.length ? "(?:\\/[^\\/]+)*" : "\\/.+"
7325
- ],
7326
- [
7327
- /(^|[^\\]+)(\\\*)+(?=.+)/g,
7328
- (_, p1, p2) => {
7329
- const unescaped = p2.replace(/\\\*/g, "[^\\/]*");
7330
- return p1 + unescaped;
7331
- }
7332
- ],
7333
- [
7334
- /\\\\\\(?=[$.|*+(){^])/g,
7335
- () => ESCAPE
7336
- ],
7337
- [
7338
- /\\\\/g,
7339
- () => ESCAPE
7340
- ],
7341
- [
7342
- /(\\)?\[([^\]/]*?)(\\*)($|\])/g,
7343
- (match, leadEscape, range, endEscape, close) => leadEscape === ESCAPE ? `\\[${range}${cleanRangeBackSlash(endEscape)}${close}` : close === "]" ? endEscape.length % 2 === 0 ? `[${negateRange(sanitizeRange(range))}${endEscape}]` : "[]" : "[]"
7344
- ],
7345
- [
7346
- /(?:[^*])$/,
7347
- (match) => /\/$/.test(match) ? `${match}$` : `${match}(?=$|\\/$)`
7348
- ]
7349
- ];
7350
- var REGEX_REPLACE_TRAILING_WILDCARD = /(^|\\\/)?\\\*$/;
7351
- var MODE_IGNORE = "regex";
7352
- var MODE_CHECK_IGNORE = "checkRegex";
7353
- var UNDERSCORE = "_";
7354
- var TRAILING_WILD_CARD_REPLACERS = {
7355
- [MODE_IGNORE](_, p1) {
7356
- const prefix = p1 ? `${p1}[^/]+` : "[^/]*";
7357
- return `${prefix}(?=$|\\/$)`;
7358
- },
7359
- [MODE_CHECK_IGNORE](_, p1) {
7360
- const prefix = p1 ? `${p1}[^/]*` : "[^/]*";
7361
- return `${prefix}(?=$|\\/$)`;
7362
- }
7363
- };
7364
- var makeRegexPrefix = (pattern) => REPLACERS.reduce((prev, [matcher, replacer]) => prev.replace(matcher, replacer.bind(pattern)), pattern);
7365
- var isString = (subject) => typeof subject === "string";
7366
- var checkPattern = (pattern) => pattern && isString(pattern) && !REGEX_TEST_BLANK_LINE.test(pattern) && !REGEX_INVALID_TRAILING_BACKSLASH.test(pattern) && pattern.indexOf("#") !== 0;
7367
- var splitPattern = (pattern) => pattern.split(REGEX_SPLITALL_CRLF).filter(Boolean);
7368
-
7369
- class IgnoreRule {
7370
- constructor(pattern, mark, body, ignoreCase, negative, prefix) {
7371
- this.pattern = pattern;
7372
- this.mark = mark;
7373
- this.negative = negative;
7374
- define2(this, "body", body);
7375
- define2(this, "ignoreCase", ignoreCase);
7376
- define2(this, "regexPrefix", prefix);
7377
- }
7378
- get regex() {
7379
- const key = UNDERSCORE + MODE_IGNORE;
7380
- if (this[key]) {
7381
- return this[key];
7382
- }
7383
- return this._make(MODE_IGNORE, key);
7384
- }
7385
- get checkRegex() {
7386
- const key = UNDERSCORE + MODE_CHECK_IGNORE;
7387
- if (this[key]) {
7388
- return this[key];
7389
- }
7390
- return this._make(MODE_CHECK_IGNORE, key);
7391
- }
7392
- _make(mode, key) {
7393
- const str = this.regexPrefix.replace(REGEX_REPLACE_TRAILING_WILDCARD, TRAILING_WILD_CARD_REPLACERS[mode]);
7394
- const regex2 = this.ignoreCase ? new RegExp(str, "i") : new RegExp(str);
7395
- return define2(this, key, regex2);
7396
- }
7397
- }
7398
- var createRule = ({
7399
- pattern,
7400
- mark
7401
- }, ignoreCase) => {
7402
- let negative = false;
7403
- let body = pattern;
7404
- if (body.indexOf("!") === 0) {
7405
- negative = true;
7406
- body = body.substr(1);
7407
- }
7408
- body = body.replace(REGEX_REPLACE_LEADING_EXCAPED_EXCLAMATION, "!").replace(REGEX_REPLACE_LEADING_EXCAPED_HASH, "#");
7409
- const regexPrefix = makeRegexPrefix(body);
7410
- return new IgnoreRule(pattern, mark, body, ignoreCase, negative, regexPrefix);
7411
- };
7412
-
7413
- class RuleManager {
7414
- constructor(ignoreCase) {
7415
- this._ignoreCase = ignoreCase;
7416
- this._rules = [];
7417
- }
7418
- _add(pattern) {
7419
- if (pattern && pattern[KEY_IGNORE]) {
7420
- this._rules = this._rules.concat(pattern._rules._rules);
7421
- this._added = true;
7422
- return;
7423
- }
7424
- if (isString(pattern)) {
7425
- pattern = {
7426
- pattern
7427
- };
7428
- }
7429
- if (checkPattern(pattern.pattern)) {
7430
- const rule = createRule(pattern, this._ignoreCase);
7431
- this._added = true;
7432
- this._rules.push(rule);
7433
- }
7434
- }
7435
- add(pattern) {
7436
- this._added = false;
7437
- makeArray(isString(pattern) ? splitPattern(pattern) : pattern).forEach(this._add, this);
7438
- return this._added;
7439
- }
7440
- test(path, checkUnignored, mode) {
7441
- let ignored = false;
7442
- let unignored = false;
7443
- let matchedRule;
7444
- this._rules.forEach((rule) => {
7445
- const { negative } = rule;
7446
- if (unignored === negative && ignored !== unignored || negative && !ignored && !unignored && !checkUnignored) {
7447
- return;
7448
- }
7449
- const matched = rule[mode].test(path);
7450
- if (!matched) {
7451
- return;
7452
- }
7453
- ignored = !negative;
7454
- unignored = negative;
7455
- matchedRule = negative ? UNDEFINED : rule;
7456
- });
7457
- const ret = {
7458
- ignored,
7459
- unignored
7460
- };
7461
- if (matchedRule) {
7462
- ret.rule = matchedRule;
7463
- }
7464
- return ret;
7465
- }
7466
- }
7467
- var throwError = (message, Ctor) => {
7468
- throw new Ctor(message);
7469
- };
7470
- var checkPath = (path, originalPath, doThrow) => {
7471
- if (!isString(path)) {
7472
- return doThrow(`path must be a string, but got \`${originalPath}\``, TypeError);
7473
- }
7474
- if (!path) {
7475
- return doThrow(`path must not be empty`, TypeError);
7476
- }
7477
- if (checkPath.isNotRelative(path)) {
7478
- const r = "`path.relative()`d";
7479
- return doThrow(`path should be a ${r} string, but got "${originalPath}"`, RangeError);
7480
- }
7481
- return true;
7482
- };
7483
- var isNotRelative = (path) => REGEX_TEST_INVALID_PATH.test(path);
7484
- checkPath.isNotRelative = isNotRelative;
7485
- checkPath.convert = (p) => p;
7486
-
7487
- class Ignore {
7488
- constructor({
7489
- ignorecase = true,
7490
- ignoreCase = ignorecase,
7491
- allowRelativePaths = false
7492
- } = {}) {
7493
- define2(this, KEY_IGNORE, true);
7494
- this._rules = new RuleManager(ignoreCase);
7495
- this._strictPathCheck = !allowRelativePaths;
7496
- this._initCache();
7497
- }
7498
- _initCache() {
7499
- this._ignoreCache = Object.create(null);
7500
- this._testCache = Object.create(null);
7501
- }
7502
- add(pattern) {
7503
- if (this._rules.add(pattern)) {
7504
- this._initCache();
7505
- }
7506
- return this;
7507
- }
7508
- addPattern(pattern) {
7509
- return this.add(pattern);
7510
- }
7511
- _test(originalPath, cache, checkUnignored, slices) {
7512
- const path = originalPath && checkPath.convert(originalPath);
7513
- checkPath(path, originalPath, this._strictPathCheck ? throwError : RETURN_FALSE);
7514
- return this._t(path, cache, checkUnignored, slices);
7515
- }
7516
- checkIgnore(path) {
7517
- if (!REGEX_TEST_TRAILING_SLASH.test(path)) {
7518
- return this.test(path);
7519
- }
7520
- const slices = path.split(SLASH).filter(Boolean);
7521
- slices.pop();
7522
- if (slices.length) {
7523
- const parent = this._t(slices.join(SLASH) + SLASH, this._testCache, true, slices);
7524
- if (parent.ignored) {
7525
- return parent;
7526
- }
7527
- }
7528
- return this._rules.test(path, false, MODE_CHECK_IGNORE);
7529
- }
7530
- _t(path, cache, checkUnignored, slices) {
7531
- if (path in cache) {
7532
- return cache[path];
7533
- }
7534
- if (!slices) {
7535
- slices = path.split(SLASH).filter(Boolean);
7536
- }
7537
- slices.pop();
7538
- if (!slices.length) {
7539
- return cache[path] = this._rules.test(path, checkUnignored, MODE_IGNORE);
7540
- }
7541
- const parent = this._t(slices.join(SLASH) + SLASH, cache, checkUnignored, slices);
7542
- return cache[path] = parent.ignored ? parent : this._rules.test(path, checkUnignored, MODE_IGNORE);
7543
- }
7544
- ignores(path) {
7545
- return this._test(path, this._ignoreCache, false).ignored;
7546
- }
7547
- createFilter() {
7548
- return (path) => !this.ignores(path);
7549
- }
7550
- filter(paths) {
7551
- return makeArray(paths).filter(this.createFilter());
7552
- }
7553
- test(path) {
7554
- return this._test(path, this._testCache, true);
7555
- }
7556
- }
7557
- var factory = (options) => new Ignore(options);
7558
- var isPathValid = (path) => checkPath(path && checkPath.convert(path), path, RETURN_FALSE);
7559
- var setupWindows = () => {
7560
- const makePosix = (str) => /^\\\\\?\\/.test(str) || /["<>|\u0000-\u001F]+/u.test(str) ? str : str.replace(/\\/g, "/");
7561
- checkPath.convert = makePosix;
7562
- const REGEX_TEST_WINDOWS_PATH_ABSOLUTE = /^[a-z]:\//i;
7563
- checkPath.isNotRelative = (path) => REGEX_TEST_WINDOWS_PATH_ABSOLUTE.test(path) || isNotRelative(path);
7564
- };
7565
- if (typeof process !== "undefined" && process.platform === "win32") {
7566
- setupWindows();
7567
- }
7568
- module.exports = factory;
7569
- factory.default = factory;
7570
- module.exports.isPathValid = isPathValid;
7571
- define2(module.exports, Symbol.for("setupWindows"), setupWindows);
7572
- });
7573
-
7574
7574
  // node_modules/js-yaml/lib/common.js
7575
7575
  var require_common3 = __commonJS((exports, module) => {
7576
7576
  function isNothing(subject) {
@@ -36604,8 +36604,24 @@ var require_src9 = __commonJS((exports, module) => {
36604
36604
  });
36605
36605
 
36606
36606
  // src/cli.ts
36607
- import { mkdir as mkdir3, readdir, readFile as readFile5, rm, writeFile as writeFile4 } from "node:fs/promises";
36608
- import { dirname as dirname3, isAbsolute as isAbsolute2, join as join6, relative, resolve as resolve3, sep as sep2 } from "node:path";
36607
+ import {
36608
+ mkdir as mkdir3,
36609
+ readdir,
36610
+ readFile as readFile5,
36611
+ realpath,
36612
+ rename as rename2,
36613
+ rm,
36614
+ writeFile as writeFile4
36615
+ } from "node:fs/promises";
36616
+ import {
36617
+ basename as basename3,
36618
+ dirname as dirname4,
36619
+ isAbsolute as isAbsolute2,
36620
+ join as join6,
36621
+ relative,
36622
+ resolve as resolve3,
36623
+ sep as sep2
36624
+ } from "node:path";
36609
36625
 
36610
36626
  // node_modules/ora/index.js
36611
36627
  import process8 from "node:process";
@@ -40012,10 +40028,10 @@ function ora(options) {
40012
40028
 
40013
40029
  // src/bundle.ts
40014
40030
  var import_fast_glob = __toESM(require_out4(), 1);
40015
- var import_picomatch = __toESM(require_picomatch3(), 1);
40016
40031
  var import_ignore = __toESM(require_ignore(), 1);
40032
+ var import_picomatch = __toESM(require_picomatch3(), 1);
40017
40033
  import { lstat, open, readFile } from "node:fs/promises";
40018
- import { isAbsolute, join as join2, resolve as resolve2, sep } from "node:path";
40034
+ import { dirname, isAbsolute, join as join2, resolve as resolve2, sep } from "node:path";
40019
40035
 
40020
40036
  // src/config.ts
40021
40037
  var import_cosmiconfig = __toESM(require_dist(), 1);
@@ -54309,29 +54325,57 @@ var PatternsSchema = exports_external.union([
54309
54325
  exports_external.string().min(1),
54310
54326
  exports_external.array(exports_external.string().min(1)).min(1)
54311
54327
  ]);
54328
+ var IdentifierSchema = exports_external.string().trim().min(1);
54329
+ var BundleNameSchema = exports_external.string().regex(/^[A-Za-z0-9][A-Za-z0-9._-]*$/, "Bundle name must start with a letter or digit and contain only letters, digits, dot, underscore or hyphen");
54330
+ var LinearSourceSchema = exports_external.union([
54331
+ IdentifierSchema,
54332
+ exports_external.strictObject({
54333
+ team: IdentifierSchema,
54334
+ project: IdentifierSchema.optional(),
54335
+ includeClosed: exports_external.boolean().default(false)
54336
+ })
54337
+ ]);
54312
54338
  var BundleConfigSchema = exports_external.union([
54313
54339
  exports_external.string().min(1),
54314
54340
  exports_external.array(exports_external.string().min(1)).min(1),
54315
- exports_external.object({
54316
- include: PatternsSchema,
54317
- outfile: exports_external.string().optional(),
54341
+ exports_external.strictObject({
54342
+ include: PatternsSchema.optional(),
54343
+ linear: LinearSourceSchema.optional(),
54344
+ outfile: exports_external.string().min(1).optional(),
54318
54345
  index: exports_external.boolean().default(true),
54319
54346
  prompt: exports_external.string().optional()
54347
+ }).refine((bundle) => bundle.include || bundle.linear, {
54348
+ message: 'Bundle needs a source: "include" patterns, "linear", or both'
54320
54349
  })
54321
54350
  ]);
54322
- var UploadConfigSchema = exports_external.object({
54351
+ var UploadConfigSchema = exports_external.strictObject({
54323
54352
  provider: exports_external.literal("gdrive"),
54324
- folderId: exports_external.string().optional(),
54325
- clientId: exports_external.string().min(1),
54326
- clientSecret: exports_external.string().min(1),
54353
+ folderId: IdentifierSchema.optional(),
54354
+ clientId: IdentifierSchema,
54355
+ clientSecret: IdentifierSchema,
54327
54356
  exclude: exports_external.array(exports_external.string()).optional()
54328
54357
  });
54329
- var ConfigSchema = exports_external.object({
54358
+ var ConfigSchema = exports_external.strictObject({
54330
54359
  root: exports_external.string().default(""),
54331
54360
  outDir: exports_external.string().default(".srcpack"),
54332
54361
  emptyOutDir: exports_external.boolean().optional(),
54333
54362
  upload: exports_external.union([UploadConfigSchema, exports_external.array(UploadConfigSchema).min(1)]).optional(),
54334
- bundles: exports_external.record(exports_external.string(), BundleConfigSchema)
54363
+ bundles: exports_external.record(BundleNameSchema, BundleConfigSchema)
54364
+ }).superRefine((config2, ctx) => {
54365
+ const uploads = config2.upload ? Array.isArray(config2.upload) ? config2.upload : [config2.upload] : [];
54366
+ const names = new Set(Object.keys(config2.bundles));
54367
+ uploads.forEach((upload, i) => {
54368
+ const path = Array.isArray(config2.upload) ? ["upload", i, "exclude"] : ["upload", "exclude"];
54369
+ for (const name of upload.exclude ?? []) {
54370
+ if (!names.has(name)) {
54371
+ ctx.addIssue({
54372
+ code: "custom",
54373
+ path,
54374
+ message: `Unknown bundle "${name}"`
54375
+ });
54376
+ }
54377
+ }
54378
+ });
54335
54379
  });
54336
54380
  function defineConfig(config2) {
54337
54381
  return config2;
@@ -54343,13 +54387,22 @@ class ConfigError extends Error {
54343
54387
  this.name = "ConfigError";
54344
54388
  }
54345
54389
  }
54390
+ function flatten(issue2, prefix = []) {
54391
+ const path = [...prefix, ...issue2.path];
54392
+ const nested = issue2.code === "invalid_union" ? issue2.errors?.flat() : issue2.code === "invalid_key" ? issue2.issues : undefined;
54393
+ return nested?.length ? nested.flatMap((child) => flatten(child, path)) : [{ ...issue2, path }];
54394
+ }
54395
+ function describe3(issues) {
54396
+ const leaves = issues.flatMap((issue2) => flatten(issue2));
54397
+ const specific = leaves.filter((leaf) => leaf.code !== "invalid_type");
54398
+ const best = (specific.length ? specific : leaves).reduce((a, b) => b.path.length > a.path.length ? b : a);
54399
+ const path = best.path.join(".");
54400
+ return path ? `${path}: ${best.message}` : best.message;
54401
+ }
54346
54402
  function parseConfig(value) {
54347
54403
  const result = ConfigSchema.safeParse(value);
54348
54404
  if (!result.success) {
54349
- const issue2 = result.error.issues[0];
54350
- const path = issue2.path.join(".");
54351
- const message = path ? `${path}: ${issue2.message}` : issue2.message;
54352
- throw new ConfigError(message);
54405
+ throw new ConfigError(describe3(result.error.issues));
54353
54406
  }
54354
54407
  const config2 = result.data;
54355
54408
  config2.root = config2.root ? resolve(expandPath(config2.root)) : process.cwd();
@@ -54456,8 +54509,217 @@ async function resolveGitSource(pattern, cwd) {
54456
54509
  }
54457
54510
  }
54458
54511
 
54512
+ // src/linear.ts
54513
+ var API_URL = "https://api.linear.app/graphql";
54514
+ var TIMEOUT_MS = 30000;
54515
+ var TOKEN_ENV = "LINEAR_API_KEY";
54516
+ var PAGE = 50;
54517
+ var CLOSED_STATES = ["completed", "canceled", "duplicate"];
54518
+ var PRIORITY = ["None", "Urgent", "High", "Medium", "Low"];
54519
+
54520
+ class LinearError extends Error {
54521
+ constructor(message) {
54522
+ super(message);
54523
+ this.name = "LinearError";
54524
+ }
54525
+ }
54526
+ function requireToken() {
54527
+ const token = process.env[TOKEN_ENV]?.trim();
54528
+ if (!token) {
54529
+ throw new LinearError(`${TOKEN_ENV} is not set. Create a personal API key in Linear ` + "(Settings → Security & access → Personal API keys).");
54530
+ }
54531
+ return token;
54532
+ }
54533
+ async function graphql(query, variables, token) {
54534
+ let response;
54535
+ try {
54536
+ response = await fetch(API_URL, {
54537
+ method: "POST",
54538
+ headers: { authorization: token, "content-type": "application/json" },
54539
+ body: JSON.stringify({ query, variables }),
54540
+ signal: AbortSignal.timeout(TIMEOUT_MS)
54541
+ });
54542
+ } catch (error52) {
54543
+ if (error52.name === "TimeoutError") {
54544
+ throw new LinearError(`Linear API request timed out after ${TIMEOUT_MS / 1000}s.`);
54545
+ }
54546
+ throw new LinearError(`Cannot reach the Linear API: ${error52.message}`);
54547
+ }
54548
+ if (response.status === 401 || response.status === 403) {
54549
+ throw new LinearError(`${TOKEN_ENV} was rejected by Linear (not authorized).`);
54550
+ }
54551
+ let body;
54552
+ try {
54553
+ body = await response.json();
54554
+ } catch {
54555
+ throw new LinearError(`Linear API returned ${response.status}.`);
54556
+ }
54557
+ if (body.errors?.length) {
54558
+ throw new LinearError(body.errors.map((e) => e.message).join("; "));
54559
+ }
54560
+ if (!response.ok || !body.data) {
54561
+ throw new LinearError(`Linear API returned ${response.status}.`);
54562
+ }
54563
+ return body.data;
54564
+ }
54565
+ function normalize(source) {
54566
+ if (typeof source === "string") {
54567
+ return { team: source, includeClosed: false };
54568
+ }
54569
+ return {
54570
+ team: source.team,
54571
+ project: source.project,
54572
+ includeClosed: source.includeClosed ?? false
54573
+ };
54574
+ }
54575
+ async function resolveScope(team, project, token) {
54576
+ const projects = project ? "projects(filter: { name: { eq: $project } }, first: 2) { nodes { id } }" : "";
54577
+ const query = `
54578
+ query ($team: String!${project ? ", $project: String!" : ""}) {
54579
+ teams(filter: { key: { eq: $team } }, first: 1) {
54580
+ nodes { key ${projects} }
54581
+ }
54582
+ }
54583
+ `;
54584
+ const data = await graphql(query, project ? { team, project } : { team }, token);
54585
+ const found = data.teams.nodes[0];
54586
+ if (!found) {
54587
+ throw new LinearError(`Team "${team}" not found in this Linear workspace. ` + "Use the team key shown in issue identifiers (the ENG in ENG-123).");
54588
+ }
54589
+ if (!project)
54590
+ return {};
54591
+ const matches = found.projects?.nodes ?? [];
54592
+ if (matches.length === 0) {
54593
+ throw new LinearError(`Project "${project}" not found in team "${team}".`);
54594
+ }
54595
+ if (matches.length > 1) {
54596
+ throw new LinearError(`Project "${project}" is ambiguous: team "${team}" has more than one project with that name.`);
54597
+ }
54598
+ return { projectId: matches[0].id };
54599
+ }
54600
+ async function fetchIssues(filter, token) {
54601
+ const query = `
54602
+ query ($cursor: String, $filter: IssueFilter) {
54603
+ issues(first: ${PAGE}, after: $cursor, filter: $filter, orderBy: createdAt) {
54604
+ nodes {
54605
+ identifier
54606
+ title
54607
+ description
54608
+ priority
54609
+ estimate
54610
+ dueDate
54611
+ url
54612
+ createdAt
54613
+ updatedAt
54614
+ state { name type }
54615
+ # A deliberate cap, not pagination: 50 labels is far past what an
54616
+ # issue carries, and each nested page multiplies query complexity
54617
+ labels(first: 50) { nodes { name parent { name } } }
54618
+ project { name }
54619
+ projectMilestone { name }
54620
+ parent { identifier }
54621
+ assignee { name }
54622
+ }
54623
+ pageInfo { hasNextPage endCursor }
54624
+ }
54625
+ }
54626
+ `;
54627
+ const issues = [];
54628
+ let cursor = null;
54629
+ do {
54630
+ const data = await graphql(query, { cursor, filter }, token);
54631
+ issues.push(...data.issues.nodes);
54632
+ cursor = data.issues.pageInfo.hasNextPage ? data.issues.pageInfo.endCursor : null;
54633
+ } while (cursor);
54634
+ return issues;
54635
+ }
54636
+ function stripEmbeds(markdown) {
54637
+ return markdown.replace(/<linear-embed\b[^>]*>.*?<\/linear-embed>/gs, "[embed]").replace(/<linear-embed\b[^>]*\/?>/g, "[embed]").trimEnd();
54638
+ }
54639
+ function labelNames(issue2) {
54640
+ return issue2.labels.nodes.map((l) => l.parent ? `${l.parent.name}/${l.name}` : l.name);
54641
+ }
54642
+ function issueNumber(issue2) {
54643
+ const n = Number(issue2.identifier.split("-").pop());
54644
+ return Number.isFinite(n) ? n : Number.MAX_SAFE_INTEGER;
54645
+ }
54646
+ function renderSummary(scope, issues) {
54647
+ const tally = new Map;
54648
+ for (const issue2 of issues) {
54649
+ tally.set(issue2.state.name, (tally.get(issue2.state.name) ?? 0) + 1);
54650
+ }
54651
+ const counts = [...tally].sort((a, b) => b[1] - a[1]).map(([name, n]) => `${name} ${n}`).join(" · ");
54652
+ const rows = [...issues].sort((a, b) => issueNumber(a) - issueNumber(b)).map((issue2) => {
54653
+ const title = issue2.title.replace(/\|/g, "\\|");
54654
+ const priority = PRIORITY[issue2.priority] ?? String(issue2.priority);
54655
+ return `| ${issue2.identifier} | ${issue2.state.name} | ${priority} | ${title} |`;
54656
+ });
54657
+ return [
54658
+ `# ${scope} — ${issues.length} ${issues.length === 1 ? "issue" : "issues"}`,
54659
+ "",
54660
+ counts,
54661
+ "",
54662
+ "| Issue | State | Priority | Title |",
54663
+ "| --- | --- | --- | --- |",
54664
+ ...rows
54665
+ ].join(`
54666
+ `);
54667
+ }
54668
+ function render(issue2) {
54669
+ const field = (name, value) => `${name.padEnd(10)} ${value?.length ? value : "—"}`;
54670
+ const description = issue2.description?.trim() ? stripEmbeds(issue2.description) : "(no description)";
54671
+ return [
54672
+ `# ${issue2.identifier} ${issue2.title}`,
54673
+ "",
54674
+ field("State", `${issue2.state.name} (${issue2.state.type})`),
54675
+ field("Priority", PRIORITY[issue2.priority] ?? String(issue2.priority)),
54676
+ field("Estimate", issue2.estimate === null ? null : String(issue2.estimate)),
54677
+ field("Labels", labelNames(issue2).join(", ")),
54678
+ field("Project", issue2.project?.name),
54679
+ field("Milestone", issue2.projectMilestone?.name),
54680
+ field("Parent", issue2.parent?.identifier),
54681
+ field("Assignee", issue2.assignee?.name),
54682
+ field("Due", issue2.dueDate),
54683
+ field("Created", issue2.createdAt.slice(0, 10)),
54684
+ field("Updated", issue2.updatedAt.slice(0, 10)),
54685
+ field("URL", issue2.url),
54686
+ "",
54687
+ description
54688
+ ].join(`
54689
+ `);
54690
+ }
54691
+ async function resolveLinearSource(source) {
54692
+ const { team, project, includeClosed } = normalize(source);
54693
+ const token = requireToken();
54694
+ const { projectId } = await resolveScope(team, project, token);
54695
+ const filter = { team: { key: { eq: team } } };
54696
+ if (projectId)
54697
+ filter.project = { id: { eq: projectId } };
54698
+ if (!includeClosed)
54699
+ filter.state = { type: { nin: CLOSED_STATES } };
54700
+ const issues = await fetchIssues(filter, token);
54701
+ if (issues.length === 0)
54702
+ return [];
54703
+ const scope = project ? `${team} / ${project}` : team;
54704
+ const entries = [
54705
+ { path: "linear/issues.md", content: renderSummary(scope, issues) }
54706
+ ];
54707
+ for (const issue2 of issues) {
54708
+ entries.push({
54709
+ path: `linear/issues/${issue2.identifier}.md`,
54710
+ content: render(issue2)
54711
+ });
54712
+ }
54713
+ return entries;
54714
+ }
54715
+
54459
54716
  // src/bundle.ts
54460
54717
  var BINARY_CHECK_SIZE = 8192;
54718
+ var GLOB_OPTIONS = {
54719
+ onlyFiles: true,
54720
+ dot: true,
54721
+ followSymbolicLinks: false
54722
+ };
54461
54723
  async function isBundleable(filePath) {
54462
54724
  let stats;
54463
54725
  try {
@@ -54493,6 +54755,8 @@ function normalizePatterns(config2) {
54493
54755
  patterns = [config2];
54494
54756
  } else if (Array.isArray(config2)) {
54495
54757
  patterns = config2;
54758
+ } else if (config2.include === undefined) {
54759
+ patterns = [];
54496
54760
  } else {
54497
54761
  patterns = Array.isArray(config2.include) ? config2.include : [config2.include];
54498
54762
  }
@@ -54534,27 +54798,73 @@ function gitignoreToGlobPatterns(lines) {
54534
54798
  const trimmed = line.trim();
54535
54799
  if (!trimmed || trimmed.startsWith("#"))
54536
54800
  continue;
54537
- if (trimmed.startsWith("/") || trimmed.includes("*") || trimmed.includes("?") || trimmed.includes("[") || trimmed.includes("/") || trimmed.includes("\\")) {
54801
+ const name = trimmed.endsWith("/") ? trimmed.slice(0, -1) : trimmed;
54802
+ if (name.startsWith("/") || name.includes("*") || name.includes("?") || name.includes("[") || name.includes("/") || name.includes("\\")) {
54538
54803
  continue;
54539
54804
  }
54540
- const name = trimmed.endsWith("/") ? trimmed.slice(0, -1) : trimmed;
54541
54805
  if (name && /^[\w.-]+$/.test(name)) {
54542
54806
  patterns.push(`**/${name}/**`);
54543
54807
  }
54544
54808
  }
54545
54809
  return patterns;
54546
54810
  }
54547
- async function loadGitignore(cwd) {
54548
- const ig = import_ignore.default();
54549
- const gitignorePath = join2(cwd, ".gitignore");
54550
- let globPatterns = [];
54811
+ async function readIgnoreFile(path) {
54551
54812
  try {
54552
- const content = await readFile(gitignorePath, "utf-8");
54553
- ig.add(content);
54554
- globPatterns = gitignoreToGlobPatterns(content.split(`
54555
- `));
54556
- } catch {}
54557
- return { ignore: ig, globPatterns };
54813
+ return await readFile(path, "utf-8");
54814
+ } catch (error52) {
54815
+ if (error52.code === "ENOENT")
54816
+ return null;
54817
+ throw new ConfigError(`Cannot read "${path}": ${error52.message}. ` + "srcpack stops rather than bundle files it cannot confirm are ignored.");
54818
+ }
54819
+ }
54820
+ async function loadGitignore(cwd) {
54821
+ const rootContent = await readIgnoreFile(join2(cwd, ".gitignore"));
54822
+ const globPatterns = rootContent ? gitignoreToGlobPatterns(rootContent.split(`
54823
+ `)) : [];
54824
+ const layers = [];
54825
+ if (rootContent)
54826
+ layers.push({ dir: "", ig: import_ignore.default().add(rootContent) });
54827
+ const nested = await import_fast_glob.glob(["**/.gitignore"], {
54828
+ cwd,
54829
+ dot: true,
54830
+ onlyFiles: true,
54831
+ followSymbolicLinks: false,
54832
+ ignore: globPatterns
54833
+ });
54834
+ for (const file2 of nested) {
54835
+ const content = await readIgnoreFile(join2(cwd, file2));
54836
+ if (content)
54837
+ layers.push({ dir: dirname(file2), ig: import_ignore.default().add(content) });
54838
+ }
54839
+ return { ignores: makeIgnores(layers), globPatterns };
54840
+ }
54841
+ function makeIgnores(layers) {
54842
+ if (layers.length === 0)
54843
+ return () => false;
54844
+ const ordered = [...layers].sort((a, b) => b.dir.length - a.dir.length);
54845
+ const opinion = (path) => {
54846
+ for (const { dir, ig } of ordered) {
54847
+ if (dir && !path.startsWith(`${dir}/`))
54848
+ continue;
54849
+ const relative = dir ? path.slice(dir.length + 1) : path;
54850
+ if (!relative || relative === "/")
54851
+ continue;
54852
+ const { ignored, unignored } = ig.test(relative);
54853
+ if (ignored)
54854
+ return true;
54855
+ if (unignored)
54856
+ return false;
54857
+ }
54858
+ return;
54859
+ };
54860
+ return (path) => {
54861
+ const segments = path.split("/");
54862
+ for (let i = 1;i < segments.length; i++) {
54863
+ if (opinion(`${segments.slice(0, i).join("/")}/`))
54864
+ return true;
54865
+ }
54866
+ return opinion(path) === true;
54867
+ };
54558
54868
  }
54559
54869
  function isExternalPattern(pattern) {
54560
54870
  if (isAbsolute(pattern))
@@ -54562,8 +54872,15 @@ function isExternalPattern(pattern) {
54562
54872
  const normalized = pattern.startsWith("./") ? pattern.slice(2) : pattern;
54563
54873
  return normalized.startsWith("../");
54564
54874
  }
54875
+ function pathKey(path) {
54876
+ return path.normalize("NFC").toLowerCase();
54877
+ }
54565
54878
  function isOwnOutput(filePath, outputs) {
54566
- return outputs.some((out) => filePath === out || filePath.startsWith(out + sep));
54879
+ const key = pathKey(filePath);
54880
+ return outputs.some((out) => {
54881
+ const outKey = pathKey(out);
54882
+ return key === outKey || key.startsWith(outKey + sep);
54883
+ });
54567
54884
  }
54568
54885
  async function resolvePatterns(config2, cwd, outputs = []) {
54569
54886
  const { include, exclude, force } = normalizePatterns(config2);
@@ -54591,24 +54908,48 @@ async function resolvePatterns(config2, cwd, outputs = []) {
54591
54908
  const globs = include.filter((p) => !isGitSource(p));
54592
54909
  const internalPatterns = globs.filter((p) => !isExternalPattern(p));
54593
54910
  if (internalPatterns.length > 0) {
54594
- const { ignore: gitignore, globPatterns } = await loadGitignore(cwd);
54911
+ const { ignores, globPatterns } = await loadGitignore(cwd);
54595
54912
  const matches = await import_fast_glob.glob(internalPatterns, {
54913
+ ...GLOB_OPTIONS,
54596
54914
  cwd,
54597
- onlyFiles: true,
54598
- dot: true,
54599
54915
  ignore: globPatterns
54600
54916
  });
54601
- await add(matches.filter((m) => !gitignore.ignores(m)));
54917
+ await add(matches.filter((m) => !ignores(m)));
54602
54918
  }
54603
54919
  const externalPatterns = globs.filter(isExternalPattern);
54604
54920
  if (externalPatterns.length > 0) {
54605
- await add(await import_fast_glob.glob(externalPatterns, { cwd, onlyFiles: true, dot: true }));
54921
+ await add(await import_fast_glob.glob(externalPatterns, { ...GLOB_OPTIONS, cwd }));
54606
54922
  }
54607
54923
  if (force.length > 0) {
54608
- await add(await import_fast_glob.glob(force, { cwd, onlyFiles: true, dot: true }));
54924
+ await add(await import_fast_glob.glob(force, { ...GLOB_OPTIONS, cwd }));
54609
54925
  }
54610
54926
  return [...files].sort();
54611
54927
  }
54928
+ function getLinear(config2) {
54929
+ if (typeof config2 === "object" && !Array.isArray(config2)) {
54930
+ return config2.linear;
54931
+ }
54932
+ return;
54933
+ }
54934
+ async function resolveEntries(config2, cwd, outputs = []) {
54935
+ const linearSource = getLinear(config2);
54936
+ const paths = await resolvePatterns(config2, cwd, outputs);
54937
+ const entries = paths.map((path) => ({ path }));
54938
+ if (linearSource) {
54939
+ const { exclude } = normalizePatterns(config2);
54940
+ const excludeMatchers = exclude.map((p) => import_picomatch.default(p));
54941
+ const taken = new Set(paths.map((path) => resolve2(cwd, path)));
54942
+ for (const entry of await resolveLinearSource(linearSource)) {
54943
+ if (isExcluded(entry.path, excludeMatchers))
54944
+ continue;
54945
+ if (taken.has(resolve2(cwd, entry.path))) {
54946
+ throw new ConfigError(`Linear issue collides with the file "${entry.path}". ` + "Rename the file, or narrow the include patterns so it isn't matched.");
54947
+ }
54948
+ entries.push(entry);
54949
+ }
54950
+ }
54951
+ return entries.sort((a, b) => a.path < b.path ? -1 : a.path > b.path ? 1 : 0);
54952
+ }
54612
54953
  function countLines(content) {
54613
54954
  if (content === "")
54614
54955
  return 0;
@@ -54634,28 +54975,29 @@ function formatIndex(index) {
54634
54975
  function formatSeparator(index, filePath) {
54635
54976
  return `#==> [${index}] ${filePath} <==`;
54636
54977
  }
54637
- async function createBundle(files, cwd, options = {}) {
54978
+ async function createBundle(entries, cwd, options = {}) {
54638
54979
  const { includeIndex = true } = options;
54639
54980
  const prompt = options.prompt?.trim() || undefined;
54640
54981
  const index = [];
54641
54982
  const contentParts = [];
54642
54983
  let currentLine = 1;
54643
- for (let i = 0;i < files.length; i++) {
54644
- const filePath = files[i];
54645
- const content2 = await readFile(resolve2(cwd, filePath), "utf-8");
54984
+ for (let i = 0;i < entries.length; i++) {
54985
+ const entry = entries[i];
54986
+ const filePath = entry.path;
54987
+ const content2 = entry.content ?? await readFile(resolve2(cwd, filePath), "utf-8");
54646
54988
  const lines = countLines(content2);
54647
54989
  const contentStartLine = currentLine + 1;
54648
- const entry = {
54990
+ const indexEntry = {
54649
54991
  path: filePath,
54650
54992
  lines,
54651
54993
  startLine: contentStartLine,
54652
54994
  endLine: contentStartLine + Math.max(0, lines - 1)
54653
54995
  };
54654
- index.push(entry);
54996
+ index.push(indexEntry);
54655
54997
  contentParts.push(formatSeparator(i + 1, filePath));
54656
54998
  contentParts.push(content2.endsWith(`
54657
54999
  `) ? content2.slice(0, -1) : content2);
54658
- currentLine = entry.endLine + 1;
55000
+ currentLine = indexEntry.endLine + 1;
54659
55001
  }
54660
55002
  const promptLines = prompt ? countLines(prompt) + 3 : 0;
54661
55003
  if (includeIndex) {
@@ -54720,10 +55062,10 @@ async function resolvePrompt(prompt, cwd) {
54720
55062
  return prompt.trim() || undefined;
54721
55063
  }
54722
55064
  async function bundleOne(config2, cwd, outputs = []) {
54723
- const files = await resolvePatterns(config2, cwd, outputs);
55065
+ const entries = await resolveEntries(config2, cwd, outputs);
54724
55066
  const includeIndex = getIncludeIndex(config2);
54725
55067
  const prompt = await resolvePrompt(getPrompt(config2), cwd);
54726
- return createBundle(files, cwd, { includeIndex, prompt });
55068
+ return createBundle(entries, cwd, { includeIndex, prompt });
54727
55069
  }
54728
55070
 
54729
55071
  // src/gdrive.ts
@@ -54733,7 +55075,7 @@ import { spawn } from "node:child_process";
54733
55075
  import { createReadStream as createReadStream2 } from "node:fs";
54734
55076
  import { chmod, mkdir as mkdir2, readFile as readFile3, writeFile as writeFile2 } from "node:fs/promises";
54735
55077
  import { homedir as homedir3 } from "node:os";
54736
- import { dirname as dirname2, join as join4, basename as basename2 } from "node:path";
55078
+ import { dirname as dirname3, join as join4, basename as basename2 } from "node:path";
54737
55079
 
54738
55080
  // node_modules/oauth-callback/dist/index.js
54739
55081
  import fs2 from "node:fs";
@@ -61115,7 +61457,7 @@ async function readCredentials() {
61115
61457
  }
61116
61458
  }
61117
61459
  async function writeCredentials(creds) {
61118
- await mkdir2(dirname2(CREDENTIALS_PATH), { recursive: true, mode: 448 });
61460
+ await mkdir2(dirname3(CREDENTIALS_PATH), { recursive: true, mode: 448 });
61119
61461
  await writeFile2(CREDENTIALS_PATH, JSON.stringify(creds, null, 2), {
61120
61462
  mode: 384
61121
61463
  });
@@ -62717,21 +63059,69 @@ function formatNumber(n2) {
62717
63059
  function plural(n2, singular, pluralForm) {
62718
63060
  return n2 === 1 ? singular : pluralForm ?? singular + "s";
62719
63061
  }
63062
+ var DEFAULT_OUT_DIR = ".srcpack";
63063
+ async function physicalPath(path3) {
63064
+ try {
63065
+ return await realpath(path3);
63066
+ } catch {
63067
+ const parent = dirname4(path3);
63068
+ if (parent === path3)
63069
+ return path3;
63070
+ return join6(await physicalPath(parent), basename3(path3));
63071
+ }
63072
+ }
63073
+ async function entryPath(path3) {
63074
+ return join6(await physicalPath(dirname4(path3)), basename3(path3));
63075
+ }
62720
63076
  function isInside(path3, dir) {
62721
63077
  const rel = relative(dir, path3);
62722
63078
  return rel !== ".." && !rel.startsWith(`..${sep2}`) && !isAbsolute2(rel);
62723
63079
  }
63080
+ async function writeBundle(path3, content) {
63081
+ const temp = `${path3}.${process.pid}.tmp`;
63082
+ try {
63083
+ await writeFile4(temp, content);
63084
+ await rename2(temp, path3);
63085
+ } finally {
63086
+ await rm(temp, { force: true });
63087
+ }
63088
+ }
62724
63089
  async function emptyDirectory(dir, skip = []) {
62725
63090
  let entries;
62726
63091
  try {
62727
63092
  entries = await readdir(dir);
62728
- } catch {
62729
- return;
63093
+ } catch (error53) {
63094
+ if (error53.code === "ENOENT")
63095
+ return;
63096
+ throw new ConfigError(`Cannot empty outDir "${dir}": ${error53.message}`);
62730
63097
  }
62731
63098
  const skipSet = new Set(skip);
62732
63099
  await Promise.all(entries.filter((entry) => !skipSet.has(entry)).map((entry) => rm(join6(dir, entry), { recursive: true, force: true })));
62733
63100
  }
62734
63101
  var AD_HOC_FLAGS = ["--staged", "--dirty", "--since"];
63102
+ var KNOWN_FLAGS = new Set([
63103
+ ...AD_HOC_FLAGS,
63104
+ "--dry-run",
63105
+ "--emptyOutDir",
63106
+ "--no-emptyOutDir",
63107
+ "--no-upload",
63108
+ "--help",
63109
+ "-h",
63110
+ "--version",
63111
+ "-v"
63112
+ ]);
63113
+ function assertKnownFlags(args) {
63114
+ const unknown3 = args.find((arg) => arg.startsWith("-") && !KNOWN_FLAGS.has(arg));
63115
+ if (unknown3) {
63116
+ console.error(`Unknown option: ${unknown3}`);
63117
+ console.error("Run `srcpack --help` to see the available options.");
63118
+ process.exit(1);
63119
+ }
63120
+ if (args.includes("--emptyOutDir") && args.includes("--no-emptyOutDir")) {
63121
+ console.error("Cannot combine --emptyOutDir with --no-emptyOutDir.");
63122
+ process.exit(1);
63123
+ }
63124
+ }
62735
63125
  function parseAdHocBundle(args) {
62736
63126
  const flags = AD_HOC_FLAGS.filter((flag) => args.includes(flag));
62737
63127
  if (flags.length > 1) {
@@ -62787,7 +63177,7 @@ Options:
62787
63177
  --dirty Bundle staged, unstaged, and untracked changes
62788
63178
  --since <rev> Bundle changes since <rev> (e.g. --since main)
62789
63179
  --dry-run Preview bundles without writing files
62790
- --emptyOutDir Empty output directory before bundling
63180
+ --emptyOutDir Empty output directory before writing
62791
63181
  --no-emptyOutDir Keep existing files in output directory
62792
63182
  --no-upload Skip uploading to cloud storage
62793
63183
  -h, --help Show this help message
@@ -62795,14 +63185,15 @@ Options:
62795
63185
  `);
62796
63186
  return;
62797
63187
  }
62798
- if (args[0] === "init") {
62799
- await runInit();
62800
- return;
62801
- }
62802
- if (args[0] === "login") {
62803
- await runLogin();
63188
+ if (args[0] === "init" || args[0] === "login") {
63189
+ if (args.length > 1) {
63190
+ console.error(`srcpack ${args[0]} takes no arguments.`);
63191
+ process.exit(1);
63192
+ }
63193
+ await (args[0] === "init" ? runInit() : runLogin());
62804
63194
  return;
62805
63195
  }
63196
+ assertKnownFlags(args);
62806
63197
  const dryRun = args.includes("--dry-run");
62807
63198
  const noUpload = args.includes("--no-upload");
62808
63199
  const emptyOutDirFlag = args.includes("--emptyOutDir") ? true : args.includes("--no-emptyOutDir") ? false : undefined;
@@ -62825,7 +63216,7 @@ Options:
62825
63216
  const bundles = adHoc ? { [adHoc.name]: adHoc.patterns } : config3.bundles;
62826
63217
  const bundleNames = requestedBundles.length ? requestedBundles : Object.keys(bundles);
62827
63218
  for (const name of bundleNames) {
62828
- if (!(name in bundles)) {
63219
+ if (!Object.hasOwn(bundles, name)) {
62829
63220
  console.error(`Unknown bundle: ${name}`);
62830
63221
  process.exit(1);
62831
63222
  }
@@ -62835,22 +63226,38 @@ Options:
62835
63226
  return;
62836
63227
  }
62837
63228
  const root = config3.root;
63229
+ const rootPath = await physicalPath(root);
62838
63230
  const outDirPath = resolve3(root, config3.outDir);
62839
- const outDirInsideRoot = isInside(outDirPath, root);
62840
- const emptyOutDir = emptyOutDirFlag ?? (adHoc ? false : config3.emptyOutDir ?? outDirInsideRoot);
62841
- if (!adHoc && !outDirInsideRoot && emptyOutDirFlag === undefined && config3.emptyOutDir === undefined) {
62842
- console.warn(`Warning: outDir "${config3.outDir}" is outside project root. ` + "Use --emptyOutDir to suppress this warning and empty the directory.");
62843
- }
62844
- const outDirHoldsRoot = isInside(root, outDirPath);
63231
+ const outDirPhysical = await physicalPath(outDirPath);
63232
+ const defaultOutDir = join6(rootPath, DEFAULT_OUT_DIR);
63233
+ if (resolve3(root, DEFAULT_OUT_DIR) === outDirPath && outDirPhysical !== defaultOutDir) {
63234
+ throw new ConfigError(`Refusing to use "${DEFAULT_OUT_DIR}": it resolves to "${outDirPhysical}", not "${defaultOutDir}". ` + "Set outDir to that path explicitly if that is where bundles belong.");
63235
+ }
63236
+ const ownsOutDir = outDirPhysical === defaultOutDir;
63237
+ const emptyOutDir = emptyOutDirFlag ?? (adHoc ? false : config3.emptyOutDir ?? ownsOutDir);
63238
+ const outDirHoldsRoot = isInside(rootPath, outDirPhysical);
62845
63239
  if (emptyOutDir && outDirHoldsRoot) {
62846
63240
  throw new ConfigError(`Refusing to empty outDir "${config3.outDir}": it contains the project root. ` + "Use a subdirectory, or set emptyOutDir: false.");
62847
63241
  }
62848
- if (emptyOutDir && !dryRun && requestedBundles.length === 0) {
62849
- await emptyDirectory(outDirPath, [".git"]);
63242
+ const ownOutputs = new Set;
63243
+ const writers = new Map;
63244
+ for (const [name, bundleConfig] of Object.entries(config3.bundles)) {
63245
+ const outfile = resolve3(root, getOutfile(bundleConfig, name, config3.outDir));
63246
+ const entry = await entryPath(outfile);
63247
+ const key = pathKey(entry);
63248
+ const first = writers.get(key);
63249
+ if (first) {
63250
+ throw new ConfigError(`Bundles "${first}" and "${name}" both write to "${relative(root, outfile) || outfile}". ` + "Give one of them its own outfile.");
63251
+ }
63252
+ writers.set(key, name);
63253
+ ownOutputs.add(outfile);
63254
+ ownOutputs.add(entry);
62850
63255
  }
62851
- const ownOutputs = Object.entries(config3.bundles).map(([name, bundleConfig]) => resolve3(root, getOutfile(bundleConfig, name, config3.outDir)));
62852
- if (!outDirHoldsRoot)
62853
- ownOutputs.push(outDirPath);
63256
+ if (!outDirHoldsRoot) {
63257
+ ownOutputs.add(outDirPath);
63258
+ ownOutputs.add(outDirPhysical);
63259
+ }
63260
+ const outputPaths = [...ownOutputs];
62854
63261
  const outputs = [];
62855
63262
  const bundleSpinner = ora({
62856
63263
  text: `Bundling ${bundleNames[0]}...`,
@@ -62861,13 +63268,24 @@ Options:
62861
63268
  const name = bundleNames[i3];
62862
63269
  bundleSpinner.text = `Bundling ${name}... (${i3 + 1}/${bundleNames.length})`;
62863
63270
  const bundleConfig = bundles[name];
62864
- const result = await bundleOne(bundleConfig, root, ownOutputs);
63271
+ let result;
63272
+ try {
63273
+ result = await bundleOne(bundleConfig, root, outputPaths);
63274
+ } catch (error53) {
63275
+ if (error53 instanceof ConfigError || error53 instanceof GitError || error53 instanceof LinearError) {
63276
+ error53.message = `Bundle "${name}": ${error53.message}`;
63277
+ }
63278
+ throw error53;
63279
+ }
62865
63280
  const outfile = getOutfile(bundleConfig, name, config3.outDir);
62866
63281
  outputs.push({ name, outfile, result });
62867
63282
  }
62868
63283
  } finally {
62869
63284
  bundleSpinner.stop();
62870
63285
  }
63286
+ if (emptyOutDir && !dryRun && requestedBundles.length === 0) {
63287
+ await emptyDirectory(outDirPath, [".git"]);
63288
+ }
62871
63289
  const maxNameLen = Math.max(...outputs.map((o2) => o2.name.length));
62872
63290
  const maxFilesLen = Math.max(...outputs.map((o2) => formatNumber(o2.result.index.length).length));
62873
63291
  const maxLinesLen = Math.max(...outputs.map((o2) => formatNumber(sumLines(o2.result)).length));
@@ -62890,8 +63308,8 @@ Options:
62890
63308
  }
62891
63309
  console.log(` ${nameCol} ${filesCol} ${plural(fileCount, "file")} ${linesCol} ${plural(lineCount, "line")} → skipped`);
62892
63310
  } else {
62893
- await mkdir3(dirname3(outPath), { recursive: true });
62894
- await writeFile4(outPath, result.content);
63311
+ await mkdir3(dirname4(outPath), { recursive: true });
63312
+ await writeBundle(outPath, result.content);
62895
63313
  const displayPath = relative(process.cwd(), outPath);
62896
63314
  console.log(` ${nameCol} ${filesCol} ${plural(fileCount, "file")} ${linesCol} ${plural(lineCount, "line")} → ${displayPath}`);
62897
63315
  }
@@ -63027,6 +63445,6 @@ function getOutfile(bundleConfig, name, outDir) {
63027
63445
  return join6(outDir, `${name}.txt`);
63028
63446
  }
63029
63447
  main().catch((err) => {
63030
- console.error(err instanceof ConfigError || err instanceof GitError ? err.message : err);
63448
+ console.error(err instanceof ConfigError || err instanceof GitError || err instanceof LinearError ? err.message : err);
63031
63449
  process.exit(1);
63032
63450
  });